diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 5b24ef8a64..9e6ddb439e 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -573,6 +573,8 @@ bool hif_can_suspend_link(struct hif_opaque_softc *); int hif_bus_resume(struct hif_opaque_softc *); int hif_bus_suspend(struct hif_opaque_softc *); +int hif_bus_resume_noirq(struct hif_opaque_softc *); +int hif_bus_suspend_noirq(struct hif_opaque_softc *); #ifdef FEATURE_RUNTIME_PM int hif_pre_runtime_suspend(struct hif_opaque_softc *hif_ctx); diff --git a/hif/src/dispatcher/dummy.c b/hif/src/dispatcher/dummy.c index e9362f96d5..1690e058d8 100644 --- a/hif/src/dispatcher/dummy.c +++ b/hif/src/dispatcher/dummy.c @@ -83,6 +83,34 @@ int hif_dummy_bus_resume(struct hif_softc *hif_ctx) return 0; } +/** + * hif_dummy_suspend_noirq() - suspend the bus + * @hif_ctx: hif context + * + * dummy for busses that don't need to syncronize + * with interrupt disable. + * + * Return: 0 for success and non-zero for failure + */ +int hif_dummy_bus_suspend_noirq(struct hif_softc *hif_ctx) +{ + return 0; +} + +/** + * hif_dummy_resume_noirq() - resume the bus + * @hif_ctx: hif context + * + * dummy for busses that don't need to syncronize + * with interrupt disable. + * + * Return: 0 for success and non-zero for failure + */ +int hif_dummy_bus_resume_noirq(struct hif_softc *hif_ctx) +{ + return 0; +} + /** * hif_dummy_target_sleep_state_adjust() - api to adjust state of target * @scn: hif context diff --git a/hif/src/dispatcher/dummy.h b/hif/src/dispatcher/dummy.h index 049fa1a533..b531c1dd4e 100644 --- a/hif/src/dispatcher/dummy.h +++ b/hif/src/dispatcher/dummy.h @@ -30,6 +30,8 @@ void hif_dummy_bus_prevent_linkdown(struct hif_softc *scn, bool flag); void hif_dummy_reset_soc(struct hif_softc *scn); int hif_dummy_bus_suspend(struct hif_softc *hif_ctx); int hif_dummy_bus_resume(struct hif_softc *hif_ctx); +int hif_dummy_bus_suspend_noirq(struct hif_softc *hif_ctx); +int hif_dummy_bus_resume_noirq(struct hif_softc *hif_ctx); int hif_dummy_target_sleep_state_adjust(struct hif_softc *scn, bool sleep_ok, bool wait_for_it); void hif_dummy_enable_power_management(struct hif_softc *hif_ctx, diff --git a/hif/src/dispatcher/multibus.c b/hif/src/dispatcher/multibus.c index 416d997a5b..5643b6f057 100644 --- a/hif/src/dispatcher/multibus.c +++ b/hif/src/dispatcher/multibus.c @@ -55,8 +55,10 @@ static void hif_intialize_default_ops(struct hif_softc *hif_sc) &hif_dummy_display_stats; bus_ops->hif_clear_stats = &hif_dummy_clear_stats; - bus_ops->hif_set_bundle_mode = hif_dummy_set_bundle_mode; - bus_ops->hif_bus_reset_resume = hif_dummy_bus_reset_resume; + bus_ops->hif_set_bundle_mode = &hif_dummy_set_bundle_mode; + bus_ops->hif_bus_reset_resume = &hif_dummy_bus_reset_resume; + bus_ops->hif_bus_suspend_noirq = &hif_dummy_bus_suspend_noirq; + bus_ops->hif_bus_resume_noirq = &hif_dummy_bus_resume_noirq; } #define NUM_OPS (sizeof(struct hif_bus_ops) / sizeof(void *)) @@ -195,6 +197,18 @@ int hif_bus_resume(struct hif_opaque_softc *hif_ctx) return hif_sc->bus_ops.hif_bus_resume(hif_sc); } +int hif_bus_suspend_noirq(struct hif_opaque_softc *hif_ctx) +{ + struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx); + return hif_sc->bus_ops.hif_bus_suspend_noirq(hif_sc); +} + +int hif_bus_resume_noirq(struct hif_opaque_softc *hif_ctx) +{ + struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx); + return hif_sc->bus_ops.hif_bus_resume_noirq(hif_sc); +} + int hif_target_sleep_state_adjust(struct hif_softc *hif_sc, bool sleep_ok, bool wait_for_it) { diff --git a/hif/src/dispatcher/multibus.h b/hif/src/dispatcher/multibus.h index 71b7a3c76b..63423630c1 100644 --- a/hif/src/dispatcher/multibus.h +++ b/hif/src/dispatcher/multibus.h @@ -42,6 +42,8 @@ struct hif_bus_ops { void (*hif_reset_soc)(struct hif_softc *hif_sc); int (*hif_bus_suspend)(struct hif_softc *hif_ctx); int (*hif_bus_resume)(struct hif_softc *hif_ctx); + int (*hif_bus_suspend_noirq)(struct hif_softc *hif_ctx); + int (*hif_bus_resume_noirq)(struct hif_softc *hif_ctx); int (*hif_target_sleep_state_adjust)(struct hif_softc *scn, bool sleep_ok, bool wait_for_it); void (*hif_disable_isr)(struct hif_softc *hif_sc); diff --git a/hif/src/dispatcher/multibus_snoc.c b/hif/src/dispatcher/multibus_snoc.c index ae292709fe..2dc80d62e6 100644 --- a/hif/src/dispatcher/multibus_snoc.c +++ b/hif/src/dispatcher/multibus_snoc.c @@ -47,6 +47,9 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops) bus_ops->hif_reset_soc = &hif_dummy_reset_soc; bus_ops->hif_bus_suspend = &hif_snoc_bus_suspend; bus_ops->hif_bus_resume = &hif_snoc_bus_resume; + bus_ops->hif_bus_suspend_noirq = &hif_snoc_bus_suspend_noirq; + /* snoc_bus_resume_noirq had no side effects, use dummy resume_noirq */ + bus_ops->hif_bus_resume_noirq = &hif_dummy_bus_resume_noirq; bus_ops->hif_target_sleep_state_adjust = &hif_dummy_target_sleep_state_adjust; diff --git a/hif/src/dispatcher/snoc_api.h b/hif/src/dispatcher/snoc_api.h index 813171f119..06fc43d5ae 100644 --- a/hif/src/dispatcher/snoc_api.h +++ b/hif/src/dispatcher/snoc_api.h @@ -32,6 +32,7 @@ QDF_STATUS hif_snoc_open(struct hif_softc *hif_ctx, void hif_snoc_close(struct hif_softc *hif_ctx); int hif_snoc_bus_suspend(struct hif_softc *hif_ctx); int hif_snoc_bus_resume(struct hif_softc *hif_ctx); +int hif_snoc_bus_suspend_noirq(struct hif_softc *scn); void hif_snoc_disable_isr(struct hif_softc *hif_ctx); void hif_snoc_nointrs(struct hif_softc *scn); QDF_STATUS hif_snoc_enable_bus(struct hif_softc *ol_sc, diff --git a/hif/src/snoc/if_snoc.c b/hif/src/snoc/if_snoc.c index 77bc554936..201eb7c8fd 100644 --- a/hif/src/snoc/if_snoc.c +++ b/hif/src/snoc/if_snoc.c @@ -380,75 +380,6 @@ QDF_STATUS hif_snoc_setup_wakeup_sources(struct hif_softc *scn, bool enable) return QDF_STATUS_SUCCESS; } -/** - * __hif_snoc_irq_state_vote() - enable/disable all the ce interrupts - * @scn: hif context pointer - * @enble: true to enable the interrupts false to disable - * - * takes care of unwinding partial successes. - * - * Return: QDF_STATUS_SUCCESS on success - */ - -static QDF_STATUS __hif_snoc_irq_state_vote(struct hif_softc *scn, bool enable) -{ - int num_ce = scn->ce_count; - int ce_id = 0; - int irq; - - while (ce_id < num_ce) { - irq = icnss_get_irq(ce_id); - if (irq < 0) - goto error; - - if (enable) - enable_irq(irq); - else - disable_irq(irq); - - ce_id++; - } - - return QDF_STATUS_SUCCESS; - -error: - HIF_ERROR("%s: failed to map ce to irq", __func__); - - while (--ce_id >= 0) { - irq = icnss_get_irq(ce_id); - if (irq < 0) - continue; - - if (enable) - disable_irq(irq); - else - enable_irq(irq); - } - return QDF_STATUS_E_FAULT; -} - -/** - * hif_snoc_enable_irqs() - enable the ce irqs - * @scn: hif context - * - * Return: QDF_STATUS_SUCCESS on success - */ -static QDF_STATUS hif_snoc_enable_irqs(struct hif_softc *scn) -{ - return __hif_snoc_irq_state_vote(scn, true); -} - -/** - * hif_snoc_enable_irqs() - enable the ce irqs - * @scn: hif context - * - * Return: QDF_STATUS_SUCCESS on success - */ -static QDF_STATUS hif_snoc_disable_irqs(struct hif_softc *scn) -{ - return __hif_snoc_irq_state_vote(scn, false); -} - /** * hif_snoc_bus_suspend() - prepare to suspend the bus * @scn: hif context @@ -463,24 +394,8 @@ static QDF_STATUS hif_snoc_disable_irqs(struct hif_softc *scn) int hif_snoc_bus_suspend(struct hif_softc *scn) { if (hif_snoc_setup_wakeup_sources(scn, true) != QDF_STATUS_SUCCESS) - goto error; - - if (hif_snoc_disable_irqs(scn) != QDF_STATUS_SUCCESS) - goto wakeup_sources; - - if (hif_drain_tasklets(scn) != 0) - goto enable_irqs; + return -EFAULT; return 0; - -enable_irqs: - if (hif_snoc_enable_irqs(scn) != QDF_STATUS_SUCCESS) - QDF_BUG(0); -wakeup_sources: - if (hif_snoc_setup_wakeup_sources(scn, false) != QDF_STATUS_SUCCESS) - QDF_BUG(0); -error: - return -EFAULT; - } /** @@ -497,8 +412,22 @@ int hif_snoc_bus_resume(struct hif_softc *scn) if (hif_snoc_setup_wakeup_sources(scn, false) != QDF_STATUS_SUCCESS) QDF_BUG(0); - if (hif_snoc_enable_irqs(scn) != QDF_STATUS_SUCCESS) - QDF_BUG(0); - return 0; } + +/** + * hif_snoc_bus_suspend_noirq() - ensure there are no pending transactions + * @scn: hif context + * + * Ensure that if we recieved the wakeup message before the irq + * was disabled that the message is pocessed before suspending. + * + * Return: -EBUSY if we fail to flush the tasklets. + */ +int hif_snoc_bus_suspend_noirq(struct hif_softc *scn) +{ + if (hif_drain_tasklets(scn) != 0) + return -EBUSY; + return 0; +} +