Bladeren bron

qcacmn: Tx packet capture

Add support to send MSDU, mgmt. and ctrl payload along with metadata
to upper layer callback

FR 42132

Change-Id: Ie751322c7c15419ea908538e9e8687b64693fcfa
CRs-Fixed:2068486
Soumya Bhat 7 jaren geleden
bovenliggende
commit
cfbb8952ff
7 gewijzigde bestanden met toevoegingen van 173 en 1 verwijderingen
  1. 9 0
      dp/inc/cdp_txrx_cmn_struct.h
  2. 10 0
      dp/inc/cdp_txrx_ctrl.h
  3. 3 0
      dp/inc/cdp_txrx_ops.h
  4. 43 1
      dp/wifi3.0/dp_htt.c
  5. 49 0
      dp/wifi3.0/dp_main.c
  6. 57 0
      dp/wifi3.0/dp_tx.c
  7. 2 0
      dp/wifi3.0/dp_types.h

+ 9 - 0
dp/inc/cdp_txrx_cmn_struct.h

@@ -531,6 +531,15 @@ struct cdp_soc_t {
 	struct ol_if_ops *ol_ops;
 };
 
+/*
+ * cdp_pdev_param_type: different types of parameters
+ *			to set values in pdev
+ * @CDP_ENABLE_TX_CAPTURE: Enable Tx capture feature
+ */
+enum cdp_pdev_param_type {
+	CDP_CONFIG_TX_CAPTURE,
+};
+
 /*
  * cdp_vdev_param_type: different types of parameters
  *			to set values in vdev

+ 10 - 0
dp/inc/cdp_txrx_ctrl.h

@@ -389,6 +389,16 @@ cdp_peer_set_nawds(ol_txrx_soc_handle soc,
 	return;
 }
 
+static inline void cdp_txrx_set_pdev_param(ol_txrx_soc_handle soc,
+		struct cdp_pdev *pdev, enum cdp_pdev_param_type type,
+		uint8_t val)
+{
+	if (soc->ops->ctrl_ops->txrx_set_pdev_param)
+		return soc->ops->ctrl_ops->txrx_set_pdev_param
+			(pdev, type, val);
+
+}
+
 /**
  * @brief Subscribe to a specified WDI event.
  * @details

+ 3 - 0
dp/inc/cdp_txrx_ops.h

@@ -415,6 +415,9 @@ struct cdp_ctrl_ops {
 
 	void (*txrx_update_mgmt_txpow_vdev)(struct cdp_vdev *vdev,
 			uint8_t subtype, uint8_t tx_power);
+
+	void (*txrx_set_pdev_param)(struct cdp_pdev *pdev,
+			enum cdp_pdev_param_type type, uint8_t val);
 };
 
 struct cdp_me_ops {

+ 43 - 1
dp/wifi3.0/dp_htt.c

@@ -44,6 +44,8 @@ do {                                                             \
 		htt_htc_misc_pkt_list_add(soc, pkt);             \
 } while (0)
 
+#define HTT_MGMT_CTRL_TLV_RESERVERD_LEN 12
+
 /*
  * dp_tx_stats_update() - Update per-peer statistics
  * @soc: Datapath soc handle
@@ -1789,6 +1791,42 @@ static void dp_process_ppdu_stats_user_common_array_tlv(struct dp_pdev *pdev,
 		HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_DUR_GET(*tag_buf);
 }
 
+/*
+ * dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv: Process
+ * htt_ppdu_stats_tx_mgmtctrl_payload_tlv
+ * @pdev: DP PDEV handle
+ * @tag_buf: buffer containing the htt_ppdu_stats_tx_mgmtctrl_payload_tlv
+ * @length: tlv_length
+ *
+ * return:void
+ */
+static void dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(
+	struct dp_pdev *pdev, uint32_t *tag_buf, uint32_t length)
+{
+	htt_ppdu_stats_tx_mgmtctrl_payload_tlv *dp_stats_buf =
+		(htt_ppdu_stats_tx_mgmtctrl_payload_tlv *)tag_buf;
+
+	qdf_nbuf_t nbuf = NULL;
+
+	uint32_t payload_size = length - HTT_MGMT_CTRL_TLV_RESERVERD_LEN;
+
+	nbuf = qdf_nbuf_alloc(pdev->soc->osdev, payload_size, 0, 4, true);
+
+	if (!nbuf) {
+		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+				"Nbuf Allocation failed for Mgmt. payload");
+		qdf_assert(0);
+		return;
+	}
+
+	qdf_nbuf_put_tail(nbuf, payload_size);
+	qdf_mem_copy(qdf_nbuf_data(nbuf), dp_stats_buf->payload, payload_size);
+
+	dp_wdi_event_handler(WDI_EVENT_TX_MGMT_CTRL, pdev->soc,
+		nbuf, HTT_INVALID_PEER,
+		WDI_NO_VAL, pdev->pdev_id);
+}
+
 /**
  * dp_process_ppdu_tag(): Function to process the PPDU TLVs
  * @soc: DP Physical device (radio) handle
@@ -1838,6 +1876,10 @@ static void dp_process_ppdu_tag(struct dp_pdev *pdev, uint32_t *tag_buf,
 		dp_process_ppdu_stats_user_common_array_tlv(pdev,
 							tag_buf);
 		break;
+	case HTT_PPDU_STATS_TX_MGMTCTRL_PAYLOAD_TLV:
+		dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(pdev,
+							tag_buf, tlv_len);
+		break;
 	default:
 		break;
 	}
@@ -1908,7 +1950,7 @@ static void dp_txrx_ppdu_stats_handler(struct dp_soc *soc,
 	int status;
 	int i;
 
-	if (!pdev->enhanced_stats_en)
+	if (!pdev->enhanced_stats_en && !pdev->tx_sniffer_enable)
 		return;
 
 	if (!pdev->tx_ppdu_info.buf) {

+ 49 - 0
dp/wifi3.0/dp_main.c

@@ -4795,6 +4795,30 @@ dp_ppdu_ring_cfg(struct dp_pdev *pdev)
 		RX_BUFFER_SIZE, &htt_tlv_filter);
 }
 
+/*
+ * dp_config_tx_capture()- API to enable/disable tx capture
+ * @pdev_handle: DP_PDEV handle
+ * @val: user provided value
+ *
+ * Return: void
+ */
+static void
+dp_config_tx_capture(struct cdp_pdev *pdev_handle, int val)
+{
+	struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
+
+	if (val) {
+		pdev->tx_sniffer_enable = 1;
+		dp_h2t_cfg_stats_msg_send(pdev, 0xffff);
+	} else {
+		pdev->tx_sniffer_enable = 0;
+
+		if (!pdev->enhanced_stats_en)
+			dp_h2t_cfg_stats_msg_send(pdev, 0);
+	}
+
+}
+
 /*
  * dp_enable_enhanced_stats()- API to enable enhanced statistcs
  * @pdev_handle: DP_PDEV handle
@@ -4821,7 +4845,11 @@ static void
 dp_disable_enhanced_stats(struct cdp_pdev *pdev_handle)
 {
 	struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
+
 	pdev->enhanced_stats_en = 0;
+
+	if (!pdev->tx_sniffer_enable)
+		dp_h2t_cfg_stats_msg_send(pdev, 0);
 }
 
 /*
@@ -4866,6 +4894,26 @@ dp_get_fw_peer_stats(struct cdp_pdev *pdev_handle, uint8_t *mac_addr,
 
 }
 
+/*
+ * dp_set_pdev_param: function to set parameters in pdev
+ * @pdev_handle: DP pdev handle
+ * @param: parameter type to be set
+ * @val: value of parameter to be set
+ *
+ * return: void
+ */
+static void dp_set_pdev_param(struct cdp_pdev *pdev_handle,
+		enum cdp_pdev_param_type param, uint8_t val)
+{
+	switch (param) {
+	case CDP_CONFIG_TX_CAPTURE:
+		dp_config_tx_capture(pdev_handle, val);
+		break;
+	default:
+		break;
+	}
+}
+
 /*
  * dp_set_vdev_param: function to set parameters in vdev
  * @param: parameter type to be set
@@ -5374,6 +5422,7 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
 	/* TODO: Add other functions */
 	.txrx_wdi_event_sub = dp_wdi_event_sub,
 	.txrx_wdi_event_unsub = dp_wdi_event_unsub,
+	.txrx_set_pdev_param = dp_set_pdev_param,
 };
 
 static struct cdp_me_ops dp_ops_me = {

+ 57 - 0
dp/wifi3.0/dp_tx.c

@@ -1731,6 +1731,56 @@ static void dp_tx_inspect_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
 	dp_tx_desc_release(tx_desc, tx_desc->pool_id);
 }
 
+#ifdef FEATURE_PERPKT_INFO
+static QDF_STATUS
+dp_send_compl_to_stack(struct dp_soc *soc,  struct dp_tx_desc_s *desc,
+				uint16_t peer_id, uint16_t ppdu_id)
+{
+	struct tx_capture_hdr *ppdu_hdr;
+	struct ethhdr *eh;
+	struct dp_peer *peer = NULL;
+	qdf_nbuf_t netbuf = desc->nbuf;
+
+	if (!desc->pdev->tx_sniffer_enable)
+		return QDF_STATUS_E_NOSUPPORT;
+
+	eh = (struct ethhdr *)(netbuf->data);
+	peer = (peer_id == HTT_INVALID_PEER) ? NULL :
+			dp_peer_find_by_id(soc, peer_id);
+
+	if (!peer) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+				FL("Peer Invalid"));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (!qdf_nbuf_push_head(netbuf, sizeof(struct tx_capture_hdr))) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+				FL("No headroom"));
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	ppdu_hdr = (struct tx_capture_hdr *)qdf_nbuf_data(netbuf);
+	qdf_mem_copy(ppdu_hdr->ta, (eh->h_dest), IEEE80211_ADDR_LEN);
+	ppdu_hdr->ppdu_id = ppdu_id;
+	qdf_mem_copy(ppdu_hdr->ra, peer->mac_addr.raw,
+			IEEE80211_ADDR_LEN);
+
+	dp_wdi_event_handler(WDI_EVENT_TX_DATA, soc,
+			netbuf, peer_id,
+			WDI_NO_VAL, desc->pdev->pdev_id);
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static QDF_STATUS
+dp_send_compl_to_stack(struct dp_soc *soc,  struct dp_tx_desc_s *desc,
+				uint16_t peer_id, uint16_t ppdu_id)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+#endif
+
 /**
  * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor
  * @soc: Soc handle
@@ -1743,6 +1793,10 @@ static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
 {
 	struct dp_vdev *vdev = desc->vdev;
 	qdf_nbuf_t nbuf = desc->nbuf;
+	struct hal_tx_completion_status ts = {0};
+
+	if (desc)
+		hal_tx_comp_get_status(&desc->comp, &ts);
 
 	/* If it is TDLS mgmt, don't unmap or free the frame */
 	if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME)
@@ -1769,6 +1823,9 @@ static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
 
 	qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE);
 
+	if (dp_send_compl_to_stack(soc, desc, ts.peer_id, ts.ppdu_id))
+		return;
+
 	if (!vdev->mesh_vdev) {
 		qdf_nbuf_free(nbuf);
 	} else {

+ 2 - 0
dp/wifi3.0/dp_types.h

@@ -1046,6 +1046,8 @@ struct dp_pdev {
 		uint8_t last_user;
 		qdf_nbuf_t buf;
 	} tx_ppdu_info;
+
+	bool tx_sniffer_enable;
 };
 
 struct dp_peer;