From 9238dbf63c61eca888b45c1243cfb6c550598582 Mon Sep 17 00:00:00 2001 From: Vulupala Shashank Reddy Date: Mon, 13 Sep 2021 11:01:44 +0530 Subject: [PATCH 01/18] qcacmn: Add APIs to get data packets info Add APIs to get TCP fin/fin-ack/rst packets information. Change-Id: Ia1150c81076fa47ae7f34d14bc73efc82003258a CRs-Fixed: 3046235 --- qdf/inc/qdf_nbuf.h | 39 ++++++++++++++++++++++ qdf/linux/src/i_qdf_nbuf.h | 8 +++++ qdf/linux/src/qdf_nbuf.c | 66 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index 05a67bb7b67e..9f2c7871bcf6 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -2952,6 +2952,32 @@ bool qdf_nbuf_data_is_dns_response(qdf_nbuf_t buf) return __qdf_nbuf_data_is_dns_response(qdf_nbuf_data(buf)); } +/** + * qdf_nbuf_data_is_tcp_fin() - check if skb data is a tcp fin + * @buf: buffer + * + * Return: true if packet is tcp fin packet. + * false otherwise. + */ +static inline +bool qdf_nbuf_data_is_tcp_fin(qdf_nbuf_t buf) +{ + return __qdf_nbuf_data_is_tcp_fin(qdf_nbuf_data(buf)); +} + +/** + * qdf_nbuf_data_is_tcp_fin_ack() - check if skb data is a tcp fin ack + * @buf: buffer + * + * Return: true if packet is tcp fin ack packet. + * false otherwise. + */ +static inline +bool qdf_nbuf_data_is_tcp_fin_ack(qdf_nbuf_t buf) +{ + return __qdf_nbuf_data_is_tcp_fin_ack(qdf_nbuf_data(buf)); +} + /** * qdf_nbuf_data_is_tcp_syn() - check if skb data is a tcp syn * @buf: buffer @@ -2978,6 +3004,19 @@ bool qdf_nbuf_data_is_tcp_syn_ack(qdf_nbuf_t buf) return __qdf_nbuf_data_is_tcp_syn_ack(qdf_nbuf_data(buf)); } +/** + * qdf_nbuf_data_is_tcp_rst() - check if skb data is a tcp rst + * @buf: buffer + * + * Return: true if packet is tcp rst packet. + * false otherwise. + */ +static inline +bool qdf_nbuf_data_is_tcp_rst(qdf_nbuf_t buf) +{ + return __qdf_nbuf_data_is_tcp_rst(qdf_nbuf_data(buf)); +} + /** * qdf_nbuf_data_is_tcp_ack() - check if skb data is a tcp ack * @buf: buffer diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index cc049e2a8690..0471fcc41ce9 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -73,6 +73,11 @@ typedef struct sk_buff_head __qdf_nbuf_queue_head_t; /* mark the first packet after wow wakeup */ #define QDF_MARK_FIRST_WAKEUP_PACKET 0x80000000 +/* TCP Related MASK */ +#define QDF_NBUF_PKT_TCPOP_FIN 0x01 +#define QDF_NBUF_PKT_TCPOP_FIN_ACK 0x11 +#define QDF_NBUF_PKT_TCPOP_RST 0x04 + /* * Make sure that qdf_dma_addr_t in the cb block is always 64 bit aligned */ @@ -836,8 +841,11 @@ uint32_t __qdf_nbuf_get_arp_tgt_ip(uint8_t *data); uint8_t *__qdf_nbuf_get_dns_domain_name(uint8_t *data, uint32_t len); bool __qdf_nbuf_data_is_dns_query(uint8_t *data); bool __qdf_nbuf_data_is_dns_response(uint8_t *data); +bool __qdf_nbuf_data_is_tcp_fin(uint8_t *data); +bool __qdf_nbuf_data_is_tcp_fin_ack(uint8_t *data); bool __qdf_nbuf_data_is_tcp_syn(uint8_t *data); bool __qdf_nbuf_data_is_tcp_syn_ack(uint8_t *data); +bool __qdf_nbuf_data_is_tcp_rst(uint8_t *data); bool __qdf_nbuf_data_is_tcp_ack(uint8_t *data); uint16_t __qdf_nbuf_data_get_tcp_src_port(uint8_t *data); uint16_t __qdf_nbuf_data_get_tcp_dst_port(uint8_t *data); diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index f7963e010eb7..4821a4052240 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -1725,6 +1725,50 @@ bool __qdf_nbuf_data_is_dns_response(uint8_t *data) return false; } +/** + * __qdf_nbuf_data_is_tcp_fin() - check if skb data is a tcp fin + * @data: Pointer to network data buffer + * + * This api is to check if the packet is tcp fin. + * + * Return: true if packet is tcp fin packet. + * false otherwise. + */ +bool __qdf_nbuf_data_is_tcp_fin(uint8_t *data) +{ + uint8_t op_code; + + op_code = (uint8_t)(*(uint8_t *)(data + + QDF_NBUF_PKT_TCP_OPCODE_OFFSET)); + + if (op_code == QDF_NBUF_PKT_TCPOP_FIN) + return true; + + return false; +} + +/** + * __qdf_nbuf_data_is_tcp_fin_ack() - check if skb data is a tcp fin ack + * @data: Pointer to network data buffer + * + * This api is to check if the tcp packet is fin ack. + * + * Return: true if packet is tcp fin ack packet. + * false otherwise. + */ +bool __qdf_nbuf_data_is_tcp_fin_ack(uint8_t *data) +{ + uint8_t op_code; + + op_code = (uint8_t)(*(uint8_t *)(data + + QDF_NBUF_PKT_TCP_OPCODE_OFFSET)); + + if (op_code == QDF_NBUF_PKT_TCPOP_FIN_ACK) + return true; + + return false; +} + /** * __qdf_nbuf_data_is_tcp_syn() - check if skb data is a tcp syn * @data: Pointer to network data buffer @@ -1767,6 +1811,28 @@ bool __qdf_nbuf_data_is_tcp_syn_ack(uint8_t *data) return false; } +/** + * __qdf_nbuf_data_is_tcp_rst() - check if skb data is a tcp rst + * @data: Pointer to network data buffer + * + * This api is to check if the tcp packet is rst. + * + * Return: true if packet is tcp rst packet. + * false otherwise. + */ +bool __qdf_nbuf_data_is_tcp_rst(uint8_t *data) +{ + uint8_t op_code; + + op_code = (uint8_t)(*(uint8_t *)(data + + QDF_NBUF_PKT_TCP_OPCODE_OFFSET)); + + if (op_code == QDF_NBUF_PKT_TCPOP_RST) + return true; + + return false; +} + /** * __qdf_nbuf_data_is_tcp_ack() - check if skb data is a tcp ack * @data: Pointer to network data buffer From 854f611aa4f39ae6340a181aa399d9bdf7bc29be Mon Sep 17 00:00:00 2001 From: Balaji Pothunoori Date: Mon, 4 Oct 2021 17:20:16 +0530 Subject: [PATCH 02/18] qcacmn: add vendor command to configure the parameters for monitor mode Add new vendor command to configure monitor mode packet filter parameters which includes data/mgmt/ctrl frame types. Change-Id: Ie5e5d35b725e3d1b617edc1c889dc269b22a3673 CRs-Fixed: 3025489 --- os_if/linux/qca_vendor.h | 136 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/os_if/linux/qca_vendor.h b/os_if/linux/qca_vendor.h index d3b91124e082..6e816b8afa89 100644 --- a/os_if/linux/qca_vendor.h +++ b/os_if/linux/qca_vendor.h @@ -475,6 +475,29 @@ * configurations, concurrency combinations, etc. The attributes used * with this command are defined in * enum qca_wlan_vendor_attr_usable_channels. + * + * @QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE: This vendor subcommand is used + * to set packet monitor mode that aims to send the specified set of TX and + * RX frames on the current client interface to an active monitor interface. + * If this Monitor mode is set, the driver will send the configured frames, + * from the interface on which the command is issued, to an active monitor + * interface. The attributes used with this command are defined in + * enum qca_wlan_vendor_attr_set_monitor_mode. + * + * Though the monitor mode is configured for the respective data/mgmt/ctrl + * frames, it is up to the respective WLAN driver/firmware/hardware designs + * to consider the possibility of sending these frames over the monitor + * interface. For example, the control frames are handled with in the + * hardware and thus passing such frames over the monitor interface is left + * to the respective designs. + * + * Also, this monitor mode is governed to behave accordingly in + * suspend/resume states. If the firmware handles any of such frames + * in suspend state without waking up the host and if the monitor mode + * is configured to notify all such frames, then the firmware is expected + * to resume the host and forward the respective frames to the monitor + * interface. Please note that such a request to get the frames over the + * monitor interface will have a definite power implications. */ enum qca_nl80211_vendor_subcmds { @@ -708,6 +731,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196, QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY = 197, QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198, + QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202, }; enum qca_wlan_vendor_tos { @@ -11014,4 +11038,116 @@ enum qca_wlan_vendor_attr_usable_channels { QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST - 1, }; +/** + * qca_wlan_vendor_monitor_data_frame_type - Represent the various + * data types to be sent over the monitor interface. + */ +enum qca_wlan_vendor_monitor_data_frame_type { + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL = BIT(0), + + /* valid only if QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL is + not set */ + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ARP = BIT(1), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV4 = BIT(2), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV6 = BIT(3), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_EAPOL = BIT(4), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV4 = BIT(5), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV6 = BIT(6), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYN = BIT(7), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FIN = BIT(9), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FINACK = BIT(10), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_ACK = BIT(11), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_RST = BIT(12), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV4 = BIT(13), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV6 = BIT(14), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_RTP = BIT(15), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_SIP = BIT(16), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_QOS_NULL = BIT(17), +}; + +/** + * qca_wlan_vendor_monitor_mgmt_frame_type - Represent the various + * mgmt types to be sent over the monitor interface. + * @QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL: All the MGMT Frames. + * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON: All the MGMT Frames + * except the Beacons. Valid only in the Connect state. + * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON: Only the connected + * BSSID Beacons. Valid only in the Connect state. + * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents + * the Beacons obtained during the scan (off channel and connected channel) + * when in connected state. + */ + +enum qca_wlan_vendor_monitor_mgmt_frame_type { + QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0), + /* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set */ + QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON = BIT(1), + QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON = BIT(2), + QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON = BIT(3), +}; + +/** + * qca_wlan_vendor_monitor_ctrl_frame_type - Represent the various + * ctrl types to be sent over the monitor interface. + * @QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL: All the ctrl Frames. + * @QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME: Trigger Frame. + */ +enum qca_wlan_vendor_monitor_ctrl_frame_type { + QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL = BIT(0), + /* valid only if QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL is not set */ + QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME = BIT(1), +}; + +/** + * enum qca_wlan_vendor_attr_set_monitor_mode - Used by the + * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the + * monitor mode. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These data packets + * are represented by enum qca_wlan_vendor_monitor_data_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These data packets + * are represented by enum qca_wlan_vendor_monitor_data_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These mgmt packets + * are represented by enum qca_wlan_vendor_monitor_mgmt_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These mgmt packets + * are represented by enum qca_wlan_vendor_monitor_mgmt_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These ctrl packets + * are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These ctrl packets + * are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: + * u32 attribute, An interval only for the connected beacon interval, which + * expects that the connected BSSID's beacons shall be sent on the monitor + * interface only on this specific interval. + */ +enum qca_wlan_vendor_attr_set_monitor_mode { + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX = + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1, + +}; + #endif From e23020bd46d67146b3dcfbc24ff64249d2e03909 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Wed, 29 Sep 2021 18:05:28 +0530 Subject: [PATCH 03/18] qcacmn: Add cdp api to update the packet capture mode Add a CDP api to update the packet capture mode in dp_soc when it get updated by user using vendor command. Change-Id: Id0856aeeb5e1a77e1ce6fb23562fdbff4a2fb320 CRs-Fixed: 3048344 --- dp/inc/cdp_txrx_cmn.h | 29 +++++++++++++++++++++++++++++ dp/inc/cdp_txrx_ops.h | 3 +++ dp/wifi3.0/dp_main.c | 13 +++++++++++++ 3 files changed, 45 insertions(+) diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 3fc8d89427dc..620513343129 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -2730,4 +2730,33 @@ cdp_drain_txrx(ol_txrx_soc_handle soc) return soc->ops->cmn_drv_ops->txrx_drain(soc); } + +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 +/** + * cdp_set_pkt_capture_mode() - set pkt capture mode in dp ctx + * @soc: opaque soc handle + * @val: value to be set + */ +static inline void +cdp_set_pkt_capture_mode(ol_txrx_soc_handle soc, bool val) +{ + 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->cmn_drv_ops || + !soc->ops->cmn_drv_ops->set_pkt_capture_mode) + return; + + soc->ops->cmn_drv_ops->set_pkt_capture_mode(soc, val); +} +#else +static inline void +cdp_set_pkt_capture_mode(ol_txrx_soc_handle soc, bool val) +{ +} +#endif #endif /* _CDP_TXRX_CMN_H_ */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 93789956bb51..921876d0a690 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -578,6 +578,9 @@ struct cdp_cmn_ops { ol_osif_peer_handle osif_peer); #endif /* QCA_SUPPORT_WDS_EXTENDED */ void (*txrx_drain)(ol_txrx_soc_handle soc); +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 + void (*set_pkt_capture_mode)(struct cdp_soc_t *soc, bool val); +#endif }; struct cdp_ctrl_ops { diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index c1615ed0da86..4c6578961d33 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -11294,6 +11294,16 @@ static void dp_drain_txrx(struct cdp_soc_t *soc_handle) } #endif +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 +static void +dp_set_pkt_capture_mode(struct cdp_soc_t *soc_handle, bool val) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + + soc->wlan_cfg_ctx->pkt_capture_mode = val; +} +#endif + static struct cdp_cmn_ops dp_ops_cmn = { .txrx_soc_attach_target = dp_soc_attach_target_wifi3, .txrx_vdev_attach = dp_vdev_attach_wifi3, @@ -11396,6 +11406,9 @@ static struct cdp_cmn_ops dp_ops_cmn = { #if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE) .txrx_drain = dp_drain_txrx, #endif +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 + .set_pkt_capture_mode = dp_set_pkt_capture_mode, +#endif }; static struct cdp_ctrl_ops dp_ops_ctrl = { From 796b48ae0bd63e1cfc5a7f758526449fd8f856e9 Mon Sep 17 00:00:00 2001 From: Amit Mehta Date: Wed, 6 Oct 2021 17:16:17 +0530 Subject: [PATCH 04/18] qcacmn: Ring History Display update TP and HP values are assigned wrongly while printing ring history. Fixing assignment. Change-Id: I50ea90a3b49ab4d5459a3e0ddfa259f669764433 CRs-Fixed: 3051531 --- dp/wifi3.0/dp_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 4c6578961d33..b9f1537f81dc 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -10495,27 +10495,27 @@ static void dp_display_srng_info(struct cdp_soc_t *soc_hdl) dp_info("SRNG HP-TP data:"); for (i = 0; i < soc->num_tcl_data_rings; i++) { hal_get_sw_hptp(hal_soc, soc->tcl_data_ring[i].hal_srng, - &hp, &tp); + &tp, &hp); dp_info("TCL DATA ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp); hal_get_sw_hptp(hal_soc, soc->tx_comp_ring[i].hal_srng, - &hp, &tp); + &tp, &hp); dp_info("TX comp ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp); } for (i = 0; i < soc->num_reo_dest_rings; i++) { hal_get_sw_hptp(hal_soc, soc->reo_dest_ring[i].hal_srng, - &hp, &tp); + &tp, &hp); dp_info("REO DST ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp); } - hal_get_sw_hptp(hal_soc, soc->reo_exception_ring.hal_srng, &hp, &tp); + hal_get_sw_hptp(hal_soc, soc->reo_exception_ring.hal_srng, &tp, &hp); dp_info("REO exception ring: hp=0x%x, tp=0x%x", hp, tp); - hal_get_sw_hptp(hal_soc, soc->rx_rel_ring.hal_srng, &hp, &tp); + hal_get_sw_hptp(hal_soc, soc->rx_rel_ring.hal_srng, &tp, &hp); dp_info("WBM RX release ring: hp=0x%x, tp=0x%x", hp, tp); - hal_get_sw_hptp(hal_soc, soc->wbm_desc_rel_ring.hal_srng, &hp, &tp); + hal_get_sw_hptp(hal_soc, soc->wbm_desc_rel_ring.hal_srng, &tp, &hp); dp_info("WBM desc release ring: hp=0x%x, tp=0x%x", hp, tp); } From 92c8c2bb8482435675f4dc2ed196f46daddfa72b Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Wed, 13 Oct 2021 04:17:50 +0800 Subject: [PATCH 05/18] qcacmn: Check function pointer to avoid NULL point dereference It calls spectral_process_phyerr of spectral operations without any check. Which cause null point dereference potentially. So, check this pointer before calling. Change-Id: Iae246f847dd41e62b628223652a9527a65b43799 CRs-Fixed: 3055246 --- target_if/spectral/target_if_spectral.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target_if/spectral/target_if_spectral.h b/target_if/spectral/target_if_spectral.h index 1ff8609ee436..3add3240564c 100644 --- a/target_if/spectral/target_if_spectral.h +++ b/target_if/spectral/target_if_spectral.h @@ -1732,6 +1732,10 @@ void target_if_spectral_process_phyerr( } p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (!p_sops->spectral_process_phyerr) { + spectral_err("null spectral_process_phyerr"); + return; + } p_sops->spectral_process_phyerr(spectral, data, datalen, p_rfqual, p_chaninfo, tsf64, acs_stats); From f2b85f4201e865cd97811f20874f5ac9bf9a0ebd Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Fri, 3 Sep 2021 00:25:41 +0530 Subject: [PATCH 06/18] qcacmn: Validate SSID first while fetching peer pmksa Validate the SSID & cache ID if SSID length is present in the pmksa entry, as in FILS case only SSID and cache id are filled and BSSID is not filled. So validate the BSSID only if the SSID is not present. Change-Id: Ia0a31f953869f00495fad597bb564ec706425312 CRs-Fixed: 3051530 --- .../crypto/src/wlan_crypto_global_api.c | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index fd847dbe18b9..72649ff046a2 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -370,7 +370,8 @@ QDF_STATUS wlan_crypto_set_pmksa(struct wlan_crypto_params *crypto_params, return QDF_STATUS_E_INVAL; } crypto_params->pmksa[first_available_slot] = pmksa; - crypto_debug("PMKSA: Added the PMKSA entry at index=%d", i); + crypto_debug("PMKSA: Added the PMKSA entry at index=%d", + first_available_slot); return QDF_STATUS_SUCCESS; } @@ -379,7 +380,7 @@ static QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, struct wlan_crypto_pmksa *pmksa) { - uint8_t i, j; + uint8_t i, j, valid_entries_in_table = 0; bool match_found = false; u8 del_pmk[MAX_PMK_LEN] = {0}; @@ -387,7 +388,12 @@ QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) { if (!crypto_params->pmksa[i]) continue; - if (qdf_is_macaddr_equal(&pmksa->bssid, + + valid_entries_in_table++; + + if (!pmksa->ssid_len && + !qdf_is_macaddr_zero(&pmksa->bssid) && + qdf_is_macaddr_equal(&pmksa->bssid, &crypto_params->pmksa[i]->bssid)) { match_found = true; } else if (pmksa->ssid_len && @@ -435,7 +441,8 @@ QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, } if (i == WLAN_CRYPTO_MAX_PMKID && !match_found) - crypto_debug("No such pmksa entry exists"); + crypto_debug("No such pmksa entry exists: valid entries:%d", + valid_entries_in_table); return QDF_STATUS_SUCCESS; } @@ -453,6 +460,8 @@ QDF_STATUS wlan_crypto_pmksa_flush(struct wlan_crypto_params *crypto_params) crypto_params->pmksa[i] = NULL; } + crypto_debug("Flushed the pmksa table"); + return QDF_STATUS_SUCCESS; } @@ -607,16 +616,19 @@ wlan_crypto_get_peer_pmksa(struct wlan_objmgr_vdev *vdev, for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) { if (!crypto_params->pmksa[i]) continue; - if (qdf_is_macaddr_equal(&pmksa->bssid, - &crypto_params->pmksa[i]->bssid)) { + + if (pmksa->ssid_len && + !qdf_mem_cmp(pmksa->ssid, + crypto_params->pmksa[i]->ssid, + pmksa->ssid_len) && + !qdf_mem_cmp(pmksa->cache_id, + crypto_params->pmksa[i]->cache_id, + WLAN_CACHE_ID_LEN)) { return crypto_params->pmksa[i]; - } else if (pmksa->ssid_len && - !qdf_mem_cmp(pmksa->ssid, - crypto_params->pmksa[i]->ssid, - pmksa->ssid_len) && - !qdf_mem_cmp(pmksa->cache_id, - crypto_params->pmksa[i]->cache_id, - WLAN_CACHE_ID_LEN)){ + } else if (!pmksa->ssid_len && + !qdf_is_macaddr_zero(&pmksa->bssid) && + qdf_is_macaddr_equal(&pmksa->bssid, + &crypto_params->pmksa[i]->bssid)) { return crypto_params->pmksa[i]; } } From 294e63f9872dd41060a6c198bb6edf638e02d6ce Mon Sep 17 00:00:00 2001 From: Vevek Venkatesan Date: Wed, 13 Oct 2021 17:48:45 +0530 Subject: [PATCH 07/18] qcacmn: cleanup FEATURE_HAL_DELAYED_REG_WRITE_V2 support This FEATURE_HAL_DELAYED_REG_WRITE_V2 was added to fix the Audio jank issue, but it could not resolve it completely, so that was later fixed by existing delayed reg write support with the help of SMP2P messages to communicate with FW regarding PCIe link status. This code is not being used, so removing it and cleaning up the redundant code. Change-Id: Iada088e72a76b4c071c8a80ee945f36ac959670e CRs-Fixed: 3056475 --- hal/wifi3.0/hal_api.h | 6 +- hal/wifi3.0/hal_internal.h | 48 +--- hal/wifi3.0/hal_srng.c | 461 +------------------------------------ 3 files changed, 9 insertions(+), 506 deletions(-) diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 5910bd795b12..a07ffc269803 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -455,8 +455,7 @@ static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc, { qdf_iowrite32(addr, value); } -#elif defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#elif defined(FEATURE_HAL_DELAYED_REG_WRITE) static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc, struct hal_srng *srng, void __iomem *addr, @@ -778,8 +777,7 @@ static inline void hal_write32_mb_confirm_retry(struct hal_soc *hal_soc, } #endif /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */ -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_dump_reg_write_srng_stats() - dump SRNG reg write stats * @hal_soc: HAL soc handle diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index a8857c89c96e..e1aec3aa0d18 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021 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 @@ -25,8 +25,7 @@ #include "qdf_mem.h" #include "qdf_nbuf.h" #include "pld_common.h" -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) #include "qdf_defer.h" #include "qdf_timer.h" #endif @@ -259,8 +258,7 @@ typedef struct hal_ring_handle *hal_ring_handle_t; */ #define HAL_SRNG_FLUSH_EVENT BIT(0) -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * struct hal_reg_write_q_elem - delayed register write queue element @@ -339,21 +337,6 @@ struct hal_reg_write_soc_stats { uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; uint32_t dequeue_delay; }; - -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -struct hal_reg_write_tcl_stats { - uint32_t wq_delayed; - uint32_t wq_direct; - uint32_t timer_enq; - uint32_t timer_direct; - uint32_t enq_timer_set; - uint32_t direct_timer_set; - uint32_t timer_reset; - qdf_time_t enq_time; - qdf_time_t deq_time; - uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; -}; -#endif #endif /* Common SRNG ring structure for source and destination rings */ @@ -476,10 +459,7 @@ struct hal_srng { /* last ring desc entry cleared */ uint32_t last_desc_cleared; #endif -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) - /* Previous hp/tp (based on ring dir) value written to the reg */ - uint32_t last_reg_wr_val; +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /* flag to indicate whether srng is already queued for delayed write */ uint8_t reg_write_in_progress; /* last dequeue elem time stamp */ @@ -718,8 +698,7 @@ struct hal_hw_txrx_ops { */ struct hal_soc_stats { uint32_t reg_write_fail; -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) struct hal_reg_write_soc_stats wstats; #endif #ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE @@ -835,20 +814,6 @@ struct hal_soc { /* read index used by worker thread to dequeue/write registers */ uint32_t read_idx; #endif /*FEATURE_HAL_DELAYED_REG_WRITE */ -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 - /* delayed work for TCL reg write to be queued into workqueue */ - qdf_work_t tcl_reg_write_work; - /* workqueue for TCL delayed register writes */ - qdf_workqueue_t *tcl_reg_write_wq; - /* flag denotes whether TCL delayed write work is active */ - qdf_atomic_t tcl_work_active; - /* flag indiactes TCL write happening from direct context */ - bool tcl_direct; - /* timer to handle the pending TCL reg writes */ - qdf_timer_t tcl_reg_write_timer; - /* stats related to TCL reg write */ - struct hal_reg_write_tcl_stats tcl_stats; -#endif /* FEATURE_HAL_DELAYED_REG_WRITE_V2 */ qdf_atomic_t active_work_cnt; #ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE struct shadow_reg_config @@ -857,8 +822,7 @@ struct hal_soc { #endif }; -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_delayed_reg_write() - delayed regiter write * @hal_soc: HAL soc handle diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 0f76e4a5ff7e..7396981bd295 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -446,8 +446,7 @@ uint32_t hal_get_target_type(hal_soc_handle_t hal_soc_hdl) qdf_export_symbol(hal_get_target_type); -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_is_reg_write_tput_level_high() - throughput level for delayed reg writes * @hal: hal_soc pointer @@ -501,41 +500,6 @@ void hal_dump_reg_write_srng_stats(hal_soc_handle_t hal_soc_hdl) hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf))); } -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -/** - * hal_dump_tcl_stats() - dump the TCL reg write stats - * @hal: hal_soc pointer - * - * Return: None - */ -static inline void hal_dump_tcl_stats(struct hal_soc *hal) -{ - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - uint32_t *hist = hal->tcl_stats.sched_delay; - char buf[HAL_REG_WRITE_SRNG_STATS_LEN]; - - hal_debug("TCL: %s sched-delay hist %u %u %u %u", - hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf)), - hist[REG_WRITE_SCHED_DELAY_SUB_100us], - hist[REG_WRITE_SCHED_DELAY_SUB_1000us], - hist[REG_WRITE_SCHED_DELAY_SUB_5000us], - hist[REG_WRITE_SCHED_DELAY_GT_5000us]); - hal_debug("wq_dly %u wq_dir %u tim_enq %u tim_dir %u enq_tim_cnt %u dir_tim_cnt %u rst_tim_cnt %u", - hal->tcl_stats.wq_delayed, - hal->tcl_stats.wq_direct, - hal->tcl_stats.timer_enq, - hal->tcl_stats.timer_direct, - hal->tcl_stats.enq_timer_set, - hal->tcl_stats.direct_timer_set, - hal->tcl_stats.timer_reset); -} - -#else -static inline void hal_dump_tcl_stats(struct hal_soc *hal) -{ -} -#endif - void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl) { uint32_t *hist; @@ -553,8 +517,6 @@ void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl) hist[REG_WRITE_SCHED_DELAY_SUB_1000us], hist[REG_WRITE_SCHED_DELAY_SUB_5000us], hist[REG_WRITE_SCHED_DELAY_GT_5000us]); - - hal_dump_tcl_stats(hal); } int hal_get_reg_write_pending_work(void *hal_soc) @@ -577,46 +539,6 @@ int hal_get_reg_write_pending_work(void *hal_soc) #define HAL_REG_WRITE_QUEUE_LEN 32 #endif -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -/** - * hal_process_reg_write_q_elem() - process a regiter write queue element - * @hal: hal_soc pointer - * @q_elem: pointer to hal regiter write queue element - * - * Return: The value which was written to the address - */ -static uint32_t -hal_process_reg_write_q_elem(struct hal_soc *hal, - struct hal_reg_write_q_elem *q_elem) -{ - struct hal_srng *srng = q_elem->srng; - uint32_t write_val; - - SRNG_LOCK(&srng->lock); - srng->reg_write_in_progress = false; - srng->wstats.dequeues++; - - if (srng->ring_dir == HAL_SRNG_SRC_RING) { - write_val = srng->u.src_ring.hp; - q_elem->dequeue_val = write_val; - q_elem->valid = 0; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, - srng->u.src_ring.hp_addr, - write_val, false); - } else { - write_val = srng->u.dst_ring.tp; - q_elem->dequeue_val = write_val; - q_elem->valid = 0; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, - srng->u.dst_ring.tp_addr, - write_val, false); - } - - return write_val; -} -#else /** * hal_process_reg_write_q_elem() - process a regiter write queue element * @hal: hal_soc pointer @@ -656,7 +578,6 @@ hal_process_reg_write_q_elem(struct hal_soc *hal, return write_val; } -#endif /** * hal_reg_write_fill_sched_delay_hist() - fill reg write delay histogram in hal @@ -962,383 +883,6 @@ static inline void hal_delayed_reg_write_deinit(struct hal_soc *hal) } #endif -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -#ifdef MEMORY_DEBUG -/** - * hal_reg_write_get_timestamp() - Function to get the timestamp - * - * Return: return present simestamp - */ -static inline qdf_time_t hal_del_reg_write_get_ts(void) -{ - return qdf_get_log_timestamp(); -} - -/** - * hal_del_reg_write_ts_usecs() - Convert the timestamp to micro secs - * @ts: timestamp value to be converted - * - * Return: return the timestamp in micro secs - */ -static inline qdf_time_t hal_del_reg_write_ts_usecs(qdf_time_t ts) -{ - return qdf_log_timestamp_to_usecs(ts); -} - -/** - * hal_tcl_write_fill_sched_delay_hist() - fill TCL reg write delay histogram - * @hal: hal_soc pointer - * @delay: delay in us - * - * Return: None - */ -static inline void hal_tcl_write_fill_sched_delay_hist(struct hal_soc *hal) -{ - uint32_t *hist; - uint32_t delay_us; - - hal->tcl_stats.deq_time = hal_del_reg_write_get_ts(); - delay_us = hal_del_reg_write_ts_usecs(hal->tcl_stats.deq_time - - hal->tcl_stats.enq_time); - - hist = hal->tcl_stats.sched_delay; - if (delay_us < 100) - hist[REG_WRITE_SCHED_DELAY_SUB_100us]++; - else if (delay_us < 1000) - hist[REG_WRITE_SCHED_DELAY_SUB_1000us]++; - else if (delay_us < 5000) - hist[REG_WRITE_SCHED_DELAY_SUB_5000us]++; - else - hist[REG_WRITE_SCHED_DELAY_GT_5000us]++; -} - -#else -static inline qdf_time_t hal_del_reg_write_get_ts(void) -{ - return 0; -} - -static inline qdf_time_t hal_del_reg_write_ts_usecs(qdf_time_t ts) -{ - return 0; -} - -static inline void hal_tcl_write_fill_sched_delay_hist(struct hal_soc *hal) -{ -} -#endif - -/** - * hal_tcl_reg_write_work() - Worker to process delayed SW2TCL1 writes - * @arg: hal_soc pointer - * - * Return: None - */ -static void hal_tcl_reg_write_work(void *arg) -{ - struct hal_soc *hal = arg; - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - - SRNG_LOCK(&srng->lock); - srng->wstats.dequeues++; - hal_tcl_write_fill_sched_delay_hist(hal); - - /* - * During the tranition of low to high tput scenario, reg write moves - * from delayed to direct write context, there is a little chance that - * worker thread gets scheduled later than direct context write which - * already wrote the latest HP value. This check can catch that case - * and avoid the repetitive writing of the same HP value. - */ - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - srng->last_reg_wr_val = srng->u.src_ring.hp; - if (hal->tcl_direct) { - /* - * TCL reg writes have been moved to direct context and - * the assumption is that PCIe bus stays in Active state - * during high tput, hence its fine to write the HP - * while the SRNG_LOCK is being held. - */ - hal->tcl_stats.wq_direct++; - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - } else { - /* - * TCL reg write to happen in delayed context, - * write operation might take time due to possibility of - * PCIe bus stays in low power state during low tput, - * Hence release the SRNG_LOCK before writing. - */ - hal->tcl_stats.wq_delayed++; - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - } - } else { - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - } - - /* - * Decrement active_work_cnt to make sure that hif_try_complete_tasks - * will wait. This will avoid race condition between delayed register - * worker and bus suspend (system suspend or runtime suspend). - * - * The following decrement should be done at the end! - */ - qdf_atomic_dec(&hal->active_work_cnt); - qdf_atomic_set(&hal->tcl_work_active, false); -} - -static void __hal_flush_tcl_reg_write_work(struct hal_soc *hal) -{ - qdf_cancel_work(&hal->tcl_reg_write_work); -} - -/** - * hal_tcl_reg_write_enqueue() - enqueue TCL register writes into kworker - * @hal_soc: hal_soc pointer - * @srng: srng pointer - * @addr: iomem address of regiter - * @value: value to be written to iomem address - * - * This function executes from within the SRNG LOCK - * - * Return: None - */ -static void hal_tcl_reg_write_enqueue(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - hal_soc->tcl_stats.enq_time = hal_del_reg_write_get_ts(); - - if (qdf_queue_work(hal_soc->qdf_dev, hal_soc->tcl_reg_write_wq, - &hal_soc->tcl_reg_write_work)) { - srng->reg_write_in_progress = true; - qdf_atomic_inc(&hal_soc->active_work_cnt); - qdf_atomic_set(&hal_soc->tcl_work_active, true); - srng->wstats.enqueues++; - } else { - hal_soc->tcl_stats.enq_timer_set++; - qdf_timer_mod(&hal_soc->tcl_reg_write_timer, 1); - } -} - -/** - * hal_tcl_reg_write_timer() - timer handler to take care of pending TCL writes - * @arg: srng handle - * - * This function handles the pending TCL reg writes missed due to the previous - * scheduled worker running. - * - * Return: None - */ -static void hal_tcl_reg_write_timer(void *arg) -{ - hal_ring_handle_t srng_hdl = arg; - struct hal_srng *srng; - struct hal_soc *hal; - - srng = (struct hal_srng *)srng_hdl; - hal = srng->hal_soc; - - if (hif_pm_runtime_get(hal->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE, - true)) { - hal_srng_set_event(srng_hdl, HAL_SRNG_FLUSH_EVENT); - hal_srng_inc_flush_cnt(srng_hdl); - goto fail; - } - - SRNG_LOCK(&srng->lock); - if (hal->tcl_direct) { - /* - * Due to the previous scheduled worker still running, - * direct reg write cannot be performed, so posted the - * pending writes to timer context. - */ - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - srng->last_reg_wr_val = srng->u.src_ring.hp; - srng->wstats.direct++; - hal->tcl_stats.timer_direct++; - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - } - } else { - /* - * Due to the previous scheduled worker still running, - * queue_work from delayed context would fail, - * so retry from timer context. - */ - if (qdf_queue_work(hal->qdf_dev, hal->tcl_reg_write_wq, - &hal->tcl_reg_write_work)) { - srng->reg_write_in_progress = true; - qdf_atomic_inc(&hal->active_work_cnt); - qdf_atomic_set(&hal->tcl_work_active, true); - srng->wstats.enqueues++; - hal->tcl_stats.timer_enq++; - } else { - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - hal->tcl_stats.timer_reset++; - qdf_timer_mod(&hal->tcl_reg_write_timer, 1); - } - } - } - SRNG_UNLOCK(&srng->lock); - hif_pm_runtime_put(hal->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE); - -fail: - return; -} - -/** - * hal_delayed_tcl_reg_write_init() - Initialization for delayed TCL reg writes - * @hal_soc: hal_soc pointer - * - * Initialize main data structures to process TCL register writes in a delayed - * workqueue. - * - * Return: QDF_STATUS_SUCCESS on success else a QDF error. - */ -static QDF_STATUS hal_delayed_tcl_reg_write_init(struct hal_soc *hal) -{ - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - QDF_STATUS status; - - hal->tcl_reg_write_wq = - qdf_alloc_high_prior_ordered_workqueue("hal_tcl_reg_write_wq"); - if (!hal->tcl_reg_write_wq) { - hal_err("hal_tcl_reg_write_wq alloc failed"); - return QDF_STATUS_E_NOMEM; - } - - status = qdf_create_work(0, &hal->tcl_reg_write_work, - hal_tcl_reg_write_work, hal); - if (status != QDF_STATUS_SUCCESS) { - hal_err("tcl_reg_write_work create failed"); - goto fail; - } - - status = qdf_timer_init(hal->qdf_dev, &hal->tcl_reg_write_timer, - hal_tcl_reg_write_timer, (void *)srng, - QDF_TIMER_TYPE_WAKE_APPS); - if (status != QDF_STATUS_SUCCESS) { - hal_err("tcl_reg_write_timer init failed"); - goto fail; - } - - qdf_atomic_init(&hal->tcl_work_active); - - return QDF_STATUS_SUCCESS; - -fail: - qdf_destroy_workqueue(0, hal->tcl_reg_write_wq); - return status; -} - -/** - * hal_delayed_tcl_reg_write_deinit() - De-Initialize delayed TCL reg writes - * @hal_soc: hal_soc pointer - * - * De-initialize main data structures to process TCL register writes in a - * delayed workqueue. - * - * Return: None - */ -static void hal_delayed_tcl_reg_write_deinit(struct hal_soc *hal) -{ - qdf_timer_stop(&hal->tcl_reg_write_timer); - qdf_timer_free(&hal->tcl_reg_write_timer); - - __hal_flush_tcl_reg_write_work(hal); - qdf_flush_workqueue(0, hal->tcl_reg_write_wq); - qdf_destroy_workqueue(0, hal->tcl_reg_write_wq); -} - -#else -static inline QDF_STATUS hal_delayed_tcl_reg_write_init(struct hal_soc *hal) -{ - return QDF_STATUS_SUCCESS; -} - -static inline void hal_delayed_tcl_reg_write_deinit(struct hal_soc *hal) -{ -} -#endif - -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -#ifdef FEATURE_HAL_DELAYED_REG_WRITE -static inline void hal_reg_write_enqueue_v2(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - hal_reg_write_enqueue(hal_soc, srng, addr, value); -} -#else -static inline void hal_reg_write_enqueue_v2(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - qdf_atomic_inc(&hal_soc->stats.wstats.direct); - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, value, false); -} -#endif -void hal_delayed_reg_write(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - switch (srng->ring_type) { - case TCL_DATA: - if (hal_is_reg_write_tput_level_high(hal_soc)) { - hal_soc->tcl_direct = true; - if (srng->reg_write_in_progress || - !qdf_atomic_read(&hal_soc->tcl_work_active)) { - /* - * Now the delayed work have either completed - * the writing or not even scheduled and would - * be blocked by SRNG_LOCK, hence it is fine to - * do direct write here. - */ - srng->last_reg_wr_val = srng->u.src_ring.hp; - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, - srng->last_reg_wr_val, - false); - } else { - hal_soc->tcl_stats.direct_timer_set++; - qdf_timer_mod(&hal_soc->tcl_reg_write_timer, 1); - } - } else { - hal_soc->tcl_direct = false; - if (srng->reg_write_in_progress) { - srng->wstats.coalesces++; - } else { - hal_tcl_reg_write_enqueue(hal_soc, srng, - addr, value); - } - } - break; - case CE_SRC: - case CE_DST: - case CE_DST_STATUS: - hal_reg_write_enqueue_v2(hal_soc, srng, addr, value); - break; - default: - qdf_atomic_inc(&hal_soc->stats.wstats.direct); - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, value, false); - break; - } -} - -#else #ifdef FEATURE_HAL_DELAYED_REG_WRITE #ifdef QCA_WIFI_QCA6750 void hal_delayed_reg_write(struct hal_soc *hal_soc, @@ -1398,7 +942,6 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc, } #endif #endif -#endif /** * hal_attach - Initialize HAL layer @@ -1470,7 +1013,6 @@ void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev) qdf_atomic_init(&hal->active_work_cnt); hal_delayed_reg_write_init(hal); - hal_delayed_tcl_reg_write_init(hal); return (void *)hal; @@ -1521,7 +1063,6 @@ extern void hal_detach(void *hal_soc) struct hal_soc *hal = (struct hal_soc *)hal_soc; hal_delayed_reg_write_deinit(hal); - hal_delayed_tcl_reg_write_deinit(hal); qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev, sizeof(*(hal->shadow_rdptr_mem_vaddr)) * HAL_SRNG_ID_MAX, From 737d944f2abc74677c7d28c2e011f8a81f607024 Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 4 Oct 2021 12:43:06 +0530 Subject: [PATCH 08/18] qcacmn: Allow NAN LOG messages upto a size of 400 bytes Currently, host allows NAN log messages from firmware upto a max size of 200 bytes. But firmware may need to send bigger messages than this in case of stats events as tx/rx stats message length can go upto 350 bytes. So, allow NAN messages upto 400 bytes to avoid splitting the stats messages. Change-Id: Ibb03944da81ed8d378dadbf4750013e0fe941e57 CRs-Fixed: 3049258 --- wmi/src/wmi_unified_nan_tlv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wmi/src/wmi_unified_nan_tlv.c b/wmi/src/wmi_unified_nan_tlv.c index 42acfd137778..de5706c8f514 100644 --- a/wmi/src/wmi_unified_nan_tlv.c +++ b/wmi/src/wmi_unified_nan_tlv.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2021 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 @@ -693,7 +693,7 @@ static QDF_STATUS extract_ndp_initiator_rsp_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } -#define MAX_NAN_MSG_LEN 200 +#define MAX_NAN_MSG_LEN 400 static QDF_STATUS extract_nan_msg_tlv(uint8_t *data, struct nan_dump_msg *msg) From 518cd0745c37d1ba4cb5fb686b9ad6ea0ccd2639 Mon Sep 17 00:00:00 2001 From: Karthik Kantamneni Date: Wed, 6 Oct 2021 14:51:58 +0530 Subject: [PATCH 09/18] qcacmn: Add HIF events to track NAPI POLL exit time Add HIF events to track NAPI POLL exit time, this gives information about actual time spent by wlan host in napi softirq. Change-Id: I7548fd05f2f7db714ac9bcf79171ffb3d478e936 CRs-Fixed: 3052902 --- hif/inc/hif.h | 6 +++++- hif/src/hif_exec.c | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 3ffa9a28f0b1..9786f4aa6d4e 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -327,6 +327,8 @@ struct hif_opaque_softc { * @HIF_EVENT_BH_SCHED: NAPI POLL scheduled event * @HIF_EVENT_SRNG_ACCESS_START: hal ring access start event * @HIF_EVENT_SRNG_ACCESS_END: hal ring access end event + * @HIF_EVENT_BH_COMPLETE: NAPI POLL completion event + * @HIF_EVENT_BH_FORCE_BREAK: NAPI POLL force break event */ enum hif_event_type { HIF_EVENT_IRQ_TRIGGER, @@ -335,6 +337,8 @@ enum hif_event_type { HIF_EVENT_BH_SCHED, HIF_EVENT_SRNG_ACCESS_START, HIF_EVENT_SRNG_ACCESS_END, + HIF_EVENT_BH_COMPLETE, + HIF_EVENT_BH_FORCE_BREAK, /* Do check hif_hist_skip_event_record when adding new events */ }; @@ -360,7 +364,7 @@ enum hif_system_pm_state { /* HIF_EVENT_HIST_MAX should always be power of 2 */ #define HIF_EVENT_HIST_MAX 512 #define HIF_NUM_INT_CONTEXTS HIF_MAX_GROUP -#define HIF_EVENT_HIST_ENABLE_MASK 0x3F +#define HIF_EVENT_HIST_ENABLE_MASK 0xFF static inline uint64_t hif_get_log_timestamp(void) { diff --git a/hif/src/hif_exec.c b/hif/src/hif_exec.c index 62a44bc7958a..ad0f200525cb 100644 --- a/hif/src/hif_exec.c +++ b/hif/src/hif_exec.c @@ -119,6 +119,11 @@ hif_hist_skip_event_record(struct hif_event_history *hist_ev, if (rec->type != HIF_EVENT_SRNG_ACCESS_START) return true; break; + case HIF_EVENT_BH_COMPLETE: + case HIF_EVENT_BH_FORCE_BREAK: + if (rec->type != HIF_EVENT_SRNG_ACCESS_END) + return true; + break; default: break; } @@ -623,6 +628,8 @@ static int hif_exec_poll(struct napi_struct *napi, int budget) actual_dones = work_done; if (!hif_ext_group->force_break && work_done < normalized_budget) { + hif_record_event(hif_ext_group->hif, hif_ext_group->grp_id, + 0, 0, 0, HIF_EVENT_BH_COMPLETE); napi_complete(napi); qdf_atomic_dec(&scn->active_grp_tasklet_cnt); hif_ext_group->irq_enable(hif_ext_group); @@ -630,6 +637,8 @@ static int hif_exec_poll(struct napi_struct *napi, int budget) } else { /* if the ext_group supports time based yield, claim full work * done anyways */ + hif_record_event(hif_ext_group->hif, hif_ext_group->grp_id, + 0, 0, 0, HIF_EVENT_BH_FORCE_BREAK); work_done = normalized_budget; } From 1cbe11a69585c3246215b5f6b92343ede6f26570 Mon Sep 17 00:00:00 2001 From: Jianmin Zhu Date: Sat, 23 Oct 2021 23:08:56 +0800 Subject: [PATCH 10/18] qcacmn: channel_switch_complete_evt need wake up all waiting threads 2 threads blocked to wait channel_switch_complete_evt for SAP channel switch is already in progress, qdf_event_set only woke up 1st thread later, 2nd thread still kept blocked with hold net_dev for debug id NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_SAP, leak happened. Change-Id: Ib76318dd4a613ca1852a56b7701a04385b69ba56 CRs-Fixed: 3061976 --- qdf/inc/qdf_event.h | 30 +++++++++++++++++++++++++++++- qdf/linux/src/qdf_event.c | 33 ++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/qdf/inc/qdf_event.h b/qdf/inc/qdf_event.h index 27de4c79369c..04e09434f243 100644 --- a/qdf/inc/qdf_event.h +++ b/qdf/inc/qdf_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018, 2021 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 @@ -41,8 +41,36 @@ typedef __qdf_event_t qdf_event_t; QDF_STATUS qdf_event_create(qdf_event_t *event); +/** + * qdf_event_set() - sets a QDF event for single waiting threads + * @event: The event to set to the signalled state + * + * The state of the specified event is set to signalled by calling + * qdf_event_set(). + * + * Single thread waiting on the event as a result of a qdf_event_wait() will + * be unblocked and available to be scheduled for execution when the event + * is signaled by a call to qdf_event_set(). + * + * Return: QDF status + */ QDF_STATUS qdf_event_set(qdf_event_t *event); +/** + * qdf_event_set_all() - sets a QDF event for all waiting threads + * @event: The event to set to the signalled state + * + * The state of the specified event is set to signalled by calling + * qdf_event_set_all(). + * + * Any threads waiting on the event as a result of a qdf_event_wait() will + * be unblocked and available to be scheduled for execution when the event + * is signaled by a call to qdf_event_set(). + * + * Return: QDF status + */ +QDF_STATUS qdf_event_set_all(qdf_event_t *event); + QDF_STATUS qdf_event_reset(qdf_event_t *event); QDF_STATUS qdf_event_destroy(qdf_event_t *event); diff --git a/qdf/linux/src/qdf_event.c b/qdf/linux/src/qdf_event.c index 3fcaae820464..b77556ddf74c 100644 --- a/qdf/linux/src/qdf_event.c +++ b/qdf/linux/src/qdf_event.c @@ -77,19 +77,6 @@ QDF_STATUS qdf_event_create(qdf_event_t *event) } qdf_export_symbol(qdf_event_create); -/** - * qdf_event_set() - sets a QDF event - * @event: The event to set to the signalled state - * - * The state of the specified event is set to signalled by calling - * qdf_event_set(). - * - * Any threads waiting on the event as a result of a qdf_event_wait() will - * be unblocked and available to be scheduled for execution when the event - * is signaled by a call to qdf_event_set(). - * - * Return: QDF status - */ QDF_STATUS qdf_event_set(qdf_event_t *event) { QDF_BUG(event); @@ -106,8 +93,28 @@ QDF_STATUS qdf_event_set(qdf_event_t *event) return QDF_STATUS_SUCCESS; } + qdf_export_symbol(qdf_event_set); +QDF_STATUS qdf_event_set_all(qdf_event_t *event) +{ + QDF_BUG(event); + if (!event) + return QDF_STATUS_E_FAULT; + + /* ensure event is initialized */ + QDF_BUG(event->cookie == LINUX_EVENT_COOKIE); + if (event->cookie != LINUX_EVENT_COOKIE) + return QDF_STATUS_E_INVAL; + + event->done = true; + complete_all(&event->complete); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(qdf_event_set_all); + /** * qdf_event_reset() - resets a QDF event * @event: The event to set to the NOT signalled state From 3bd491ab961002dfae9c01f8602ecc3add91554e Mon Sep 17 00:00:00 2001 From: Lin Bai Date: Fri, 13 Aug 2021 18:20:08 +0800 Subject: [PATCH 11/18] qcacmn: Move unsafe info to regulator msg If two channel avoid event reported by FW back to back, flag psoc_priv_obj->ch_avoid_ind of 2nd event set by reg_process_ch_avoid_event may be modified when processing 1st event in reg_call_chan_change_cbks, from scheduler_thread context. Copy chan avoid info to message post to scheduler to avoid such timing issue. Change-Id: I8fd5e7e8f2d9b2117a5c6a54fd8b64659e10f7d6 CRs-Fixed: 3012331 --- umac/regulatory/core/src/reg_callbacks.c | 48 +++++++++++-------- .../inc/reg_services_public_struct.h | 24 ++++++---- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/umac/regulatory/core/src/reg_callbacks.c b/umac/regulatory/core/src/reg_callbacks.c index ed253021d077..62b0a069024e 100644 --- a/umac/regulatory/core/src/reg_callbacks.c +++ b/umac/regulatory/core/src/reg_callbacks.c @@ -37,9 +37,13 @@ * change. * @psoc: Pointer to global psoc structure. * @pdev: Pointer to global pdev structure. + * @ch_avoid_ind: if chan avoid indicated + * @avoid_info: chan avoid info if @ch_avoid_ind is true */ static void reg_call_chan_change_cbks(struct wlan_objmgr_psoc *psoc, - struct wlan_objmgr_pdev *pdev) + struct wlan_objmgr_pdev *pdev, + bool ch_avoid_ind, + struct avoid_freq_ind_data *avoid_info) { struct chan_change_cbk_entry *cbk_list; struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; @@ -70,21 +74,9 @@ static void reg_call_chan_change_cbks(struct wlan_objmgr_psoc *psoc, NUM_CHANNELS * sizeof(struct regulatory_channel)); - if (psoc_priv_obj->ch_avoid_ind) { - avoid_freq_ind = qdf_mem_malloc(sizeof(*avoid_freq_ind)); - if (!avoid_freq_ind) - goto skip_ch_avoid_ind; + if (ch_avoid_ind) + avoid_freq_ind = avoid_info; - qdf_mem_copy(&avoid_freq_ind->freq_list, - &psoc_priv_obj->avoid_freq_list, - sizeof(struct ch_avoid_ind_type)); - qdf_mem_copy(&avoid_freq_ind->chan_list, - &psoc_priv_obj->unsafe_chan_list, - sizeof(struct unsafe_ch_list)); - psoc_priv_obj->ch_avoid_ind = false; - } - -skip_ch_avoid_ind: cbk_list = psoc_priv_obj->cbk_list; for (ctr = 0; ctr < REG_MAX_CHAN_CHANGE_CBKS; ctr++) { @@ -98,8 +90,6 @@ skip_ch_avoid_ind: cbk_list[ctr].arg); } qdf_mem_free(cur_chan_list); - if (avoid_freq_ind) - qdf_mem_free(avoid_freq_ind); } /** @@ -111,10 +101,28 @@ static void reg_alloc_and_fill_payload(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, struct reg_sched_payload **payload) { + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + *payload = NULL; + return; + } + *payload = qdf_mem_malloc(sizeof(**payload)); if (*payload) { (*payload)->psoc = psoc; (*payload)->pdev = pdev; + (*payload)->ch_avoid_ind = !!psoc_priv_obj->ch_avoid_ind; + qdf_mem_copy(&(*payload)->avoid_info.freq_list, + &psoc_priv_obj->avoid_freq_list, + sizeof(psoc_priv_obj->avoid_freq_list)); + qdf_mem_copy(&(*payload)->avoid_info.chan_list, + &psoc_priv_obj->unsafe_chan_list, + sizeof(psoc_priv_obj->unsafe_chan_list)); + + psoc_priv_obj->ch_avoid_ind = false; } } @@ -146,7 +154,8 @@ static QDF_STATUS reg_sched_chan_change_cbks_sb(struct scheduler_msg *msg) struct wlan_objmgr_psoc *psoc = load->psoc; struct wlan_objmgr_pdev *pdev = load->pdev; - reg_call_chan_change_cbks(psoc, pdev); + reg_call_chan_change_cbks(psoc, pdev, load->ch_avoid_ind, + &load->avoid_info); wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_SB_ID); wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); @@ -183,7 +192,8 @@ static QDF_STATUS reg_sched_chan_change_cbks_nb(struct scheduler_msg *msg) struct wlan_objmgr_psoc *psoc = load->psoc; struct wlan_objmgr_pdev *pdev = load->pdev; - reg_call_chan_change_cbks(psoc, pdev); + reg_call_chan_change_cbks(psoc, pdev, load->ch_avoid_ind, + &load->avoid_info); wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID); wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_NB_ID); diff --git a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index 8887cdad7540..46b1e668709b 100644 --- a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -1203,16 +1203,6 @@ struct reg_freq_range { uint32_t high_freq; }; -/** - * struct reg_sched_payload - * @psoc: psoc ptr - * @pdev: pdev ptr - */ -struct reg_sched_payload { - struct wlan_objmgr_psoc *psoc; - struct wlan_objmgr_pdev *pdev; -}; - /** * enum direction * @NORTHBOUND: northbound @@ -1359,6 +1349,20 @@ struct avoid_freq_ind_data { struct unsafe_ch_list chan_list; }; +/** + * struct reg_sched_payload + * @psoc: psoc ptr + * @pdev: pdev ptr + * @ch_avoid_ind: if avoidance event indicated + * @avoid_info: chan avoid info if @ch_avoid_ind is true + */ +struct reg_sched_payload { + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + bool ch_avoid_ind; + struct avoid_freq_ind_data avoid_info; +}; + #define FIVEG_STARTING_FREQ 5000 #define TWOG_STARTING_FREQ 2407 #define TWOG_CHAN_14_IN_MHZ 2484 From 871a0512abd807bde0c6ffa045327d370176ed1d Mon Sep 17 00:00:00 2001 From: Jianmin Zhu Date: Tue, 26 Oct 2021 15:06:46 +0800 Subject: [PATCH 12/18] qcacmn: Fix wrong rssi in monitor mode If ppdu rssi unit is dbm, need convert to db for API: qdf_nbuf_update_radiotap, only need convert once for first mdpu in the ppdu. if convert for each mpdu, wrong rssi will be saved. Change-Id: I85e92121ddb289e3513022ff092083825197efb4 CRs-Fixed: 3057041 --- dp/wifi3.0/dp_rx_mon_dest.c | 23 ----------------------- qdf/linux/src/qdf_nbuf.c | 10 +++++++++- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c index 7e0eea1062cc..2816a59fbb1d 100644 --- a/dp/wifi3.0/dp_rx_mon_dest.c +++ b/dp/wifi3.0/dp_rx_mon_dest.c @@ -1411,27 +1411,6 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu(struct dp_soc *soc, uint32_t mac_id, } #endif -#ifdef DP_MON_RSSI_IN_DBM -/* - * dp_rx_mon_rssi_convert(): convert rssi_comb from unit dBm to dB - * to match with radiotap further conversion requirement - * @rx_status: monitor mode rx status pointer - * - * Return: none - */ -static inline -void dp_rx_mon_rssi_convert(struct mon_rx_status *rx_status) -{ - rx_status->rssi_comb = rx_status->rssi_comb - - rx_status->chan_noise_floor; -} -#else -static inline -void dp_rx_mon_rssi_convert(struct mon_rx_status *rx_status) -{ -} -#endif - /* * dp_rx_mon_deliver(): function to deliver packets to stack * @soc: DP soc @@ -1469,8 +1448,6 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, pdev->ppdu_info.rx_status.device_id = soc->device_id; pdev->ppdu_info.rx_status.chan_noise_floor = pdev->chan_noise_floor; - /* convert rssi_comb from dBm to positive dB value */ - dp_rx_mon_rssi_convert(&pdev->ppdu_info.rx_status); dp_handle_tx_capture(soc, pdev, mon_mpdu); diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 4821a4052240..9340d33d774c 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -4504,6 +4504,14 @@ static unsigned int qdf_nbuf_update_radiotap_ampdu_flags( return rtap_len; } +#ifdef DP_MON_RSSI_IN_DBM +#define QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status) \ +(rx_status->rssi_comb) +#else +#define QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status) \ +(rx_status->rssi_comb + rx_status->chan_noise_floor) +#endif + /** * qdf_nbuf_update_radiotap() - Update radiotap header from rx_status * @rx_status: Pointer to rx_status. @@ -4579,7 +4587,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status, * rssi_comb is int dB, need to convert it to dBm. * normalize value to noise floor of -96 dBm */ - rtap_buf[rtap_len] = rx_status->rssi_comb + rx_status->chan_noise_floor; + rtap_buf[rtap_len] = QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status); rtap_len += 1; /* RX signal noise floor */ From 8dca694d199b519d4cf0cccfcd40b7ae1fca1542 Mon Sep 17 00:00:00 2001 From: Karthik Kantamneni Date: Thu, 28 Oct 2021 12:38:50 +0530 Subject: [PATCH 13/18] qcacmn: Flush reg work instead of cancelling in deinit path Currently reg work is being cancelled in deinit path, cancel work will remove all the pending work items and wait for completion of current executing work. But in reg work case even pending work items has to be executed because we don't want to skip HP/TP values update. To avoid this make sure all the pending reg work items are flushed then disable the work for further queueing. Change-Id: I2ba1e26cf41fb3b0c33ec584c56525cbfac94d8f CRs-Fixed: 3065038 --- hal/wifi3.0/hal_srng.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 7396981bd295..4a55cbb70cb8 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -739,8 +739,8 @@ static void hal_reg_write_work(void *arg) static void __hal_flush_reg_write_work(struct hal_soc *hal) { - qdf_cancel_work(&hal->reg_write_work); - + qdf_flush_work(&hal->reg_write_work); + qdf_disable_work(&hal->reg_write_work); } void hal_flush_reg_write_work(hal_soc_handle_t hal_handle) From 4a8efff23347b9b777f306a31b50cdb2e98a593e Mon Sep 17 00:00:00 2001 From: Amit Mehta Date: Wed, 4 Aug 2021 17:15:45 +0530 Subject: [PATCH 14/18] qcacmn: Change logging time-stamp source Currently there is mismatch in time-stamp source for hif_hist_skip_event_record with respect to hif_hist_record_event Updating time-stamp source in hif_hist_record_event to match with hif_hist_skip_event_record time-stamp source. Change-Id: I55680c40860eafb5c6ed6117ab7c55bb38cc24bb CRs-Fixed: 3000319 --- hif/src/hif_exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hif/src/hif_exec.c b/hif/src/hif_exec.c index ad0f200525cb..76a4e0a9382e 100644 --- a/hif/src/hif_exec.c +++ b/hif/src/hif_exec.c @@ -96,7 +96,7 @@ hif_hist_skip_event_record(struct hif_event_history *hist_ev, HIF_EVENT_HIST_MAX)) { last_irq_rec = &hist_ev->event[hist_ev->misc.last_irq_index]; - last_irq_rec->timestamp = qdf_get_log_timestamp(); + last_irq_rec->timestamp = hif_get_log_timestamp(); last_irq_rec->cpu_id = qdf_get_cpu(); last_irq_rec->hp++; last_irq_rec->tp = last_irq_rec->timestamp - @@ -106,7 +106,7 @@ hif_hist_skip_event_record(struct hif_event_history *hist_ev, break; case HIF_EVENT_BH_SCHED: if (rec->type == HIF_EVENT_BH_SCHED) { - rec->timestamp = qdf_get_log_timestamp(); + rec->timestamp = hif_get_log_timestamp(); rec->cpu_id = qdf_get_cpu(); return true; } From cd924b9139856ab6b594a875458d856831b59846 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Fri, 8 Oct 2021 01:39:36 +0530 Subject: [PATCH 15/18] qcacmn: Vendor command to configure/trigger the roam events Introduce a new vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS that aims to configure/trigger the roam events from the driver. Change-Id: Ifd9464cc8cb485890c8d171dc136d377f7a59fa1 CRs-Fixed: 3028404 --- os_if/linux/qca_vendor.h | 162 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/os_if/linux/qca_vendor.h b/os_if/linux/qca_vendor.h index 6e816b8afa89..97309a331915 100644 --- a/os_if/linux/qca_vendor.h +++ b/os_if/linux/qca_vendor.h @@ -498,6 +498,13 @@ * to resume the host and forward the respective frames to the monitor * interface. Please note that such a request to get the frames over the * monitor interface will have a definite power implications. + * + * @QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS: This vendor subcommand is used both + * as a request to set the driver/firmware with the parameters to trigger + * the roaming events, and also used by the driver/firmware to pass on the + * various roam events to userspace. + * Applicable only for the STA mode. The attributes used with this command + * are defined in enum qca_wlan_vendor_attr_roam_events. */ enum qca_nl80211_vendor_subcmds { @@ -732,6 +739,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY = 197, QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198, QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202, + QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203, }; enum qca_wlan_vendor_tos { @@ -11150,4 +11158,158 @@ enum qca_wlan_vendor_attr_set_monitor_mode { }; +/** + * enum qca_wlan_vendor_roam_scan_state - Roam scan state flags. + * Bits will be set to 1 if the corresponding state is enabled. + * + * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_START: Scan Start. + * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_END: Scan end. + */ +enum qca_wlan_vendor_roam_scan_state { + QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START = BIT(0), + QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END = BIT(1), +}; + +/** + * enum qca_wlan_vendor_roam_event_type - Roam event type flags. + * Bits will be set to 1 if the corresponding event is notified. + * + * @QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON: Represents that the roam event + * carries the trigger reason. When set, it is expected that the roam event + * carries the respective reason via the attribute + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON. This event also carries + * the BSSID, RSSI, frequency info of the AP to which the roam is attempted. + * + * @QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON: Represents that the roam event + * carries the roam fail reason. When set, it is expected that the roam event + * carries the respective reason via the attribute + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_FAIL_REASON. This event also carries the + * BSSID, RSSI, frequency info of the AP to which the roam was attempted. + * + * @QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON: Represents that the roam + * event carries the roam invoke fail reason. When set, it is expected that + * the roam event carries the respective reason via the attribute + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON. + * + * @QCA_WLAN_VENDOR_ROAM_EVENT_SCAN_STATE: Represents that the roam event + * carries the roam scan state. When set, it is expected that the roam event + * carries the respective scan state via the attribute + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE and the corresponding + * frequency info via QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST. + */ +enum qca_wlan_vendor_roam_event_type { + QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON = BIT(0), + QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON = BIT(1), + QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON = BIT(2), + QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE = BIT(3), +}; + +/** + * enum qca_wlan_vendor_attr_roam_events_candidate_info: Roam candidate info. + * Referred by QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID: 6-byte MAC address + * representing the BSSID of the AP to which the Roam is attempted. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI: Signed 32-bit value + * in dBm, signifying the RSSI of the candidate BSSID to which the Roaming is + * attempted. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ: u32, Frequency in MHz + * on which the roam is attempted. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON: u32, used in + * STA mode only. This represents the roam fail reason for the last failed + * roaming attempt by the firmware for the specific BSSID. Different roam + * failure reason codes are specified in enum qca_vendor_roam_fail_reasons. + */ +enum qca_wlan_vendor_attr_roam_events_candidate_info { + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID = 1, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI = 2, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ = 3, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON = 4, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_roam_events - Used by the + * vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS to either configure the + * roam events to the driver or notify these events from the driver. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE: u8 attribute. Configures the + * driver/firmware to enable/disable the notification of roam events. It's a + * mandatory attribute and used only in the request from the userspace to the + * host driver. 1-Enable, 0-Disable. + * If the roaming is totally offloaded to the firmware, this request when + * enabled shall mandate the firmware to notify all the relevant roam events + * represented by the below attributes. If the host is in the suspend mode, + * the behavior of the firmware to notify these events is guided by + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_DEVICE_STATE, and if the request is to get + * these events in the suspend state, the firmware is expected to wake up the + * host before the respective events are notified. Please note that such a + * request to get the events in the suspend state will have a definite power + * implication. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE: flag attribute. Represents + * that the roam events need to be notified in the suspend state too. By + * default, these roam events are notified in the resume state. With this flag, + * the roam events are notified in both resume and suspend states. + * This attribute is used in the request from the userspace to the host driver. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE: u32, used in STA mode only. + * Represents the different roam event types, signified by the enum + * qca_wlan_vendor_roam_event_type. + * Each bit of this attribute represents the different roam even types reported + * through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON: u32, used in STA + * mode only. This represents the roam trigger reason for the last roaming + * attempted by the firmware. Each bit of this attribute represents the + * different roam trigger reason code which are defined in enum + * qca_vendor_roam_triggers. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON: u32, used in + * STA mode only. This represents the roam invoke fail reason for the last + * failed roam invoke. Different roam invoke failure reason codes + * are specified in enum qca_vendor_roam_invoke_fail_reasons. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO: Array of candidates info + * for which the roam is attempted. Each entry is a nested attribute defined + * by enum qca_wlan_vendor_attr_roam_events_candidate_info. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE: u8 attribute. Represents + * the scan state on which the roam events need to be notified. The values for + * this attribute are referred from enum qca_wlan_vendor_roam_scan_state. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST: Nested attribute of + * u32 values. List of frequencies in MHz considered for a roam scan. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + */ + +enum qca_wlan_vendor_attr_roam_events { + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE = 3, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON = 4, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON = 5, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO = 6, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE = 7, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST = 8, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX = + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST - 1, +}; + #endif From 0ed270bc997977edd41a459f0dc97b3facddd2c9 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Mon, 27 Sep 2021 13:43:49 +0530 Subject: [PATCH 16/18] qcacmn: Add roam set param command for roam params This change introduces the new roam set param WMI command to set the roam params from host to FW. Also added a fail_bssid param in wmi_roam_result TLV to know the roam failed AP BSSID from the FW. Added a new vendor command event for sending roam events stats attributes to userspace. Change-Id: I7a08635a7912cbd940d90a2d62433296740ad913 CRs-Fixed: 3050799 --- os_if/linux/wlan_cfg80211.h | 3 +++ wmi/inc/wmi_unified_api.h | 20 +++++++++++++++++ wmi/inc/wmi_unified_param.h | 2 ++ wmi/inc/wmi_unified_priv.h | 3 +++ wmi/src/wmi_unified_api.c | 13 +++++++++++ wmi/src/wmi_unified_tlv.c | 45 +++++++++++++++++++++++++++++++++++++ 6 files changed, 86 insertions(+) diff --git a/os_if/linux/wlan_cfg80211.h b/os_if/linux/wlan_cfg80211.h index 2769d7288650..ea022611eb04 100644 --- a/os_if/linux/wlan_cfg80211.h +++ b/os_if/linux/wlan_cfg80211.h @@ -238,6 +238,9 @@ enum qca_nl80211_vendor_subcmds_index { #ifdef WLAN_CFR_ENABLE QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG_INDEX, #endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS_INDEX, +#endif }; #if !defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC) && \ diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 6956d03061fb..cfc2e5ec3ba3 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -859,6 +859,26 @@ QDF_STATUS wmi_unified_vdev_set_param_send(wmi_unified_t wmi_handle, struct vdev_set_params *param); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * wmi_unified_roam_set_param_send() - WMI roam set parameter function + * @wmi_handle: handle to WMI. + * @roam_param: pointer to hold roam set parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_roam_set_param_send(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param); +#else +static inline QDF_STATUS +wmi_unified_roam_set_param_send(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * wmi_unified_sifs_trigger_send() - WMI vdev sifs trigger parameter function * @wmi_handle: handle to WMI. diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 85fbd47c86de..0e224b67b650 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -7887,12 +7887,14 @@ struct wmi_roam_scan_data { * @status: 0 - Roaming is success ; 1 - Roaming failed ; * 2 - No roam * @fail_reason: One of WMI_ROAM_FAIL_REASON_ID + * @fail_bssid: BSSID of the last attempted roam failed AP */ struct wmi_roam_result { bool present; uint32_t timestamp; uint32_t status; uint32_t fail_reason; + struct qdf_mac_addr fail_bssid; }; /** diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 6ed14454981a..ba47388218c6 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1015,6 +1015,9 @@ QDF_STATUS (*send_pdev_set_pcl_cmd)(wmi_unified_t wmi_handle, #ifdef WLAN_FEATURE_ROAM_OFFLOAD QDF_STATUS (*send_vdev_set_pcl_cmd)(wmi_unified_t wmi_handle, struct set_pcl_cmd_params *params); + +QDF_STATUS (*send_roam_set_param_cmd)(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param); #endif #ifdef WLAN_POLICY_MGR_ENABLE diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 71733a726529..5ecf442f8c42 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -399,6 +399,19 @@ wmi_unified_vdev_set_param_send(wmi_unified_t wmi_handle, return QDF_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +QDF_STATUS +wmi_unified_roam_set_param_send(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param) +{ + if (wmi_handle->ops->send_roam_set_param_cmd) + return wmi_handle->ops->send_roam_set_param_cmd(wmi_handle, + roam_param); + + return QDF_STATUS_E_FAILURE; +} +#endif + QDF_STATUS wmi_unified_sifs_trigger_send(wmi_unified_t wmi_handle, struct sifs_trigger_param *param) { diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 76da4ea51604..b004aaef6df6 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -14263,6 +14263,7 @@ extract_roam_result_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, dst->status = src_data->roam_status; dst->timestamp = src_data->timestamp; dst->fail_reason = src_data->roam_fail_reason; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_data->bssid, dst->fail_bssid.bytes); return QDF_STATUS_SUCCESS; } @@ -14328,6 +14329,47 @@ extract_roam_11kv_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_SUCCESS; } + +/** + * send_roam_set_param_cmd_tlv() - WMI roam set parameter function + * @wmi_handle : handle to WMI. + * @roam_param : pointer to hold roam set parameter + * + * Return: 0 on success and -ve on failure. + */ +static QDF_STATUS +send_roam_set_param_cmd_tlv(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param) +{ + QDF_STATUS ret; + wmi_roam_set_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint16_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) + return QDF_STATUS_E_NOMEM; + + cmd = (wmi_roam_set_param_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_set_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_set_param_cmd_fixed_param)); + cmd->vdev_id = roam_param->vdev_id; + cmd->param_id = roam_param->param_id; + cmd->param_value = roam_param->param_value; + wmi_debug("Setting vdev %d roam_param = %x, value = %u", + cmd->vdev_id, cmd->param_id, cmd->param_value); + wmi_mtrace(WMI_ROAM_SET_PARAM_CMDID, cmd->vdev_id, 0); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_ROAM_SET_PARAM_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) { + wmi_err("Failed to send roam set param command, ret = %d", ret); + wmi_buf_free(buf); + } + + return ret; +} #else static inline QDF_STATUS extract_roam_trigger_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, @@ -15039,6 +15081,9 @@ struct wmi_ops tlv_ops = { .extract_pdev_csa_switch_count_status = extract_pdev_csa_switch_count_status_tlv, .send_set_tpc_power_cmd = send_set_tpc_power_cmd_tlv, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + .send_roam_set_param_cmd = send_roam_set_param_cmd_tlv, +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ }; /** From 4e10e7c5ae0ee7bb6dcb1e2c123cc8f1ec79a9a1 Mon Sep 17 00:00:00 2001 From: Amit Mehta Date: Fri, 15 Oct 2021 15:11:58 +0530 Subject: [PATCH 17/18] qcacmn: Update MPDU retries in case of successful transmission In case of successful transmission If MPDU tx is retried more than the threshold then increment MPDU retry count by transmit_cnt / threshold Change-Id: Idbc7e2d0579ff68e272132fe4ffe9f951c4aacf5 CRs-Fixed: 3058464 --- dp/inc/cdp_txrx_stats_struct.h | 2 ++ dp/wifi3.0/dp_internal.h | 2 ++ dp/wifi3.0/dp_tx.c | 7 ++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index 11c5ec3aa0ba..de4ed05f0882 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -1024,6 +1024,8 @@ struct cdp_tx_stats { uint32_t num_ppdu_cookie_valid; uint32_t no_ack_count[QDF_PROTO_SUBTYPE_MAX]; struct cdp_pkt_info tx_success_twt; + /* mpdu retry count in case of successful transmission */ + uint32_t mpdu_success_with_retries; }; /* struct cdp_rx_stats - rx Level Stats diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 22da8713a5cf..13e4a851611c 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -871,6 +871,8 @@ static inline void dp_update_vdev_stats(struct dp_soc *soc, tgtobj->tx.dropped.fw_reason3 += srcobj->stats.tx.dropped.fw_reason3; tgtobj->tx.dropped.age_out += srcobj->stats.tx.dropped.age_out; + tgtobj->tx.mpdu_success_with_retries += + srcobj->stats.tx.mpdu_success_with_retries; tgtobj->rx.err.mic_err += srcobj->stats.rx.err.mic_err; if (srcobj->stats.rx.rssi != 0) tgtobj->rx.rssi = srcobj->stats.rx.rssi; diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index e54928cb66ca..1848fa50f48d 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -58,6 +58,8 @@ /* invalid peer id for reinject*/ #define DP_INVALID_PEER 0XFFFE +#define DP_RETRY_COUNT 7 + /*mapping between hal encrypt type and cdp_sec_type*/ #define MAX_CDP_SEC_TYPE 12 static const uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = { @@ -4113,12 +4115,15 @@ dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc, DP_STATS_INCC(peer, tx.stbc, 1, ts->stbc); DP_STATS_INCC(peer, tx.ldpc, 1, ts->ldpc); DP_STATS_INCC(peer, tx.retries, 1, ts->transmit_cnt > 1); - #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, pdev->soc, &peer->stats, ts->peer_id, UPDATE_PEER_STATS, pdev->pdev_id); #endif + if (ts->first_msdu) + DP_STATS_INCC(peer, tx.mpdu_success_with_retries, + qdf_do_div(ts->transmit_cnt, DP_RETRY_COUNT), + ts->transmit_cnt > DP_RETRY_COUNT); } #ifdef QCA_LL_TX_FLOW_CONTROL_V2 From 233121e3a7800dcb5a2942f1ef7a4fb5d3075375 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 9 Nov 2021 13:13:05 +0530 Subject: [PATCH 18/18] qcacmn: Use a max of 5 WBM2SW rings for HSP to address wcov failure The maximum WBM2SW rings in whunt for HSP is 5 and the same could be 4 in wlan code which will result in wcov failure for HSP. Use a maximum of 5 WBM2SW rings for HSP based on FW_SIM config flag to address this failure. Change-Id: I8340cd094eb1e0cf842894e5c89174d410729028 CRs-Fixed: 3071662 --- hal/wifi3.0/qca6490/hal_6490.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hal/wifi3.0/qca6490/hal_6490.c b/hal/wifi3.0/qca6490/hal_6490.c index b8f9766ddef5..00d2a7a2f34b 100644 --- a/hal/wifi3.0/qca6490/hal_6490.c +++ b/hal/wifi3.0/qca6490/hal_6490.c @@ -2073,7 +2073,11 @@ struct hal_hw_srng_config hw_srng_table_6490[] = { }, { /* WBM2SW_RELEASE */ .start_ring_id = HAL_SRNG_WBM2SW0_RELEASE, +#ifdef CONFIG_PLD_PCIE_FW_SIM + .max_rings = 5, +#else .max_rings = 4, +#endif .entry_size = sizeof(struct wbm_release_ring) >> 2, .lmac_ring = FALSE, .ring_dir = HAL_SRNG_DST_RING,