From f94d7a3a51070d185e9203b53a3d669e27931e3d Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Mon, 6 Mar 2023 13:50:40 +0100 Subject: [PATCH 01/43] wifi: ath9k: Remove Qwest/Actiontec 802AIN ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The USB device 1668:1200 is Qwest/Actiontec 802AIN which is also correctly claimed to be supported by carl9170. Supposedly, the successor 802AIN2 has an ath9k compatible chip whose USB ID (unknown) could be inserted instead. Drop the ID from the wrong driver. I happened to find this by chance while packaging the ath9k and carl9170 firmware for Debian. Signed-off-by: Bastian Germann Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230306125041.2221-1-bage@debian.org --- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index e0130beb304d..27ff1ca2631f 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -42,8 +42,6 @@ static const struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x7015), .driver_info = AR9287_USB }, /* Atheros */ - { USB_DEVICE(0x1668, 0x1200), - .driver_info = AR9287_USB }, /* Verizon */ { USB_DEVICE(0x0cf3, 0x7010), .driver_info = AR9280_USB }, /* Atheros */ From f94557154d9fc77c392844523388edd4661a27a3 Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Sat, 11 Mar 2023 20:36:47 +0530 Subject: [PATCH 02/43] wifi: wcn36xx: add support for pronto-v3 Pronto v3 has a different DXE address than prior Pronto versions. This patch changes the macro to return the correct register address based on the pronto version. Signed-off-by: Vladimir Lypak Signed-off-by: Sireesh Kodali Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230311150647.22935-2-sireeshkodali1@gmail.com --- drivers/net/wireless/ath/wcn36xx/dxe.c | 23 +++++++++++----------- drivers/net/wireless/ath/wcn36xx/dxe.h | 4 ++-- drivers/net/wireless/ath/wcn36xx/main.c | 1 + drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 + 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 4e9e13941c8f..9013f056eecb 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -112,8 +112,8 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L; wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H; - wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L; - wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H; + wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L(wcn); + wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H(wcn); wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD; wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD; @@ -165,8 +165,9 @@ void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn) wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); } -static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) +static int wcn36xx_dxe_init_descs(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *wcn_ch) { + struct device *dev = wcn->dev; struct wcn36xx_dxe_desc *cur_dxe = NULL; struct wcn36xx_dxe_desc *prev_dxe = NULL; struct wcn36xx_dxe_ctl *cur_ctl = NULL; @@ -190,11 +191,11 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn switch (wcn_ch->ch_type) { case WCN36XX_DXE_CH_TX_L: cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L; - cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L; + cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L(wcn); break; case WCN36XX_DXE_CH_TX_H: cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H; - cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H; + cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H(wcn); break; case WCN36XX_DXE_CH_RX_L: cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; @@ -914,7 +915,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for TX LOW channel */ /***************************************/ - ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_tx_l_ch); if (ret) { dev_err(wcn->dev, "Error allocating descriptor\n"); return ret; @@ -928,14 +929,14 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /* Program DMA destination addr for TX LOW */ wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_DEST_ADDR_TX_L, - WCN36XX_DXE_WQ_TX_L); + WCN36XX_DXE_WQ_TX_L(wcn)); wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); /***************************************/ /* Init descriptors for TX HIGH channel */ /***************************************/ - ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_tx_h_ch); if (ret) { dev_err(wcn->dev, "Error allocating descriptor\n"); goto out_err_txh_ch; @@ -950,14 +951,14 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /* Program DMA destination addr for TX HIGH */ wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_DEST_ADDR_TX_H, - WCN36XX_DXE_WQ_TX_H); + WCN36XX_DXE_WQ_TX_H(wcn)); wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); /***************************************/ /* Init descriptors for RX LOW channel */ /***************************************/ - ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch); + ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_rx_l_ch); if (ret) { dev_err(wcn->dev, "Error allocating descriptor\n"); goto out_err_rxl_ch; @@ -988,7 +989,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for RX HIGH channel */ /***************************************/ - ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch); + ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_rx_h_ch); if (ret) { dev_err(wcn->dev, "Error allocating descriptor\n"); goto out_err_rxh_ch; diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index 26a31edf52e9..dd8c684a3ba7 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h @@ -135,8 +135,8 @@ H2H_TEST_RX_TX = DMA2 WCN36xx_DXE_CTRL_ENDIANNESS) /* TODO This must calculated properly but not hardcoded */ -#define WCN36XX_DXE_WQ_TX_L 0x17 -#define WCN36XX_DXE_WQ_TX_H 0x17 +#define WCN36XX_DXE_WQ_TX_L(wcn) ((wcn)->is_pronto_v3 ? 0x6 : 0x17) +#define WCN36XX_DXE_WQ_TX_H(wcn) ((wcn)->is_pronto_v3 ? 0x6 : 0x17) #define WCN36XX_DXE_WQ_RX_L 0xB #define WCN36XX_DXE_WQ_RX_H 0x4 diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 3b79cc1c7c5b..8dbd115a393c 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1508,6 +1508,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, } wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto"); + wcn->is_pronto_v3 = !!of_device_is_compatible(mmio_node, "qcom,pronto-v3-pil"); /* Map the CCU memory */ index = of_property_match_string(mmio_node, "reg-names", "ccu"); diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 9aa08b636d08..ff4a8e5d7209 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -217,6 +217,7 @@ struct wcn36xx { u8 fw_major; u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE]; bool is_pronto; + bool is_pronto_v3; /* extra byte for the NULL termination */ u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; From 488d9a484f96eee4f0e8e108aed42a057a1c7295 Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Tue, 7 Mar 2023 02:47:06 -0800 Subject: [PATCH 03/43] wifi: ath12k: Add missing unwind goto in ath12k_pci_probe() Smatch Warns: drivers/net/wireless/ath/ath12k/pci.c:1198 ath12k_pci_probe() warn: missing unwind goto? Store the error value in ret and use correct label with a goto. Only Compile tested, found with Smatch. Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") Reported-by: Dan Carpenter Link: https://lore.kernel.org/all/Y+426q6cfkEdb5Bv@kili/ Suggested-by: Dan Carpenter Signed-off-by: Harshit Mogalapalli Reviewed-by: Simon Horman Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230307104706.240119-1-harshit.m.mogalapalli@oracle.com --- drivers/net/wireless/ath/ath12k/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index d32637b0113d..00b0080dbac3 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -1223,7 +1223,8 @@ static int ath12k_pci_probe(struct pci_dev *pdev, dev_err(&pdev->dev, "Unknown hardware version found for QCN9274: 0x%x\n", soc_hw_version_major); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto err_pci_free_region; } break; case WCN7850_DEVICE_ID: From 3b1088a09ec9438523c251d8435e78988824bc0d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 7 Mar 2023 16:22:39 -0600 Subject: [PATCH 04/43] wifi: ath11k: Replace fake flex-array with flexible-array member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zero-length arrays as fake flexible arrays are deprecated and we are moving towards adopting C99 flexible-array members instead. Address 25 of the following warnings found with GCC-13 and -fstrict-flex-arrays=3 enabled: drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c:30:51: warning: array subscript is outside array bounds of ‘const u32[0]’ {aka ‘const unsigned int[]’} [-Warray-bounds=] This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/21 Link: https://github.com/KSPP/linux/issues/266 Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] Signed-off-by: Gustavo A. R. Silva Reviewed-by: Simon Horman Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/ZAe5L5DtmsQxzqRH@work --- .../wireless/ath/ath11k/debugfs_htt_stats.h | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h index 2b97cbbd28cb..0bbd58a380de 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h @@ -143,7 +143,8 @@ enum htt_tx_pdev_underrun_enum { /* Bytes stored in little endian order */ /* Length should be multiple of DWORD */ struct htt_stats_string_tlv { - u32 data[0]; /* Can be variable length */ + /* Can be variable length */ + DECLARE_FLEX_ARRAY(u32, data); } __packed; #define HTT_STATS_MAC_ID GENMASK(7, 0) @@ -205,27 +206,32 @@ struct htt_tx_pdev_stats_cmn_tlv { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_pdev_stats_urrn_tlv_v { - u32 urrn_stats[0]; /* HTT_TX_PDEV_MAX_URRN_STATS */ + /* HTT_TX_PDEV_MAX_URRN_STATS */ + DECLARE_FLEX_ARRAY(u32, urrn_stats); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_pdev_stats_flush_tlv_v { - u32 flush_errs[0]; /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */ + /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */ + DECLARE_FLEX_ARRAY(u32, flush_errs); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_pdev_stats_sifs_tlv_v { - u32 sifs_status[0]; /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */ + /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */ + DECLARE_FLEX_ARRAY(u32, sifs_status); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_pdev_stats_phy_err_tlv_v { - u32 phy_errs[0]; /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */ + /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */ + DECLARE_FLEX_ARRAY(u32, phy_errs); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_pdev_stats_sifs_hist_tlv_v { - u32 sifs_hist_status[0]; /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */ + /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */ + DECLARE_FLEX_ARRAY(u32, sifs_hist_status); }; struct htt_tx_pdev_stats_tx_ppdu_stats_tlv_v { @@ -590,20 +596,20 @@ struct htt_tx_hwq_difs_latency_stats_tlv_v { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_hwq_cmd_result_stats_tlv_v { - /* Histogram of sched cmd result */ - u32 cmd_result[0]; /* HTT_TX_HWQ_MAX_CMD_RESULT_STATS */ + /* Histogram of sched cmd result, HTT_TX_HWQ_MAX_CMD_RESULT_STATS */ + DECLARE_FLEX_ARRAY(u32, cmd_result); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_hwq_cmd_stall_stats_tlv_v { - /* Histogram of various pause conitions */ - u32 cmd_stall_status[0]; /* HTT_TX_HWQ_MAX_CMD_STALL_STATS */ + /* Histogram of various pause conitions, HTT_TX_HWQ_MAX_CMD_STALL_STATS */ + DECLARE_FLEX_ARRAY(u32, cmd_stall_status); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_hwq_fes_result_stats_tlv_v { - /* Histogram of number of user fes result */ - u32 fes_result[0]; /* HTT_TX_HWQ_MAX_FES_RESULT_STATS */ + /* Histogram of number of user fes result, HTT_TX_HWQ_MAX_FES_RESULT_STATS */ + DECLARE_FLEX_ARRAY(u32, fes_result); }; /* NOTE: Variable length TLV, use length spec to infer array size @@ -635,8 +641,8 @@ struct htt_tx_hwq_tried_mpdu_cnt_hist_tlv_v { * #define WAL_TXOP_USED_HISTOGRAM_INTERVAL 1000 ( 1 ms ) */ struct htt_tx_hwq_txop_used_cnt_hist_tlv_v { - /* Histogram of txop used cnt */ - u32 txop_used_cnt_hist[0]; /* HTT_TX_HWQ_TXOP_USED_CNT_HIST */ + /* Histogram of txop used cnt, HTT_TX_HWQ_TXOP_USED_CNT_HIST */ + DECLARE_FLEX_ARRAY(u32, txop_used_cnt_hist); }; /* == TX SELFGEN STATS == */ @@ -804,17 +810,20 @@ struct htt_tx_pdev_mpdu_stats_tlv { /* == TX SCHED STATS == */ /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_sched_txq_cmd_posted_tlv_v { - u32 sched_cmd_posted[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ + /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ + DECLARE_FLEX_ARRAY(u32, sched_cmd_posted); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_sched_txq_cmd_reaped_tlv_v { - u32 sched_cmd_reaped[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ + /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ + DECLARE_FLEX_ARRAY(u32, sched_cmd_reaped); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_sched_txq_sched_order_su_tlv_v { - u32 sched_order_su[0]; /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */ + /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */ + DECLARE_FLEX_ARRAY(u32, sched_order_su); }; enum htt_sched_txq_sched_ineligibility_tlv_enum { @@ -842,7 +851,7 @@ enum htt_sched_txq_sched_ineligibility_tlv_enum { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_sched_txq_sched_ineligibility_tlv_v { /* indexed by htt_sched_txq_sched_ineligibility_tlv_enum */ - u32 sched_ineligibility[0]; + DECLARE_FLEX_ARRAY(u32, sched_ineligibility); }; #define HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID GENMASK(7, 0) @@ -888,18 +897,20 @@ struct htt_stats_tx_sched_cmn_tlv { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_tqm_gen_mpdu_stats_tlv_v { - u32 gen_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */ + /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */ + DECLARE_FLEX_ARRAY(u32, gen_mpdu_end_reason); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_tqm_list_mpdu_stats_tlv_v { - u32 list_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */ + /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */ + DECLARE_FLEX_ARRAY(u32, list_mpdu_end_reason); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_tx_tqm_list_mpdu_cnt_tlv_v { - u32 list_mpdu_cnt_hist[0]; - /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */ + /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */ + DECLARE_FLEX_ARRAY(u32, list_mpdu_cnt_hist); }; struct htt_tx_tqm_pdev_stats_tlv_v { @@ -1098,7 +1109,7 @@ struct htt_tx_de_compl_stats_tlv { * ENTRIES_PER_BIN_COUNT) */ struct htt_tx_de_fw2wbm_ring_full_hist_tlv { - u32 fw2wbm_ring_full_hist[0]; + DECLARE_FLEX_ARRAY(u32, fw2wbm_ring_full_hist); }; struct htt_tx_de_cmn_stats_tlv { @@ -1151,7 +1162,7 @@ struct htt_ring_if_cmn_tlv { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_sfm_client_user_tlv_v { /* Number of DWORDS used per user and per client */ - u32 dwords_used_by_user_n[0]; + DECLARE_FLEX_ARRAY(u32, dwords_used_by_user_n); }; struct htt_sfm_client_tlv { @@ -1436,12 +1447,14 @@ struct htt_rx_soc_fw_stats_tlv { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_rx_soc_fw_refill_ring_empty_tlv_v { - u32 refill_ring_empty_cnt[0]; /* HTT_RX_STATS_REFILL_MAX_RING */ + /* HTT_RX_STATS_REFILL_MAX_RING */ + DECLARE_FLEX_ARRAY(u32, refill_ring_empty_cnt); }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_rx_soc_fw_refill_ring_num_refill_tlv_v { - u32 refill_ring_num_refill[0]; /* HTT_RX_STATS_REFILL_MAX_RING */ + /* HTT_RX_STATS_REFILL_MAX_RING */ + DECLARE_FLEX_ARRAY(u32, refill_ring_num_refill); }; /* RXDMA error code from WBM released packets */ @@ -1473,7 +1486,7 @@ enum htt_rx_rxdma_error_code_enum { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v { - u32 rxdma_err[0]; /* HTT_RX_RXDMA_MAX_ERR_CODE */ + DECLARE_FLEX_ARRAY(u32, rxdma_err); /* HTT_RX_RXDMA_MAX_ERR_CODE */ }; /* REO error code from WBM released packets */ @@ -1505,7 +1518,7 @@ enum htt_rx_reo_error_code_enum { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_rx_soc_fw_refill_ring_num_reo_err_tlv_v { - u32 reo_err[0]; /* HTT_RX_REO_MAX_ERR_CODE */ + DECLARE_FLEX_ARRAY(u32, reo_err); /* HTT_RX_REO_MAX_ERR_CODE */ }; /* == RX PDEV STATS == */ @@ -1622,13 +1635,13 @@ struct htt_rx_pdev_fw_stats_phy_err_tlv { /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_rx_pdev_fw_ring_mpdu_err_tlv_v { /* Num error MPDU for each RxDMA error type */ - u32 fw_ring_mpdu_err[0]; /* HTT_RX_STATS_RXDMA_MAX_ERR */ + DECLARE_FLEX_ARRAY(u32, fw_ring_mpdu_err); /* HTT_RX_STATS_RXDMA_MAX_ERR */ }; /* NOTE: Variable length TLV, use length spec to infer array size */ struct htt_rx_pdev_fw_mpdu_drop_tlv_v { /* Num MPDU dropped */ - u32 fw_mpdu_drop[0]; /* HTT_RX_STATS_FW_DROP_REASON_MAX */ + DECLARE_FLEX_ARRAY(u32, fw_mpdu_drop); /* HTT_RX_STATS_FW_DROP_REASON_MAX */ }; #define HTT_PDEV_CCA_STATS_TX_FRAME_INFO_PRESENT (0x1) From 5a78ac33e3cb8822da64dd1af196e83664b332b0 Mon Sep 17 00:00:00 2001 From: Aditya Kumar Singh Date: Thu, 9 Mar 2023 15:23:08 +0530 Subject: [PATCH 05/43] wifi: ath11k: fix deinitialization of firmware resources Currently, in ath11k_ahb_fw_resources_init(), iommu domain mapping is done only for the chipsets having fixed firmware memory. Also, for such chipsets, mapping is done only if it does not have TrustZone support. During deinitialization, only if TrustZone support is not there, iommu is unmapped back. However, for non fixed firmware memory chipsets, TrustZone support is not there and this makes the condition check to true and it tries to unmap the memory which was not mapped during initialization. This leads to the following trace - [ 83.198790] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008 [ 83.259537] Modules linked in: ath11k_ahb ath11k qmi_helpers .. snip .. [ 83.280286] pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 83.287228] pc : __iommu_unmap+0x30/0x140 [ 83.293907] lr : iommu_unmap+0x5c/0xa4 [ 83.298072] sp : ffff80000b3abad0 .. snip .. [ 83.369175] Call trace: [ 83.376282] __iommu_unmap+0x30/0x140 [ 83.378541] iommu_unmap+0x5c/0xa4 [ 83.382360] ath11k_ahb_fw_resource_deinit.part.12+0x2c/0xac [ath11k_ahb] [ 83.385666] ath11k_ahb_free_resources+0x140/0x17c [ath11k_ahb] [ 83.392521] ath11k_ahb_shutdown+0x34/0x40 [ath11k_ahb] [ 83.398248] platform_shutdown+0x20/0x2c [ 83.403455] device_shutdown+0x16c/0x1c4 [ 83.407621] kernel_restart_prepare+0x34/0x3c [ 83.411529] kernel_restart+0x14/0x74 [ 83.415781] __do_sys_reboot+0x1c4/0x22c [ 83.419427] __arm64_sys_reboot+0x1c/0x24 [ 83.423420] invoke_syscall+0x44/0xfc [ 83.427326] el0_svc_common.constprop.3+0xac/0xe8 [ 83.430974] do_el0_svc+0xa0/0xa8 [ 83.435659] el0_svc+0x1c/0x44 [ 83.438957] el0t_64_sync_handler+0x60/0x144 [ 83.441910] el0t_64_sync+0x15c/0x160 [ 83.446343] Code: aa0103f4 f9400001 f90027a1 d2800001 (f94006a0) [ 83.449903] ---[ end trace 0000000000000000 ]--- This can be reproduced by probing an AHB chipset which is not having a fixed memory region. During reboot (or rmmod) trace can be seen. Fix this issue by adding a condition check on firmware fixed memory hw_param as done in the counter initialization function. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Fixes: f9eec4947add ("ath11k: Add support for targets without trustzone") Signed-off-by: Aditya Kumar Singh Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230309095308.24937-1-quic_adisi@quicinc.com --- drivers/net/wireless/ath/ath11k/ahb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index b549576d0b51..5cbba9a8b6ba 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -1078,6 +1078,12 @@ static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab) struct iommu_domain *iommu; size_t unmapped_size; + /* Chipsets not requiring MSA would have not initialized + * MSA resources, return success in such cases. + */ + if (!ab->hw_params.fixed_fw_mem) + return 0; + if (ab_ahb->fw.use_tz) return 0; From 68e93ac5a31d4975b25f819b2dfe914c72abc3bb Mon Sep 17 00:00:00 2001 From: Harshitha Prem Date: Wed, 15 Mar 2023 12:24:43 +0200 Subject: [PATCH 06/43] wifi: ath11k: fix BUFFER_DONE read on monitor ring rx buffer Perform dma_sync_single_for_cpu() on monitor ring rx buffer before reading BUFFER_DONE tag and do dma_unmap_single() only after device had set BUFFER_DONE tag to the buffer. Also when BUFFER_DONE tag is not set, allow the buffer to get read next time without freeing skb. This helps to fix AP+Monitor VAP with flood traffic scenario to see monitor ring rx buffer overrun missing BUFFER_DONE tag to be set. Also remove redundant rx dma buf free performed on DP rx_mon_status_refill_ring. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sathishkumar Muruganandam Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230309164434.32660-1-quic_hprem@quicinc.com --- drivers/net/wireless/ath/ath11k/dp_rx.c | 57 ++++++++++--------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index b65a84a88264..99859b59138e 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -435,7 +435,6 @@ int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id, static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar, struct dp_rxdma_ring *rx_ring) { - struct ath11k_pdev_dp *dp = &ar->dp; struct sk_buff *skb; int buf_id; @@ -453,28 +452,6 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar, idr_destroy(&rx_ring->bufs_idr); spin_unlock_bh(&rx_ring->idr_lock); - /* if rxdma1_enable is false, mon_status_refill_ring - * isn't setup, so don't clean. - */ - if (!ar->ab->hw_params.rxdma1_enable) - return 0; - - rx_ring = &dp->rx_mon_status_refill_ring[0]; - - spin_lock_bh(&rx_ring->idr_lock); - idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) { - idr_remove(&rx_ring->bufs_idr, buf_id); - /* XXX: Understand where internal driver does this dma_unmap - * of rxdma_buffer. - */ - dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr, - skb->len + skb_tailroom(skb), DMA_BIDIRECTIONAL); - dev_kfree_skb_any(skb); - } - - idr_destroy(&rx_ring->bufs_idr); - spin_unlock_bh(&rx_ring->idr_lock); - return 0; } @@ -3029,39 +3006,51 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id, spin_lock_bh(&rx_ring->idr_lock); skb = idr_find(&rx_ring->bufs_idr, buf_id); + spin_unlock_bh(&rx_ring->idr_lock); + if (!skb) { ath11k_warn(ab, "rx monitor status with invalid buf_id %d\n", buf_id); - spin_unlock_bh(&rx_ring->idr_lock); pmon->buf_state = DP_MON_STATUS_REPLINISH; goto move_next; } - idr_remove(&rx_ring->bufs_idr, buf_id); - spin_unlock_bh(&rx_ring->idr_lock); - rxcb = ATH11K_SKB_RXCB(skb); - dma_unmap_single(ab->dev, rxcb->paddr, - skb->len + skb_tailroom(skb), - DMA_FROM_DEVICE); + dma_sync_single_for_cpu(ab->dev, rxcb->paddr, + skb->len + skb_tailroom(skb), + DMA_FROM_DEVICE); tlv = (struct hal_tlv_hdr *)skb->data; if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) != HAL_RX_STATUS_BUFFER_DONE) { - ath11k_warn(ab, "mon status DONE not set %lx\n", + ath11k_warn(ab, "mon status DONE not set %lx, buf_id %d\n", FIELD_GET(HAL_TLV_HDR_TAG, - tlv->tl)); - dev_kfree_skb_any(skb); + tlv->tl), buf_id); + /* If done status is missing, hold onto status + * ring until status is done for this status + * ring buffer. + * Keep HP in mon_status_ring unchanged, + * and break from here. + * Check status for same buffer for next time + */ pmon->buf_state = DP_MON_STATUS_NO_DMA; - goto move_next; + break; } + spin_lock_bh(&rx_ring->idr_lock); + idr_remove(&rx_ring->bufs_idr, buf_id); + spin_unlock_bh(&rx_ring->idr_lock); if (ab->hw_params.full_monitor_mode) { ath11k_dp_rx_mon_update_status_buf_state(pmon, tlv); if (paddr == pmon->mon_status_paddr) pmon->buf_state = DP_MON_STATUS_MATCH; } + + dma_unmap_single(ab->dev, rxcb->paddr, + skb->len + skb_tailroom(skb), + DMA_FROM_DEVICE); + __skb_queue_tail(skb_list, skb); } else { pmon->buf_state = DP_MON_STATUS_REPLINISH; From 960412bee0ea75f6b3c2dca4a3535795ee84c47a Mon Sep 17 00:00:00 2001 From: Rajat Soni Date: Wed, 15 Mar 2023 14:36:32 +0530 Subject: [PATCH 07/43] wifi: ath12k: fix memory leak in ath12k_qmi_driver_event_work() Currently the buffer pointed by event is not freed in case ATH12K_FLAG_UNREGISTERING bit is set, this causes memory leak. Add a goto skip instead of return, to ensure event and all the list entries are freed properly. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Rajat Soni Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230315090632.15065-1-quic_rajson@quicinc.com --- drivers/net/wireless/ath/ath12k/qmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 979a63f2e2ab..03ba245fbee9 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -2991,7 +2991,7 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work) spin_unlock(&qmi->event_lock); if (test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags)) - return; + goto skip; switch (event->type) { case ATH12K_QMI_EVENT_SERVER_ARRIVE: @@ -3032,6 +3032,8 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work) ath12k_warn(ab, "invalid event type: %d", event->type); break; } + +skip: kfree(event); spin_lock(&qmi->event_lock); } From cbc0008c9b39ea95b5125ab77fb409d9a32a42e1 Mon Sep 17 00:00:00 2001 From: Aditya Kumar Singh Date: Wed, 15 Mar 2023 17:02:02 +0530 Subject: [PATCH 08/43] wifi: ath12k: fix firmware assert during channel switch for peer sta Currently, during change in bandwidth for peer sta, host sends the new value of channel width via WMI_PEER_CHWIDTH set peer param command alone. This can lead to firmware assert in some scenario since before the command, firmware was having value of channel width and its corresponding phymode. After the command, host tries to set the new value of channel width alone which can become incompatible when compared with its phymode. For example: Bandwidth Upgrade ~~~~~~~~~~~~~~~~~~ After association, sta is in 40 MHz bandwidth in 11ax-HE40 phymode. After bandwidth upgrades, sta moves to 80 MHz but as per phymode, max bandwidth is still 40 MHz. Hence, firmware assert is seen. So in this case first phymode should be moved to 11ax-HE80 followed by bandwidth change. Bandwidth Downgrade ~~~~~~~~~~~~~~~~~~ Similarly, reverse of above is also possible when sta is in 40 MHz bandwidth in 11ax-HE40 phymode. Bandwidth should be changed to 20 MHz and if host sends phymode first then, phymode will become 11ax-HE20 and will be incompatible with bandwidth value and hence firmware assert will be seen. Hence, in this case first channel width should be set followed by phymode. Fix this issue by sending WMI set peer param command for phymode as well as bandwidth based on the type of bandwidth change i.e upgrade or downgrade. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aditya Kumar Singh Signed-off-by: Aaradhana Sahu Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230315113202.8774-1-quic_aarasahu@quicinc.com --- drivers/net/wireless/ath/ath12k/core.h | 1 + drivers/net/wireless/ath/ath12k/mac.c | 117 +++++++++++++++++++------ 2 files changed, 89 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index dffa687ee40e..9439052a652e 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -395,6 +395,7 @@ struct ath12k_sta { u8 rssi_comb; struct ath12k_rx_peer_stats *rx_stats; struct ath12k_wbm_tx_stats *wbm_tx_stats; + u32 bw_prev; }; #define ATH12K_MIN_5G_FREQ 4150 diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index bf7e5b6977b2..ee792822b411 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -3220,10 +3220,11 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) enum nl80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; - u32 changed, bw, nss, smps; + u32 changed, bw, nss, smps, bw_prev; int err, num_vht_rates; const struct cfg80211_bitrate_mask *mask; struct ath12k_wmi_peer_assoc_arg peer_arg; + enum wmi_phy_mode peer_phymode; arsta = container_of(wk, struct ath12k_sta, update_wk); sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); @@ -3243,6 +3244,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) arsta->changed = 0; bw = arsta->bw; + bw_prev = arsta->bw_prev; nss = arsta->nss; smps = arsta->smps; @@ -3255,11 +3257,53 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) ath12k_mac_max_vht_nss(vht_mcs_mask))); if (changed & IEEE80211_RC_BW_CHANGED) { - err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, - WMI_PEER_CHWIDTH, bw); - if (err) - ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", - sta->addr, bw, err); + ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg); + peer_phymode = peer_arg.peer_phymode; + + if (bw > bw_prev) { + /* Phymode shows maximum supported channel width, if we + * upgrade bandwidth then due to sanity check of firmware, + * we have to send WMI_PEER_PHYMODE followed by + * WMI_PEER_CHWIDTH + */ + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth upgrade for sta %pM new %d old %d\n", + sta->addr, bw, bw_prev); + err = ath12k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, WMI_PEER_PHYMODE, + peer_phymode); + if (err) { + ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n", + sta->addr, peer_phymode, err); + goto err_rc_bw_changed; + } + err = ath12k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, WMI_PEER_CHWIDTH, + bw); + if (err) + ath12k_warn(ar->ab, "failed to update STA %pM to peer bandwidth %d: %d\n", + sta->addr, bw, err); + } else { + /* When we downgrade bandwidth this will conflict with phymode + * and cause to trigger firmware crash. In this case we send + * WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE + */ + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth downgrade for sta %pM new %d old %d\n", + sta->addr, bw, bw_prev); + err = ath12k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, WMI_PEER_CHWIDTH, + bw); + if (err) { + ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n", + sta->addr, bw, err); + goto err_rc_bw_changed; + } + err = ath12k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, WMI_PEER_PHYMODE, + peer_phymode); + if (err) + ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n", + sta->addr, peer_phymode, err); + } } if (changed & IEEE80211_RC_NSS_CHANGED) { @@ -3321,7 +3365,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk) sta->addr, arvif->vdev_id); } } - +err_rc_bw_changed: mutex_unlock(&ar->conf_mutex); } @@ -3433,6 +3477,34 @@ static int ath12k_mac_station_add(struct ath12k *ar, return ret; } +static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar, + struct ieee80211_sta *sta) +{ + u32 bw = WMI_PEER_CHWIDTH_20MHZ; + + switch (sta->deflink.bandwidth) { + case IEEE80211_STA_RX_BW_20: + bw = WMI_PEER_CHWIDTH_20MHZ; + break; + case IEEE80211_STA_RX_BW_40: + bw = WMI_PEER_CHWIDTH_40MHZ; + break; + case IEEE80211_STA_RX_BW_80: + bw = WMI_PEER_CHWIDTH_80MHZ; + break; + case IEEE80211_STA_RX_BW_160: + bw = WMI_PEER_CHWIDTH_160MHZ; + break; + default: + ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n", + sta->deflink.bandwidth, sta->addr); + bw = WMI_PEER_CHWIDTH_20MHZ; + break; + } + + return bw; +} + static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -3498,6 +3570,13 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, if (ret) ath12k_warn(ar->ab, "Failed to associate station: %pM\n", sta->addr); + + spin_lock_bh(&ar->data_lock); + + arsta->bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta); + arsta->bw_prev = sta->deflink.bandwidth; + + spin_unlock_bh(&ar->data_lock); } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { spin_lock_bh(&ar->ab->base_lock); @@ -3607,28 +3686,8 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, spin_lock_bh(&ar->data_lock); if (changed & IEEE80211_RC_BW_CHANGED) { - bw = WMI_PEER_CHWIDTH_20MHZ; - - switch (sta->deflink.bandwidth) { - case IEEE80211_STA_RX_BW_20: - bw = WMI_PEER_CHWIDTH_20MHZ; - break; - case IEEE80211_STA_RX_BW_40: - bw = WMI_PEER_CHWIDTH_40MHZ; - break; - case IEEE80211_STA_RX_BW_80: - bw = WMI_PEER_CHWIDTH_80MHZ; - break; - case IEEE80211_STA_RX_BW_160: - bw = WMI_PEER_CHWIDTH_160MHZ; - break; - default: - ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n", - sta->deflink.bandwidth, sta->addr); - bw = WMI_PEER_CHWIDTH_20MHZ; - break; - } - + bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta); + arsta->bw_prev = arsta->bw; arsta->bw = bw; } From 4c26033d75e414cf0c500055ec58511f93684d87 Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Thu, 16 Mar 2023 12:11:44 +0800 Subject: [PATCH 09/43] wifi: ath12k: Identify DFS channel when sending scan channel list command WMI_CHAN_INFO_DFS flag should be set when configuring a DFS channel included in scan channel list. Without it, firmware will not send a probe request frame which is needed in connection to an AP configured with hidden SSID/network_id. So fix this to allow probe request frames to be sent in cases where a beacon frame has been seen on the channel first. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Baochen Qiang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230316041144.7770-1-quic_bqiang@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 3e6991120e53..af910296c41e 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -2438,6 +2438,9 @@ int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar, if (channel_arg->psc_channel) chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_PSC); + if (channel_arg->dfs_set) + chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_DFS); + chan_info->info |= le32_encode_bits(channel_arg->phy_mode, WMI_CHAN_INFO_MODE); *reg1 |= le32_encode_bits(channel_arg->minpower, From 72d17c3e86d0f7fad8f3ae77d87d00b7b6788a8e Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Fri, 17 Mar 2023 14:25:33 +0800 Subject: [PATCH 10/43] wifi: ath12k: Enable IMPS for WCN7850 To reduce power consumption, change idle_ps to true to enable Idle Mode Power Save (IMPS) for WCN7850. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Baochen Qiang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230317062533.18240-1-quic_bqiang@quicinc.com --- drivers/net/wireless/ath/ath12k/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c index 91d576fd4b0f..1ffac7e3deaa 100644 --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c @@ -944,7 +944,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .interface_modes = BIT(NL80211_IFTYPE_STATION), .supports_monitor = false, - .idle_ps = false, + .idle_ps = true, .download_calib = false, .supports_suspend = false, .tcl_ring_retry = false, From 4b50d4205207ab706b3ecd0d122c014845b8e1f0 Mon Sep 17 00:00:00 2001 From: P Praneesh Date: Fri, 17 Mar 2023 21:50:56 +0530 Subject: [PATCH 11/43] wifi: ath12k: fill peer meta data during reo_reinject Firmware expects physical address in the reo entrance ring when MLO is enabled and peer meta data in the queue_addr_lo for the non MLO cases. Current implementation fills the physical address for the non MLO cases and firmware decodes it differently which leads to SOC CSR region access which is not related to firmware/MAC operation. Fix this by sending only peer_meta data and destination indication bit during non MLO case. This prevents firmware from invalid decoding. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: P Praneesh Signed-off-by: Manish Dharanenthiran Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230317162056.20353-1-quic_mdharane@quicinc.com --- drivers/net/wireless/ath/ath12k/dp_rx.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 0adcbcfa0db5..b368494071ea 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -3047,10 +3047,14 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar, reo_ent_ring->rx_mpdu_info.peer_meta_data = reo_dest_ring->rx_mpdu_info.peer_meta_data; - reo_ent_ring->queue_addr_lo = cpu_to_le32(lower_32_bits(rx_tid->paddr)); - reo_ent_ring->info0 = le32_encode_bits(upper_32_bits(rx_tid->paddr), - HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI) | - le32_encode_bits(dst_ind, HAL_REO_ENTR_RING_INFO0_DEST_IND); + /* Firmware expects physical address to be filled in queue_addr_lo in + * the MLO scenario and in case of non MLO peer meta data needs to be + * filled. + * TODO: Need to handle for MLO scenario. + */ + reo_ent_ring->queue_addr_lo = reo_dest_ring->rx_mpdu_info.peer_meta_data; + reo_ent_ring->info0 = le32_encode_bits(dst_ind, + HAL_REO_ENTR_RING_INFO0_DEST_IND); reo_ent_ring->info1 = le32_encode_bits(rx_tid->cur_sn, HAL_REO_ENTR_RING_INFO1_MPDU_SEQ_NUM); From e93bbd65547ea8073b707c9034c3f051f8018614 Mon Sep 17 00:00:00 2001 From: Aaradhana Sahu Date: Mon, 20 Mar 2023 10:54:27 +0530 Subject: [PATCH 12/43] wifi: ath12k: fix packets are sent in native wifi mode while we set raw mode Currently, if we set raw mode as encap type, packets are sent in native wifi mode which is default mode. This is caused by no check being present for raw mode in ath12k_dp_tx_get_encap_type function, so it's always going in native wifi mode. Fix, this issue by adding check condition for raw mode. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Aaradhana Sahu Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230320052427.12271-1-quic_aarasahu@quicinc.com --- drivers/net/wireless/ath/ath12k/dp_tx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c index fd8d850f9818..d3c7c76d6b75 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c @@ -13,6 +13,10 @@ static enum hal_tcl_encap_type ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath12k_base *ab = arvif->ar->ab; + + if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) + return HAL_TCL_ENCAP_TYPE_RAW; if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) return HAL_TCL_ENCAP_TYPE_ETHERNET; From 392b6b76fd3940ba9978ecd8fe30d9ed979d3bf7 Mon Sep 17 00:00:00 2001 From: Harshitha Prem Date: Mon, 20 Mar 2023 14:34:00 +0530 Subject: [PATCH 13/43] wifi: ath12k: fix incorrect handling of AMSDU frames When a data traffic with size greater than 1500 is initiated, say size 65500, it is sent as a set of AMSDUs (3 MSDUs) in a MPDU. These AMSDUs are incorrectly classified as multicast and peer id gets changed, except for first msdu, because of mcast_bcast bit derived from rx_desc for every msdu received. The mcast_bcast bit in rx_desc is only valid for first msdu. Hence, add changes to derive mcast_bcast only if it is a first msdu. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230320090400.30027-1-quic_hprem@quicinc.com --- drivers/net/wireless/ath/ath12k/dp_rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index b368494071ea..e78478a5b978 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -196,7 +196,8 @@ static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab, static bool ath12k_dp_rx_h_is_mcbc(struct ath12k_base *ab, struct hal_rx_desc *desc) { - return ab->hw_params->hal_ops->rx_desc_is_mcbc(desc); + return (ath12k_dp_rx_h_first_msdu(ab, desc) && + ab->hw_params->hal_ops->rx_desc_is_mcbc(desc)); } static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab, From 25d165c498025f401eed6503f03115c1fb896c47 Mon Sep 17 00:00:00 2001 From: Harshitha Prem Date: Mon, 20 Mar 2023 14:42:08 +0530 Subject: [PATCH 14/43] wifi: ath12k: incorrect channel survey dump When underlying hardware supports more than one band, then wiphy is aware of all the frequency bands present. Example, say wiphy0 is aware of 2 GHz, 5 GHz and 6 GHz band information. Hence, when an virtual AP interface is brought up in auto channel selection on each band. Survey is initiated from the userspace application for all the virtual AP interfaces simultaneously. For survey dump collection, freq_to_idx() api is used to map the index of particular frequency to populate its survey. When the dump was collected, the index fetched was incorrect. Example, in case of multi-hardware, the index of channel 36 was reported as 14, because wiphy0 had index 0-13 for 2 GHz channels, instead of 0 for that ar which resulted in invalid survey sent to userspace application. The incorrect index was because of the mapping did not consider whether the freq band is present in its radio structure (ar) or not. To handle this, the freq_to_idx() api should map index for the particular band in the ar structure. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230320091208.25535-1-quic_hprem@quicinc.com --- drivers/net/wireless/ath/ath12k/wmi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index af910296c41e..7ae0bb78b2b5 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -4937,6 +4937,9 @@ static int freq_to_idx(struct ath12k *ar, int freq) int band, ch, idx = 0; for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { + if (!ar->mac.sbands[band].channels) + continue; + sband = ar->hw->wiphy->bands[band]; if (!sband) continue; From b6b88111c0dbcef04cd0e0bafd646e4c09728302 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 21 Mar 2023 10:40:10 +0100 Subject: [PATCH 15/43] dt-bindings: net: wireless: add ath11k pcie bindings Add devicetree bindings for Qualcomm ath11k PCIe devices such as WCN6855 for which the calibration data variant may need to be described. Signed-off-by: Johan Hovold Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230321094011.9759-2-johan+linaro@kernel.org --- .../net/wireless/qcom,ath11k-pci.yaml | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml new file mode 100644 index 000000000000..817f02a8b481 --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) 2023 Linaro Limited +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/wireless/qcom,ath11k-pci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies ath11k wireless devices (PCIe) + +maintainers: + - Kalle Valo + +description: | + Qualcomm Technologies IEEE 802.11ax PCIe devices + +properties: + compatible: + enum: + - pci17cb,1103 # WCN6855 + + reg: + maxItems: 1 + + qcom,ath11k-calibration-variant: + $ref: /schemas/types.yaml#/definitions/string + description: | + string to uniquely identify variant of the calibration data for designs + with colliding bus and device ids + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + pcie { + #address-cells = <3>; + #size-cells = <2>; + + pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + bus-range = <0x01 0xff>; + + wifi@0 { + compatible = "pci17cb,1103"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + + qcom,ath11k-calibration-variant = "LE_X13S"; + }; + }; + }; From 9fc093b756f64788ce33e3484f6f59a169704759 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Wed, 22 Mar 2023 08:28:55 -0400 Subject: [PATCH 16/43] wifi: ath10k: remove unused ath10k_get_ring_byte function clang with W=1 reports: drivers/net/wireless/ath/ath10k/ce.c:88:1: error: unused function 'ath10k_get_ring_byte' [-Werror,-Wunused-function] ath10k_get_ring_byte(unsigned int offset, ^ This function is not used so remove it. Signed-off-by: Tom Rix Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230322122855.2570417-1-trix@redhat.com --- drivers/net/wireless/ath/ath10k/ce.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index b656cfc03648..c27b8204718a 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -84,13 +84,6 @@ ath10k_set_ring_byte(unsigned int offset, return ((offset << addr_map->lsb) & addr_map->mask); } -static inline unsigned int -ath10k_get_ring_byte(unsigned int offset, - struct ath10k_hw_ce_regs_addr_map *addr_map) -{ - return ((offset & addr_map->mask) >> (addr_map->lsb)); -} - static inline u32 ath10k_ce_read32(struct ath10k *ar, u32 offset) { struct ath10k_ce *ce = ath10k_ce_priv(ar); From 72383ed78c1c01d36612ca5c6fdd2f35fd859bbd Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 17 Mar 2023 11:30:47 -0600 Subject: [PATCH 17/43] wifi: carl9170: Fix multiple -Warray-bounds warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC (and Clang)[1] does not like having a partially allocated object, since it cannot reason about it for bounds checking. Instead, fully allocate struct carl9170_cmd. Fix the following warnings Seen under GCC 13: drivers/net/wireless/ath/carl9170/cmd.c:125:30: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[4]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:126:30: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[4]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:125:30: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[20]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:126:30: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[20]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:161:12: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[20]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:162:12: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[20]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:163:12: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[20]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:164:12: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[20]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:125:30: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[8]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:126:30: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[8]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/cmd.c:220:12: warning: array subscript ‘struct carl9170_cmd[0]’ is partly outside array bounds of ‘unsigned char[8]’ [-Warray-bounds=] Link: https://github.com/KSPP/linux/issues/268 Link: godbolt.org/z/KP97sxh3T [1] Signed-off-by: Gustavo A. R. Silva Acked-by: Christian Lamparter Reviewed-by: Kees Cook Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/ZBSjx236+BTiRByf@work --- drivers/net/wireless/ath/carl9170/cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c index f2b4f537e4c1..b8ed193c0195 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.c +++ b/drivers/net/wireless/ath/carl9170/cmd.c @@ -120,7 +120,7 @@ struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, { struct carl9170_cmd *tmp; - tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC); + tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); if (tmp) { tmp->hdr.cmd = cmd; tmp->hdr.len = len; From 1be3640cbb4a52ac9a2653ff20d68f983366092c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 17 Mar 2023 11:39:36 -0600 Subject: [PATCH 18/43] wifi: carl9170: Replace fake flex-array with flexible-array member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zero-length arrays as fake flexible arrays are deprecated and we are moving towards adopting C99 flexible-array members instead. Address the following warnings found with GCC-13 and -fstrict-flex-arrays=3 enabled: drivers/net/wireless/ath/carl9170/tx.c:702:61: warning: array subscript i is outside array bounds of ‘const struct _carl9170_tx_status[0]’ [-Warray-bounds=] drivers/net/wireless/ath/carl9170/tx.c:701:65: warning: array subscript i is outside array bounds of ‘const struct _carl9170_tx_status[0]’ [-Warray-bounds=] This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. Link: https://github.com/KSPP/linux/issues/21 Link: https://github.com/KSPP/linux/issues/267 Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] Signed-off-by: Gustavo A. R. Silva Acked-by: Christian Lamparter Reviewed-by: Kees Cook Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/ZBSl2M+aGIO1fnuG@work --- drivers/net/wireless/ath/carl9170/fwcmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index ff4b3b50250c..e5bcc364f088 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -320,9 +320,9 @@ struct carl9170_rsp { struct carl9170_u32_list rreg_res; struct carl9170_u32_list echo; #ifdef __CARL9170FW__ - struct carl9170_tx_status tx_status[0]; + DECLARE_FLEX_ARRAY(struct carl9170_tx_status, tx_status); #endif /* __CARL9170FW__ */ - struct _carl9170_tx_status _tx_status[0]; + DECLARE_FLEX_ARRAY(struct _carl9170_tx_status, _tx_status); struct carl9170_gpio gpio; struct carl9170_tsf_rsp tsf; struct carl9170_psm psm; From 8b4d2f080afbd4280ecca0f4b3ceea943a7a86d0 Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Thu, 23 Mar 2023 11:39:13 +0530 Subject: [PATCH 19/43] wifi: ath11k: Optimize 6 GHz scan time Currently, time taken to scan all supported channels on WCN6750 is ~8 seconds and connection time is almost 10 seconds. WCN6750 supports three Wi-Fi bands (i.e., 2.4/5/6 GHz) and the numbers of channels for scan come around ~100 channels (default case). Since the chip doesn't have support for DBS (Dual Band Simultaneous), scans cannot be parallelized resulting in longer scan times. Among the 100 odd channels, ~60 channels are in 6 GHz band. Therefore, optimizing the scan for 6 GHz channels will bring down the overall scan time. WCN6750 firmware has support to scan a 6 GHz channel based on co-located AP information i.e., RNR IE which is found in the legacy 2.4/5 GHz scan results. When a scan request with all supported channel list is enqueued to the firmware, then based on WMI_SCAN_CHAN_FLAG_SCAN_ONLY_IF_RNR_FOUND scan channel flag, firmware will scan only those 6 GHz channels for which RNR IEs are found in the legacy scan results. In the proposed design, based on NL80211_SCAN_FLAG_COLOCATED_6GHZ scan flag, driver will set the WMI_SCAN_CHAN_FLAG_SCAN_ONLY_IF_RNR_FOUND flag for non-PSC channels. Since there is high probability to find 6 GHz APs on PSC channels, these channels are always scanned. Only non-PSC channels are selectively scanned based on cached RNR information from the legacy scan results. If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set in the scan flags, then scan will happen on all supported channels (default behavior). With these optimizations, scan time is improved by 1.5-1.8 seconds on WCN6750. Similar savings have been observed on WCN6855. Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.16 Signed-off-by: Manikanta Pubbisetty Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230323060913.10097-1-quic_mpubbise@quicinc.com --- drivers/net/wireless/ath/ath11k/mac.c | 25 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath11k/wmi.h | 4 ++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index cad832e0e6b8..c81b238d0d91 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -3819,8 +3819,29 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, goto exit; } - for (i = 0; i < arg->num_chan; i++) - arg->chan_list[i] = req->channels[i]->center_freq; + for (i = 0; i < arg->num_chan; i++) { + if (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL, + ar->ab->wmi_ab.svc_map)) { + arg->chan_list[i] = + u32_encode_bits(req->channels[i]->center_freq, + WMI_SCAN_CONFIG_PER_CHANNEL_MASK); + + /* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is set in scan + * flags, then scan all PSC channels in 6 GHz band and + * those non-PSC channels where RNR IE is found during + * the legacy 2.4/5 GHz scan. + * If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set, + * then all channels in 6 GHz will be scanned. + */ + if (req->channels[i]->band == NL80211_BAND_6GHZ && + req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ && + !cfg80211_channel_is_psc(req->channels[i])) + arg->chan_list[i] |= + WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND; + } else { + arg->chan_list[i] = req->channels[i]->center_freq; + } + } } if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index b23b7a22bc9a..86b22f2cec12 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -2100,6 +2100,7 @@ enum wmi_tlv_service { /* The second 128 bits */ WMI_MAX_EXT_SERVICE = 256, + WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL = 265, WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326, @@ -3249,6 +3250,9 @@ struct wmi_start_scan_cmd { #define WMI_SCAN_DWELL_MODE_SHIFT 21 #define WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE 0x00000800 +#define WMI_SCAN_CONFIG_PER_CHANNEL_MASK GENMASK(19, 0) +#define WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND BIT(20) + enum { WMI_SCAN_DWELL_MODE_DEFAULT = 0, WMI_SCAN_DWELL_MODE_CONSERVATIVE = 1, From 813968c24126cc5c8320cd5db0e262069a535063 Mon Sep 17 00:00:00 2001 From: Ganesh Babu Jothiram Date: Fri, 24 Mar 2023 16:57:00 +0200 Subject: [PATCH 20/43] wifi: ath11k: Configure the FTM responder role using firmware capability flag Fine Time Measurement(FTM) is offloaded feature to firmware. Hence, the configuration of FTM responder role is done using firmware capability flag instead of hw param. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Ganesh Babu Jothiram Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230317072034.8217-1-quic_gjothira@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 8 -------- drivers/net/wireless/ath/ath11k/hw.h | 1 - drivers/net/wireless/ath/ath11k/mac.c | 4 ++-- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 75fdbe4ef83a..498310e38d44 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -116,7 +116,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .tcl_ring_retry = true, .tx_ring_size = DP_TCL_DATA_RING_SIZE, .smp2p_wow_exit = false, - .ftm_responder = true, }, { .hw_rev = ATH11K_HW_IPQ6018_HW10, @@ -199,7 +198,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .tx_ring_size = DP_TCL_DATA_RING_SIZE, .smp2p_wow_exit = false, .support_fw_mac_sequence = false, - .ftm_responder = true, }, { .name = "qca6390 hw2.0", @@ -284,7 +282,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .tx_ring_size = DP_TCL_DATA_RING_SIZE, .smp2p_wow_exit = false, .support_fw_mac_sequence = true, - .ftm_responder = false, }, { .name = "qcn9074 hw1.0", @@ -366,7 +363,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .tx_ring_size = DP_TCL_DATA_RING_SIZE, .smp2p_wow_exit = false, .support_fw_mac_sequence = false, - .ftm_responder = true, }, { .name = "wcn6855 hw2.0", @@ -451,7 +447,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .tx_ring_size = DP_TCL_DATA_RING_SIZE, .smp2p_wow_exit = false, .support_fw_mac_sequence = true, - .ftm_responder = false, }, { .name = "wcn6855 hw2.1", @@ -534,7 +529,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .tx_ring_size = DP_TCL_DATA_RING_SIZE, .smp2p_wow_exit = false, .support_fw_mac_sequence = true, - .ftm_responder = false, }, { .name = "wcn6750 hw1.0", @@ -615,7 +609,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750, .smp2p_wow_exit = true, .support_fw_mac_sequence = true, - .ftm_responder = false, }, { .hw_rev = ATH11K_HW_IPQ5018_HW10, @@ -695,7 +688,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .tx_ring_size = DP_TCL_DATA_RING_SIZE, .smp2p_wow_exit = false, .support_fw_mac_sequence = false, - .ftm_responder = true, }, }; diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 0be4e1232384..9f45d061d826 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -224,7 +224,6 @@ struct ath11k_hw_params { u32 tx_ring_size; bool smp2p_wow_exit; bool support_fw_mac_sequence; - bool ftm_responder; }; struct ath11k_hw_ops { diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index c81b238d0d91..7226d88c0c48 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -3538,7 +3538,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_FTM_RESPONDER && arvif->ftm_responder != info->ftm_responder && - ar->ab->hw_params.ftm_responder && + test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map) && (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT)) { arvif->ftm_responder = info->ftm_responder; @@ -9234,7 +9234,7 @@ static int __ath11k_mac_register(struct ath11k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); - if (ab->hw_params.ftm_responder) + if (test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map)) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); From 031ffa6c2cd305a57ccc6d610f2decd956b2e7f6 Mon Sep 17 00:00:00 2001 From: P Praneesh Date: Fri, 24 Mar 2023 16:57:00 +0200 Subject: [PATCH 21/43] wifi: ath11k: fix rssi station dump not updated in QCN9074 In QCN9074, station dump signal values display default value which is -95 dbm, since there is firmware header change for HAL_RX_MPDU_START between QCN9074 and IPQ8074 which cause wrong peer_id fetch from msdu. Fix this by updating hal_rx_mpdu_info with corresponding QCN9074 tlv format. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01695-QCAHKSWPL_SILICONZ-1 Signed-off-by: P Praneesh Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230320110312.20639-1-quic_ppranees@quicinc.com --- drivers/net/wireless/ath/ath11k/hal_rx.c | 10 ++++++++- drivers/net/wireless/ath/ath11k/hal_rx.h | 18 +++++++++++++++- drivers/net/wireless/ath/ath11k/hw.c | 27 ++++++++++++++++-------- drivers/net/wireless/ath/ath11k/hw.h | 2 +- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c index 7f39c6fb7408..b9939c5a4ecd 100644 --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c @@ -865,6 +865,12 @@ ath11k_hal_rx_populate_mu_user_info(void *rx_tlv, struct hal_rx_mon_ppdu_info *p ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status); } +static u16 ath11k_hal_rx_mpduinfo_get_peerid(struct ath11k_base *ab, + struct hal_rx_mpdu_info *mpdu_info) +{ + return ab->hw_params.hw_ops->mpdu_info_get_peerid(mpdu_info); +} + static enum hal_rx_mon_status ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab, struct hal_rx_mon_ppdu_info *ppdu_info, @@ -1459,9 +1465,11 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab, break; } case HAL_RX_MPDU_START: { + struct hal_rx_mpdu_info *mpdu_info = + (struct hal_rx_mpdu_info *)tlv_data; u16 peer_id; - peer_id = ab->hw_params.hw_ops->mpdu_info_get_peerid(tlv_data); + peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info); if (peer_id) ppdu_info->peer_id = peer_id; break; diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.h b/drivers/net/wireless/ath/ath11k/hal_rx.h index f6bae07abfd3..47e8208b22e1 100644 --- a/drivers/net/wireless/ath/ath11k/hal_rx.h +++ b/drivers/net/wireless/ath/ath11k/hal_rx.h @@ -405,7 +405,7 @@ struct hal_rx_phyrx_rssi_legacy_info { #define HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855 GENMASK(15, 0) #define HAL_RX_MPDU_INFO_INFO1_MPDU_LEN GENMASK(13, 0) -struct hal_rx_mpdu_info { +struct hal_rx_mpdu_info_ipq8074 { __le32 rsvd0; __le32 info0; __le32 rsvd1[11]; @@ -413,12 +413,28 @@ struct hal_rx_mpdu_info { __le32 rsvd2[9]; } __packed; +struct hal_rx_mpdu_info_qcn9074 { + __le32 rsvd0[10]; + __le32 info0; + __le32 rsvd1[2]; + __le32 info1; + __le32 rsvd2[9]; +} __packed; + struct hal_rx_mpdu_info_wcn6855 { __le32 rsvd0[8]; __le32 info0; __le32 rsvd1[14]; } __packed; +struct hal_rx_mpdu_info { + union { + struct hal_rx_mpdu_info_ipq8074 ipq8074; + struct hal_rx_mpdu_info_qcn9074 qcn9074; + struct hal_rx_mpdu_info_wcn6855 wcn6855; + } u; +} __packed; + #define HAL_RX_PPDU_END_DURATION GENMASK(23, 0) struct hal_rx_ppdu_end_duration { __le32 rsvd0[9]; diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c index 60ac215e0678..6b4355a68e26 100644 --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c @@ -835,26 +835,35 @@ static void ath11k_hw_ipq5018_reo_setup(struct ath11k_base *ab) ring_hash_map); } -static u16 ath11k_hw_ipq8074_mpdu_info_get_peerid(u8 *tlv_data) +static u16 +ath11k_hw_ipq8074_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info) { u16 peer_id = 0; - struct hal_rx_mpdu_info *mpdu_info = - (struct hal_rx_mpdu_info *)tlv_data; peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID, - __le32_to_cpu(mpdu_info->info0)); + __le32_to_cpu(mpdu_info->u.ipq8074.info0)); return peer_id; } -static u16 ath11k_hw_wcn6855_mpdu_info_get_peerid(u8 *tlv_data) +static u16 +ath11k_hw_qcn9074_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info) +{ + u16 peer_id = 0; + + peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID, + __le32_to_cpu(mpdu_info->u.qcn9074.info0)); + + return peer_id; +} + +static u16 +ath11k_hw_wcn6855_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info) { u16 peer_id = 0; - struct hal_rx_mpdu_info_wcn6855 *mpdu_info = - (struct hal_rx_mpdu_info_wcn6855 *)tlv_data; peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855, - __le32_to_cpu(mpdu_info->info0)); + __le32_to_cpu(mpdu_info->u.wcn6855.info0)); return peer_id; } @@ -1042,7 +1051,7 @@ const struct ath11k_hw_ops qcn9074_ops = { .rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention, .rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload, .reo_setup = ath11k_hw_ipq8074_reo_setup, - .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, + .mpdu_info_get_peerid = ath11k_hw_qcn9074_mpdu_info_get_peerid, .rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid, .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, .get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector, diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 9f45d061d826..6a5dd2dbdb3a 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -263,7 +263,7 @@ struct ath11k_hw_ops { struct rx_attention *(*rx_desc_get_attention)(struct hal_rx_desc *desc); u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc); void (*reo_setup)(struct ath11k_base *ab); - u16 (*mpdu_info_get_peerid)(u8 *tlv_data); + u16 (*mpdu_info_get_peerid)(struct hal_rx_mpdu_info *mpdu_info); bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc); u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc); u32 (*get_ring_selector)(struct sk_buff *skb); From 447b0398a9cd41ca343dfd43e555af92d6214487 Mon Sep 17 00:00:00 2001 From: Bhagavathi Perumal S Date: Fri, 24 Mar 2023 16:57:00 +0200 Subject: [PATCH 22/43] wifi: ath11k: Fix invalid management rx frame length issue The WMI management rx event has multiple arrays of TLVs, however the common WMI TLV parser won't handle multiple TLV tags of same type. So the multiple array tags of WMI management rx TLV is parsed incorrectly and the length calculated becomes wrong when the target sends multiple array tags. Add separate TLV parser to handle multiple arrays for WMI management rx TLV. This fixes invalid length issue when the target sends multiple array tags. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Bhagavathi Perumal S Co-developed-by: Nagarajan Maran Signed-off-by: Nagarajan Maran Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230320133840.30162-1-quic_nmaran@quicinc.com --- drivers/net/wireless/ath/ath11k/wmi.c | 45 +++++++++++++++++++++------ 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 27f3fceb33c5..f338d4447f11 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -82,6 +82,12 @@ struct wmi_tlv_fw_stats_parse { bool chain_rssi_done; }; +struct wmi_tlv_mgmt_rx_parse { + const struct wmi_mgmt_rx_hdr *fixed; + const u8 *frame_buf; + bool frame_buf_done; +}; + static const struct wmi_tlv_policy wmi_tlv_policies[] = { [WMI_TAG_ARRAY_BYTE] = { .min_len = 0 }, @@ -5633,28 +5639,49 @@ static int ath11k_pull_vdev_stopped_param_tlv(struct ath11k_base *ab, struct sk_ return 0; } +static int ath11k_wmi_tlv_mgmt_rx_parse(struct ath11k_base *ab, + u16 tag, u16 len, + const void *ptr, void *data) +{ + struct wmi_tlv_mgmt_rx_parse *parse = data; + + switch (tag) { + case WMI_TAG_MGMT_RX_HDR: + parse->fixed = ptr; + break; + case WMI_TAG_ARRAY_BYTE: + if (!parse->frame_buf_done) { + parse->frame_buf = ptr; + parse->frame_buf_done = true; + } + break; + } + return 0; +} + static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab, struct sk_buff *skb, struct mgmt_rx_event_params *hdr) { - const void **tb; + struct wmi_tlv_mgmt_rx_parse parse = { }; const struct wmi_mgmt_rx_hdr *ev; const u8 *frame; int ret; - tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); - if (IS_ERR(tb)) { - ret = PTR_ERR(tb); - ath11k_warn(ab, "failed to parse tlv: %d\n", ret); + ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len, + ath11k_wmi_tlv_mgmt_rx_parse, + &parse); + if (ret) { + ath11k_warn(ab, "failed to parse mgmt rx tlv %d\n", + ret); return ret; } - ev = tb[WMI_TAG_MGMT_RX_HDR]; - frame = tb[WMI_TAG_ARRAY_BYTE]; + ev = parse.fixed; + frame = parse.frame_buf; if (!ev || !frame) { ath11k_warn(ab, "failed to fetch mgmt rx hdr"); - kfree(tb); return -EPROTO; } @@ -5673,7 +5700,6 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab, if (skb->len < (frame - skb->data) + hdr->buf_len) { ath11k_warn(ab, "invalid length in mgmt rx hdr ev"); - kfree(tb); return -EPROTO; } @@ -5685,7 +5711,6 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab, ath11k_ce_byte_swap(skb->data, hdr->buf_len); - kfree(tb); return 0; } From 756a7f90878f0866fd2fe167ef37e90b47326b96 Mon Sep 17 00:00:00 2001 From: P Praneesh Date: Fri, 24 Mar 2023 16:57:01 +0200 Subject: [PATCH 23/43] wifi: ath11k: fix writing to unintended memory region While initializing spectral, the magic value is getting written to the invalid memory address leading to random boot-up crash. This occurs due to the incorrect index increment in ath11k_dbring_fill_magic_value function. Fix it by replacing the existing logic with memset32 to ensure there is no invalid memory access. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.4.0.1-01838-QCAHKSWPL_SILICONZ-1 Fixes: d3d358efc553 ("ath11k: add spectral/CFR buffer validation support") Signed-off-by: P Praneesh Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230321052900.16895-1-quic_ppranees@quicinc.com --- drivers/net/wireless/ath/ath11k/dbring.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dbring.c b/drivers/net/wireless/ath/ath11k/dbring.c index 2107ec05d14f..5536e8642331 100644 --- a/drivers/net/wireless/ath/ath11k/dbring.c +++ b/drivers/net/wireless/ath/ath11k/dbring.c @@ -26,13 +26,13 @@ int ath11k_dbring_validate_buffer(struct ath11k *ar, void *buffer, u32 size) static void ath11k_dbring_fill_magic_value(struct ath11k *ar, void *buffer, u32 size) { - u32 *temp; - int idx; + /* memset32 function fills buffer payload with the ATH11K_DB_MAGIC_VALUE + * and the variable size is expected to be the number of u32 values + * to be stored, not the number of bytes. + */ + size = size / sizeof(u32); - size = size >> 2; - - for (idx = 0, temp = buffer; idx < size; idx++, temp++) - *temp++ = ATH11K_DB_MAGIC_VALUE; + memset32(buffer, ATH11K_DB_MAGIC_VALUE, size); } static int ath11k_dbring_bufs_replenish(struct ath11k *ar, From e89a51aedf380bc60219dc9afa96c36507060fb3 Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Wed, 15 Mar 2023 21:48:17 +0530 Subject: [PATCH 24/43] wifi: ath11k: Send 11d scan start before WMI_START_SCAN_CMDID Firmwares advertising the support of triggering 11d algorithm on the scan results of a regular scan expects driver to send WMI_11D_SCAN_START_CMDID before sending WMI_START_SCAN_CMDID. Triggering 11d algorithm on the scan results of a normal scan helps in completely avoiding a separate 11d scan for determining regdomain. This indirectly helps in speeding up connections on station interfaces on the chipsets supporting 11D scan. To enable this feature, send WMI_11D_SCAN_START_CMDID just before sending WMI_START_SCAN_CMDID if the firmware advertises WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN service flag. WCN6750 & WCN6855 supports this feature. Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-01160-QCAMSLSWPLZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23 Signed-off-by: Manikanta Pubbisetty Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230315161817.29627-1-quic_mpubbise@quicinc.com --- drivers/net/wireless/ath/ath11k/mac.c | 12 ++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 7226d88c0c48..c0dc3e387aad 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -3755,6 +3755,18 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, int i; u32 scan_timeout; + /* Firmwares advertising the support of triggering 11D algorithm + * on the scan results of a regular scan expects driver to send + * WMI_11D_SCAN_START_CMDID before sending WMI_START_SCAN_CMDID. + * With this feature, separate 11D scan can be avoided since + * regdomain can be determined with the scan results of the + * regular scan. + */ + if (ar->state_11d == ATH11K_11D_PREPARING && + test_bit(WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN, + ar->ab->wmi_ab.svc_map)) + ath11k_mac_11d_scan_start(ar, arvif->vdev_id); + mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 86b22f2cec12..92fddb77669c 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -2103,6 +2103,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL = 265, WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326, + WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN = 357, /* The third 128 bits */ WMI_MAX_EXT2_SERVICE = 384 From f812e2a9f85d6bea78957ccb5197e4491316848b Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Thu, 23 Mar 2023 19:26:09 +0800 Subject: [PATCH 25/43] wifi: ath11k: Remove redundant pci_clear_master Remove pci_clear_master to simplify the code, the bus-mastering is also cleared in do_pci_disable_device, like this: ./drivers/pci/pci.c:2197 static void do_pci_disable_device(struct pci_dev *dev) { u16 pci_command; pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, pci_command); } pcibios_disable_device(dev); }. And dev->is_busmaster is set to 0 in pci_disable_device. Signed-off-by: Cai Huoqing Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230323112613.7550-1-cai.huoqing@linux.dev --- drivers/net/wireless/ath/ath11k/pci.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 0aeef2948ff5..522d01e5e11c 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -540,7 +540,7 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev) if (!ab->mem) { ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM); ret = -EIO; - goto clear_master; + goto release_region; } ab->mem_ce = ab->mem; @@ -548,8 +548,6 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev) ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem); return 0; -clear_master: - pci_clear_master(pdev); release_region: pci_release_region(pdev, ATH11K_PCI_BAR_NUM); disable_device: @@ -565,7 +563,6 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci) pci_iounmap(pci_dev, ab->mem); ab->mem = NULL; - pci_clear_master(pci_dev); pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM); if (pci_is_enabled(pci_dev)) pci_disable_device(pci_dev); From 76008fc13b09a89e4251e6af5062043427babaa2 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Thu, 23 Mar 2023 19:26:10 +0800 Subject: [PATCH 26/43] wifi: ath10k: Remove redundant pci_clear_master Remove pci_clear_master to simplify the code, the bus-mastering is also cleared in do_pci_disable_device, like this: ./drivers/pci/pci.c:2197 static void do_pci_disable_device(struct pci_dev *dev) { u16 pci_command; pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, pci_command); } pcibios_disable_device(dev); }. And dev->is_busmaster is set to 0 in pci_disable_device. Signed-off-by: Cai Huoqing Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230323112613.7550-2-cai.huoqing@linux.dev --- drivers/net/wireless/ath/ath10k/pci.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 728d607289c3..a7f44f6335fb 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3406,15 +3406,12 @@ static int ath10k_pci_claim(struct ath10k *ar) if (!ar_pci->mem) { ath10k_err(ar, "failed to iomap BAR%d\n", BAR_NUM); ret = -EIO; - goto err_master; + goto err_region; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot pci_mem 0x%pK\n", ar_pci->mem); return 0; -err_master: - pci_clear_master(pdev); - err_region: pci_release_region(pdev, BAR_NUM); @@ -3431,7 +3428,6 @@ static void ath10k_pci_release(struct ath10k *ar) pci_iounmap(pdev, ar_pci->mem); pci_release_region(pdev, BAR_NUM); - pci_clear_master(pdev); pci_disable_device(pdev); } From b9235aef84929e5330cb87125a6baf1cf7988983 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Thu, 23 Mar 2023 19:26:11 +0800 Subject: [PATCH 27/43] wifi: ath12k: Remove redundant pci_clear_master Remove pci_clear_master to simplify the code, the bus-mastering is also cleared in do_pci_disable_device, like this: ./drivers/pci/pci.c:2197 static void do_pci_disable_device(struct pci_dev *dev) { u16 pci_command; pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, pci_command); } pcibios_disable_device(dev); }. And dev->is_busmaster is set to 0 in pci_disable_device. Signed-off-by: Cai Huoqing Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230323112613.7550-3-cai.huoqing@linux.dev --- drivers/net/wireless/ath/ath12k/pci.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 00b0080dbac3..9f174daf324c 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -755,14 +755,12 @@ static int ath12k_pci_claim(struct ath12k_pci *ab_pci, struct pci_dev *pdev) if (!ab->mem) { ath12k_err(ab, "failed to map pci bar %d\n", ATH12K_PCI_BAR_NUM); ret = -EIO; - goto clear_master; + goto release_region; } ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem); return 0; -clear_master: - pci_clear_master(pdev); release_region: pci_release_region(pdev, ATH12K_PCI_BAR_NUM); disable_device: @@ -778,7 +776,6 @@ static void ath12k_pci_free_region(struct ath12k_pci *ab_pci) pci_iounmap(pci_dev, ab->mem); ab->mem = NULL; - pci_clear_master(pci_dev); pci_release_region(pci_dev, ATH12K_PCI_BAR_NUM); if (pci_is_enabled(pci_dev)) pci_disable_device(pci_dev); From 5c690db63b45c6c4c4932b13173af71df369dba5 Mon Sep 17 00:00:00 2001 From: Tamizh Chelvam Raja Date: Tue, 28 Mar 2023 12:41:50 +0530 Subject: [PATCH 28/43] wifi: ath11k: Disable Spectral scan upon removing interface Host might receive spectral events during interface down sequence and this might create below errors. failed to handle dma buf release event -22 failed to handle dma buf release event -22 Fix this by disabling spectral config during remove interface. Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 Signed-off-by: Tamizh Chelvam Raja Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230328071150.29645-1-quic_tamizhr@quicinc.com --- drivers/net/wireless/ath/ath11k/mac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index c0dc3e387aad..4447fd4bd68f 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -6685,6 +6685,11 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw, ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n", arvif->vdev_id); + ret = ath11k_spectral_vif_stop(arvif); + if (ret) + ath11k_warn(ab, "failed to stop spectral for vdev %i: %d\n", + arvif->vdev_id, ret); + if (arvif->vdev_type == WMI_VDEV_TYPE_STA) ath11k_mac_11d_scan_stop(ar); From abf57d84973ce1abcb67504ac0df8aea1fe09a76 Mon Sep 17 00:00:00 2001 From: Youghandhar Chintala Date: Tue, 28 Mar 2023 17:04:55 +0530 Subject: [PATCH 29/43] wifi: ath11k: enable SAR support on WCN6750 Currently, SAR is enabled only on WCN6855, enable this for WCN6750 too. This functionality gets triggered, when the user space application calls NL80211_CMD_SET_SAR_SPECS. Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 Signed-off-by: Youghandhar Chintala Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230328113455.11252-1-quic_youghand@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 498310e38d44..b1b90bd34d67 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -593,7 +593,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .current_cc_support = true, .dbr_debug_support = false, .global_reset = false, - .bios_sar_capa = NULL, + .bios_sar_capa = &ath11k_hw_sar_capa_wcn6855, .m3_fw_support = false, .fixed_bdf_addr = false, .fixed_mem_region = false, From 06c58473969239e00d76b683edd511952060ca56 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 30 Mar 2023 16:37:18 +0200 Subject: [PATCH 30/43] wifi: ath11k: pci: Add more MODULE_FIRMWARE() entries As there are a few more models supported by the driver, let's add the missing MODULE_FIRMWARE() entries for them. The lack of them resulted in the missing device enablement on some systems, such as the installation image of openSUSE. While we are at it, use the wildcard instead of listing each firmware files individually for each. Signed-off-by: Takashi Iwai Reviewed-by: Simon Horman Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230330143718.19511-1-tiwai@suse.de --- drivers/net/wireless/ath/ath11k/pci.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 522d01e5e11c..7b33731a50ee 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -1036,7 +1036,8 @@ module_exit(ath11k_pci_exit); MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices"); MODULE_LICENSE("Dual BSD/GPL"); -/* QCA639x 2.0 firmware files */ -MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_BOARD_API2_FILE); -MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_AMSS_FILE); -MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_M3_FILE); +/* firmware files */ +MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/*"); +MODULE_FIRMWARE(ATH11K_FW_DIR "/QCN9074/hw1.0/*"); +MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.0/*"); +MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.1/*"); From a87a9110ac0dcbfd9458b6665c141fa1c16a669d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 5 Apr 2023 12:04:25 +0300 Subject: [PATCH 31/43] wifi: ath11k: print a warning when crypto_alloc_shash() fails Christoph reported that ath11k failed to initialise when michael_mic.ko module was not installed. To make it easier to notice that case print a warning when crypto_alloc_shash() fails. Compile tested only. Reported-by: Christoph Hellwig Link: https://lore.kernel.org/all/20221130133016.GC3055@lst.de/ Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230405090425.1351-1-kvalo@kernel.org --- drivers/net/wireless/ath/ath11k/dp_rx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 99859b59138e..d22e5349c551 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -3106,8 +3106,11 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id int i; tfm = crypto_alloc_shash("michael_mic", 0, 0); - if (IS_ERR(tfm)) + if (IS_ERR(tfm)) { + ath11k_warn(ab, "failed to allocate michael_mic shash: %ld\n", + PTR_ERR(tfm)); return PTR_ERR(tfm); + } spin_lock_bh(&ab->base_lock); From a06bfb3c9f69f303692cdae87bc0899d2ae8b2a6 Mon Sep 17 00:00:00 2001 From: Harshitha Prem Date: Tue, 4 Apr 2023 00:11:54 +0530 Subject: [PATCH 32/43] wifi: ath11k: Ignore frags from uninitialized peer in dp. When max virtual ap interfaces are configured in all the bands with ACS and hostapd restart is done every 60s, a crash is observed at random times. In this certain scenario, a fragmented packet is received for self peer, for which rx_tid and rx_frags are not initialized in datapath. While handling this fragment, crash is observed as the rx_frag list is uninitialised and when we walk in ath11k_dp_rx_h_sort_frags, skb null leads to exception. To address this, before processing received fragments we check dp_setup_done flag is set to ensure that peer has completed its dp peer setup for fragment queue, else ignore processing the fragments. Call trace: ath11k_dp_process_rx_err+0x550/0x1084 [ath11k] ath11k_dp_service_srng+0x70/0x370 [ath11k] 0xffffffc009693a04 __napi_poll+0x30/0xa4 net_rx_action+0x118/0x270 __do_softirq+0x10c/0x244 irq_exit+0x64/0xb4 __handle_domain_irq+0x88/0xac gic_handle_irq+0x74/0xbc el1_irq+0xf0/0x1c0 arch_cpu_idle+0x10/0x18 do_idle+0x104/0x248 cpu_startup_entry+0x20/0x64 rest_init+0xd0/0xdc arch_call_rest_init+0xc/0x14 start_kernel+0x480/0x4b8 Code: f9400281 f94066a2 91405021 b94a0023 (f9406401) Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Harshitha Prem Signed-off-by: Nagarajan Maran Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230403184155.8670-2-quic_nmaran@quicinc.com --- drivers/net/wireless/ath/ath11k/dp.c | 4 +++- drivers/net/wireless/ath/ath11k/dp_rx.c | 8 ++++++++ drivers/net/wireless/ath/ath11k/peer.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c index f5156a7fbdd7..d070bcb3fe24 100644 --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -36,6 +36,7 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr) } ath11k_peer_rx_tid_cleanup(ar, peer); + peer->dp_setup_done = false; crypto_free_shash(peer->tfm_mmic); spin_unlock_bh(&ab->base_lock); } @@ -72,7 +73,8 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr) ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id); if (ret) { ath11k_warn(ab, "failed to setup rx defrag context\n"); - return ret; + tid--; + goto peer_clean; } /* TODO: Setup other peer specific resource used in data path */ diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index d22e5349c551..ab6b18de6371 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -3130,6 +3130,7 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id } peer->tfm_mmic = tfm; + peer->dp_setup_done = true; spin_unlock_bh(&ab->base_lock); return 0; @@ -3575,6 +3576,13 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar, ret = -ENOENT; goto out_unlock; } + if (!peer->dp_setup_done) { + ath11k_warn(ab, "The peer %pM [%d] has uninitialized datapath\n", + peer->addr, peer_id); + ret = -ENOENT; + goto out_unlock; + } + rx_tid = &peer->rx_tid[tid]; if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) || diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h index 6dd17bafe3a0..9bd385d0a38c 100644 --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h @@ -35,6 +35,7 @@ struct ath11k_peer { u16 sec_type; u16 sec_type_grp; bool is_authorized; + bool dp_setup_done; }; void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); From 41e02bf4ae32cf2ac47b08b4caaa9c1a032e4ce7 Mon Sep 17 00:00:00 2001 From: Harshitha Prem Date: Tue, 4 Apr 2023 00:11:55 +0530 Subject: [PATCH 33/43] wifi: ath11k: fix undefined behavior with __fls in dp "__fls" would have an undefined behavior if the argument is passed as "0". Hence, added changes to handle the same. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Harshitha Prem Signed-off-by: Nagarajan Maran Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230403184155.8670-3-quic_nmaran@quicinc.com --- drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index ab6b18de6371..847da167a41c 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -3598,7 +3598,7 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar, goto out_unlock; } - if (frag_no > __fls(rx_tid->rx_frag_bitmap)) + if (!rx_tid->rx_frag_bitmap || (frag_no > __fls(rx_tid->rx_frag_bitmap))) __skb_queue_tail(&rx_tid->rx_frags, msdu); else ath11k_dp_rx_h_sort_frags(ar, &rx_tid->rx_frags, msdu); From e04e4b6e01e71978d5df92a5f25b472e1827b46b Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Thu, 30 Mar 2023 15:21:59 +0200 Subject: [PATCH 34/43] wifi: ath9k: fix per-packet TX-power cap for TPC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix incorrect usage of plain rate_idx as index into the max (power) per rate lookup table. For transmit power control (TPC), the ath9k driver maintains internal tables (in struct ath_hw) to store the max allowed power level per rate. They are used to limit a given TX-power according to regulatory and user limits in the TX-path per packet. The tables are filled in a predefined order, starting with values for CCK + OFDM rates and followed by the values for MCS rates. Thus, the maximum power levels for MCS do not start at index 0 in the table but are shifted by a fixed value. The TX-power limiting in ath_get_rate_txpower currently does not apply this shift, thus retrieves the incorrect maximum power level for a given rate. In particular for MCS rates, the maximum power levels for CCK/OFDM rates were used, e.g. maximum power for OFDM 0 was used for MCS 0. If STBC is used, the power is mostly limited to 0 because the STBC table is zeroed for legacy CCK/OFDM rates. Encountered this during testing of our work-in-progress TPC per packet for ath9k. This only has an effect when TPC is enabled in ath9k (tpc_enabled in struct ath_hw) which defaults to false. In this case it has a significant impact on the used TX-power, throughput + RSSI. Otherwise the affected code is just skipped and TX-power is limited with the hardware registers only. This patch fixes this table lookup. Tested on OpenWrt (kernel 5.15.98, but backported ath9k driver) with small desk setup using ath9k chips AR9280 and AR9580. Cap of TX-power is working properly for all rates now, throughput and RSSI as expected, equal to as if TPC was disabled. Compile-tested with latest 6.3 kernel + allyesconfig. Signed-off-by: Jonas Jelonek Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230330132159.758088-1-jelonek.jonas@gmail.com --- drivers/net/wireless/ath/ath9k/xmit.c | 30 +++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index ef9a8e0b75e6..f6f2ab7a63ff 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -34,6 +34,12 @@ #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) +/* Shifts in ar5008_phy.c and ar9003_phy.c are equal for all revisions */ +#define ATH9K_PWRTBL_11NA_OFDM_SHIFT 0 +#define ATH9K_PWRTBL_11NG_OFDM_SHIFT 4 +#define ATH9K_PWRTBL_11NA_HT_SHIFT 8 +#define ATH9K_PWRTBL_11NG_HT_SHIFT 12 + static u16 bits_per_symbol[][2] = { /* 20MHz 40MHz */ @@ -1169,13 +1175,14 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop) } static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, - u8 rateidx, bool is_40, bool is_cck) + u8 rateidx, bool is_40, bool is_cck, bool is_mcs) { u8 max_power; struct sk_buff *skb; struct ath_frame_info *fi; struct ieee80211_tx_info *info; struct ath_hw *ah = sc->sc_ah; + bool is_2ghz, is_5ghz, use_stbc; if (sc->tx99_state || !ah->tpc_enabled) return MAX_RATE_POWER; @@ -1184,6 +1191,19 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, fi = get_frame_info(skb); info = IEEE80211_SKB_CB(skb); + is_2ghz = info->band == NL80211_BAND_2GHZ; + is_5ghz = info->band == NL80211_BAND_5GHZ; + use_stbc = is_mcs && rateidx < 8 && (info->flags & + IEEE80211_TX_CTL_STBC); + + if (is_mcs) + rateidx += is_5ghz ? ATH9K_PWRTBL_11NA_HT_SHIFT + : ATH9K_PWRTBL_11NG_HT_SHIFT; + else if (is_2ghz && !is_cck) + rateidx += ATH9K_PWRTBL_11NG_OFDM_SHIFT; + else + rateidx += ATH9K_PWRTBL_11NA_OFDM_SHIFT; + if (!AR_SREV_9300_20_OR_LATER(ah)) { int txpower = fi->tx_power; @@ -1193,10 +1213,8 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, u16 eeprom_rev = ah->eep_ops->get_eeprom_rev(ah); if (eeprom_rev >= AR5416_EEP_MINOR_VER_2) { - bool is_2ghz; struct modal_eep_header *pmodal; - is_2ghz = info->band == NL80211_BAND_2GHZ; pmodal = &eep->modalHeader[is_2ghz]; power_ht40delta = pmodal->ht40PowerIncForPdadc; } else { @@ -1229,7 +1247,7 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, if (!max_power && !AR_SREV_9280_20_OR_LATER(ah)) max_power = 1; } else if (!bf->bf_state.bfs_paprd) { - if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC)) + if (use_stbc) max_power = min_t(u8, ah->tx_power_stbc[rateidx], fi->tx_power); else @@ -1319,7 +1337,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, } info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, - is_40, false); + is_40, false, true); continue; } @@ -1350,7 +1368,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, is_cck = IS_CCK_RATE(info->rates[i].Rate); info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, false, - is_cck); + is_cck, false); } /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ From ed09c61eb19d9889780c791cb316ac76468f5186 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 17 Apr 2023 13:35:00 +0300 Subject: [PATCH 35/43] dt-bindings: net: Convert ath10k to YAML Convert the ath10k bindings to YAML. Dropped properties that are absent at the current state of mainline: - qcom,msi_addr - qcom,msi_base Somewhat based on the ath11k bindings. Signed-off-by: Konrad Dybcio Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230406-topic-ath10k_bindings-v4-1-9f67a6bb0d56@linaro.org --- .../bindings/net/wireless/qcom,ath10k.txt | 215 ----------- .../bindings/net/wireless/qcom,ath10k.yaml | 358 ++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 359 insertions(+), 216 deletions(-) delete mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt deleted file mode 100644 index b61c2d5a0ff7..000000000000 --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt +++ /dev/null @@ -1,215 +0,0 @@ -* Qualcomm Atheros ath10k wireless devices - -Required properties: -- compatible: Should be one of the following: - * "qcom,ath10k" - * "qcom,ipq4019-wifi" - * "qcom,wcn3990-wifi" - -PCI based devices uses compatible string "qcom,ath10k" and takes calibration -data along with board specific data via "qcom,ath10k-calibration-data". -Rest of the properties are not applicable for PCI based devices. - -AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi" -and also uses most of the properties defined in this doc (except -"qcom,ath10k-calibration-data"). It uses "qcom,ath10k-pre-calibration-data" -to carry pre calibration data. - -In general, entry "qcom,ath10k-pre-calibration-data" and -"qcom,ath10k-calibration-data" conflict with each other and only one -can be provided per device. - -SNOC based devices (i.e. wcn3990) uses compatible string "qcom,wcn3990-wifi". - -- reg: Address and length of the register set for the device. -- reg-names: Must include the list of following reg names, - "membase" -- interrupts: reference to the list of 17 interrupt numbers for "qcom,ipq4019-wifi" - compatible target. - reference to the list of 12 interrupt numbers for "qcom,wcn3990-wifi" - compatible target. - Must contain interrupt-names property per entry for - "qcom,ath10k", "qcom,ipq4019-wifi" compatible targets. - -- interrupt-names: Must include the entries for MSI interrupt - names ("msi0" to "msi15") and legacy interrupt - name ("legacy") for "qcom,ath10k", "qcom,ipq4019-wifi" - compatible targets. - -Optional properties: -- resets: Must contain an entry for each entry in reset-names. - See ../reset/reseti.txt for details. -- reset-names: Must include the list of following reset names, - "wifi_cpu_init" - "wifi_radio_srif" - "wifi_radio_warm" - "wifi_radio_cold" - "wifi_core_warm" - "wifi_core_cold" -- clocks: List of clock specifiers, must contain an entry for each required - entry in clock-names. -- clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref", - "wifi_wcss_rtc" for "qcom,ipq4019-wifi" compatible target and - "cxo_ref_clk_pin" and optionally "qdss" for "qcom,wcn3990-wifi" - compatible target. -- qcom,msi_addr: MSI interrupt address. -- qcom,msi_base: Base value to add before writing MSI data into - MSI address register. -- qcom,ath10k-calibration-variant: string to search for in the board-2.bin - variant list with the same bus and device - specific ids -- qcom,ath10k-calibration-data : calibration data + board specific data - as an array, the length can vary between - hw versions. -- qcom,ath10k-pre-calibration-data : pre calibration data as an array, - the length can vary between hw versions. -- -supply: handle to the regulator device tree node - optional "supply-name" are "vdd-0.8-cx-mx", - "vdd-1.8-xo", "vdd-1.3-rfa", "vdd-3.3-ch0", - and "vdd-3.3-ch1". -- memory-region: - Usage: optional - Value type: - Definition: reference to the reserved-memory for the msa region - used by the wifi firmware running in Q6. -- iommus: - Usage: optional - Value type: - Definition: A list of phandle and IOMMU specifier pairs. -- ext-fem-name: - Usage: Optional - Value type: string - Definition: Name of external front end module used. Some valid FEM names - for example: "microsemi-lx5586", "sky85703-11" - and "sky85803" etc. -- qcom,snoc-host-cap-8bit-quirk: - Usage: Optional - Value type: - Definition: Quirk specifying that the firmware expects the 8bit version - of the host capability QMI request -- qcom,xo-cal-data: xo cal offset to be configured in xo trim register. - -- qcom,msa-fixed-perm: Boolean context flag to disable SCM call for statically - mapped msa region. - -- qcom,coexist-support : should contain eithr "0" or "1" to indicate coex - support by the hardware. -- qcom,coexist-gpio-pin : gpio pin number information to support coex - which will be used by wifi firmware. - -* Subnodes -The ath10k wifi node can contain one optional firmware subnode. -Firmware subnode is needed when the platform does not have TustZone. -The firmware subnode must have: - -- iommus: - Usage: required - Value type: - Definition: A list of phandle and IOMMU specifier pairs. - - -Example (to supply PCI based wifi block details): - -In this example, the node is defined as child node of the PCI controller. - -pci { - pcie@0 { - reg = <0 0 0 0 0>; - #interrupt-cells = <1>; - #size-cells = <2>; - #address-cells = <3>; - device_type = "pci"; - - wifi@0,0 { - reg = <0 0 0 0 0>; - qcom,ath10k-calibration-data = [ 01 02 03 ... ]; - ext-fem-name = "microsemi-lx5586"; - }; - }; -}; - -Example (to supply ipq4019 SoC wifi block details): - -wifi0: wifi@a000000 { - compatible = "qcom,ipq4019-wifi"; - reg = <0xa000000 0x200000>; - resets = <&gcc WIFI0_CPU_INIT_RESET>, - <&gcc WIFI0_RADIO_SRIF_RESET>, - <&gcc WIFI0_RADIO_WARM_RESET>, - <&gcc WIFI0_RADIO_COLD_RESET>, - <&gcc WIFI0_CORE_WARM_RESET>, - <&gcc WIFI0_CORE_COLD_RESET>; - reset-names = "wifi_cpu_init", - "wifi_radio_srif", - "wifi_radio_warm", - "wifi_radio_cold", - "wifi_core_warm", - "wifi_core_cold"; - clocks = <&gcc GCC_WCSS2G_CLK>, - <&gcc GCC_WCSS2G_REF_CLK>, - <&gcc GCC_WCSS2G_RTC_CLK>; - clock-names = "wifi_wcss_cmd", - "wifi_wcss_ref", - "wifi_wcss_rtc"; - interrupts = <0 0x20 0x1>, - <0 0x21 0x1>, - <0 0x22 0x1>, - <0 0x23 0x1>, - <0 0x24 0x1>, - <0 0x25 0x1>, - <0 0x26 0x1>, - <0 0x27 0x1>, - <0 0x28 0x1>, - <0 0x29 0x1>, - <0 0x2a 0x1>, - <0 0x2b 0x1>, - <0 0x2c 0x1>, - <0 0x2d 0x1>, - <0 0x2e 0x1>, - <0 0x2f 0x1>, - <0 0xa8 0x0>; - interrupt-names = "msi0", "msi1", "msi2", "msi3", - "msi4", "msi5", "msi6", "msi7", - "msi8", "msi9", "msi10", "msi11", - "msi12", "msi13", "msi14", "msi15", - "legacy"; - qcom,msi_addr = <0x0b006040>; - qcom,msi_base = <0x40>; - qcom,ath10k-pre-calibration-data = [ 01 02 03 ... ]; - qcom,coexist-support = <1>; - qcom,coexist-gpio-pin = <0x33>; -}; - -Example (to supply wcn3990 SoC wifi block details): - -wifi@18000000 { - compatible = "qcom,wcn3990-wifi"; - reg = <0x18800000 0x800000>; - reg-names = "membase"; - clocks = <&clock_gcc clk_rf_clk2_pin>; - clock-names = "cxo_ref_clk_pin"; - interrupts = - , - , - , - , - , - , - , - , - , - , - , - ; - vdd-0.8-cx-mx-supply = <&pm8998_l5>; - vdd-1.8-xo-supply = <&vreg_l7a_1p8>; - vdd-1.3-rfa-supply = <&vreg_l17a_1p3>; - vdd-3.3-ch0-supply = <&vreg_l25a_3p3>; - vdd-3.3-ch1-supply = <&vreg_l26a_3p3>; - memory-region = <&wifi_msa_mem>; - iommus = <&apps_smmu 0x0040 0x1>; - qcom,msa-fixed-perm; - wifi-firmware { - iommus = <&apps_iommu 0xc22 0x1>; - }; -}; diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml new file mode 100644 index 000000000000..c85ed330426d --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml @@ -0,0 +1,358 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/wireless/qcom,ath10k.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies ath10k wireless devices + +maintainers: + - Kalle Valo + +description: + Qualcomm Technologies, Inc. IEEE 802.11ac devices. + +properties: + compatible: + enum: + - qcom,ath10k # SDIO-based devices + - qcom,ipq4019-wifi + - qcom,wcn3990-wifi # SNoC-based devices + + reg: + maxItems: 1 + + reg-names: + items: + - const: membase + + interrupts: + minItems: 12 + maxItems: 17 + + interrupt-names: + minItems: 12 + maxItems: 17 + + memory-region: + maxItems: 1 + description: + Reference to the MSA memory region used by the Wi-Fi firmware + running on the Q6 core. + + iommus: + minItems: 1 + maxItems: 2 + + clocks: + minItems: 1 + maxItems: 3 + + clock-names: + minItems: 1 + maxItems: 3 + + resets: + maxItems: 6 + + reset-names: + items: + - const: wifi_cpu_init + - const: wifi_radio_srif + - const: wifi_radio_warm + - const: wifi_radio_cold + - const: wifi_core_warm + - const: wifi_core_cold + + ext-fem-name: + $ref: /schemas/types.yaml#/definitions/string + description: Name of external front end module used. + enum: + - microsemi-lx5586 + - sky85703-11 + - sky85803 + + wifi-firmware: + type: object + additionalProperties: false + description: | + The ath10k Wi-Fi node can contain one optional firmware subnode. + Firmware subnode is needed when the platform does not have Trustzone. + properties: + iommus: + maxItems: 1 + required: + - iommus + + qcom,ath10k-calibration-data: + $ref: /schemas/types.yaml#/definitions/uint8-array + description: + Calibration data + board-specific data as a byte array. The length + can vary between hardware versions. + + qcom,ath10k-calibration-variant: + $ref: /schemas/types.yaml#/definitions/string + description: + Unique variant identifier of the calibration data in board-2.bin + for designs with colliding bus and device specific ids + + qcom,ath10k-pre-calibration-data: + $ref: /schemas/types.yaml#/definitions/uint8-array + description: + Pre-calibration data as a byte array. The length can vary between + hardware versions. + + qcom,coexist-support: + $ref: /schemas/types.yaml#/definitions/uint8 + enum: [0, 1] + description: + Indicate coex support by the hardware. + + qcom,coexist-gpio-pin: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + COEX GPIO number provided to the Wi-Fi firmware. + + qcom,msa-fixed-perm: + type: boolean + description: + Whether to skip executing an SCM call that reassigns the memory + region ownership. + + qcom,smem-states: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: State bits used by the AP to signal the WLAN Q6. + items: + - description: Signal bits used to enable/disable low power mode + on WCN in the case of WoW (Wake on Wireless). + + qcom,smem-state-names: + description: The names of the state bits used for SMP2P output. + items: + - const: wlan-smp2p-out + + qcom,snoc-host-cap-8bit-quirk: + type: boolean + description: + Quirk specifying that the firmware expects the 8bit version + of the host capability QMI request + + qcom,xo-cal-data: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + XO cal offset to be configured in XO trim register. + + vdd-0.8-cx-mx-supply: + description: Main logic power rail + + vdd-1.8-xo-supply: + description: Crystal oscillator supply + + vdd-1.3-rfa-supply: + description: RFA supply + + vdd-3.3-ch0-supply: + description: Primary Wi-Fi antenna supply + + vdd-3.3-ch1-supply: + description: Secondary Wi-Fi antenna supply + +required: + - compatible + - reg + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,ipq4019-wifi + then: + properties: + interrupts: + minItems: 17 + maxItems: 17 + + interrupt-names: + items: + - const: msi0 + - const: msi1 + - const: msi2 + - const: msi3 + - const: msi4 + - const: msi5 + - const: msi6 + - const: msi7 + - const: msi8 + - const: msi9 + - const: msi10 + - const: msi11 + - const: msi12 + - const: msi13 + - const: msi14 + - const: msi15 + - const: legacy + + clocks: + items: + - description: Wi-Fi command clock + - description: Wi-Fi reference clock + - description: Wi-Fi RTC clock + + clock-names: + items: + - const: wifi_wcss_cmd + - const: wifi_wcss_ref + - const: wifi_wcss_rtc + + required: + - clocks + - clock-names + - interrupts + - interrupt-names + - resets + - reset-names + + - if: + properties: + compatible: + contains: + enum: + - qcom,wcn3990-wifi + + then: + properties: + clocks: + minItems: 1 + items: + - description: XO reference clock + - description: Qualcomm Debug Subsystem clock + + clock-names: + minItems: 1 + items: + - const: cxo_ref_clk_pin + - const: qdss + + interrupts: + items: + - description: CE0 + - description: CE1 + - description: CE2 + - description: CE3 + - description: CE4 + - description: CE5 + - description: CE6 + - description: CE7 + - description: CE8 + - description: CE9 + - description: CE10 + - description: CE11 + + interrupt-names: false + + required: + - interrupts + +examples: + # SNoC + - | + #include + #include + + wifi@18800000 { + compatible = "qcom,wcn3990-wifi"; + reg = <0x18800000 0x800000>; + reg-names = "membase"; + memory-region = <&wlan_msa_mem>; + clocks = <&rpmcc RPM_SMD_RF_CLK2_PIN>; + clock-names = "cxo_ref_clk_pin"; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + iommus = <&anoc2_smmu 0x1900>, + <&anoc2_smmu 0x1901>; + qcom,snoc-host-cap-8bit-quirk; + vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>; + vdd-1.8-xo-supply = <&vreg_l7a_1p8>; + vdd-1.3-rfa-supply = <&vreg_l17a_1p3>; + vdd-3.3-ch0-supply = <&vreg_l25a_3p3>; + vdd-3.3-ch1-supply = <&vreg_l23a_3p3>; + + wifi-firmware { + iommus = <&apps_smmu 0x1c02 0x1>; + }; + }; + + # AHB + - | + #include + + wifi@a000000 { + compatible = "qcom,ipq4019-wifi"; + reg = <0xa000000 0x200000>; + resets = <&gcc WIFI0_CPU_INIT_RESET>, + <&gcc WIFI0_RADIO_SRIF_RESET>, + <&gcc WIFI0_RADIO_WARM_RESET>, + <&gcc WIFI0_RADIO_COLD_RESET>, + <&gcc WIFI0_CORE_WARM_RESET>, + <&gcc WIFI0_CORE_COLD_RESET>; + reset-names = "wifi_cpu_init", + "wifi_radio_srif", + "wifi_radio_warm", + "wifi_radio_cold", + "wifi_core_warm", + "wifi_core_cold"; + clocks = <&gcc GCC_WCSS2G_CLK>, + <&gcc GCC_WCSS2G_REF_CLK>, + <&gcc GCC_WCSS2G_RTC_CLK>; + clock-names = "wifi_wcss_cmd", + "wifi_wcss_ref", + "wifi_wcss_rtc"; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "msi8", + "msi9", + "msi10", + "msi11", + "msi12", + "msi13", + "msi14", + "msi15", + "legacy"; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 8d5bc223f305..c659e12e0c4f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17196,7 +17196,7 @@ S: Supported W: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git F: drivers/net/wireless/ath/ath10k/ -F: Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt +F: Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml QUALCOMM ATHEROS ATH11K WIRELESS DRIVER M: Kalle Valo From 93a91f40c25c3d0e61f8540a7accf105090f9995 Mon Sep 17 00:00:00 2001 From: Harshitha Prem Date: Mon, 17 Apr 2023 13:35:00 +0300 Subject: [PATCH 36/43] wifi: ath11k: fix double free of peer rx_tid during reo cmd failure Peer rx_tid is locally copied thrice during peer_rx_tid_cleanup to send REO_CMD_UPDATE_RX_QUEUE followed by REO_CMD_FLUSH_CACHE to flush all aged REO descriptors from HW cache. When sending REO_CMD_FLUSH_CACHE fails, we do dma unmap of already mapped rx_tid->vaddr and free it. This is not checked during reo_cmd_list_cleanup() and dp_reo_cmd_free() before trying to free and unmap again. Fix this by setting rx_tid->vaddr NULL in rx tid delete and also wherever freeing it to check in reo_cmd_list_cleanup() and reo_cmd_free() before trying to free again. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sathishkumar Muruganandam Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230403182420.23375-2-quic_hprem@quicinc.com --- drivers/net/wireless/ath/ath11k/dp_rx.c | 43 ++++++++++++++++++------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 847da167a41c..1d45aa018df3 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -668,13 +668,18 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab) struct ath11k_dp *dp = &ab->dp; struct dp_reo_cmd *cmd, *tmp; struct dp_reo_cache_flush_elem *cmd_cache, *tmp_cache; + struct dp_rx_tid *rx_tid; spin_lock_bh(&dp->reo_cmd_lock); list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { list_del(&cmd->list); - dma_unmap_single(ab->dev, cmd->data.paddr, - cmd->data.size, DMA_BIDIRECTIONAL); - kfree(cmd->data.vaddr); + rx_tid = &cmd->data; + if (rx_tid->vaddr) { + dma_unmap_single(ab->dev, rx_tid->paddr, + rx_tid->size, DMA_BIDIRECTIONAL); + kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; + } kfree(cmd); } @@ -682,9 +687,13 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab) &dp->reo_cmd_cache_flush_list, list) { list_del(&cmd_cache->list); dp->reo_cmd_cache_flush_count--; - dma_unmap_single(ab->dev, cmd_cache->data.paddr, - cmd_cache->data.size, DMA_BIDIRECTIONAL); - kfree(cmd_cache->data.vaddr); + rx_tid = &cmd_cache->data; + if (rx_tid->vaddr) { + dma_unmap_single(ab->dev, rx_tid->paddr, + rx_tid->size, DMA_BIDIRECTIONAL); + kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; + } kfree(cmd_cache); } spin_unlock_bh(&dp->reo_cmd_lock); @@ -698,10 +707,12 @@ static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx, if (status != HAL_REO_CMD_SUCCESS) ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n", rx_tid->tid, status); - - dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, - DMA_BIDIRECTIONAL); - kfree(rx_tid->vaddr); + if (rx_tid->vaddr) { + dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, + DMA_BIDIRECTIONAL); + kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; + } } static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, @@ -740,6 +751,7 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, DMA_BIDIRECTIONAL); kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; } } @@ -792,6 +804,7 @@ static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx, dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, DMA_BIDIRECTIONAL); kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; } void ath11k_peer_rx_tid_delete(struct ath11k *ar, @@ -804,6 +817,8 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar, if (!rx_tid->active) return; + rx_tid->active = false; + cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; cmd.addr_lo = lower_32_bits(rx_tid->paddr); cmd.addr_hi = upper_32_bits(rx_tid->paddr); @@ -818,9 +833,11 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar, dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size, DMA_BIDIRECTIONAL); kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; } - rx_tid->active = false; + rx_tid->paddr = 0; + rx_tid->size = 0; } static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab, @@ -967,6 +984,7 @@ static void ath11k_dp_rx_tid_mem_free(struct ath11k_base *ab, dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, DMA_BIDIRECTIONAL); kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; rx_tid->active = false; @@ -1067,7 +1085,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, return ret; err_mem_free: - kfree(vaddr); + kfree(rx_tid->vaddr); + rx_tid->vaddr = NULL; return ret; } From a8ae833657a45746debde85c38bb7f070d344026 Mon Sep 17 00:00:00 2001 From: Harshitha Prem Date: Mon, 17 Apr 2023 13:35:01 +0300 Subject: [PATCH 37/43] wifi: ath11k: Prevent REO cmd failures Prevent REO cmd failures causing double free by increasing REO cmd ring size and moving REO status ring mask to IRQ group 3 from group 0 to separate from tx completion ring on IRQ group 0 which may delay reo status processing. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sathishkumar Muruganandam Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230403182420.23375-3-quic_hprem@quicinc.com --- drivers/net/wireless/ath/ath11k/dp.h | 2 +- drivers/net/wireless/ath/ath11k/hw.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h index be9eafc872b3..6022e27ba91d 100644 --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h @@ -214,7 +214,7 @@ struct ath11k_pdev_dp { #define DP_REO_REINJECT_RING_SIZE 32 #define DP_RX_RELEASE_RING_SIZE 1024 #define DP_REO_EXCEPTION_RING_SIZE 128 -#define DP_REO_CMD_RING_SIZE 128 +#define DP_REO_CMD_RING_SIZE 256 #define DP_REO_STATUS_RING_SIZE 2048 #define DP_RXDMA_BUF_RING_SIZE 4096 #define DP_RXDMA_REFILL_RING_SIZE 2048 diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c index 6b4355a68e26..eb995f9cf0fa 100644 --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c @@ -1233,6 +1233,7 @@ const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074 = { ATH11K_RX_WBM_REL_RING_MASK_0, }, .reo_status = { + 0, 0, 0, ATH11K_REO_STATUS_RING_MASK_0, }, .rxdma2host = { From 20487cc3ff36bbfa9505f0a078ba98f09abfc717 Mon Sep 17 00:00:00 2001 From: Harshitha Prem Date: Mon, 17 Apr 2023 13:35:01 +0300 Subject: [PATCH 38/43] wifi: ath11k: add peer mac information in failure cases During reo command failure, the peer mac detail for which the reo command was not successful is unknown. Hence, to improve the debuggability, add the peer mac information in the failure cases which would be useful during multi client cases. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sathishkumar Muruganandam Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230403182420.23375-4-quic_hprem@quicinc.com --- drivers/net/wireless/ath/ath11k/dp_rx.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 1d45aa018df3..a4934bd79969 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -1009,7 +1009,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, peer = ath11k_peer_find(ab, vdev_id, peer_mac); if (!peer) { - ath11k_warn(ab, "failed to find the peer to set up rx tid\n"); + ath11k_warn(ab, "failed to find the peer %pM to set up rx tid\n", + peer_mac); spin_unlock_bh(&ab->base_lock); return -ENOENT; } @@ -1022,7 +1023,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, ba_win_sz, ssn, true); spin_unlock_bh(&ab->base_lock); if (ret) { - ath11k_warn(ab, "failed to update reo for rx tid %d\n", tid); + ath11k_warn(ab, "failed to update reo for peer %pM rx tid %d\n: %d", + peer_mac, tid, ret); return ret; } @@ -1030,8 +1032,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, peer_mac, paddr, tid, 1, ba_win_sz); if (ret) - ath11k_warn(ab, "failed to send wmi command to update rx reorder queue, tid :%d (%d)\n", - tid, ret); + ath11k_warn(ab, "failed to send wmi rx reorder queue for peer %pM tid %d: %d\n", + peer_mac, tid, ret); return ret; } @@ -1064,6 +1066,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, ret = dma_mapping_error(ab->dev, paddr); if (ret) { spin_unlock_bh(&ab->base_lock); + ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n", + peer_mac, tid, ret); goto err_mem_free; } @@ -1077,8 +1081,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, paddr, tid, 1, ba_win_sz); if (ret) { - ath11k_warn(ar->ab, "failed to setup rx reorder queue, tid :%d (%d)\n", - tid, ret); + ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n", + peer_mac, tid, ret); ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid); } From 6257c702264c44d74c6b71f0c62a7665da2dc356 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Chitrapu Date: Mon, 17 Apr 2023 13:35:02 +0300 Subject: [PATCH 39/43] wifi: ath11k: fix tx status reporting in encap offload mode ieee80211_tx_status() treats packets in 802.11 frame format and tries to extract sta address from packet header. When tx encap offload is enabled, this becomes invalid operation. Hence, switch to using ieee80211_tx_status_ext() after filling in station address for handling both 802.11 and 802.3 frames. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230403195738.25367-2-quic_pradeepc@quicinc.com --- drivers/net/wireless/ath/ath11k/dp.h | 4 +++ drivers/net/wireless/ath/ath11k/dp_tx.c | 33 ++++++++++++++++++++++++- drivers/net/wireless/ath/ath11k/dp_tx.h | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h index 6022e27ba91d..d04f78ab6b37 100644 --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h @@ -303,12 +303,16 @@ struct ath11k_dp { #define HTT_TX_WBM_COMP_STATUS_OFFSET 8 +#define HTT_INVALID_PEER_ID 0xffff + /* HTT tx completion is overlaid in wbm_release_ring */ #define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(12, 9) #define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13) #define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13) #define HTT_TX_WBM_COMP_INFO1_ACK_RSSI GENMASK(31, 24) +#define HTT_TX_WBM_COMP_INFO2_SW_PEER_ID GENMASK(15, 0) +#define HTT_TX_WBM_COMP_INFO2_VALID BIT(21) struct htt_tx_wbm_completion { u32 info0; diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 8afbba236935..08a28464eb7a 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -316,10 +316,12 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab, struct dp_tx_ring *tx_ring, struct ath11k_dp_htt_wbm_tx_status *ts) { + struct ieee80211_tx_status status = { 0 }; struct sk_buff *msdu; struct ieee80211_tx_info *info; struct ath11k_skb_cb *skb_cb; struct ath11k *ar; + struct ath11k_peer *peer; spin_lock(&tx_ring->tx_idr_lock); msdu = idr_remove(&tx_ring->txbuf_idr, ts->msdu_id); @@ -341,6 +343,11 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab, dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + if (!skb_cb->vif) { + dev_kfree_skb_any(msdu); + return; + } + memset(&info->status, 0, sizeof(info->status)); if (ts->acked) { @@ -355,7 +362,23 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab, } } - ieee80211_tx_status(ar->hw, msdu); + spin_lock_bh(&ab->base_lock); + peer = ath11k_peer_find_by_id(ab, ts->peer_id); + if (!peer || !peer->sta) { + ath11k_dbg(ab, ATH11K_DBG_DATA, + "dp_tx: failed to find the peer with peer_id %d\n", + ts->peer_id); + spin_unlock_bh(&ab->base_lock); + dev_kfree_skb_any(msdu); + return; + } + spin_unlock_bh(&ab->base_lock); + + status.sta = peer->sta; + status.info = info; + status.skb = msdu; + + ieee80211_tx_status_ext(ar->hw, &status); } static void @@ -379,7 +402,15 @@ ath11k_dp_tx_process_htt_tx_complete(struct ath11k_base *ab, ts.msdu_id = msdu_id; ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO1_ACK_RSSI, status_desc->info1); + + if (FIELD_GET(HTT_TX_WBM_COMP_INFO2_VALID, status_desc->info2)) + ts.peer_id = FIELD_GET(HTT_TX_WBM_COMP_INFO2_SW_PEER_ID, + status_desc->info2); + else + ts.peer_id = HTT_INVALID_PEER_ID; + ath11k_dp_tx_htt_tx_complete_buf(ab, tx_ring, &ts); + break; case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT: diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.h b/drivers/net/wireless/ath/ath11k/dp_tx.h index e87d65bfbf06..68a21ea9b934 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.h +++ b/drivers/net/wireless/ath/ath11k/dp_tx.h @@ -13,6 +13,7 @@ struct ath11k_dp_htt_wbm_tx_status { u32 msdu_id; bool acked; int ack_rssi; + u16 peer_id; }; void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts); From 2f0c9ac8362da09c80f1cd422ef7fd6fa9b252b9 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Chitrapu Date: Mon, 17 Apr 2023 13:35:02 +0300 Subject: [PATCH 40/43] wifi: ath11k: Fix incorrect update of radiotap fields Fix incorrect update of ppdu stats causing incorrect radiotap fields. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230403195738.25367-3-quic_pradeepc@quicinc.com --- drivers/net/wireless/ath/ath11k/hal_rx.c | 4 ++-- drivers/net/wireless/ath/ath11k/hal_rx.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c index b9939c5a4ecd..bb1d40034aa8 100644 --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c @@ -1029,7 +1029,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab, info1 = __le32_to_cpu(vht_sig->info1); ppdu_info->ldpc = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING, - info0); + info1); ppdu_info->mcs = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_MCS, info1); gi_setting = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_GI_SETTING, @@ -1452,7 +1452,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab, * PHYRX_OTHER_RECEIVE_INFO TLV. */ ppdu_info->rssi_comb = - FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB, + FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB, __le32_to_cpu(rssi->info0)); if (db2dbm) { diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.h b/drivers/net/wireless/ath/ath11k/hal_rx.h index 47e8208b22e1..61bd8416c4fd 100644 --- a/drivers/net/wireless/ath/ath11k/hal_rx.h +++ b/drivers/net/wireless/ath/ath11k/hal_rx.h @@ -385,7 +385,7 @@ struct hal_rx_he_sig_b2_ofdma_info { __le32 info0; } __packed; -#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8) +#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8) #define HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20 GENMASK(7, 0) From f9fff67d2d7ca6fa8066132003a3deef654c55b1 Mon Sep 17 00:00:00 2001 From: Nagarajan Maran Date: Mon, 17 Apr 2023 13:35:02 +0300 Subject: [PATCH 41/43] wifi: ath11k: Fix SKB corruption in REO destination ring While running traffics for a long time, randomly an RX descriptor filled with value "0" from REO destination ring is received. This descriptor which is invalid causes the wrong SKB (SKB stored in the IDR lookup with buffer id "0") to be fetched which in turn causes SKB memory corruption issue and the same leads to crash after some time. Changed the start id for idr allocation to "1" and the buffer id "0" is reserved for error validation. Introduced Sanity check to validate the descriptor, before processing the SKB. Crash Signature : Unable to handle kernel paging request at virtual address 3f004900 PC points to "b15_dma_inv_range+0x30/0x50" LR points to "dma_cache_maint_page+0x8c/0x128". The Backtrace obtained is as follows: [<8031716c>] (b15_dma_inv_range) from [<80313a4c>] (dma_cache_maint_page+0x8c/0x128) [<80313a4c>] (dma_cache_maint_page) from [<80313b90>] (__dma_page_dev_to_cpu+0x28/0xcc) [<80313b90>] (__dma_page_dev_to_cpu) from [<7fb5dd68>] (ath11k_dp_process_rx+0x1e8/0x4a4 [ath11k]) [<7fb5dd68>] (ath11k_dp_process_rx [ath11k]) from [<7fb53c20>] (ath11k_dp_service_srng+0xb0/0x2ac [ath11k]) [<7fb53c20>] (ath11k_dp_service_srng [ath11k]) from [<7f67bba4>] (ath11k_pci_ext_grp_napi_poll+0x1c/0x78 [ath11k_pci]) [<7f67bba4>] (ath11k_pci_ext_grp_napi_poll [ath11k_pci]) from [<807d5cf4>] (__napi_poll+0x28/0xb8) [<807d5cf4>] (__napi_poll) from [<807d5f28>] (net_rx_action+0xf0/0x280) [<807d5f28>] (net_rx_action) from [<80302148>] (__do_softirq+0xd0/0x280) [<80302148>] (__do_softirq) from [<80320408>] (irq_exit+0x74/0xd4) [<80320408>] (irq_exit) from [<803638a4>] (__handle_domain_irq+0x90/0xb4) [<803638a4>] (__handle_domain_irq) from [<805bedec>] (gic_handle_irq+0x58/0x90) [<805bedec>] (gic_handle_irq) from [<80301a78>] (__irq_svc+0x58/0x8c) Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Nagarajan Maran Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230403191533.28114-1-quic_nmaran@quicinc.com --- drivers/net/wireless/ath/ath11k/dp_rx.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index a4934bd79969..f67ce62b2b48 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -389,10 +389,10 @@ int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id, goto fail_free_skb; spin_lock_bh(&rx_ring->idr_lock); - buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 0, - rx_ring->bufs_max * 3, GFP_ATOMIC); + buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 1, + (rx_ring->bufs_max * 3) + 1, GFP_ATOMIC); spin_unlock_bh(&rx_ring->idr_lock); - if (buf_id < 0) + if (buf_id <= 0) goto fail_dma_unmap; desc = ath11k_hal_srng_src_get_next_entry(ab, srng); @@ -2665,6 +2665,9 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id, cookie); mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, cookie); + if (unlikely(buf_id == 0)) + continue; + ar = ab->pdevs[mac_id].ar; rx_ring = &ar->dp.rx_refill_buf_ring; spin_lock_bh(&rx_ring->idr_lock); From b956e3110a797a3663f91f9b8935b667cc23fe72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Mon, 17 Apr 2023 13:35:03 +0300 Subject: [PATCH 42/43] wifi: ath9k: Don't mark channelmap stack variable read-only in ath9k_mci_update_wlan_channels() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This partially reverts commit e161d4b60ae3a5356e07202e0bfedb5fad82c6aa. Turns out the channelmap variable is not actually read-only, it's modified through the MCI_GPM_CLR_CHANNEL_BIT() macro further down in the function, so making it read-only causes page faults when that code is hit. Link: https://bugzilla.kernel.org/show_bug.cgi?id=217183 Fixes: e161d4b60ae3 ("wifi: ath9k: Make arrays prof_prio and channelmap static const") Cc: stable@vger.kernel.org Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230413214118.153781-1-toke@toke.dk --- drivers/net/wireless/ath/ath9k/mci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 3363fc4e8966..a0845002d6fe 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c @@ -646,9 +646,7 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all) struct ath_hw *ah = sc->sc_ah; struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; struct ath9k_channel *chan = ah->curchan; - static const u32 channelmap[] = { - 0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff - }; + u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff}; int i; s16 chan_start, chan_end; u16 wlan_chan; From b100722a777f6455d913666a376f81342b2cb995 Mon Sep 17 00:00:00 2001 From: Muna Sinada Date: Mon, 17 Apr 2023 13:22:27 -0700 Subject: [PATCH 43/43] wifi: ath11k: Remove disabling of 80+80 and 160 MHz This is a regression fix for 80+80 and 160 MHz support bits being cleared, therefore not adverised. Remove disable of 80+80 and 160 MHz capability flags and assign valid center frequency 2 similar to VHT80_80. Fixes: 38dfe775d0ab ("wifi: ath11k: push MU-MIMO params from hostapd to hardware") Reported-by: Robert Marko Tested-by: Robert Marko # IPQ8074 WLAN.HK.2.9.0.1-01385-QCAHKSWPL_SILICONZ-1 Link: https://bugzilla.kernel.org/show_bug.cgi?id=217299 Co-developed-by: P Praneesh Signed-off-by: P Praneesh Signed-off-by: Muna Sinada Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1681762947-13882-1-git-send-email-quic_msinada@quicinc.com --- drivers/net/wireless/ath/ath11k/mac.c | 4 ---- drivers/net/wireless/ath/ath11k/wmi.c | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 4447fd4bd68f..1c93f1afccc5 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5585,10 +5585,6 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar, he_cap_elem->mac_cap_info[1] &= IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK; - he_cap_elem->phy_cap_info[0] &= - ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; - he_cap_elem->phy_cap_info[0] &= - ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; he_cap_elem->phy_cap_info[5] &= ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK; diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index f338d4447f11..d0b59bc2905a 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -871,7 +871,8 @@ static void ath11k_wmi_put_wmi_channel(struct wmi_channel *chan, chan->band_center_freq2 = arg->channel.band_center_freq1; - } else if (arg->channel.mode == MODE_11AC_VHT80_80) { + } else if ((arg->channel.mode == MODE_11AC_VHT80_80) || + (arg->channel.mode == MODE_11AX_HE80_80)) { chan->band_center_freq2 = arg->channel.band_center_freq2; } else { chan->band_center_freq2 = 0;