From 054160176eeedf190464225dede91f9a39b9fb97 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 25 Jun 2014 18:57:23 +0530 Subject: 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 Reviewed-on: http://git-master/r/428371 (cherry picked from commit 9a37528314f2a2504e4530719f817a93db9a5bf0) Reviewed-on: http://git-master/r/428352 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Sachin Nikam --- drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/gpu/nvgpu/gk20a/pmu_gk20a.c') diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 45087094..808bf015 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c @@ -490,6 +490,7 @@ int gk20a_init_pmu(struct pmu_gk20a *pmu) 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); @@ -1771,7 +1772,11 @@ int gk20a_init_pmu_setup_hw1(struct gk20a *g) int err; 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), @@ -2881,6 +2886,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()) & @@ -2893,6 +2904,7 @@ void gk20a_pmu_isr(struct gk20a *g) if (!intr || pmu->pmu_state == PMU_STATE_OFF) { gk20a_writel(g, pwr_falcon_irqsclr_r(), intr); mutex_unlock(&pmu->isr_mutex); + mutex_unlock(&pmu->isr_enable_lock); return; } @@ -2925,6 +2937,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, @@ -3342,7 +3355,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; -- cgit v1.2.2