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>
This commit is contained in:
Thomas Fleury
2017-09-18 17:38:06 -07:00
committed by mobile promotions
parent ca92c1f400
commit 0a93373364

View File

@@ -268,6 +268,7 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
int ret = 0; int ret = 0;
struct gk20a_platform *platform = gk20a_get_platform(dev); struct gk20a_platform *platform = gk20a_get_platform(dev);
bool irqs_enabled;
gk20a_dbg_fn(""); gk20a_dbg_fn("");
@@ -276,6 +277,15 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
if (!g->power_on) if (!g->power_on)
goto done; goto done;
/* disable IRQs and wait for completion */
irqs_enabled = g->irqs_enabled;
if (irqs_enabled) {
disable_irq(g->irq_stall);
if (g->irq_stall != g->irq_nonstall)
disable_irq(g->irq_nonstall);
g->irqs_enabled = 0;
}
gk20a_scale_suspend(dev); gk20a_scale_suspend(dev);
gk20a_cde_suspend(l); gk20a_cde_suspend(l);
@@ -284,17 +294,6 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
if (ret) if (ret)
goto error; goto error;
/*
* After this point, gk20a interrupts should not get
* serviced.
*/
if (g->irqs_enabled) {
disable_irq(g->irq_stall);
if (g->irq_stall != g->irq_nonstall)
disable_irq(g->irq_nonstall);
g->irqs_enabled = 0;
}
/* Decrement platform power refcount */ /* Decrement platform power refcount */
if (platform->idle) if (platform->idle)
platform->idle(dev); platform->idle(dev);
@@ -306,6 +305,14 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
return 0; return 0;
error: error:
/* re-enabled IRQs if previously enabled */
if (irqs_enabled) {
enable_irq(g->irq_stall);
if (g->irq_stall != g->irq_nonstall)
enable_irq(g->irq_nonstall);
g->irqs_enabled = 1;
}
gk20a_scale_resume(dev); gk20a_scale_resume(dev);
done: done:
nvgpu_mutex_release(&g->poweroff_lock); nvgpu_mutex_release(&g->poweroff_lock);