diff --git a/components/ipa/core/inc/wlan_ipa_core.h b/components/ipa/core/inc/wlan_ipa_core.h index 535f8f6cba9d..7d8510a1324d 100644 --- a/components/ipa/core/inc/wlan_ipa_core.h +++ b/components/ipa/core/inc/wlan_ipa_core.h @@ -650,5 +650,14 @@ void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx, * Return: None */ void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx); + +/** + * wlan_ipa_fw_rejuvenate_send_msg() - send fw rejuvenate message to IPA driver + * @ipa_ctx: IPA context + * + * Return: void + */ +void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx); + #endif /* IPA_OFFLOAD */ #endif /* _WLAN_IPA_CORE_H_ */ diff --git a/components/ipa/core/inc/wlan_ipa_main.h b/components/ipa/core/inc/wlan_ipa_main.h index 596e69ae12c9..4efb7f648949 100644 --- a/components/ipa/core/inc/wlan_ipa_main.h +++ b/components/ipa/core/inc/wlan_ipa_main.h @@ -413,5 +413,14 @@ void ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev, * Return: None */ void ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev); + +/** + * ipa_fw_rejuvenate_send_msg() - send fw rejuvenate message to IPA driver + * @pdev: pdev obj + * + * Return: None + */ +void ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev); + #endif /* IPA_OFFLOAD */ #endif /* end of _WLAN_IPA_MAIN_H_ */ diff --git a/components/ipa/core/src/wlan_ipa_core.c b/components/ipa/core/src/wlan_ipa_core.c index 9f9bc1ceed10..c7bdbad71146 100644 --- a/components/ipa/core/src/wlan_ipa_core.c +++ b/components/ipa/core/src/wlan_ipa_core.c @@ -3004,3 +3004,29 @@ void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx) } } } + +void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx) +{ + qdf_ipa_msg_meta_t meta; + qdf_ipa_wlan_msg_t *msg; + int ret; + + meta.msg_len = sizeof(*msg); + msg = qdf_mem_malloc(meta.msg_len); + if (!msg) { + ipa_debug("msg allocation failed"); + return; + } + + QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN); + ipa_debug("ipa_send_msg(Evt:%d)", + meta.msg_type); + ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn); + + if (ret) { + ipa_err("ipa_send_msg(Evt:%d)-fail=%d", + meta.msg_type, ret); + qdf_mem_free(msg); + } + ipa_ctx->stats.num_send_msg++; +} diff --git a/components/ipa/core/src/wlan_ipa_main.c b/components/ipa/core/src/wlan_ipa_main.c index 31a20806840a..c4e2c048a5a9 100644 --- a/components/ipa/core/src/wlan_ipa_main.c +++ b/components/ipa/core/src/wlan_ipa_main.c @@ -589,3 +589,16 @@ void ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev) return wlan_ipa_uc_ssr_cleanup(ipa_obj); } + +void ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_ipa_priv *ipa_obj; + + ipa_obj = ipa_pdev_get_priv_obj(pdev); + if (!ipa_obj) { + ipa_err("IPA object is NULL"); + return; + } + + return wlan_ipa_fw_rejuvenate_send_msg(ipa_obj); +} diff --git a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h index b9a041c526bd..d10db6a17707 100644 --- a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h +++ b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h @@ -323,6 +323,15 @@ void ucfg_ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev, * Return: None */ void ucfg_ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev); + +/** + * ucfg_ipa_fw_rejuvenate_send_msg() - Send msg to IPA driver in FW rejuvenate + * @pdev: pdev obj + * + * Return: None + */ +void ucfg_ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev); + #else static inline bool ucfg_ipa_is_present(void) @@ -503,5 +512,10 @@ static inline void ucfg_ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev) { } + +static inline +void ucfg_ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev) +{ +} #endif /* IPA_OFFLOAD */ #endif /* _WLAN_IPA_UCFG_API_H_ */ diff --git a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c index 7bca1ec617ea..314e4abbeb64 100644 --- a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c +++ b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c @@ -191,3 +191,8 @@ void ucfg_ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev) { return ipa_uc_ssr_cleanup(pdev); } + +void ucfg_ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev) +{ + return ipa_fw_rejuvenate_send_msg(pdev); +} diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index a69da7a8dfef..b41f92695e06 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -1552,6 +1552,9 @@ static void wlan_hdd_handle_the_pld_uevent(struct pld_uevent_data *uevent) qdf_complete_wait_events(); cds_set_target_ready(false); wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, NULL); + if (pld_is_fw_rejuvenate(hdd_ctx->parent_dev) && + ucfg_ipa_is_enabled()) + ucfg_ipa_fw_rejuvenate_send_msg(hdd_ctx->pdev); break; default: break; diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h index 216fe4556d90..7dab6cb5f907 100644 --- a/core/pld/inc/pld_common.h +++ b/core/pld/inc/pld_common.h @@ -546,6 +546,17 @@ int pld_is_fw_down(struct device *dev); int pld_force_assert_target(struct device *dev); bool pld_is_fw_dump_skipped(struct device *dev); +/** + * pld_is_fw_rejuvenate() - Check WLAN fw is rejuvenating + * + * Help the driver decide whether FW down is due to + * SSR or FW rejuvenate. + * + * Return: 1 FW is rejuvenating + * 0 FW is not rejuvenating + */ +int pld_is_fw_rejuvenate(struct device *dev); + #if defined(CONFIG_WCNSS_MEM_PRE_ALLOC) && defined(FEATURE_SKB_PRE_ALLOC) /** diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c index 64cc7206f646..ff6b39966155 100644 --- a/core/pld/src/pld_common.c +++ b/core/pld/src/pld_common.c @@ -1555,3 +1555,18 @@ bool pld_is_fw_dump_skipped(struct device *dev) } return ret; } + +int pld_is_fw_rejuvenate(struct device *dev) +{ + int ret = 0; + enum pld_bus_type type = pld_get_bus_type(dev); + + switch (type) { + case PLD_BUS_TYPE_SNOC: + ret = pld_snoc_is_fw_rejuvenate(); + break; + default: + break; + } + return ret; +} diff --git a/core/pld/src/pld_snoc.h b/core/pld/src/pld_snoc.h index 991554ab06c7..954989c821be 100644 --- a/core/pld/src/pld_snoc.h +++ b/core/pld/src/pld_snoc.h @@ -126,6 +126,12 @@ static inline int pld_snoc_force_assert_target(struct device *dev) { return 0; } + +static inline int pld_snoc_is_fw_rejuvenate(void) +{ + return 0; +} + #else int pld_snoc_register_driver(void); void pld_snoc_unregister_driver(void); @@ -293,5 +299,11 @@ static inline int pld_snoc_force_assert_target(struct device *dev) { return icnss_trigger_recovery(dev); } + +static inline int pld_snoc_is_fw_rejuvenate(void) +{ + return icnss_is_rejuvenate(); +} + #endif #endif