]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
gpu: nvgpu: fix possible PMU isr race
authorDeepak Nibade <dnibade@nvidia.com>
Wed, 25 Jun 2014 13:27:23 +0000 (18:57 +0530)
committerMandar Padmawar <mpadmawar@nvidia.com>
Fri, 27 Jun 2014 06:39:38 +0000 (23:39 -0700)
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>
drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
drivers/gpu/nvgpu/gk20a/pmu_gk20a.h

index f0846ef57c3dc0403a3ccf1c6dbce52e86a723a4..0895f3dbb2263315714a1bb4c00bc79ff3cbd8b2 100644 (file)
@@ -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;
index ef2fed6c5c3e8902566e26063e98fa83402a475c..b92c14d4859c857f0c9f3d88fbb2b484e39f7fe5 100644 (file)
@@ -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;