drivers/net/wireless/ath/ath11k/core.c | 12 +----------- drivers/net/wireless/ath/ath11k/dp.c | 12 ++++++------ drivers/net/wireless/ath/ath11k/dp.h | 1 - drivers/net/wireless/ath/ath11k/dp_tx.c | 9 +++++---- drivers/net/wireless/ath/ath11k/hw.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath11k/hw.h | 3 ++- drivers/net/wireless/ath/ath11k/mac.c | 2 +- 7 files changed, 32 insertions(+), 24 deletions(-)
".max_tx_ring" is an upper bounds to indexing ".tcl2wbm_rbm_map". It
is initialized in, core.c, a different file than the array init. This
spaghetti-like relation is fragile and not obvious. Accidentally
setting ".max_tx_ring" too high leads to a hard to track out-of-
bounds access and memory corruption.
Clarify this dependency by moving ".max_tx_ring" adjacent to the array
".tcl2wbm_rbm_map". Use ARRAY_SIZE() instead of #defines to initialize
the length field. Remove DP_TCL_NUM_RING_MAX_QCA6390, as it is no
longer required.
The intent is to make the code easier to understand rather than fix
an existing bug.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
---
I am trying to make ath11k work on IPQ9574. My device uses a IPQ9570
with a QCN5024 as the 2.4 GHz wifi.
I spent a few days tracking a memory corruption bug caused by
erroneously setting ".max_tx_ring" too high. I think I would not have
made this mistake if the initializations of .max_tx_ring and
.tcl2wbm_rbm_map were right next to each other.
drivers/net/wireless/ath/ath11k/core.c | 12 +-----------
drivers/net/wireless/ath/ath11k/dp.c | 12 ++++++------
drivers/net/wireless/ath/ath11k/dp.h | 1 -
drivers/net/wireless/ath/ath11k/dp_tx.c | 9 +++++----
drivers/net/wireless/ath/ath11k/hw.c | 17 +++++++++++++++++
drivers/net/wireless/ath/ath11k/hw.h | 3 ++-
drivers/net/wireless/ath/ath11k/mac.c | 2 +-
7 files changed, 32 insertions(+), 24 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 812686173ac8a..07199ceecbeb4 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -100,7 +100,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
@@ -184,7 +183,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
@@ -271,7 +269,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -358,7 +355,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = true,
.alloc_cacheable_memory = true,
@@ -445,7 +441,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -533,7 +528,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -619,7 +613,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_wcn6750,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -662,7 +655,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
.ring_mask = &ath11k_hw_ring_mask_ipq8074,
.credit_flow = false,
- .max_tx_ring = 1,
.spectral = {
.fft_sz = 2,
.fft_pad_sz = 0,
@@ -698,7 +690,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.idle_ps = false,
.supports_suspend = false,
- .hal_params = &ath11k_hw_hal_params_ipq8074,
+ .hal_params = &ath11k_hw_hal_params_ipq5018,
.single_pdev_only = false,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
@@ -789,7 +781,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@@ -876,7 +867,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
- .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 56b1a657e0b0f..bd6778d357275 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -344,7 +344,7 @@ void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
if (!ab->hw_params.supports_shadow_regs)
return;
- for (i = 0; i < ab->hw_params.max_tx_ring; i++)
+ for (i = 0; i < ab->hw_params.hal_params->map_len; i++)
ath11k_dp_shadow_stop_timer(ab, &ab->dp.tx_ring_timer[i]);
ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);
@@ -359,7 +359,7 @@ static void ath11k_dp_srng_common_cleanup(struct ath11k_base *ab)
ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring);
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_data_ring);
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_comp_ring);
}
@@ -400,7 +400,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
goto err;
}
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
tcl_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].tcl_ring_num;
wbm_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num;
@@ -782,7 +782,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
int i, j;
int tot_work_done = 0;
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
if (BIT(ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num) &
ab->hw_params.ring_mask->tx[grp_id])
ath11k_dp_tx_completion_handler(ab, i);
@@ -1035,7 +1035,7 @@ void ath11k_dp_free(struct ath11k_base *ab)
ath11k_dp_reo_cmd_list_cleanup(ab);
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
spin_lock_bh(&dp->tx_ring[i].tx_idr_lock);
idr_for_each(&dp->tx_ring[i].txbuf_idr,
ath11k_dp_tx_pending_cleanup, ab);
@@ -1086,7 +1086,7 @@ int ath11k_dp_alloc(struct ath11k_base *ab)
size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE;
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
idr_init(&dp->tx_ring[i].txbuf_idr);
spin_lock_init(&dp->tx_ring[i].tx_idr_lock);
dp->tx_ring[i].tcl_data_ring_id = i;
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index 7a55afd33be82..1bd513f68a3c3 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -199,7 +199,6 @@ struct ath11k_pdev_dp {
#define DP_BA_WIN_SZ_MAX 256
#define DP_TCL_NUM_RING_MAX 3
-#define DP_TCL_NUM_RING_MAX_QCA6390 1
#define DP_IDLE_SCATTER_BUFS_MAX 16
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 562aba66582f3..53e34a2bea54e 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -91,6 +91,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
struct hal_srng *tcl_ring;
struct ieee80211_hdr *hdr = (void *)skb->data;
struct dp_tx_ring *tx_ring;
+ size_t max_tx_ring = ab->hw_params.hal_params->map_len;
void *hal_tcl_desc;
u8 pool_id;
u8 hal_ring_id;
@@ -113,7 +114,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
tcl_ring_sel:
tcl_ring_retry = false;
- ti.ring_id = ring_selector % ab->hw_params.max_tx_ring;
+ ti.ring_id = ring_selector % max_tx_ring;
ti.rbm_id = ab->hw_params.hal_params->tcl2wbm_rbm_map[ti.ring_id].rbm_id;
ring_map |= BIT(ti.ring_id);
@@ -126,7 +127,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
spin_unlock_bh(&tx_ring->tx_idr_lock);
if (unlikely(ret < 0)) {
- if (ring_map == (BIT(ab->hw_params.max_tx_ring) - 1) ||
+ if (ring_map == (BIT(max_tx_ring) - 1) ||
!ab->hw_params.tcl_ring_retry) {
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
return -ENOSPC;
@@ -244,8 +245,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
* checking this ring earlier for each pkt tx.
* Restart ring selection if some rings are not checked yet.
*/
- if (unlikely(ring_map != (BIT(ab->hw_params.max_tx_ring)) - 1) &&
- ab->hw_params.tcl_ring_retry && ab->hw_params.max_tx_ring > 1) {
+ if (unlikely(ring_map != (BIT(max_tx_ring)) - 1) &&
+ ab->hw_params.tcl_ring_retry && max_tx_ring > 1) {
tcl_ring_retry = true;
ring_selector++;
}
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index caa6dc12a790b..8b1aef7a536ec 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -2707,6 +2707,14 @@ const struct ath11k_hw_regs wcn6750_regs = {
.hal_reo1_misc_ctl = 0x000005d8,
};
+static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq5018[] = {
+ {
+ .tcl_ring_num = 0,
+ .wbm_ring_num = 0,
+ .rbm_id = HAL_RX_BUF_RBM_SW0_BM,
+ },
+};
+
static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq8074[] = {
{
.tcl_ring_num = 0,
@@ -2822,19 +2830,28 @@ const struct ath11k_hw_regs ipq5018_regs = {
.hal_wbm1_release_ring_base_lsb = 0x0000097c,
};
+const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq5018 = {
+ .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
+ .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq5018,
+ .map_len = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq5018),
+};
+
const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
+ .map_len = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq8074),
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
+ .map_len = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq8074),
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_wcn6750,
+ .map_len = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_wcn6750),
};
static const struct cfg80211_sar_freq_ranges ath11k_hw_sar_freq_ranges_wcn6855[] = {
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 52d9f4c13b136..e311c3541eb78 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -134,6 +134,7 @@ struct ath11k_hw_tcl2wbm_rbm_map {
struct ath11k_hw_hal_params {
enum hal_rx_buf_return_buf_manager rx_buf_rbm;
const struct ath11k_hw_tcl2wbm_rbm_map *tcl2wbm_rbm_map;
+ size_t map_len;
};
struct ath11k_hw_params {
@@ -198,7 +199,6 @@ struct ath11k_hw_params {
bool supports_regdb;
bool fix_l1ss;
bool credit_flow;
- u8 max_tx_ring;
const struct ath11k_hw_hal_params *hal_params;
bool supports_dynamic_smps_6ghz;
bool alloc_cacheable_memory;
@@ -291,6 +291,7 @@ extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018;
extern const struct ce_remap ath11k_ce_remap_ipq5018;
+extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq5018;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 3276fe443502f..1c972e7bada8f 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -7392,7 +7392,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
idr_for_each(&ar->txmgmt_idr,
ath11k_mac_vif_txmgmt_idr_remove, vif);
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
+ for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
idr_for_each(&ab->dp.tx_ring[i].txbuf_idr,
ath11k_mac_vif_unref, vif);
--
2.45.1
Hi Alexandru,
kernel test robot noticed the following build errors:
[auto build test ERROR on ath/ath-next]
[also build test ERROR on linus/master v6.18 next-20251210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Alexandru-Gagniuc/wifi-ath11k-move-max_tx_ring-to-struct-ath11k_hw_hal_params/20251210-104321
base: https://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git ath-next
patch link: https://lore.kernel.org/r/20251210024036.3965135-1-mr.nuke.me%40gmail.com
patch subject: [PATCH] wifi: ath11k: move .max_tx_ring to struct ath11k_hw_hal_params
config: sparc64-allmodconfig (https://download.01.org/0day-ci/archive/20251211/202512111054.OwS5ClW9-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 6ec8c4351cfc1d0627d1633b02ea787bd29c77d8)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251211/202512111054.OwS5ClW9-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512111054.OwS5ClW9-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/net/wireless/ath/ath11k/debugfs.c:710:32: error: no member named 'max_tx_ring' in 'struct ath11k_hw_params'
710 | for (i = 0; i < ab->hw_params.max_tx_ring; i++)
| ~~~~~~~~~~~~~ ^
1 error generated.
vim +710 drivers/net/wireless/ath/ath11k/debugfs.c
da3a9d3c15769b Kalle Valo 2020-09-16 657
cb4e57db2ff0c8 Kalle Valo 2020-09-16 658 static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
da3a9d3c15769b Kalle Valo 2020-09-16 659 char __user *user_buf,
da3a9d3c15769b Kalle Valo 2020-09-16 660 size_t count, loff_t *ppos)
da3a9d3c15769b Kalle Valo 2020-09-16 661 {
da3a9d3c15769b Kalle Valo 2020-09-16 662 struct ath11k_base *ab = file->private_data;
da3a9d3c15769b Kalle Valo 2020-09-16 663 struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
da3a9d3c15769b Kalle Valo 2020-09-16 664 int len = 0, i, retval;
da3a9d3c15769b Kalle Valo 2020-09-16 665 const int size = 4096;
da3a9d3c15769b Kalle Valo 2020-09-16 666 static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
da3a9d3c15769b Kalle Valo 2020-09-16 667 "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
da3a9d3c15769b Kalle Valo 2020-09-16 668 "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
da3a9d3c15769b Kalle Valo 2020-09-16 669 "AMSDU parse", "SA timeout", "DA timeout",
da3a9d3c15769b Kalle Valo 2020-09-16 670 "Flow timeout", "Flush req"};
da3a9d3c15769b Kalle Valo 2020-09-16 671 static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
da3a9d3c15769b Kalle Valo 2020-09-16 672 "Desc addr zero", "Desc inval", "AMPDU in non BA",
da3a9d3c15769b Kalle Valo 2020-09-16 673 "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
da3a9d3c15769b Kalle Valo 2020-09-16 674 "Frame OOR", "BAR OOR", "No BA session",
da3a9d3c15769b Kalle Valo 2020-09-16 675 "Frame SN equal SSN", "PN check fail", "2k err",
da3a9d3c15769b Kalle Valo 2020-09-16 676 "PN err", "Desc blocked"};
da3a9d3c15769b Kalle Valo 2020-09-16 677
da3a9d3c15769b Kalle Valo 2020-09-16 678 char *buf;
da3a9d3c15769b Kalle Valo 2020-09-16 679
da3a9d3c15769b Kalle Valo 2020-09-16 680 buf = kzalloc(size, GFP_KERNEL);
da3a9d3c15769b Kalle Valo 2020-09-16 681 if (!buf)
da3a9d3c15769b Kalle Valo 2020-09-16 682 return -ENOMEM;
da3a9d3c15769b Kalle Valo 2020-09-16 683
da3a9d3c15769b Kalle Valo 2020-09-16 684 len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
da3a9d3c15769b Kalle Valo 2020-09-16 685 len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
da3a9d3c15769b Kalle Valo 2020-09-16 686 soc_stats->err_ring_pkts);
da3a9d3c15769b Kalle Valo 2020-09-16 687 len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
da3a9d3c15769b Kalle Valo 2020-09-16 688 soc_stats->invalid_rbm);
da3a9d3c15769b Kalle Valo 2020-09-16 689 len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
da3a9d3c15769b Kalle Valo 2020-09-16 690 for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
da3a9d3c15769b Kalle Valo 2020-09-16 691 len += scnprintf(buf + len, size - len, "%s: %u\n",
da3a9d3c15769b Kalle Valo 2020-09-16 692 rxdma_err[i], soc_stats->rxdma_error[i]);
da3a9d3c15769b Kalle Valo 2020-09-16 693
da3a9d3c15769b Kalle Valo 2020-09-16 694 len += scnprintf(buf + len, size - len, "\nREO errors:\n");
da3a9d3c15769b Kalle Valo 2020-09-16 695 for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
da3a9d3c15769b Kalle Valo 2020-09-16 696 len += scnprintf(buf + len, size - len, "%s: %u\n",
da3a9d3c15769b Kalle Valo 2020-09-16 697 reo_err[i], soc_stats->reo_error[i]);
da3a9d3c15769b Kalle Valo 2020-09-16 698
da3a9d3c15769b Kalle Valo 2020-09-16 699 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
da3a9d3c15769b Kalle Valo 2020-09-16 700 len += scnprintf(buf + len, size - len,
da3a9d3c15769b Kalle Valo 2020-09-16 701 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
da3a9d3c15769b Kalle Valo 2020-09-16 702 soc_stats->hal_reo_error[0],
da3a9d3c15769b Kalle Valo 2020-09-16 703 soc_stats->hal_reo_error[1],
da3a9d3c15769b Kalle Valo 2020-09-16 704 soc_stats->hal_reo_error[2],
da3a9d3c15769b Kalle Valo 2020-09-16 705 soc_stats->hal_reo_error[3]);
da3a9d3c15769b Kalle Valo 2020-09-16 706
da3a9d3c15769b Kalle Valo 2020-09-16 707 len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
da3a9d3c15769b Kalle Valo 2020-09-16 708 len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
da3a9d3c15769b Kalle Valo 2020-09-16 709
31582373a4a8e8 Baochen Qiang 2021-10-11 @710 for (i = 0; i < ab->hw_params.max_tx_ring; i++)
da3a9d3c15769b Kalle Valo 2020-09-16 711 len += scnprintf(buf + len, size - len, "ring%d: %u\n",
da3a9d3c15769b Kalle Valo 2020-09-16 712 i, soc_stats->tx_err.desc_na[i]);
da3a9d3c15769b Kalle Valo 2020-09-16 713
da3a9d3c15769b Kalle Valo 2020-09-16 714 len += scnprintf(buf + len, size - len,
da3a9d3c15769b Kalle Valo 2020-09-16 715 "\nMisc Transmit Failures: %d\n",
da3a9d3c15769b Kalle Valo 2020-09-16 716 atomic_read(&soc_stats->tx_err.misc_fail));
da3a9d3c15769b Kalle Valo 2020-09-16 717
cb4e57db2ff0c8 Kalle Valo 2020-09-16 718 len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
da3a9d3c15769b Kalle Valo 2020-09-16 719
da3a9d3c15769b Kalle Valo 2020-09-16 720 if (len > size)
da3a9d3c15769b Kalle Valo 2020-09-16 721 len = size;
da3a9d3c15769b Kalle Valo 2020-09-16 722 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
da3a9d3c15769b Kalle Valo 2020-09-16 723 kfree(buf);
da3a9d3c15769b Kalle Valo 2020-09-16 724
da3a9d3c15769b Kalle Valo 2020-09-16 725 return retval;
da3a9d3c15769b Kalle Valo 2020-09-16 726 }
da3a9d3c15769b Kalle Valo 2020-09-16 727
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Alexandru,
kernel test robot noticed the following build errors:
[auto build test ERROR on ath/ath-next]
[also build test ERROR on linus/master v6.18 next-20251210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Alexandru-Gagniuc/wifi-ath11k-move-max_tx_ring-to-struct-ath11k_hw_hal_params/20251210-104321
base: https://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git ath-next
patch link: https://lore.kernel.org/r/20251210024036.3965135-1-mr.nuke.me%40gmail.com
patch subject: [PATCH] wifi: ath11k: move .max_tx_ring to struct ath11k_hw_hal_params
config: nios2-allmodconfig (https://download.01.org/0day-ci/archive/20251211/202512110958.VLhPFYua-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251211/202512110958.VLhPFYua-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512110958.VLhPFYua-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/net/wireless/ath/ath11k/debugfs.c: In function 'ath11k_debugfs_dump_soc_dp_stats':
>> drivers/net/wireless/ath/ath11k/debugfs.c:710:38: error: 'struct ath11k_hw_params' has no member named 'max_tx_ring'
710 | for (i = 0; i < ab->hw_params.max_tx_ring; i++)
| ^
vim +710 drivers/net/wireless/ath/ath11k/debugfs.c
da3a9d3c15769b8 Kalle Valo 2020-09-16 657
cb4e57db2ff0c8d Kalle Valo 2020-09-16 658 static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
da3a9d3c15769b8 Kalle Valo 2020-09-16 659 char __user *user_buf,
da3a9d3c15769b8 Kalle Valo 2020-09-16 660 size_t count, loff_t *ppos)
da3a9d3c15769b8 Kalle Valo 2020-09-16 661 {
da3a9d3c15769b8 Kalle Valo 2020-09-16 662 struct ath11k_base *ab = file->private_data;
da3a9d3c15769b8 Kalle Valo 2020-09-16 663 struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
da3a9d3c15769b8 Kalle Valo 2020-09-16 664 int len = 0, i, retval;
da3a9d3c15769b8 Kalle Valo 2020-09-16 665 const int size = 4096;
da3a9d3c15769b8 Kalle Valo 2020-09-16 666 static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
da3a9d3c15769b8 Kalle Valo 2020-09-16 667 "Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
da3a9d3c15769b8 Kalle Valo 2020-09-16 668 "Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
da3a9d3c15769b8 Kalle Valo 2020-09-16 669 "AMSDU parse", "SA timeout", "DA timeout",
da3a9d3c15769b8 Kalle Valo 2020-09-16 670 "Flow timeout", "Flush req"};
da3a9d3c15769b8 Kalle Valo 2020-09-16 671 static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
da3a9d3c15769b8 Kalle Valo 2020-09-16 672 "Desc addr zero", "Desc inval", "AMPDU in non BA",
da3a9d3c15769b8 Kalle Valo 2020-09-16 673 "Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
da3a9d3c15769b8 Kalle Valo 2020-09-16 674 "Frame OOR", "BAR OOR", "No BA session",
da3a9d3c15769b8 Kalle Valo 2020-09-16 675 "Frame SN equal SSN", "PN check fail", "2k err",
da3a9d3c15769b8 Kalle Valo 2020-09-16 676 "PN err", "Desc blocked"};
da3a9d3c15769b8 Kalle Valo 2020-09-16 677
da3a9d3c15769b8 Kalle Valo 2020-09-16 678 char *buf;
da3a9d3c15769b8 Kalle Valo 2020-09-16 679
da3a9d3c15769b8 Kalle Valo 2020-09-16 680 buf = kzalloc(size, GFP_KERNEL);
da3a9d3c15769b8 Kalle Valo 2020-09-16 681 if (!buf)
da3a9d3c15769b8 Kalle Valo 2020-09-16 682 return -ENOMEM;
da3a9d3c15769b8 Kalle Valo 2020-09-16 683
da3a9d3c15769b8 Kalle Valo 2020-09-16 684 len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
da3a9d3c15769b8 Kalle Valo 2020-09-16 685 len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
da3a9d3c15769b8 Kalle Valo 2020-09-16 686 soc_stats->err_ring_pkts);
da3a9d3c15769b8 Kalle Valo 2020-09-16 687 len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
da3a9d3c15769b8 Kalle Valo 2020-09-16 688 soc_stats->invalid_rbm);
da3a9d3c15769b8 Kalle Valo 2020-09-16 689 len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
da3a9d3c15769b8 Kalle Valo 2020-09-16 690 for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
da3a9d3c15769b8 Kalle Valo 2020-09-16 691 len += scnprintf(buf + len, size - len, "%s: %u\n",
da3a9d3c15769b8 Kalle Valo 2020-09-16 692 rxdma_err[i], soc_stats->rxdma_error[i]);
da3a9d3c15769b8 Kalle Valo 2020-09-16 693
da3a9d3c15769b8 Kalle Valo 2020-09-16 694 len += scnprintf(buf + len, size - len, "\nREO errors:\n");
da3a9d3c15769b8 Kalle Valo 2020-09-16 695 for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
da3a9d3c15769b8 Kalle Valo 2020-09-16 696 len += scnprintf(buf + len, size - len, "%s: %u\n",
da3a9d3c15769b8 Kalle Valo 2020-09-16 697 reo_err[i], soc_stats->reo_error[i]);
da3a9d3c15769b8 Kalle Valo 2020-09-16 698
da3a9d3c15769b8 Kalle Valo 2020-09-16 699 len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
da3a9d3c15769b8 Kalle Valo 2020-09-16 700 len += scnprintf(buf + len, size - len,
da3a9d3c15769b8 Kalle Valo 2020-09-16 701 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
da3a9d3c15769b8 Kalle Valo 2020-09-16 702 soc_stats->hal_reo_error[0],
da3a9d3c15769b8 Kalle Valo 2020-09-16 703 soc_stats->hal_reo_error[1],
da3a9d3c15769b8 Kalle Valo 2020-09-16 704 soc_stats->hal_reo_error[2],
da3a9d3c15769b8 Kalle Valo 2020-09-16 705 soc_stats->hal_reo_error[3]);
da3a9d3c15769b8 Kalle Valo 2020-09-16 706
da3a9d3c15769b8 Kalle Valo 2020-09-16 707 len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
da3a9d3c15769b8 Kalle Valo 2020-09-16 708 len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
da3a9d3c15769b8 Kalle Valo 2020-09-16 709
31582373a4a8e88 Baochen Qiang 2021-10-11 @710 for (i = 0; i < ab->hw_params.max_tx_ring; i++)
da3a9d3c15769b8 Kalle Valo 2020-09-16 711 len += scnprintf(buf + len, size - len, "ring%d: %u\n",
da3a9d3c15769b8 Kalle Valo 2020-09-16 712 i, soc_stats->tx_err.desc_na[i]);
da3a9d3c15769b8 Kalle Valo 2020-09-16 713
da3a9d3c15769b8 Kalle Valo 2020-09-16 714 len += scnprintf(buf + len, size - len,
da3a9d3c15769b8 Kalle Valo 2020-09-16 715 "\nMisc Transmit Failures: %d\n",
da3a9d3c15769b8 Kalle Valo 2020-09-16 716 atomic_read(&soc_stats->tx_err.misc_fail));
da3a9d3c15769b8 Kalle Valo 2020-09-16 717
cb4e57db2ff0c8d Kalle Valo 2020-09-16 718 len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
da3a9d3c15769b8 Kalle Valo 2020-09-16 719
da3a9d3c15769b8 Kalle Valo 2020-09-16 720 if (len > size)
da3a9d3c15769b8 Kalle Valo 2020-09-16 721 len = size;
da3a9d3c15769b8 Kalle Valo 2020-09-16 722 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
da3a9d3c15769b8 Kalle Valo 2020-09-16 723 kfree(buf);
da3a9d3c15769b8 Kalle Valo 2020-09-16 724
da3a9d3c15769b8 Kalle Valo 2020-09-16 725 return retval;
da3a9d3c15769b8 Kalle Valo 2020-09-16 726 }
da3a9d3c15769b8 Kalle Valo 2020-09-16 727
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On 12/10/2025 10:40 AM, Alexandru Gagniuc wrote: > ".max_tx_ring" is an upper bounds to indexing ".tcl2wbm_rbm_map". It > is initialized in, core.c, a different file than the array init. This > spaghetti-like relation is fragile and not obvious. Accidentally > setting ".max_tx_ring" too high leads to a hard to track out-of- > bounds access and memory corruption. > > Clarify this dependency by moving ".max_tx_ring" adjacent to the array > ".tcl2wbm_rbm_map". Use ARRAY_SIZE() instead of #defines to initialize > the length field. Remove DP_TCL_NUM_RING_MAX_QCA6390, as it is no > longer required. > > The intent is to make the code easier to understand rather than fix > an existing bug. > Even the code chane works, I am not sure whether we should do this. Because, logically max_tx_ring represents hardware capability which is static. However the change actually implies max_tx_ring varies on tcl2wbm_rbm_map definition. If we are going to add something to avoid the potential out-of-bound access or to improve code readability, how about something like ASSERT(hw_params.max_tx_ring <= ARRAR_SIZE(tcl2wbm_rbm_map))
On 12/10/25 12:46 AM, Baochen Qiang wrote: > > > On 12/10/2025 10:40 AM, Alexandru Gagniuc wrote: >> ".max_tx_ring" is an upper bounds to indexing ".tcl2wbm_rbm_map". It >> is initialized in, core.c, a different file than the array init. This >> spaghetti-like relation is fragile and not obvious. Accidentally >> setting ".max_tx_ring" too high leads to a hard to track out-of- >> bounds access and memory corruption. >> >> Clarify this dependency by moving ".max_tx_ring" adjacent to the array >> ".tcl2wbm_rbm_map". Use ARRAY_SIZE() instead of #defines to initialize >> the length field. Remove DP_TCL_NUM_RING_MAX_QCA6390, as it is no >> longer required. >> >> The intent is to make the code easier to understand rather than fix >> an existing bug. >> > > Even the code chane works, I am not sure whether we should do this. Because, logically > max_tx_ring represents hardware capability which is static. However the change actually > implies max_tx_ring varies on tcl2wbm_rbm_map definition. I see what you mean, although tcl2wbm_rbm_map is const. More details below. > If we are going to add something to avoid the potential out-of-bound access or to improve > code readability, how about something like > > ASSERT(hw_params.max_tx_ring <= ARRAR_SIZE(tcl2wbm_rbm_map)) A static assert might be a good solution. I don't know how to do that. By the time we have hw_params.max_tx_ring and tcl2wbm_rbm_map, the latter is a pointer, so we can't use ARRAY_SIZE(). We could try to do it dynamically, but I feel that's spaghetti code: if (tcl2wbm_rbm_map == &ath11k_hw_hal_params_ipq8074) ASSERT(hw_params.max_tx_ring <= ARRAY_SIZE(ath11k_hw_hal_params_ipq8074)); else if (...) ... Alternatively, I can take the suggestion from your other email, and keep the "max_tx_ring", or "num_tx_rings" name. Because it is part of the hw_params struct (via .hal_params), it still describes the hardware. While the value is derived from a constant array, instead of being hardcoded, it remains an immutable quantity, consistent with a static hardware descriptor, would you agree? Alex
On 12/11/2025 12:28 AM, mr.nuke.me@gmail.com wrote: > On 12/10/25 12:46 AM, Baochen Qiang wrote: >> >> >> On 12/10/2025 10:40 AM, Alexandru Gagniuc wrote: >>> ".max_tx_ring" is an upper bounds to indexing ".tcl2wbm_rbm_map". It >>> is initialized in, core.c, a different file than the array init. This >>> spaghetti-like relation is fragile and not obvious. Accidentally >>> setting ".max_tx_ring" too high leads to a hard to track out-of- >>> bounds access and memory corruption. >>> >>> Clarify this dependency by moving ".max_tx_ring" adjacent to the array >>> ".tcl2wbm_rbm_map". Use ARRAY_SIZE() instead of #defines to initialize >>> the length field. Remove DP_TCL_NUM_RING_MAX_QCA6390, as it is no >>> longer required. >>> >>> The intent is to make the code easier to understand rather than fix >>> an existing bug. >>> >> >> Even the code chane works, I am not sure whether we should do this. Because, logically >> max_tx_ring represents hardware capability which is static. However the change actually >> implies max_tx_ring varies on tcl2wbm_rbm_map definition. > > I see what you mean, although tcl2wbm_rbm_map is const. More details below. > > >> If we are going to add something to avoid the potential out-of-bound access or to improve >> code readability, how about something like >> >> ASSERT(hw_params.max_tx_ring <= ARRAR_SIZE(tcl2wbm_rbm_map)) > A static assert might be a good solution. I don't know how to do that. > By the time we have hw_params.max_tx_ring and tcl2wbm_rbm_map, the > latter is a pointer, so we can't use ARRAY_SIZE(). We could try to do Yeah, that is a problem ... > it dynamically, but I feel that's spaghetti code: > > if (tcl2wbm_rbm_map == &ath11k_hw_hal_params_ipq8074) > ASSERT(hw_params.max_tx_ring <= ARRAY_SIZE(ath11k_hw_hal_params_ipq8074)); > else if (...) > ... > Hmm, this is ugly. I would rather have map_size = ARRAR_SIZE() in each hal_params, and then ASSERT(hw_params.max_tx_ring <= hw_params.hal_params->map_size) > Alternatively, I can take the suggestion from your other email, and > keep the "max_tx_ring", or "num_tx_rings" name. Because it is part of > the hw_params struct (via .hal_params), it still describes the > hardware. While the value is derived from a constant array, instead > of being hardcoded, it remains an immutable quantity, consistent with > a static hardware descriptor, would you agree? Also works for me. You can make the decision. > > Alex >
On 12/10/2025 10:40 AM, Alexandru Gagniuc wrote:
> ".max_tx_ring" is an upper bounds to indexing ".tcl2wbm_rbm_map". It
> is initialized in, core.c, a different file than the array init. This
> spaghetti-like relation is fragile and not obvious. Accidentally
> setting ".max_tx_ring" too high leads to a hard to track out-of-
> bounds access and memory corruption.
>
> Clarify this dependency by moving ".max_tx_ring" adjacent to the array
> ".tcl2wbm_rbm_map". Use ARRAY_SIZE() instead of #defines to initialize
In addition to moving, you also have a renaming. Please mention this. Or can we use
existing max_tx_ring instead? IMO it is more meaningful than map_len.
> the length field. Remove DP_TCL_NUM_RING_MAX_QCA6390, as it is no
> longer required.
>
> The intent is to make the code easier to understand rather than fix
> an existing bug.
>
> Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
> ---
>
> I am trying to make ath11k work on IPQ9574. My device uses a IPQ9570
> with a QCN5024 as the 2.4 GHz wifi.
>
> I spent a few days tracking a memory corruption bug caused by
> erroneously setting ".max_tx_ring" too high. I think I would not have
> made this mistake if the initializations of .max_tx_ring and
> .tcl2wbm_rbm_map were right next to each other.
>
>
> drivers/net/wireless/ath/ath11k/core.c | 12 +-----------
> drivers/net/wireless/ath/ath11k/dp.c | 12 ++++++------
> drivers/net/wireless/ath/ath11k/dp.h | 1 -
> drivers/net/wireless/ath/ath11k/dp_tx.c | 9 +++++----
> drivers/net/wireless/ath/ath11k/hw.c | 17 +++++++++++++++++
> drivers/net/wireless/ath/ath11k/hw.h | 3 ++-
> drivers/net/wireless/ath/ath11k/mac.c | 2 +-
> 7 files changed, 32 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
> index 812686173ac8a..07199ceecbeb4 100644
> --- a/drivers/net/wireless/ath/ath11k/core.c
> +++ b/drivers/net/wireless/ath/ath11k/core.c
> @@ -100,7 +100,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = false,
> .fix_l1ss = true,
> .credit_flow = false,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX,
> .hal_params = &ath11k_hw_hal_params_ipq8074,
> .supports_dynamic_smps_6ghz = false,
> .alloc_cacheable_memory = true,
> @@ -184,7 +183,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = false,
> .fix_l1ss = true,
> .credit_flow = false,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX,
> .hal_params = &ath11k_hw_hal_params_ipq8074,
> .supports_dynamic_smps_6ghz = false,
> .alloc_cacheable_memory = true,
> @@ -271,7 +269,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = false,
> .fix_l1ss = true,
> .credit_flow = true,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
> .hal_params = &ath11k_hw_hal_params_qca6390,
> .supports_dynamic_smps_6ghz = false,
> .alloc_cacheable_memory = false,
> @@ -358,7 +355,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = false,
> .fix_l1ss = true,
> .credit_flow = false,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX,
> .hal_params = &ath11k_hw_hal_params_ipq8074,
> .supports_dynamic_smps_6ghz = true,
> .alloc_cacheable_memory = true,
> @@ -445,7 +441,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = true,
> .fix_l1ss = false,
> .credit_flow = true,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
> .hal_params = &ath11k_hw_hal_params_qca6390,
> .supports_dynamic_smps_6ghz = false,
> .alloc_cacheable_memory = false,
> @@ -533,7 +528,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = true,
> .fix_l1ss = false,
> .credit_flow = true,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
> .hal_params = &ath11k_hw_hal_params_qca6390,
> .supports_dynamic_smps_6ghz = false,
> .alloc_cacheable_memory = false,
> @@ -619,7 +613,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = true,
> .fix_l1ss = false,
> .credit_flow = true,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX,
> .hal_params = &ath11k_hw_hal_params_wcn6750,
> .supports_dynamic_smps_6ghz = false,
> .alloc_cacheable_memory = false,
> @@ -662,7 +655,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
> .ring_mask = &ath11k_hw_ring_mask_ipq8074,
> .credit_flow = false,
> - .max_tx_ring = 1,
> .spectral = {
> .fft_sz = 2,
> .fft_pad_sz = 0,
> @@ -698,7 +690,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = false,
> .idle_ps = false,
> .supports_suspend = false,
> - .hal_params = &ath11k_hw_hal_params_ipq8074,
> + .hal_params = &ath11k_hw_hal_params_ipq5018,
> .single_pdev_only = false,
> .coldboot_cal_mm = true,
> .coldboot_cal_ftm = true,
> @@ -789,7 +781,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = true,
> .fix_l1ss = false,
> .credit_flow = true,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
> .hal_params = &ath11k_hw_hal_params_qca6390,
> .supports_dynamic_smps_6ghz = false,
> .alloc_cacheable_memory = false,
> @@ -876,7 +867,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
> .supports_regdb = true,
> .fix_l1ss = false,
> .credit_flow = true,
> - .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
> .hal_params = &ath11k_hw_hal_params_qca6390,
> .supports_dynamic_smps_6ghz = false,
> .alloc_cacheable_memory = false,
> diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
> index 56b1a657e0b0f..bd6778d357275 100644
> --- a/drivers/net/wireless/ath/ath11k/dp.c
> +++ b/drivers/net/wireless/ath/ath11k/dp.c
> @@ -344,7 +344,7 @@ void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
> if (!ab->hw_params.supports_shadow_regs)
> return;
>
> - for (i = 0; i < ab->hw_params.max_tx_ring; i++)
> + for (i = 0; i < ab->hw_params.hal_params->map_len; i++)
> ath11k_dp_shadow_stop_timer(ab, &ab->dp.tx_ring_timer[i]);
>
> ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);
> @@ -359,7 +359,7 @@ static void ath11k_dp_srng_common_cleanup(struct ath11k_base *ab)
> ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring);
> ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring);
> ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring);
> - for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
> + for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
> ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_data_ring);
> ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_comp_ring);
> }
> @@ -400,7 +400,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
> goto err;
> }
>
> - for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
> + for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
> tcl_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].tcl_ring_num;
> wbm_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num;
>
> @@ -782,7 +782,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
> int i, j;
> int tot_work_done = 0;
>
> - for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
> + for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
> if (BIT(ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num) &
> ab->hw_params.ring_mask->tx[grp_id])
> ath11k_dp_tx_completion_handler(ab, i);
> @@ -1035,7 +1035,7 @@ void ath11k_dp_free(struct ath11k_base *ab)
>
> ath11k_dp_reo_cmd_list_cleanup(ab);
>
> - for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
> + for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
> spin_lock_bh(&dp->tx_ring[i].tx_idr_lock);
> idr_for_each(&dp->tx_ring[i].txbuf_idr,
> ath11k_dp_tx_pending_cleanup, ab);
> @@ -1086,7 +1086,7 @@ int ath11k_dp_alloc(struct ath11k_base *ab)
>
> size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE;
>
> - for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
> + for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
> idr_init(&dp->tx_ring[i].txbuf_idr);
> spin_lock_init(&dp->tx_ring[i].tx_idr_lock);
> dp->tx_ring[i].tcl_data_ring_id = i;
> diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
> index 7a55afd33be82..1bd513f68a3c3 100644
> --- a/drivers/net/wireless/ath/ath11k/dp.h
> +++ b/drivers/net/wireless/ath/ath11k/dp.h
> @@ -199,7 +199,6 @@ struct ath11k_pdev_dp {
> #define DP_BA_WIN_SZ_MAX 256
>
> #define DP_TCL_NUM_RING_MAX 3
> -#define DP_TCL_NUM_RING_MAX_QCA6390 1
>
> #define DP_IDLE_SCATTER_BUFS_MAX 16
>
> diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
> index 562aba66582f3..53e34a2bea54e 100644
> --- a/drivers/net/wireless/ath/ath11k/dp_tx.c
> +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
> @@ -91,6 +91,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
> struct hal_srng *tcl_ring;
> struct ieee80211_hdr *hdr = (void *)skb->data;
> struct dp_tx_ring *tx_ring;
> + size_t max_tx_ring = ab->hw_params.hal_params->map_len;
> void *hal_tcl_desc;
> u8 pool_id;
> u8 hal_ring_id;
> @@ -113,7 +114,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
> tcl_ring_sel:
> tcl_ring_retry = false;
>
> - ti.ring_id = ring_selector % ab->hw_params.max_tx_ring;
> + ti.ring_id = ring_selector % max_tx_ring;
> ti.rbm_id = ab->hw_params.hal_params->tcl2wbm_rbm_map[ti.ring_id].rbm_id;
>
> ring_map |= BIT(ti.ring_id);
> @@ -126,7 +127,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
> spin_unlock_bh(&tx_ring->tx_idr_lock);
>
> if (unlikely(ret < 0)) {
> - if (ring_map == (BIT(ab->hw_params.max_tx_ring) - 1) ||
> + if (ring_map == (BIT(max_tx_ring) - 1) ||
> !ab->hw_params.tcl_ring_retry) {
> atomic_inc(&ab->soc_stats.tx_err.misc_fail);
> return -ENOSPC;
> @@ -244,8 +245,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
> * checking this ring earlier for each pkt tx.
> * Restart ring selection if some rings are not checked yet.
> */
> - if (unlikely(ring_map != (BIT(ab->hw_params.max_tx_ring)) - 1) &&
> - ab->hw_params.tcl_ring_retry && ab->hw_params.max_tx_ring > 1) {
> + if (unlikely(ring_map != (BIT(max_tx_ring)) - 1) &&
> + ab->hw_params.tcl_ring_retry && max_tx_ring > 1) {
> tcl_ring_retry = true;
> ring_selector++;
> }
> diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
> index caa6dc12a790b..8b1aef7a536ec 100644
> --- a/drivers/net/wireless/ath/ath11k/hw.c
> +++ b/drivers/net/wireless/ath/ath11k/hw.c
> @@ -2707,6 +2707,14 @@ const struct ath11k_hw_regs wcn6750_regs = {
> .hal_reo1_misc_ctl = 0x000005d8,
> };
>
> +static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq5018[] = {
> + {
> + .tcl_ring_num = 0,
> + .wbm_ring_num = 0,
> + .rbm_id = HAL_RX_BUF_RBM_SW0_BM,
> + },
> +};
> +
> static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq8074[] = {
> {
> .tcl_ring_num = 0,
> @@ -2822,19 +2830,28 @@ const struct ath11k_hw_regs ipq5018_regs = {
> .hal_wbm1_release_ring_base_lsb = 0x0000097c,
> };
>
> +const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq5018 = {
> + .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
> + .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq5018,
> + .map_len = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq5018),
> +};
> +
> const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
> .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
> .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
> + .map_len = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq8074),
> };
>
> const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390 = {
> .rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
> .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
> + .map_len = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq8074),
this accidently changes max_tx_ring to 3, however it should be 1 for chips using
ath11k_hw_hal_params_qca6390.
> };
>
> const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750 = {
> .rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
> .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_wcn6750,
> + .map_len = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_wcn6750),
> };
>
> static const struct cfg80211_sar_freq_ranges ath11k_hw_sar_freq_ranges_wcn6855[] = {
> diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
> index 52d9f4c13b136..e311c3541eb78 100644
> --- a/drivers/net/wireless/ath/ath11k/hw.h
> +++ b/drivers/net/wireless/ath/ath11k/hw.h
> @@ -134,6 +134,7 @@ struct ath11k_hw_tcl2wbm_rbm_map {
> struct ath11k_hw_hal_params {
> enum hal_rx_buf_return_buf_manager rx_buf_rbm;
> const struct ath11k_hw_tcl2wbm_rbm_map *tcl2wbm_rbm_map;
> + size_t map_len;
> };
>
> struct ath11k_hw_params {
> @@ -198,7 +199,6 @@ struct ath11k_hw_params {
> bool supports_regdb;
> bool fix_l1ss;
> bool credit_flow;
> - u8 max_tx_ring;
> const struct ath11k_hw_hal_params *hal_params;
> bool supports_dynamic_smps_6ghz;
> bool alloc_cacheable_memory;
> @@ -291,6 +291,7 @@ extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018;
>
> extern const struct ce_remap ath11k_ce_remap_ipq5018;
>
> +extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq5018;
> extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074;
> extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390;
> extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750;
> diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
> index 3276fe443502f..1c972e7bada8f 100644
> --- a/drivers/net/wireless/ath/ath11k/mac.c
> +++ b/drivers/net/wireless/ath/ath11k/mac.c
> @@ -7392,7 +7392,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
> idr_for_each(&ar->txmgmt_idr,
> ath11k_mac_vif_txmgmt_idr_remove, vif);
>
> - for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
> + for (i = 0; i < ab->hw_params.hal_params->map_len; i++) {
> spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
> idr_for_each(&ab->dp.tx_ring[i].txbuf_idr,
> ath11k_mac_vif_unref, vif);
© 2016 - 2025 Red Hat, Inc.