|
@@ -812,6 +812,53 @@ int hif_drain_fw_diag_ce(struct hif_softc *scn)
|
|
|
return ce_poll_reap_by_id(scn, ce_id);
|
|
|
}
|
|
|
|
|
|
+#ifdef CE_TASKLET_SCHEDULE_ON_FULL
|
|
|
+static inline int ce_check_tasklet_status(int ce_id,
|
|
|
+ struct ce_tasklet_entry *entry)
|
|
|
+{
|
|
|
+ struct HIF_CE_state *hif_ce_state = entry->hif_ce_state;
|
|
|
+ struct hif_softc *scn = HIF_GET_SOFTC(hif_ce_state);
|
|
|
+ struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
|
|
|
+
|
|
|
+ if (hif_napi_enabled(hif_hdl, ce_id)) {
|
|
|
+ struct qca_napi_info *napi;
|
|
|
+
|
|
|
+ napi = scn->napi_data.napis[ce_id];
|
|
|
+ if (test_bit(NAPI_STATE_SCHED, &napi->napi.state))
|
|
|
+ return -EBUSY;
|
|
|
+ } else {
|
|
|
+ if (test_bit(TASKLET_STATE_SCHED,
|
|
|
+ &hif_ce_state->tasklets[ce_id].intr_tq.state))
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline void ce_interrupt_lock(struct CE_state *ce_state)
|
|
|
+{
|
|
|
+ qdf_spin_lock_irqsave(&ce_state->ce_interrupt_lock);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void ce_interrupt_unlock(struct CE_state *ce_state)
|
|
|
+{
|
|
|
+ qdf_spin_unlock_irqrestore(&ce_state->ce_interrupt_lock);
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline int ce_check_tasklet_status(int ce_id,
|
|
|
+ struct ce_tasklet_entry *entry)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline void ce_interrupt_lock(struct CE_state *ce_state)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static inline void ce_interrupt_unlock(struct CE_state *ce_state)
|
|
|
+{
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/**
|
|
|
* ce_dispatch_interrupt() - dispatch an interrupt to a processing context
|
|
|
* @ce_id: ce_id
|
|
@@ -825,6 +872,7 @@ irqreturn_t ce_dispatch_interrupt(int ce_id,
|
|
|
struct HIF_CE_state *hif_ce_state = tasklet_entry->hif_ce_state;
|
|
|
struct hif_softc *scn = HIF_GET_SOFTC(hif_ce_state);
|
|
|
struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
|
|
|
+ struct CE_state *ce_state = scn->ce_id_to_state[ce_id];
|
|
|
|
|
|
if (tasklet_entry->ce_id != ce_id) {
|
|
|
bool rl;
|
|
@@ -845,10 +893,18 @@ irqreturn_t ce_dispatch_interrupt(int ce_id,
|
|
|
return IRQ_NONE;
|
|
|
}
|
|
|
|
|
|
+ ce_interrupt_lock(ce_state);
|
|
|
+ if (ce_check_tasklet_status(ce_id, tasklet_entry)) {
|
|
|
+ ce_interrupt_unlock(ce_state);
|
|
|
+ return IRQ_NONE;
|
|
|
+ }
|
|
|
+
|
|
|
hif_irq_disable(scn, ce_id);
|
|
|
|
|
|
- if (!TARGET_REGISTER_ACCESS_ALLOWED(scn))
|
|
|
+ if (!TARGET_REGISTER_ACCESS_ALLOWED(scn)) {
|
|
|
+ ce_interrupt_unlock(ce_state);
|
|
|
return IRQ_HANDLED;
|
|
|
+ }
|
|
|
|
|
|
hif_record_ce_desc_event(scn, ce_id, HIF_IRQ_EVENT,
|
|
|
NULL, NULL, 0, 0);
|
|
@@ -857,6 +913,7 @@ irqreturn_t ce_dispatch_interrupt(int ce_id,
|
|
|
if (unlikely(hif_interrupt_is_ut_resume(scn, ce_id))) {
|
|
|
hif_ut_fw_resume(scn);
|
|
|
hif_irq_enable(scn, ce_id);
|
|
|
+ ce_interrupt_unlock(ce_state);
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
@@ -867,6 +924,8 @@ irqreturn_t ce_dispatch_interrupt(int ce_id,
|
|
|
else
|
|
|
hif_tasklet_schedule(hif_hdl, tasklet_entry);
|
|
|
|
|
|
+ ce_interrupt_unlock(ce_state);
|
|
|
+
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|