diff --git a/core/hif/inc/hif.h b/core/hif/inc/hif.h index 3ccf9d2f4a9f..2deb9c831901 100644 --- a/core/hif/inc/hif.h +++ b/core/hif/inc/hif.h @@ -646,6 +646,7 @@ void hif_enable_power_gating(void *hif_ctx); #ifdef FEATURE_RUNTIME_PM struct hif_pm_runtime_lock; int hif_pm_runtime_get(void *hif_ctx); +void hif_pm_runtime_get_noresume(void *hif_ctx); int hif_pm_runtime_put(void *hif_ctx); struct hif_pm_runtime_lock *hif_runtime_lock_init(const char *name); void hif_runtime_lock_deinit(struct hif_pm_runtime_lock *lock); @@ -659,6 +660,10 @@ int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, struct hif_pm_runtime_lock { const char *name; }; + +static inline void hif_pm_runtime_get_noresume(void *hif_ctx) +{} + static inline int hif_pm_runtime_get(void *hif_ctx) { return 0; } static inline int hif_pm_runtime_put(void *hif_ctx) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 31a64f5cbdac..0b7d9d000e37 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -779,6 +779,7 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, } while (ce_completed_recv_next(copyeng, &ce_context, &transfer_context, &CE_data, &nbytes, &transfer_id, &flags) == CDF_STATUS_SUCCESS); + } /* TBDXXX: Set CE High Watermark; invoke txResourceAvailHandler in response */ diff --git a/core/hif/src/ce/ce_service.c b/core/hif/src/ce/ce_service.c index 0d97b4949943..0437f2d43b71 100644 --- a/core/hif/src/ce/ce_service.c +++ b/core/hif/src/ce/ce_service.c @@ -548,6 +548,7 @@ int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, struct CE_src_desc *shadow_src_desc = CE_SRC_RING_TO_DESC(shadow_base, write_index); + hif_pm_runtime_get_noresume(scn); msdu = msdus[i]; /* @@ -619,10 +620,15 @@ int ce_send_fast(struct CE_handle *copyeng, cdf_nbuf_t *msdus, /* Write the final index to h/w one-shot */ if (i) { src_ring->write_index = write_index; - /* Don't call WAR_XXX from here - * Just call XXX instead, that has the reqd. intel - */ - war_ce_src_ring_write_idx_set(scn, ctrl_addr, write_index); + + if (hif_pm_runtime_get(scn) == 0) { + /* Don't call WAR_XXX from here + * Just call XXX instead, that has the reqd. intel + */ + war_ce_src_ring_write_idx_set(scn, ctrl_addr, + write_index); + hif_pm_runtime_put(scn); + } } cdf_spin_unlock_bh(&ce_state->ce_index_lock); diff --git a/core/hif/src/pcie/if_pci.c b/core/hif/src/pcie/if_pci.c index 7b90546f4c4c..1425d2c1b617 100644 --- a/core/hif/src/pcie/if_pci.c +++ b/core/hif/src/pcie/if_pci.c @@ -2004,6 +2004,41 @@ int hif_runtime_suspend(void) return hif_bus_suspend(); } +#ifdef WLAN_FEATURE_FASTPATH +/** + * hif_fastpath_resume() - resume fastpath for runtimepm + * + * ensure that the fastpath write index register is up to date + * since runtime pm may cause ce_send_fast to skip the register + * write. + */ +static void hif_fastpath_resume(void) +{ + struct ol_softc *scn = + (struct ol_softc *)cds_get_context(CDF_MODULE_ID_HIF); + struct CE_state *ce_state; + + if (!scn) + return; + + if (scn->fastpath_mode_on) { + if (Q_TARGET_ACCESS_BEGIN(scn)) { + ce_state = scn->ce_id_to_state[CE_HTT_H2T_MSG]; + cdf_spin_lock_bh(&ce_state->ce_index_lock); + + /*war_ce_src_ring_write_idx_set */ + CE_SRC_RING_WRITE_IDX_SET(scn, ce_state->ctrl_addr, + ce_state->src_ring->write_index); + cdf_spin_unlock_bh(&ce_state->ce_index_lock); + Q_TARGET_ACCESS_END(scn); + } + } +} +#else +static void hif_fastpath_resume(void) {} +#endif + + /** * hif_runtime_resume() - do the bus resume part of a runtime resume * @@ -2011,7 +2046,11 @@ int hif_runtime_suspend(void) */ int hif_runtime_resume(void) { - return hif_bus_resume(); + int status = hif_bus_resume(); + + hif_fastpath_resume(); + + return status; } void hif_disable_isr(void *ol_sc) @@ -2690,6 +2729,23 @@ int hif_get_target_type(struct ol_softc *ol_sc, struct device *dev, } #ifdef FEATURE_RUNTIME_PM + +void hif_pm_runtime_get_noresume(void *hif_ctx) +{ + struct ol_softc *scn = hif_ctx; + struct hif_pci_softc *sc; + + if (NULL == scn) + return; + + sc = scn->hif_sc; + if (NULL == sc) + return; + + sc->pm_stats.runtime_get++; + pm_runtime_get_noresume(sc->dev); +} + /** * hif_pm_runtime_get() - do a get opperation on the device * diff --git a/core/hif/src/snoc/if_snoc.c b/core/hif/src/snoc/if_snoc.c index f84b772b0d4d..52bebcd3ec2a 100644 --- a/core/hif/src/snoc/if_snoc.c +++ b/core/hif/src/snoc/if_snoc.c @@ -186,7 +186,6 @@ static int hif_runtime_resume(void) return hif_bus_resume(); } - /** * hif_enable_power_gating(): enable HW power gating *