diff --git a/drivers/gpu/nvgpu/common/sec2/sec2_msg.c b/drivers/gpu/nvgpu/common/sec2/sec2_msg.c index 504c457bf..1ecc248bf 100644 --- a/drivers/gpu/nvgpu/common/sec2/sec2_msg.c +++ b/drivers/gpu/nvgpu/common/sec2/sec2_msg.c @@ -199,6 +199,54 @@ exit: return status; } +static void sec2_isr(struct gk20a *g, struct nvgpu_sec2 *sec2) +{ + bool recheck = false; + u32 intr; + + if (!g->ops.sec2.is_interrupted(sec2)) { + return; + } + + nvgpu_mutex_acquire(&sec2->isr_mutex); + if (!sec2->isr_enabled) { + goto exit; + } + + intr = g->ops.sec2.get_intr(g); + if (intr == 0U) { + goto exit; + } + + /* + * Handle swgen0 interrupt to process received messages from SEC2. + * If any other interrupt is to be handled with some software + * action expected, then it should be handled here. + * g->ops.sec2.isr call below will handle other hardware interrupts + * that are not expected to be handled in software. + */ + if (g->ops.sec2.msg_intr_received(g)) { + if (nvgpu_sec2_process_message(sec2) != 0) { + g->ops.sec2.clr_intr(g, intr); + goto exit; + } + recheck = true; + } + + g->ops.sec2.process_intr(g, sec2); + g->ops.sec2.clr_intr(g, intr); + + if (recheck) { + if (!nvgpu_sec2_queue_is_empty(sec2->queues, + SEC2_NV_MSGQ_LOG_ID)) { + g->ops.sec2.set_msg_intr(g); + } + } + +exit: + nvgpu_mutex_release(&sec2->isr_mutex); +} + int nvgpu_sec2_wait_message_cond(struct nvgpu_sec2 *sec2, u32 timeout_ms, void *var, u8 val) { @@ -213,9 +261,7 @@ int nvgpu_sec2_wait_message_cond(struct nvgpu_sec2 *sec2, u32 timeout_ms, return 0; } - if (g->ops.sec2.is_interrupted(sec2)) { - g->ops.sec2.isr(g); - } + sec2_isr(g, sec2); nvgpu_usleep_range(delay, delay * 2U); delay = min_t(u32, delay << 1U, POLL_DELAY_MAX_US); diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index b7fa8af28..0270b92e2 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -1840,7 +1840,11 @@ struct gpu_ops { void (*secured_sec2_start)(struct gk20a *g); void (*enable_irq)(struct nvgpu_sec2 *sec2, bool enable); bool (*is_interrupted)(struct nvgpu_sec2 *sec2); - void (*isr)(struct gk20a *g); + u32 (*get_intr)(struct gk20a *g); + bool (*msg_intr_received)(struct gk20a *g); + void (*set_msg_intr)(struct gk20a *g); + void (*clr_intr)(struct gk20a *g, u32 intr); + void (*process_intr)(struct gk20a *g, struct nvgpu_sec2 *sec2); void (*msgq_tail)(struct gk20a *g, struct nvgpu_sec2 *sec2, u32 *tail, bool set); u32 (*falcon_base_addr)(void); diff --git a/drivers/gpu/nvgpu/tu104/hal_tu104.c b/drivers/gpu/nvgpu/tu104/hal_tu104.c index 9ddf4b1cf..749bd3a82 100644 --- a/drivers/gpu/nvgpu/tu104/hal_tu104.c +++ b/drivers/gpu/nvgpu/tu104/hal_tu104.c @@ -1412,7 +1412,11 @@ static const struct gpu_ops tu104_ops = { .secured_sec2_start = tu104_start_sec2_secure, .enable_irq = tu104_sec2_enable_irq, .is_interrupted = tu104_sec2_is_interrupted, - .isr = tu104_sec2_isr, + .get_intr = tu104_sec2_get_intr, + .msg_intr_received = tu104_sec2_msg_intr_received, + .set_msg_intr = tu104_sec2_set_msg_intr, + .clr_intr = tu104_sec2_clr_intr, + .process_intr = tu104_sec2_process_intr, .msgq_tail = tu104_sec2_msgq_tail, .falcon_base_addr = tu104_sec2_falcon_base_addr, .sec2_reset = tu104_sec2_reset, diff --git a/drivers/gpu/nvgpu/tu104/sec2_tu104.c b/drivers/gpu/nvgpu/tu104/sec2_tu104.c index 0a110e8ca..bbd6ea95e 100644 --- a/drivers/gpu/nvgpu/tu104/sec2_tu104.c +++ b/drivers/gpu/nvgpu/tu104/sec2_tu104.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -310,7 +309,7 @@ void tu104_sec2_enable_irq(struct nvgpu_sec2 *sec2, bool enable) u32 intr_mask; u32 intr_dest; - nvgpu_falcon_set_irq(&g->sec2.flcn, false, 0x0, 0x0); + g->ops.falcon.set_irq(&sec2->flcn, false, 0x0, 0x0); if (enable) { /* dest 0=falcon, 1=host; level 0=irq0, 1=irq1 */ @@ -343,7 +342,7 @@ void tu104_sec2_enable_irq(struct nvgpu_sec2 *sec2, bool enable) psec_falcon_irqmset_swgen0_f(1) | psec_falcon_irqmset_swgen1_f(1); - nvgpu_falcon_set_irq(&g->sec2.flcn, true, intr_mask, intr_dest); + g->ops.falcon.set_irq(&sec2->flcn, true, intr_mask, intr_dest); } } @@ -364,34 +363,43 @@ bool tu104_sec2_is_interrupted(struct nvgpu_sec2 *sec2) return false; } -void tu104_sec2_isr(struct gk20a *g) +u32 tu104_sec2_get_intr(struct gk20a *g) { - struct nvgpu_sec2 *sec2 = &g->sec2; - struct nvgpu_engine_mem_queue *queue; - u32 intr, mask; - bool recheck = false; - - nvgpu_mutex_acquire(&sec2->isr_mutex); - if (!sec2->isr_enabled) { - nvgpu_mutex_release(&sec2->isr_mutex); - return; - } + u32 mask; mask = gk20a_readl(g, psec_falcon_irqmask_r()) & gk20a_readl(g, psec_falcon_irqdest_r()); - intr = gk20a_readl(g, psec_falcon_irqstat_r()); + return gk20a_readl(g, psec_falcon_irqstat_r()) & mask; +} - intr = gk20a_readl(g, psec_falcon_irqstat_r()) & mask; - if (intr == 0U) { - gk20a_writel(g, psec_falcon_irqsclr_r(), intr); - nvgpu_mutex_release(&sec2->isr_mutex); - return; - } +bool tu104_sec2_msg_intr_received(struct gk20a *g) +{ + u32 intr = tu104_sec2_get_intr(g); + + return (intr & psec_falcon_irqstat_swgen0_true_f()) != 0U; +} + +void tu104_sec2_set_msg_intr(struct gk20a *g) +{ + gk20a_writel(g, psec_falcon_irqsset_r(), + psec_falcon_irqsset_swgen0_set_f()); +} + +void tu104_sec2_clr_intr(struct gk20a *g, u32 intr) +{ + gk20a_writel(g, psec_falcon_irqsclr_r(), intr); +} + +void tu104_sec2_process_intr(struct gk20a *g, struct nvgpu_sec2 *sec2) +{ + u32 intr; + + intr = tu104_sec2_get_intr(g); if ((intr & psec_falcon_irqstat_halt_true_f()) != 0U) { nvgpu_err(g, "sec2 halt intr not implemented"); - nvgpu_falcon_dump_stats(&g->sec2.flcn); + g->ops.falcon.dump_falcon_stats(&sec2->flcn); } if ((intr & psec_falcon_irqstat_exterr_true_f()) != 0U) { nvgpu_err(g, @@ -402,27 +410,7 @@ void tu104_sec2_isr(struct gk20a *g) ~psec_falcon_exterrstat_valid_m()); } - if ((intr & psec_falcon_irqstat_swgen0_true_f()) != 0U) { - if (nvgpu_sec2_process_message(sec2) != 0) { - gk20a_writel(g, psec_falcon_irqsclr_r(), intr); - goto exit; - } - recheck = true; - } - - gk20a_writel(g, psec_falcon_irqsclr_r(), intr); - - if (recheck) { - queue = sec2->queues[SEC2_NV_MSGQ_LOG_ID]; - if (!nvgpu_engine_mem_queue_is_empty(queue)) { - gk20a_writel(g, psec_falcon_irqsset_r(), - psec_falcon_irqsset_swgen0_set_f()); - } - } - -exit: nvgpu_sec2_dbg(g, "Done"); - nvgpu_mutex_release(&sec2->isr_mutex); } void tu104_start_sec2_secure(struct gk20a *g) diff --git a/drivers/gpu/nvgpu/tu104/sec2_tu104.h b/drivers/gpu/nvgpu/tu104/sec2_tu104.h index 2b2a5f0cd..83f84e1de 100644 --- a/drivers/gpu/nvgpu/tu104/sec2_tu104.h +++ b/drivers/gpu/nvgpu/tu104/sec2_tu104.h @@ -23,6 +23,7 @@ #ifndef NVGPU_SEC2_TU104_H #define NVGPU_SEC2_TU104_H +struct gk20a; struct nvgpu_sec2; int tu104_sec2_reset(struct gk20a *g); @@ -39,8 +40,12 @@ int tu104_sec2_queue_tail(struct gk20a *g, u32 queue_id, u32 queue_index, void tu104_sec2_msgq_tail(struct gk20a *g, struct nvgpu_sec2 *sec2, u32 *tail, bool set); -void tu104_sec2_isr(struct gk20a *g); bool tu104_sec2_is_interrupted(struct nvgpu_sec2 *sec2); +u32 tu104_sec2_get_intr(struct gk20a *g); +bool tu104_sec2_msg_intr_received(struct gk20a *g); +void tu104_sec2_set_msg_intr(struct gk20a *g); +void tu104_sec2_clr_intr(struct gk20a *g, u32 intr); +void tu104_sec2_process_intr(struct gk20a *g, struct nvgpu_sec2 *sec2); void tu104_sec2_enable_irq(struct nvgpu_sec2 *sec2, bool enable); void tu104_start_sec2_secure(struct gk20a *g); u32 tu104_sec2_falcon_base_addr(void);