* [PATCH] wifi: mt76: connac: fix txpower_cur not being updated
@ 2026-01-25 22:22 Lucid Duck
2026-01-27 1:59 ` Nick
` (3 more replies)
0 siblings, 4 replies; 19+ messages in thread
From: Lucid Duck @ 2026-01-25 22:22 UTC (permalink / raw)
To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Lucid Duck
The mt76_connac_mcu_set_rate_txpower() function sends TX power settings
to the firmware but never updates phy->txpower_cur. This causes
mt76_get_txpower() to return stale or incorrect values (typically
showing 3 dBm regardless of actual transmit power) when userspace
queries TX power via nl80211.
This affects MT7921 and other connac-based devices. Users observe:
$ iw dev wlan0 info
...
txpower 3.00 dBm
The firmware receives and applies the correct power level, but the
reported value is wrong because txpower_cur is never set.
Fix by updating phy->txpower_cur after successfully configuring TX
power, matching the behavior of other mt76 drivers like mt7915.
Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca>
---
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 045771228..7cd357419 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -2251,7 +2251,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
{
- int err;
+ int err, tx_power;
if (phy->cap.has_2ghz) {
err = mt76_connac_mcu_rate_txpower_band(phy,
@@ -2272,6 +2272,12 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
return err;
}
+ /* Update txpower_cur for accurate reporting via nl80211 */
+ tx_power = 2 * phy->hw->conf.power_level;
+ if (!tx_power)
+ tx_power = 127;
+ phy->txpower_cur = tx_power;
+
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH] wifi: mt76: connac: fix txpower_cur not being updated 2026-01-25 22:22 [PATCH] wifi: mt76: connac: fix txpower_cur not being updated Lucid Duck @ 2026-01-27 1:59 ` Nick 2026-01-27 12:21 ` Felix Fietkau ` (2 subsequent siblings) 3 siblings, 0 replies; 19+ messages in thread From: Nick @ 2026-01-27 1:59 UTC (permalink / raw) To: Lucid Duck; +Cc: linux-wireless, Felix Fietkau, Lorenzo Bianconi, Ryder Lee > The mt76_connac_mcu_set_rate_txpower() function sends TX power settings > to the firmware but never updates phy->txpower_cur. This causes > mt76_get_txpower() to return stale or incorrect values (typically > showing 3 dBm regardless of actual transmit power) when userspace > queries TX power via nl80211. > > This affects MT7921 and other connac-based devices. Users observe: > $ iw dev wlan0 info > ... > txpower 3.00 dBm > > The firmware receives and applies the correct power level, but the > reported value is wrong because txpower_cur is never set. > > Fix by updating phy->txpower_cur after successfully configuring TX > power, matching the behavior of other mt76 drivers like mt7915. > > Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> > --- > drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > index 045771228..7cd357419 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > @@ -2251,7 +2251,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, > > int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) > { > - int err; > + int err, tx_power; > > if (phy->cap.has_2ghz) { > err = mt76_connac_mcu_rate_txpower_band(phy, > @@ -2272,6 +2272,12 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) > return err; > } > > + /* Update txpower_cur for accurate reporting via nl80211 */ > + tx_power = 2 * phy->hw->conf.power_level; > + if (!tx_power) > + tx_power = 127; > + phy->txpower_cur = tx_power; > + > return 0; > } > EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower); > -- > 2.52.0 > Tested on kernel 6.18.7 $ iw dev phy#0 Unnamed/non-netdev interface wdev 0x2 addr 76:19:f8:16:a4:48 type P2P-device txpower 67.00 dBm Interface wlan0 ifindex 3 wdev 0x1 addr 74:19:f8:16:a4:48 type managed txpower 67.00 dBm ... Device tested is a USB WiFi adapter using the mt7921u driver. The txpower output is not correct. This is a problem that really needs to be fixed. My hope is that those that know how to help, do so. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] wifi: mt76: connac: fix txpower_cur not being updated 2026-01-25 22:22 [PATCH] wifi: mt76: connac: fix txpower_cur not being updated Lucid Duck 2026-01-27 1:59 ` Nick @ 2026-01-27 12:21 ` Felix Fietkau 2026-01-27 16:17 ` Bitterblue Smith 2026-01-30 21:54 ` [PATCH v2] wifi: mt76: mt7921: fix txpower reporting Lucid Duck 2026-01-30 21:58 ` [PATCH v2] wifi: mt76: mt7921: fix txpower reporting Lucid Duck 3 siblings, 1 reply; 19+ messages in thread From: Felix Fietkau @ 2026-01-27 12:21 UTC (permalink / raw) To: Lucid Duck, linux-wireless; +Cc: Lorenzo Bianconi, Ryder Lee On 25.01.26 23:22, Lucid Duck wrote: > The mt76_connac_mcu_set_rate_txpower() function sends TX power settings > to the firmware but never updates phy->txpower_cur. This causes > mt76_get_txpower() to return stale or incorrect values (typically > showing 3 dBm regardless of actual transmit power) when userspace > queries TX power via nl80211. > > This affects MT7921 and other connac-based devices. Users observe: > $ iw dev wlan0 info > ... > txpower 3.00 dBm > > The firmware receives and applies the correct power level, but the > reported value is wrong because txpower_cur is never set. > > Fix by updating phy->txpower_cur after successfully configuring TX > power, matching the behavior of other mt76 drivers like mt7915. > > Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> > --- > drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > index 045771228..7cd357419 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > @@ -2251,7 +2251,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, > > int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) > { > - int err; > + int err, tx_power; > > if (phy->cap.has_2ghz) { > err = mt76_connac_mcu_rate_txpower_band(phy, > @@ -2272,6 +2272,12 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) > return err; > } > > + /* Update txpower_cur for accurate reporting via nl80211 */ > + tx_power = 2 * phy->hw->conf.power_level; > + if (!tx_power) > + tx_power = 127; > + phy->txpower_cur = tx_power; phy->hw->conf.power_level is the user configured power level, not what the hardware is capable of transmitting. To fix it properly, I think you should determine the maximum rate power used in the loop within mt76_connac_mcu_rate_txpower_band (updated with each call). - Felix ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] wifi: mt76: connac: fix txpower_cur not being updated 2026-01-27 12:21 ` Felix Fietkau @ 2026-01-27 16:17 ` Bitterblue Smith 2026-01-27 17:00 ` Felix Fietkau 0 siblings, 1 reply; 19+ messages in thread From: Bitterblue Smith @ 2026-01-27 16:17 UTC (permalink / raw) To: Felix Fietkau, Lucid Duck, linux-wireless; +Cc: Lorenzo Bianconi, Ryder Lee On 27/01/2026 14:21, Felix Fietkau wrote: > On 25.01.26 23:22, Lucid Duck wrote: >> The mt76_connac_mcu_set_rate_txpower() function sends TX power settings >> to the firmware but never updates phy->txpower_cur. This causes >> mt76_get_txpower() to return stale or incorrect values (typically >> showing 3 dBm regardless of actual transmit power) when userspace >> queries TX power via nl80211. >> >> This affects MT7921 and other connac-based devices. Users observe: >> $ iw dev wlan0 info >> ... >> txpower 3.00 dBm >> >> The firmware receives and applies the correct power level, but the >> reported value is wrong because txpower_cur is never set. >> >> Fix by updating phy->txpower_cur after successfully configuring TX >> power, matching the behavior of other mt76 drivers like mt7915. >> >> Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> >> --- >> drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 8 +++++++- >> 1 file changed, 7 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c >> index 045771228..7cd357419 100644 >> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c >> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c >> @@ -2251,7 +2251,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, >> int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) >> { >> - int err; >> + int err, tx_power; >> if (phy->cap.has_2ghz) { >> err = mt76_connac_mcu_rate_txpower_band(phy, >> @@ -2272,6 +2272,12 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) >> return err; >> } >> + /* Update txpower_cur for accurate reporting via nl80211 */ >> + tx_power = 2 * phy->hw->conf.power_level; >> + if (!tx_power) >> + tx_power = 127; >> + phy->txpower_cur = tx_power; > > phy->hw->conf.power_level is the user configured power level, not what the hardware is capable of transmitting. > > To fix it properly, I think you should determine the maximum rate power used in the loop within mt76_connac_mcu_rate_txpower_band (updated with each call). > > - Felix > What about these older patches? https://patchwork.kernel.org/project/linux-wireless/list/?series=932665&submitter=&state=*&q=&archive=&delegate= ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] wifi: mt76: connac: fix txpower_cur not being updated 2026-01-27 16:17 ` Bitterblue Smith @ 2026-01-27 17:00 ` Felix Fietkau 0 siblings, 0 replies; 19+ messages in thread From: Felix Fietkau @ 2026-01-27 17:00 UTC (permalink / raw) To: Bitterblue Smith, Lucid Duck, linux-wireless; +Cc: Lorenzo Bianconi, Ryder Lee On 27.01.26 17:17, Bitterblue Smith wrote: > On 27/01/2026 14:21, Felix Fietkau wrote: >> On 25.01.26 23:22, Lucid Duck wrote: >>> The mt76_connac_mcu_set_rate_txpower() function sends TX power settings >>> to the firmware but never updates phy->txpower_cur. This causes >>> mt76_get_txpower() to return stale or incorrect values (typically >>> showing 3 dBm regardless of actual transmit power) when userspace >>> queries TX power via nl80211. >>> >>> This affects MT7921 and other connac-based devices. Users observe: >>> $ iw dev wlan0 info >>> ... >>> txpower 3.00 dBm >>> >>> The firmware receives and applies the correct power level, but the >>> reported value is wrong because txpower_cur is never set. >>> >>> Fix by updating phy->txpower_cur after successfully configuring TX >>> power, matching the behavior of other mt76 drivers like mt7915. >>> >>> Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> >>> --- >>> drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 8 +++++++- >>> 1 file changed, 7 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c >>> index 045771228..7cd357419 100644 >>> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c >>> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c >>> @@ -2251,7 +2251,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, >>> int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) >>> { >>> - int err; >>> + int err, tx_power; >>> if (phy->cap.has_2ghz) { >>> err = mt76_connac_mcu_rate_txpower_band(phy, >>> @@ -2272,6 +2272,12 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) >>> return err; >>> } >>> + /* Update txpower_cur for accurate reporting via nl80211 */ >>> + tx_power = 2 * phy->hw->conf.power_level; >>> + if (!tx_power) >>> + tx_power = 127; >>> + phy->txpower_cur = tx_power; >> >> phy->hw->conf.power_level is the user configured power level, not what the hardware is capable of transmitting. >> >> To fix it properly, I think you should determine the maximum rate power used in the loop within mt76_connac_mcu_rate_txpower_band (updated with each call). >> >> - Felix >> > > What about these older patches? > > https://patchwork.kernel.org/project/linux-wireless/list/?series=932665&submitter=&state=*&q=&archive=&delegate= If I remember correctly, I found some issues in those patches and asked the Author about them and he mentioned that he only tested them on some old 5.15 vendor tree and didn't actually use anything recent. So I dropped them from my tree again. - Felix ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2] wifi: mt76: mt7921: fix txpower reporting 2026-01-25 22:22 [PATCH] wifi: mt76: connac: fix txpower_cur not being updated Lucid Duck 2026-01-27 1:59 ` Nick 2026-01-27 12:21 ` Felix Fietkau @ 2026-01-30 21:54 ` Lucid Duck 2026-02-10 3:02 ` Nick 2026-03-09 21:50 ` Lucid Duck 2026-01-30 21:58 ` [PATCH v2] wifi: mt76: mt7921: fix txpower reporting Lucid Duck 3 siblings, 2 replies; 19+ messages in thread From: Lucid Duck @ 2026-01-30 21:54 UTC (permalink / raw) To: nbd; +Cc: lorenzo, linux-wireless, Lucid Duck The mt7921 driver never updates phy->txpower_cur, causing mt76_get_txpower() to report incorrect values via nl80211. Users see bogus txpower readings (typically 3 dBm or 67 dBm) regardless of actual regulatory limits. Fix this by updating txpower_cur in mt7921_bss_info_changed() when BSS_CHANGED_TXPOWER is set. Use bss_conf.txpower as the primary source, with a fallback to the channel's max_reg_power for cases where bss_conf.txpower is not populated (INT_MIN). Tested on Alfa AWUS036AXML (MT7921AU), kernel 6.18.6: - 2.4GHz ch1: 33 dBm (30 dBm limit + 3 dBm path delta) - PASS - 5GHz ch100: 27 dBm (24 dBm limit + 3 dBm path delta) - PASS - 6GHz ch5: 15 dBm (12 dBm limit + 3 dBm path delta) - PASS Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> --- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index f37a35b..99fe46d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -725,6 +725,25 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_CQM) mt7921_mcu_set_rssimonitor(dev, vif); + if (changed & BSS_CHANGED_TXPOWER) { + int tx_power = info->txpower; + + /* + * Workaround for kernel 6.18+: bss_conf.txpower may not be + * populated (INT_MIN) even when BSS_CHANGED_TXPOWER is set. + * In this case, use the channel's max regulatory power. + */ + if (tx_power == INT_MIN || tx_power <= 0) { + struct ieee80211_channel *chan = phy->mt76->chandef.chan; + if (chan) + tx_power = chan->max_reg_power; + } + + /* txpower is in dBm, txpower_cur is in 0.5dBm units */ + if (tx_power > 0 && tx_power < 127) + phy->mt76->txpower_cur = tx_power * 2; + } + if (changed & BSS_CHANGED_ASSOC) { mt7921_mcu_sta_update(dev, NULL, vif, true, MT76_STA_INFO_STATE_ASSOC); -- 2.43.0 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v2] wifi: mt76: mt7921: fix txpower reporting 2026-01-30 21:54 ` [PATCH v2] wifi: mt76: mt7921: fix txpower reporting Lucid Duck @ 2026-02-10 3:02 ` Nick 2026-02-12 2:46 ` Lucid Duck 2026-03-09 21:50 ` Lucid Duck 1 sibling, 1 reply; 19+ messages in thread From: Nick @ 2026-02-10 3:02 UTC (permalink / raw) To: Lucid Duck; +Cc: nbd, lorenzo, linux-wireless > The mt7921 driver never updates phy->txpower_cur, causing > mt76_get_txpower() to report incorrect values via nl80211. > Users see bogus txpower readings (typically 3 dBm or 67 dBm) > regardless of actual regulatory limits. > > Fix this by updating txpower_cur in mt7921_bss_info_changed() > when BSS_CHANGED_TXPOWER is set. Use bss_conf.txpower as the > primary source, with a fallback to the channel's max_reg_power > for cases where bss_conf.txpower is not populated (INT_MIN). > > Tested on Alfa AWUS036AXML (MT7921AU), kernel 6.18.6: > - 2.4GHz ch1: 33 dBm (30 dBm limit + 3 dBm path delta) - PASS > - 5GHz ch100: 27 dBm (24 dBm limit + 3 dBm path delta) - PASS > - 6GHz ch5: 15 dBm (12 dBm limit + 3 dBm path delta) - PASS I just tested this patch with a fresh download of kernel 6.18.8. All I see is 3 dBm when running "iw dev". My USB WiFi adapter also uses the mt7921u driver. Also, something just doesn't seem right with 33, 27 and 15 dBm. You are in CA, right? > Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> > --- > drivers/net/wireless/mediatek/mt76/mt7921/main.c | 19 +++++++++++++++++++ > 1 file changed, 19 insertions(+) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c > index f37a35b..99fe46d 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c > @@ -725,6 +725,25 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, > if (changed & BSS_CHANGED_CQM) > mt7921_mcu_set_rssimonitor(dev, vif); > > + if (changed & BSS_CHANGED_TXPOWER) { > + int tx_power = info->txpower; > + > + /* > + * Workaround for kernel 6.18+: bss_conf.txpower may not be > + * populated (INT_MIN) even when BSS_CHANGED_TXPOWER is set. > + * In this case, use the channel's max regulatory power. > + */ > + if (tx_power == INT_MIN || tx_power <= 0) { > + struct ieee80211_channel *chan = phy->mt76->chandef.chan; > + if (chan) > + tx_power = chan->max_reg_power; > + } > + > + /* txpower is in dBm, txpower_cur is in 0.5dBm units */ > + if (tx_power > 0 && tx_power < 127) > + phy->mt76->txpower_cur = tx_power * 2; > + } > + > if (changed & BSS_CHANGED_ASSOC) { > mt7921_mcu_sta_update(dev, NULL, vif, true, > MT76_STA_INFO_STATE_ASSOC); > -- > 2.43.0 > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] wifi: mt76: mt7921: fix txpower reporting 2026-02-10 3:02 ` Nick @ 2026-02-12 2:46 ` Lucid Duck 0 siblings, 0 replies; 19+ messages in thread From: Lucid Duck @ 2026-02-12 2:46 UTC (permalink / raw) To: morrownr; +Cc: nbd, lorenzo, linux-wireless, Lucid Duck [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1973 bytes --] On Mon, 9 Feb 2026, Nick wrote: > I just tested this patch with a fresh download of kernel 6.18.8. All I > see is 3 dBm when running "iw dev". My USB WiFi adapter also uses the > mt7921u driver. Hi Nick, Thanks for testing. First thing to check: were you associated to an AP when you ran the command? This v2 updates txpower_cur from mt7921_bss_info_changed() on BSS_CHANGED_TXPOWER, which only fires when there is an active BSS context. If the interface is not connected, that callback may never run and txpower_cur can remain at its default (which often shows up as 3 dBm via iw). Could you share the output of these while testing? iw dev wlan0 link iw dev wlan0 info iw reg get If you can reproduce the 3 dBm while clearly associated (the iw ... link output shows a connected state), then we are looking at a different path not triggering the update on your setup, and I can adjust where the driver sets txpower_cur (likely earlier around channel context setup rather than only in BSS change handling). > Also, something just doesn't seem right with 33, 27 and 15 dBm. You > are in CA, right? I am in Canada (not California). Those numbers are not a measurement of actual RF output, they are derived from the regulatory information (the chan->max_reg_power fallback path) when bss_conf.txpower is not populated. They will vary based on regulatory domain and the channel/band selected. For reference: Canada (ISED) US (FCC) 2.4 GHz 30 dBm 30 dBm 5 GHz DFS 24 dBm 24 dBm 6 GHz LPI 12 dBm 30 dBm The 6 GHz band is where the difference is most visible — ISED limits low-power indoor to 12 dBm while FCC allows 30 dBm. The values you see will depend on what iw reg get reports for your system. Thanks again, your results are helpful for tightening up the next revision. Lucid Duck ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] wifi: mt76: mt7921: fix txpower reporting 2026-01-30 21:54 ` [PATCH v2] wifi: mt76: mt7921: fix txpower reporting Lucid Duck 2026-02-10 3:02 ` Nick @ 2026-03-09 21:50 ` Lucid Duck 2026-03-12 6:38 ` Sean Wang 1 sibling, 1 reply; 19+ messages in thread From: Lucid Duck @ 2026-03-09 21:50 UTC (permalink / raw) To: Felix Fietkau; +Cc: linux-wireless, Lucid Duck Hi Felix, Friendly ping on this v2 from January 30. Life got in the way of following up sooner -- apologies for the delay. Since submitting, Nick (morrownr, USB-WiFi maintainer) has tested and confirmed the fix works on his MT7921U adapter -- 33 dBm on 2.4 GHz and 24 dBm on 5 GHz, both matching regulatory limits as expected. I noticed Bryam Vargas recently submitted a competing fix that updates txpower_cur in mt76_connac_mcu_set_rate_txpower(). That function is only called from mt7921_set_sar_specs(), so it wouldn't fire during normal AP association or channel changes. My v2 hooks bss_info_changed() on BSS_CHANGED_TXPOWER, which covers the common case. Happy to rework if you'd prefer a different approach -- just wanted to make sure this wasn't lost in the shuffle. Thanks, Lucid Duck ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] wifi: mt76: mt7921: fix txpower reporting 2026-03-09 21:50 ` Lucid Duck @ 2026-03-12 6:38 ` Sean Wang 2026-03-17 17:30 ` [PATCH v3 0/1] wifi: mt76: mt7921: fix txpower reporting from rate power configuration Lucid Duck 0 siblings, 1 reply; 19+ messages in thread From: Sean Wang @ 2026-03-12 6:38 UTC (permalink / raw) To: Lucid Duck; +Cc: Felix Fietkau, linux-wireless Hi Lucid, On Mon, Mar 9, 2026 at 4:55 PM Lucid Duck <lucid_duck@justthetip.ca> wrote: > > Hi Felix, > > Friendly ping on this v2 from January 30. Life got in the way of > following up sooner -- apologies for the delay. > > Since submitting, Nick (morrownr, USB-WiFi maintainer) has tested and > confirmed the fix works on his MT7921U adapter -- 33 dBm on 2.4 GHz > and 24 dBm on 5 GHz, both matching regulatory limits as expected. > > I noticed Bryam Vargas recently submitted a competing fix that updates > txpower_cur in mt76_connac_mcu_set_rate_txpower(). That function is > only called from mt7921_set_sar_specs(), so it wouldn't fire during > normal AP association or channel changes. My v2 hooks > bss_info_changed() on BSS_CHANGED_TXPOWER, which covers the common > case. > The maximum value tracked in the loop inside mt76_connac_mcu_rate_txpower_band() is close to the actual maximum power that users generally expect to see reported. If the value is not derived from that path, the reported txpower may not reflect the SAR limits that are actually applied to the hardware. mt7921_set_sar_specs() is mainly the userspace entry point for SAR configuration. The actual SAR power update path goes through mt7921_set_tx_sar_pwr(). If you look closely, mt7921_set_tx_sar_pwr() is invoked in several situations, including device start and regulatory updates. Therefore it is still part of the configuration flow that determines the effective transmit power. > Happy to rework if you'd prefer a different approach -- just wanted to > make sure this wasn't lost in the shuffle. > > Thanks, > Lucid Duck > ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 0/1] wifi: mt76: mt7921: fix txpower reporting from rate power configuration 2026-03-12 6:38 ` Sean Wang @ 2026-03-17 17:30 ` Lucid Duck 2026-03-17 17:30 ` [PATCH v3 1/1] " Lucid Duck 0 siblings, 1 reply; 19+ messages in thread From: Lucid Duck @ 2026-03-17 17:30 UTC (permalink / raw) To: linux-wireless Cc: nbd, sean.wang, lorenzo, linux-mediatek, morrownr, Lucid Duck Sean, Felix, Here's v3 of the txpower fix, reworked based on both of your feedback. Felix pointed out in v1 review that the fix should determine the maximum rate power from the loop in mt76_connac_mcu_rate_txpower_band(). Sean confirmed this direction in v2 review and clarified that the value should come from the same computation that configures the firmware's per-rate power tables, not from bss_conf.txpower. v3 does exactly that. The loop already computes the right value via mt76_get_rate_power_limits() but discards the return. This patch captures it and stores it to phy->txpower_cur for the current channel, matching how mt7915 handles this in mt7915_mcu_set_txpower_sku(). Nick independently confirmed v2 produced correct values on his MT7921AU -- v3 preserves those results while addressing the source-of-truth concern. Two additional issues came up during implementation: - mt7921's chanctx callbacks don't update phy->chandef (the common mt76_add_chanctx does, but mt7921 overrides it with a minimal version). Fixed by syncing chandef from ctx->def and re-triggering the rate power path in add_chanctx and change_chanctx. - For chanctx drivers, mac80211 routes iw set txpower through BSS_CHANGED_TXPOWER, not IEEE80211_CONF_CHANGE_POWER, and never updates hw->conf.power_level. Added a BSS_CHANGED_TXPOWER handler to bridge this into the rate power path. Tested on Alfa AWUS036AXML (MT7921AU), kernel 6.17.1, Canada: Band Auto User limit (15dBm) Stock (before) 2.4GHz 33 dBm 18 dBm 3 dBm 5GHz 26 dBm 18 dBm 3 dBm 6GHz 15 dBm 8 dBm (5dBm limit) 3 dBm Values match regulatory limits + 3 dBm 2x2 path delta. Test suite (973 tests, 3.5 hours): Regulatory accuracy: correct on all 3 bands (2.4/5/6 GHz) User txpower sweep: every 1 dBm from 1 to reg_max, all 3 bands Band switching: 100 cycles between 2.4 and 5 GHz, 0 failures Module reload: 50 rmmod/insmod/connect/verify cycles, 0 failures 2-hour soak: 480 samples at 15s intervals, zero drift Band rotation soak: 30 rotations across all 3 bands over 1 hour, 240 samples, 0 failures Regdomain switching: 10 countries (CA/US/JP/DE/GB/AU/NZ/BR/KR/TW) mid-session without reconnecting, all correct (JP correctly dropped to 23 dBm on 5GHz UNII-1) Monitor mode: correct on ch1/6/11 (2.4GHz) and ch36/44/149 (5GHz), txpower set works in monitor mode Edge cases: min power (1dBm), over-max clamping, rapid power changes (10 in 10s), all correct Firmware cross-check: debugfs txpower_sku confirms per-rate tables match regulatory limits on all bands Lucid Duck (1): wifi: mt76: mt7921: fix txpower reporting from rate power configuration .../wireless/mediatek/mt76/mt76_connac_mcu.c | 12 +++++++--- .../net/wireless/mediatek/mt76/mt7921/main.c | 22 ++++++++++++++++++- 2 files changed, 30 insertions(+), 4 deletions(-) -- 2.51.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 1/1] wifi: mt76: mt7921: fix txpower reporting from rate power configuration 2026-03-17 17:30 ` [PATCH v3 0/1] wifi: mt76: mt7921: fix txpower reporting from rate power configuration Lucid Duck @ 2026-03-17 17:30 ` Lucid Duck 2026-03-17 21:51 ` Lucid Duck 2026-03-19 6:00 ` Sean Wang 0 siblings, 2 replies; 19+ messages in thread From: Lucid Duck @ 2026-03-17 17:30 UTC (permalink / raw) To: linux-wireless Cc: nbd, sean.wang, lorenzo, linux-mediatek, morrownr, Lucid Duck The mt7921 driver never updates phy->txpower_cur when TX power rate configuration is sent to firmware. This causes mt76_get_txpower() to report bogus values to userspace (typically 3 dBm) regardless of actual regulatory or SAR limits. User-set txpower limits via iw are also not reflected. Three root causes are addressed: 1. The rate power loop in mt76_connac_mcu_rate_txpower_band() computes the correct bounded TX power for each channel but discards the return value of mt76_get_rate_power_limits(). Fix: capture the return value and store it to phy->txpower_cur when processing the current channel. 2. mt7921 uses the chanctx model but its add_chanctx callback bypasses the common mt76_phy_update_channel(), leaving phy->chandef stale. Fix: update phy->chandef from ctx->def in both add_chanctx and change_chanctx, and trigger the rate power path to refresh txpower_cur. Also trigger on IEEE80211_CONF_CHANGE_CHANNEL in config(), matching mt7915. 3. For chanctx drivers, mac80211 routes user txpower changes through BSS_CHANGED_TXPOWER in bss_info_changed() -- not through IEEE80211_CONF_CHANGE_POWER in config(). hw->conf.power_level is never updated. Fix: handle BSS_CHANGED_TXPOWER in mt7921_bss_info_changed(), bridge bss_conf.txpower to hw->conf.power_level, and re-trigger the rate power path. Tested on Alfa AWUS036AXML (MT7921AU), kernel 6.17.1-300.fc43: Before: iw dev wlan0 info shows "txpower 3.00 dBm" (wrong) After: correct per-band values, user limits reflected Test results (regulatory domain: Canada/CA): - 2.4GHz ch6: 33 dBm (30 dBm limit + 3 dBm 2x2 path delta) - 5GHz ch36: 26 dBm (23 dBm limit + 3 dBm path delta) - 6GHz ch5: 15 dBm (12 dBm limit + 3 dBm path delta) - Band switch: 100 cycles, 0 failures - Module reload: 50 cycles, 0 failures - 2-hour soak: 480 samples, zero drift - Regdomain switching: 10 countries, all correct - User txpower limits: reflected on all bands - Monitor mode: correct on all tested channels Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> --- .../wireless/mediatek/mt76/mt76_connac_mcu.c | 12 +++++++--- .../net/wireless/mediatek/mt76/mt7921/main.c | 22 ++++++++++++++++++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 16db0f208..5856924a9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -2193,14 +2193,20 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, .hw_value = ch_list[idx], .band = band, }; - s8 reg_power, sar_power; + s8 reg_power, sar_power, max_power; reg_power = mt76_connac_get_ch_power(phy, &chan, tx_power); sar_power = mt76_get_sar_power(phy, &chan, reg_power); - mt76_get_rate_power_limits(phy, &chan, limits, - sar_power); + max_power = mt76_get_rate_power_limits(phy, &chan, + limits, + sar_power); + + if (phy->chandef.chan && + phy->chandef.chan->hw_value == ch_list[idx] && + phy->chandef.chan->band == band) + phy->txpower_cur = max_power; tx_power_tlv.last_msg = ch_list[idx] == last_ch; sku_tlbv.channel = ch_list[idx]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 5881040ac..38a59c6f2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -638,7 +638,8 @@ static int mt7921_config(struct ieee80211_hw *hw, int radio_idx, u32 changed) mt792x_mutex_acquire(dev); - if (changed & IEEE80211_CONF_CHANGE_POWER) { + if (changed & (IEEE80211_CONF_CHANGE_POWER | + IEEE80211_CONF_CHANGE_CHANNEL)) { ret = mt7921_set_tx_sar_pwr(hw, NULL); if (ret) goto out; @@ -719,6 +720,14 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_CQM) mt7921_mcu_set_rssimonitor(dev, vif); + if (changed & BSS_CHANGED_TXPOWER) { + int tx_power = info->txpower; + + if (tx_power != INT_MIN && tx_power > 0) + hw->conf.power_level = tx_power; + mt7921_set_tx_sar_pwr(hw, NULL); + } + if (changed & BSS_CHANGED_ASSOC) { mt7921_mcu_sta_update(dev, NULL, vif, true, MT76_STA_INFO_STATE_ASSOC); @@ -1360,8 +1369,15 @@ mt7921_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; dev->new_ctx = ctx; + mphy->chandef = ctx->def; + + mt792x_mutex_acquire(dev); + mt7921_set_tx_sar_pwr(hw, NULL); + mt792x_mutex_release(dev); + return 0; } @@ -1396,6 +1412,10 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, mt7921_mcu_config_sniffer(mvif, ctx); else mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->bss_conf.mt76, ctx); + + phy->mt76->chandef = ctx->def; + mt7921_set_tx_sar_pwr(hw, NULL); + mt792x_mutex_release(phy->dev); } -- 2.51.0 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v3 1/1] wifi: mt76: mt7921: fix txpower reporting from rate power configuration 2026-03-17 17:30 ` [PATCH v3 1/1] " Lucid Duck @ 2026-03-17 21:51 ` Lucid Duck 2026-03-19 6:00 ` Sean Wang 1 sibling, 0 replies; 19+ messages in thread From: Lucid Duck @ 2026-03-17 21:51 UTC (permalink / raw) To: linux-wireless; +Cc: nbd, sean.wang, lorenzo, linux-mediatek, stable I missed adding the stable tag. This bug has been present since the mt7921 driver was introduced, so it should be backported to maintained stable kernels: Cc: stable@vger.kernel.org Fixes: 1c099ab44727 ("mt76: mt7921: add MAC support") Sorry for the oversight. Lucid Duck ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 1/1] wifi: mt76: mt7921: fix txpower reporting from rate power configuration 2026-03-17 17:30 ` [PATCH v3 1/1] " Lucid Duck 2026-03-17 21:51 ` Lucid Duck @ 2026-03-19 6:00 ` Sean Wang 2026-03-19 20:38 ` [PATCH v4] " Lucid Duck 1 sibling, 1 reply; 19+ messages in thread From: Sean Wang @ 2026-03-19 6:00 UTC (permalink / raw) To: Lucid Duck; +Cc: linux-wireless, nbd, lorenzo, linux-mediatek, morrownr Hi, On Tue, Mar 17, 2026 at 12:30 PM Lucid Duck <lucid_duck@justthetip.ca> wrote: > > The mt7921 driver never updates phy->txpower_cur > when TX power rate configuration is sent to firmware. This causes > mt76_get_txpower() to report bogus values to userspace (typically > 3 dBm) regardless of actual regulatory or SAR limits. User-set > txpower limits via iw are also not reflected. > > Three root causes are addressed: > > 1. The rate power loop in mt76_connac_mcu_rate_txpower_band() computes > the correct bounded TX power for each channel but discards the return > value of mt76_get_rate_power_limits(). Fix: capture the return value > and store it to phy->txpower_cur when processing the current channel. > > 2. mt7921 uses the chanctx model but its add_chanctx callback bypasses > the common mt76_phy_update_channel(), leaving phy->chandef stale. > Fix: update phy->chandef from ctx->def in both add_chanctx and > change_chanctx, and trigger the rate power path to refresh > txpower_cur. Also trigger on IEEE80211_CONF_CHANGE_CHANNEL in > config(), matching mt7915. > > 3. For chanctx drivers, mac80211 routes user txpower changes through > BSS_CHANGED_TXPOWER in bss_info_changed() -- not through > IEEE80211_CONF_CHANGE_POWER in config(). hw->conf.power_level is > never updated. Fix: handle BSS_CHANGED_TXPOWER in > mt7921_bss_info_changed(), bridge bss_conf.txpower to > hw->conf.power_level, and re-trigger the rate power path. > > Tested on Alfa AWUS036AXML (MT7921AU), kernel 6.17.1-300.fc43: > > Before: iw dev wlan0 info shows "txpower 3.00 dBm" (wrong) > After: correct per-band values, user limits reflected > > Test results (regulatory domain: Canada/CA): > - 2.4GHz ch6: 33 dBm (30 dBm limit + 3 dBm 2x2 path delta) > - 5GHz ch36: 26 dBm (23 dBm limit + 3 dBm path delta) > - 6GHz ch5: 15 dBm (12 dBm limit + 3 dBm path delta) > - Band switch: 100 cycles, 0 failures > - Module reload: 50 cycles, 0 failures > - 2-hour soak: 480 samples, zero drift > - Regdomain switching: 10 countries, all correct > - User txpower limits: reflected on all bands > - Monitor mode: correct on all tested channels > > Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> > --- > .../wireless/mediatek/mt76/mt76_connac_mcu.c | 12 +++++++--- > .../net/wireless/mediatek/mt76/mt7921/main.c | 22 ++++++++++++++++++- > 2 files changed, 30 insertions(+), 4 deletions(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > index 16db0f208..5856924a9 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > @@ -2193,14 +2193,20 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, > .hw_value = ch_list[idx], > .band = band, > }; > - s8 reg_power, sar_power; > + s8 reg_power, sar_power, max_power; > > reg_power = mt76_connac_get_ch_power(phy, &chan, > tx_power); > sar_power = mt76_get_sar_power(phy, &chan, reg_power); > > - mt76_get_rate_power_limits(phy, &chan, limits, > - sar_power); > + max_power = mt76_get_rate_power_limits(phy, &chan, > + limits, > + sar_power); > + > + if (phy->chandef.chan && > + phy->chandef.chan->hw_value == ch_list[idx] && > + phy->chandef.chan->band == band) > + phy->txpower_cur = max_power; > > tx_power_tlv.last_msg = ch_list[idx] == last_ch; > sku_tlbv.channel = ch_list[idx]; > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c > index 5881040ac..38a59c6f2 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c > @@ -638,7 +638,8 @@ static int mt7921_config(struct ieee80211_hw *hw, int radio_idx, u32 changed) > > mt792x_mutex_acquire(dev); > > - if (changed & IEEE80211_CONF_CHANGE_POWER) { > + if (changed & (IEEE80211_CONF_CHANGE_POWER | > + IEEE80211_CONF_CHANGE_CHANNEL)) { > ret = mt7921_set_tx_sar_pwr(hw, NULL); > if (ret) > goto out; > @@ -719,6 +720,14 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, > if (changed & BSS_CHANGED_CQM) > mt7921_mcu_set_rssimonitor(dev, vif); > > + if (changed & BSS_CHANGED_TXPOWER) { > + int tx_power = info->txpower; > + > + if (tx_power != INT_MIN && tx_power > 0) > + hw->conf.power_level = tx_power; > + mt7921_set_tx_sar_pwr(hw, NULL); > + } > + > if (changed & BSS_CHANGED_ASSOC) { > mt7921_mcu_sta_update(dev, NULL, vif, true, > MT76_STA_INFO_STATE_ASSOC); > @@ -1360,8 +1369,15 @@ mt7921_add_chanctx(struct ieee80211_hw *hw, > struct ieee80211_chanctx_conf *ctx) > { > struct mt792x_dev *dev = mt792x_hw_dev(hw); > + struct mt76_phy *mphy = hw->priv; > > dev->new_ctx = ctx; > + mphy->chandef = ctx->def; > + > + mt792x_mutex_acquire(dev); > + mt7921_set_tx_sar_pwr(hw, NULL); > + mt792x_mutex_release(dev); > + > return 0; > } > > @@ -1396,6 +1412,10 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, > mt7921_mcu_config_sniffer(mvif, ctx); > else > mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->bss_conf.mt76, ctx); > + > + phy->mt76->chandef = ctx->def; > + mt7921_set_tx_sar_pwr(hw, NULL); > + I do not think the additional mt7921_set_tx_sar_pwr() calls are justified. mt7921_set_tx_sar_pwr() is not a lightweight per-channel refresh. It rebuilds and pushes the rate txpower table for all channels in the band through the MCU path. This is appropriate when the underlying power constraints change (e.g. SAR, regulatory limits, or user-configured txpower), but not for pure channel/chanctx transitions. add_chanctx(), change_chanctx(), and IEEE80211_CONF_CHANGE_CHANNEL only reflect channel/context changes and do not imply that the firmware txpower table needs to be recomputed. Using mt7921_set_tx_sar_pwr() here effectively turns it into a catch-all sync path. If the issue is stale txpower reporting after a channel switch, it should be fixed by updating phy->txpower_cur from the already computed bounded max power for the current channel, rather than re-triggering full table programming on every chanctx/channel event. BSS_CHANGED_TXPOWER is also problematic. It is a per-BSS (per-vif) event, while hw->conf.power_level is shared per-HW state. Writing info->txpower into hw->conf.power_level allows one interface to affect the effective txpower of others sharing the same PHY, which breaks multi-vif semantics. > mt792x_mutex_release(phy->dev); > } > > -- > 2.51.0 > ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v4] wifi: mt76: mt7921: fix txpower reporting from rate power configuration 2026-03-19 6:00 ` Sean Wang @ 2026-03-19 20:38 ` Lucid Duck 2026-03-20 1:17 ` Lucid Duck 2026-03-21 8:58 ` Sean Wang 0 siblings, 2 replies; 19+ messages in thread From: Lucid Duck @ 2026-03-19 20:38 UTC (permalink / raw) To: Sean Wang Cc: Felix Fietkau, Lorenzo Bianconi, linux-wireless, linux-mediatek, morrownr, Lucid Duck, stable The mt7921 driver never updates phy->txpower_cur from the rate power configuration sent to firmware, causing mt76_get_txpower() to report bogus values to userspace (typically 3 dBm) regardless of actual regulatory or SAR limits. Two issues are addressed: 1. The rate power loop in mt76_connac_mcu_rate_txpower_band() computes the correct bounded TX power per channel via mt76_get_rate_power_limits() but discards the return value. Capture it and store to phy->txpower_cur when processing the current channel, matching how mt7915 handles this in mt7915_mcu_set_txpower_sku(). Subtract the multi-chain path delta before storing, since mt76_get_txpower() adds it back when reporting -- consistent with mt7915's use of mt76_get_power_bound() which performs the same subtraction. 2. mt7921 uses the chanctx model but its add_chanctx callback does not update phy->chandef, leaving it stale after association. The rate power loop's channel comparison then fails silently. Sync phy->chandef from ctx->def in add_chanctx and change_chanctx, and recompute txpower_cur via a lightweight helper that performs the same bounded power calculation for the current channel without reprogramming firmware rate tables. Tested on Alfa AWUS036AXML (MT7921AU), kernel 6.19.8, Canada: Before: iw dev wlan0 info shows "txpower 3.00 dBm" (wrong) After: 2.4GHz 36 dBm, 5GHz 23 dBm, 6GHz 12 dBm (match regulatory) Cc: stable@vger.kernel.org Fixes: 1c099ab44727 ("mt76: mt7921: add MAC support") Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> --- Changes since v3: - Removed mt7921_set_tx_sar_pwr() from add_chanctx and change_chanctx. Channel transitions don't change underlying power constraints, so reprogramming the full rate table is unnecessary. Replaced with a lightweight helper that recomputes txpower_cur locally. - Removed IEEE80211_CONF_CHANGE_CHANNEL trigger from config(). - Removed BSS_CHANGED_TXPOWER handler from bss_info_changed(). Writing per-vif txpower into per-HW hw->conf.power_level breaks multi-vif semantics. User txpower limits need a different approach (follow-up). - Subtracted path delta before storing txpower_cur. The connac rate loop stores total bounded power, but mt76_get_txpower() adds the multi-chain path delta when reporting. mt7915 accounts for this via mt76_get_power_bound(), which subtracts the delta before storing. Without the same subtraction, reported values were inflated by 3 dBm on 2x2 devices. .../wireless/mediatek/mt76/mt76_connac_mcu.c | 14 +++++++-- .../net/wireless/mediatek/mt76/mt7921/main.c | 30 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 16db0f208..e26a2cb39 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -2193,14 +2193,22 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, .hw_value = ch_list[idx], .band = band, }; - s8 reg_power, sar_power; + s8 reg_power, sar_power, max_power; reg_power = mt76_connac_get_ch_power(phy, &chan, tx_power); sar_power = mt76_get_sar_power(phy, &chan, reg_power); - mt76_get_rate_power_limits(phy, &chan, limits, - sar_power); + max_power = mt76_get_rate_power_limits(phy, &chan, + limits, + sar_power); + + if (phy->chandef.chan && + phy->chandef.chan->hw_value == ch_list[idx] && + phy->chandef.chan->band == band) + phy->txpower_cur = max_power - + mt76_tx_power_path_delta( + hweight16(phy->chainmask)); tx_power_tlv.last_msg = ch_list[idx] == last_ch; sku_tlbv.channel = ch_list[idx]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 5881040ac..a77ae5791 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1355,13 +1355,39 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt792x_mutex_release(dev); } +static void mt7921_update_txpower_cur(struct mt76_phy *phy) +{ + struct mt76_power_limits limits; + struct ieee80211_channel *chan = phy->chandef.chan; + int n_chains = hweight16(phy->chainmask); + s8 reg_power, sar_power, max_power; + int tx_power; + + if (!chan) + return; + + tx_power = 2 * phy->hw->conf.power_level; + if (!tx_power) + tx_power = 127; + + reg_power = mt76_connac_get_ch_power(phy, chan, tx_power); + sar_power = mt76_get_sar_power(phy, chan, reg_power); + max_power = mt76_get_rate_power_limits(phy, chan, &limits, sar_power); + + phy->txpower_cur = max_power - mt76_tx_power_path_delta(n_chains); +} + static int mt7921_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; dev->new_ctx = ctx; + mphy->chandef = ctx->def; + mt7921_update_txpower_cur(mphy); + return 0; } @@ -1396,6 +1422,10 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, mt7921_mcu_config_sniffer(mvif, ctx); else mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->bss_conf.mt76, ctx); + + phy->mt76->chandef = ctx->def; + mt7921_update_txpower_cur(phy->mt76); + mt792x_mutex_release(phy->dev); } -- 2.53.0 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v4] wifi: mt76: mt7921: fix txpower reporting from rate power configuration 2026-03-19 20:38 ` [PATCH v4] " Lucid Duck @ 2026-03-20 1:17 ` Lucid Duck 2026-03-20 6:34 ` Greg KH 2026-03-21 8:58 ` Sean Wang 1 sibling, 1 reply; 19+ messages in thread From: Lucid Duck @ 2026-03-20 1:17 UTC (permalink / raw) To: sean.wang; +Cc: nbd, lorenzo, linux-wireless, linux-mediatek, morrownr, stable Note for stable backport: this patch uses mt76_tx_power_path_delta() which was introduced in commit 56e38675c5bd ("mt76: support power delta calculation for 5 TX paths"). That commit renamed the older mt76_tx_power_nss_delta() and is needed as a prerequisite for the backport to compile. For stable kernels that don't have 56e3867, a trivial substitution of mt76_tx_power_nss_delta for mt76_tx_power_path_delta produces identical results for 1-4 chain devices (the lookup tables match exactly). Reported-by: sam8641 (compile failure on 6.12.74) ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4] wifi: mt76: mt7921: fix txpower reporting from rate power configuration 2026-03-20 1:17 ` Lucid Duck @ 2026-03-20 6:34 ` Greg KH 0 siblings, 0 replies; 19+ messages in thread From: Greg KH @ 2026-03-20 6:34 UTC (permalink / raw) To: Lucid Duck Cc: sean.wang, nbd, lorenzo, linux-wireless, linux-mediatek, morrownr, stable On Thu, Mar 19, 2026 at 06:17:27PM -0700, Lucid Duck wrote: > Note for stable backport: this patch uses mt76_tx_power_path_delta() > which was introduced in commit 56e38675c5bd ("mt76: support power delta > calculation for 5 TX paths"). That commit renamed the older > mt76_tx_power_nss_delta() and is needed as a prerequisite for the > backport to compile. > > For stable kernels that don't have 56e3867, a trivial substitution of > mt76_tx_power_nss_delta for mt76_tx_power_path_delta produces identical > results for 1-4 chain devices (the lookup tables match exactly). > > Reported-by: sam8641 (compile failure on 6.12.74) This "note for stable backport" will get lost, sorry. Can you provide working backports to stable@vger.kernel.org when this lands in Linus's tree? thanks, greg k-h ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4] wifi: mt76: mt7921: fix txpower reporting from rate power configuration 2026-03-19 20:38 ` [PATCH v4] " Lucid Duck 2026-03-20 1:17 ` Lucid Duck @ 2026-03-21 8:58 ` Sean Wang 1 sibling, 0 replies; 19+ messages in thread From: Sean Wang @ 2026-03-21 8:58 UTC (permalink / raw) To: Lucid Duck Cc: Felix Fietkau, Lorenzo Bianconi, linux-wireless, linux-mediatek, morrownr, stable Hi, On Thu, Mar 19, 2026 at 3:39 PM Lucid Duck <lucid_duck@justthetip.ca> wrote: > > The mt7921 driver never updates phy->txpower_cur from the rate power > configuration sent to firmware, causing mt76_get_txpower() to report > bogus values to userspace (typically 3 dBm) regardless of actual > regulatory or SAR limits. > > Two issues are addressed: > > 1. The rate power loop in mt76_connac_mcu_rate_txpower_band() computes > the correct bounded TX power per channel via > mt76_get_rate_power_limits() but discards the return value. Capture > it and store to phy->txpower_cur when processing the current > channel, matching how mt7915 handles this in > mt7915_mcu_set_txpower_sku(). Subtract the multi-chain path delta > before storing, since mt76_get_txpower() adds it back when > reporting -- consistent with mt7915's use of mt76_get_power_bound() > which performs the same subtraction. > > 2. mt7921 uses the chanctx model but its add_chanctx callback does not > update phy->chandef, leaving it stale after association. The rate > power loop's channel comparison then fails silently. Sync > phy->chandef from ctx->def in add_chanctx and change_chanctx, and > recompute txpower_cur via a lightweight helper that performs the > same bounded power calculation for the current channel without > reprogramming firmware rate tables. > > Tested on Alfa AWUS036AXML (MT7921AU), kernel 6.19.8, Canada: > > Before: iw dev wlan0 info shows "txpower 3.00 dBm" (wrong) > After: 2.4GHz 36 dBm, 5GHz 23 dBm, 6GHz 12 dBm (match regulatory) > > Cc: stable@vger.kernel.org > Fixes: 1c099ab44727 ("mt76: mt7921: add MAC support") > Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca> > --- > Changes since v3: > - Removed mt7921_set_tx_sar_pwr() from add_chanctx and change_chanctx. > Channel transitions don't change underlying power constraints, so > reprogramming the full rate table is unnecessary. Replaced with a > lightweight helper that recomputes txpower_cur locally. > - Removed IEEE80211_CONF_CHANGE_CHANNEL trigger from config(). > - Removed BSS_CHANGED_TXPOWER handler from bss_info_changed(). Writing > per-vif txpower into per-HW hw->conf.power_level breaks multi-vif > semantics. User txpower limits need a different approach (follow-up). > - Subtracted path delta before storing txpower_cur. The connac rate > loop stores total bounded power, but mt76_get_txpower() adds the > multi-chain path delta when reporting. mt7915 accounts for this via > mt76_get_power_bound(), which subtracts the delta before storing. > Without the same subtraction, reported values were inflated by 3 dBm > on 2x2 devices. > > .../wireless/mediatek/mt76/mt76_connac_mcu.c | 14 +++++++-- > .../net/wireless/mediatek/mt76/mt7921/main.c | 30 +++++++++++++++++++ > 2 files changed, 41 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > index 16db0f208..e26a2cb39 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c > @@ -2193,14 +2193,22 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, > .hw_value = ch_list[idx], > .band = band, > }; > - s8 reg_power, sar_power; > + s8 reg_power, sar_power, max_power; > > reg_power = mt76_connac_get_ch_power(phy, &chan, > tx_power); > sar_power = mt76_get_sar_power(phy, &chan, reg_power); > > - mt76_get_rate_power_limits(phy, &chan, limits, > - sar_power); > + max_power = mt76_get_rate_power_limits(phy, &chan, > + limits, > + sar_power); > + > + if (phy->chandef.chan && > + phy->chandef.chan->hw_value == ch_list[idx] && > + phy->chandef.chan->band == band) > + phy->txpower_cur = max_power - > + mt76_tx_power_path_delta( > + hweight16(phy->chainmask)); > > tx_power_tlv.last_msg = ch_list[idx] == last_ch; > sku_tlbv.channel = ch_list[idx]; > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c > index 5881040ac..a77ae5791 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c > @@ -1355,13 +1355,39 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, > mt792x_mutex_release(dev); > } > > +static void mt7921_update_txpower_cur(struct mt76_phy *phy) > +{ > + struct mt76_power_limits limits; > + struct ieee80211_channel *chan = phy->chandef.chan; > + int n_chains = hweight16(phy->chainmask); > + s8 reg_power, sar_power, max_power; > + int tx_power; > + > + if (!chan) > + return; > + > + tx_power = 2 * phy->hw->conf.power_level; > + if (!tx_power) > + tx_power = 127; > + > + reg_power = mt76_connac_get_ch_power(phy, chan, tx_power); > + sar_power = mt76_get_sar_power(phy, chan, reg_power); > + max_power = mt76_get_rate_power_limits(phy, chan, &limits, sar_power); > + > + phy->txpower_cur = max_power - mt76_tx_power_path_delta(n_chains); > +} > + > static int > mt7921_add_chanctx(struct ieee80211_hw *hw, > struct ieee80211_chanctx_conf *ctx) > { > struct mt792x_dev *dev = mt792x_hw_dev(hw); > + struct mt76_phy *mphy = hw->priv; > > dev->new_ctx = ctx; > + mphy->chandef = ctx->def; > + mt7921_update_txpower_cur(mphy); > + I don't think this is the right fix. This mixes multiple things in one patch and duplicates the same power limit calculation in shared connac code and mt7921-specific code. The issue is in txpower reporting. A channel context is just a view of the current PHY configuration and should not be used to overwrite PHY state. I think this needs to be reworked in a cleaner way, with the shared logic kept in shared code and the reporting side fixed in the common mt792x path so it can apply cleanly to both mt7921 and mt7925. Given the points above, I'd prefer not to keep iterating on the current approach for v5. I'll try to rework this along the lines above and send an updated version. > return 0; > } > > @@ -1396,6 +1422,10 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, > mt7921_mcu_config_sniffer(mvif, ctx); > else > mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->bss_conf.mt76, ctx); > + > + phy->mt76->chandef = ctx->def; > + mt7921_update_txpower_cur(phy->mt76); > + > mt792x_mutex_release(phy->dev); > } > > -- > 2.53.0 > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] wifi: mt76: mt7921: fix txpower reporting 2026-01-25 22:22 [PATCH] wifi: mt76: connac: fix txpower_cur not being updated Lucid Duck ` (2 preceding siblings ...) 2026-01-30 21:54 ` [PATCH v2] wifi: mt76: mt7921: fix txpower reporting Lucid Duck @ 2026-01-30 21:58 ` Lucid Duck 3 siblings, 0 replies; 19+ messages in thread From: Lucid Duck @ 2026-01-30 21:58 UTC (permalink / raw) To: nbd; +Cc: lorenzo, linux-wireless, Lucid Duck On Tue, 27 Jan 2026, Felix Fietkau wrote: > phy->hw->conf.power_level is the user configured power level, not what > the hardware is capable of transmitting. > > To fix it properly, I think you should determine the maximum rate power > used in the loop within mt76_connac_mcu_rate_txpower_band (updated with > each call). Thanks for the feedback, Felix. I looked into tracking the max rate power in mt76_connac_mcu_rate_txpower_band() as you suggested. However, I found that this function is only called from mt7921_set_sar_specs() during SAR configuration changes - it's not in the normal connection code path when a user associates with an AP. As an alternative, this patch updates txpower_cur in mt7921_bss_info_changed() when BSS_CHANGED_TXPOWER is set. It uses info->txpower from bss_conf as the primary source, with a fallback to chan->max_reg_power for cases where bss_conf.txpower isn't populated (which can happen on newer kernels). If I've misunderstood your suggestion or there's a better approach, I'd be happy to revise. Background: I originally started debugging this driver because hcxdumptool was crashing repeatedly on my new Alfa AWUS036AXML adapter. The crashes appeared related to the bogus txpower values being reported (3 dBm or 67 dBm). After applying this patch, hcxdumptool runs without crashing and txpower values are reported correctly. Test Results: Tested on Alfa AWUS036AXML (MT7921AU), kernel 6.18.6: Test Expected Actual Status -------------- ---------- ---------- ------ 2.4GHz ch1 ~33 dBm 33.00 dBm PASS 5GHz ch100 ~27 dBm 27.00 dBm PASS 6GHz ch5 ~15 dBm 15.00 dBm PASS Band switching Updates Correct PASS Consistency Stable 5/5 PASS hcxdumptool No crash 8927 pkts PASS Regulatory baseline (Canada): - 2.4GHz: 30 dBm limit + 3 dBm path delta = 33 dBm reported - 5GHz DFS: 24 dBm limit + 3 dBm path delta = 27 dBm reported - 6GHz: 12 dBm limit + 3 dBm path delta = 15 dBm reported Before patch: $ iw dev wlan0 info | grep txpower txpower 3.00 dBm # bogus value After patch: $ iw dev wlan0 info | grep txpower txpower 33.00 dBm # matches regulatory limit Lucid ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-03-21 8:58 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-01-25 22:22 [PATCH] wifi: mt76: connac: fix txpower_cur not being updated Lucid Duck 2026-01-27 1:59 ` Nick 2026-01-27 12:21 ` Felix Fietkau 2026-01-27 16:17 ` Bitterblue Smith 2026-01-27 17:00 ` Felix Fietkau 2026-01-30 21:54 ` [PATCH v2] wifi: mt76: mt7921: fix txpower reporting Lucid Duck 2026-02-10 3:02 ` Nick 2026-02-12 2:46 ` Lucid Duck 2026-03-09 21:50 ` Lucid Duck 2026-03-12 6:38 ` Sean Wang 2026-03-17 17:30 ` [PATCH v3 0/1] wifi: mt76: mt7921: fix txpower reporting from rate power configuration Lucid Duck 2026-03-17 17:30 ` [PATCH v3 1/1] " Lucid Duck 2026-03-17 21:51 ` Lucid Duck 2026-03-19 6:00 ` Sean Wang 2026-03-19 20:38 ` [PATCH v4] " Lucid Duck 2026-03-20 1:17 ` Lucid Duck 2026-03-20 6:34 ` Greg KH 2026-03-21 8:58 ` Sean Wang 2026-01-30 21:58 ` [PATCH v2] wifi: mt76: mt7921: fix txpower reporting Lucid Duck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox