diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h index be50315fac..159fd7fbb1 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h +++ b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h @@ -745,6 +745,19 @@ typedef QDF_STATUS (*mgmt_frame_fill_peer_cb)( struct wlan_objmgr_peer *peer, qdf_nbuf_t buf); +/** + * mgmt_frame_nbuf_op - Function pointer for any nbuf ops + * @peer: peer + * @buf: buffer + * + * This is the function pointer to be called during drain at peer + * peer deletion + * + * Return: None + */ +typedef void (*mgmt_frame_nbuf_op)(struct wlan_objmgr_peer *peer, + qdf_nbuf_t buf); + /** * struct mgmt_txrx_mgmt_frame_cb_info - frm and corresponding rx cb info * @frm_type: mgmt frm type @@ -847,6 +860,20 @@ QDF_STATUS wlan_mgmt_txrx_register_rx_cb( struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info, uint8_t num_entries); +/** + * wlan_mgmt_txrx_peer_drain() - Function to drain all mgmt packets + * specific to a peer + * @peer: peer context + * @mgmt_nbuf_op: callback func to UMAC for nbuf related operation + * + * This function drains all mgmt packets of a peer at the time of + * peer deletion. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS wlan_mgmt_txrx_peer_drain(struct wlan_objmgr_peer *peer, + mgmt_frame_nbuf_op mgmt_nbuf_op); + /** * wlan_mgmt_txrx_vdev_drain() - Function to drain all mgmt packets * specific to a vdev diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c index 4dc065d25b..8850f65806 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c @@ -770,6 +770,58 @@ QDF_STATUS wlan_mgmt_txrx_pdev_close(struct wlan_objmgr_pdev *pdev) return QDF_STATUS_SUCCESS; } +QDF_STATUS wlan_mgmt_txrx_peer_drain(struct wlan_objmgr_peer *peer, + mgmt_frame_nbuf_op mgmt_nbuf_op) +{ + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_vdev *vdev; + struct mgmt_txrx_priv_pdev_context *mgmt_txrx_ctx; + struct mgmt_txrx_desc_elem_t *mgmt_desc; + struct wlan_objmgr_peer *des_peer; + uint32_t pool_size; + int i; + + vdev = wlan_peer_get_vdev(peer); + if (!vdev) { + mgmt_txrx_err("vdev context is NULL"); + return QDF_STATUS_E_INVAL; + } + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + mgmt_txrx_err("pdev context is NULL"); + return QDF_STATUS_E_INVAL; + } + + mgmt_txrx_ctx = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_MGMT_TXRX); + if (!mgmt_txrx_ctx) { + mgmt_txrx_err("mgmt txrx context is NULL"); + return QDF_STATUS_E_FAILURE; + } + + pool_size = mgmt_txrx_ctx->mgmt_desc_pool.free_list.max_size; + if (!pool_size) { + mgmt_txrx_err("pool size is 0"); + return QDF_STATUS_E_FAILURE; + } + + for (i = 0; i < pool_size; i++) { + if (mgmt_txrx_ctx->mgmt_desc_pool.pool[i].in_use) { + mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[i]; + des_peer = mgmt_txrx_get_peer(pdev, mgmt_desc->desc_id); + if (peer == des_peer) { + if (mgmt_nbuf_op) + mgmt_nbuf_op(peer, mgmt_desc->nbuf); + mgmt_txrx_tx_completion_handler(pdev, + mgmt_desc->desc_id, 0, 0); + } + } + } + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS wlan_mgmt_txrx_vdev_drain(struct wlan_objmgr_vdev *vdev, mgmt_frame_fill_peer_cb mgmt_fill_peer_cb, void *status)