Prechádzať zdrojové kódy

qcacmn: Add support for Mesh Tx path

Added mesh specific data path changes. Extract mesh meta header in the
packet and pass it to firmware. Fill tx completion stats and call upper layer
call back function incase external tx completion is registered.

Change-Id: Ic3c1c37b2f59b1a35e3cf00a4498342dc20427d2
CRs-Fixed: 2003389
Venkateswara Swamy Bandaru 8 rokov pred
rodič
commit
3f62370e23
3 zmenil súbory, kde vykonal 169 pridanie a 87 odobranie
  1. 14 0
      dp/wifi3.0/dp_main.c
  2. 144 60
      dp/wifi3.0/dp_tx.c
  3. 11 27
      dp/wifi3.0/dp_tx.h

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

@@ -1830,6 +1830,17 @@ static struct cdp_cfg *dp_get_ctrl_pdev_from_vdev_wifi3(struct cdp_vdev *pvdev)
 	return (struct cdp_cfg *)pdev->wlan_cfg_ctx;
 }
 
+#ifdef MESH_MODE_SUPPORT
+void dp_peer_set_mesh_mode(struct cdp_vdev *vdev_hdl, u_int32_t val)
+{
+	struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl;
+
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+		FL("%s: val %d"), __func__, val);
+	vdev->mesh_vdev = val;
+}
+#endif
+
 static struct cdp_cmn_ops dp_ops_cmn = {
 	.txrx_soc_attach_target = dp_soc_attach_target_wifi3,
 	.txrx_vdev_attach = dp_vdev_attach_wifi3,
@@ -1855,6 +1866,9 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
 	.txrx_peer_authorize = dp_peer_authorize,
 	.txrx_set_vdev_rx_decap_type = dp_set_vdev_rx_decap_type,
 	.txrx_set_tx_encap_type = dp_set_vdev_tx_encap_type,
+#ifdef MESH_MODE_SUPPORT
+	.txrx_set_mesh_mode  = dp_peer_set_mesh_mode,
+#endif
 	/* TODO: Add other functions */
 };
 

+ 144 - 60
dp/wifi3.0/dp_tx.c

@@ -24,6 +24,9 @@
 #include "qdf_mem.h"
 #include "qdf_nbuf.h"
 #include <wlan_cfg.h>
+#ifdef MESH_MODE_SUPPORT
+#include "if_meta_hdr.h"
+#endif
 
 #ifdef TX_PER_PDEV_DESC_POOL
 	#define DP_TX_GET_DESC_POOL_ID(vdev) (vdev->pdev->pdev_id)
@@ -157,14 +160,13 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id)
  *
  */
 static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
-					  uint8_t align_pad)
+		uint8_t align_pad, uint32_t *meta_data)
 {
+	struct htt_tx_msdu_desc_ext2_t *desc_ext =
+				(struct htt_tx_msdu_desc_ext2_t *) meta_data;
 	uint8_t htt_desc_size  = 0;
-	struct htt_tx_msdu_desc_ext2_t desc_ext;
-	uint8_t *hdr;
-	uint8_t ratecode;
-	uint8_t noqos;
-	struct meta_hdr_s *mhdr;
+
+	uint8_t *hdr = NULL;
 
 	qdf_nbuf_unshare(nbuf);
 
@@ -174,47 +176,13 @@ static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	 * Metadata - HTT MSDU Extension header
 	 */
 	htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext2_t);
-	memset(&desc_ext, 0, htt_desc_size);
 
 	if (vdev->mesh_vdev) {
-		/* Extract the mesh metaheader */
-		mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf);
-		qdf_nbuf_pull_head(nbuf, sizeof(struct meta_hdr_s));
-
-		/*use auto rate*/
-		if (!(mhdr->flags & METAHDR_FLAG_AUTO_RATE)) {
-			ratecode = mhdr->rates[0];
-			/* TODO - check the conversion logic here */
-			desc_ext.mcs_mask = (1 << (ratecode + 4));
-			desc_ext.valid_mcs_mask = 1;
-		}
 
 		/* Fill and add HTT metaheader */
 		hdr = qdf_nbuf_push_head(nbuf, htt_desc_size + align_pad);
 
-		desc_ext.power = mhdr->power;
-		desc_ext.retry_limit = mhdr->max_tries[0];
-		desc_ext.key_flags = mhdr->keyix & 0x3;
-
-		if (mhdr->flags & METAHDR_FLAG_NOENCRYPT) {
-			desc_ext.encrypt_type = 0;
-			desc_ext.valid_encrypt_type = 1;
-		}
-
-		desc_ext.valid_pwr = 1;
-		desc_ext.valid_mcs_mask = 1;
-		desc_ext.valid_key_flags = 1;
-		desc_ext.valid_retries = 1;
-
-		if (mhdr->flags & METAHDR_FLAG_NOQOS) {
-			noqos = 1;
-			/*
-			 * TODO - send this TID info to hw_enqueue function
-			 * tid = HTT_NON_QOS_TID;
-			 */
-		}
-
-		qdf_mem_copy(hdr, &desc_ext, htt_desc_size);
+		qdf_mem_copy(hdr, desc_ext, htt_desc_size);
 
 	} else if (vdev->opmode == wlan_op_mode_ocb) {
 		/* Todo - Add support for DSRC */
@@ -248,6 +216,13 @@ struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev,
 	if (!msdu_ext_desc)
 		return NULL;
 
+	if (qdf_unlikely(vdev->mesh_vdev)) {
+		qdf_mem_copy(&cached_ext_desc[HAL_TX_EXTENSION_DESC_LEN_BYTES],
+				&msdu_info->meta_data[0],
+				sizeof(struct htt_tx_msdu_desc_ext2_t));
+		qdf_atomic_inc(&vdev->pdev->num_tx_exception);
+	}
+
 	switch (msdu_info->frm_type) {
 	case dp_tx_frm_sg:
 	case dp_tx_frm_me:
@@ -288,7 +263,8 @@ struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev,
  */
 static
 struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev,
-		qdf_nbuf_t nbuf, uint8_t desc_pool_id)
+		qdf_nbuf_t nbuf, uint8_t desc_pool_id,
+		uint32_t *meta_data)
 {
 	QDF_STATUS status;
 	uint8_t align_pad;
@@ -349,7 +325,7 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev,
 	if (qdf_unlikely(vdev->mesh_vdev ||
 				(vdev->opmode == wlan_op_mode_ocb))) {
 		htt_hdr_size = dp_tx_prepare_htt_metadata(vdev, nbuf,
-				align_pad);
+				align_pad, meta_data);
 		tx_desc->pkt_offset += htt_hdr_size;
 		tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
 		is_exception = 1;
@@ -442,6 +418,8 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev,
 	tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
 	qdf_atomic_inc(&pdev->num_tx_exception);
 #endif
+	if (qdf_unlikely(vdev->mesh_vdev))
+		tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
 
 	tx_desc->msdu_ext_desc = msdu_ext_desc;
 	tx_desc->flags |= DP_TX_DESC_FLAG_FRAG;
@@ -636,7 +614,8 @@ static int dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
  *         nbuf when it fails to send
  */
 static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
-					 uint8_t tid, struct dp_tx_queue *tx_q)
+		uint8_t tid, struct dp_tx_queue *tx_q,
+		uint32_t *meta_data)
 {
 	struct dp_pdev *pdev = vdev->pdev;
 	struct dp_soc *soc = pdev->soc;
@@ -645,7 +624,7 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng;
 
 	/* Setup Tx descriptor for an MSDU, and MSDU extension descriptor */
-	tx_desc = dp_tx_prepare_desc_single(vdev, nbuf, tx_q->desc_pool_id);
+	tx_desc = dp_tx_prepare_desc_single(vdev, nbuf, tx_q->desc_pool_id, meta_data);
 	if (!tx_desc) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			  "%s Tx_desc prepare Fail vdev %p queue %d\n",
@@ -861,6 +840,72 @@ static qdf_nbuf_t dp_tx_prepare_sg(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	return nbuf;
 }
 
+#ifdef MESH_MODE_SUPPORT
+
+/**
+ * dp_tx_extract_mesh_meta_data()- Extract mesh meta hdr info from nbuf
+				and prepare msdu_info for mesh frames.
+ * @vdev: DP vdev handle
+ * @nbuf: skb
+ * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension desc.
+ *
+ * Return: void
+ */
+static
+void dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
+				struct dp_tx_msdu_info_s *msdu_info)
+{
+	struct meta_hdr_s *mhdr;
+	struct htt_tx_msdu_desc_ext2_t *meta_data =
+				(struct htt_tx_msdu_desc_ext2_t *)&msdu_info->meta_data[0];
+
+	mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf);
+
+	memset(meta_data, 0, sizeof(struct htt_tx_msdu_desc_ext2_t));
+
+	if (!(mhdr->flags & METAHDR_FLAG_AUTO_RATE)) {
+		meta_data->power = mhdr->power;
+		meta_data->mcs_mask = mhdr->rates[0] & 0xF;
+		meta_data->nss_mask = (mhdr->rates[0] >> 4) & 0x3;
+		meta_data->pream_type = (mhdr->rates[0] >> 6) & 0x3;
+
+		meta_data->retry_limit = mhdr->max_tries[0];
+		meta_data->dyn_bw = 1;
+
+		meta_data->valid_pwr = 1;
+		meta_data->valid_mcs_mask = 1;
+		meta_data->valid_nss_mask = 1;
+		meta_data->valid_preamble_type  = 1;
+		meta_data->valid_retries = 1;
+		meta_data->valid_bw_info = 1;
+	}
+
+
+	if (mhdr->flags & METAHDR_FLAG_NOENCRYPT) {
+		meta_data->encrypt_type = 0;
+		meta_data->valid_encrypt_type = 1;
+	}
+
+	if (mhdr->flags & METAHDR_FLAG_NOQOS)
+		msdu_info->tid = HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST;
+	else
+		msdu_info->tid = qdf_nbuf_get_priority(nbuf);
+
+	meta_data->valid_key_flags = 1;
+	meta_data->key_flags = (mhdr->keyix & 0x3);
+
+	qdf_nbuf_pull_head(nbuf, sizeof(struct meta_hdr_s));
+	return;
+}
+#else
+static
+void dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
+				struct dp_tx_msdu_info_s *msdu_info)
+{
+}
+
+#endif
+
 /**
  * dp_tx_send() - Transmit a frame on a given VAP
  * @vap_dev: DP vdev handle
@@ -884,7 +929,14 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 			"%s , skb %0x:%0x:%0x:%0x:%0x:%0x\n",
 			__func__, nbuf->data[0], nbuf->data[1], nbuf->data[2],
 			nbuf->data[3], nbuf->data[4], nbuf->data[5]);
+	/*
+	 * Set Default Host TID value to invalid TID
+	 * (TID override disabled)
+	 */
+	msdu_info.tid = HTT_TX_EXT_TID_INVALID;
 
+	if (qdf_unlikely(vdev->mesh_vdev))
+		dp_tx_extract_mesh_meta_data(vdev, nbuf, &msdu_info);
 	/*
 	 * Get HW Queue to use for this frame.
 	 * TCL supports upto 4 DMA rings, out of which 3 rings are
@@ -895,12 +947,6 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 	 */
 	dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue);
 
-	/*
-	 * Set Default Host TID value to invalid TID
-	 * (TID override disabled)
-	 */
-	msdu_info.tid = HTT_TX_EXT_TID_INVALID;
-
 	/*
 	 * TCL H/W supports 2 DSCP-TID mapping tables.
 	 *  Table 1 - Default DSCP-TID mapping table
@@ -981,7 +1027,7 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 	 * SRNG. There is no need to setup a MSDU extension descriptor.
 	 */
 	nbuf = dp_tx_send_msdu_single(vdev, nbuf, msdu_info.tid,
-			&msdu_info.tx_queue);
+			&msdu_info.tx_queue, msdu_info.meta_data);
 
 	return nbuf;
 
@@ -1015,7 +1061,11 @@ void dp_tx_reinject_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
 
 	DP_STATS_MSDU_INCR(soc, tx.reinject.pkts, tx_desc->nbuf);
 
-	dp_tx_send(vdev, tx_desc->nbuf);
+	if (qdf_unlikely(vdev->mesh_vdev)) {
+		DP_TX_FREE_SINGLE_BUF(vdev->pdev->soc, tx_desc->nbuf);
+	} else
+		dp_tx_send(vdev, tx_desc->nbuf);
+
 	dp_tx_desc_release(tx_desc, tx_desc->pool_id);
 }
 
@@ -1105,11 +1155,44 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status)
 	}
 }
 
+#ifdef MESH_MODE_SUPPORT
+/**
+ * dp_tx_comp_fill_tx_completion_stats() - Fill per packet Tx completion stats
+ *                                         in mesh meta header
+ * @tx_desc: software descriptor head pointer
+ * @ts: pointer to tx completion stats
+ * Return: none
+ */
+static
+void dp_tx_comp_fill_tx_completion_stats(struct dp_tx_desc_s *tx_desc,
+		struct hal_tx_completion_status *ts)
+{
+	struct meta_hdr_s *mhdr;
+	qdf_nbuf_t netbuf = tx_desc->nbuf;
+
+	if (!tx_desc->msdu_ext_desc) {
+		qdf_nbuf_pull_head(netbuf, tx_desc->pkt_offset);
+	}
+	qdf_nbuf_push_head(netbuf, sizeof(struct meta_hdr_s));
+
+	mhdr = (struct meta_hdr_s *)qdf_nbuf_data(netbuf);
+	mhdr->rssi = ts->ack_frame_rssi;
+}
+
+#else
+static
+void dp_tx_comp_fill_tx_completion_stats(struct dp_tx_desc_s *tx_desc,
+		struct hal_tx_completion_status *ts)
+{
+}
+
+#endif
+
+
 /**
  * dp_tx_comp_process_tx_status() - Parse and Dump Tx completion status info
  * @tx_desc: software descriptor head pointer
  *
- *
  * Return: none
  */
 static inline void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc)
@@ -1145,6 +1228,9 @@ static inline void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc)
 				ts.tsf, ts.ppdu_id, ts.transmit_cnt, ts.tid,
 				ts.peer_id);
 
+	if (qdf_unlikely(tx_desc->vdev->mesh_vdev))
+		dp_tx_comp_fill_tx_completion_stats(tx_desc, &ts);
+
 }
 
 /**
@@ -1194,14 +1280,12 @@ static void dp_tx_comp_process_desc(struct dp_soc *soc,
 			} else {
 				/* SG free */
 				/* Free buffer */
-				qdf_nbuf_unmap(soc->osdev, desc->nbuf,
-						QDF_DMA_TO_DEVICE);
-				qdf_nbuf_free(desc->nbuf);
+				DP_TX_FREE_DMA_TO_DEVICE(soc, desc->vdev,
+								desc->nbuf);
 			}
 		} else {
-			qdf_nbuf_unmap(soc->osdev, desc->nbuf,
-					QDF_DMA_TO_DEVICE);
-			qdf_nbuf_free(desc->nbuf);
+			/* Free buffer */
+			DP_TX_FREE_DMA_TO_DEVICE(soc, desc->vdev, desc->nbuf);
 		}
 
 		next = desc->next;

+ 11 - 27
dp/wifi3.0/dp_tx.h

@@ -42,6 +42,16 @@ do {                                                           \
 	qdf_nbuf_free(buf);                                    \
 } while (0)
 
+#define DP_TX_FREE_DMA_TO_DEVICE(soc, vdev, buf)               \
+do {                                                           \
+	qdf_nbuf_unmap(soc->osdev, buf, QDF_DMA_TO_DEVICE);    \
+	if (!vdev->mesh_vdev) {                                \
+		qdf_nbuf_free(buf);                            \
+	} else {                                               \
+		vdev->osif_tx_free_ext((buf));		       \
+	}                                                      \
+} while (0)
+
 #define OCB_HEADER_VERSION	 1
 
 /**
@@ -130,35 +140,9 @@ struct dp_tx_msdu_info_s {
 		struct qdf_tso_info_t tso_info;
 		struct dp_tx_sg_info_s sg_info;
 	} u;
+	uint32_t meta_data[5];
 };
 
-struct meta_hdr_s {
-	uint8_t magic;
-	uint8_t flags;
-	uint8_t channel;
-	uint8_t keyix;
-	uint8_t rssi;
-	uint8_t silence;
-	uint8_t power;
-	uint8_t retries;
-	uint8_t max_tries[2];
-	uint8_t rates[2];
-	uint8_t unused[4];
-};
-
-#define METAHDR_FLAG_TX                 (1<<0) /* packet transmission */
-#define METAHDR_FLAG_TX_FAIL            (1<<1) /* transmission failed */
-#define METAHDR_FLAG_TX_USED_ALT_RATE   (1<<2) /* used alternate bitrate */
-#define METAHDR_FLAG_AUTO_RATE          (1<<5)
-#define METAHDR_FLAG_NOENCRYPT          (1<<6)
-#define METAHDR_FLAG_NOQOS              (1<<7)
-
-#define METAHDR_FLAG_RX_ERR             (1<<3) /* failed crc check */
-#define METAHDR_FLAG_RX_MORE            (1<<4) /* first part of a frag skb */
-#define METAHDR_FLAG_LOG                (1<<7)
-
-#define METAHDR_FLAG_RX_4SS             (1<<1) /* rx 4ss frame */
-
 QDF_STATUS dp_tx_vdev_attach(struct dp_vdev *vdev);
 QDF_STATUS dp_tx_vdev_detach(struct dp_vdev *vdev);