summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2014-06-25 09:27:23 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:10:19 -0400
commit054160176eeedf190464225dede91f9a39b9fb97 (patch)
tree05b849479a256c359969f8764cbef3ac6615beae /drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
parentebf7d4e25a526a6a485cac6a9637f9748966aafe (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 (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 <snikam@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/pmu_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c17
1 files changed, 17 insertions, 0 deletions
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)
490 490
491 mutex_init(&pmu->elpg_mutex); 491 mutex_init(&pmu->elpg_mutex);
492 mutex_init(&pmu->isr_mutex); 492 mutex_init(&pmu->isr_mutex);
493 mutex_init(&pmu->isr_enable_lock);
493 mutex_init(&pmu->pmu_copy_lock); 494 mutex_init(&pmu->pmu_copy_lock);
494 mutex_init(&pmu->pmu_seq_lock); 495 mutex_init(&pmu->pmu_seq_lock);
495 496
@@ -1771,7 +1772,11 @@ int gk20a_init_pmu_setup_hw1(struct gk20a *g)
1771 int err; 1772 int err;
1772 1773
1773 gk20a_dbg_fn(""); 1774 gk20a_dbg_fn("");
1775
1776 mutex_lock(&pmu->isr_enable_lock);
1774 pmu_reset(pmu); 1777 pmu_reset(pmu);
1778 pmu->isr_enabled = true;
1779 mutex_unlock(&pmu->isr_enable_lock);
1775 1780
1776 /* setup apertures - virtual */ 1781 /* setup apertures - virtual */
1777 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_UCODE), 1782 gk20a_writel(g, pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_UCODE),
@@ -2881,6 +2886,12 @@ void gk20a_pmu_isr(struct gk20a *g)
2881 2886
2882 gk20a_dbg_fn(""); 2887 gk20a_dbg_fn("");
2883 2888
2889 mutex_lock(&pmu->isr_enable_lock);
2890 if (!pmu->isr_enabled) {
2891 mutex_unlock(&pmu->isr_enable_lock);
2892 return;
2893 }
2894
2884 mutex_lock(&pmu->isr_mutex); 2895 mutex_lock(&pmu->isr_mutex);
2885 2896
2886 mask = gk20a_readl(g, pwr_falcon_irqmask_r()) & 2897 mask = gk20a_readl(g, pwr_falcon_irqmask_r()) &
@@ -2893,6 +2904,7 @@ void gk20a_pmu_isr(struct gk20a *g)
2893 if (!intr || pmu->pmu_state == PMU_STATE_OFF) { 2904 if (!intr || pmu->pmu_state == PMU_STATE_OFF) {
2894 gk20a_writel(g, pwr_falcon_irqsclr_r(), intr); 2905 gk20a_writel(g, pwr_falcon_irqsclr_r(), intr);
2895 mutex_unlock(&pmu->isr_mutex); 2906 mutex_unlock(&pmu->isr_mutex);
2907 mutex_unlock(&pmu->isr_enable_lock);
2896 return; 2908 return;
2897 } 2909 }
2898 2910
@@ -2925,6 +2937,7 @@ void gk20a_pmu_isr(struct gk20a *g)
2925 } 2937 }
2926 2938
2927 mutex_unlock(&pmu->isr_mutex); 2939 mutex_unlock(&pmu->isr_mutex);
2940 mutex_unlock(&pmu->isr_enable_lock);
2928} 2941}
2929 2942
2930static bool pmu_validate_cmd(struct pmu_gk20a *pmu, struct pmu_cmd *cmd, 2943static bool pmu_validate_cmd(struct pmu_gk20a *pmu, struct pmu_cmd *cmd,
@@ -3342,7 +3355,11 @@ int gk20a_pmu_destroy(struct gk20a *g)
3342 g->pg_ungating_time_us += (u64)elpg_ungating_time; 3355 g->pg_ungating_time_us += (u64)elpg_ungating_time;
3343 g->pg_gating_cnt += gating_cnt; 3356 g->pg_gating_cnt += gating_cnt;
3344 3357
3358 mutex_lock(&pmu->isr_enable_lock);
3345 pmu_enable(pmu, false); 3359 pmu_enable(pmu, false);
3360 pmu->isr_enabled = false;
3361 mutex_unlock(&pmu->isr_enable_lock);
3362
3346 pmu->pmu_state = PMU_STATE_OFF; 3363 pmu->pmu_state = PMU_STATE_OFF;
3347 pmu->pmu_ready = false; 3364 pmu->pmu_ready = false;
3348 pmu->perfmon_ready = false; 3365 pmu->perfmon_ready = false;