From 0f9bf924b2be88502c9920ace258c27e0172e3d5 Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Fri, 23 May 2014 13:29:53 -0700 Subject: 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 Reviewed-on: http://git-master/r/416339 Reviewed-by: Mitch Luban --- drivers/gpu/nvgpu/gk20a/gk20a.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers/gpu/nvgpu/gk20a/gk20a.c') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 2310b81c..c72b8735 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -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); -- cgit v1.2.2