diff options
author | Thomas Fleury <tfleury@nvidia.com> | 2017-09-18 20:38:06 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-10-29 14:00:51 -0400 |
commit | 0a93373364f8520e552f96b7e8fc22a5917f83ea (patch) | |
tree | c73fc8f977a07cc7aa2a8d0f07b1039441b21e06 /drivers/gpu/nvgpu | |
parent | ca92c1f400f26703643251bc0052d9a23f60bd03 (diff) |
gpu: nvgpu: disable IRQs before preparing powering down
Disable IRQs and wait for completion before preparing powering
down. This avoids concurrency with threaded interrupts.
JIRA EVLR-1852
Change-Id: Iab4cfb0e796b5748430d38daa2a3be8c03b10fff
Signed-off-by: Thomas Fleury <tfleury@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1563896
GVS: Gerrit_Virtual_Submit
Reviewed-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index e7e79949..68ae1a66 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c | |||
@@ -268,6 +268,7 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
268 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | 268 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); |
269 | int ret = 0; | 269 | int ret = 0; |
270 | struct gk20a_platform *platform = gk20a_get_platform(dev); | 270 | struct gk20a_platform *platform = gk20a_get_platform(dev); |
271 | bool irqs_enabled; | ||
271 | 272 | ||
272 | gk20a_dbg_fn(""); | 273 | gk20a_dbg_fn(""); |
273 | 274 | ||
@@ -276,6 +277,15 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
276 | if (!g->power_on) | 277 | if (!g->power_on) |
277 | goto done; | 278 | goto done; |
278 | 279 | ||
280 | /* disable IRQs and wait for completion */ | ||
281 | irqs_enabled = g->irqs_enabled; | ||
282 | if (irqs_enabled) { | ||
283 | disable_irq(g->irq_stall); | ||
284 | if (g->irq_stall != g->irq_nonstall) | ||
285 | disable_irq(g->irq_nonstall); | ||
286 | g->irqs_enabled = 0; | ||
287 | } | ||
288 | |||
279 | gk20a_scale_suspend(dev); | 289 | gk20a_scale_suspend(dev); |
280 | 290 | ||
281 | gk20a_cde_suspend(l); | 291 | gk20a_cde_suspend(l); |
@@ -284,17 +294,6 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
284 | if (ret) | 294 | if (ret) |
285 | goto error; | 295 | goto error; |
286 | 296 | ||
287 | /* | ||
288 | * After this point, gk20a interrupts should not get | ||
289 | * serviced. | ||
290 | */ | ||
291 | if (g->irqs_enabled) { | ||
292 | disable_irq(g->irq_stall); | ||
293 | if (g->irq_stall != g->irq_nonstall) | ||
294 | disable_irq(g->irq_nonstall); | ||
295 | g->irqs_enabled = 0; | ||
296 | } | ||
297 | |||
298 | /* Decrement platform power refcount */ | 297 | /* Decrement platform power refcount */ |
299 | if (platform->idle) | 298 | if (platform->idle) |
300 | platform->idle(dev); | 299 | platform->idle(dev); |
@@ -306,6 +305,14 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
306 | return 0; | 305 | return 0; |
307 | 306 | ||
308 | error: | 307 | error: |
308 | /* re-enabled IRQs if previously enabled */ | ||
309 | if (irqs_enabled) { | ||
310 | enable_irq(g->irq_stall); | ||
311 | if (g->irq_stall != g->irq_nonstall) | ||
312 | enable_irq(g->irq_nonstall); | ||
313 | g->irqs_enabled = 1; | ||
314 | } | ||
315 | |||
309 | gk20a_scale_resume(dev); | 316 | gk20a_scale_resume(dev); |
310 | done: | 317 | done: |
311 | nvgpu_mutex_release(&g->poweroff_lock); | 318 | nvgpu_mutex_release(&g->poweroff_lock); |