diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c index 16c7c052a5..43e2eee564 100644 --- a/hif/src/ce/ce_tasklet.c +++ b/hif/src/ce/ce_tasklet.c @@ -377,6 +377,28 @@ void hif_clear_ce_stats(struct HIF_CE_state *hif_ce_state) qdf_mem_zero(&hif_ce_state->stats, sizeof(struct ce_stats)); } +/** + * hif_tasklet_schedule() - schedule tasklet + * @hif_ctx: hif context + * @tasklet_entry: ce tasklet entry + * + * Return: false if tasklet already scheduled, otherwise true + */ +static inline bool hif_tasklet_schedule(struct hif_opaque_softc *hif_ctx, + struct ce_tasklet_entry *tasklet_entry) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + + if (test_bit(TASKLET_STATE_SCHED, &tasklet_entry->intr_tq.state)) { + HIF_DBG("tasklet scheduled, return"); + qdf_atomic_dec(&scn->active_tasklet_cnt); + return false; + } + + tasklet_schedule(&tasklet_entry->intr_tq); + return true; +} + /** * ce_dispatch_interrupt() - dispatch an interrupt to a processing context * @ce_id: ce_id @@ -422,7 +444,7 @@ irqreturn_t ce_dispatch_interrupt(int ce_id, if (hif_napi_enabled(hif_hdl, ce_id)) hif_napi_schedule(hif_hdl, ce_id); else - tasklet_schedule(&tasklet_entry->intr_tq); + hif_tasklet_schedule(hif_hdl, tasklet_entry); return IRQ_HANDLED; } diff --git a/hif/src/hif_napi.c b/hif/src/hif_napi.c index a609fab001..813188b3f1 100644 --- a/hif/src/hif_napi.c +++ b/hif/src/hif_napi.c @@ -750,17 +750,14 @@ inline void hif_napi_enable_irq(struct hif_opaque_softc *hif, int id) * @scn: hif context * @ce_id: index of napi instance * - * Return: void + * Return: false if napi didn't enable or already scheduled, otherwise true */ -int hif_napi_schedule(struct hif_opaque_softc *hif_ctx, int ce_id) +bool hif_napi_schedule(struct hif_opaque_softc *hif_ctx, int ce_id) { int cpu = smp_processor_id(); struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); struct qca_napi_info *napii; - hif_record_ce_desc_event(scn, ce_id, NAPI_SCHEDULE, - NULL, NULL, 0, 0); - napii = scn->napi_data.napis[ce_id]; if (qdf_unlikely(!napii)) { HIF_ERROR("%s, scheduling unallocated napi (ce:%d)", @@ -769,6 +766,14 @@ int hif_napi_schedule(struct hif_opaque_softc *hif_ctx, int ce_id) return false; } + if (test_bit(NAPI_STATE_SCHED, &napii->napi.state)) { + NAPI_DEBUG("napi scheduled, return"); + qdf_atomic_dec(&scn->active_tasklet_cnt); + return false; + } + + hif_record_ce_desc_event(scn, ce_id, NAPI_SCHEDULE, + NULL, NULL, 0, 0); napii->stats[cpu].napi_schedules++; NAPI_DEBUG("scheduling napi %d (ce:%d)", napii->id, ce_id); napi_schedule(&(napii->napi)); diff --git a/hif/src/hif_napi.h b/hif/src/hif_napi.h index e2e61d280a..0d164f155f 100644 --- a/hif/src/hif_napi.h +++ b/hif/src/hif_napi.h @@ -168,7 +168,7 @@ bool hif_napi_created(struct hif_opaque_softc *hif, int ce); void hif_napi_enable_irq(struct hif_opaque_softc *hif, int id); /* called by ce_tasklet.c::ce_dispatch_interrupt*/ -int hif_napi_schedule(struct hif_opaque_softc *scn, int ce_id); +bool hif_napi_schedule(struct hif_opaque_softc *scn, int ce_id); /* called by hdd_napi, which is called by kernel */ int hif_napi_poll(struct hif_opaque_softc *hif_ctx, @@ -253,8 +253,8 @@ static inline bool hif_napi_created(struct hif_opaque_softc *hif, int ce) static inline void hif_napi_enable_irq(struct hif_opaque_softc *hif, int id) { return; } -static inline int hif_napi_schedule(struct hif_opaque_softc *hif, int ce_id) -{ return 0; } +static inline bool hif_napi_schedule(struct hif_opaque_softc *hif, int ce_id) +{ return false; } static inline int hif_napi_poll(struct napi_struct *napi, int budget) { return -EPERM; }