Browse Source

qcacmn: Adding support to drain mgmt frames

FW recovery path needs this function as mgmt Tx
completions are not expected from the FW.

CRs-Fixed: 2178618
Change-Id: I7dddbff544dcce4dd9fe95ab79fb891bbd11b4ab
Vinay Adella 7 years ago
parent
commit
1de7baec7e

+ 29 - 0
umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h

@@ -689,6 +689,19 @@ typedef QDF_STATUS (*mgmt_frame_rx_callback)(
 			struct mgmt_rx_event_params *mgmt_rx_params,
 			enum mgmt_frame_type frm_type);
 
+/**
+ * mgmt_frame_fill_peer_cb - Function pointer to fill peer in the buf
+ * @peer: peer
+ * @buf: buffer
+ *
+ * This is the function pointer to be called during drain to fill the
+ * peer into the buf's cb structure.
+ *
+ * Return: QDF_STATUS_SUCCESS - in case of success
+ */
+typedef QDF_STATUS (*mgmt_frame_fill_peer_cb)(
+			struct wlan_objmgr_peer *peer,
+			qdf_nbuf_t buf);
 
 /**
  * struct mgmt_txrx_mgmt_frame_cb_info - frm and corresponding rx cb info
@@ -792,6 +805,22 @@ 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_pdev_drain() - Function to drain all mgmt packets
+ * @pdev: pdev context
+ * @mgmt_fill_peer_cb: callback func to UMAC to fill peer into buf
+ * @status: opaque pointer about the status of the pkts passed to UMAC
+ *
+ * This function drains all mgmt packets. This can be used in the
+ * event of target going down without sending completions.
+ *
+ * Return: QDF_STATUS_SUCCESS - in case of success
+ */
+QDF_STATUS wlan_mgmt_txrx_pdev_drain(
+			struct wlan_objmgr_pdev *pdev,
+			mgmt_frame_fill_peer_cb mgmt_fill_peer_cb,
+			void *status);
+
 /**
  * wlan_mgmt_txrx_deregister_rx_cb() - deregisters the rx cb for mgmt. frames
  * @psoc: psoc context

+ 44 - 0
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c

@@ -30,6 +30,7 @@
 #include "wlan_objmgr_vdev_obj.h"
 #include "wlan_objmgr_peer_obj.h"
 #include "qdf_nbuf.h"
+#include "wlan_lmac_if_api.h"
 
 /**
  * wlan_mgmt_txrx_psoc_obj_create_notification() - called from objmgr when psoc
@@ -768,3 +769,46 @@ QDF_STATUS wlan_mgmt_txrx_psoc_close(struct wlan_objmgr_psoc *psoc)
 	}
 	return QDF_STATUS_SUCCESS;
 }
+
+QDF_STATUS wlan_mgmt_txrx_pdev_drain(struct wlan_objmgr_pdev *pdev,
+				mgmt_frame_fill_peer_cb mgmt_fill_peer_cb,
+				void *status)
+{
+	struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
+	struct mgmt_txrx_desc_elem_t *mgmt_desc;
+	struct wlan_objmgr_peer *peer;
+	uint32_t pool_size;
+	int i;
+
+	if (!pdev) {
+		mgmt_txrx_err("pdev context is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+	mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
+		wlan_objmgr_pdev_get_comp_private_obj(pdev,
+			WLAN_UMAC_COMP_MGMT_TXRX);
+	if (!mgmt_txrx_pdev_ctx) {
+		mgmt_txrx_err("mgmt txrx context is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	pool_size = mgmt_txrx_pdev_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_pdev_ctx->mgmt_desc_pool.pool[i].in_use) {
+			mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i];
+			peer = mgmt_txrx_get_peer(pdev, mgmt_desc->desc_id);
+			QDF_ASSERT(peer != NULL);
+			if (mgmt_fill_peer_cb)
+				mgmt_fill_peer_cb(peer, mgmt_desc->nbuf);
+			mgmt_txrx_tx_completion_handler(pdev,
+				mgmt_desc->desc_id, 0, status);
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}