diff --git a/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c b/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c index 5d7dc27b2eeb..e2bab0ce60e9 100644 --- a/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c +++ b/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c @@ -110,7 +110,8 @@ struct mgmt_txrx_desc_elem_t *wlan_mgmt_txrx_desc_get( != QDF_STATUS_SUCCESS) { qdf_spin_unlock_bh( &mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock); - mgmt_txrx_err("mgmt descriptor freelist is empty"); + mgmt_txrx_err("Descriptor freelist empty for mgmt_txrx_ctx %p", + mgmt_txrx_ctx); return NULL; } @@ -119,8 +120,8 @@ struct mgmt_txrx_desc_elem_t *wlan_mgmt_txrx_desc_get( if (status != QDF_STATUS_SUCCESS) { qdf_spin_unlock_bh( &mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock); - mgmt_txrx_err("Failed to get mgmt descriptor from freelist with status %d", - status); + mgmt_txrx_err("Failed to get descriptor from list: status %d", + status); qdf_assert_always(0); return NULL; } diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_tgt_api.h b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_tgt_api.h index 852b967bf712..2bdd4c9237f2 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_tgt_api.h +++ b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_tgt_api.h @@ -54,7 +54,8 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( * @tx_compl_params: tx completion params * * This function handles tx completions of mgmt. frames and is registered to - * LMAC_if layer through lmac_if cbs. + * LMAC_if layer through lmac_if cbs.The cb needs to free the nbuf. In case no + * callback is registered, this function will free the nbuf. * * Return: QDF_STATUS_SUCCESS - in case of success */ @@ -100,7 +101,7 @@ tgt_mgmt_txrx_get_peer_from_desc_id( * This function extracts vdev id from mgmt desc extracted from desc id. * * Return: vdev_id - in case of success - * 0 - in case of failure + * WLAN_UMAC_VDEV_ID_MAX - in case of failure */ uint8_t tgt_mgmt_txrx_get_vdev_id_from_desc_id( struct wlan_objmgr_psoc *psoc, diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c index 692a3c0950fc..f60086530912 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c @@ -884,6 +884,64 @@ QDF_STATUS tgt_mgmt_txrx_tx_completion_handler( uint32_t desc_id, uint32_t status, void *tx_compl_params) { + struct mgmt_txrx_priv_context *mgmt_txrx_ctx; + struct mgmt_txrx_desc_elem_t *mgmt_desc; + void *cb_context; + mgmt_tx_download_comp_cb tx_compl_cb; + mgmt_ota_comp_cb ota_comp_cb; + qdf_nbuf_t nbuf; + + mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *) + wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_MGMT_TXRX); + if (!mgmt_txrx_ctx) { + mgmt_txrx_err("Mgmt txrx context empty for psoc %p", psoc); + return QDF_STATUS_E_NULL_VALUE; + } + mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id]; + if (!mgmt_desc) { + mgmt_txrx_err("Mgmt desc empty for id %d psoc %p ", + desc_id, psoc); + return QDF_STATUS_E_NULL_VALUE; + } + tx_compl_cb = mgmt_desc->tx_dwnld_cmpl_cb; + ota_comp_cb = mgmt_desc->tx_ota_cmpl_cb; + nbuf = mgmt_desc->nbuf; + + /* + * TO DO + * Make the API more generic to handle tx download completion as well + * as OTA completion separately. + */ + + /* + * 1. If the tx frame is sent by any UMAC converged component then it + * passes the context as NULL while calling mgmt txrx API for + * sending mgmt frame. If context is NULL, peer will be passed as + * cb_context in completion callbacks. + * 2. If the tx frame is sent by legacy MLME then it passes the context + * as its specific context (for ex- mac context in case of MCL) while + * calling mgmt txrx API for sending mgmt frame. This caller specific + * context is passed as cb_context in completion callbacks. + */ + if (mgmt_desc->context) + cb_context = mgmt_desc->context; + else + cb_context = (void *)mgmt_desc->peer; + + if (!tx_compl_cb && !ota_comp_cb) { + qdf_nbuf_free(nbuf); + goto no_registered_cb; + } + + if (tx_compl_cb) + tx_compl_cb(cb_context, nbuf, status); + + if (ota_comp_cb) + ota_comp_cb(cb_context, nbuf, status, tx_compl_params); + +no_registered_cb: + wlan_mgmt_txrx_desc_put(mgmt_txrx_ctx, desc_id); return QDF_STATUS_SUCCESS; } @@ -891,6 +949,27 @@ qdf_nbuf_t tgt_mgmt_txrx_get_nbuf_from_desc_id( struct wlan_objmgr_psoc *psoc, uint32_t desc_id) { + struct mgmt_txrx_priv_context *mgmt_txrx_ctx; + struct mgmt_txrx_desc_elem_t *mgmt_desc; + qdf_nbuf_t buf; + + mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *) + wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_MGMT_TXRX); + if (!mgmt_txrx_ctx) { + mgmt_txrx_err("Mgmt txrx context empty for psoc %p", psoc); + goto fail; + } + mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id]; + if (!mgmt_desc) { + mgmt_txrx_err("Mgmt descriptor unavailable for id %d psoc %p", + desc_id, psoc); + goto fail; + } + buf = mgmt_desc->nbuf; + return buf; + +fail: return NULL; } @@ -899,6 +978,29 @@ tgt_mgmt_txrx_get_peer_from_desc_id( struct wlan_objmgr_psoc *psoc, uint32_t desc_id) { + struct mgmt_txrx_priv_context *mgmt_txrx_ctx; + struct mgmt_txrx_desc_elem_t *mgmt_desc; + struct wlan_objmgr_peer *peer; + + mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *) + wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_MGMT_TXRX); + if (!mgmt_txrx_ctx) { + mgmt_txrx_err("Mgmt txrx context empty for psoc %p", psoc); + goto fail; + } + + mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id]; + if (!mgmt_desc) { + mgmt_txrx_err("Mgmt descriptor unavailable for id %d psoc %p", + desc_id, psoc); + goto fail; + } + + peer = mgmt_desc->peer; + return peer; + +fail: return NULL; } @@ -906,5 +1008,28 @@ uint8_t tgt_mgmt_txrx_get_vdev_id_from_desc_id( struct wlan_objmgr_psoc *psoc, uint32_t desc_id) { - return 0; + struct mgmt_txrx_priv_context *mgmt_txrx_ctx; + struct mgmt_txrx_desc_elem_t *mgmt_desc; + uint8_t vdev_id; + + mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *) + wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_MGMT_TXRX); + if (!mgmt_txrx_ctx) { + mgmt_txrx_err("Mgmt txrx context empty for psoc %p", psoc); + goto fail; + } + + mgmt_desc = &mgmt_txrx_ctx->mgmt_desc_pool.pool[desc_id]; + if (!mgmt_desc) { + mgmt_txrx_err("Mgmt descriptor unavailable for id %d psoc %p", + desc_id, psoc); + goto fail; + } + + vdev_id = mgmt_desc->vdev_id; + return vdev_id; + +fail: + return WLAN_UMAC_VDEV_ID_MAX; } 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 563b6871b7bc..3533e2d65225 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 @@ -26,6 +26,9 @@ #include "wlan_mgmt_txrx_main_i.h" #include "wlan_objmgr_psoc_obj.h" #include "wlan_objmgr_global_obj.h" +#include "wlan_objmgr_pdev_obj.h" +#include "wlan_objmgr_vdev_obj.h" +#include "wlan_objmgr_peer_obj.h" #include "qdf_nbuf.h" /** @@ -210,6 +213,60 @@ QDF_STATUS wlan_mgmt_txrx_mgmt_frame_tx(struct wlan_objmgr_peer *peer, enum wlan_umac_comp_id comp_id, void *mgmt_tx_params) { + struct mgmt_txrx_desc_elem_t *desc; + struct wlan_objmgr_psoc *psoc; + struct mgmt_txrx_priv_context *txrx_ctx; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev_objmgr *vdev_obj; + + vdev = wlan_peer_get_vdev(peer); + if (!vdev) { + mgmt_txrx_err("vdev unavailable for peer %p psoc %p", + peer, psoc); + return QDF_STATUS_E_NULL_VALUE; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + mgmt_txrx_err("psoc unavailable for peer %p vdev %p", + peer, vdev); + return QDF_STATUS_E_NULL_VALUE; + } + + txrx_ctx = (struct mgmt_txrx_priv_context *) + wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_MGMT_TXRX); + if (!txrx_ctx) { + mgmt_txrx_err("No txrx context for peer %p psoc %p", + peer, psoc); + return QDF_STATUS_E_NULL_VALUE; + } + + desc = wlan_mgmt_txrx_desc_get(txrx_ctx); + if (!desc) + return QDF_STATUS_E_RESOURCES; + + desc->nbuf = buf; + desc->tx_ota_cmpl_cb = tx_ota_comp_cb; + desc->tx_dwnld_cmpl_cb = tx_comp_cb; + desc->peer = peer; + desc->vdev_id = vdev_obj->vdev_id; + desc->context = context; + + if (!psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.mgmt_tx_send) { + mgmt_txrx_err("mgmt txrx tx op to send mgmt frame is NULL for psoc: %p", + psoc); + wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id); + return QDF_STATUS_E_FAILURE; + } + + if (psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.mgmt_tx_send( + vdev, buf, desc->desc_id, mgmt_tx_params)) { + mgmt_txrx_err("Mgmt send fail for peer %p psoc %p", + peer, psoc); + wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id); + return QDF_STATUS_E_FAILURE; + } return QDF_STATUS_SUCCESS; } @@ -217,6 +274,32 @@ QDF_STATUS wlan_mgmt_txrx_beacon_frame_tx(struct wlan_objmgr_peer *peer, qdf_nbuf_t buf, enum wlan_umac_comp_id comp_id) { + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_psoc *psoc; + + vdev = wlan_peer_get_vdev(peer); + if (!vdev) { + mgmt_txrx_err("vdev unavailable for peer %p", peer); + return QDF_STATUS_E_NULL_VALUE; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + mgmt_txrx_err("psoc unavailable for peer %p", peer); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.beacon_send) { + mgmt_txrx_err("mgmt txrx tx op to send beacon frame is NULL for psoc: %p", + psoc); + return QDF_STATUS_E_FAILURE; + } + + if (psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.beacon_send(vdev, buf)) { + mgmt_txrx_err("Beacon send fail for peer %p psoc %p", + peer, psoc); + return QDF_STATUS_E_FAILURE; + } return QDF_STATUS_SUCCESS; } diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h index 9b8f6c477be8..84131325df88 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h @@ -48,6 +48,9 @@ /* Max no. of peers for STA vap */ #define WLAN_UMAC_MAX_STA_PEERS 2 +/* Max vdev_id */ +#define WLAN_UMAC_VDEV_ID_MAX 0xFF + /* 802.11 cap info */ #define WLAN_CAPINFO_ESS 0x0001 #define WLAN_CAPINFO_IBSS 0x0002