diff --git a/drivers/gpu/nvgpu/hal/init/hal_gm20b.c b/drivers/gpu/nvgpu/hal/init/hal_gm20b.c index e0fdaffe7..37ee980ea 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gm20b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gm20b.c @@ -828,6 +828,7 @@ static const struct gops_pmu gm20b_ops_pmu = { .pmu_mutex_acquire = gk20a_pmu_mutex_acquire, .pmu_mutex_release = gk20a_pmu_mutex_release, .pmu_is_interrupted = gk20a_pmu_is_interrupted, + .get_irqmask = gk20a_pmu_get_irqmask, .pmu_isr = gk20a_pmu_isr, .pmu_init_perfmon_counter = gk20a_pmu_init_perfmon_counter, .pmu_pg_idle_counter_config = gk20a_pmu_pg_idle_counter_config, diff --git a/drivers/gpu/nvgpu/hal/init/hal_gp10b.c b/drivers/gpu/nvgpu/hal/init/hal_gp10b.c index 9012c0e19..43c825a1e 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gp10b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gp10b.c @@ -910,6 +910,7 @@ static const struct gops_pmu gp10b_ops_pmu = { .pmu_mutex_acquire = gk20a_pmu_mutex_acquire, .pmu_mutex_release = gk20a_pmu_mutex_release, .pmu_is_interrupted = gk20a_pmu_is_interrupted, + .get_irqmask = gk20a_pmu_get_irqmask, .pmu_isr = gk20a_pmu_isr, .pmu_init_perfmon_counter = gk20a_pmu_init_perfmon_counter, .pmu_pg_idle_counter_config = gk20a_pmu_pg_idle_counter_config, diff --git a/drivers/gpu/nvgpu/hal/init/hal_gv11b.c b/drivers/gpu/nvgpu/hal/init/hal_gv11b.c index 1d448371a..3dd7ef8e2 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gv11b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gv11b.c @@ -1100,6 +1100,7 @@ static const struct gops_pmu gv11b_ops_pmu = { .validate_mem_integrity = gv11b_pmu_validate_mem_integrity, .pmu_enable_irq = gv11b_pmu_enable_irq, .get_irqdest = gv11b_pmu_get_irqdest, + .get_irqmask = gk20a_pmu_get_irqmask, .pmu_isr = gk20a_pmu_isr, .handle_ext_irq = gv11b_pmu_handle_ext_irq, #ifdef CONFIG_NVGPU_LS_PMU diff --git a/drivers/gpu/nvgpu/hal/init/hal_tu104.c b/drivers/gpu/nvgpu/hal/init/hal_tu104.c index e30644ed5..7417ce177 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_tu104.c +++ b/drivers/gpu/nvgpu/hal/init/hal_tu104.c @@ -1140,6 +1140,7 @@ static const struct gops_pmu tu104_ops_pmu = { .pmu_get_queue_head = tu104_pmu_queue_head_r, .pmu_mutex_release = gk20a_pmu_mutex_release, .pmu_is_interrupted = gk20a_pmu_is_interrupted, + .get_irqmask = gk20a_pmu_get_irqmask, .pmu_isr = gk20a_pmu_isr, .pmu_init_perfmon_counter = gk20a_pmu_init_perfmon_counter, .pmu_pg_idle_counter_config = gk20a_pmu_pg_idle_counter_config, diff --git a/drivers/gpu/nvgpu/hal/pmu/pmu_gk20a.h b/drivers/gpu/nvgpu/hal/pmu/pmu_gk20a.h index 01cc1b2b7..652091143 100644 --- a/drivers/gpu/nvgpu/hal/pmu/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/hal/pmu/pmu_gk20a.h @@ -33,6 +33,7 @@ struct pmu_mutexes; #define PMU_MODE_MISMATCH_STATUS_VAL 0xDEADDEADU void gk20a_pmu_isr(struct gk20a *g); +u32 gk20a_pmu_get_irqmask(struct gk20a *g); #ifdef CONFIG_NVGPU_LS_PMU void gk20a_pmu_dump_falcon_stats(struct nvgpu_pmu *pmu); diff --git a/drivers/gpu/nvgpu/hal/pmu/pmu_gk20a_fusa.c b/drivers/gpu/nvgpu/hal/pmu/pmu_gk20a_fusa.c index 80da5b835..25b2916af 100644 --- a/drivers/gpu/nvgpu/hal/pmu/pmu_gk20a_fusa.c +++ b/drivers/gpu/nvgpu/hal/pmu/pmu_gk20a_fusa.c @@ -28,33 +28,41 @@ #include "pmu_gk20a.h" -void gk20a_pmu_isr(struct gk20a *g) +u32 gk20a_pmu_get_irqmask(struct gk20a *g) { - struct nvgpu_pmu *pmu = g->pmu; - u32 intr, mask; - - nvgpu_log_fn(g, " "); - - nvgpu_mutex_acquire(&pmu->isr_mutex); - if (!pmu->isr_enabled) { - nvgpu_mutex_release(&pmu->isr_mutex); - return; - } + u32 mask = 0U; mask = nvgpu_readl(g, pwr_falcon_irqmask_r()); mask &= nvgpu_readl(g, pwr_falcon_irqdest_r()); + return mask; +} + +void gk20a_pmu_isr(struct gk20a *g) +{ + struct nvgpu_pmu *pmu = g->pmu; + u32 intr = 0U; + u32 mask = 0U; + + nvgpu_log_fn(g, " "); + intr = nvgpu_readl(g, pwr_falcon_irqstat_r()); + mask = g->ops.pmu.get_irqmask(g); + nvgpu_pmu_dbg(g, "received PMU interrupt: stat:0x%08x mask:0x%08x", + intr, mask); - nvgpu_pmu_dbg(g, "received falcon interrupt: 0x%08x", intr); - - intr = nvgpu_readl(g, pwr_falcon_irqstat_r()) & mask; - - if (intr == 0U) { + nvgpu_mutex_acquire(&pmu->isr_mutex); + if (!pmu->isr_enabled || !(intr & mask)) { + nvgpu_log_info(g, + "clearing unhandled interrupt: stat:0x%08x mask:0x%08x", + intr, mask); + nvgpu_writel(g, pwr_falcon_irqsclr_r(), intr); nvgpu_mutex_release(&pmu->isr_mutex); return; } + intr = intr & mask; + if (g->ops.pmu.handle_ext_irq != NULL) { g->ops.pmu.handle_ext_irq(g, intr); } diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops/pmu.h b/drivers/gpu/nvgpu/include/nvgpu/gops/pmu.h index 8f4ce88c4..5b0de3325 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gops/pmu.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gops/pmu.h @@ -311,6 +311,7 @@ struct gops_pmu { void (*pmu_enable_irq)(struct nvgpu_pmu *pmu, bool enable); u32 (*get_irqdest)(struct gk20a *g); + u32 (*get_irqmask)(struct gk20a *g); #ifdef CONFIG_NVGPU_LS_PMU u32 (*get_inst_block_config)(struct gk20a *g);