diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2014-06-25 09:27:23 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:10:19 -0400 |
commit | 054160176eeedf190464225dede91f9a39b9fb97 (patch) | |
tree | 05b849479a256c359969f8764cbef3ac6615beae /drivers | |
parent | ebf7d4e25a526a6a485cac6a9637f9748966aafe (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')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 17 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 3 |
2 files changed, 20 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 | ||
2930 | static bool pmu_validate_cmd(struct pmu_gk20a *pmu, struct pmu_cmd *cmd, | 2943 | static 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; |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index 40d41ee9..5c8a3215 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | |||
@@ -1054,6 +1054,9 @@ struct pmu_gk20a { | |||
1054 | u32 sample_buffer; | 1054 | u32 sample_buffer; |
1055 | 1055 | ||
1056 | struct mutex isr_mutex; | 1056 | struct mutex isr_mutex; |
1057 | struct mutex isr_enable_lock; | ||
1058 | bool isr_enabled; | ||
1059 | |||
1057 | bool zbc_ready; | 1060 | bool zbc_ready; |
1058 | union { | 1061 | union { |
1059 | struct pmu_cmdline_args_v0 args_v0; | 1062 | struct pmu_cmdline_args_v0 args_v0; |