qcacmn: Add support for TX path for mgmt_txrx

Add support for Tx path and TX completion path
for mgmt_txrx for the converged umac.

Change-Id: I964ee78ae4f6ff1fc5f26a6f7d16ae6b4e50bbee
CRS Fixed: 1103247
This commit is contained in:
Himanshu Agarwal 2016-12-20 20:05:14 +05:30 • committed by qcabuildsw
commit f0d971512c
5 changed files with 219 additions and 6 deletions

View file

@ -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;
}

View file

@ -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,

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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