diff --git a/core/hdd/inc/wlan_hdd_ipa.h b/core/hdd/inc/wlan_hdd_ipa.h index a2f5fb32e1c1..d4189bee05ab 100644 --- a/core/hdd/inc/wlan_hdd_ipa.h +++ b/core/hdd/inc/wlan_hdd_ipa.h @@ -56,6 +56,9 @@ void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter, uint8_t reason); bool hdd_ipa_is_enabled(hdd_context_t *pHddCtx); bool hdd_ipa_uc_is_enabled(hdd_context_t *pHddCtx); int hdd_ipa_send_mcc_scc_msg(hdd_context_t *pHddCtx, bool mcc_mode); +int hdd_ipa_uc_ssr_reinit(void); +int hdd_ipa_uc_ssr_deinit(void); +void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx); #else static inline CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) { @@ -131,12 +134,6 @@ static inline bool hdd_ipa_uc_is_enabled(hdd_context_t *pHddCtx) { return false; } -#endif /* IPA_OFFLOAD */ - -#ifdef IPA_UC_OFFLOAD -int hdd_ipa_uc_ssr_reinit(void); -int hdd_ipa_uc_ssr_deinit(void); -#else static inline int hdd_ipa_uc_ssr_reinit(void) { return false; @@ -146,6 +143,10 @@ static inline int hdd_ipa_uc_ssr_deinit(void) { return false; } +static inline void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx) +{ + return; +} #endif #endif /* #ifndef HDD_IPA_H__ */ diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 7f6ed0b45938..236dd036d23d 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -397,6 +397,7 @@ struct hdd_ipa_priv { struct ipa_uc_stas_map assoc_stas_map[WLAN_MAX_STA_COUNT]; cdf_list_t pending_event; cdf_mutex_t event_lock; + bool ipa_pipes_down; uint32_t ipa_tx_packets_diff; uint32_t ipa_rx_packets_diff; uint32_t ipa_p_tx_packets; @@ -1005,7 +1006,7 @@ static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa) return result; } ol_txrx_ipa_uc_set_active(cds_ctx->pdev_txrx_ctx, true, false); - + hdd_ipa->ipa_pipes_down = false; return 0; } @@ -1019,6 +1020,8 @@ static int hdd_ipa_uc_disable_pipes(struct hdd_ipa_priv *hdd_ipa) { int result; + hdd_ipa->ipa_pipes_down = true; + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, "%s: Disable RX PIPE", __func__); result = ipa_suspend_wdi_pipe(hdd_ipa->rx_pipe_handle); if (result) { @@ -1754,7 +1757,37 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) return CDF_STATUS_SUCCESS; } -#ifdef IPA_UC_OFFLOAD +/** + * hdd_ipa_uc_force_pipe_shutdown() - Force shutdown IPA pipe + * @hdd_ctx: hdd main context + * + * Force shutdown IPA pipe + * Independent of FW pipe status, IPA pipe shutdonw progress + * in case, any STA does not leave properly, IPA HW pipe should cleaned up + * independent from FW pipe status + * + * Return: NONE + */ +void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx) +{ + struct hdd_ipa_priv *hdd_ipa; + + if (!hdd_ipa_is_enabled(hdd_ctx) || !hdd_ctx->hdd_ipa) + return; + + hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa; + if (false == hdd_ipa->ipa_pipes_down) { + HDD_IPA_LOG(CDF_TRACE_LEVEL_ERROR, + "IPA pipes are not down yet, force shutdown"); + hdd_ipa_uc_disable_pipes(hdd_ipa); + } else { + HDD_IPA_LOG(CDF_TRACE_LEVEL_INFO, + "IPA pipes are down, do nothing"); + } + + return; +} + /** * hdd_ipa_uc_ssr_deinit() - handle ipa deinit for SSR * @@ -1763,6 +1796,7 @@ static CDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx) * * Return: 0 - Success */ +#ifdef IPA_UC_OFFLOAD int hdd_ipa_uc_ssr_deinit(void) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; @@ -1798,6 +1832,13 @@ int hdd_ipa_uc_ssr_deinit(void) */ return 0; } +#else +int hdd_ipa_uc_ssr_deinit(void) +{ + return 0; +} +#endif + /** * hdd_ipa_uc_ssr_reinit() - handle ipa reinit after SSR @@ -1807,6 +1848,7 @@ int hdd_ipa_uc_ssr_deinit(void) * * Return: 0 - Success */ +#ifdef IPA_UC_OFFLOAD int hdd_ipa_uc_ssr_reinit(void) { struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; @@ -1821,6 +1863,11 @@ int hdd_ipa_uc_ssr_reinit(void) */ return 0; } +#else +int hdd_ipa_uc_ssr_reinit(void) +{ + return 0; +} #endif /** @@ -3813,7 +3860,7 @@ CDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) hdd_ipa->resource_loading = false; hdd_ipa->resource_unloading = false; hdd_ipa->sta_connected = 0; - + hdd_ipa->ipa_pipes_down = true; /* Setup IPA sys_pipe for MCC */ if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) { ret = hdd_ipa_setup_sys_pipe(hdd_ipa); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c25c880ffba7..85e62e6a441f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -5672,6 +5672,8 @@ static void hdd_driver_exit(void) hddLog(CDF_TRACE_LEVEL_FATAL, FL("module exit called before probe")); } else { + /* Check IPA HW Pipe shutdown */ + hdd_ipa_uc_force_pipe_shutdown(hdd_ctx); #ifdef QCA_PKT_PROTO_TRACE cds_pkt_proto_trace_close(); #endif /* QCA_PKT_PROTO_TRACE */