diff --git a/dp/wifi3.0/be/dp_be_tx.c b/dp/wifi3.0/be/dp_be_tx.c index f5f7c91aff..9045293170 100644 --- a/dp/wifi3.0/be/dp_be_tx.c +++ b/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); diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index e4ca90dfc5..0b3fcb7acc 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/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 diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index d921425673..96b6e34b3d 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/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); diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 35e3de0ff3..4744a17f61 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/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]; diff --git a/wlan_cfg/cfg_dp.h b/wlan_cfg/cfg_dp.h index ec7f545c5b..047c7a6e14 100644 --- a/wlan_cfg/cfg_dp.h +++ b/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 +/* + * + * TX packet inspect for ILP - Enable/Disable + * + * @Default: true + * + * This ini enable/disables TX packet inspection for ILP feature + * + * Usage: Internal + * + * + */ +#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_ */ diff --git a/wlan_cfg/wlan_cfg.c b/wlan_cfg/wlan_cfg.c index b74022642c..06b67d8827 100644 --- a/wlan_cfg/wlan_cfg.c +++ b/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; } diff --git a/wlan_cfg/wlan_cfg.h b/wlan_cfg/wlan_cfg.h index 35d7105616..81dcea39c5 100644 --- a/wlan_cfg/wlan_cfg.h +++ b/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 }; /**