From 7f898dfcc20c6ad27c946334cf5e432699aca714 Mon Sep 17 00:00:00 2001 From: Shashikala Prabhu Date: Wed, 28 Jun 2023 17:26:35 +0530 Subject: [PATCH] qcacmn: Add buffer window for umac reset in progress When the peer delete timer/vdev manager response timer expires, host checks if the umac reset is in progress. If so, host will retrigger the timer. It is possible that the umac reset is just completed and either of these two timers got expired. In this case, host will assert saying that the peer delete response/vdev manager response is not received from FW. FW may take a few milliseconds to send the peer delete/vdev manager response to the host after the umac recovery completes. Hence, to avoid the crash, check if the umac reset was in progress during the umac reset buffer window. Add the below changes as well, 1) INI support to get the umac reset buffer window value. 2) Renamed the API dp_umac_reset_is_inprogress as dp_get_umac_reset_in_progress_state to return either CDP_UMAC_RESET_IN_PROGRESS or CDP_UMAC_RESET_IN_PROGRESS_DURING_BUFFER_WINDOW. Change-Id: Ie15ef0731bad4b0ed955a479f00e297b7ba10729 CRs-Fixed: 3522665 --- dp/inc/cdp_txrx_cmn_struct.h | 14 +++++++++++ dp/inc/cdp_txrx_ctrl.h | 46 +++++++++++++++++++++++++++++------- dp/inc/cdp_txrx_ops.h | 5 +++- dp/wifi3.0/be/mlo/dp_mlo.c | 29 +++++++++++++++++++---- dp/wifi3.0/dp_internal.h | 14 ++++++----- dp/wifi3.0/dp_main.c | 4 +++- wlan_cfg/cfg_dp.h | 20 +++++++++++++++- wlan_cfg/wlan_cfg.c | 33 ++++++++++++++++++++++++++ wlan_cfg/wlan_cfg.h | 23 ++++++++++++++++++ 9 files changed, 165 insertions(+), 23 deletions(-) diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 60a17d4f62..d3f704a8a0 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -3237,4 +3237,18 @@ struct cdp_txrx_peer_params_update { uint8_t pdev_id; }; +/** + * enum cdp_umac_reset_state - umac reset in progress state + * @CDP_UMAC_RESET_NOT_IN_PROGRESS: Umac reset is not in progress + * @CDP_UMAC_RESET_IN_PROGRESS: Umac reset is in progress + * @CDP_UMAC_RESET_IN_PROGRESS_DURING_BUFFER_WINDOW: Umac reset was in progress + * during this buffer window. + * @CDP_UMAC_RESET_INVALID_STATE: Umac reset invalid state + */ +enum cdp_umac_reset_state { + CDP_UMAC_RESET_NOT_IN_PROGRESS, + CDP_UMAC_RESET_IN_PROGRESS, + CDP_UMAC_RESET_IN_PROGRESS_DURING_BUFFER_WINDOW, + CDP_UMAC_RESET_INVALID_STATE +}; #endif diff --git a/dp/inc/cdp_txrx_ctrl.h b/dp/inc/cdp_txrx_ctrl.h index 921faf3e63..c9aea879f3 100644 --- a/dp/inc/cdp_txrx_ctrl.h +++ b/dp/inc/cdp_txrx_ctrl.h @@ -1408,6 +1408,29 @@ QDF_STATUS cdp_txrx_get_pdev_phyrx_error_mask(ol_txrx_soc_handle soc, } #endif +#ifdef DP_UMAC_HW_RESET_SUPPORT +/** + * cdp_get_umac_reset_in_progress_state() - API to get the umac reset in + * progress state + * @soc: opaque soc handle + * + * Return: Umac reset in progress state + */ +static inline enum cdp_umac_reset_state +cdp_get_umac_reset_in_progress_state(ol_txrx_soc_handle soc) +{ + if (!soc || !soc->ops) { + dp_cdp_debug("Invalid soc or soc->ops:"); + return CDP_UMAC_RESET_INVALID_STATE; + } + + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->get_umac_reset_in_progress_state) + return CDP_UMAC_RESET_INVALID_STATE; + + return soc->ops->ctrl_ops->get_umac_reset_in_progress_state(soc); +} + /** * cdp_umac_reset_is_inprogress() - API to check if umac reset is in progress * @soc: opaque soc handle @@ -1417,18 +1440,23 @@ QDF_STATUS cdp_txrx_get_pdev_phyrx_error_mask(ol_txrx_soc_handle soc, static inline bool cdp_umac_reset_is_inprogress(ol_txrx_soc_handle soc) { - if (!soc || !soc->ops) { - dp_cdp_debug("Invalid Instance:"); - QDF_BUG(0); - return false; - } + enum cdp_umac_reset_state state; - if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->umac_reset_is_inprogress) - return false; + state = cdp_get_umac_reset_in_progress_state(soc); - return soc->ops->ctrl_ops->umac_reset_is_inprogress(soc); + if (state == CDP_UMAC_RESET_IN_PROGRESS || + state == CDP_UMAC_RESET_IN_PROGRESS_DURING_BUFFER_WINDOW) + return true; + else + return false; } +#else +static inline bool +cdp_umac_reset_is_inprogress(ol_txrx_soc_handle soc) +{ + return false; +} +#endif #ifdef WLAN_SUPPORT_RX_FISA static inline diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 8f4a7571a1..6a148b3c95 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -954,12 +954,15 @@ struct cdp_ctrl_ops { uint32_t *mask, uint32_t *mask_cont); #endif - bool (*umac_reset_is_inprogress)(struct cdp_soc_t *psoc); #ifdef WLAN_SUPPORT_RX_FISA QDF_STATUS (*txrx_fisa_config)(struct cdp_soc_t *soc, uint8_t pdev_id, enum cdp_fisa_config_id config_id, union cdp_fisa_config *cfg); #endif +#ifdef DP_UMAC_HW_RESET_SUPPORT + enum cdp_umac_reset_state (*get_umac_reset_in_progress_state)( + struct cdp_soc_t *psoc); +#endif }; struct cdp_me_ops { diff --git a/dp/wifi3.0/be/mlo/dp_mlo.c b/dp/wifi3.0/be/mlo/dp_mlo.c index 6d2017eae8..ffbb904df5 100644 --- a/dp/wifi3.0/be/mlo/dp_mlo.c +++ b/dp/wifi3.0/be/mlo/dp_mlo.c @@ -1659,17 +1659,19 @@ QDF_STATUS dp_mlo_umac_reset_stats_print(struct dp_soc *soc) return QDF_STATUS_SUCCESS; } -bool dp_umac_reset_is_inprogress(struct cdp_soc_t *psoc) +enum cdp_umac_reset_state +dp_get_umac_reset_in_progress_state(struct cdp_soc_t *psoc) { struct dp_soc_umac_reset_ctx *umac_reset_ctx; struct dp_soc *soc = (struct dp_soc *)psoc; struct dp_soc_mlo_umac_reset_ctx *grp_umac_reset_ctx; struct dp_soc_be *be_soc = NULL; struct dp_mlo_ctxt *mlo_ctx = NULL; + enum cdp_umac_reset_state umac_reset_is_inprogress; if (!soc) { dp_umac_reset_err("DP SOC is null"); - return false; + return CDP_UMAC_RESET_INVALID_STATE; } umac_reset_ctx = &soc->umac_reset_ctx; @@ -1680,11 +1682,28 @@ bool dp_umac_reset_is_inprogress(struct cdp_soc_t *psoc) if (mlo_ctx) { grp_umac_reset_ctx = &mlo_ctx->grp_umac_reset_ctx; - return grp_umac_reset_ctx->umac_reset_in_progress; + umac_reset_is_inprogress = + grp_umac_reset_ctx->umac_reset_in_progress; } else { - return (umac_reset_ctx->current_state != - UMAC_RESET_STATE_WAIT_FOR_TRIGGER); + umac_reset_is_inprogress = (umac_reset_ctx->current_state != + UMAC_RESET_STATE_WAIT_FOR_TRIGGER); } + + if (umac_reset_is_inprogress) + return CDP_UMAC_RESET_IN_PROGRESS; + + /* Check if the umac reset was in progress during the buffer + * window. + */ + umac_reset_is_inprogress = + ((qdf_get_log_timestamp_usecs() - + umac_reset_ctx->ts.post_reset_complete_done) <= + (wlan_cfg_get_umac_reset_buffer_window_ms(soc->wlan_cfg_ctx) * + 1000)); + + return (umac_reset_is_inprogress ? + CDP_UMAC_RESET_IN_PROGRESS_DURING_BUFFER_WINDOW : + CDP_UMAC_RESET_NOT_IN_PROGRESS); } #endif diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 9dc5d36df2..769417fdd4 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -2825,12 +2825,14 @@ QDF_STATUS dp_mlo_umac_reset_stats_print(struct dp_soc *soc) QDF_STATUS dp_umac_reset_notify_asserted_soc(struct dp_soc *soc); /** - * dp_umac_reset_is_inprogress() - Check if umac reset is in progress + * dp_get_umac_reset_in_progress_state() - API to check umac reset in progress + * state * @psoc: dp soc handle * - * Return: true if umac reset is in progress, else false. + * Return: umac reset state */ -bool dp_umac_reset_is_inprogress(struct cdp_soc_t *psoc); +enum cdp_umac_reset_state +dp_get_umac_reset_in_progress_state(struct cdp_soc_t *psoc); #else static inline QDF_STATUS dp_umac_reset_notify_asserted_soc(struct dp_soc *soc) @@ -2838,10 +2840,10 @@ QDF_STATUS dp_umac_reset_notify_asserted_soc(struct dp_soc *soc) return QDF_STATUS_SUCCESS; } -static inline -bool dp_umac_reset_is_inprogress(struct cdp_soc_t *psoc) +static inline enum cdp_umac_reset_state +dp_get_umac_reset_in_progress_state(struct cdp_soc_t *psoc) { - return false; + return CDP_UMAC_RESET_NOT_IN_PROGRESS; } #endif diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 11978a26e6..11903c004d 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -11296,7 +11296,9 @@ static struct cdp_ctrl_ops dp_ops_ctrl = { .txrx_get_pdev_phyrx_error_mask = dp_get_pdev_phyrx_error_mask, #endif .txrx_peer_flush_frags = dp_peer_flush_frags, - .umac_reset_is_inprogress = dp_umac_reset_is_inprogress, +#ifdef DP_UMAC_HW_RESET_SUPPORT + .get_umac_reset_in_progress_state = dp_get_umac_reset_in_progress_state, +#endif #ifdef WLAN_SUPPORT_RX_FISA .txrx_fisa_config = dp_fisa_config, #endif diff --git a/wlan_cfg/cfg_dp.h b/wlan_cfg/cfg_dp.h index 22fa532704..0c7b7f8d58 100644 --- a/wlan_cfg/cfg_dp.h +++ b/wlan_cfg/cfg_dp.h @@ -1936,6 +1936,23 @@ WLAN_CFG_SPECIAL_MSK, \ CFG_VALUE_OR_DEFAULT, "special frame to deliver to stack") +#ifdef DP_UMAC_HW_RESET_SUPPORT +#define CFG_DP_UMAC_RESET_BUFFER_WINDOW_MIN 100 +#define CFG_DP_UMAC_RESET_BUFFER_WINDOW_MAX 10000 +#define CFG_DP_UMAC_RESET_BUFFER_WINDOW_DEFAULT 1000 + +#define CFG_DP_UMAC_RESET_BUFFER_WINDOW \ + CFG_INI_UINT("umac_reset_buffer_window", \ + CFG_DP_UMAC_RESET_BUFFER_WINDOW_MIN, \ + CFG_DP_UMAC_RESET_BUFFER_WINDOW_MAX, \ + CFG_DP_UMAC_RESET_BUFFER_WINDOW_DEFAULT, \ + CFG_VALUE_OR_DEFAULT, \ + "Buffer time to check if umac reset was in progress during this window, configured time is in milliseconds") +#define CFG_DP_UMAC_RESET_BUFFER_WINDOW_CFG CFG(CFG_DP_UMAC_RESET_BUFFER_WINDOW) +#else +#define CFG_DP_UMAC_RESET_BUFFER_WINDOW_CFG +#endif /* DP_UMAC_HW_RESET_SUPPORT */ + #define CFG_DP \ CFG(CFG_DP_HTT_PACKET_TYPE) \ CFG(CFG_DP_INT_BATCH_THRESHOLD_OTHER) \ @@ -2066,5 +2083,6 @@ CFG(CFG_DP_POINTER_NUM_THRESHOLD_RX) \ CFG_DP_LOCAL_PKT_CAPTURE_CONFIG \ CFG(CFG_SPECIAL_FRAME_MSK) \ - CFG(CFG_DP_SW2RXDMA_LINK_RING) + CFG(CFG_DP_SW2RXDMA_LINK_RING) \ + CFG_DP_UMAC_RESET_BUFFER_WINDOW_CFG #endif /* _CFG_DP_H_ */ diff --git a/wlan_cfg/wlan_cfg.c b/wlan_cfg/wlan_cfg.c index 971bbcc20d..6e907ca761 100644 --- a/wlan_cfg/wlan_cfg.c +++ b/wlan_cfg/wlan_cfg.c @@ -3963,6 +3963,29 @@ wlan_soc_tx_packet_inspect_attach(struct cdp_ctrl_objmgr_psoc *psoc, } #endif +#ifdef DP_UMAC_HW_RESET_SUPPORT +/** + * wlan_soc_umac_reset_cfg_attach() - Update umac reset buffer window config + * @psoc: object manager psoc + * @wlan_cfg_ctx: dp soc cfg ctx + * + * Return: None + */ +static void +wlan_soc_umac_reset_cfg_attach(struct cdp_ctrl_objmgr_psoc *psoc, + struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx) +{ + wlan_cfg_ctx->umac_reset_buffer_window = + cfg_get(psoc, CFG_DP_UMAC_RESET_BUFFER_WINDOW); +} +#else +static void +wlan_soc_umac_reset_cfg_attach(struct cdp_ctrl_objmgr_psoc *psoc, + struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx) +{ +} +#endif /* DP_UMAC_HW_RESET_SUPPORT */ + #ifdef WLAN_SOFTUMAC_SUPPORT struct wlan_cfg_dp_soc_ctxt * wlan_cfg_soc_attach(struct cdp_ctrl_objmgr_psoc *psoc) @@ -4137,6 +4160,7 @@ wlan_cfg_soc_attach(struct cdp_ctrl_objmgr_psoc *psoc) cfg_get(psoc, CFG_DP_TXMON_SW_PEER_FILTERING); wlan_soc_tx_packet_inspect_attach(psoc, wlan_cfg_ctx); wlan_soc_local_pkt_capture_cfg_attach(psoc, wlan_cfg_ctx); + wlan_soc_umac_reset_cfg_attach(psoc, wlan_cfg_ctx); return wlan_cfg_ctx; } @@ -4383,6 +4407,7 @@ wlan_cfg_soc_attach(struct cdp_ctrl_objmgr_psoc *psoc) wlan_soc_local_pkt_capture_cfg_attach(psoc, wlan_cfg_ctx); wlan_cfg_ctx->special_frame_msk = cfg_get(psoc, CFG_SPECIAL_FRAME_MSK); + wlan_soc_umac_reset_cfg_attach(psoc, wlan_cfg_ctx); return wlan_cfg_ctx; } @@ -5257,6 +5282,14 @@ wlan_cfg_get_rx_rings_mapping(struct wlan_cfg_dp_soc_ctxt *cfg) return cfg->rx_rings_mapping; } +#ifdef DP_UMAC_HW_RESET_SUPPORT +uint32_t +wlan_cfg_get_umac_reset_buffer_window_ms(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->umac_reset_buffer_window; +} +#endif + bool wlan_cfg_get_dp_caps(struct wlan_cfg_dp_soc_ctxt *cfg, enum cdp_capabilities dp_caps) diff --git a/wlan_cfg/wlan_cfg.h b/wlan_cfg/wlan_cfg.h index 8631e84923..2c815dd3bf 100644 --- a/wlan_cfg/wlan_cfg.h +++ b/wlan_cfg/wlan_cfg.h @@ -343,6 +343,9 @@ struct wlan_srng_cfg { * @local_pkt_capture: flag indicating enable/disable of local packet capture * @special_frame_msk: Special frame mask * @rx_rr: rx round robin enable / disable + * @umac_reset_buffer_window: Buffer time to check if umac reset was in progress + * during this window, configured time is in + * milliseconds. */ struct wlan_cfg_dp_soc_ctxt { int num_int_ctxts; @@ -549,6 +552,9 @@ struct wlan_cfg_dp_soc_ctxt { #ifdef WLAN_SUPPORT_RX_FLOW_TAG bool rx_rr; #endif +#ifdef DP_UMAC_HW_RESET_SUPPORT + uint32_t umac_reset_buffer_window; +#endif }; /** @@ -2633,4 +2639,21 @@ bool wlan_cfg_get_local_pkt_capture(struct wlan_cfg_dp_soc_ctxt *cfg) */ uint32_t wlan_cfg_get_special_frame_cfg(struct wlan_cfg_dp_soc_ctxt *cfg); + +#ifdef DP_UMAC_HW_RESET_SUPPORT +/** + * wlan_cfg_get_umac_reset_buffer_window_ms() - Get umac reset buffer window + * @cfg: soc configuration context + * + * Return: Umac reset buffer window in milliseconds + */ +uint32_t +wlan_cfg_get_umac_reset_buffer_window_ms(struct wlan_cfg_dp_soc_ctxt *cfg); +#else +static inline uint32_t +wlan_cfg_get_umac_reset_buffer_window_ms(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return 0; +} +#endif /* DP_UMAC_HW_RESET_SUPPORT */ #endif /*__WLAN_CFG_H*/