mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
gpu: nvgpu: Remove GPU MMIO access on power/rail gate
This is to weed out accesses to the GPU while it is gated. Otherwise the accesses are silently dropped or cause a HW hang (on older chips). Bug 1514949 Change-Id: Ice4cdb9f1f736978ebb3db847f39c7439bf98134 Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/416339 Reviewed-by: Mitch Luban <mluban@nvidia.com>
This commit is contained in:
committed by
Dan Willemsen
parent
e2638d73fd
commit
0f9bf924b2
@@ -164,6 +164,32 @@ static inline u32 sim_readl(struct gk20a *g, u32 r)
|
||||
return readl(g->sim.regs+r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locks out the driver from accessing GPU registers. This prevents access to
|
||||
* thse registers after the GPU has been clock or power gated. This should help
|
||||
* find annoying bugs where register reads and writes are silently dropped
|
||||
* after the GPU has been turned off. On older chips these reads and writes can
|
||||
* also lock the entire CPU up.
|
||||
*/
|
||||
int gk20a_lockout_registers(struct gk20a *g)
|
||||
{
|
||||
g->regs = NULL;
|
||||
g->bar1 = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undoes gk20a_lockout_registers().
|
||||
*/
|
||||
int gk20a_restore_registers(struct gk20a *g)
|
||||
{
|
||||
g->regs = g->regs_saved;
|
||||
g->bar1 = g->bar1_saved;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kunmap_and_free_iopage(void **kvaddr, struct page **page)
|
||||
{
|
||||
if (*kvaddr) {
|
||||
@@ -676,6 +702,9 @@ static int gk20a_init_support(struct platform_device *dev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
g->regs_saved = g->regs;
|
||||
g->bar1_saved = g->bar1;
|
||||
|
||||
/* Get interrupt numbers */
|
||||
g->irq_nonstall = platform_get_irq(dev, 1);
|
||||
if (g->irq_stall < 0 || g->irq_nonstall < 0) {
|
||||
@@ -786,6 +815,9 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
|
||||
|
||||
g->power_on = false;
|
||||
|
||||
/* Stop CPU from accessing the GPU registers. */
|
||||
gk20a_lockout_registers(g);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -820,6 +852,10 @@ static int gk20a_pm_finalize_poweron(struct device *dev)
|
||||
|
||||
trace_gk20a_finalize_poweron(dev_name(dev));
|
||||
|
||||
err = gk20a_restore_registers(g);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
nice_value = task_nice(current);
|
||||
set_user_nice(current, -20);
|
||||
|
||||
|
||||
@@ -232,9 +232,11 @@ struct gk20a {
|
||||
|
||||
struct resource *reg_mem;
|
||||
void __iomem *regs;
|
||||
void __iomem *regs_saved;
|
||||
|
||||
struct resource *bar1_mem;
|
||||
void __iomem *bar1;
|
||||
void __iomem *bar1_saved;
|
||||
|
||||
bool power_on;
|
||||
|
||||
@@ -487,6 +489,9 @@ static inline void gk20a_mem_wr32(void *ptr, int w, u32 data)
|
||||
}
|
||||
|
||||
/* register accessors */
|
||||
int gk20a_lockout_registers(struct gk20a *g);
|
||||
int gk20a_restore_registers(struct gk20a *g);
|
||||
|
||||
static inline void gk20a_writel(struct gk20a *g, u32 r, u32 v)
|
||||
{
|
||||
gk20a_dbg(gpu_dbg_reg, " r=0x%x v=0x%x", r, v);
|
||||
|
||||
Reference in New Issue
Block a user