Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH rtw-next] wifi: rtw88: Ignore TX report sequence number from the 8051 chips
From: Bitterblue Smith @ 2026-02-13 23:23 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org
In-Reply-To: <f9652882eeb042f89463e0fa864f1412@realtek.com>

On 11/02/2026 04:03, Ping-Ke Shih wrote:
> 
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> On 10/02/2026 08:44, Ping-Ke Shih wrote:
>>> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>>>> On 09/02/2026 10:19, Ping-Ke Shih wrote:
>>>>> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>>>>>> When connected to a network in the 2.4 GHz band, wpa_supplicant (or
>>>>>> NetworkManager?) triggers a scan every five minutes. During these scans
>>>>>> mac80211 transmits many QoS Null frames in quick succession. Because
>>>>>> these frames are marked with IEEE80211_TX_CTL_REQ_TX_STATUS, rtw88
>>>>>> asks the firmware to report the TX ACK status for each of these frames.
>>>>>> Sometimes the firmware can't process the TX status requests quickly
>>>>>> enough, they add up, it only processes some of them, and then marks
>>>>>> every subsequent TX status report with the wrong number.
>>>>>
>>>>> Does it mean number of reports is correct? But with incorrect sequence number?
>>>>> Then, you just ignore checking 'sn' but assume 'st' is correct.
>>>>>
>>>>
>>>> The number of reports is correct most of the time. Only when the firmware
>>>> is overwhelmed (?) it doesn't provide every report, but later it recovers.
>>>>
>>>
>>> I was not aware that this happened while scanning, so we might apply this loose
>>> checking under scan condition -- test_bit(RTW_FLAG_SCANNING, rtwdev->flags)"?
>>> If TX report is because of re-key, it can still use original rule.
>>>
>>> [...]
>>>
>>
>> We can't do that because the sequence number is permanently messed up.
> 
> Indeed...
> 
>>
>> I thought about ignoring IEEE80211_TX_CTL_REQ_TX_STATUS on null frames
>> sent during scans, but unfortunately the last 2 or 3 QOS Null frames
>> are sent after RTW_FLAG_SCANNING is unset, and they still trigger the
>> problem.
>>
>> While poking around today I noticed that only non-QOS null frames are
>> treated like management frames. QOS null frames are treated like data
>> frames. So I tried this change:
>>
>> diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
>> index 783975acdcff..ea83daa9d60d 100644
>> --- a/drivers/net/wireless/realtek/rtw88/tx.c
>> +++ b/drivers/net/wireless/realtek/rtw88/tx.c
>> @@ -424,7 +424,7 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
>>                 pkt_info->mac_id = rtwvif->mac_id;
>>         }
>>
>> -       if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc))
>> +       if (ieee80211_is_mgmt(fc) || ieee80211_is_any_nullfunc(fc))
>>                 rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, sta, skb);
>>         else if (ieee80211_is_data(fc))
>>                 rtw_tx_data_pkt_info_update(rtwdev, pkt_info, sta, skb);
>>
>> With this I can't trigger the problem anymore. The sequence numbers
>> are normal every time. Well, it's too soon to be sure, so I will keep
>> testing for a few days.
> 
> Good finding. Please keep testing it.
> 

Still no problem two days later.

> FYI. Having the lunar New Year next week, I will not reply your mail soon.
> 

Have a good holiday!

>>
>>>>
>>>>>>
>>>>>> The symptom is that after a while the warning "failed to get tx report
>>>>>> from firmware" appears every five minutes.
>>>>>>
>>>>>> This problem apparently happens only with the older RTL8723D, RTL8821A,
>>>>>> RTL8812A, and probably RTL8703B chips. Ignore the TX report sequence
>>>>>> number reported by these chips and match the reports with the requests
>>>>>> in the order they come in.
>>>>>>
>>>>>> Tested with RTL8821AU and RTL8723DU.
>>>>>>
>>>>>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>>>>>> ---
>>>>>>  drivers/net/wireless/realtek/rtw88/tx.c | 2 +-
>>>>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
>>>>>> index c04ff31d0f1e..98215ecc884a 100644
>>>>>> --- a/drivers/net/wireless/realtek/rtw88/tx.c
>>>>>> +++ b/drivers/net/wireless/realtek/rtw88/tx.c
>>>>>> @@ -248,7 +248,7 @@ void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src)
>>>>>>         spin_lock_irqsave(&tx_report->q_lock, flags);
>>>>>>         skb_queue_walk_safe(&tx_report->queue, cur, tmp) {
>>>>>>                 n = (u8 *)IEEE80211_SKB_CB(cur)->status.status_driver_data;
>>>>>> -               if (*n == sn) {
>>>>>> +               if (*n == sn || rtw_chip_wcpu_8051(rtwdev)) {
>>>>>
>>>>> Can we only limit to USB devices (or non-PCI devices)?
>>>>>
>>>>
>>>> I don't think so. RTL8821AE also has this problem. I didn't mention it
>>>> in the commit message because support for RTL8821AE in rtw88 is
>>>> unofficial. (I modified rtw88_pci to handle the older generation, see
>>>> the use_new_trx_flow=false code path in rtlwifi.)
>>>
>>> How about official RTL8723DE?
>>>
>>
>> I don't have RTL8723DE. I can try with RTL8723DS, although it's annoying
>> to use. (The host is some kind of single board computer. It has only a
>> serial interface and when I connect that to my laptop it makes the
>> touchpad slow for some reason.)
> 
> I found a RTL8723DE and tested scan during connection over 10 times
> (with local modification to print TX-sn/RX-sn).
> I'd say RTL8723DE doesn't have this problem.
> 

It can take hours, although with RTL8821AE it happens in just a few
minutes.

>>
>>>>
>>>>>>                         __skb_unlink(cur, &tx_report->queue);
>>>>>>                         rtw_tx_report_tx_status(rtwdev, cur, st == 0);
>>>>>>                         break;
>>>>>> --
>>>>>> 2.52.0
>>>>>
>>>
> 


^ permalink raw reply

* Re: wifi: mac80211: question about 20/40 coex support
From: Alex Gavin @ 2026-02-13 22:01 UTC (permalink / raw)
  To: Alexander Wilhelm; +Cc: Johannes Berg, linux-wireless, linux-kernel
In-Reply-To: <61276f01-5fdb-48d9-8c5a-cc3a765bb642@icloud.com>

On 2/13/26 13:44, Alex Gavin wrote:
> On 2/13/26 01:46, Alexander Wilhelm wrote:
>> On Fri, Feb 13, 2026 at 12:14:16AM -0800, Alex Gavin wrote:
>>> On 2/12/26 23:05, Alexander Wilhelm wrote:
>>>>
>>>> Hello wireless devs,
>>>>
>>>> I am analyzing a wireless management frame taken from the beacon of an
>>>> access point, and in this frame the `20/40 Coexistence Management Support`
>>>> bit is set to 0, indicating that the feature is not supported. See frame
>>>> below:
>>>>
>>>>     Frame 2: 217 bytes on wire (1736 bits), 217 bytes captured (1736 bits)
>>>>     Radiotap Header v0, Length 26
>>>>     802.11 radio information
>>>>     IEEE 802.11 Beacon frame, Flags: ........
>>>>     IEEE 802.11 Wireless Management
>>>>         Fixed parameters (12 bytes)
>>>>         Tagged parameters (155 bytes)
>>>>             Tag: SSID parameter set: "SSID"
>>>>             Tag: Supported Rates 6(B), 9, 12(B), 18, 24(B), 36, 48, 54, [Mbit/sec]
>>>>             Tag: DS Parameter set: Current Channel: 6
>>>>             Tag: Traffic Indication Map (TIM): DTIM 0 of 2 bitmap
>>>>             Tag: Country Information: Country Code DE, Environment All
>>>>             Tag: ERP Information
>>>>             Tag: QBSS Load Element 802.11e CCA Version
>>>>             Tag: Supported Operating Classes
>>>>             Tag: HT Capabilities (802.11n D1.10)
>>>>             Tag: HT Information (802.11n D1.10)
>>>>             Tag: Extended Capabilities (10 octets)
>>>>                 Tag Number: Extended Capabilities (127)
>>>>                 Tag length: 10
>>>>                 Extended Capabilities: 0x04 (octet 1)
>>>>                     .... ...0 = 20/40 BSS Coexistence Management Support: Not supported
>>>>                     .... ..0. = General Link (GLK): 0x0
>>>>                     .... .1.. = Extended Channel Switching: Supported
>>>>                     .... 0... = GLK-GCR: 0x0
>>>>                     ...0 .... = PSMP Capability: Not supported
>>>>                     ..0. .... = Reserved: 0x0
>>>>                     .0.. .... = S-PSMP Support: Not supported
>>>>                     0... .... = Event: Not supported
>>>>                 Extended Capabilities: 0x00 (octet 2)
>>>>                 Extended Capabilities: 0x00 (octet 3)
>>>>                 Extended Capabilities: 0x02 (octet 4)
>>>>                 Extended Capabilities: 0x00 (octet 5)
>>>>                 Extended Capabilities: 0x00 (octet 6)
>>>>                 Extended Capabilities: 0x01 (octet 7)
>>>>                 Extended Capabilities: 0x0040 (octets 8 & 9)
>>>>                 Extended Capabilities: 0x40 (octet 10)
>>>>             Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element
>>>>
>>>> I reviewed several driver implementations, and none of them seem to
>>>> advertise this capability. I also could not find any definition for this
>>>> bit in `include/linux/ieee80211.h`, unlike many other capability bits that
>>>> are defined (e.g. `WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING` or
>>>> `WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT`). From what I can see, none of the
>>>> `mac80211`‑based drivers appear to support this feature, is that correct?
>>>>
>>>> Additionally, I want to confirm whether my understanding of the feature is
>>>> accurate: the 20/40 Coexistence mechanism implements the “good neighbor”
>>>> policy, meaning that an AP using a 40 MHz channel in the 2.4 GHz band must
>>>> fall back to 20 MHz when it detects an overlapping BSS (OBSS). Is that
>>>> right?
>>>>
>>>> Any clarification would be greatly appreciated.
>>>>
>>>>
>>>> Best regards
>>>> Alexander Wilhelm
>>>>
>>>
>>> From my understanding, this is implemented in userspace (i.e. hostapd), at least in upstream code.
>>
>> I've alredy seen the code in `hostapd` that implements a fallback to 20
>> MHz. But that implementation is based only on scan results, not on 20/40
>> coexistence feautre. Here the snippet from `ieee80211n_check_scan`
>> function:
>>
>>     [...]
>>     if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
>>             oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
>>     else
>>             oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
>>     wpa_scan_results_free(scan_res);
>>
>>     iface->secondary_ch = iface->conf->secondary_channel;
>>     if (!oper40) {
>>             wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
>>                        "channel pri=%d sec=%d based on overlapping BSSes",
>>                        iface->conf->channel,
>>                        iface->conf->channel +
>>                        iface->conf->secondary_channel * 4);
>>             iface->conf->secondary_channel = 0;
>>             if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
>>                     /*
>>                      * TODO: Could consider scheduling another scan to check
>>                      * if channel width can be changed if no coex reports
>>                      * are received from associating stations.
>>                      */
>>             }
>>     }
>>     [...]
> 
> There are ways the BSS can switch from 40 MHz to 20 MHz operation beyond just scan results.
> 
> For example, a newly-associated, 40 MHz intolerant station could cause hostapd to reconfigure to 20
> MHz operation, assuming the WPA_DRIVER_FLAGS_HT_2040_COEX is set by radio driver capabilities.
> 
> Directly handling association:
> 
> handle_assoc()
> -> update_ht_state()
> -> update_sta_ht()
> -> ht40_intolerant_add()
> -> ieee802_11_set_beacons()
> -> ieee802_11_set_beacon()
> -> __ieee802_11_set_beacon()
> -> ieee802_11_build_ap_params()
> -> hostapd_build_ap_extra_ies()
> -> hostapd_eid_ext_capab()
> -> hostapd_ext_capab_byte()
> 
> 
> Or from driver callback:
> 
> hostapd_notif_assoc()
> -> ht40_intolerant_add()
> -> ieee802_11_set_beacons()
> ...
> -> hostapd_ext_capab_byte()
> 
> 
> Additionally, receipt of a 20/40 MHz Coex Management Action frame in 'hostapd_2040_coex_action()'
> may trigger the AP to reconfigure to 20 MHz using a similar code path.
> 
> For testing, wpa_supplicant supports configuring 40 MHz intolerant stations. See below from its
> config file reference [1]:
> 
> # ht40_intolerant: Whether 40 MHz intolerant should be indicated.
> # 0 = 40 MHz tolerant (default)
> # 1 = 40 MHz intolerant
> 
> I've uploaded some example hostapd and wpa_supplicant configs here [2], if you'd like something to
> reference or play around with. Associating the intolerant station config should trigger hostapd to
> switch from 40 MHz to 20 MHz with this configuration, assuming radio driver support as mentioned above.
> 
> [1] https://git.w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf
> [2] https://codeberg.org/a-gavin/hostap-confs/src/branch/main/open/20-40MHz-bss-coexistence

Since you mentioned packet capture analysis, to observe a 40 MHz BSS switch to 20 MHz operation, pay
close attention to the HT Operation IE in the Beacon frames.

Assuming you're using Wireshark, you should see the 'HT Operation Information Subset (1 of 3)'
section switch from showing 'Supported channel width: Channel of any width supported' to '20 MHz
channel width only'. I'm sure other programs are similar.

Using the 40 MHz intolerant association example, you should see this switch immediately after
station association.


40 MHz operation:

Tag: HT Operation
    Tag Number: HT Operation (61)
    Tag length: 22
    Primary Channel: 1
    HT Operation Information Subset (1 of 3): 0x05
        .... ..01 = Secondary channel offset: Secondary channel is above the primary channel (0x1)
        .... .1.. = Supported channel width: Channel of any width supported
        .... 0... = Reduced Interframe Spacing (RIFS): Prohibited
        0000 .... = Reserved: 0x0
    HT Operation Information Subset (2 of 3): 0x0000
    HT Operation Information Subset (3 of 3): 0x0000
    Rx Supported Modulation and Coding Scheme Set: Basic MCS Set


20 MHz operation:

Tag: HT Operation
    Tag Number: HT Operation (61)
    Tag length: 22
    Primary Channel: 1
    HT Operation Information Subset (1 of 3): 0x00
        .... ..00 = Secondary channel offset: No secondary channel (0x0)
        .... .0.. = Supported channel width: 20 MHz channel width only
        .... 0... = Reduced Interframe Spacing (RIFS): Prohibited
        0000 .... = Reserved: 0x0
    HT Operation Information Subset (2 of 3): 0x0000
    HT Operation Information Subset (3 of 3): 0x0000
    Basic HT-MCS Set: Reserved: 00000000000000000000000000000000


Hope this helps!

>>> In hostapd, the '20/40 BSS Coexistence Management Support' bit you reference is set in the
>>> 'hostapd_ext_capab_byte()' function in 'src/ap/ieee802_11_shared.c' when 'obss_interval' is set in
>>> the AP config file.
>>>
>>> For more information on the 'obss_interval' config item see the following from the hostapd config
>>> reference here [1]:
>>>
>>> # If set non-zero, require stations to perform scans of overlapping
>>> # channels to test for stations which would be affected by 40 MHz traffic.
>>> # This parameter sets the interval in seconds between these scans. Setting this
>>> # to non-zero allows 2.4 GHz band AP to move dynamically to a 40 MHz channel if
>>> # no co-existence issues with neighboring devices are found.
>>> #obss_interval=0
>>
>> Great, I found the the configuration in my `hostapd` version and the code
>> that implements the handling of this kind of management frames. I'll give
>> the configuration option a try.
>>
>>> The following sections from the 802.11 standard may be helpful to understand this topic in more
>>> depth, although I'm sure there's information online that may be easier to digest:
>>>
>>> - 9.4.2.58 20/40 BSS Coexistence element
>>> - 9.4.2.54.2 HT Capability Information field
>>> - 11.15.12 Switching between 40 MHz and 20 MHz
>>>
>>> From 11.15.12:
>>>
>>> TE-B: On any of the channels of the channel set defined in Clause 18, reception of a 20/40 BSS
>>> Coexistence Management, Beacon, Probe Request, or Probe Response frame that contains a value of 1 in
>>> a Forty MHz Intolerant field and that has the Address 1 field equal to the receiving STA’s address
>>> or to a group address, with no further addressing qualifications.
>>
>> Thank you for the support, Alex. The information helps me a lot.
>>
>>
>> Best regards
>> Alexander Wilhelm
> 
> 


^ permalink raw reply

* Re: wifi: mac80211: question about 20/40 coex support
From: Alex Gavin @ 2026-02-13 21:44 UTC (permalink / raw)
  To: Alexander Wilhelm; +Cc: Johannes Berg, linux-wireless, linux-kernel
In-Reply-To: <aY7y84VZW465W_zr@FUE-ALEWI-WINX>

On 2/13/26 01:46, Alexander Wilhelm wrote:
> On Fri, Feb 13, 2026 at 12:14:16AM -0800, Alex Gavin wrote:
>> On 2/12/26 23:05, Alexander Wilhelm wrote:
>>>
>>> Hello wireless devs,
>>>
>>> I am analyzing a wireless management frame taken from the beacon of an
>>> access point, and in this frame the `20/40 Coexistence Management Support`
>>> bit is set to 0, indicating that the feature is not supported. See frame
>>> below:
>>>
>>>     Frame 2: 217 bytes on wire (1736 bits), 217 bytes captured (1736 bits)
>>>     Radiotap Header v0, Length 26
>>>     802.11 radio information
>>>     IEEE 802.11 Beacon frame, Flags: ........
>>>     IEEE 802.11 Wireless Management
>>>         Fixed parameters (12 bytes)
>>>         Tagged parameters (155 bytes)
>>>             Tag: SSID parameter set: "SSID"
>>>             Tag: Supported Rates 6(B), 9, 12(B), 18, 24(B), 36, 48, 54, [Mbit/sec]
>>>             Tag: DS Parameter set: Current Channel: 6
>>>             Tag: Traffic Indication Map (TIM): DTIM 0 of 2 bitmap
>>>             Tag: Country Information: Country Code DE, Environment All
>>>             Tag: ERP Information
>>>             Tag: QBSS Load Element 802.11e CCA Version
>>>             Tag: Supported Operating Classes
>>>             Tag: HT Capabilities (802.11n D1.10)
>>>             Tag: HT Information (802.11n D1.10)
>>>             Tag: Extended Capabilities (10 octets)
>>>                 Tag Number: Extended Capabilities (127)
>>>                 Tag length: 10
>>>                 Extended Capabilities: 0x04 (octet 1)
>>>                     .... ...0 = 20/40 BSS Coexistence Management Support: Not supported
>>>                     .... ..0. = General Link (GLK): 0x0
>>>                     .... .1.. = Extended Channel Switching: Supported
>>>                     .... 0... = GLK-GCR: 0x0
>>>                     ...0 .... = PSMP Capability: Not supported
>>>                     ..0. .... = Reserved: 0x0
>>>                     .0.. .... = S-PSMP Support: Not supported
>>>                     0... .... = Event: Not supported
>>>                 Extended Capabilities: 0x00 (octet 2)
>>>                 Extended Capabilities: 0x00 (octet 3)
>>>                 Extended Capabilities: 0x02 (octet 4)
>>>                 Extended Capabilities: 0x00 (octet 5)
>>>                 Extended Capabilities: 0x00 (octet 6)
>>>                 Extended Capabilities: 0x01 (octet 7)
>>>                 Extended Capabilities: 0x0040 (octets 8 & 9)
>>>                 Extended Capabilities: 0x40 (octet 10)
>>>             Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element
>>>
>>> I reviewed several driver implementations, and none of them seem to
>>> advertise this capability. I also could not find any definition for this
>>> bit in `include/linux/ieee80211.h`, unlike many other capability bits that
>>> are defined (e.g. `WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING` or
>>> `WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT`). From what I can see, none of the
>>> `mac80211`‑based drivers appear to support this feature, is that correct?
>>>
>>> Additionally, I want to confirm whether my understanding of the feature is
>>> accurate: the 20/40 Coexistence mechanism implements the “good neighbor”
>>> policy, meaning that an AP using a 40 MHz channel in the 2.4 GHz band must
>>> fall back to 20 MHz when it detects an overlapping BSS (OBSS). Is that
>>> right?
>>>
>>> Any clarification would be greatly appreciated.
>>>
>>>
>>> Best regards
>>> Alexander Wilhelm
>>>
>>
>> From my understanding, this is implemented in userspace (i.e. hostapd), at least in upstream code.
> 
> I've alredy seen the code in `hostapd` that implements a fallback to 20
> MHz. But that implementation is based only on scan results, not on 20/40
> coexistence feautre. Here the snippet from `ieee80211n_check_scan`
> function:
> 
>     [...]
>     if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
>             oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
>     else
>             oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
>     wpa_scan_results_free(scan_res);
> 
>     iface->secondary_ch = iface->conf->secondary_channel;
>     if (!oper40) {
>             wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
>                        "channel pri=%d sec=%d based on overlapping BSSes",
>                        iface->conf->channel,
>                        iface->conf->channel +
>                        iface->conf->secondary_channel * 4);
>             iface->conf->secondary_channel = 0;
>             if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
>                     /*
>                      * TODO: Could consider scheduling another scan to check
>                      * if channel width can be changed if no coex reports
>                      * are received from associating stations.
>                      */
>             }
>     }
>     [...]

There are ways the BSS can switch from 40 MHz to 20 MHz operation beyond just scan results.

For example, a newly-associated, 40 MHz intolerant station could cause hostapd to reconfigure to 20
MHz operation, assuming the WPA_DRIVER_FLAGS_HT_2040_COEX is set by radio driver capabilities.

Directly handling association:

handle_assoc()
-> update_ht_state()
-> update_sta_ht()
-> ht40_intolerant_add()
-> ieee802_11_set_beacons()
-> ieee802_11_set_beacon()
-> __ieee802_11_set_beacon()
-> ieee802_11_build_ap_params()
-> hostapd_build_ap_extra_ies()
-> hostapd_eid_ext_capab()
-> hostapd_ext_capab_byte()


Or from driver callback:

hostapd_notif_assoc()
-> ht40_intolerant_add()
-> ieee802_11_set_beacons()
...
-> hostapd_ext_capab_byte()


Additionally, receipt of a 20/40 MHz Coex Management Action frame in 'hostapd_2040_coex_action()'
may trigger the AP to reconfigure to 20 MHz using a similar code path.

For testing, wpa_supplicant supports configuring 40 MHz intolerant stations. See below from its
config file reference [1]:

# ht40_intolerant: Whether 40 MHz intolerant should be indicated.
# 0 = 40 MHz tolerant (default)
# 1 = 40 MHz intolerant

I've uploaded some example hostapd and wpa_supplicant configs here [2], if you'd like something to
reference or play around with. Associating the intolerant station config should trigger hostapd to
switch from 40 MHz to 20 MHz with this configuration, assuming radio driver support as mentioned above.

[1] https://git.w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf
[2] https://codeberg.org/a-gavin/hostap-confs/src/branch/main/open/20-40MHz-bss-coexistence

>> In hostapd, the '20/40 BSS Coexistence Management Support' bit you reference is set in the
>> 'hostapd_ext_capab_byte()' function in 'src/ap/ieee802_11_shared.c' when 'obss_interval' is set in
>> the AP config file.
>>
>> For more information on the 'obss_interval' config item see the following from the hostapd config
>> reference here [1]:
>>
>> # If set non-zero, require stations to perform scans of overlapping
>> # channels to test for stations which would be affected by 40 MHz traffic.
>> # This parameter sets the interval in seconds between these scans. Setting this
>> # to non-zero allows 2.4 GHz band AP to move dynamically to a 40 MHz channel if
>> # no co-existence issues with neighboring devices are found.
>> #obss_interval=0
> 
> Great, I found the the configuration in my `hostapd` version and the code
> that implements the handling of this kind of management frames. I'll give
> the configuration option a try.
> 
>> The following sections from the 802.11 standard may be helpful to understand this topic in more
>> depth, although I'm sure there's information online that may be easier to digest:
>>
>> - 9.4.2.58 20/40 BSS Coexistence element
>> - 9.4.2.54.2 HT Capability Information field
>> - 11.15.12 Switching between 40 MHz and 20 MHz
>>
>> From 11.15.12:
>>
>> TE-B: On any of the channels of the channel set defined in Clause 18, reception of a 20/40 BSS
>> Coexistence Management, Beacon, Probe Request, or Probe Response frame that contains a value of 1 in
>> a Forty MHz Intolerant field and that has the Address 1 field equal to the receiving STA’s address
>> or to a group address, with no further addressing qualifications.
> 
> Thank you for the support, Alex. The information helps me a lot.
> 
> 
> Best regards
> Alexander Wilhelm


^ permalink raw reply

* Subject: [Call for Testers] Modern rtw88 port for RTL8723BS (SDIO)
From: Luka Gejak @ 2026-02-13 17:06 UTC (permalink / raw)
  To: linux-wireless; +Cc: kvalo, pkshih, lukagejak5

Hi everyone,

I have been working on a standalone, out-of-tree port of the rtw88 driver specifically for the RTL8723BS (SDIO) chipset. As many of you know, the RTL8723BS is still technically in the "staging" directory in the mainline kernel (rtl8723bs). My goal was to bring this hardware into the modern mac80211 framework by backporting the rtw88 core and implementing the 8723B-specific PHY logic.

What’s implemented:

Full integration with the rtw88 core framework.
PHY/Calibration: Implemented IQK calibration and thermal-based TX power tracking.
Build System: Clean, standalone Makefile that supports automated KDIR detection.
Validation: Code passes make C=1 (Sparse) and includes a basic validation script.

The Catch:
I do not currently have the physical hardware (RTL8723BS) to perform a "live" test. I am looking for volunteers who have devices using this chip (common in Intel Atom tablets/sticks) to see if the modules load and can successfully scan/associate with APs.

Repository:
https://github.com/MocLG/rtw88-rtl8723bs

How to help:

Clone the repo and run make. Follow the loading order in the README. Share your dmesg | grep rtw88 output in the GitHub Issues.
I'd appreciate any feedback on stability or range compared to the legacy staging driver!

Signed-off-by: Luka Gejak luka.gejak@linux.dev

^ permalink raw reply

* Re: Receiving broadcast data frames in AP mode
From: Yannik Marchand @ 2026-02-13 16:30 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless
In-Reply-To: <c09802fb-bde5-4775-bb24-69f465c638be@me.com>

Update: I have no idea why, but sending all frames to ff:ff:ff:ff:ff:ff 
instead of the MAC address of my Switch seems to have solved the issue. 
It looks like all UDP packets are now being received properly :)

Kind regards,
Yannik Marchand

On 13/02/2026 16:13, Yannik Marchand wrote:
> Hello,
>
> Thank you for these insights. I want to provide a quick status update.
>
> It seems that the protocol is somewhere between ad-hoc and 
> infrastructure mode. When a station joins the network, it must send an 
> authentication and association request to the host of the network, 
> which is similar to infrastructure mode. However, once authenticated, 
> the nodes can communicate directly with each other, which is more like 
> ad-hoc mode. Interestingly, packets from the host seem to have FromDS 
> set, while packets from other nodes in the network have neither FromDS 
> nor ToDS set.
>
> Unfortunately, using an interface in IBSS mode did not work, because 
> none of my hardware supports receiving association requests in IBSS mode.
>
> Later, I learned about WiFi-Direct and P2P. While I initially thought 
> that using a P2P-GO mode interface would make it work, it seems that 
> it suffers from the same issue as AP mode, where broadcast data frames 
> are not received.
>
> Then, I tried implementing the entire protocol in monitor mode. While 
> I have learned a lot, this turned out to be quite hard.
>
> Today, I have finally managed to make it somewhat work. My setup uses 
> three interfaces, which is similar to what you suggested: one in AP 
> mode, one in monitor mode, and a TAP interface. The AP mode interface 
> handles the association and authentication frames. The monitor mode 
> interface handles the data frames. After parsing and decrypting the 
> data frames, the frames are written to the TAP interface, to avoid 
> having to implement L3 as well.
>
> There are still some issues currently. For example, after sending 
> around 12 packets to the Nintendo Switch, the Nintendo Switch seems to 
> stop receiving packets. However, I am happy that I'm getting closer to 
> finding a working solution.
>
> Kind regards,
> Yannik Marchand
>
> On 07/10/2025 11:47, Johannes Berg wrote:
>> Hi,
>>
>>> I have been using nl80211 to implement local wireless communication 
>>> with
>>> a Nintendo Switch device. The current implementation can be found here:
>>> https://github.com/kinnay/LDN.
>>
>> :)
>>
>>> We have run into the issue that we are not receiving any data frames in
>>> AP mode. In station mode it works fine. Inspecting the traffic with
>>> Wireshark in monitor mode showed that the data frames are being sent to
>>> the broadcast address ff:ff:ff:ff:ff:ff. Some research suggested that
>>> the Linux kernel might drop these packets by design:
>>> https://github.com/torvalds/linux/blob/7f7072574127c9e971cad83a0274e86f6275c0d5/net/mac80211/rx.c#L4443. 
>>>
>>
>> Yes, a real AP will never receive broadcast data frames, since it
>> controls the BSS and all traffic flows through it. In fact, hardware or
>> firmware would likely filter them as well, so even removing this check
>> may not address this for all devices.
>>
>>> Currently, we are wondering if it is necessary to switch to adhoc mode.
>>
>> That might not be a bad idea, but then you don't have control over which
>> station is sending beacons - though I guess if you actually have
>> multiple Linux hosts it wouldn't matter so much?
>>
>>> This would be inconvenient, as not all devices support adhoc mode,
>>
>> Not all devices support AP mode either, and see above wrt. filtering, so
>> I think either way you don't have some devices.
>>
>>>   and I
>>> am also not sure how adhoc mode can be used correctly. We do need to
>>> send beacon frames, and process association requests, but
>>> NL80211_CMD_START_AP and NL80211_CMD_SET_BEACON seem to be unsupported
>>> in adhoc mode.
>>
>> I don't know what you need from the beacon - almost sounds like not much
>> - so might not need SET_BEACON rather than JOIN_IBSS. Managing stations
>> from userspace is supported for secure IBSS though, wpa_s implements
>> that.
>>
>>> * Is it correct that there is no way to receive broadcast data 
>>> frames in
>>> AP mode?
>>
>> Well, we could hack out the check, but it wouldn't necessarily fix the
>> issue. So I'd say generally, the answer is yes.
>>
>>> * Is there any documentation or example code on using adhoc mode with
>>> nl80211?
>>
>> Only whatever is in wpa_supplicant for secure IBSS. I don't think the
>> 'secure' part is really a requirement, but it's been ages.
>>
>>> * Any general advice on moving forward?
>>
>> In the past you could maybe have used 'cooked monitor' but we removed
>> that, so now I guess the best you could do in AP mode is to add a
>> monitor interface (you already say that's how some frames are
>> transmitted, though that doesn't actually seem necessary) and listen for
>> the data frames there? If the hardware/firmware actually receives them,
>> you should be able to see them there. If not, well, then it just can't
>> work in AP mode anyway.
>>
>> (I suspect, for example, that Intel hardware generally won't give you
>> the frames, but I haven't tested it now.)
>>
>>
>> In a way the bigger question is what do the consoles expect from the AP?
>> Do they, for example, go into powersave and expect traffic to be
>> buffered for them? Because in that case IBSS won't work anyway, and it
>> seems a bit hard to imagine they wouldn't...
>>
>> Or could you maybe simply not care and always make one of them the AP,
>> perhaps unless there's no real console anyway, and then you have no
>> powersave expectations on the Linux side from IBSS?
>>
>> johannes
>

^ permalink raw reply

* Re: [PATCH wireless-next v3 2/2] wifi: mac80211_hwsim: Add UHR capabilities to the driver
From: Pablo MARTIN-GOMEZ @ 2026-02-13 14:36 UTC (permalink / raw)
  To: Karthikeyan Kathirvel, johannes; +Cc: linux-wireless, ath12k
In-Reply-To: <20260212180128.257565-3-karthikeyan.kathirvel@oss.qualcomm.com>

Hello,
On 12/02/2026 19:01, Karthikeyan Kathirvel wrote:
> Add UHR capabilities for bringing up the interface in UHR mode.
> This is required to validate UHR test cases.
>
> Signed-off-by: Karthikeyan Kathirvel <karthikeyan.kathirvel@oss.qualcomm.com>
> ---
>   drivers/net/wireless/virtual/mac80211_hwsim.c | 285 ++++++++++++++++++
>   1 file changed, 285 insertions(+)
>
> diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
> index 4d9f5f87e814..5a576bbb7688 100644
> --- a/drivers/net/wireless/virtual/mac80211_hwsim.c
> +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
> @@ -4478,6 +4478,49 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = {
>   			},
>   			/* PPE threshold information is not supported */
>   		},
> +		.uhr_cap = {
> +			.has_uhr = true,
> +			.mac = {
> +				.mac_cap[0] =
> +					IEEE80211_UHR_MAC_CAP0_DPS_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_NPCA_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_ENH_BSR_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_ADD_MAP_TID_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_EOTSP_SUPP,
> +				.mac_cap[1] =
> +					IEEE80211_UHR_MAC_CAP1_DSO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_PEDCA_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_PUO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_DUO_SUPP,
> +				.mac_cap[2] =
> +					IEEE80211_UHR_MAC_CAP2_OMC_UL_MU_DIS_RX_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_AOM_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_IFCS_LOC_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_TXSPG_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_TXOP_RET_IN_TXSPG |
> +					IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW,
> +				.mac_cap[3] =
> +					IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH |
> +					IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV |
> +					IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW,
> +				.mac_cap[4] =
> +					IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH |
> +					IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
> +					IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE |
> +					IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP,
> +			},
> +			.phy = {
> +				.cap =
> +					IEEE80211_UHR_PHY_CAP_ELR_RX |
> +					IEEE80211_UHR_PHY_CAP_ELR_TX,

`IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_LE80` and `IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_LE80` are for 80MHz and lower, it should include 20/40 MHz of 2.4 GHz, no?

> +			},
> +		},
>   	},
>   	{
>   		.types_mask = BIT(NL80211_IFTYPE_AP) |
> @@ -4586,6 +4629,50 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = {
>   			},
>   			/* PPE threshold information is not supported */
>   		},
> +		.uhr_cap = {
> +			.has_uhr = true,
> +			.mac = {
> +				.mac_cap[0] =
> +					IEEE80211_UHR_MAC_CAP0_DPS_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_NPCA_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_ENH_BSR_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_ADD_MAP_TID_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_EOTSP_SUPP,
> +				.mac_cap[1] =
> +					IEEE80211_UHR_MAC_CAP1_DSO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_PEDCA_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_DBE_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_PUO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_DUO_SUPP,
> +				.mac_cap[2] =
> +					IEEE80211_UHR_MAC_CAP2_OMC_UL_MU_DIS_RX_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_AOM_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_IFCS_LOC_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_TXSPG_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_TXOP_RET_IN_TXSPG |
> +					IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW,
> +				.mac_cap[3] =
> +					IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH |
> +					IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV |
> +					IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW,
> +				.mac_cap[4] =
> +					IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH |
> +					IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
> +					IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE |
> +					IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP,
> +			},
> +			.phy = {
> +				.cap =
> +					IEEE80211_UHR_PHY_CAP_ELR_RX |
> +					IEEE80211_UHR_PHY_CAP_ELR_TX,
Same
> +			},
> +		},
>   	},
>   #ifdef CONFIG_MAC80211_MESH
>   	{
> @@ -4755,6 +4842,55 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = {
>   			},
>   			/* PPE threshold information is not supported */
>   		},
> +		.uhr_cap = {
> +			.has_uhr = true,
> +			.mac = {
> +				.mac_cap[0] =
> +					IEEE80211_UHR_MAC_CAP0_DPS_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_NPCA_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_ENH_BSR_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_ADD_MAP_TID_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_EOTSP_SUPP,
> +				.mac_cap[1] =
> +					IEEE80211_UHR_MAC_CAP1_DSO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_PEDCA_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_PUO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_DUO_SUPP,
> +				.mac_cap[2] =
> +					IEEE80211_UHR_MAC_CAP2_OMC_UL_MU_DIS_RX_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_AOM_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_IFCS_LOC_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_TXSPG_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_TXOP_RET_IN_TXSPG |
> +					IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW,
> +				.mac_cap[3] =
> +					IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH |
> +					IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV |
> +					IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW,
> +				.mac_cap[4] =
> +					IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH |
> +					IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
> +					IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE |
> +					IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP,
> +			},
> +			.phy = {
> +				.cap =
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_LE80 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_LE80 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_160 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_160 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_320 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_320 |
I'm not aware of an operating class that allows 320 MHz on 5 GHz (or 
even a non standard use of it), 
`IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_320` and 
`IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_320` should be dropped
> +					IEEE80211_UHR_PHY_CAP_ELR_RX |
> +					IEEE80211_UHR_PHY_CAP_ELR_TX,
> +			},
> +		},
>   	},
>   	{
>   		.types_mask = BIT(NL80211_IFTYPE_AP) |
> @@ -4880,6 +5016,56 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = {
>   			},
>   			/* PPE threshold information is not supported */
>   		},
> +		.uhr_cap = {
> +			.has_uhr = true,
> +			.mac = {
> +				.mac_cap[0] =
> +					IEEE80211_UHR_MAC_CAP0_DPS_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_NPCA_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_ENH_BSR_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_ADD_MAP_TID_SUPP |
> +					IEEE80211_UHR_MAC_CAP0_EOTSP_SUPP,
> +				.mac_cap[1] =
> +					IEEE80211_UHR_MAC_CAP1_DSO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_PEDCA_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_DBE_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_PUO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPP |
> +					IEEE80211_UHR_MAC_CAP1_DUO_SUPP,
> +				.mac_cap[2] =
> +					IEEE80211_UHR_MAC_CAP2_OMC_UL_MU_DIS_RX_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_AOM_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_IFCS_LOC_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_TXSPG_SUPP |
> +					IEEE80211_UHR_MAC_CAP2_TXOP_RET_IN_TXSPG |
> +					IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW,
> +				.mac_cap[3] =
> +					IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH |
> +					IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV |
> +					IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW,
> +				.mac_cap[4] =
> +					IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH |
> +					IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS |
> +					IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE |
> +					IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP,
> +			},
> +			.phy = {
> +				.cap =
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_LE80 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_LE80 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_160 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_160 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_320 |
> +					IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_320 |

Same

[...]

Best regards,

Pablo MG


^ permalink raw reply

* Re: [RFC PATCH 2/2] wifi: ath10k: only wait for response to SET_KEY
From: James Prestwood @ 2026-02-13 14:00 UTC (permalink / raw)
  To: Jeff Johnson, Richard Acayan, linux-wireless, ath10k,
	Baochen Qiang
In-Reply-To: <3e1274fd-fe95-420c-94e3-ac34f497b7ae@oss.qualcomm.com>

Hi Jeff/Baochen,

On 2/12/26 9:56 AM, Jeff Johnson wrote:
> On 2/11/2026 6:11 PM, James Prestwood wrote:
>> On 2/9/26 6:12 PM, Richard Acayan wrote:
>>> When sending DELETE_KEY, the driver times out waiting for a response
>>> that doesn't come. Only wait for a response when sending SET_KEY.
>> We've run into the exact same thing on the QCA6174 and have been
>> carrying an identical patch to this for at least a year.
>>
>> https://lore.kernel.org/linux-wireless/b2838a23-ea30-4dee-b513-f5471d486af2@gmail.com/
> Baochen,
> Were we ever able to reproduce this?
> Do we normally always get a response to DELETE_KEY but in some instances it
> comes very late (or not at all)?
> If we remove the wait, is there any concern that a late arriving DELETE_KEY
> response might be processed as a response to a subsequent SET_KEY command?

For some added color, we only see this oddly with some vendors of APs, 
primarily "classic" Cisco Aeronet equipment (not Meraki).

Its still a mystery why certain AP vendors are able to trigger this 
given its deleting a key locally on the device. The major issue here is 
on roams when deleting the key from the prior BSS where we time out, 
thereby delaying the roam for 3 seconds. This then causes downstream 
effects like the reassociation timeout expiring on the AP which causes a 
disassociation. With some customers using Cisco its actually happens 
near 100% of the time, killing roaming entirely.

Thanks,

James

>
> /jeff

^ permalink raw reply

* Re: [PATCH wireless-next v8 2/3] wifi: cfg80211: add initial UHR support
From: Johannes Berg @ 2026-02-13 10:26 UTC (permalink / raw)
  To: Harshitha Prem, linux-wireless
  Cc: Karthikeyan Kathirvel, vasanthakumar.thiagarajan,
	Lorenzo Bianconi, ath12k, Jeff Johnson, Ping-Ke Shih
In-Reply-To: <be9ab3c7f05b0f56f19aee0ffc7c2f96138b9a05.camel@sipsolutions.net>

On Fri, 2026-02-13 at 11:11 +0100, Johannes Berg wrote:
> Hi Harshita,
> 
> > > Should we add a separate netlink attribute for the UHR operation, which
> > > hostapd would fill with the _full_ data like it appears in association
> > > response etc.?
> > > 
> > > That way, hostapd doesn't need to build a separate data/attribute
> > > structure but can just use hostapd_eid_uhr_operation(..., false) for it.
> > > 
> > > An alternative would be to add more attributes for everything, but it's
> > > probably more complicated on both sides?
> 
> > Thank you for the suggestions.
> > 
> > We feel that using separate nested attributes for each feature is the better approach, as this allows us to reuse the attributes for the Enhanced BSS Parameter Critical Update procedure, where similar information is carried in the UHR parameters update element.
> 
> Heh, I'll admit I'm surprised - I'm usually the one advocating for
> finer-grained attributes, and here I didn't ;-)

Wait, so I wrote a lot and forgot to circle back to this question ...

Basically I think that it's not going to be useful to split it up. I
have no objections to it, but it complicates the code (especially in
hostapd) quite a bit, because it's going to be either

 1) include each thing (NPCA, DBE, ...) in its own attribute, so that
    e.g. NPCA would be 4 or 6 bytes per spec format, but then we need
    separate validation for each in nl80211

 2) we really break it all down to each individual value, so e.g. NPCA
    would have separate attributes for minimum duration threshold,
    switch and switch back delay, initial QSRC and a MOPLEN flag; this
    is a bit easier to capture in a policy, but a LOT of parameters
    overall.

The thing - and why I wrote so much - is that we basically only need a
single current, and in the case of updates additionally a single post-
update, UHR operation.

So unless we're going to completely design away from beacon templates
and create an API where including the UHR Parameters Update element is
fully the firmware's (or driver's) responsibility across all the
different frame types, then the split isn't really needed. And even if
we _do_ design it completely that way, giving the post-update UHR
operation and comparing to the pre-update one isn't a huge stretch for a
design that just required fully rebuilding all the frames (parsing all
the way into fragmented elements and putting them back together in a
completely new way, including re-fragmenting elements and subelements
etc. which all sounds very messy to me.)

johannes

^ permalink raw reply

* Re: [PATCH wireless-next v8 2/3] wifi: cfg80211: add initial UHR support
From: Johannes Berg @ 2026-02-13 10:11 UTC (permalink / raw)
  To: Harshitha Prem, linux-wireless
  Cc: Karthikeyan Kathirvel, vasanthakumar.thiagarajan,
	Lorenzo Bianconi, ath12k, Jeff Johnson, Ping-Ke Shih
In-Reply-To: <5d54feea-d0cd-4bd7-b0d2-02e42f0fe5e1@oss.qualcomm.com>

Hi Harshita,

> > Should we add a separate netlink attribute for the UHR operation, which
> > hostapd would fill with the _full_ data like it appears in association
> > response etc.?
> > 
> > That way, hostapd doesn't need to build a separate data/attribute
> > structure but can just use hostapd_eid_uhr_operation(..., false) for it.
> > 
> > An alternative would be to add more attributes for everything, but it's
> > probably more complicated on both sides?

> Thank you for the suggestions.
> 
> We feel that using separate nested attributes for each feature is the better approach, as this allows us to reuse the attributes for the Enhanced BSS Parameter Critical Update procedure, where similar information is carried in the UHR parameters update element.

Heh, I'll admit I'm surprised - I'm usually the one advocating for
finer-grained attributes, and here I didn't ;-)

> While this approach is slightly more verbose, we believe it offers better extensibility for the future.

Does it actually, though?

I had sort of expected hostapd to add the UHR Parameters Update element
to the beacons, and configure some way of having firmware set the
countdown ("Countdown Timer"). Turns out this is not only in beacons but
also in probe response, (re)association response and (UHR? [1]) link
reconfiguration response frames.

[1] the spec says "Link Reconfiguration Response" but I think it should
say "UHR Link Reconfiguration Response"

But I guess this is going to end up a continuation of the previous wifi7
discussion from last year [2] which hadn't really completed. And Lorenzo
just posted another thing on this [3].

[2] https://lore.kernel.org/linux-wireless/20250717045540.27208-1-aditya.kumar.singh@oss.qualcomm.com/
[3] https://lore.kernel.org/linux-wireless/20260212-mt7996-link-reconf-v1-0-2b110340d6c4@kernel.org/


So I think maybe we need to figure out how we will do all of this first?

Naively, I would've said ... something stupid. I'm reading the spec as
I'm writing this ;-) The UHR Parameters Update element is actually
included in all the beacons across the entire AP MLD.

Maybe we need to take a step back from our previous discussion as well,
and introduce a broader concept here?


I could imagine, for example, something where you say in the nl80211 API
some variation of

 1) Let's start a new update operation ("NL80211_CMD_START_MLD_BSS_UPDATE"),
    I guess already with some parameters saying:
     - the updated affiliated AP (link)
     - the number of beacon intervals you want to do it for
     - the post-update UHR operation (?)
       (or the new channel if it's CSA? etc.?)

     - maybe - more critical if we use it for CSA - already the beacon
       templates for all the links? with all the things I say in (2)
       below, but that's more complex maybe?

       the reason I say this is that there's a difference here in how
       the counter is done - for CSA etc. the things have to disappear
       from the beacon immediately, for UHR updates they stick around
       and the counter indicates "in the past"

    returning a cookie for the operation.

 2) hostapd updates each link's beacon now including the UHR Parameters
    Update element(s), for each currently ongoing update it includes -
    indexed by the cookie - a list of offsets where the counters are
    updated.

    Thing is that this depends on the operation - CSA will already need
    the post-switch beacon template so the flow can continue without
    involving hostapd, hostapd may however need to update the beacon in
    the interim (both pre- and post-switch ones!) and need to refer
    again to where the counters are filled in ...


Either way, it feels like we've reached the end of where the current
design with CSA and BSS color updates will take us. Lorenzo already gave
up and put the parsing into the driver to find the offsets, but I
personally think that's very inflexible.

Some operations such as link removal may not need to have perfect
timing, but some others like CSA really do want the updates to happen at
the precise moment.

In some way, it's almost good that we haven't completed the WiFi7 part
since the UHR part throws another curveball with the counters
decrementing below zero - for past updates - in a sense.


johannes

^ permalink raw reply

* [PATCH wireless-next v2 2/2] wifi: mac80211: Set link ID for NULL packets sent to probe stations
From: Suraj P Kizhakkethil @ 2026-02-13 10:01 UTC (permalink / raw)
  To: johannes
  Cc: linux-wireless, Suraj P Kizhakkethil, Sriram R,
	Rameshkumar Sundaram
In-Reply-To: <20260213100126.1414398-1-suraj.kizhakkethil@oss.qualcomm.com>

Currently, for AP MLD, the link ID is not provided when a NULL
packet is triggered to probe a station. For non-MLO stations connected
to an AP MLD, use the station's default link to send the NULL packets
and set addr2 and addr3 to the link address. For MLO stations, set the
link ID to unspecified to let the driver select the appropriate link.

Co-developed-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Co-developed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Signed-off-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Signed-off-by: Suraj P Kizhakkethil <suraj.kizhakkethil@oss.qualcomm.com>
---
 net/mac80211/cfg.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 70a210db16cd..36f921fd2176 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4616,7 +4616,9 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
 	struct ieee80211_tx_info *info;
 	struct sta_info *sta;
 	struct ieee80211_chanctx_conf *chanctx_conf;
+	struct ieee80211_bss_conf *conf;
 	enum nl80211_band band;
+	u8 link_id = 0;
 	int ret;
 
 	/* the lock is needed to assign the cookie later */
@@ -4632,6 +4634,23 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
 	qos = sta->sta.wme;
 
 	if (ieee80211_vif_is_mld(&sdata->vif)) {
+		if (sta->sta.mlo) {
+			link_id = IEEE80211_LINK_UNSPECIFIED;
+		} else {
+			/*
+			 * For non-MLO clients connected to an AP MLD, band
+			 * information is not used; instead, sta->deflink is
+			 * used to send packets.
+			 */
+			link_id = sta->deflink.link_id;
+
+			conf = rcu_dereference(sdata->vif.link_conf[link_id]);
+
+			if (unlikely(!conf)) {
+				ret = -ENOLINK;
+				goto unlock;
+			}
+		}
 		/* MLD transmissions must not rely on the band */
 		band = 0;
 	} else {
@@ -4668,8 +4687,13 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
 	nullfunc->frame_control = fc;
 	nullfunc->duration_id = 0;
 	memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
-	memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
-	memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
+	if (ieee80211_vif_is_mld(&sdata->vif) && !sta->sta.mlo) {
+		memcpy(nullfunc->addr2, conf->addr, ETH_ALEN);
+		memcpy(nullfunc->addr3, conf->addr, ETH_ALEN);
+	} else {
+		memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
+		memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
+	}
 	nullfunc->seq_ctrl = 0;
 
 	info = IEEE80211_SKB_CB(skb);
@@ -4678,6 +4702,8 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
 		       IEEE80211_TX_INTFL_NL80211_FRAME_TX;
 	info->band = band;
 
+	info->control.flags |= u32_encode_bits(link_id,
+					       IEEE80211_TX_CTRL_MLO_LINK);
 	skb_set_queue_mapping(skb, IEEE80211_AC_VO);
 	skb->priority = 7;
 	if (qos)
-- 
2.34.1


^ permalink raw reply related

* [PATCH wireless-next v2 1/2] wifi: mac80211: set band information only for non-MLD when probing stations using NULL frame
From: Suraj P Kizhakkethil @ 2026-02-13 10:01 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Suraj P Kizhakkethil
In-Reply-To: <20260213100126.1414398-1-suraj.kizhakkethil@oss.qualcomm.com>

Currently, when sending a NULL frame to probe a station, the band
information is derived from the chanctx_conf in the mac80211 vif's
bss_conf. However, for AP MLD, chanctx_conf is not assigned to the
vif's bss_conf; instead it is assigned on a per-link basis. As a result,
for AP MLD, sending a NULL packet to probe will trigger a warning.

WARNING: net/mac80211/cfg.c:4635 at ieee80211_probe_client+0x1a8/0x1d8 [mac80211], CPU#2: hostapd/244
Call trace:
 ieee80211_probe_client+0x1a8/0x1d8 [mac80211] (P)
 nl80211_probe_client+0xac/0x170 [cfg80211]
 genl_family_rcv_msg_doit+0xc8/0x134
 genl_rcv_msg+0x200/0x280
 netlink_rcv_skb+0x38/0xf0
 genl_rcv+0x34/0x48
 netlink_unicast+0x314/0x3a0
 netlink_sendmsg+0x150/0x390
 ____sys_sendmsg+0x1f4/0x21c
 ___sys_sendmsg+0x98/0xc0
 __sys_sendmsg+0x74/0xcc
 __arm64_sys_sendmsg+0x20/0x34
 invoke_syscall.constprop.0+0x4c/0xd0
 do_el0_svc+0x3c/0xd0
 el0_svc+0x28/0xc0
 el0t_64_sync_handler+0x98/0xdc
 el0t_64_sync+0x154/0x158
---[ end trace 0000000000000000 ]---

For NULL packets sent to probe stations, set the band information only
for non-MLD, since MLD transmissions does not rely on band.

Signed-off-by: Suraj P Kizhakkethil <suraj.kizhakkethil@oss.qualcomm.com>
---
 net/mac80211/cfg.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5d04d7d550b0..70a210db16cd 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4631,12 +4631,17 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
 
 	qos = sta->sta.wme;
 
-	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
-	if (WARN_ON(!chanctx_conf)) {
-		ret = -EINVAL;
-		goto unlock;
+	if (ieee80211_vif_is_mld(&sdata->vif)) {
+		/* MLD transmissions must not rely on the band */
+		band = 0;
+	} else {
+		chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+		if (WARN_ON(!chanctx_conf)) {
+			ret = -EINVAL;
+			goto unlock;
+		}
+		band = chanctx_conf->def.chan->band;
 	}
-	band = chanctx_conf->def.chan->band;
 
 	if (qos) {
 		fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
-- 
2.34.1


^ permalink raw reply related

* [PATCH wireless-next v2 0/2] wifi: mac80211: Fix issues related to sending NULL packets to probe stations
From: Suraj P Kizhakkethil @ 2026-02-13 10:01 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Suraj P Kizhakkethil

This patch series addresses issues observed when sending NULL
packets to probe stations.
---
v2:
 - Modified commit message
 - Refactored the patches according to Johannes's comments
---

Suraj P Kizhakkethil (2):
  wifi: mac80211: set band information only for non-MLD when probing
    stations using NULL frame
  wifi: mac80211: Set link ID for NULL packets sent to probe stations

 net/mac80211/cfg.c | 45 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 38 insertions(+), 7 deletions(-)


base-commit: 333225e1e9ead7b06e5363389403bdac72ba3046
-- 
2.34.1


^ permalink raw reply

* Re: wifi: mac80211: question about 20/40 coex support
From: Alexander Wilhelm @ 2026-02-13  9:46 UTC (permalink / raw)
  To: Alex Gavin; +Cc: Johannes Berg, linux-wireless, linux-kernel
In-Reply-To: <a3fd0a27-f09f-4950-919d-1b4ba2dcb16a@icloud.com>

On Fri, Feb 13, 2026 at 12:14:16AM -0800, Alex Gavin wrote:
> On 2/12/26 23:05, Alexander Wilhelm wrote:
> > 
> > Hello wireless devs,
> > 
> > I am analyzing a wireless management frame taken from the beacon of an
> > access point, and in this frame the `20/40 Coexistence Management Support`
> > bit is set to 0, indicating that the feature is not supported. See frame
> > below:
> > 
> >     Frame 2: 217 bytes on wire (1736 bits), 217 bytes captured (1736 bits)
> >     Radiotap Header v0, Length 26
> >     802.11 radio information
> >     IEEE 802.11 Beacon frame, Flags: ........
> >     IEEE 802.11 Wireless Management
> >         Fixed parameters (12 bytes)
> >         Tagged parameters (155 bytes)
> >             Tag: SSID parameter set: "SSID"
> >             Tag: Supported Rates 6(B), 9, 12(B), 18, 24(B), 36, 48, 54, [Mbit/sec]
> >             Tag: DS Parameter set: Current Channel: 6
> >             Tag: Traffic Indication Map (TIM): DTIM 0 of 2 bitmap
> >             Tag: Country Information: Country Code DE, Environment All
> >             Tag: ERP Information
> >             Tag: QBSS Load Element 802.11e CCA Version
> >             Tag: Supported Operating Classes
> >             Tag: HT Capabilities (802.11n D1.10)
> >             Tag: HT Information (802.11n D1.10)
> >             Tag: Extended Capabilities (10 octets)
> >                 Tag Number: Extended Capabilities (127)
> >                 Tag length: 10
> >                 Extended Capabilities: 0x04 (octet 1)
> >                     .... ...0 = 20/40 BSS Coexistence Management Support: Not supported
> >                     .... ..0. = General Link (GLK): 0x0
> >                     .... .1.. = Extended Channel Switching: Supported
> >                     .... 0... = GLK-GCR: 0x0
> >                     ...0 .... = PSMP Capability: Not supported
> >                     ..0. .... = Reserved: 0x0
> >                     .0.. .... = S-PSMP Support: Not supported
> >                     0... .... = Event: Not supported
> >                 Extended Capabilities: 0x00 (octet 2)
> >                 Extended Capabilities: 0x00 (octet 3)
> >                 Extended Capabilities: 0x02 (octet 4)
> >                 Extended Capabilities: 0x00 (octet 5)
> >                 Extended Capabilities: 0x00 (octet 6)
> >                 Extended Capabilities: 0x01 (octet 7)
> >                 Extended Capabilities: 0x0040 (octets 8 & 9)
> >                 Extended Capabilities: 0x40 (octet 10)
> >             Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element
> > 
> > I reviewed several driver implementations, and none of them seem to
> > advertise this capability. I also could not find any definition for this
> > bit in `include/linux/ieee80211.h`, unlike many other capability bits that
> > are defined (e.g. `WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING` or
> > `WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT`). From what I can see, none of the
> > `mac80211`‑based drivers appear to support this feature, is that correct?
> > 
> > Additionally, I want to confirm whether my understanding of the feature is
> > accurate: the 20/40 Coexistence mechanism implements the “good neighbor”
> > policy, meaning that an AP using a 40 MHz channel in the 2.4 GHz band must
> > fall back to 20 MHz when it detects an overlapping BSS (OBSS). Is that
> > right?
> > 
> > Any clarification would be greatly appreciated.
> > 
> > 
> > Best regards
> > Alexander Wilhelm
> > 
> 
> From my understanding, this is implemented in userspace (i.e. hostapd), at least in upstream code.

I've alredy seen the code in `hostapd` that implements a fallback to 20
MHz. But that implementation is based only on scan results, not on 20/40
coexistence feautre. Here the snippet from `ieee80211n_check_scan`
function:

    [...]
    if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
            oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
    else
            oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
    wpa_scan_results_free(scan_res);

    iface->secondary_ch = iface->conf->secondary_channel;
    if (!oper40) {
            wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
                       "channel pri=%d sec=%d based on overlapping BSSes",
                       iface->conf->channel,
                       iface->conf->channel +
                       iface->conf->secondary_channel * 4);
            iface->conf->secondary_channel = 0;
            if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
                    /*
                     * TODO: Could consider scheduling another scan to check
                     * if channel width can be changed if no coex reports
                     * are received from associating stations.
                     */
            }
    }
    [...]

> In hostapd, the '20/40 BSS Coexistence Management Support' bit you reference is set in the
> 'hostapd_ext_capab_byte()' function in 'src/ap/ieee802_11_shared.c' when 'obss_interval' is set in
> the AP config file.
> 
> For more information on the 'obss_interval' config item see the following from the hostapd config
> reference here [1]:
> 
> # If set non-zero, require stations to perform scans of overlapping
> # channels to test for stations which would be affected by 40 MHz traffic.
> # This parameter sets the interval in seconds between these scans. Setting this
> # to non-zero allows 2.4 GHz band AP to move dynamically to a 40 MHz channel if
> # no co-existence issues with neighboring devices are found.
> #obss_interval=0

Great, I found the the configuration in my `hostapd` version and the code
that implements the handling of this kind of management frames. I'll give
the configuration option a try.

> The following sections from the 802.11 standard may be helpful to understand this topic in more
> depth, although I'm sure there's information online that may be easier to digest:
> 
> - 9.4.2.58 20/40 BSS Coexistence element
> - 9.4.2.54.2 HT Capability Information field
> - 11.15.12 Switching between 40 MHz and 20 MHz
> 
> From 11.15.12:
> 
> TE-B: On any of the channels of the channel set defined in Clause 18, reception of a 20/40 BSS
> Coexistence Management, Beacon, Probe Request, or Probe Response frame that contains a value of 1 in
> a Forty MHz Intolerant field and that has the Address 1 field equal to the receiving STA’s address
> or to a group address, with no further addressing qualifications.

Thank you for the support, Alex. The information helps me a lot.


Best regards
Alexander Wilhelm

^ permalink raw reply

* Re: wifi: mac80211: question about 20/40 coex support
From: Alex Gavin @ 2026-02-13  8:14 UTC (permalink / raw)
  To: Alexander Wilhelm, Johannes Berg; +Cc: linux-wireless, linux-kernel
In-Reply-To: <aY7NLLnOCXS8L31z@FUE-ALEWI-WINX>

On 2/12/26 23:05, Alexander Wilhelm wrote:
> 
> Hello wireless devs,
> 
> I am analyzing a wireless management frame taken from the beacon of an
> access point, and in this frame the `20/40 Coexistence Management Support`
> bit is set to 0, indicating that the feature is not supported. See frame
> below:
> 
>     Frame 2: 217 bytes on wire (1736 bits), 217 bytes captured (1736 bits)
>     Radiotap Header v0, Length 26
>     802.11 radio information
>     IEEE 802.11 Beacon frame, Flags: ........
>     IEEE 802.11 Wireless Management
>         Fixed parameters (12 bytes)
>         Tagged parameters (155 bytes)
>             Tag: SSID parameter set: "SSID"
>             Tag: Supported Rates 6(B), 9, 12(B), 18, 24(B), 36, 48, 54, [Mbit/sec]
>             Tag: DS Parameter set: Current Channel: 6
>             Tag: Traffic Indication Map (TIM): DTIM 0 of 2 bitmap
>             Tag: Country Information: Country Code DE, Environment All
>             Tag: ERP Information
>             Tag: QBSS Load Element 802.11e CCA Version
>             Tag: Supported Operating Classes
>             Tag: HT Capabilities (802.11n D1.10)
>             Tag: HT Information (802.11n D1.10)
>             Tag: Extended Capabilities (10 octets)
>                 Tag Number: Extended Capabilities (127)
>                 Tag length: 10
>                 Extended Capabilities: 0x04 (octet 1)
>                     .... ...0 = 20/40 BSS Coexistence Management Support: Not supported
>                     .... ..0. = General Link (GLK): 0x0
>                     .... .1.. = Extended Channel Switching: Supported
>                     .... 0... = GLK-GCR: 0x0
>                     ...0 .... = PSMP Capability: Not supported
>                     ..0. .... = Reserved: 0x0
>                     .0.. .... = S-PSMP Support: Not supported
>                     0... .... = Event: Not supported
>                 Extended Capabilities: 0x00 (octet 2)
>                 Extended Capabilities: 0x00 (octet 3)
>                 Extended Capabilities: 0x02 (octet 4)
>                 Extended Capabilities: 0x00 (octet 5)
>                 Extended Capabilities: 0x00 (octet 6)
>                 Extended Capabilities: 0x01 (octet 7)
>                 Extended Capabilities: 0x0040 (octets 8 & 9)
>                 Extended Capabilities: 0x40 (octet 10)
>             Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element
> 
> I reviewed several driver implementations, and none of them seem to
> advertise this capability. I also could not find any definition for this
> bit in `include/linux/ieee80211.h`, unlike many other capability bits that
> are defined (e.g. `WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING` or
> `WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT`). From what I can see, none of the
> `mac80211`‑based drivers appear to support this feature, is that correct?
> 
> Additionally, I want to confirm whether my understanding of the feature is
> accurate: the 20/40 Coexistence mechanism implements the “good neighbor”
> policy, meaning that an AP using a 40 MHz channel in the 2.4 GHz band must
> fall back to 20 MHz when it detects an overlapping BSS (OBSS). Is that
> right?
> 
> Any clarification would be greatly appreciated.
> 
> 
> Best regards
> Alexander Wilhelm
> 

From my understanding, this is implemented in userspace (i.e. hostapd), at least in upstream code.

In hostapd, the '20/40 BSS Coexistence Management Support' bit you reference is set in the
'hostapd_ext_capab_byte()' function in 'src/ap/ieee802_11_shared.c' when 'obss_interval' is set in
the AP config file.

For more information on the 'obss_interval' config item see the following from the hostapd config
reference here [1]:

# If set non-zero, require stations to perform scans of overlapping
# channels to test for stations which would be affected by 40 MHz traffic.
# This parameter sets the interval in seconds between these scans. Setting this
# to non-zero allows 2.4 GHz band AP to move dynamically to a 40 MHz channel if
# no co-existence issues with neighboring devices are found.
#obss_interval=0


The following sections from the 802.11 standard may be helpful to understand this topic in more
depth, although I'm sure there's information online that may be easier to digest:

- 9.4.2.58 20/40 BSS Coexistence element
- 9.4.2.54.2 HT Capability Information field
- 11.15.12 Switching between 40 MHz and 20 MHz

From 11.15.12:

TE-B: On any of the channels of the channel set defined in Clause 18, reception of a 20/40 BSS
Coexistence Management, Beacon, Probe Request, or Probe Response frame that contains a value of 1 in
a Forty MHz Intolerant field and that has the Address 1 field equal to the receiving STA’s address
or to a group address, with no further addressing qualifications.


Best,

Alex


[1] https://git.w1.fi/cgit/hostap/plain/hostapd/hostapd.conf



^ permalink raw reply

* [PATCH] wifi: mt76: mt7996: Disable Rx hdr_trans in monitor mode
From: Ryder Lee @ 2026-02-13  8:00 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-mediatek, linux-wireless, Ryder Lee

Ensure raw frames are captured without header modification.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt7996/main.c | 2 ++
 drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 7046bf26d8ed..bd3409b296b3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -485,6 +485,8 @@ static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled)
 
 	mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx),
 		       MT_DMA_DCR0_RXD_G5_EN, enabled);
+	mt76_rmw_field(dev, MT_MDP_DCR0,
+		       MT_MDP_DCR0_RX_HDR_TRANS_EN, !enabled);
 	mt7996_phy_set_rxfilter(phy);
 	mt7996_mcu_set_sniffer_mode(phy, enabled);
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h
index e48e0e575b64..393faae2d52b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h
@@ -159,6 +159,9 @@ enum offs_rev {
 #define MT_MDP_BASE				0x820cc000
 #define MT_MDP(ofs)				(MT_MDP_BASE + (ofs))
 
+#define MT_MDP_DCR0				MT_MDP(0x800)
+#define MT_MDP_DCR0_RX_HDR_TRANS_EN		BIT(19)
+
 #define MT_MDP_DCR2				MT_MDP(0x8e8)
 #define MT_MDP_DCR2_RX_TRANS_SHORT		BIT(2)
 
-- 
2.45.2


^ permalink raw reply related

* wifi: mac80211: question about 20/40 coex support
From: Alexander Wilhelm @ 2026-02-13  7:05 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, linux-kernel


Hello wireless devs,

I am analyzing a wireless management frame taken from the beacon of an
access point, and in this frame the `20/40 Coexistence Management Support`
bit is set to 0, indicating that the feature is not supported. See frame
below:

    Frame 2: 217 bytes on wire (1736 bits), 217 bytes captured (1736 bits)
    Radiotap Header v0, Length 26
    802.11 radio information
    IEEE 802.11 Beacon frame, Flags: ........
    IEEE 802.11 Wireless Management
        Fixed parameters (12 bytes)
        Tagged parameters (155 bytes)
            Tag: SSID parameter set: "SSID"
            Tag: Supported Rates 6(B), 9, 12(B), 18, 24(B), 36, 48, 54, [Mbit/sec]
            Tag: DS Parameter set: Current Channel: 6
            Tag: Traffic Indication Map (TIM): DTIM 0 of 2 bitmap
            Tag: Country Information: Country Code DE, Environment All
            Tag: ERP Information
            Tag: QBSS Load Element 802.11e CCA Version
            Tag: Supported Operating Classes
            Tag: HT Capabilities (802.11n D1.10)
            Tag: HT Information (802.11n D1.10)
            Tag: Extended Capabilities (10 octets)
                Tag Number: Extended Capabilities (127)
                Tag length: 10
                Extended Capabilities: 0x04 (octet 1)
                    .... ...0 = 20/40 BSS Coexistence Management Support: Not supported
                    .... ..0. = General Link (GLK): 0x0
                    .... .1.. = Extended Channel Switching: Supported
                    .... 0... = GLK-GCR: 0x0
                    ...0 .... = PSMP Capability: Not supported
                    ..0. .... = Reserved: 0x0
                    .0.. .... = S-PSMP Support: Not supported
                    0... .... = Event: Not supported
                Extended Capabilities: 0x00 (octet 2)
                Extended Capabilities: 0x00 (octet 3)
                Extended Capabilities: 0x02 (octet 4)
                Extended Capabilities: 0x00 (octet 5)
                Extended Capabilities: 0x00 (octet 6)
                Extended Capabilities: 0x01 (octet 7)
                Extended Capabilities: 0x0040 (octets 8 & 9)
                Extended Capabilities: 0x40 (octet 10)
            Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element

I reviewed several driver implementations, and none of them seem to
advertise this capability. I also could not find any definition for this
bit in `include/linux/ieee80211.h`, unlike many other capability bits that
are defined (e.g. `WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING` or
`WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT`). From what I can see, none of the
`mac80211`‑based drivers appear to support this feature, is that correct?

Additionally, I want to confirm whether my understanding of the feature is
accurate: the 20/40 Coexistence mechanism implements the “good neighbor”
policy, meaning that an AP using a 40 MHz channel in the 2.4 GHz band must
fall back to 20 MHz when it detects an overlapping BSS (OBSS). Is that
right?

Any clarification would be greatly appreciated.


Best regards
Alexander Wilhelm

^ permalink raw reply

* [PATCH rtw-next 12/12] wifi: rtw89: ser: post-recover DMAC state to prevent LPS
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

If entering LPS during SER (system error recovery), IMR might fail to
be re-enabled after SER. Then, the next SER would not be noticed well.
After FW v0.35.100.0, Wi-Fi 7 chipsets adjust the order in which SER
recovers DMAC state to prevent LPS from being in the middle of SER.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h | 1 +
 drivers/net/wireless/realtek/rtw89/fw.c   | 1 +
 drivers/net/wireless/realtek/rtw89/mac.c  | 7 ++++++-
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 5d1cec20bc80..cf0cc718f41c 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4796,6 +4796,7 @@ enum rtw89_fw_feature {
 	RTW89_FW_FEATURE_SER_L1_BY_EVENT,
 	RTW89_FW_FEATURE_SIM_SER_L0L1_BY_HALT_H2C,
 	RTW89_FW_FEATURE_LPS_ML_INFO_V1,
+	RTW89_FW_FEATURE_SER_POST_RECOVER_DMAC,
 
 	NUM_OF_RTW89_FW_FEATURES,
 };
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 67154e666ba2..c035e89e75dd 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -923,6 +923,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
 	__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 84, 0, RFK_PRE_NOTIFY_MCC_V1),
 	__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 84, 0, ADDR_CAM_V0),
 	__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 97, 0, SIM_SER_L0L1_BY_HALT_H2C),
+	__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 100, 0, SER_POST_RECOVER_DMAC),
 };
 
 static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 243cc02ad24e..923f39e39a26 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -826,7 +826,9 @@ u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
 	}
 
 	err = rtw89_read32(rtwdev, R_AX_HALT_C2H);
-	rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, 0);
+
+	if (!RTW89_CHK_FW_FEATURE(SER_POST_RECOVER_DMAC, &rtwdev->fw))
+		rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, 0);
 
 	err_scnr = RTW89_ERROR_SCENARIO(err);
 	if (err_scnr == RTW89_WCPU_CPU_EXCEPTION)
@@ -846,6 +848,9 @@ u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
 	if (chip->chip_gen != RTW89_CHIP_AX)
 		rtw89_write32(rtwdev, R_AX_HALT_C2H, 0);
 
+	if (RTW89_CHK_FW_FEATURE(SER_POST_RECOVER_DMAC, &rtwdev->fw))
+		rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, 0);
+
 	return err;
 }
 EXPORT_SYMBOL(rtw89_mac_get_err_status);
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 11/12] wifi: rtw89: ser: Wi-Fi 7 reset HALT C2H after reading it
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

When a SER (system error recovery) interrupt happens, driver reads HALT C2H
register to get the error status via MAC. For Wi-Fi 7 chipset, driver needs
to reset HALT C2H register after reading it to make FW aware that.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/mac.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 4d507eccaa00..243cc02ad24e 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -814,6 +814,7 @@ static bool rtw89_mac_suppress_log(struct rtw89_dev *rtwdev, u32 err)
 u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
 {
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+	const struct rtw89_chip_info *chip = rtwdev->chip;
 	u32 err, err_scnr;
 	int ret;
 
@@ -836,11 +837,15 @@ u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
 		err = MAC_AX_ERR_RXI300;
 
 	if (rtw89_mac_suppress_log(rtwdev, err))
-		return err;
+		goto bottom;
 
 	rtw89_fw_st_dbg_dump(rtwdev);
 	mac->dump_err_status(rtwdev, err);
 
+bottom:
+	if (chip->chip_gen != RTW89_CHIP_AX)
+		rtw89_write32(rtwdev, R_AX_HALT_C2H, 0);
+
 	return err;
 }
 EXPORT_SYMBOL(rtw89_mac_get_err_status);
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 10/12] wifi: rtw89: debug: add SER SW counters to count simulation
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

Some chipsets, e.g. Wi-Fi 7, will not record SER (system error recovery),
which are triggered by simulations, in the HW counters. Their HW counters
only record the SER happen in field. However for verification, it's still
needed to check if simulations are triggered. So, add SW counters to count
any causes that SER happen. But, SW can only count L1 and L2. SW does not
involve L0 SER, so SW cannot count it.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h  | 7 +++++++
 drivers/net/wireless/realtek/rtw89/debug.c | 6 ++++++
 drivers/net/wireless/realtek/rtw89/ser.c   | 2 ++
 3 files changed, 15 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 1ad1fd2a1f6f..5d1cec20bc80 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -5753,11 +5753,18 @@ enum rtw89_ser_rcvy_step {
 	RTW89_NUM_OF_SER_FLAGS
 };
 
+struct rtw89_ser_count {
+	unsigned int l1;
+	unsigned int l2;
+};
+
 struct rtw89_ser {
 	u8 state;
 	u8 alarm_event;
 	bool prehandle_l1;
 
+	struct rtw89_ser_count sw_cnt;
+
 	struct work_struct ser_hdl_work;
 	struct delayed_work ser_alarm_work;
 	const struct state_ent *st_tbl;
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index d46691fa09bc..4cff3d927a69 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -3780,6 +3780,7 @@ static ssize_t rtw89_debug_priv_ser_counters_get(struct rtw89_dev *rtwdev,
 						 struct rtw89_debugfs_priv *debugfs_priv,
 						 char *buf, size_t bufsz)
 {
+	const struct rtw89_ser_count *sw_cnt = &rtwdev->ser.sw_cnt;
 	const struct rtw89_chip_info *chip = rtwdev->chip;
 	struct rtw89_dbg_ser_counters cnt = {};
 	char *p = buf, *end = buf + bufsz;
@@ -3797,6 +3798,11 @@ static ssize_t rtw89_debug_priv_ser_counters_get(struct rtw89_dev *rtwdev,
 		return -EOPNOTSUPP;
 	}
 
+	p += scnprintf(p, end - p, "SER L1 SW Count: %u\n", sw_cnt->l1);
+	p += scnprintf(p, end - p, "SER L2 SW Count: %u\n", sw_cnt->l2);
+
+	/* Some chipsets won't record SER simulation in HW cnt. */
+	p += scnprintf(p, end - p, "---\n");
 	p += scnprintf(p, end - p, "SER L0 Count: %d\n", cnt.l0);
 	p += scnprintf(p, end - p, "SER L1 Count: %d\n", cnt.l1);
 	p += scnprintf(p, end - p, "SER L0 promote event: %d\n", cnt.l0_to_l1);
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
index 7fdc69578da3..b2c910cf9587 100644
--- a/drivers/net/wireless/realtek/rtw89/ser.c
+++ b/drivers/net/wireless/realtek/rtw89/ser.c
@@ -498,6 +498,7 @@ static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt)
 	switch (evt) {
 	case SER_EV_STATE_IN:
 		wiphy_lock(wiphy);
+		ser->sw_cnt.l1++;
 		wiphy_delayed_work_cancel(wiphy, &rtwdev->track_work);
 		wiphy_delayed_work_cancel(wiphy, &rtwdev->track_ps_work);
 		wiphy_unlock(wiphy);
@@ -730,6 +731,7 @@ static void ser_l2_reset_st_hdl(struct rtw89_ser *ser, u8 evt)
 	switch (evt) {
 	case SER_EV_STATE_IN:
 		wiphy_lock(rtwdev->hw->wiphy);
+		ser->sw_cnt.l2++;
 		ser_l2_reset_st_pre_hdl(ser);
 		wiphy_unlock(rtwdev->hw->wiphy);
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 09/12] wifi: rtw89: rfk: add hardware version to rtw89_fw_h2c_rf_pre_ntfy_mcc for new WiFi 7 firmware
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

The RF calibration in firmware needs proper hardware version to select
corresponding logic, so add the field to H2C command accordingly.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/fw.c | 1 +
 drivers/net/wireless/realtek/rtw89/fw.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index bfa5cac24d88..67154e666ba2 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -7371,6 +7371,7 @@ int rtw89_fw_h2c_rf_pre_ntfy_mcc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	h2c = (struct rtw89_fw_h2c_rfk_pre_info_mcc *)skb->data;
 
 	h2c->aid = cpu_to_le32(hal->aid);
+	h2c->acv = hal->acv;
 
 done:
 	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 80d260eb08cd..57e3b464c0a2 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -4881,6 +4881,8 @@ struct rtw89_fw_h2c_rfk_pre_info_mcc {
 	struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 base;
 	u8 rsvd[2];
 	__le32 aid;
+	u8 acv;
+	u8 rsvd2[3];
 } __packed;
 
 struct rtw89_h2c_rf_tssi {
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 08/12] wifi: rtw89: add H2C command to protect TX/RX for unused PHY
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

From: Kuan-Chung Chen <damon.chen@realtek.com>

For BE chips, the unused PHY should pause transmissions and receptions.
This ensures that no unexpected packets are routed to an inactive PHY,
which could otherwise trigger SER L0 and lead to TX hang.

Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/fw.c       | 87 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/fw.h       | 51 +++++++++++
 drivers/net/wireless/realtek/rtw89/mac.c      |  3 +
 drivers/net/wireless/realtek/rtw89/mac80211.c |  5 ++
 drivers/net/wireless/realtek/rtw89/ps.c       |  2 +
 5 files changed, 148 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 64874907bfe0..bfa5cac24d88 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -6871,6 +6871,93 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
 	return 0;
 }
 
+int rtw89_fw_h2c_trx_protect(struct rtw89_dev *rtwdev,
+			     enum rtw89_phy_idx phy_idx, bool enable)
+{
+	struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+	struct rtw89_h2c_trx_protect *h2c;
+	u32 len = sizeof(*h2c);
+	struct sk_buff *skb;
+	int ret;
+
+	if (chip->chip_gen != RTW89_CHIP_BE)
+		return 0;
+
+	skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+	if (!skb) {
+		rtw89_err(rtwdev, "failed to alloc skb for h2c trx protect\n");
+		return -ENOMEM;
+	}
+
+	skb_put(skb, len);
+	h2c = (struct rtw89_h2c_trx_protect *)skb->data;
+
+	h2c->c0 = le32_encode_bits(BIT(phy_idx), RTW89_H2C_TRX_PROTECT_C0_BAND_BITMAP) |
+		  le32_encode_bits(0, RTW89_H2C_TRX_PROTECT_C0_OP_MODE);
+	h2c->c1 = le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_C1_RX_IN) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_C1_PPDU_STS) |
+		  le32_encode_bits(1, RTW89_H2C_TRX_PROTECT_C1_MSK_RX_IN) |
+		  le32_encode_bits(1, RTW89_H2C_TRX_PROTECT_C1_MSK_PPDU_STS);
+	h2c->w0 = le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_BE0) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_BK0) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_VI0) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_VO0) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_BE1) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_BK1) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_VI1) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_VO1) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_MG0) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_MG1) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_MG2) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_HI)  |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_BCN) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_UL) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT0) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT1) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT2) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT3) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_SPEQ0) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W0_TXEN_SPEQ1);
+	h2c->m0 = cpu_to_le32(RTW89_H2C_TRX_PROTECT_W0_TXEN_BE0 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_BK0 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_VI0 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_VO0 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_BE1 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_BK1 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_VI1 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_VO1 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_MG0 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_MG1 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_MG2 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_HI |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_BCN |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_UL |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT0 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT1 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT2 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT3 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_SPEQ0 |
+			      RTW89_H2C_TRX_PROTECT_W0_TXEN_SPEQ1);
+	h2c->w1 = le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W1_CHINFO_EN) |
+		  le32_encode_bits(enable, RTW89_H2C_TRX_PROTECT_W1_DFS_EN);
+	h2c->m1 = cpu_to_le32(RTW89_H2C_TRX_PROTECT_W1_CHINFO_EN |
+			      RTW89_H2C_TRX_PROTECT_W1_DFS_EN);
+
+	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+			      H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
+			      H2C_FUNC_TRX_PROTECT, 0, 1, len);
+
+	ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait,
+				    RTW89_FW_OFLD_WAIT_COND_TRX_PROTECT);
+	if (ret) {
+		rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to trx protect\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
 			struct rtw89_fw_h2c_rf_reg_info *info,
 			u16 len, u8 page)
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index c60d419616d6..80d260eb08cd 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -3106,6 +3106,44 @@ struct rtw89_h2c_scanofld_be {
 #define RTW89_H2C_SCANOFLD_BE_W9_SIZE_MACC GENMASK(15, 8)
 #define RTW89_H2C_SCANOFLD_BE_W9_SIZE_OP GENMASK(23, 16)
 
+struct rtw89_h2c_trx_protect {
+	__le32 c0;
+	__le32 c1;
+	__le32 w0;
+	__le32 m0;
+	__le32 w1;
+	__le32 m1;
+} __packed;
+
+#define RTW89_H2C_TRX_PROTECT_C0_BAND_BITMAP GENMASK(2, 0)
+#define RTW89_H2C_TRX_PROTECT_C0_OP_MODE GENMASK(4, 3)
+#define RTW89_H2C_TRX_PROTECT_C1_RX_IN BIT(0)
+#define RTW89_H2C_TRX_PROTECT_C1_PPDU_STS BIT(4)
+#define RTW89_H2C_TRX_PROTECT_C1_MSK_RX_IN BIT(16)
+#define RTW89_H2C_TRX_PROTECT_C1_MSK_PPDU_STS BIT(20)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_BE0 BIT(0)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_BK0 BIT(1)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_VI0 BIT(2)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_VO0 BIT(3)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_BE1 BIT(4)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_BK1 BIT(5)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_VI1 BIT(6)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_VO1 BIT(7)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_MG0 BIT(8)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_MG1 BIT(9)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_MG2 BIT(10)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_HI BIT(11)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_BCN BIT(12)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_UL BIT(13)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT0 BIT(14)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT1 BIT(15)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT2 BIT(16)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_TWT3 BIT(17)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_SPEQ0 BIT(18)
+#define RTW89_H2C_TRX_PROTECT_W0_TXEN_SPEQ1 BIT(19)
+#define RTW89_H2C_TRX_PROTECT_W1_CHINFO_EN BIT(0)
+#define RTW89_H2C_TRX_PROTECT_W1_DFS_EN BIT(1)
+
 struct rtw89_h2c_fwips {
 	__le32 w0;
 } __packed;
@@ -4598,6 +4636,7 @@ enum rtw89_fw_ofld_h2c_func {
 	H2C_FUNC_OFLD_TP		= 0x20,
 	H2C_FUNC_MAC_MACID_PAUSE_SLEEP	= 0x28,
 	H2C_FUNC_SCANOFLD_BE		= 0x2c,
+	H2C_FUNC_TRX_PROTECT		= 0x34,
 
 	NUM_OF_RTW89_FW_OFLD_H2C_FUNC,
 };
@@ -4608,6 +4647,7 @@ enum rtw89_fw_ofld_h2c_func {
 #define RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op) \
 	RTW89_FW_OFLD_WAIT_COND(RTW89_PKT_OFLD_WAIT_TAG(pkt_id, pkt_op), \
 				H2C_FUNC_PACKET_OFLD)
+#define RTW89_FW_OFLD_WAIT_COND_TRX_PROTECT RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_TRX_PROTECT)
 
 #define RTW89_SCANOFLD_WAIT_COND_ADD_CH RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_ADD_SCANOFLD_CH)
 
@@ -5294,6 +5334,8 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
 				 struct rtw89_scan_option *opt,
 				 struct rtw89_vif_link *vif,
 				 bool wowlan);
+int rtw89_fw_h2c_trx_protect(struct rtw89_dev *rtwdev,
+			     enum rtw89_phy_idx phy_idx, bool enable);
 int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
 			struct rtw89_fw_h2c_rf_reg_info *info,
 			u16 len, u8 page);
@@ -5469,6 +5511,15 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
 		rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(rtwdev);
 }
 
+static inline void rtw89_fw_h2c_init_trx_protect(struct rtw89_dev *rtwdev)
+{
+	u8 active_bands = rtw89_get_active_phy_bitmap(rtwdev);
+	int i;
+
+	for (i = 0; i < RTW89_PHY_NUM; i++)
+		rtw89_fw_h2c_trx_protect(rtwdev, i, active_bands & BIT(i));
+}
+
 static inline int rtw89_chip_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
 						  struct rtw89_vif_link *rtwvif_link,
 						  struct rtw89_sta_link *rtwsta_link)
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 8472f1a63951..4d507eccaa00 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -5412,6 +5412,9 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le
 			cond = RTW89_SCANOFLD_BE_WAIT_COND_START;
 			h2c_return &= RTW89_C2H_SCAN_DONE_ACK_RETURN;
 			break;
+		case H2C_FUNC_TRX_PROTECT:
+			cond = RTW89_FW_OFLD_WAIT_COND_TRX_PROTECT;
+			break;
 		}
 
 		data.err = !!h2c_return;
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 315bb0d0759f..6b8f8bf2234d 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -528,6 +528,8 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev,
 	if (vif->type == NL80211_IFTYPE_AP || sta->tdls)
 		rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE);
 
+	rtw89_fw_h2c_init_trx_protect(rtwdev);
+
 	return 0;
 
 unset_link:
@@ -1584,6 +1586,8 @@ static void __rtw89_ops_clr_vif_links(struct rtw89_dev *rtwdev,
 		if (unlikely(!rtwvif_link))
 			continue;
 
+		rtw89_fw_h2c_trx_protect(rtwdev, rtwvif_link->phy_idx, false);
+
 		__rtw89_ops_remove_iface_link(rtwdev, rtwvif_link);
 
 		rtw89_vif_unset_link(rtwvif, link_id);
@@ -1609,6 +1613,7 @@ static int __rtw89_ops_set_vif_links(struct rtw89_dev *rtwdev,
 				  __func__, link_id);
 			return ret;
 		}
+		rtw89_fw_h2c_trx_protect(rtwdev, rtwvif_link->phy_idx, true);
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index aad2ee7926d6..125cf14fa581 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -226,6 +226,8 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev)
 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
 		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
 			rtw89_leave_lps_vif(rtwdev, rtwvif_link);
+
+	rtw89_fw_h2c_init_trx_protect(rtwdev);
 }
 
 void rtw89_enter_ips(struct rtw89_dev *rtwdev)
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 07/12] wifi: rtw89: 8851b: update supported firmware format to 1
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

More data will be included in Firmware file and loaded via FW elements.
Increase RTL8851B FW format to 1 to prevent old driver from failing to
recognize FW with FW elements.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8851b.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 0ea125ef21fa..a0769cdd2352 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -15,7 +15,7 @@
 #include "txrx.h"
 #include "util.h"
 
-#define RTW8851B_FW_FORMAT_MAX 0
+#define RTW8851B_FW_FORMAT_MAX 1
 #define RTW8851B_FW_BASENAME "rtw89/rtw8851b_fw"
 #define RTW8851B_MODULE_FIRMWARE \
 	RTW89_GEN_MODULE_FWNAME(RTW8851B_FW_BASENAME, RTW8851B_FW_FORMAT_MAX)
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 06/12] wifi: rtw89: 8852a: update supported firmware format to 1
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

More data will be included in Firmware file and loaded via FW elements.
Unlike other chips, for RF radio, RTL8852A uses rtw89_phy_config_rf_reg
instead of v1, so update loading handling of corresponding FW element.
And then, increase RTL8852A FW format to 1 to prevent old driver from
misusing the data in FW elements.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/fw.c       | 5 ++++-
 drivers/net/wireless/realtek/rtw89/phy.c      | 8 ++++----
 drivers/net/wireless/realtek/rtw89/phy.h      | 4 ++++
 drivers/net/wireless/realtek/rtw89/rtw8852a.c | 2 +-
 4 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index ff27f00ec6d2..64874907bfe0 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1073,6 +1073,7 @@ int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev,
 				 const union rtw89_fw_element_arg arg)
 {
 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
+	const struct rtw89_chip_info *chip = rtwdev->chip;
 	struct rtw89_hal *hal = &rtwdev->hal;
 	struct rtw89_phy_table *tbl, **pp;
 	struct rtw89_reg2_def *regs;
@@ -1129,7 +1130,9 @@ int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev,
 
 	if (radio) {
 		tbl->rf_path = arg.rf_path;
-		tbl->config = rtw89_phy_config_rf_reg_v1;
+		tbl->config = chip->chip_id == RTL8852A ?
+			      rtw89_phy_config_rf_reg :
+			      rtw89_phy_config_rf_reg_v1;
 	}
 
 	*pp = tbl;
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 6c6d5f1da867..0e9925f43260 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -1659,10 +1659,10 @@ static void rtw89_phy_config_rf_reg_noio(struct rtw89_dev *rtwdev,
 				     (struct rtw89_fw_h2c_rf_reg_info *)extra_data);
 }
 
-static void rtw89_phy_config_rf_reg(struct rtw89_dev *rtwdev,
-				    const struct rtw89_reg2_def *reg,
-				    enum rtw89_rf_path rf_path,
-				    void *extra_data)
+void rtw89_phy_config_rf_reg(struct rtw89_dev *rtwdev,
+			     const struct rtw89_reg2_def *reg,
+			     enum rtw89_rf_path rf_path,
+			     void *extra_data)
 {
 	if (reg->addr == 0xfe) {
 		mdelay(50);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index ab263738d212..094c7e45f254 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -852,6 +852,10 @@ bool rtw89_phy_write_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
 void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev);
 void rtw89_phy_init_bb_afe(struct rtw89_dev *rtwdev);
 void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio);
+void rtw89_phy_config_rf_reg(struct rtw89_dev *rtwdev,
+			     const struct rtw89_reg2_def *reg,
+			     enum rtw89_rf_path rf_path,
+			     void *extra_data);
 void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
 				const struct rtw89_reg2_def *reg,
 				enum rtw89_rf_path rf_path,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 6089cf9e1d54..898c534a5762 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -12,7 +12,7 @@
 #include "rtw8852a_table.h"
 #include "txrx.h"
 
-#define RTW8852A_FW_FORMAT_MAX 0
+#define RTW8852A_FW_FORMAT_MAX 1
 #define RTW8852A_FW_BASENAME "rtw89/rtw8852a_fw"
 #define RTW8852A_MODULE_FIRMWARE \
 	RTW89_GEN_MODULE_FWNAME(RTW8852A_FW_BASENAME, RTW8852A_FW_FORMAT_MAX)
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 05/12] wifi: rtw89: 8852a: move DIG tables to rtw8852a.c
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

Now, most of PHY parameter tables in driver can be loaded via FW elements.
Plan to generate the corresponding FW elements for 8852A PHY tables. Then,
after FW elements work for a enough time, rtw8852a_table.c can be cleaned
up. However, DIG (dynamic initial gain) tables are legacy for 8852A only,
so FW element doesn't support. Their sizes are not very big, so move them
to rtw8852a.c and keep rtw8852a_table.c for PHY tables which are supported
by FW elements.

No logic is changed.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8852a.c | 51 +++++++++++++++++++
 .../wireless/realtek/rtw89/rtw8852a_table.c   | 51 -------------------
 .../wireless/realtek/rtw89/rtw8852a_table.h   |  1 -
 3 files changed, 51 insertions(+), 52 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 0d5ec9755783..6089cf9e1d54 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2179,6 +2179,57 @@ static void rtw8852a_query_ppdu(struct rtw89_dev *rtwdev,
 		rtw8852a_fill_freq_with_ppdu(rtwdev, phy_ppdu, status);
 }
 
+#define DECLARE_DIG_TABLE(name) \
+static const struct rtw89_phy_dig_gain_cfg name##_table = { \
+	.table = name, \
+	.size = ARRAY_SIZE(name) \
+}
+
+static const struct rtw89_reg_def rtw89_8852a_lna_gain_g[] = {
+	{R_PATH0_LNA_ERR1, B_PATH0_LNA_ERR_G0_G_MSK},
+	{R_PATH0_LNA_ERR2, B_PATH0_LNA_ERR_G1_G_MSK},
+	{R_PATH0_LNA_ERR2, B_PATH0_LNA_ERR_G2_G_MSK},
+	{R_PATH0_LNA_ERR3, B_PATH0_LNA_ERR_G3_G_MSK},
+	{R_PATH0_LNA_ERR3, B_PATH0_LNA_ERR_G4_G_MSK},
+	{R_PATH0_LNA_ERR4, B_PATH0_LNA_ERR_G5_G_MSK},
+	{R_PATH0_LNA_ERR5, B_PATH0_LNA_ERR_G6_G_MSK},
+};
+
+DECLARE_DIG_TABLE(rtw89_8852a_lna_gain_g);
+
+static const struct rtw89_reg_def rtw89_8852a_tia_gain_g[] = {
+	{R_PATH0_TIA_ERR_G0, B_PATH0_TIA_ERR_G0_G_MSK},
+	{R_PATH0_TIA_ERR_G1, B_PATH0_TIA_ERR_G1_G_MSK},
+};
+
+DECLARE_DIG_TABLE(rtw89_8852a_tia_gain_g);
+
+static const struct rtw89_reg_def rtw89_8852a_lna_gain_a[] = {
+	{R_PATH0_LNA_ERR1, B_PATH0_LNA_ERR_G0_A_MSK},
+	{R_PATH0_LNA_ERR1, B_PATH0_LNA_ERR_G1_A_MSK},
+	{R_PATH0_LNA_ERR2, B_PATH0_LNA_ERR_G2_A_MSK},
+	{R_PATH0_LNA_ERR3, B_PATH0_LNA_ERR_G3_A_MSK},
+	{R_PATH0_LNA_ERR3, B_PATH0_LNA_ERR_G4_A_MSK},
+	{R_PATH0_LNA_ERR4, B_PATH0_LNA_ERR_G5_A_MSK},
+	{R_PATH0_LNA_ERR4, B_PATH0_LNA_ERR_G6_A_MSK},
+};
+
+DECLARE_DIG_TABLE(rtw89_8852a_lna_gain_a);
+
+static const struct rtw89_reg_def rtw89_8852a_tia_gain_a[] = {
+	{R_PATH0_TIA_ERR_G0, B_PATH0_TIA_ERR_G0_A_MSK},
+	{R_PATH0_TIA_ERR_G1, B_PATH0_TIA_ERR_G1_A_MSK},
+};
+
+DECLARE_DIG_TABLE(rtw89_8852a_tia_gain_a);
+
+static const struct rtw89_phy_dig_gain_table rtw89_8852a_phy_dig_table = {
+	.cfg_lna_g = &rtw89_8852a_lna_gain_g_table,
+	.cfg_tia_g = &rtw89_8852a_tia_gain_g_table,
+	.cfg_lna_a = &rtw89_8852a_lna_gain_a_table,
+	.cfg_tia_a = &rtw89_8852a_tia_gain_a_table
+};
+
 #ifdef CONFIG_PM
 static const struct wiphy_wowlan_support rtw_wowlan_stub_8852a = {
 	.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
index 495890c180ef..ffdeb3801991 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
@@ -50952,50 +50952,6 @@ const s8 rtw89_8852a_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
 	[2][1][RTW89_UK][46] = 32,
 };
 
-#define DECLARE_DIG_TABLE(name) \
-static const struct rtw89_phy_dig_gain_cfg name##_table = { \
-	.table = name, \
-	.size = ARRAY_SIZE(name) \
-}
-
-static const struct rtw89_reg_def rtw89_8852a_lna_gain_g[] = {
-	{R_PATH0_LNA_ERR1, B_PATH0_LNA_ERR_G0_G_MSK},
-	{R_PATH0_LNA_ERR2, B_PATH0_LNA_ERR_G1_G_MSK},
-	{R_PATH0_LNA_ERR2, B_PATH0_LNA_ERR_G2_G_MSK},
-	{R_PATH0_LNA_ERR3, B_PATH0_LNA_ERR_G3_G_MSK},
-	{R_PATH0_LNA_ERR3, B_PATH0_LNA_ERR_G4_G_MSK},
-	{R_PATH0_LNA_ERR4, B_PATH0_LNA_ERR_G5_G_MSK},
-	{R_PATH0_LNA_ERR5, B_PATH0_LNA_ERR_G6_G_MSK},
-};
-
-DECLARE_DIG_TABLE(rtw89_8852a_lna_gain_g);
-
-static const struct rtw89_reg_def rtw89_8852a_tia_gain_g[] = {
-	{R_PATH0_TIA_ERR_G0, B_PATH0_TIA_ERR_G0_G_MSK},
-	{R_PATH0_TIA_ERR_G1, B_PATH0_TIA_ERR_G1_G_MSK},
-};
-
-DECLARE_DIG_TABLE(rtw89_8852a_tia_gain_g);
-
-static const struct rtw89_reg_def rtw89_8852a_lna_gain_a[] = {
-	{R_PATH0_LNA_ERR1, B_PATH0_LNA_ERR_G0_A_MSK},
-	{R_PATH0_LNA_ERR1, B_PATH0_LNA_ERR_G1_A_MSK},
-	{R_PATH0_LNA_ERR2, B_PATH0_LNA_ERR_G2_A_MSK},
-	{R_PATH0_LNA_ERR3, B_PATH0_LNA_ERR_G3_A_MSK},
-	{R_PATH0_LNA_ERR3, B_PATH0_LNA_ERR_G4_A_MSK},
-	{R_PATH0_LNA_ERR4, B_PATH0_LNA_ERR_G5_A_MSK},
-	{R_PATH0_LNA_ERR4, B_PATH0_LNA_ERR_G6_A_MSK},
-};
-
-DECLARE_DIG_TABLE(rtw89_8852a_lna_gain_a);
-
-static const struct rtw89_reg_def rtw89_8852a_tia_gain_a[] = {
-	{R_PATH0_TIA_ERR_G0, B_PATH0_TIA_ERR_G0_A_MSK},
-	{R_PATH0_TIA_ERR_G1, B_PATH0_TIA_ERR_G1_A_MSK},
-};
-
-DECLARE_DIG_TABLE(rtw89_8852a_tia_gain_a);
-
 const struct rtw89_phy_table rtw89_8852a_phy_bb_table = {
 	.regs		= rtw89_8852a_phy_bb_regs,
 	.n_regs		= ARRAY_SIZE(rtw89_8852a_phy_bb_regs),
@@ -51042,13 +50998,6 @@ const struct rtw89_txpwr_track_cfg rtw89_8852a_trk_cfg = {
 	.delta_swingidx_2g_cck_a_p = _txpwr_track_delta_swingidx_2g_cck_a_p,
 };
 
-const struct rtw89_phy_dig_gain_table rtw89_8852a_phy_dig_table = {
-	.cfg_lna_g = &rtw89_8852a_lna_gain_g_table,
-	.cfg_tia_g = &rtw89_8852a_tia_gain_g_table,
-	.cfg_lna_a = &rtw89_8852a_lna_gain_a_table,
-	.cfg_tia_a = &rtw89_8852a_tia_gain_a_table
-};
-
 const struct rtw89_rfe_parms rtw89_8852a_dflt_parms = {
 	.byr_tbl = &rtw89_8852a_byr_table,
 	.rule_2ghz = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
index 7463ae6ee3f9..58fe8575c1c9 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
@@ -11,7 +11,6 @@ extern const struct rtw89_phy_table rtw89_8852a_phy_bb_table;
 extern const struct rtw89_phy_table rtw89_8852a_phy_radioa_table;
 extern const struct rtw89_phy_table rtw89_8852a_phy_radiob_table;
 extern const struct rtw89_phy_table rtw89_8852a_phy_nctl_table;
-extern const struct rtw89_phy_dig_gain_table rtw89_8852a_phy_dig_table;
 extern const struct rtw89_txpwr_track_cfg rtw89_8852a_trk_cfg;
 extern const struct rtw89_rfe_parms rtw89_8852a_dflt_parms;
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 04/12] wifi: rtw89: 8852b: update supported firmware format to 2
From: Ping-Ke Shih @ 2026-02-13  6:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: damon.chen, kevin_yang
In-Reply-To: <20260213061552.29997-1-pkshih@realtek.com>

After firmware version 0.29.29.15, more data are included in firmware
file. Increase format to 2 to prevent old driver failed to load the new
firmware.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8852b.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index b687ddaa839e..f4fb5f76298c 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -13,7 +13,7 @@
 #include "rtw8852b_table.h"
 #include "txrx.h"
 
-#define RTW8852B_FW_FORMAT_MAX 1
+#define RTW8852B_FW_FORMAT_MAX 2
 #define RTW8852B_FW_BASENAME "rtw89/rtw8852b_fw"
 #define RTW8852B_MODULE_FIRMWARE \
 	RTW89_GEN_MODULE_FWNAME(RTW8852B_FW_BASENAME, RTW8852B_FW_FORMAT_MAX)
-- 
2.25.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox