소스 검색

qcacmn: Set TX flow queue for TCP ack

If TX data is TCP ACK, configure TX flow index 3 in
SW2TCL data cmd ring descriptor.

Change-Id: Ibd08b13ba8f0481aa11cd9c3dc54a49cd73674fb
CRs-Fixed: 3368303
Jinwei Chen 2 년 전
부모
커밋
b4f81eace0
7개의 변경된 파일248개의 추가작업 그리고 4개의 파일을 삭제
  1. 38 1
      dp/wifi3.0/be/dp_be_tx.c
  2. 79 0
      qdf/inc/qdf_nbuf.h
  3. 2 0
      qdf/linux/src/i_qdf_nbuf.h
  4. 74 0
      qdf/linux/src/qdf_nbuf.c
  5. 23 1
      wlan_cfg/cfg_dp.h
  6. 26 1
      wlan_cfg/wlan_cfg.c
  7. 6 1
      wlan_cfg/wlan_cfg.h

+ 38 - 1
dp/wifi3.0/be/dp_be_tx.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. 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
@@ -445,6 +445,7 @@ static inline uint8_t dp_tx_get_rbm_id_be(struct dp_soc *soc,
 	return rbm;
 }
 #endif
+
 #ifdef QCA_SUPPORT_TX_MIN_RATES_FOR_SPECIAL_FRAMES
 
 /*
@@ -490,6 +491,40 @@ dp_tx_set_min_rates_for_critical_frames(struct dp_soc *soc,
 }
 #endif
 
+#ifdef DP_TX_PACKET_INSPECT_FOR_ILP
+/**
+ * dp_tx_set_particular_tx_queue() - set particular TX TQM flow queue 3 for
+ *				     TX packets, currently TCP ACK only
+ * @soc: DP soc structure pointer
+ * @hal_tx_desc: HAL descriptor where fields are set
+ * @nbuf: skb to be considered for particular TX queue
+ *
+ * Return: None
+ */
+static inline
+void dp_tx_set_particular_tx_queue(struct dp_soc *soc,
+				   uint32_t *hal_tx_desc,
+				   qdf_nbuf_t nbuf)
+{
+	if (!soc->wlan_cfg_ctx->tx_pkt_inspect_for_ilp)
+		return;
+
+	if (qdf_unlikely(QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) ==
+			 QDF_NBUF_CB_PACKET_TYPE_TCP_ACK)) {
+		hal_tx_desc_set_flow_override_enable(hal_tx_desc, 1);
+		hal_tx_desc_set_flow_override(hal_tx_desc, 1);
+		hal_tx_desc_set_who_classify_info_sel(hal_tx_desc, 1);
+	}
+}
+#else
+static inline
+void dp_tx_set_particular_tx_queue(struct dp_soc *soc,
+				   uint32_t *hal_tx_desc,
+				   qdf_nbuf_t nbuf)
+{
+}
+#endif
+
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
 	defined(WLAN_MCAST_MLO)
 #ifdef QCA_MULTIPASS_SUPPORT
@@ -1079,6 +1114,8 @@ dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
 
 	dp_tx_set_min_rates_for_critical_frames(soc, hal_tx_desc_cached,
 						tx_desc->nbuf);
+	dp_tx_set_particular_tx_queue(soc, hal_tx_desc_cached,
+				      tx_desc->nbuf);
 	dp_tx_desc_set_ktimestamp(vdev, tx_desc);
 
 	hal_ring_hdl = dp_tx_get_hal_ring_hdl(soc, ring_id);

+ 79 - 0
qdf/inc/qdf_nbuf.h

@@ -98,6 +98,8 @@
 #define QDF_NBUF_TRAC_DOUBLE_VLAN_IP_OFFSET	22
 /* One dword for IPv4 header size unit */
 #define QDF_NBUF_IPV4_HDR_SIZE_UNIT	4
+#define QDF_NBUF_TRAC_IPV4_TOTAL_LEN_OFFSET 16
+#define QDF_NBUF_TRAC_IPV6_PAYLOAD_LEN_OFFSET 18
 
 /* EAPOL Related MASK */
 #define EAPOL_PACKET_TYPE_OFFSET		15
@@ -150,6 +152,14 @@
 #define QDF_NBUF_PKT_TCPOP_ACK			0x10
 #define QDF_NBUF_PKT_TCP_SRC_PORT_OFFSET	34
 #define QDF_NBUF_PKT_TCP_DST_PORT_OFFSET	36
+#define QDF_NBUF_PKT_IPV4_TCP_HDR_LEN_OFFSET 46
+#define QDF_NBUF_PKT_IPV4_TCP_OPCODE_OFFSET 47
+#define QDF_NBUF_PKT_IPV6_TCP_HDR_LEN_OFFSET 66
+#define QDF_NBUF_PKT_IPV6_TCP_OPCODE_OFFSET 67
+#define QDF_NBUF_PKT_TCP_HDR_LEN_MASK 0xF0
+#define QDF_NBUF_PKT_TCP_HDR_LEN_LSB 4
+#define QDF_NBUF_PKT_TCP_HDR_LEN_UNIT 4
+#define QDF_NBUF_PKT_TCP_ACK_MAX_LEN 100
 
 /* DNS Related MASK */
 #define QDF_NBUF_PKT_DNS_OVER_UDP_OPCODE_OFFSET	44
@@ -4248,6 +4258,75 @@ bool qdf_nbuf_is_mcast_replay(qdf_nbuf_t buf)
 	return __qdf_nbuf_is_mcast_replay(buf);
 }
 
+#ifdef DP_TX_PACKET_INSPECT_FOR_ILP
+/* Reuse bit24~31 in skb->priority for packet type */
+#define QDF_NBUF_PRIORITY_PKT_TYPE_MASK 0xFF000000
+#define QDF_NBUF_PRIORITY_PKT_TYPE_LSB 24
+/* TCP ACK */
+#define QDF_NBUF_PRIORITY_PKT_TCP_ACK 0x1
+
+#define QDF_NBUF_GET_PRIORITY_PKT_TYPE(_pri) \
+	(((_pri) & QDF_NBUF_PRIORITY_PKT_TYPE_MASK) >> \
+	 QDF_NBUF_PRIORITY_PKT_TYPE_LSB)
+
+#define QDF_NBUF_PRIORITY_PKT_TYPE(_pkt_type) \
+	(((_pkt_type) << QDF_NBUF_PRIORITY_PKT_TYPE_LSB) & \
+	 QDF_NBUF_PRIORITY_PKT_TYPE_MASK)
+
+/**
+ * qdf_nbuf_get_priority_pkt_type() - Get packet type from priority
+ * @nbuf: pointer to network buffer
+ *
+ * Return: packet type
+ */
+static inline
+uint8_t qdf_nbuf_get_priority_pkt_type(qdf_nbuf_t nbuf)
+{
+	return QDF_NBUF_GET_PRIORITY_PKT_TYPE(nbuf->priority);
+}
+
+/**
+ * qdf_nbuf_set_priority_pkt_type() - Set packet type to priority
+ * @nbuf: pointer to network buffer
+ * @pkt_type: packet type to be set
+ *
+ * Return: none
+ */
+static inline
+void qdf_nbuf_set_priority_pkt_type(qdf_nbuf_t nbuf, uint8_t pkt_type)
+{
+	nbuf->priority |= QDF_NBUF_PRIORITY_PKT_TYPE(pkt_type);
+}
+
+/**
+ * qdf_nbuf_remove_priority_pkt_type() - Remove the packet type bits
+ *					 from priority
+ * @@nbuf: pointer to network buffer
+ *
+ * Return: none
+ */
+static inline
+void qdf_nbuf_remove_priority_pkt_type(qdf_nbuf_t nbuf)
+{
+	nbuf->priority &= ~QDF_NBUF_PRIORITY_PKT_TYPE_MASK;
+}
+#endif
+
+/**
+ * qdf_nbuf_is_ipv4_v6_pure_tcp_ack() - check if it is pure tcp ack
+ *					without data payload
+ * @buf: Network buffer
+ *
+ * Check whether the packet is pure TCP ack without data payload.
+ *
+ * Return : true if TCP ack, else return false
+ */
+static inline
+bool qdf_nbuf_is_ipv4_v6_pure_tcp_ack(qdf_nbuf_t buf)
+{
+	return __qdf_nbuf_is_ipv4_v6_pure_tcp_ack(buf);
+}
+
 /**
  * qdf_nbuf_is_arp_local() - check if it is local or no local arp
  * @buf: Network buffer

+ 2 - 0
qdf/linux/src/i_qdf_nbuf.h

@@ -91,6 +91,7 @@ typedef struct skb_shared_info *__qdf_nbuf_shared_info_t;
 #define QDF_NBUF_CB_PACKET_TYPE_ICMPv6 6
 #define QDF_NBUF_CB_PACKET_TYPE_DHCPV6 7
 #define QDF_NBUF_CB_PACKET_TYPE_END_INDICATION 8
+#define QDF_NBUF_CB_PACKET_TYPE_TCP_ACK 9
 
 #define RADIOTAP_BASE_HEADER_LEN sizeof(struct ieee80211_radiotap_header)
 
@@ -961,6 +962,7 @@ uint8_t __qdf_nbuf_data_get_ipv6_tc(uint8_t *data);
 void __qdf_nbuf_data_set_ipv4_tos(uint8_t *data, uint8_t tos);
 void __qdf_nbuf_data_set_ipv6_tc(uint8_t *data, uint8_t tc);
 bool __qdf_nbuf_is_ipv4_last_fragment(struct sk_buff *skb);
+bool __qdf_nbuf_is_ipv4_v6_pure_tcp_ack(struct sk_buff *skb);
 
 #ifdef QDF_NBUF_GLOBAL_COUNT
 int __qdf_nbuf_count_get(void);

+ 74 - 0
qdf/linux/src/qdf_nbuf.c

@@ -3102,6 +3102,80 @@ bool __qdf_nbuf_is_arp_local(struct sk_buff *skb)
 	return false;
 }
 
+/**
+ * __qdf_nbuf_data_get_tcp_hdr_len() - get TCP header length
+ * @data: pointer to data of network buffer
+ * @tcp_hdr_len_offset: bytes offset for tcp header length of ethernet packets
+ *
+ * Return: TCP header length in unit of byte
+ */
+static inline
+uint8_t __qdf_nbuf_data_get_tcp_hdr_len(uint8_t *data,
+					uint8_t tcp_hdr_len_offset)
+{
+	uint8_t tcp_hdr_len;
+
+	tcp_hdr_len =
+		*((uint8_t *)(data + tcp_hdr_len_offset));
+
+	tcp_hdr_len = ((tcp_hdr_len & QDF_NBUF_PKT_TCP_HDR_LEN_MASK) >>
+		       QDF_NBUF_PKT_TCP_HDR_LEN_LSB) *
+		       QDF_NBUF_PKT_TCP_HDR_LEN_UNIT;
+
+	return tcp_hdr_len;
+}
+
+bool __qdf_nbuf_is_ipv4_v6_pure_tcp_ack(struct sk_buff *skb)
+{
+	bool is_tcp_ack = false;
+	uint8_t op_code, tcp_hdr_len;
+	uint16_t ip_payload_len;
+	uint8_t *data = skb->data;
+
+	/*
+	 * If packet length > TCP ACK max length or it's nonlinearized,
+	 * then it must not be TCP ACK.
+	 */
+	if (qdf_nbuf_len(skb) > QDF_NBUF_PKT_TCP_ACK_MAX_LEN ||
+	    qdf_nbuf_is_nonlinear(skb))
+		return false;
+
+	if (qdf_nbuf_is_ipv4_tcp_pkt(skb)) {
+		ip_payload_len =
+			QDF_SWAP_U16(*((uint16_t *)(data +
+				     QDF_NBUF_TRAC_IPV4_TOTAL_LEN_OFFSET)))
+					- QDF_NBUF_TRAC_IPV4_HEADER_SIZE;
+
+		tcp_hdr_len = __qdf_nbuf_data_get_tcp_hdr_len(
+					data,
+					QDF_NBUF_PKT_IPV4_TCP_HDR_LEN_OFFSET);
+
+		op_code = (uint8_t)(*(uint8_t *)(data +
+				QDF_NBUF_PKT_IPV4_TCP_OPCODE_OFFSET));
+
+		if (ip_payload_len == tcp_hdr_len &&
+		    op_code == QDF_NBUF_PKT_TCPOP_ACK)
+			is_tcp_ack = true;
+
+	} else if (qdf_nbuf_is_ipv6_tcp_pkt(skb)) {
+		ip_payload_len =
+			QDF_SWAP_U16(*((uint16_t *)(data +
+				QDF_NBUF_TRAC_IPV6_PAYLOAD_LEN_OFFSET)));
+
+		tcp_hdr_len = __qdf_nbuf_data_get_tcp_hdr_len(
+					data,
+					QDF_NBUF_PKT_IPV6_TCP_HDR_LEN_OFFSET);
+		op_code = (uint8_t)(*(uint8_t *)(data +
+				QDF_NBUF_PKT_IPV6_TCP_OPCODE_OFFSET));
+
+		if (ip_payload_len == tcp_hdr_len &&
+		    op_code == QDF_NBUF_PKT_TCPOP_ACK)
+			is_tcp_ack = true;
+	}
+
+	return is_tcp_ack;
+}
+
 #ifdef NBUF_MEMORY_DEBUG
 
 static spinlock_t g_qdf_net_buf_track_lock[QDF_NET_BUF_TRACK_MAX_SIZE];

+ 23 - 1
wlan_cfg/cfg_dp.h

@@ -1813,6 +1813,27 @@
 	CFG_INI_BOOL("host_ast_db_enable", false, \
 	"Host AST entries database Enable/Disable")
 
+#ifdef DP_TX_PACKET_INSPECT_FOR_ILP
+/*
+ * <ini>
+ * TX packet inspect for ILP - Enable/Disable
+ *
+ * @Default: true
+ *
+ * This ini enable/disables TX packet inspection for ILP feature
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_TX_PKT_INSPECT_FOR_ILP \
+	CFG_INI_BOOL("tx_pkt_inspect_for_ilp", true, \
+	"TX packet inspect for ILP")
+#define CFG_TX_PKT_INSPECT_FOR_ILP_CFG CFG(CFG_TX_PKT_INSPECT_FOR_ILP)
+#else
+#define CFG_TX_PKT_INSPECT_FOR_ILP_CFG
+#endif
+
 #define CFG_DP \
 		CFG(CFG_DP_HTT_PACKET_TYPE) \
 		CFG(CFG_DP_INT_BATCH_THRESHOLD_OTHER) \
@@ -1934,5 +1955,6 @@
 		CFG(CFG_DP_HOST_AST_DB_ENABLE) \
 		CFG_DP_SAWF_STATS_CONFIG \
 		CFG(CFG_DP_HANDLE_INVALID_DECAP_TYPE_DISABLE) \
-		CFG(CFG_DP_TXMON_SW_PEER_FILTERING)
+		CFG(CFG_DP_TXMON_SW_PEER_FILTERING) \
+		CFG_TX_PKT_INSPECT_FOR_ILP_CFG
 #endif /* _CFG_DP_H_ */

+ 26 - 1
wlan_cfg/wlan_cfg.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. 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
@@ -2835,6 +2835,29 @@ void wlan_cfg_set_sawf_stats_config(struct wlan_cfg_dp_soc_ctxt *cfg,
 }
 #endif /* CONFIG_SAWF_STATS */
 
+#ifdef DP_TX_PACKET_INSPECT_FOR_ILP
+/**
+ * wlan_soc_tx_packet_inspect_attach() - Update TX packet inspection config
+ * @psoc: object manager psoc
+ * @wlan_cfg_ctx: dp soc cfg ctx
+ *
+ * Return: None
+ */
+static void
+wlan_soc_tx_packet_inspect_attach(struct cdp_ctrl_objmgr_psoc *psoc,
+				  struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx)
+{
+	wlan_cfg_ctx->tx_pkt_inspect_for_ilp =
+			cfg_get(psoc, CFG_TX_PKT_INSPECT_FOR_ILP);
+}
+#else
+static void
+wlan_soc_tx_packet_inspect_attach(struct cdp_ctrl_objmgr_psoc *psoc,
+				  struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx)
+{
+}
+#endif
+
 struct wlan_cfg_dp_soc_ctxt *
 wlan_cfg_soc_attach(struct cdp_ctrl_objmgr_psoc *psoc)
 {
@@ -3059,6 +3082,8 @@ wlan_cfg_soc_attach(struct cdp_ctrl_objmgr_psoc *psoc)
 			cfg_get(psoc, CFG_DP_HANDLE_INVALID_DECAP_TYPE_DISABLE);
 	wlan_cfg_ctx->txmon_sw_peer_filtering =
 			cfg_get(psoc, CFG_DP_TXMON_SW_PEER_FILTERING);
+	wlan_soc_tx_packet_inspect_attach(psoc, wlan_cfg_ctx);
+
 	return wlan_cfg_ctx;
 }
 

+ 6 - 1
wlan_cfg/wlan_cfg.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. 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
@@ -327,6 +327,8 @@ struct wlan_srng_cfg {
  * @notify_frame_support: flag indicating capability to mark notify frames
  * @is_handle_invalid_decap_type_disabled: flag to indicate if invalid decap
  *                                         type handling is disabled
+ * @tx_pkt_inspect_for_ilp: flag to indicate if TX packet inspection for HW
+ *			    based ILP feature is enabled
  */
 struct wlan_cfg_dp_soc_ctxt {
 	int num_int_ctxts;
@@ -516,6 +518,9 @@ struct wlan_cfg_dp_soc_ctxt {
 	uint8_t napi_scale_factor;
 	uint8_t notify_frame_support;
 	bool is_handle_invalid_decap_type_disabled;
+#ifdef DP_TX_PACKET_INSPECT_FOR_ILP
+	bool tx_pkt_inspect_for_ilp;
+#endif
 };
 
 /**