Browse Source

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
Himanshu Agarwal 8 years ago
parent
commit
f0d971512c

+ 4 - 3
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;
 	}

+ 3 - 2
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,

+ 126 - 1
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;
 }

+ 83 - 0
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;
 }
 

+ 3 - 0
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