Browse Source

qcacmn: Handling vlan tagged frames for multipass phrase feature

1. Remove vlan tag in tx and enqueue to hardware.
2. Add vlan tag in rx after peer-vlan_id lookup.

Change-Id: I932202540ac03cabdd20ffd4849fe759ea8a7abb
Varsha Mishra 5 years ago
parent
commit
6e1760c2c4

+ 31 - 0
dp/inc/cdp_txrx_cmn.h

@@ -1500,6 +1500,7 @@ cdp_get_peer_mac_addr_frm_id(ol_txrx_soc_handle soc, uint16_t peer_id,
 
 /**
  * cdp_set_vdev_dscp_tid_map(): function to set DSCP-tid map in the vap
+ * @soc : soc handle
  * @vdev: vdev handle
  * @map_id: id of the tid map
  *
@@ -1523,6 +1524,36 @@ static inline void cdp_set_vdev_dscp_tid_map(ol_txrx_soc_handle soc,
 				map_id);
 }
 
+#ifdef QCA_MULTIPASS_SUPPORT
+/**
+ * cdp_set_vlan_groupkey(): function to set vlan ID - group key map in the vap
+ * @soc : soc handle
+ * @vdev: vdev handle
+ * @vlan_id: vlan id
+ * @group_key: corresponding group key to vlan ID
+ *
+ * Return: void
+ */
+static inline
+QDF_STATUS cdp_set_vlan_groupkey(ol_txrx_soc_handle soc, struct cdp_vdev *vdev,
+				 uint16_t vlan_id, uint16_t group_key)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "%s: Invalid Instance:", __func__);
+		QDF_BUG(0);
+		return 0;
+	}
+
+	if (!soc->ops->cmn_drv_ops ||
+	    !soc->ops->cmn_drv_ops->set_vlan_groupkey)
+		return 0;
+
+	return soc->ops->cmn_drv_ops->set_vlan_groupkey(vdev, vlan_id,
+							group_key);
+}
+#endif
+
 /**
  * cdp_ath_get_total_per(): function to get hw retries
  * @soc : soc handle

+ 2 - 1
dp/inc/cdp_txrx_cmn_struct.h

@@ -936,7 +936,8 @@ enum cdp_vdev_param_type {
 	CDP_CFG_WDS_AGING_TIMER,
 	CDP_ENABLE_AP_BRIDGE,
 	CDP_ENABLE_CIPHER,
-	CDP_ENABLE_QWRAP_ISOLATION
+	CDP_ENABLE_QWRAP_ISOLATION,
+	CDP_UPDATE_MULTIPASS
 };
 
 #define TXRX_FW_STATS_TXSTATS                     1

+ 20 - 0
dp/inc/cdp_txrx_ctrl.h

@@ -467,6 +467,26 @@ cdp_peer_set_nawds(ol_txrx_soc_handle soc,
 			(peer, value);
 }
 
+#ifdef QCA_MULTIPASS_SUPPORT
+static inline void
+cdp_peer_set_vlan_id(ol_txrx_soc_handle soc, struct cdp_vdev *vdev,
+		     uint8_t *peer_mac, uint8_t vlan_id)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "%s: Invalid Instance:", __func__);
+		QDF_BUG(0);
+		return;
+	}
+
+	if (!soc->ops->ctrl_ops ||
+	    !soc->ops->ctrl_ops->txrx_peer_set_vlan_id)
+		return;
+
+	soc->ops->ctrl_ops->txrx_peer_set_vlan_id(soc, vdev, peer_mac, vlan_id);
+}
+#endif
+
 /**
  * cdp_txrx_set_pdev_param() - set pdev parameter
  * @soc: opaque soc handle

+ 9 - 0
dp/inc/cdp_txrx_ops.h

@@ -466,6 +466,10 @@ struct cdp_cmn_ops {
 	QDF_STATUS (*set_vdev_tidmap_prty)(struct cdp_vdev *vdev, uint8_t prty);
 	QDF_STATUS (*set_vdev_tidmap_tbl_id)(struct cdp_vdev *vdev,
 					     uint8_t mapid);
+#ifdef QCA_MULTIPASS_SUPPORT
+	QDF_STATUS (*set_vlan_groupkey)(struct cdp_vdev *vdev_handle,
+					uint16_t vlan_id, uint16_t group_key);
+#endif
 };
 
 struct cdp_ctrl_ops {
@@ -664,6 +668,11 @@ struct cdp_ctrl_ops {
 				uint16_t protocol_type);
 #endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
+#ifdef QCA_MULTIPASS_SUPPORT
+	void (*txrx_peer_set_vlan_id)(ol_txrx_soc_handle soc,
+				      struct cdp_vdev *vdev, uint8_t *peer_mac,
+				      uint16_t vlan_id);
+#endif
 };
 
 struct cdp_me_ops {

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

@@ -4663,6 +4663,7 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev,
 	 */
 
 	TAILQ_INIT(&vdev->peer_list);
+	dp_peer_multipass_list_init(vdev);
 
 	if ((soc->intr_mode == DP_INTR_POLL) &&
 	    wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx) != 0) {
@@ -5913,6 +5914,7 @@ static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap)
 	dp_peer_rx_bufq_resources_deinit(peer);
 
 	qdf_spinlock_destroy(&peer->peer_info_lock);
+	dp_peer_multipass_list_remove(peer);
 
 	/*
 	 * Remove the reference added during peer_attach.
@@ -7654,6 +7656,9 @@ static void dp_set_vdev_param(struct cdp_vdev *vdev_handle,
 	case CDP_ENABLE_QWRAP_ISOLATION:
 		vdev->isolation_vdev = val;
 		break;
+	case CDP_UPDATE_MULTIPASS:
+		vdev->multipass_en = val;
+		break;
 	default:
 		break;
 	}
@@ -9019,6 +9024,9 @@ static struct cdp_cmn_ops dp_ops_cmn = {
 	.set_vdev_tidmap_tbl_id = dp_set_vdev_tidmap_tbl_id_wifi3,
 
 	.txrx_cp_peer_del_response = dp_cp_peer_del_resp_handler,
+#ifdef QCA_MULTIPASS_SUPPORT
+	.set_vlan_groupkey = dp_set_vlan_groupkey,
+#endif
 };
 
 static struct cdp_ctrl_ops dp_ops_ctrl = {
@@ -9059,6 +9067,9 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
 				dp_dump_pdev_rx_protocol_tag_stats,
 #endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
+#ifdef QCA_MULTIPASS_SUPPORT
+	.txrx_peer_set_vlan_id = dp_peer_set_vlan_id,
+#endif /*QCA_MULTIPASS_SUPPORT*/
 };
 
 static struct cdp_me_ops dp_ops_me = {

+ 62 - 0
dp/wifi3.0/dp_peer.h

@@ -212,4 +212,66 @@ void
 dp_peer_update_inactive_time(struct dp_pdev *pdev, uint32_t tag_type,
 			     uint32_t *tag_buf);
 
+#ifndef QCA_MULTIPASS_SUPPORT
+/**
+ * dp_peer_set_vlan_id: set vlan_id for this peer
+ * @cdp_soc: soc handle
+ * @peer_mac: mac address
+ * @vlan_id: vlan id for peer
+ *
+ * return: void
+ */
+static inline
+void dp_peer_set_vlan_id(struct cdp_soc_t *cdp_soc,
+			 struct cdp_vdev *vdev_handle, uint8_t *peer_mac,
+			 uint16_t vlan_id)
+{
+}
+
+/**
+ * dp_set_vlan_groupkey: set vlan map for vdev
+ * @vdev_handle: pointer to vdev
+ * @vlan_id: vlan_id
+ * @group_key: group key for vlan
+ *
+ * return: set success/failure
+ */
+static inline
+QDF_STATUS dp_set_vlan_groupkey(struct cdp_vdev *vdev_handle,
+				uint16_t vlan_id, uint16_t group_key)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * dp_peer_multipass_list_init: initialize multipass peer list
+ * @vdev: pointer to vdev
+ *
+ * return: void
+ */
+static inline
+void dp_peer_multipass_list_init(struct dp_vdev *vdev)
+{
+}
+
+/**
+ * dp_peer_multipass_list_remove: remove peer from special peer list
+ * @peer: peer handle
+ *
+ * return: void
+ */
+static inline
+void dp_peer_multipass_list_remove(struct dp_peer *peer)
+{
+}
+#else
+void dp_peer_set_vlan_id(struct cdp_soc_t *cdp_soc,
+			 struct cdp_vdev *vdev_handle, uint8_t *peer_mac,
+			 uint16_t vlan_id);
+QDF_STATUS dp_set_vlan_groupkey(struct cdp_vdev *vdev_handle,
+				uint16_t vlan_id, uint16_t group_key);
+void dp_peer_multipass_list_init(struct dp_vdev *vdev);
+void dp_peer_multipass_list_remove(struct dp_peer *peer);
+#endif
+
 #endif /* _DP_PEER_H_ */

+ 7 - 0
dp/wifi3.0/dp_rx.c

@@ -2025,6 +2025,13 @@ done:
 					   l2_hdr_offset);
 		}
 
+		/*
+		 * process frame for mulitpass phrase processing
+		 */
+		if (qdf_unlikely(vdev->multipass_en)) {
+			dp_rx_multipass_process(peer, nbuf, tid);
+		}
+
 		if (!dp_wds_rx_policy_check(rx_tlv_hdr, vdev, peer)) {
 			QDF_TRACE(QDF_MODULE_ID_DP,
 					QDF_TRACE_LEVEL_ERROR,

+ 12 - 0
dp/wifi3.0/dp_rx.h

@@ -1255,4 +1255,16 @@ static inline void dp_rx_flush_rx_cached(struct dp_peer *peer, bool drop)
 {
 }
 #endif
+
+#ifndef QCA_MULTIPASS_SUPPORT
+static inline
+bool dp_rx_multipass_process(struct dp_peer *peer, qdf_nbuf_t nbuf, uint8_t tid)
+{
+	return false;
+}
+#else
+bool dp_rx_multipass_process(struct dp_peer *peer, qdf_nbuf_t nbuf,
+			     uint8_t tid);
+#endif
+
 #endif /* _DP_RX_H */

+ 27 - 7
dp/wifi3.0/dp_tx.c

@@ -303,8 +303,8 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id)
  * Return: HTT metadata size
  *
  */
-static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
-		struct dp_tx_msdu_info_s *msdu_info)
+uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
+				   struct dp_tx_msdu_info_s *msdu_info)
 {
 	uint32_t *meta_data = msdu_info->meta_data;
 	struct htt_tx_msdu_desc_ext2_t *desc_ext =
@@ -323,12 +323,26 @@ static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext2_t);
 	htt_desc_size_aligned = (htt_desc_size + 7) & ~0x7;
 
-	if (vdev->mesh_vdev || msdu_info->is_tx_sniffer) {
+	if (vdev->mesh_vdev || msdu_info->is_tx_sniffer ||
+	    HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_GET(msdu_info->
+							   meta_data[0])) {
 		if (qdf_unlikely(qdf_nbuf_headroom(nbuf) <
-					htt_desc_size_aligned)) {
-			DP_STATS_INC(vdev,
-				     tx_i.dropped.headroom_insufficient, 1);
-			return 0;
+				 htt_desc_size_aligned)) {
+			nbuf = qdf_nbuf_realloc_headroom(nbuf,
+							 htt_desc_size_aligned);
+			if (!nbuf) {
+				/*
+				 * qdf_nbuf_realloc_headroom won't do skb_clone
+				 * as skb_realloc_headroom does. so, no free is
+				 * needed here.
+				 */
+				DP_STATS_INC(vdev,
+					     tx_i.dropped.headroom_insufficient,
+					     1);
+				qdf_print(" %s[%d] skb_realloc_headroom failed",
+					  __func__, __LINE__);
+				return 0;
+			}
 		}
 		/* Fill and add HTT metaheader */
 		hdr = qdf_nbuf_push_head(nbuf, htt_desc_size_aligned);
@@ -746,6 +760,11 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev,
 
 	dp_tx_trace_pkt(nbuf, tx_desc->id, vdev->vdev_id);
 
+	if (qdf_unlikely(vdev->multipass_en)) {
+		if (!dp_tx_multipass_process(soc, vdev, nbuf, msdu_info))
+			goto failure;
+	}
+
 	/*
 	 * For special modes (vdev_type == ocb or mesh), data frames should be
 	 * transmitted using varying transmit parameters (tx spec) which include
@@ -3805,6 +3824,7 @@ QDF_STATUS dp_tx_vdev_detach(struct dp_vdev *vdev)
 
 	/* Reset TX desc associated to this Vdev as NULL */
 	dp_tx_desc_flush(pdev, vdev, false);
+	dp_tx_vdev_multipass_deinit(vdev);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 25 - 0
dp/wifi3.0/dp_tx.h

@@ -237,6 +237,29 @@ static inline void dp_tx_me_exit(struct dp_pdev *pdev)
 	return;
 }
 #endif
+
+#ifndef QCA_MULTIPASS_SUPPORT
+static inline
+bool dp_tx_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev,
+			     qdf_nbuf_t nbuf,
+			     struct dp_tx_msdu_info_s *msdu_info)
+{
+	return true;
+}
+
+static inline
+void dp_tx_vdev_multipass_deinit(struct dp_vdev *vdev)
+{
+}
+
+#else
+bool dp_tx_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev,
+			     qdf_nbuf_t nbuf,
+			     struct dp_tx_msdu_info_s *msdu_info);
+
+void dp_tx_vdev_multipass_deinit(struct dp_vdev *vdev);
+#endif
+
 /**
  * dp_tx_get_queue() - Returns Tx queue IDs to be used for this Tx frame
  * @vdev: DP Virtual device handle
@@ -310,3 +333,5 @@ static inline void dp_tx_comp_process_exception(struct dp_tx_desc_s *tx_desc)
 }
 /* TODO TX_FEATURE_NOT_YET */
 #endif
+uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
+				   struct dp_tx_msdu_info_s *msdu_info);

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

@@ -1817,6 +1817,14 @@ struct dp_vdev {
 	uint8_t tidmap_prty;
 	/* Self Peer in STA mode */
 	struct dp_peer *vap_self_peer;
+
+	bool multipass_en;
+#ifdef QCA_MULTIPASS_SUPPORT
+	uint16_t *iv_vlan_map;
+
+	/* dp_peer special list */
+	TAILQ_HEAD(, dp_peer) mpass_peer_list;
+#endif
 };
 
 
@@ -1940,6 +1948,13 @@ struct dp_peer {
 	/* average sojourn time */
 	qdf_ewma_tx_lag avg_sojourn_msdu[CDP_DATA_TID_MAX];
 
+#ifdef QCA_MULTIPASS_SUPPORT
+	/* node in the special peer list element */
+	TAILQ_ENTRY(dp_peer) mpass_peer_list_elem;
+	/* vlan id for key */
+	uint16_t vlan_id;
+#endif
+
 #ifdef PEER_CACHE_RX_PKTS
 	qdf_atomic_t flush_in_progress;
 	struct dp_peer_cached_bufq bufq_info;