Przeglądaj źródła

qcacmn: FR-64493 WDS Extended support

Use AST override feature to send out multicast packet in
4 address format. Pass per packet peer_id from osif layer.

Change-Id: Ic86120169c89e7972caa3cc8c967de72670314d0
CRs-Fixed: 2775051
Varsha Mishra 4 lat temu
rodzic
commit
ca0cf99f1d
4 zmienionych plików z 194 dodań i 63 usunięć
  1. 3 0
      dp/inc/cdp_txrx_cmn_struct.h
  2. 180 57
      dp/wifi3.0/dp_tx.c
  3. 5 2
      dp/wifi3.0/dp_tx.h
  4. 6 4
      dp/wifi3.0/dp_types.h

+ 3 - 0
dp/inc/cdp_txrx_cmn_struct.h

@@ -541,6 +541,9 @@ struct cdp_tx_exception_metadata {
 	enum cdp_sec_type sec_type;
 	uint8_t is_tx_sniffer;
 	uint16_t ppdu_cookie;
+#ifdef QCA_SUPPORT_WDS_EXTENDED
+	uint8_t is_wds_extended;
+#endif
 };
 
 typedef struct cdp_soc_t *ol_txrx_soc_handle;

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

@@ -794,6 +794,82 @@ static void dp_tx_trace_pkt(qdf_nbuf_t skb, uint16_t msdu_id,
 }
 #endif
 
+#ifdef QCA_SUPPORT_WDS_EXTENDED
+/**
+ * dp_is_tx_extended() - Configure AST override from peer ast entry
+ *
+ * @vdev: DP vdev handle
+ * @tx_exc_metadata: Handle that holds exception path metadata
+ *
+ * Return: if this packet needs to exception to FW or not
+ *	   (false: exception to wlan FW, true: do not exception)
+ */
+static inline bool
+dp_is_tx_extended(struct dp_vdev *vdev, struct cdp_tx_exception_metadata
+		  *tx_exc_metadata)
+{
+	if (qdf_likely(!vdev->wds_ext_enabled))
+		return false;
+
+	if (tx_exc_metadata && !tx_exc_metadata->is_wds_extended)
+		return false;
+
+	return true;
+}
+
+/**
+ * dp_tx_wds_ext() - Configure AST override from peer ast entry
+ *
+ * @soc: DP soc handle
+ * @vdev: DP vdev handle
+ * @peer_id: peer_id of the peer for which packet is destined
+ * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension desc.
+ *
+ * Return: None
+ */
+static inline void
+dp_tx_wds_ext(struct dp_soc *soc, struct dp_vdev *vdev, uint16_t peer_id,
+	      struct dp_tx_msdu_info_s *msdu_info)
+{
+	struct dp_peer *peer = NULL;
+
+	msdu_info->search_type = vdev->search_type;
+	msdu_info->ast_idx = vdev->bss_ast_idx;
+	msdu_info->ast_hash = vdev->bss_ast_hash;
+
+	if (qdf_likely(!vdev->wds_ext_enabled))
+		return;
+
+	peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_TX);
+
+	if (qdf_unlikely(!peer))
+		return;
+
+	msdu_info->search_type = HAL_TX_ADDR_INDEX_SEARCH;
+	msdu_info->ast_idx = peer->self_ast_entry->ast_idx;
+	msdu_info->ast_hash = peer->self_ast_entry->ast_hash_value;
+	dp_peer_unref_delete(peer, DP_MOD_ID_TX);
+	msdu_info->exception_fw = 0;
+}
+#else
+
+static inline bool
+dp_is_tx_extended(struct dp_vdev *vdev, struct cdp_tx_exception_metadata
+		  *tx_exc_metadata)
+{
+	return false;
+}
+
+static inline void
+dp_tx_wds_ext(struct dp_soc *soc, struct dp_vdev *vdev, uint16_t peer_id,
+	      struct dp_tx_msdu_info_s *msdu_info)
+{
+	msdu_info->search_type = vdev->search_type;
+	msdu_info->ast_idx = vdev->bss_ast_idx;
+	msdu_info->ast_hash = vdev->bss_ast_hash;
+}
+#endif
+
 /**
  * dp_tx_desc_prepare_single - Allocate and prepare Tx descriptor
  * @vdev: DP vdev handle
@@ -849,6 +925,9 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev,
 			goto failure;
 	}
 
+	if (qdf_unlikely(dp_is_tx_extended(vdev, tx_exc_metadata)))
+		return tx_desc;
+
 	/*
 	 * For special modes (vdev_type == ocb or mesh), data frames should be
 	 * transmitted using varying transmit parameters (tx spec) which include
@@ -1255,16 +1334,19 @@ dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl,
  * Return: QDF_STATUS_SUCCESS: success
  *         QDF_STATUS_E_RESOURCES: Error return
  */
-static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
-				   struct dp_tx_desc_s *tx_desc, uint8_t tid,
-				   uint16_t fw_metadata, uint8_t ring_id,
-				   struct cdp_tx_exception_metadata
-					*tx_exc_metadata)
+static QDF_STATUS
+dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
+		 struct dp_tx_desc_s *tx_desc, uint16_t fw_metadata,
+		 struct cdp_tx_exception_metadata *tx_exc_metadata,
+		 struct dp_tx_msdu_info_s *msdu_info)
 {
 	uint8_t type;
 	void *hal_tx_desc;
 	uint32_t *hal_tx_desc_cached;
 	int coalesce = 0;
+	struct dp_tx_queue *tx_q = &msdu_info->tx_queue;
+	uint8_t ring_id = tx_q->ring_id & DP_TX_QUEUE_MASK;
+	uint8_t tid = msdu_info->tid;
 
 	/*
 	 * Setting it initialization statically here to avoid
@@ -1314,16 +1396,16 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
 	hal_tx_desc_set_lmac_id(soc->hal_soc, hal_tx_desc_cached,
 				vdev->lmac_id);
 	hal_tx_desc_set_search_type(soc->hal_soc, hal_tx_desc_cached,
-				    vdev->search_type);
+				    msdu_info->search_type);
 	hal_tx_desc_set_search_index(soc->hal_soc, hal_tx_desc_cached,
-				     vdev->bss_ast_idx);
+				     msdu_info->ast_idx);
 	hal_tx_desc_set_dscp_tid_table_id(soc->hal_soc, hal_tx_desc_cached,
 					  vdev->dscp_tid_map_id);
 
 	hal_tx_desc_set_encrypt_type(hal_tx_desc_cached,
 			sec_type_map[sec_type]);
 	hal_tx_desc_set_cache_set_num(soc->hal_soc, hal_tx_desc_cached,
-				      (vdev->bss_ast_hash & 0xF));
+				      (msdu_info->ast_hash & 0xF));
 
 	hal_tx_desc_set_fw_metadata(hal_tx_desc_cached, fw_metadata);
 	hal_tx_desc_set_buf_length(hal_tx_desc_cached, tx_desc->length);
@@ -1955,8 +2037,8 @@ dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	}
 
 	/* Enqueue the Tx MSDU descriptor to HW for transmit */
-	status = dp_tx_hw_enqueue(soc, vdev, tx_desc, tid,
-			htt_tcl_metadata, tx_q->ring_id, tx_exc_metadata);
+	status = dp_tx_hw_enqueue(soc, vdev, tx_desc, htt_tcl_metadata,
+				  tx_exc_metadata, msdu_info);
 
 	if (status != QDF_STATUS_SUCCESS) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
@@ -2087,8 +2169,8 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 		/*
 		 * Enqueue the Tx MSDU descriptor to HW for transmit
 		 */
-		status = dp_tx_hw_enqueue(soc, vdev, tx_desc, msdu_info->tid,
-			htt_tcl_metadata, tx_q->ring_id, NULL);
+		status = dp_tx_hw_enqueue(soc, vdev, tx_desc, htt_tcl_metadata,
+					  NULL, msdu_info);
 
 		if (status != QDF_STATUS_SUCCESS) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
@@ -2420,6 +2502,52 @@ static bool dp_check_exc_metadata(struct cdp_tx_exception_metadata *tx_exc)
 	return true;
 }
 
+#ifdef ATH_SUPPORT_IQUE
+/**
+ * dp_tx_mcast_enhance() - Multicast enhancement on TX
+ * @vdev: vdev handle
+ * @nbuf: skb
+ *
+ * Return: true on success,
+ *         false on failure
+ */
+static inline bool dp_tx_mcast_enhance(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
+{
+	qdf_ether_header_t *eh;
+
+	/* Mcast to Ucast Conversion*/
+	if (qdf_likely(!vdev->mcast_enhancement_en))
+		return true;
+
+	eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
+	if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost) &&
+	    !DP_FRAME_IS_BROADCAST((eh)->ether_dhost)) {
+		dp_verbose_debug("Mcast frm for ME %pK", vdev);
+
+		DP_STATS_INC_PKT(vdev, tx_i.mcast_en.mcast_pkt, 1,
+				 qdf_nbuf_len(nbuf));
+		if (dp_tx_prepare_send_me(vdev, nbuf) ==
+				QDF_STATUS_SUCCESS) {
+			return false;
+		}
+
+		if (qdf_unlikely(vdev->igmp_mcast_enhanc_en > 0)) {
+			if (dp_tx_prepare_send_igmp_me(vdev, nbuf) ==
+					QDF_STATUS_SUCCESS) {
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+#else
+static inline bool dp_tx_mcast_enhance(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
+{
+	return true;
+}
+#endif
+
 /**
  * dp_tx_per_pkt_vdev_id_check() - vdev id check for frame
  * @nbuf: qdf_nbuf_t
@@ -2489,6 +2617,7 @@ dp_tx_send_exception(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 		goto fail;
 
 	msdu_info.tid = tx_exc_metadata->tid;
+	dp_tx_wds_ext(soc, vdev, tx_exc_metadata->peer_id, &msdu_info);
 
 	eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
 	dp_verbose_debug("skb "QDF_MAC_ADDR_FMT,
@@ -2511,32 +2640,46 @@ dp_tx_send_exception(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 		goto fail;
 	}
 
-	/* TSO or SG */
-	if (qdf_unlikely(qdf_nbuf_is_tso(nbuf)) ||
-	    qdf_unlikely(qdf_nbuf_is_nonlinear(nbuf))) {
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-			  "TSO and SG are not supported in exception path");
+	/*
+	 * Classify the frame and call corresponding
+	 * "prepare" function which extracts the segment (TSO)
+	 * and fragmentation information (for TSO , SG, ME, or Raw)
+	 * into MSDU_INFO structure which is later used to fill
+	 * SW and HW descriptors.
+	 */
+	if (qdf_nbuf_is_tso(nbuf)) {
+		dp_verbose_debug("TSO frame %pK", vdev);
+		DP_STATS_INC_PKT(vdev->pdev, tso_stats.num_tso_pkts, 1,
+				 qdf_nbuf_len(nbuf));
 
-		goto fail;
-	}
+		if (dp_tx_prepare_tso(vdev, nbuf, &msdu_info)) {
+			DP_STATS_INC_PKT(vdev->pdev, tso_stats.dropped_host, 1,
+					 qdf_nbuf_len(nbuf));
+			return nbuf;
+		}
 
-	/* RAW */
-	if (qdf_unlikely(tx_exc_metadata->tx_encap_type == htt_cmn_pkt_type_raw)) {
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-			  "Raw frame is not supported in exception path");
-		goto fail;
+		goto send_multiple;
 	}
 
+	/* SG */
+	if (qdf_unlikely(qdf_nbuf_is_nonlinear(nbuf))) {
+		struct dp_tx_seg_info_s seg_info = {0};
 
-	/* Mcast enhancement*/
-	if (qdf_unlikely(vdev->mcast_enhancement_en > 0)) {
-		if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost) &&
-		    !DP_FRAME_IS_BROADCAST((eh)->ether_dhost)) {
-			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-					  "Ignoring mcast_enhancement_en which is set and sending the mcast packet to the FW");
-		}
+		nbuf = dp_tx_prepare_sg(vdev, nbuf, &seg_info, &msdu_info);
+		if (!nbuf)
+			return NULL;
+
+		dp_verbose_debug("non-TSO SG frame %pK", vdev);
+
+		DP_STATS_INC_PKT(vdev, tx_i.sg.sg_pkt, 1,
+				 qdf_nbuf_len(nbuf));
+
+		goto send_multiple;
 	}
 
+	if (qdf_unlikely(!dp_tx_mcast_enhance(vdev, nbuf)))
+		return NULL;
+
 	if (qdf_likely(tx_exc_metadata->is_tx_sniffer)) {
 		DP_STATS_INC_PKT(vdev, tx_i.sniffer_rcvd, 1,
 				 qdf_nbuf_len(nbuf));
@@ -2573,6 +2716,9 @@ dp_tx_send_exception(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 	dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TX_EXCEPTION);
 	return nbuf;
 
+send_multiple:
+	nbuf = dp_tx_send_msdu_multiple(vdev, nbuf, &msdu_info);
+
 fail:
 	if (vdev)
 		dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TX_EXCEPTION);
@@ -2844,6 +2990,7 @@ qdf_nbuf_t dp_tx_send(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 	 * (TID override disabled)
 	 */
 	msdu_info.tid = HTT_TX_EXT_TID_INVALID;
+	dp_tx_wds_ext(soc, vdev, peer_id, &msdu_info);
 	DP_STATS_INC_PKT(vdev, tx_i.rcvd, 1, qdf_nbuf_len(nbuf));
 
 	if (qdf_unlikely(vdev->mesh_vdev)) {
@@ -2915,32 +3062,8 @@ qdf_nbuf_t dp_tx_send(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 		goto send_multiple;
 	}
 
-#ifdef ATH_SUPPORT_IQUE
-	/* Mcast to Ucast Conversion*/
-	if (qdf_unlikely(vdev->mcast_enhancement_en > 0)) {
-		qdf_ether_header_t *eh = (qdf_ether_header_t *)
-					  qdf_nbuf_data(nbuf);
-		if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost) &&
-		    !DP_FRAME_IS_BROADCAST((eh)->ether_dhost)) {
-			dp_verbose_debug("Mcast frm for ME %pK", vdev);
-
-			DP_STATS_INC_PKT(vdev,
-					tx_i.mcast_en.mcast_pkt, 1,
-					qdf_nbuf_len(nbuf));
-			if (dp_tx_prepare_send_me(vdev, nbuf) ==
-					QDF_STATUS_SUCCESS) {
-				return NULL;
-			}
-
-			if (qdf_unlikely(vdev->igmp_mcast_enhanc_en > 0)) {
-				if (dp_tx_prepare_send_igmp_me(vdev, nbuf) ==
-					QDF_STATUS_SUCCESS) {
-					return NULL;
-				}
-			}
-		}
-	}
-#endif
+	if (qdf_unlikely(!dp_tx_mcast_enhance(vdev, nbuf)))
+		return NULL;
 
 	/* RAW */
 	if (qdf_unlikely(vdev->tx_encap_type == htt_cmn_pkt_type_raw)) {

+ 5 - 2
dp/wifi3.0/dp_tx.h

@@ -153,14 +153,17 @@ struct dp_tx_msdu_info_s {
 	struct dp_tx_queue tx_queue;
 	uint32_t num_seg;
 	uint8_t tid;
+	uint8_t exception_fw;
+	uint8_t is_tx_sniffer;
+	uint8_t search_type;
 	union {
 		struct qdf_tso_info_t tso_info;
 		struct dp_tx_sg_info_s sg_info;
 	} u;
 	uint32_t meta_data[DP_TX_MSDU_INFO_META_DATA_DWORDS];
-	uint8_t exception_fw;
 	uint16_t ppdu_cookie;
-	uint8_t is_tx_sniffer;
+	uint16_t ast_idx;
+	uint16_t ast_hash;
 };
 
 /**

+ 6 - 4
dp/wifi3.0/dp_types.h

@@ -199,7 +199,8 @@ enum dp_mod_id {
 	DP_MOD_ID_TDLS = 19,
 	DP_MOD_ID_MISC = 20,
 	DP_MOD_ID_MSCS = 21,
-	DP_MOD_ID_MAX = 22,
+	DP_MOD_ID_TX = 22,
+	DP_MOD_ID_MAX = 23,
 };
 
 #define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \
@@ -2300,6 +2301,10 @@ struct dp_vdev {
 	/* MEC enabled */
 	bool mec_enabled;
 
+#ifdef QCA_SUPPORT_WDS_EXTENDED
+	bool wds_ext_enabled;
+#endif /* QCA_SUPPORT_WDS_EXTENDED */
+
 	/* WDS Aging timer period */
 	uint32_t wds_aging_timer_val;
 
@@ -2518,9 +2523,6 @@ struct dp_vdev {
 	qdf_atomic_t ref_cnt;
 	qdf_atomic_t mod_refs[DP_MOD_ID_MAX];
 	uint8_t num_latency_critical_conn;
-#ifdef QCA_SUPPORT_WDS_EXTENDED
-	bool wds_ext_enabled;
-#endif /* QCA_SUPPORT_WDS_EXTENDED */
 };