Browse Source

qcacmn: Deliver STP pkts from wbm exception path

Vlan tagged STP pkts are received in host from
wbm exception path with wifi parse error code.
This is delivered to stack. Stats added for wifi
parse error and vlan tagged stp pkt count.

Change-Id: I25af5ab403ee7a46b4abe2f60328314d61587b80
CRs-fixed: 2375575
sumedh baikady 6 years ago
parent
commit
c2fa7c99c0
5 changed files with 72 additions and 22 deletions
  1. 4 0
      dp/inc/cdp_txrx_stats_struct.h
  2. 4 0
      dp/wifi3.0/dp_main.c
  3. 15 0
      dp/wifi3.0/dp_rx.h
  4. 40 21
      dp/wifi3.0/dp_rx_err.c
  5. 9 1
      qdf/inc/qdf_net_types.h

+ 4 - 0
dp/inc/cdp_txrx_stats_struct.h

@@ -1144,6 +1144,7 @@ struct cdp_htt_rx_pdev_stats {
  * @mec:Multicast Echo check
  * @mesh_filter: Mesh Filtered packets
  * @mon_rx_drop: packets dropped on monitor vap
+ * @wifi_parse: rxdma errors due to wifi parse error
  * @pkts: total packets replenished
  * @rxdma_err: rxdma errors for replenished
  * @nbuf_alloc_fail: nbuf alloc failed
@@ -1154,6 +1155,7 @@ struct cdp_htt_rx_pdev_stats {
  * @mesh_mem_alloc: Mesh Rx Stats Alloc fail
  * @tso_desc_cnt: TSO descriptors
  * @sg_desc_cnt: SG Descriptors
+ * @vlan_tag_stp_cnt: Vlan tagged Stp packets in wifi parse error
  * @desc_alloc_fail: desc alloc failed errors
  * @ip_csum_err: ip checksum errors
  * @tcp_udp_csum_err: tcp/udp checksum errors
@@ -1173,6 +1175,7 @@ struct cdp_pdev_stats {
 		uint32_t mec;
 		uint32_t mesh_filter;
 		uint32_t mon_rx_drop;
+		uint32_t wifi_parse;
 	} dropped;
 
 	struct {
@@ -1188,6 +1191,7 @@ struct cdp_pdev_stats {
 	uint32_t mesh_mem_alloc;
 	uint32_t tso_desc_cnt;
 	uint32_t sg_desc_cnt;
+	uint32_t vlan_tag_stp_cnt;
 
 	/* Rx errors */
 	struct {

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

@@ -6726,6 +6726,8 @@ dp_print_pdev_rx_stats(struct dp_pdev *pdev)
 	DP_PRINT_STATS("Dropped:");
 	DP_PRINT_STATS("	msdu_not_done = %d",
 			pdev->stats.dropped.msdu_not_done);
+	DP_PRINT_STATS("        wifi parse = %d",
+			pdev->stats.dropped.wifi_parse);
 	DP_PRINT_STATS("        mon_rx_drop = %d",
 			pdev->stats.dropped.mon_rx_drop);
 	DP_PRINT_STATS("        mec_drop = %d",
@@ -6737,6 +6739,8 @@ dp_print_pdev_rx_stats(struct dp_pdev *pdev)
 			pdev->stats.rx.to_stack.num);
 	DP_PRINT_STATS("	Bytes = %llu",
 			pdev->stats.rx.to_stack.bytes);
+	DP_PRINT_STATS("        vlan_tag_stp_cnt = %d",
+			pdev->stats.vlan_tag_stp_cnt);
 	DP_PRINT_STATS("Multicast/Broadcast:");
 	DP_PRINT_STATS("	Packets = %d",
 			pdev->stats.rx.multicast.num);

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

@@ -119,6 +119,16 @@ struct dp_rx_desc {
 	(((_cookie) & RX_DESC_COOKIE_INDEX_MASK) >>	\
 			RX_DESC_COOKIE_INDEX_SHIFT)
 
+/* DOC: Offset to obtain LLC hdr
+ *
+ * In the case of Wifi parse error
+ * to reach LLC header from beginning
+ * of VLAN tag we need to skip 8 bytes.
+ * Vlan_tag(4)+length(2)+length added
+ * by HW(2) = 8 bytes.
+ */
+#define DP_SKIP_VLAN		8
+
 /*
  *dp_rx_xor_block() - xor block of data
  *@b: destination data block
@@ -1036,4 +1046,9 @@ static inline void dp_rx_desc_prep(struct dp_rx_desc *rx_desc, qdf_nbuf_t nbuf)
 	rx_desc->unmapped = 0;
 }
 #endif /* RX_DESC_DEBUG_CHECK */
+
+void dp_rx_process_rxdma_err(struct dp_soc *soc, qdf_nbuf_t nbuf,
+			     uint8_t *rx_tlv_hdr, struct dp_peer *peer,
+			     uint8_t err_code);
+
 #endif /* _DP_RX_H */

+ 40 - 21
dp/wifi3.0/dp_rx_err.c

@@ -31,6 +31,7 @@
 #endif
 #include "dp_rx_defrag.h"
 #include <enet.h>	/* LLC_SNAP_HDR_LEN */
+#include "qdf_net_types.h"
 
 /**
  * dp_rx_mcast_echo_check() - check if the mcast pkt is a loop
@@ -843,18 +844,20 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf,
 }
 
 /**
- * dp_rx_process_err_unencrypted() - Function to deliver rxdma unencrypted_err
- *				     frames to OS
+ * dp_rx_process_rxdma_err() - Function to deliver rxdma unencrypted_err
+ *			       frames to OS or wifi parse errors.
  * @soc: core DP main context
  * @nbuf: buffer pointer
  * @rx_tlv_hdr: start of rx tlv header
  * @peer: peer reference
+ * @err_code: rxdma err code
  *
  * Return: None
  */
-static void
-dp_rx_process_err_unencrypted(struct dp_soc *soc, qdf_nbuf_t nbuf,
-			      uint8_t *rx_tlv_hdr, struct dp_peer *peer)
+void
+dp_rx_process_rxdma_err(struct dp_soc *soc, qdf_nbuf_t nbuf,
+			uint8_t *rx_tlv_hdr, struct dp_peer *peer,
+			uint8_t err_code)
 {
 	uint32_t pkt_len, l2_hdr_offset;
 	uint16_t msdu_len;
@@ -913,6 +916,21 @@ dp_rx_process_err_unencrypted(struct dp_soc *soc, qdf_nbuf_t nbuf,
 	 */
 	qdf_nbuf_pull_head(nbuf, l2_hdr_offset + RX_PKT_TLVS_LEN);
 
+	if (err_code == HAL_RXDMA_ERR_WIFI_PARSE) {
+		uint8_t *pkt_type;
+
+		pkt_type = qdf_nbuf_data(nbuf) + (2 * QDF_MAC_ADDR_SIZE);
+		if (*(uint16_t *)pkt_type == htons(QDF_ETH_TYPE_8021Q) &&
+		    *(uint16_t *)(pkt_type + DP_SKIP_VLAN) == htons(QDF_LLC_STP)) {
+			DP_STATS_INC(vdev->pdev, vlan_tag_stp_cnt, 1);
+			goto process_mesh;
+		} else {
+			DP_STATS_INC(vdev->pdev, dropped.wifi_parse, 1);
+			qdf_nbuf_free(nbuf);
+			return;
+		}
+	}
+
 	if (vdev->rx_decap_type == htt_cmn_pkt_type_raw)
 		goto process_mesh;
 
@@ -937,24 +955,24 @@ dp_rx_process_err_unencrypted(struct dp_soc *soc, qdf_nbuf_t nbuf,
 
 process_mesh:
 
-	/* Drop & free packet if mesh mode not enabled */
-	if (!vdev->mesh_vdev) {
+	if (!vdev->mesh_vdev && err_code == HAL_RXDMA_ERR_UNENCRYPTED) {
 		qdf_nbuf_free(nbuf);
 		DP_STATS_INC(soc, rx.err.invalid_vdev, 1);
 		return;
 	}
 
-	if (dp_rx_filter_mesh_packets(vdev, nbuf, rx_tlv_hdr)
-							== QDF_STATUS_SUCCESS) {
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_MED,
-				FL("mesh pkt filtered"));
-		DP_STATS_INC(vdev->pdev, dropped.mesh_filter, 1);
+	if (vdev->mesh_vdev) {
+		if (dp_rx_filter_mesh_packets(vdev, nbuf, rx_tlv_hdr)
+				      == QDF_STATUS_SUCCESS) {
+			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_MED,
+				  FL("mesh pkt filtered"));
+			DP_STATS_INC(vdev->pdev, dropped.mesh_filter, 1);
 
-		qdf_nbuf_free(nbuf);
-		return;
+			qdf_nbuf_free(nbuf);
+			return;
+		}
+		dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer);
 	}
-	dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer);
-
 process_rx:
 	if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr) &&
 				(vdev->rx_decap_type ==
@@ -1481,13 +1499,14 @@ done:
 
 				switch (wbm_err_info.rxdma_err_code) {
 				case HAL_RXDMA_ERR_UNENCRYPTED:
-					dp_rx_process_err_unencrypted(
-							soc, nbuf,
-							rx_tlv_hdr, peer);
+
+				case HAL_RXDMA_ERR_WIFI_PARSE:
+					dp_rx_process_rxdma_err(soc, nbuf,
+								rx_tlv_hdr, peer,
+								wbm_err_info.rxdma_err_code);
 					nbuf = next;
 					if (peer)
-						dp_peer_unref_del_find_by_id(
-									peer);
+						dp_peer_unref_del_find_by_id(peer);
 					continue;
 
 				case HAL_RXDMA_ERR_TKIP_MIC:

+ 9 - 1
qdf/inc/qdf_net_types.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -60,6 +60,7 @@ typedef __in6_addr_t in6_addr_t;
 
 #define QDF_ETH_TYPE_IPV4              0x0800  /* IPV4 */
 #define QDF_ETH_TYPE_IPV6              0x86dd  /* IPV6 */
+#define QDF_ETH_TYPE_8021Q             0x8100  /* 802.1Q vlan protocol */
 #define QDF_IEEE80211_4ADDR_HDR_LEN     30
 #define QDF_IEEE80211_3ADDR_HDR_LEN     24
 #define QDF_IEEE80211_FC0_SUBTYPE_QOS   0x80
@@ -68,6 +69,13 @@ typedef __in6_addr_t in6_addr_t;
 
 #define QDF_NET_IS_MAC_MULTICAST(_a)   (*(_a) & 0x01)
 
+/**
+ * In LLC header individual LSAP address 0x42 in
+ * DSAP and SSAP signifies IEEE 802.1 Bridge
+ * Spanning Tree Protocol
+ */
+#define QDF_LLC_STP 0x4242
+
 typedef struct qdf_net_ethaddr {
 	uint8_t addr[QDF_NET_ETH_LEN];
 } qdf_net_ethaddr_t;