diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 80aa34edea91e..c92880061b888 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -83,7 +83,10 @@ #include #include "wlan_roam_debug.h" #include "cfg_ucfg_api.h" - +#ifdef DP_SUPPORT_RECOVERY_NOTIFY +#include +#include +#endif #define DPT_DEBUGFS_PERMS (QDF_FILE_USR_READ | \ QDF_FILE_USR_WRITE | \ @@ -3322,6 +3325,63 @@ ol_txrx_clear_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, return status; } +#ifdef DP_SUPPORT_RECOVERY_NOTIFY +static +int ol_peer_recovery_notifier_cb(struct notifier_block *block, + unsigned long state, void *data) +{ + struct qdf_notifer_data *notif_data = data; + qdf_notif_block *notif_block; + struct ol_txrx_peer_t *peer; + struct peer_hang_data hang_data; + enum peer_debug_id_type dbg_id; + + if (!data || !block) + return -EINVAL; + + notif_block = qdf_container_of(block, qdf_notif_block, notif_block); + + peer = notif_block->priv_data; + if (!peer) + return -EINVAL; + + QDF_HANG_EVT_SET_HDR(&hang_data.tlv_header, + HANG_EVT_TAG_DP_PEER_INFO, + QDF_HANG_GET_STRUCT_TLVLEN(struct peer_hang_data)); + + qdf_mem_copy(&hang_data.peer_mac_addr, &peer->mac_addr.raw, + QDF_MAC_ADDR_SIZE); + + for (dbg_id = 0; dbg_id < PEER_DEBUG_ID_MAX; dbg_id++) + if (qdf_atomic_read(&peer->access_list[dbg_id])) + hang_data.peer_timeout_bitmask |= (1 << dbg_id); + + qdf_mem_copy(notif_data->hang_data + notif_data->offset, + &hang_data, sizeof(struct peer_hang_data)); + notif_data->offset += sizeof(struct peer_hang_data); + + return 0; +} + +static qdf_notif_block ol_peer_recovery_notifier = { + .notif_block.notifier_call = ol_peer_recovery_notifier_cb, +}; + +static +QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer) +{ + ol_peer_recovery_notifier.priv_data = peer; + + return qdf_hang_event_register_notifier(&ol_peer_recovery_notifier); +} +#else +static inline +QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * peer_unmap_timer_handler() - peer unmap timer function * @data: peer object pointer @@ -3340,6 +3400,7 @@ void peer_unmap_timer_handler(void *data) ol_txrx_err("peer %pK ("QDF_MAC_ADDR_STR")", peer, QDF_MAC_ADDR_ARRAY(peer->mac_addr.raw)); + ol_register_peer_recovery_notifier(peer); cds_trigger_recovery(QDF_PEER_UNMAP_TIMEDOUT); } @@ -5928,6 +5989,52 @@ void ol_deregister_packetdump_callback(struct cdp_soc_t *soc_hdl, pdev->ol_rx_packetdump_cb = NULL; } +#ifdef DP_SUPPORT_RECOVERY_NOTIFY +static +int ol_recovery_notifier_cb(struct notifier_block *block, + unsigned long state, void *data) +{ + struct qdf_notifer_data *notif_data = data; + qdf_notif_block *notif_block; + struct ol_txrx_soc_t *soc; + struct hif_opaque_softc *hif_handle; + + if (!data || !block) + return -EINVAL; + + notif_block = qdf_container_of(block, qdf_notif_block, notif_block); + + soc = notif_block->priv_data; + if (!soc) + return -EINVAL; + + hif_handle = cds_get_context(QDF_MODULE_ID_HIF); + hif_log_ce_info(hif_handle, notif_data->hang_data, + ¬if_data->offset); + + return 0; +} + +static qdf_notif_block ol_recovery_notifier = { + .notif_block.notifier_call = ol_recovery_notifier_cb, +}; + +static +QDF_STATUS ol_register_recovery_notifier(struct cdp_soc_t *soc_hdl) +{ + struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl); + + ol_recovery_notifier.priv_data = soc; + return qdf_hang_event_register_notifier(&ol_recovery_notifier); +} + +static +QDF_STATUS ol_unregister_recovery_notifier(void) +{ + return qdf_hang_event_unregister_notifier(&ol_recovery_notifier); +} +#endif + static struct cdp_cmn_ops ol_ops_cmn = { .txrx_soc_attach_target = ol_txrx_soc_attach_target, .txrx_vdev_attach = ol_txrx_vdev_attach, @@ -5996,6 +6103,10 @@ static struct cdp_misc_ops ol_ops_misc = { .vdev_set_bundle_require_flag = ol_tx_vdev_set_bundle_require, .pdev_reset_bundle_require_flag = ol_tx_pdev_reset_bundle_require, #endif +#ifdef DP_SUPPORT_RECOVERY_NOTIFY + .register_recovery_notifier = ol_register_recovery_notifier, + .unregister_recovery_notifier = ol_unregister_recovery_notifier, +#endif }; static struct cdp_flowctl_ops ol_ops_flowctl = { diff --git a/core/dp/txrx/ol_txrx.h b/core/dp/txrx/ol_txrx.h index 695b0c242c4bf..07e31277dc2bb 100644 --- a/core/dp/txrx/ol_txrx.h +++ b/core/dp/txrx/ol_txrx.h @@ -117,6 +117,12 @@ ol_tx_desc_pool_size_hl(struct cdp_cfg *ctrl_pdev); #define TXRX_HL_TX_DESC_QUEUE_RESTART_TH \ (TXRX_HL_TX_DESC_HI_PRIO_RESERVED + 100) +struct peer_hang_data { + uint32_t tlv_header; + uint8_t peer_mac_addr[QDF_MAC_ADDR_SIZE]; + uint16_t peer_timeout_bitmask; +} qdf_packed; + #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) void