mac80211: backport ath9k memset fixes from upstream

Backport two upstream commits that replace memset() on coherent DMA
descriptor rings with explicit WRITE_ONCE() status word stores.

On 32-bit PowerPC platforms like apm821xx, coherent DMA memory may be
mapped uncached. The optimized memset() path can use dcbz there, which
triggers alignment warnings and spams the kernel log.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/23776
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
This commit is contained in:
Rosen Penev
2026-06-15 10:00:38 +02:00
committed by Jonas Jelonek
parent ebbe3a08a7
commit e4c35c2eec
2 changed files with 142 additions and 0 deletions
@@ -0,0 +1,108 @@
From 3e14d832e30b10478d2b0945ff2651f6784385a7 Mon Sep 17 00:00:00 2001
From: Rosen Penev <rosenp@gmail.com>
Date: Sat, 16 May 2026 16:43:10 -0700
Subject: [PATCH] wifi: ath9k: Clear DMA descriptors without memset
Clear ath9k DMA descriptors with explicit status word stores instead of
memset(). The descriptor rings are coherent DMA memory, which may be
mapped uncached on 32-bit powerpc. The optimized memset() path can use
dcbz there and trigger an alignment warning.
Use WRITE_ONCE() for the descriptor status words so the compiler keeps
the clears as ordinary stores instead of folding them back into bulk
memset(). This covers AR9003 TX status descriptors as well as the RX
status area cleared when setting up RX descriptors.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/net/wireless/ath/ath9k/ar9002_mac.c | 15 +++++++++++++-
drivers/net/wireless/ath/ath9k/ar9003_mac.c | 23 +++++++++++++++++----
2 files changed, 33 insertions(+), 5 deletions(-)
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -403,6 +403,19 @@ static int ar9002_hw_get_duration(struct
}
}
+static void ath9k_hw_clear_rxdesc_status(struct ar5416_desc *ads)
+{
+ WRITE_ONCE(ads->u.rx.status0, 0);
+ WRITE_ONCE(ads->u.rx.status1, 0);
+ WRITE_ONCE(ads->u.rx.status2, 0);
+ WRITE_ONCE(ads->u.rx.status3, 0);
+ WRITE_ONCE(ads->u.rx.status4, 0);
+ WRITE_ONCE(ads->u.rx.status5, 0);
+ WRITE_ONCE(ads->u.rx.status6, 0);
+ WRITE_ONCE(ads->u.rx.status7, 0);
+ WRITE_ONCE(ads->u.rx.status8, 0);
+}
+
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags)
{
@@ -412,7 +425,7 @@ void ath9k_hw_setuprxdesc(struct ath_hw
if (flags & ATH9K_RXDESC_INTREQ)
ads->ds_ctl1 |= AR_RxIntrReq;
- memset(&ads->u.rx, 0, sizeof(ads->u.rx));
+ ath9k_hw_clear_rxdesc_status(ads);
}
EXPORT_SYMBOL(ath9k_hw_setuprxdesc);
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -352,6 +352,19 @@ static bool ar9003_hw_get_isr(struct ath
return true;
}
+static void ath9k_hw_clear_txstatus(struct ar9003_txs *ads)
+{
+ WRITE_ONCE(ads->ds_info, 0);
+ WRITE_ONCE(ads->status1, 0);
+ WRITE_ONCE(ads->status2, 0);
+ WRITE_ONCE(ads->status3, 0);
+ WRITE_ONCE(ads->status4, 0);
+ WRITE_ONCE(ads->status5, 0);
+ WRITE_ONCE(ads->status6, 0);
+ WRITE_ONCE(ads->status7, 0);
+ WRITE_ONCE(ads->status8, 0);
+}
+
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
@@ -370,7 +383,7 @@ static int ar9003_hw_proc_txdesc(struct
(MS(ads->ds_info, AR_TxRxDesc) != 1)) {
ath_dbg(ath9k_hw_common(ah), XMIT,
"Tx Descriptor error %x\n", ads->ds_info);
- memset(ads, 0, sizeof(*ads));
+ ath9k_hw_clear_txstatus(ads);
return -EIO;
}
@@ -427,7 +440,7 @@ static int ar9003_hw_proc_txdesc(struct
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
- memset(ads, 0, sizeof(*ads));
+ ath9k_hw_clear_txstatus(ads);
return 0;
}
@@ -591,10 +604,12 @@ EXPORT_SYMBOL(ath9k_hw_process_rxdesc_ed
void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah)
{
+ int i;
+
ah->ts_tail = 0;
- memset((void *) ah->ts_ring, 0,
- ah->ts_size * sizeof(struct ar9003_txs));
+ for (i = 0; i < ah->ts_size; i++)
+ ath9k_hw_clear_txstatus(&ah->ts_ring[i]);
ath_dbg(ath9k_hw_common(ah), XMIT,
"TS Start 0x%x End 0x%x Virt %p, Size %d\n",
@@ -0,0 +1,34 @@
From 0da0cfb0840f7fe7df34bde4f787d3435e3db674 Mon Sep 17 00:00:00 2001
From: Rosen Penev <rosenp@gmail.com>
Date: Sat, 16 May 2026 20:28:16 -0700
Subject: [PATCH] wifi: ath9k: remove TX99 power array zero init
This array is fully initialized in the loop itself. No need to zero
initialize and then overwrite.
Remove static from the array. This was a holdover from when the array
was a static global variable. It no longer confers any benefit.
Also add a min() call to avoid the manual if/ternary operation.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1737,10 +1737,10 @@ static void ar9003_hw_tx99_stop(struct a
static void ar9003_hw_tx99_set_txpower(struct ath_hw *ah, u8 txpower)
{
- static u8 p_pwr_array[ar9300RateSize] = { 0 };
+ u8 p_pwr_array[ar9300RateSize];
unsigned int i;
- txpower = txpower <= MAX_RATE_POWER ? txpower : MAX_RATE_POWER;
+ txpower = min(txpower, MAX_RATE_POWER);
for (i = 0; i < ar9300RateSize; i++)
p_pwr_array[i] = txpower;