Browse Source

qcacmn: Add mgmt_txrx api to drain packets specific to peer

At peer deletion corresponding mgmt packets needs to be cleaned up.
So add mgmt_txrx api to drain all the mgmt packets specific to a peer.

Change-Id: I6a7f5efa665a1da009e594248e88002df35ae9ff
CRs-Fixed: 2299964
Sravan Kumar Kairam 6 years ago
parent
commit
b7b7b36900

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

+ 52 - 0
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)