diff options
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 36 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 5 |
2 files changed, 41 insertions, 0 deletions
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) | |||
164 | return readl(g->sim.regs+r); | 164 | return readl(g->sim.regs+r); |
165 | } | 165 | } |
166 | 166 | ||
167 | /* | ||
168 | * Locks out the driver from accessing GPU registers. This prevents access to | ||
169 | * thse registers after the GPU has been clock or power gated. This should help | ||
170 | * find annoying bugs where register reads and writes are silently dropped | ||
171 | * after the GPU has been turned off. On older chips these reads and writes can | ||
172 | * also lock the entire CPU up. | ||
173 | */ | ||
174 | int gk20a_lockout_registers(struct gk20a *g) | ||
175 | { | ||
176 | g->regs = NULL; | ||
177 | g->bar1 = NULL; | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Undoes gk20a_lockout_registers(). | ||
184 | */ | ||
185 | int gk20a_restore_registers(struct gk20a *g) | ||
186 | { | ||
187 | g->regs = g->regs_saved; | ||
188 | g->bar1 = g->bar1_saved; | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
167 | static void kunmap_and_free_iopage(void **kvaddr, struct page **page) | 193 | static void kunmap_and_free_iopage(void **kvaddr, struct page **page) |
168 | { | 194 | { |
169 | if (*kvaddr) { | 195 | if (*kvaddr) { |
@@ -676,6 +702,9 @@ static int gk20a_init_support(struct platform_device *dev) | |||
676 | goto fail; | 702 | goto fail; |
677 | } | 703 | } |
678 | 704 | ||
705 | g->regs_saved = g->regs; | ||
706 | g->bar1_saved = g->bar1; | ||
707 | |||
679 | /* Get interrupt numbers */ | 708 | /* Get interrupt numbers */ |
680 | g->irq_nonstall = platform_get_irq(dev, 1); | 709 | g->irq_nonstall = platform_get_irq(dev, 1); |
681 | if (g->irq_stall < 0 || g->irq_nonstall < 0) { | 710 | if (g->irq_stall < 0 || g->irq_nonstall < 0) { |
@@ -786,6 +815,9 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
786 | 815 | ||
787 | g->power_on = false; | 816 | g->power_on = false; |
788 | 817 | ||
818 | /* Stop CPU from accessing the GPU registers. */ | ||
819 | gk20a_lockout_registers(g); | ||
820 | |||
789 | return ret; | 821 | return ret; |
790 | } | 822 | } |
791 | 823 | ||
@@ -820,6 +852,10 @@ static int gk20a_pm_finalize_poweron(struct device *dev) | |||
820 | 852 | ||
821 | trace_gk20a_finalize_poweron(dev_name(dev)); | 853 | trace_gk20a_finalize_poweron(dev_name(dev)); |
822 | 854 | ||
855 | err = gk20a_restore_registers(g); | ||
856 | if (err) | ||
857 | return err; | ||
858 | |||
823 | nice_value = task_nice(current); | 859 | nice_value = task_nice(current); |
824 | set_user_nice(current, -20); | 860 | set_user_nice(current, -20); |
825 | 861 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 991891c5..3871eb17 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -232,9 +232,11 @@ struct gk20a { | |||
232 | 232 | ||
233 | struct resource *reg_mem; | 233 | struct resource *reg_mem; |
234 | void __iomem *regs; | 234 | void __iomem *regs; |
235 | void __iomem *regs_saved; | ||
235 | 236 | ||
236 | struct resource *bar1_mem; | 237 | struct resource *bar1_mem; |
237 | void __iomem *bar1; | 238 | void __iomem *bar1; |
239 | void __iomem *bar1_saved; | ||
238 | 240 | ||
239 | bool power_on; | 241 | bool power_on; |
240 | 242 | ||
@@ -487,6 +489,9 @@ static inline void gk20a_mem_wr32(void *ptr, int w, u32 data) | |||
487 | } | 489 | } |
488 | 490 | ||
489 | /* register accessors */ | 491 | /* register accessors */ |
492 | int gk20a_lockout_registers(struct gk20a *g); | ||
493 | int gk20a_restore_registers(struct gk20a *g); | ||
494 | |||
490 | static inline void gk20a_writel(struct gk20a *g, u32 r, u32 v) | 495 | static inline void gk20a_writel(struct gk20a *g, u32 r, u32 v) |
491 | { | 496 | { |
492 | gk20a_dbg(gpu_dbg_reg, " r=0x%x v=0x%x", r, v); | 497 | gk20a_dbg(gpu_dbg_reg, " r=0x%x v=0x%x", r, v); |