summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2014-06-25 18:57:23 +0530
committerMandar Padmawar <mpadmawar@nvidia.com>2014-06-26 23:39:38 -0700
commit9a37528314f2a2504e4530719f817a93db9a5bf0 (patch)
tree6c06b7b5ac03d2434f8c241bfe20117611b3e758 /drivers/gpu
parent04343434f91c1155648f57c6ab44bfb908972b1f (diff)
gpu: nvgpu: fix possible PMU isr race
Possible race description : - while PMU is booting, it sends messages to kernel which we process in gk20a_pmu_isr() - but when messages are processed it is possible that we are on the way to rail gate the GPU and we have already called pmu_destroy() - this could lead to hangs if while processing messages, GR is already off To fix this, introduce another mutex isr_enable_lock and a flag to turn on/off ISRs - when we enable PMU, get the lock and set the flag - in pmu_destroy(), get the lock and remove the flag - in pmu_isr(), take the lock, check if flag is set or not. If flag is not set return, otherwise proceed with the messages Bug 200014542 Bug 200014887 Change-Id: I0204d8a00e4563859eebc807d4ac7d26161316ea Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/428371 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c16
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.h3
2 files changed, 19 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
index f0846ef57c3d..0895f3dbb226 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
@@ -1666,6 +1666,7 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g)
skip_init:
mutex_init(&pmu->elpg_mutex);
mutex_init(&pmu->isr_mutex);
+ mutex_init(&pmu->isr_enable_lock);
mutex_init(&pmu->pmu_copy_lock);
mutex_init(&pmu->pmu_seq_lock);
@@ -1746,7 +1747,10 @@ int gk20a_init_pmu_setup_hw1(struct gk20a *g)
gk20a_dbg_fn("");
+ mutex_lock(&pmu->isr_enable_lock);
pmu_reset(pmu);
+ pmu->isr_enabled = true;
+ mutex_unlock(&pmu->isr_enable_lock);
/* setup apertures - virtual */
gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_UCODE),
@@ -2870,6 +2874,12 @@ void gk20a_pmu_isr(struct gk20a *g)
gk20a_dbg_fn("");
+ mutex_lock(&pmu->isr_enable_lock);
+ if (!pmu->isr_enabled) {
+ mutex_unlock(&pmu->isr_enable_lock);
+ return;
+ }
+
mutex_lock(&pmu->isr_mutex);
mask = gk20a_readl(g, pwr_falcon_irqmask_r()) &
@@ -2881,6 +2891,7 @@ void gk20a_pmu_isr(struct gk20a *g)
if (!intr) {
mutex_unlock(&pmu->isr_mutex);
+ mutex_unlock(&pmu->isr_enable_lock);
return;
}
@@ -2913,6 +2924,7 @@ void gk20a_pmu_isr(struct gk20a *g)
}
mutex_unlock(&pmu->isr_mutex);
+ mutex_unlock(&pmu->isr_enable_lock);
}
static bool pmu_validate_cmd(struct pmu_gk20a *pmu, struct pmu_cmd *cmd,
@@ -3330,7 +3342,11 @@ int gk20a_pmu_destroy(struct gk20a *g)
g->pg_ungating_time_us += (u64)elpg_ungating_time;
g->pg_gating_cnt += gating_cnt;
+ mutex_lock(&pmu->isr_enable_lock);
pmu_enable(pmu, false);
+ pmu->isr_enabled = false;
+ mutex_unlock(&pmu->isr_enable_lock);
+
pmu->pmu_state = PMU_STATE_OFF;
pmu->pmu_ready = false;
pmu->perfmon_ready = false;
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
index ef2fed6c5c3e..b92c14d4859c 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
@@ -1050,6 +1050,9 @@ struct pmu_gk20a {
u32 sample_buffer;
struct mutex isr_mutex;
+ struct mutex isr_enable_lock;
+ bool isr_enabled;
+
bool zbc_ready;
union {
struct pmu_cmdline_args_v0 args_v0;