* Re: [PATCH ath-next v2] wifi: ath11k: Pass the correct value of each TID during a stop AMPDU session
From: Jeff Johnson @ 2026-02-27 17:39 UTC (permalink / raw)
To: Reshma Immaculate Rajkumar, ath11k; +Cc: linux-wireless
In-Reply-To: <20260227095609.3691546-1-reshma.rajkumar@oss.qualcomm.com>
On 2/27/2026 1:56 AM, Reshma Immaculate Rajkumar wrote:
> v2:
> * Added QTI yearless copyright
> drivers/net/wireless/ath/ath11k/dp_rx.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
> index b9e976ddcbbf..00d27e0053b2 100644
> --- a/drivers/net/wireless/ath/ath11k/dp_rx.c
> +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
> @@ -2,6 +2,7 @@
> /*
> * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
> * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
Per current guidance, which I shared privately, you should have removed the
Qualcomm Innovation Center copyright since it is now covered by the QTI one.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> */
^ permalink raw reply
* Re: [RFC PATCH 2/2] wifi: ath10k: only wait for response to SET_KEY
From: James Prestwood @ 2026-02-27 17:28 UTC (permalink / raw)
To: Baochen Qiang, Jeff Johnson, Richard Acayan, linux-wireless,
ath10k
In-Reply-To: <8b468ad4-39e3-401f-a2f2-7484759137df@oss.qualcomm.com>
Hi,
On 2/25/26 6:59 PM, Baochen Qiang wrote:
>
> On 2/13/2026 1: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?
> unfortunately no
>
>> Do we normally always get a response to DELETE_KEY but in some instances it
>> comes very late (or not at all)?
> In my tests, I never hit this issue so seems can always get a response.
>
>> 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?
> I would suggest not to remove the wait, but instead reduce the timeout to like 1s, just
> like the patch "[RFC 0/1] wifi: ath10k: improvement on key removal failure".
>
Is there a specific reason to require a wait? I would be more ok if the
way was sub-second, like 100ms or frankly even less (no idea what a
"normal" amount of time is to delete a key). The issue is this effects
roaming, and will delay roams by e.g. 1 second which is not ideal. I've
also seen a 1 second wait cause issues with configurations that expect a
very fast reassociation time. Even 1 second was causing a deauth.
I dropped this patch a long time ago and replaced it with a similar
patch being discussed here. So far, no issues, though I realize this is
a limited test with specific hardware.
Thanks,
James
>> /jeff
^ permalink raw reply
* Re: 6.18.13 iwlwifi deadlock allocating cma while work-item is active.
From: Ben Greear @ 2026-02-27 16:31 UTC (permalink / raw)
To: linux-wireless; +Cc: Korenblit, Miriam Rachel, linux-mm
In-Reply-To: <fa4e82ee-eb14-3930-c76c-f3bd59c5f258@candelatech.com>
On 2/23/26 14:36, Ben Greear wrote:
> Hello,
>
> I hit a deadlock related to CMA mem allocation attempting to flush all work
> while holding some wifi related mutex, and with a work-queue attempting to process a wifi regdomain
> work item. I really don't see any good way to fix this,
> it would seem that any code that was holding a mutex that could block a work-queue
> cannot safely allocate CMA memory? Hopefully someone else has a better idea.
I tried using a kthread to do the regulatory domain processing instead of worker item,
and that seems to have solved the problem. If that seems reasonable approach to
wifi stack folks, I can post a patch.
Thanks,
Ben
>
> For whatever reason, my hacked up kernel will print out the sysrq process stack traces I need
> to understand this, and my stable 6.18.13 will not. But, the locks-held matches in both cases, so almost
> certainly this is same problem. I can reproduce the same problem on both un-modified stable
> and my own. The details below are from my modified 6.18.9+ kernel.
>
> I only hit this (reliably?) with a KASAN enabled kernel, likely because it makes things slow enough to
> hit the problem and/or causes CMA allocations in a different manner.
>
> General way to reproduce is to have large amounts of intel be200 radios in a system, and bring them
> admin up and down.
>
>
> ## From 6.18.13 (un-modified)
>
> 40479 Feb 23 14:13:31 ct523c-de7c kernel: 5 locks held by kworker/u32:11/34989:
> 40480 Feb 23 14:13:31 ct523c-de7c kernel: #0: ffff888120161148 ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_one_work+0xf7a/0x17b0
> 40481 Feb 23 14:13:31 ct523c-de7c kernel: #1: ffff8881a561fd20 ((work_completion)(&rdev->wiphy_work)){+.+.}-{0:0}, at: process_one_work+0x7ca/0x17b0
> 40482 Feb 23 14:13:31 ct523c-de7c kernel: #2: ffff88815e618788 (&rdev->wiphy.mtx){+.+.}-{4:4}, at: cfg80211_wiphy_work+0x5c/0x570 [cfg80211]
> 40483 Feb 23 14:13:31 ct523c-de7c kernel: #3: ffffffff87232e60 (&cma->alloc_mutex){+.+.}-{4:4}, at: __cma_alloc+0x3c5/0xd20
> 40484 Feb 23 14:13:31 ct523c-de7c kernel: #4: ffffffff8534f668 (lock#5){+.+.}-{4:4}, at: __lru_add_drain_all+0x5f/0x530
>
> 40488 Feb 23 14:13:31 ct523c-de7c kernel: 4 locks held by kworker/1:0/39480:
> 40489 Feb 23 14:13:31 ct523c-de7c kernel: #0: ffff88812006b148 ((wq_completion)events){+.+.}-{0:0}, at: process_one_work+0xf7a/0x17b0
> 40490 Feb 23 14:13:31 ct523c-de7c kernel: #1: ffff88814087fd20 (reg_work){+.+.}-{0:0}, at: process_one_work+0x7ca/0x17b0
> 40491 Feb 23 14:13:31 ct523c-de7c kernel: #2: ffffffff85970028 (rtnl_mutex){+.+.}-{4:4}, at: reg_todo+0x18/0x770 [cfg80211]
> 40492 Feb 23 14:13:31 ct523c-de7c kernel: #3: ffff88815e618788 (&rdev->wiphy.mtx){+.+.}-{4:4}, at: reg_process_self_managed_hints+0x70/0x190 [cfg80211]
>
>
> ## Rest of this is from my 6.18.9+ hacks kernel.
>
> ### thread trying to allocate cma is blocked here, trying to flush work.
>
> Type "apropos word" to search for commands related to "word"...
> Reading symbols from vmlinux...
> (gdb) l *(alloc_contig_range_noprof+0x1de)
> 0xffffffff8162453e is in alloc_contig_range_noprof (/home2/greearb/git/linux-6.18.dev.y/mm/page_alloc.c:6798).
> 6793 .reason = MR_CONTIG_RANGE,
> 6794 };
> 6795
> 6796 lru_cache_disable();
> 6797
> 6798 while (pfn < end || !list_empty(&cc->migratepages)) {
> 6799 if (fatal_signal_pending(current)) {
> 6800 ret = -EINTR;
> 6801 break;
> 6802 }
> (gdb) l *(__lru_add_drain_all+0x19b)
> 0xffffffff815ae44b is in __lru_add_drain_all (/home2/greearb/git/linux-6.18.dev.y/mm/swap.c:884).
> 879 queue_work_on(cpu, mm_percpu_wq, work);
> 880 __cpumask_set_cpu(cpu, &has_work);
> 881 }
> 882 }
> 883
> 884 for_each_cpu(cpu, &has_work)
> 885 flush_work(&per_cpu(lru_add_drain_work, cpu));
> 886
> 887 done:
> 888 mutex_unlock(&lock);
> (gdb)
>
>
> #### and other thread is trying to process a regdom request, and trying to use
> # rcu and rtnl???
>
> Type "apropos word" to search for commands related to "word"...
> Reading symbols from net/wireless/cfg80211.ko...
> (gdb) l *(reg_todo+0x18)
> 0xe238 is in reg_todo (/home2/greearb/git/linux-6.18.dev.y/net/wireless/reg.c:3107).
> 3102 */
> 3103 static void reg_process_pending_hints(void)
> 3104 {
> 3105 struct regulatory_request *reg_request, *lr;
> 3106
> 3107 lr = get_last_request();
> 3108
> 3109 /* When last_request->processed becomes true this will be rescheduled */
> 3110 if (lr && !lr->processed) {
> 3111 pr_debug("Pending regulatory request, waiting for it to be processed...\n");
> (gdb)
>
> static struct regulatory_request *get_last_request(void)
> {
> return rcu_dereference_rtnl(last_request);
> }
>
>
> task:kworker/6:0 state:D stack:0 pid:56 tgid:56 ppid:2 task_flags:0x4208060 flags:0x00080000
> Workqueue: events reg_todo [cfg80211]
> Call Trace:
> <TASK>
> __schedule+0x526/0x1290
> preempt_schedule_notrace+0x35/0x50
> preempt_schedule_notrace_thunk+0x16/0x30
> rcu_is_watching+0x2a/0x30
> lock_acquire+0x26d/0x2c0
> schedule+0xac/0x120
> ? schedule+0x8d/0x120
> schedule_preempt_disabled+0x11/0x20
> __mutex_lock+0x726/0x1070
> ? reg_todo+0x18/0x2b0 [cfg80211]
> ? reg_todo+0x18/0x2b0 [cfg80211]
> reg_todo+0x18/0x2b0 [cfg80211]
> process_one_work+0x221/0x6d0
> worker_thread+0x1e5/0x3b0
> ? rescuer_thread+0x450/0x450
> kthread+0x108/0x220
> ? kthreads_online_cpu+0x110/0x110
> ret_from_fork+0x1c6/0x220
> ? kthreads_online_cpu+0x110/0x110
> ret_from_fork_asm+0x11/0x20
> </TASK>
>
> task:ip state:D stack:0 pid:72857 tgid:72857 ppid:72843 task_flags:0x400100 flags:0x00080001
> Call Trace:
> <TASK>
> __schedule+0x526/0x1290
> ? schedule+0x8d/0x120
> ? schedule+0xe2/0x120
> schedule+0x36/0x120
> schedule_timeout+0xf9/0x110
> ? mark_held_locks+0x40/0x70
> __wait_for_common+0xbe/0x1e0
> ? hrtimer_nanosleep_restart+0x120/0x120
> ? __flush_work+0x20b/0x530
> __flush_work+0x34e/0x530
> ? flush_workqueue_prep_pwqs+0x160/0x160
> ? bpf_prog_test_run_tracing+0x160/0x2d0
> __lru_add_drain_all+0x19b/0x220
> alloc_contig_range_noprof+0x1de/0x8a0
> __cma_alloc+0x1f1/0x6a0
> __dma_direct_alloc_pages.isra.0+0xcb/0x2f0
> dma_direct_alloc+0x7b/0x250
> dma_alloc_attrs+0xa1/0x2a0
> _iwl_pcie_ctxt_info_dma_alloc_coherent+0x31/0xb0 [iwlwifi]
> iwl_pcie_ctxt_info_alloc_dma+0x20/0x50 [iwlwifi]
> iwl_pcie_init_fw_sec+0x2fc/0x380 [iwlwifi]
> iwl_pcie_ctxt_info_v2_alloc+0x19e/0x530 [iwlwifi]
> iwl_trans_pcie_gen2_start_fw+0x2e2/0x820 [iwlwifi]
> ? lock_is_held_type+0x92/0x100
> iwl_trans_start_fw+0x77/0x90 [iwlwifi]
> iwl_mld_load_fw_wait_alive+0x97/0x2c0 [iwlmld]
> ? iwl_mld_mac80211_sta_state+0x780/0x780 [iwlmld]
> ? lock_is_held_type+0x92/0x100
> iwl_mld_load_fw+0x91/0x240 [iwlmld]
> ? ieee80211_open+0x3d/0xe0 [mac80211]
> ? lock_is_held_type+0x92/0x100
> iwl_mld_start_fw+0x44/0x470 [iwlmld]
> iwl_mld_mac80211_start+0x3d/0x1b0 [iwlmld]
> drv_start+0x6f/0x1d0 [mac80211]
> ieee80211_do_open+0x2d6/0x960 [mac80211]
> ieee80211_open+0x62/0xe0 [mac80211]
> __dev_open+0x11a/0x2e0
> __dev_change_flags+0x1f8/0x280
> netif_change_flags+0x22/0x60
> do_setlink.isra.0+0xe57/0x11a0
> ? __mutex_lock+0xb0/0x1070
> ? __mutex_lock+0x99e/0x1070
> ? __nla_validate_parse+0x5e/0xcd0
> ? rtnl_newlink+0x355/0xb50
> ? cap_capable+0x90/0x100
> ? security_capable+0x72/0x80
> rtnl_newlink+0x7e8/0xb50
> ? __lock_acquire+0x436/0x2190
> ? lock_acquire+0xc2/0x2c0
> ? rtnetlink_rcv_msg+0x97/0x660
> ? find_held_lock+0x2b/0x80
> ? do_setlink.isra.0+0x11a0/0x11a0
> ? rtnetlink_rcv_msg+0x3ea/0x660
> ? lock_release+0xcc/0x290
> ? do_setlink.isra.0+0x11a0/0x11a0
> rtnetlink_rcv_msg+0x409/0x660
> ? rtnl_fdb_dump+0x240/0x240
> netlink_rcv_skb+0x56/0x100
> netlink_unicast+0x1e1/0x2d0
> netlink_sendmsg+0x219/0x460
> __sock_sendmsg+0x38/0x70
> ____sys_sendmsg+0x214/0x280
> ? import_iovec+0x2c/0x30
> ? copy_msghdr_from_user+0x6c/0xa0
> ___sys_sendmsg+0x85/0xd0
> ? __lock_acquire+0x436/0x2190
> ? find_held_lock+0x2b/0x80
> ? lock_acquire+0xc2/0x2c0
> ? mntput_no_expire+0x43/0x460
> ? find_held_lock+0x2b/0x80
> ? mntput_no_expire+0x8c/0x460
> __sys_sendmsg+0x6b/0xc0
> do_syscall_64+0x6b/0x11b0
> entry_SYSCALL_64_after_hwframe+0x4b/0x53
>
> Thanks,
> Ben
>
^ permalink raw reply
* Re: [PATCH wireless-next v2 00/34] wifi: inffmac: introducing a driver for Infineon's new generation chipsets
From: Gokul Sivakumar @ 2026-02-27 14:34 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-wireless, Johannes Berg, Arend van Spriel,
wlan-kernel-dev-list
In-Reply-To: <6612163e-b933-432c-995c-6daec9c7be29@nabladev.com>
On 02/27, Marek Vasut wrote:
> On 1/16/26 5:33 PM, Gokul Sivakumar wrote:
> > On 01/15, Marek Vasut wrote:
> > > On 1/14/26 9:12 AM, Gokul Sivakumar wrote:
> > > > On 01/14, Marek Vasut wrote:
> > > > > On 1/13/26 9:33 PM, Gokul Sivakumar wrote:
> > > > > > Infineon(Cypress) is introducing a new INFFMAC (WLAN FULLMAC) Linux driver
> > > > > > specifically for its new-generation AIROC family of Wi-Fi Connectivity
> > > > > > Processor (CP) chipsets (CYW5591x), Wi-Fi + Bluetooth combo chipsets
> > > > > > (CYW5557x, CYW5551x, CYW5591x, CYW43022), and also for all future chipsets.
> > > > > Support for the CYW55572 can be easily added into the existing brcmfmac
> > > > > driver, I already posted a patch over a year ago [1], but it was blocked
> > > > > by an off-list email.
> > > >
> > > > > Frankly, I do not see any good reason why the brcmfmac driver shouldn't
> > > > > be extended when it is clearly easily doable. Adding new fork of the
> > > > > brcmfmac would only increase maintenance burden and prevent bugfixes
> > > > > from reaching the brcmfmac.
> > > > >
> > > > > [1] https://lore.kernel.org/all/20240909203133.74777-2-marex@denx.de/
> > > >
> > > > There are multiple reasons behind Infineon's proposal for this new INFFMAC
> > > > driver for its new-generation chips. Sharing a few here, and more info
> > > > is available in the v1 cover-letter [1]. For Example, the CYW5591x family
> > > > chipsets that is currently supported in this INFFMAC driver has a unique
> > > > Connected-MCU / Connectivtiy Processor (CP) Architecture [2], primarly
> > > > intended for IoT applications and it is completely different from any of
> > > > the legacy Broadcom architecture chipsets of Infineon supported currently
> > > > in upstream BRCMFMAC.
> > >
> > > This does not prevent them from being integrated in brcmfmac like many
> > > of the other already supported chips, there seems to be no technical
> > > reason here.
> >
> > I hope you would have got a chance to look into the elaborate info provided
> > in v1 cover-letter about the challenges that we faced with that approach.
> > In Infineon's new architecture CYW5591x family of chipsets coming with an
> > onboard FLASH Memory, it does not follow the traditional Device firmware
> > download sequence used by any of the legacy Broadcom chipsets and it would
> > be appropriate to use a dedicated driver for Infineon's chipsets which were
> > developed and intended mainly for IoT use-cases.
> >
> > Here it requires a Boot firmware download, and a host handshake with the
> > downloaded RAM boot firmware, followed by a CP Firmware image Download and
> > validation. Sharing here the sequence for coldboot image download to FLASH.
> >
> > Host Driver Device
> > ___________ ____________
> > | |
> > | Power UP and execute CP Firmware
> > | from FLASH if available
> > Attempt to enable SDIO F2 |
> > if fails, FLASH is empty, |
> > Need to Download Firmware |
> > | |
> > Wait for |
> > DFU_CP_D2H_MSG_BL_READY |
> > |<<======== DFU_CP_D2H_MSG_BL_READY <<============|
> > | |
> > Fetch Boot Firmware |
> > from Filesystem |
> > |======>> DFU_CP_H2D_MSG_BOOT_FWLOAD_START =====>>|
> > | |
> > |======>> Transfer Boot Firmware over SDIO =====>>|
> > | in multiple chunks |
> > | |
> > |======>> DFU_CP_H2D_MSG_BOOT_FWLOAD_DONE ======>>|
> > | Execute the downloaded
> > | RAM Bootloader
> > Wait for |
> > DFU_CP_D2H_MSG_BOOTFW_READY |
> > |<<========= DFU_CP_D2H_MSG_BOOTFW_READY <<=======|
> > | |
> > Fetch CP Firmware |
> > from Filesystem |
> > |=======>> Transfer CP Firmware over SDIO ======>>|
> > | in multiple chunks |
> > | Download CP Firmware
> > | to FLASH Memory
> > | |
> > |=======>> DFU_CP_H2D_MSG_BOOTFW_DATA_LOADED ====>|
> > | |
> > |=======>> DFU_CP_D2H_MSG_FW_VALIDAT_START ======>|
> > | |
> > Wait for Validate the CP Firmware
> > DFU_CP_D2H_MSG_FW_VALIDAT_DONE |
> > |<<======= DFU_CP_D2H_MSG_FW_VALIDAT_DONE <<======|
> > | |
> > | Execute the CP Firmware
> > Proceed with |
> > ctrl cmds to Device |
> > | |
> >
> > Here there is no need to redownload the Device Firmware from the Host
> > filesystem everyime the Host or Device goes through a power cycle. Also the
> > device is capable of fully operating in an offloaded mode even when the
> > host is in suspended state or even if fully powered off. This is critical
> > to save power for extended durations in IoT use cases which are often
> > battery operated.
>
> This seems like a technical detail of the firmware loading, which can be
> handled by the driver ?
If this is the base of your argument, then theoritically any vendor driver can
be added with the functionality to manage any other WLAN chip from another vendor.
A single monolithic wireless driver could potentially manage every vendor's chips,
without the need for any hardware specific abstraction. But, clearly this is not
how it is currently in wireless subsystem, because of multiple compelling reasons.
And given that Infineon's new architecture CYW5591x family of chipsets are completely
new, tailor made inhouse for IoT use-cases, with a different chipset architecture,
different bootflow, etc. it is not practical to add it into another vendor's driver
source which has a different flow for managing its devices.
> > > > The CYW5591x family chipsets has dedicated MCU Core
> > > > in addition to the WLAN core and an onboard FLASH memory for the Firmware.
> > >
> > > It seems all brcmfmac devices have a cortex-M core in them since a long
> > > time.
> >
> > We were intending to mention that CYW5591x Cortex-M33 core is dedicated to
> > function as a Co-Processor to the Host CPU/MCU and offload multiple wifi
> > and network operations if configured by the user before host goes to sleep.
> > You can refer the chipset block diagram in CYW55913/2/1 Product Brief [1]
> > The CYW5591x SoC Backplane interconnects are also different from any of the
> > legacy Broadcom chipsets.
>
> Maybe the driver can be forked when it turns out this functionality
> cannot be easily added into the existing driver ?
Our response remains the same, as given for your exact same question few weeks
back in this thread. We shared our explantion with the rationale behind our proposal.
> > > > And with respect to the support for the new-generation CYW5557x family of
> > > > Secure chipsets, that requires a Secure boot handshake with the Bootloader.
> > >
> > > It seems like the TRX firmware loading is trivial to add, and parts of
> > > it are already in the Linux kernel for other brcm components. It seems
> > > this TRX was used since old broadcom MIPS SoCs.
> >
> > No, your understanding needs a correction. Infineon's TRXSE and TRXS Device
> > Bootloader handshake and Firmware formats are quite different from the old
> > Broadcom TRX formats that you are mentioning here. Being two individual
> > WLAN vendors, the chipset internals, firmware formats, Device Bootloader
> > handshake cannot be expected to be the same. Yet another reason why it is
> > not practically feasible to use upstream BRCMFMAC for the new-generation
> > chipsets and new firmware releases from Infineon.
>
> Surely it is possible to do something like
>
> if (wlan_id_needs_trxse)
> load_trxse();
> else
> load_old_firmware_style();
>
> ?
>
> It seems this was already done in the two patches I submitted about a
> year ago, so this is clearly doable.
Along with TRXSE and TRXS firmwares, Infineon also uses a TRX format firmware,
which is also different with the TRX format of Broadcom's firmware. So still
need to differentiate between TRX firmwares because the WLAN vendor is different.
This is not a question about whether it is about doable, more than that, whether
it is practical.
> > > > Even if the enumeration and firmware download support for the CYW55572 is
> > > > somehow retro-fitted into the existing upstream BRCMFMAC driver, there are
> > > > multiple other features and aspects of the Driver-Device communication that
> > > > are unique to each WLAN vendor, which are not always practically feasible
> > > > to support in the same upstream driver.
> > >
> > > Why ?
> >
> > As mentioned before, various aspects of the Driver-Device communication are
> > unique to each WLAN vendor. And it is not practically feasible to confine
> > them into a common upstream driver, also not sustainable to maintain it that
> > way througout the lifetime of the hardware.
>
> The patches I submitted showed this was feasible, so I am not buying
> that argument. Can you give that a try instead ?
Our argument is on practical feasibility of doing so and its implications throughout
the lifetime of this new-generation device, when later tring to add other features and
when Infineon specific Driver-Device communiction flow evolve even more. This is quite
different from feasbility of making brcmfmac just detect the chip and load the firmware.
It is not sustainable to confine the support for a chips from multiple WLAN vendors
into the same upstream Linux driver.
Yes, we are aware of the couple patches that you submitted for upstream review. Before
that, initially those two patches were first released by Infineon downstream, only for
specific end use-cases and not actually intended for upstream.
> > > > Because currently BRCMFMAC driver
> > > > has a shared ownership with more than 3 WLAN vendor organizations and this
> > > > approach has its limitations.
> > >
> > > Yes, this means it is necessary to cooperate and coordinate with other
> > > people, on the mailing list.
> >
> > Infineon is committed to coordinate with other vendors in managing upstream
> > BRCMFMAC driver and continuing the support for its legacy chipsets that
> > still follows the legacy Broadcom architecture. Like for example, we have
> > added support for CYW54591-PCIe in upstream BRCMFMAC few months back [2],
> > because it has many things in common with other legacy Broadcom chips.
> > But the same does not applies for all the new-generation Infineon chipsets.
> >
> > > > For Example, the version of the PCIe and SDIO
> > > > BUS specific shared info in Device Memory is expected same from chipsets
> > > > from all vendors. There would be a complex need to maintain vendor specifc
> > > > as well as BUS specific Shared info version, vendor specific BUS Protocol
> > > > layers, vendor specific firmware event header OUIs (currently always expects
> > > > BRCM OUI even from other vendor chips) and even more.
> > >
> > > This sounds like code refactoring is necessary.
> > >
> > > > Confining different architecture chips from different WLAN vendors into the
> > > > same legacy BRCMFMAC driver codebase, may not be sustainable and could
> > > > potentially increase the maintainence effort and codebase complexity.
> > > > And not practically feasible to continue splitting this driver with more
> > > > vendor specific checks in the longer run. Since being different vendors,
> > > > each will only naturally diverge even more in the future with their chipset
> > > > Architecture, Driver-Device communication flow, etc. Infineon will continue
> > > > to support its legacy chipsets, already supported in the upstream BRCMFMAC.
> > > Maybe all the extra functionality can be added later, and the driver can
> > > be forked later, when it becomes clear that refactoring is not an option
> > > and it is becoming too difficult to maintain ?
> >
> > Refactoring the existing upstream BRCMFMAC driver for the new-architecture
> > chipsets developed by Infineon is not a practical option now because these
> > devices are fairly new. In the lifetime of these devices, the functionality
> > of the Devices and Driver interaction are only going to evolve even more.
> > Eventually, it would become more cumbersome to maintain as well as to avoid
> > regressions for different architecture chips from different WLAN vendors
> > if same upstream driver is used.
> >
> > We strongly believe that this is an appropriate time for thinking about a
> > proposal to proceed with a dedicated driver for the new-generation chips
> > developed individually by Infineon.
> >
> > > So far, it seems the current generation chips can be easily added to
> > > brcmfmac, even if the feature set would be limited. Adding them would
> >
> > We are not in the same page here. As mentioned earlier and as you might
> > know, there is infact much more to it than adding enumeration support for a
> > chip in a driver. Certainly not easy when eventually Infineon is required
> > to enable the end users with the actual capabilities of the chipset, also
> > Infineon has the responsibility to ensure driver compatibility with all the
> > newly shipped Device firmwares.
> >
> > > allow the maintainers to review such a smaller patchset and get at least
> > > some hardware support in, step by step, instead of this mega-patchset.
> >
> > We understood that review bandwidth is limited and have taken the feedback
> > received on v1 very seriously, so multiple features were already stripped
> > off in v2. Willing to skip even more functionality in the upcoming versions
> > and also ready to provide more information as needed to make the INFFMAC
> > driver review as much easy as possible.
>
> So, can you try and implement minimal TRXSE firmware loading and support
> for the CYW555xx for brcmfmac as an example, so it would be clear
> whether or not it can be added into the brcmfmac driver ?
No, as we mentioned earlier, just adding the enumeration & FW loading support
for the chipset in the brcmfmac driver and claiming that the device support is
available in the upstream brcmfmac driver would never be enough. Further, Infineon
has the responsibility to eventually add the actual features and capabilities of
this new-generation chip in the same upstream driver, so that the end users can
utilize the chipset to its fullest capability. It would not be practical to do this
later for the new generation Infineon chips, once the DEV ID is added into brcmfmac.
Because chipsets from multiple WLAN vendors are currently being managed by the same
driver, continuing to add more vendor specific checks for every driver functionality
is not sustainable.
The dedicated vendor WLAN drivers existing below the common cfg80211 & mac80211 layers
in the linux WLAN stack, helps to maintain the Device Hardware specific abstraction,
by taking care of the unique Device specific operation, Driver-Device Communication flow.
Confining multiple WLAN Vendor chipsets in same upstream driver, would only weaken the
abstraction even more.
We would like to emphasize that Infineon objective is not to be forever tied to the
existing common BRCMFMAC driver for its new generation chipsets, only because the
then Cypress (now Infineon) acquired few legacy chipsets (supported in brcmfmac) from
Broadcom nearly a decade ago in 2016.
> Oh ... and I also noticed, that infineon recently fully rewrote the
> history of the firmware repository [1], both the master branch history
> and the tags now point to different commit SHAs.
>
> [1] https://github.com/Infineon/ifx-linux-firmware
Ok, we will notify the respective folks internally.
Gokul
^ permalink raw reply
* Re: [PATCH v2] wifi: move action code from per-type frame structs
From: Pablo MARTIN-GOMEZ @ 2026-02-27 13:33 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
In-Reply-To: <7f71b9df99e286c695b9c159792e68b36a1dd54f.camel@sipsolutions.net>
On 27/02/2026 12:45, Johannes Berg wrote:
> On Fri, 2026-02-27 at 12:22 +0100, Pablo MARTIN-GOMEZ wrote:
>>
>>> +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
>>> @@ -755,16 +755,12 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
>>> switch (action_code) {
>>> case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
>>> /* See the layout of 'struct ieee80211_mgmt'. */
>>> - extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
>>> - sizeof(mgmt->u.action.category);
>>> + extra = IEEE80211_MIN_ACTION_SIZE(tdls_discover_resp) - 24;
>> Not sure that is clearer than:
>> ```
>> extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
>> sizeof(mgmt->u.action.category) +
>> sizeof(mgmt->u.action.action_code);
>> ```
>
> That's a bit of a corner case, but given the above code that uses 24
> explicitly, I tend to think it _is_ clearer, and it's definitely "safer
> to understand" - you know that you didn't miss anything...
>
> If someone wrote here
>
> extra = sizeof(mgmt->u.action.u.tdls_discover_resp);
>
> would you really see that it's wrong? I think it's very easy to miss.
> It's correct now, but the "- 24" definitely flags this as something
> special to check the context.
>
Reading the full function, and give that the 24 value is already
hardcoded in the above code, I guess you are right.
>>> addba_ext_data =
>>> ieee80211_retrieve_addba_ext_data(sta,
>>> - mgmt->u.action.u.addba_req.variable,
>>> + mgmt->u.action.addba_req.variable,
>>> len -
>>> offsetof(typeof(*mgmt),
>>> - u.action.u.addba_req.variable),
>>> + u.action.addba_req.variable),
>> `offsetof(typeof(*mgmt), u.action.u.type.variable` is equivalent to
>> `IEEE80211_MIN_ACTION_SIZE(type)`, isn't clearer to use it?
>
> I guess we could. I was mostly getting it to compile at some point :)
>
>>> @@ -949,8 +945,8 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
>>> }
>>> rcu_read_unlock();
>>>
>>> - baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
>>> - elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
>>> + baselen = mgmt->u.action.mesh_action.variable - (u8 *)mgmt;
>> Another equivalent to `IEEE80211_MIN_ACTION_SIZE(type)`
>
> type?
A copy-paste error, I wanted to say `IEEE80211_MIN_ACTION_SIZE(mesh_action)`
>
>>> + elems = ieee802_11_parse_elems(mgmt->u.action.mesh_action.variable,
>>> len - baselen,
>
>>> - dialog_token = mgmt->u.action.u.ttlm_req.dialog_token;
>>> - ies_len = len - offsetof(struct ieee80211_mgmt,
>>> - u.action.u.ttlm_req.variable);
>>> - elems = ieee802_11_parse_elems(mgmt->u.action.u.ttlm_req.variable,
>>> + dialog_token = mgmt->u.action.ttlm_req.dialog_token;
>>> + ies_len = len - IEEE80211_MIN_ACTION_SIZE(ttlm_req);
>> Here you did it :)
>
> Guess it didn't really matter that much. Or I stumbled over this one at
> a different time, or something :)
>
> I don't think any of this is worth changing right now. Feel free to send
> extra patches.
Fair enough. I'll send the extra patches. Otherwise the change looks
good to me.
>
> johannes
Pablo MG
^ permalink raw reply
* Re: [PATCH v2] wifi: move action code from per-type frame structs
From: Johannes Berg @ 2026-02-27 11:45 UTC (permalink / raw)
To: Pablo MARTIN-GOMEZ, linux-wireless
In-Reply-To: <418d3666-6bd2-4ea7-8e1b-4d49dda255a2@freebox.fr>
On Fri, 2026-02-27 at 12:22 +0100, Pablo MARTIN-GOMEZ wrote:
>
> > +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
> > @@ -755,16 +755,12 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
> > switch (action_code) {
> > case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
> > /* See the layout of 'struct ieee80211_mgmt'. */
> > - extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
> > - sizeof(mgmt->u.action.category);
> > + extra = IEEE80211_MIN_ACTION_SIZE(tdls_discover_resp) - 24;
> Not sure that is clearer than:
> ```
> extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
> sizeof(mgmt->u.action.category) +
> sizeof(mgmt->u.action.action_code);
> ```
That's a bit of a corner case, but given the above code that uses 24
explicitly, I tend to think it _is_ clearer, and it's definitely "safer
to understand" - you know that you didn't miss anything...
If someone wrote here
extra = sizeof(mgmt->u.action.u.tdls_discover_resp);
would you really see that it's wrong? I think it's very easy to miss.
It's correct now, but the "- 24" definitely flags this as something
special to check the context.
> > addba_ext_data =
> > ieee80211_retrieve_addba_ext_data(sta,
> > - mgmt->u.action.u.addba_req.variable,
> > + mgmt->u.action.addba_req.variable,
> > len -
> > offsetof(typeof(*mgmt),
> > - u.action.u.addba_req.variable),
> > + u.action.addba_req.variable),
> `offsetof(typeof(*mgmt), u.action.u.type.variable` is equivalent to
> `IEEE80211_MIN_ACTION_SIZE(type)`, isn't clearer to use it?
I guess we could. I was mostly getting it to compile at some point :)
> > @@ -949,8 +945,8 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
> > }
> > rcu_read_unlock();
> >
> > - baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
> > - elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
> > + baselen = mgmt->u.action.mesh_action.variable - (u8 *)mgmt;
> Another equivalent to `IEEE80211_MIN_ACTION_SIZE(type)`
type?
> > + elems = ieee802_11_parse_elems(mgmt->u.action.mesh_action.variable,
> > len - baselen,
> > - dialog_token = mgmt->u.action.u.ttlm_req.dialog_token;
> > - ies_len = len - offsetof(struct ieee80211_mgmt,
> > - u.action.u.ttlm_req.variable);
> > - elems = ieee802_11_parse_elems(mgmt->u.action.u.ttlm_req.variable,
> > + dialog_token = mgmt->u.action.ttlm_req.dialog_token;
> > + ies_len = len - IEEE80211_MIN_ACTION_SIZE(ttlm_req);
> Here you did it :)
Guess it didn't really matter that much. Or I stumbled over this one at
a different time, or something :)
I don't think any of this is worth changing right now. Feel free to send
extra patches.
johannes
^ permalink raw reply
* Re: [PATCH v2] wifi: move action code from per-type frame structs
From: Pablo MARTIN-GOMEZ @ 2026-02-27 11:22 UTC (permalink / raw)
To: Johannes Berg, linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260226183607.67e71846b59e.I9a24328e3ffcaae179466a935f1c3345029f9961@changeid>
Hello,
On 26/02/2026 18:36, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> The action code actually serves to identify the type of action
> frame, so it really isn't part of the per-type structure. Pull
> it out and have it in the general action frame format.
>
> In theory, whether or not the action code is present in this
> way is up to each category, but all categories that are defined
> right now all have that value.
>
> While at it, and since this change requires changing all users,
> remove the 'u' and make it an anonymous union in this case, so
> that all code using this changes.
>
> Change IEEE80211_MIN_ACTION_SIZE to take an argument which says
> how much of the frame is needed, e.g. category, action_code or
> the specific frame type that's defined in the union. Again this
> also ensures that all code is updated.
>
> In some cases, fix bugs where the SKB length was checked after
> having accessed beyond the checked length, in particular in FTM
> code, e.g. ieee80211_is_ftm().
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
> v2: fix public action frame handling
> ---
> drivers/net/wireless/ath/ath11k/mac.c | 4 +-
> drivers/net/wireless/ath/ath12k/mac.c | 4 +-
> drivers/net/wireless/ath/ath12k/wifi7/hw.c | 2 +-
> .../wireless/intel/iwlwifi/mld/time_sync.c | 6 +-
> .../intel/iwlwifi/mvm/ftm-initiator.c | 7 +-
> .../wireless/intel/iwlwifi/mvm/time-sync.c | 6 +-
> drivers/net/wireless/marvell/mwifiex/tdls.c | 12 +-
> drivers/net/wireless/marvell/mwl8k.c | 4 +-
> .../wireless/mediatek/mt76/mt76_connac_mac.c | 4 +-
> .../net/wireless/mediatek/mt76/mt7925/mac.c | 2 +-
> .../net/wireless/mediatek/mt76/mt7996/mac.c | 2 +-
> drivers/net/wireless/realtek/rtl8xxxu/core.c | 14 +-
> drivers/net/wireless/realtek/rtlwifi/base.c | 28 ++--
> drivers/net/wireless/realtek/rtlwifi/pci.c | 2 +-
> include/linux/ieee80211.h | 83 +++++-------
> net/mac80211/agg-rx.c | 27 ++--
> net/mac80211/agg-tx.c | 28 ++--
> net/mac80211/eht.c | 21 ++-
> net/mac80211/ht.c | 31 ++---
> net/mac80211/ibss.c | 18 +--
> net/mac80211/iface.c | 18 +--
> net/mac80211/mesh.c | 14 +-
> net/mac80211/mesh_hwmp.c | 20 ++-
> net/mac80211/mesh_plink.c | 21 ++-
> net/mac80211/mlme.c | 82 +++++-------
> net/mac80211/rx.c | 123 ++++++++----------
> net/mac80211/s1g.c | 28 ++--
> net/mac80211/spectmgmt.c | 31 ++---
> net/mac80211/tdls.c | 29 ++---
> net/mac80211/util.c | 5 +-
> net/mac80211/vht.c | 10 +-
> 31 files changed, 301 insertions(+), 385 deletions(-)
>
[...]
> diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
> index 77a9a6de636d..95fd5a924226 100644
> --- a/drivers/net/wireless/marvell/mwifiex/tdls.c
> +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
> @@ -755,16 +755,12 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
> switch (action_code) {
> case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
> /* See the layout of 'struct ieee80211_mgmt'. */
> - extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
> - sizeof(mgmt->u.action.category);
> + extra = IEEE80211_MIN_ACTION_SIZE(tdls_discover_resp) - 24;
Not sure that is clearer than:
```
extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
sizeof(mgmt->u.action.category) +
sizeof(mgmt->u.action.action_code);
```
> skb_put(skb, extra);
> mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
> - mgmt->u.action.u.tdls_discover_resp.action_code =
> - WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
> - mgmt->u.action.u.tdls_discover_resp.dialog_token =
> - dialog_token;
> - mgmt->u.action.u.tdls_discover_resp.capability =
> - cpu_to_le16(capab);
> + mgmt->u.action.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
> + mgmt->u.action.tdls_discover_resp.dialog_token = dialog_token;
> + mgmt->u.action.tdls_discover_resp.capability = cpu_to_le16(capab);
> /* move back for addr4 */
> memmove(pos + ETH_ALEN, &mgmt->u.action, extra);
> /* init address 4 */
[...]
> @@ -477,22 +478,22 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
> u8 dialog_token, addba_ext_data;
>
> /* extract session parameters from addba request frame */
> - dialog_token = mgmt->u.action.u.addba_req.dialog_token;
> - timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
> + dialog_token = mgmt->u.action.addba_req.dialog_token;
> + timeout = le16_to_cpu(mgmt->u.action.addba_req.timeout);
> start_seq_num =
> - le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
> + le16_to_cpu(mgmt->u.action.addba_req.start_seq_num) >> 4;
>
> - capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
> + capab = le16_to_cpu(mgmt->u.action.addba_req.capab);
> ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
> tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
> buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
>
> addba_ext_data =
> ieee80211_retrieve_addba_ext_data(sta,
> - mgmt->u.action.u.addba_req.variable,
> + mgmt->u.action.addba_req.variable,
> len -
> offsetof(typeof(*mgmt),
> - u.action.u.addba_req.variable),
> + u.action.addba_req.variable),
`offsetof(typeof(*mgmt), u.action.u.type.variable` is equivalent to
`IEEE80211_MIN_ACTION_SIZE(type)`, isn't clearer to use it?
> &buf_size);
>
> __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
> diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
> index d981b0fc57bf..de68f7da6f39 100644
> --- a/net/mac80211/agg-tx.c
> +++ b/net/mac80211/agg-tx.c
> @@ -9,7 +9,7 @@
> * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
> * Copyright 2007-2010, Intel Corporation
> * Copyright(c) 2015-2017 Intel Deutschland GmbH
> - * Copyright (C) 2018 - 2024 Intel Corporation
> + * Copyright (C) 2018-2026 Intel Corporation
> */
>
> #include <linux/ieee80211.h>
> @@ -68,7 +68,7 @@ static void ieee80211_send_addba_request(struct sta_info *sta, u16 tid,
> struct ieee80211_mgmt *mgmt;
> u16 capab;
>
> - skb = dev_alloc_skb(sizeof(*mgmt) +
> + skb = dev_alloc_skb(IEEE80211_MIN_ACTION_SIZE(addba_req) +
> 2 + sizeof(struct ieee80211_addba_ext_ie) +
> local->hw.extra_tx_headroom);
> if (!skb)
> @@ -77,21 +77,21 @@ static void ieee80211_send_addba_request(struct sta_info *sta, u16 tid,
> skb_reserve(skb, local->hw.extra_tx_headroom);
> mgmt = ieee80211_mgmt_ba(skb, sta->sta.addr, sdata);
>
> - skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
> + skb_put(skb, 2 + sizeof(mgmt->u.action.addba_req));
>
> mgmt->u.action.category = WLAN_CATEGORY_BACK;
> - mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
> + mgmt->u.action.action_code = WLAN_ACTION_ADDBA_REQ;
>
> - mgmt->u.action.u.addba_req.dialog_token = dialog_token;
> + mgmt->u.action.addba_req.dialog_token = dialog_token;
> capab = IEEE80211_ADDBA_PARAM_AMSDU_MASK;
> capab |= IEEE80211_ADDBA_PARAM_POLICY_MASK;
> capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
> capab |= u16_encode_bits(agg_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
>
> - mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
> + mgmt->u.action.addba_req.capab = cpu_to_le16(capab);
>
> - mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
> - mgmt->u.action.u.addba_req.start_seq_num =
> + mgmt->u.action.addba_req.timeout = cpu_to_le16(timeout);
> + mgmt->u.action.addba_req.start_seq_num =
> cpu_to_le16(start_seq_num << 4);
>
> if (sta->sta.deflink.he_cap.has_he)
> @@ -978,15 +978,15 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
>
> lockdep_assert_wiphy(sta->local->hw.wiphy);
>
> - capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
> + capab = le16_to_cpu(mgmt->u.action.addba_resp.capab);
> amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK;
> tid = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_TID_MASK);
> buf_size = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
>
> ieee80211_retrieve_addba_ext_data(sta,
> - mgmt->u.action.u.addba_resp.variable,
> + mgmt->u.action.addba_resp.variable,
> len - offsetof(typeof(*mgmt),
> - u.action.u.addba_resp.variable),
> + u.action.addba_resp.variable),
Ditto
> &buf_size);
>
> buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes);
[...]
> @@ -1613,12 +1605,12 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
> case WLAN_CATEGORY_SPECTRUM_MGMT:
> ies_len = skb->len -
> offsetof(struct ieee80211_mgmt,
> - u.action.u.chan_switch.variable);
> + u.action.chan_switch.variable);
Ditto
>
> if (ies_len < 0)
> break;
>
> - elems = ieee802_11_parse_elems(mgmt->u.action.u.chan_switch.variable,
> + elems = ieee802_11_parse_elems(mgmt->u.action.chan_switch.variable,
> ies_len,
> IEEE80211_FTYPE_MGMT |
> IEEE80211_STYPE_ACTION,
> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
> index 676b2a43c9f2..2e391cec73a0 100644
> --- a/net/mac80211/iface.c
> +++ b/net/mac80211/iface.c
> @@ -1579,7 +1579,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
>
> sta = sta_info_get_bss(sdata, mgmt->sa);
> if (sta) {
> - switch (mgmt->u.action.u.addba_req.action_code) {
> + switch (mgmt->u.action.action_code) {
> case WLAN_ACTION_ADDBA_REQ:
> ieee80211_process_addba_request(local, sta,
> mgmt, len);
> @@ -1599,9 +1599,9 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
> }
> } else if (ieee80211_is_action(mgmt->frame_control) &&
> mgmt->u.action.category == WLAN_CATEGORY_HT) {
> - switch (mgmt->u.action.u.ht_smps.action) {
> + switch (mgmt->u.action.action_code) {
> case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
> - u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
> + u8 chanwidth = mgmt->u.action.ht_notify_cw.chanwidth;
> struct ieee80211_rx_status *status;
> struct link_sta_info *link_sta;
> struct sta_info *sta;
> @@ -1628,7 +1628,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
> }
> } else if (ieee80211_is_action(mgmt->frame_control) &&
> mgmt->u.action.category == WLAN_CATEGORY_VHT) {
> - switch (mgmt->u.action.u.vht_group_notif.action_code) {
> + switch (mgmt->u.action.action_code) {
> case WLAN_VHT_ACTION_OPMODE_NOTIF: {
> struct ieee80211_rx_status *status;
> enum nl80211_band band;
> @@ -1637,7 +1637,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
>
> status = IEEE80211_SKB_RXCB(skb);
> band = status->band;
> - opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
> + opmode = mgmt->u.action.vht_opmode_notif.operating_mode;
>
> sta = sta_info_get_bss(sdata, mgmt->sa);
>
> @@ -1658,7 +1658,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
> }
> } else if (ieee80211_is_action(mgmt->frame_control) &&
> mgmt->u.action.category == WLAN_CATEGORY_S1G) {
> - switch (mgmt->u.action.u.s1g.action_code) {
> + switch (mgmt->u.action.action_code) {
> case WLAN_S1G_TWT_TEARDOWN:
> case WLAN_S1G_TWT_SETUP:
> ieee80211_s1g_rx_twt_action(sdata, skb);
> @@ -1669,7 +1669,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
> } else if (ieee80211_is_action(mgmt->frame_control) &&
> mgmt->u.action.category == WLAN_CATEGORY_PROTECTED_EHT) {
> if (sdata->vif.type == NL80211_IFTYPE_AP) {
> - switch (mgmt->u.action.u.eml_omn.action_code) {
> + switch (mgmt->u.action.action_code) {
> case WLAN_PROTECTED_EHT_ACTION_EML_OP_MODE_NOTIF:
> ieee80211_rx_eml_op_mode_notif(sdata, skb);
> break;
> @@ -1677,7 +1677,7 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
> break;
> }
> } else if (sdata->vif.type == NL80211_IFTYPE_STATION) {
> - switch (mgmt->u.action.u.ttlm_req.action_code) {
> + switch (mgmt->u.action.action_code) {
> case WLAN_PROTECTED_EHT_ACTION_TTLM_REQ:
> ieee80211_process_neg_ttlm_req(sdata, mgmt,
> skb->len);
> @@ -1765,7 +1765,7 @@ static void ieee80211_iface_process_status(struct ieee80211_sub_if_data *sdata,
>
> if (ieee80211_is_action(mgmt->frame_control) &&
> mgmt->u.action.category == WLAN_CATEGORY_S1G) {
> - switch (mgmt->u.action.u.s1g.action_code) {
> + switch (mgmt->u.action.action_code) {
> case WLAN_S1G_TWT_TEARDOWN:
> case WLAN_S1G_TWT_SETUP:
> ieee80211_s1g_status_twt_action(sdata, skb);
> diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
> index 68901f1def0d..ccbf33fb23bd 100644
> --- a/net/mac80211/mesh.c
> +++ b/net/mac80211/mesh.c
> @@ -1,7 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> * Copyright (c) 2008, 2009 open80211s Ltd.
> - * Copyright (C) 2018 - 2025 Intel Corporation
> + * Copyright (C) 2018-2026 Intel Corporation
> * Authors: Luis Carlos Cobo <luisca@cozybit.com>
> * Javier Cardona <javier@cozybit.com>
> */
> @@ -19,8 +19,7 @@ static struct kmem_cache *rm_cache;
>
> bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
> {
> - return (mgmt->u.action.u.mesh_action.action_code ==
> - WLAN_MESH_ACTION_HWMP_PATH_SELECTION);
> + return mgmt->u.action.action_code == WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
> }
>
> void ieee80211s_init(void)
> @@ -1619,13 +1618,12 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
> size_t baselen;
> u8 *pos;
>
> - if (mgmt->u.action.u.measurement.action_code !=
> - WLAN_ACTION_SPCT_CHL_SWITCH)
> + if (mgmt->u.action.action_code != WLAN_ACTION_SPCT_CHL_SWITCH)
> return;
>
> - pos = mgmt->u.action.u.chan_switch.variable;
> + pos = mgmt->u.action.chan_switch.variable;
> baselen = offsetof(struct ieee80211_mgmt,
> - u.action.u.chan_switch.variable);
> + u.action.chan_switch.variable);
Ditto
> elems = ieee802_11_parse_elems(pos, len - baselen,
> IEEE80211_FTYPE_MGMT |
> IEEE80211_STYPE_ACTION,
> @@ -1668,7 +1666,7 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
> {
> switch (mgmt->u.action.category) {
> case WLAN_CATEGORY_SELF_PROTECTED:
> - switch (mgmt->u.action.u.self_prot.action_code) {
> + switch (mgmt->u.action.action_code) {
> case WLAN_SP_MESH_PEERING_OPEN:
> case WLAN_SP_MESH_PEERING_CLOSE:
> case WLAN_SP_MESH_PEERING_CONFIRM:
> diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
> index a41b57bd11ff..dad311e0833a 100644
> --- a/net/mac80211/mesh_hwmp.c
> +++ b/net/mac80211/mesh_hwmp.c
> @@ -1,7 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> * Copyright (c) 2008, 2009 open80211s Ltd.
> - * Copyright (C) 2019, 2021-2023, 2025 Intel Corporation
> + * Copyright (C) 2019, 2021-2023, 2025-2026 Intel Corporation
> * Author: Luis Carlos Cobo <luisca@cozybit.com>
> */
>
> @@ -105,12 +105,11 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
> u32 lifetime, u32 metric, u32 preq_id,
> struct ieee80211_sub_if_data *sdata)
> {
> + int hdr_len = IEEE80211_MIN_ACTION_SIZE(mesh_action);
> struct ieee80211_local *local = sdata->local;
> struct sk_buff *skb;
> struct ieee80211_mgmt *mgmt;
> u8 *pos, ie_len;
> - int hdr_len = offsetofend(struct ieee80211_mgmt,
> - u.action.u.mesh_action);
>
> skb = dev_alloc_skb(local->tx_headroom +
> hdr_len +
> @@ -127,8 +126,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
> /* BSSID == SA */
> memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
> mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
> - mgmt->u.action.u.mesh_action.action_code =
> - WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
> + mgmt->u.action.action_code = WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
>
> switch (action) {
> case MPATH_PREQ:
> @@ -237,13 +235,12 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
> u8 ttl, const u8 *target, u32 target_sn,
> u16 target_rcode, const u8 *ra)
> {
> + int hdr_len = IEEE80211_MIN_ACTION_SIZE(mesh_action);
> struct ieee80211_local *local = sdata->local;
> struct sk_buff *skb;
> struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
> struct ieee80211_mgmt *mgmt;
> u8 *pos, ie_len;
> - int hdr_len = offsetofend(struct ieee80211_mgmt,
> - u.action.u.mesh_action);
>
> if (time_before(jiffies, ifmsh->next_perr))
> return -EAGAIN;
> @@ -265,8 +262,7 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
> /* BSSID == SA */
> memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
> mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
> - mgmt->u.action.u.mesh_action.action_code =
> - WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
> + mgmt->u.action.action_code = WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
> ie_len = 15;
> pos = skb_put(skb, 2 + ie_len);
> *pos++ = WLAN_EID_PERR;
> @@ -938,7 +934,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
> struct sta_info *sta;
>
> /* need action_code */
> - if (len < IEEE80211_MIN_ACTION_SIZE + 1)
> + if (len < IEEE80211_MIN_ACTION_SIZE(mesh_action))
> return;
>
> rcu_read_lock();
> @@ -949,8 +945,8 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
> }
> rcu_read_unlock();
>
> - baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
> - elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
> + baselen = mgmt->u.action.mesh_action.variable - (u8 *)mgmt;
Another equivalent to `IEEE80211_MIN_ACTION_SIZE(type)`
> + elems = ieee802_11_parse_elems(mgmt->u.action.mesh_action.variable,
> len - baselen,
> IEEE80211_FTYPE_MGMT |
> IEEE80211_STYPE_ACTION,
> diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
> index 04c931cd2063..7d823a55636f 100644
> --- a/net/mac80211/mesh_plink.c
> +++ b/net/mac80211/mesh_plink.c
> @@ -1,7 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> * Copyright (c) 2008, 2009 open80211s Ltd.
> - * Copyright (C) 2019, 2021-2025 Intel Corporation
> + * Copyright (C) 2019, 2021-2026 Intel Corporation
> * Author: Luis Carlos Cobo <luisca@cozybit.com>
> */
> #include <linux/gfp.h>
> @@ -13,7 +13,7 @@
> #include "rate.h"
> #include "mesh.h"
>
> -#define PLINK_CNF_AID(mgmt) ((mgmt)->u.action.u.self_prot.variable + 2)
> +#define PLINK_CNF_AID(mgmt) ((mgmt)->u.action.self_prot.variable + 2)
> #define PLINK_GET_LLID(p) (p + 2)
> #define PLINK_GET_PLID(p) (p + 4)
>
> @@ -215,6 +215,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
> enum ieee80211_self_protected_actioncode action,
> u8 *da, u16 llid, u16 plid, u16 reason)
> {
> + int hdr_len = IEEE80211_MIN_ACTION_SIZE(self_prot);
> struct ieee80211_local *local = sdata->local;
> struct sk_buff *skb;
> struct ieee80211_tx_info *info;
> @@ -223,7 +224,6 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
> u16 peering_proto = 0;
> u8 *pos, ie_len = 4;
> u8 ie_len_he_cap, ie_len_eht_cap;
> - int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot);
> int err = -ENOMEM;
>
> ie_len_he_cap = ieee80211_ie_len_he_cap(sdata);
> @@ -260,7 +260,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
> memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
> memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
> mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
> - mgmt->u.action.u.self_prot.action_code = action;
> + mgmt->u.action.action_code = action;
>
> if (action != WLAN_SP_MESH_PEERING_CLOSE) {
> struct ieee80211_supported_band *sband;
> @@ -1141,7 +1141,7 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
> return;
> }
>
> - ftype = mgmt->u.action.u.self_prot.action_code;
> + ftype = mgmt->u.action.action_code;
> if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
> (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
> (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
> @@ -1224,8 +1224,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
> size_t baselen;
> u8 *baseaddr;
>
> - /* need action_code, aux */
> - if (len < IEEE80211_MIN_ACTION_SIZE + 3)
> + /* need aux */
> + if (len < IEEE80211_MIN_ACTION_SIZE(self_prot) + 1)
> return;
>
> if (sdata->u.mesh.user_mpm)
> @@ -1238,10 +1238,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
> return;
> }
>
> - baseaddr = mgmt->u.action.u.self_prot.variable;
> - baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
> - if (mgmt->u.action.u.self_prot.action_code ==
> - WLAN_SP_MESH_PEERING_CONFIRM) {
> + baseaddr = mgmt->u.action.self_prot.variable;
> + baselen = mgmt->u.action.self_prot.variable - (u8 *)mgmt;
Ditto
> + if (mgmt->u.action.action_code == WLAN_SP_MESH_PEERING_CONFIRM) {
> baseaddr += 4;
> baselen += 4;
>
> diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> index e83582b2c377..995855d49822 100644
> --- a/net/mac80211/mlme.c
> +++ b/net/mac80211/mlme.c
> @@ -7897,7 +7897,7 @@ ieee80211_send_neg_ttlm_req(struct ieee80211_sub_if_data *sdata,
> struct ieee80211_local *local = sdata->local;
> struct ieee80211_mgmt *mgmt;
> struct sk_buff *skb;
> - int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.ttlm_req);
> + int hdr_len = IEEE80211_MIN_ACTION_SIZE(ttlm_req);
> int ttlm_max_len = 2 + 1 + sizeof(struct ieee80211_ttlm_elem) + 1 +
> 2 * 2 * IEEE80211_TTLM_NUM_TIDS;
>
> @@ -7914,9 +7914,8 @@ ieee80211_send_neg_ttlm_req(struct ieee80211_sub_if_data *sdata,
> memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
>
> mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
> - mgmt->u.action.u.ttlm_req.action_code =
> - WLAN_PROTECTED_EHT_ACTION_TTLM_REQ;
> - mgmt->u.action.u.ttlm_req.dialog_token = dialog_token;
> + mgmt->u.action.action_code = WLAN_PROTECTED_EHT_ACTION_TTLM_REQ;
> + mgmt->u.action.ttlm_req.dialog_token = dialog_token;
> ieee80211_neg_ttlm_add_suggested_map(skb, neg_ttlm);
> ieee80211_tx_skb(sdata, skb);
> }
> @@ -7966,7 +7965,7 @@ ieee80211_send_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
> struct ieee80211_local *local = sdata->local;
> struct ieee80211_mgmt *mgmt;
> struct sk_buff *skb;
> - int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.ttlm_res);
> + int hdr_len = IEEE80211_MIN_ACTION_SIZE(ttlm_res);
> int ttlm_max_len = 2 + 1 + sizeof(struct ieee80211_ttlm_elem) + 1 +
> 2 * 2 * IEEE80211_TTLM_NUM_TIDS;
> u16 status_code;
> @@ -7984,9 +7983,8 @@ ieee80211_send_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
> memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
>
> mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
> - mgmt->u.action.u.ttlm_res.action_code =
> - WLAN_PROTECTED_EHT_ACTION_TTLM_RES;
> - mgmt->u.action.u.ttlm_res.dialog_token = dialog_token;
> + mgmt->u.action.action_code = WLAN_PROTECTED_EHT_ACTION_TTLM_RES;
> + mgmt->u.action.ttlm_res.dialog_token = dialog_token;
> switch (ttlm_res) {
> default:
> WARN_ON(1);
> @@ -8003,7 +8001,7 @@ ieee80211_send_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
> break;
> }
>
> - mgmt->u.action.u.ttlm_res.status_code = cpu_to_le16(status_code);
> + mgmt->u.action.ttlm_res.status_code = cpu_to_le16(status_code);
> ieee80211_tx_skb(sdata, skb);
> }
>
> @@ -8103,10 +8101,9 @@ void ieee80211_process_neg_ttlm_req(struct ieee80211_sub_if_data *sdata,
> if (!ieee80211_vif_is_mld(&sdata->vif))
> return;
>
> - dialog_token = mgmt->u.action.u.ttlm_req.dialog_token;
> - ies_len = len - offsetof(struct ieee80211_mgmt,
> - u.action.u.ttlm_req.variable);
> - elems = ieee802_11_parse_elems(mgmt->u.action.u.ttlm_req.variable,
> + dialog_token = mgmt->u.action.ttlm_req.dialog_token;
> + ies_len = len - IEEE80211_MIN_ACTION_SIZE(ttlm_req);
Here you did it :)
> + elems = ieee802_11_parse_elems(mgmt->u.action.ttlm_req.variable,
> ies_len,
> IEEE80211_FTYPE_MGMT |
> IEEE80211_STYPE_ACTION,
> @@ -8157,8 +8154,7 @@ void ieee80211_process_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
> struct ieee80211_mgmt *mgmt, size_t len)
> {
> if (!ieee80211_vif_is_mld(&sdata->vif) ||
> - mgmt->u.action.u.ttlm_req.dialog_token !=
> - sdata->u.mgd.dialog_token_alloc)
> + mgmt->u.action.ttlm_res.dialog_token != sdata->u.mgd.dialog_token_alloc)
> return;
>
> wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
> @@ -8172,7 +8168,7 @@ void ieee80211_process_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
> * This can be better implemented in the future, to handle request
> * rejections.
> */
> - if (le16_to_cpu(mgmt->u.action.u.ttlm_res.status_code) != WLAN_STATUS_SUCCESS)
> + if (le16_to_cpu(mgmt->u.action.ttlm_res.status_code) != WLAN_STATUS_SUCCESS)
> __ieee80211_disconnect(sdata);
> }
>
> @@ -8205,12 +8201,11 @@ static void ieee80211_teardown_ttlm_work(struct wiphy *wiphy,
>
> void ieee80211_send_teardown_neg_ttlm(struct ieee80211_vif *vif)
> {
> + int frame_len = IEEE80211_MIN_ACTION_SIZE(ttlm_tear_down);
> struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> struct ieee80211_local *local = sdata->local;
> struct ieee80211_mgmt *mgmt;
> struct sk_buff *skb;
> - int frame_len = offsetofend(struct ieee80211_mgmt,
> - u.action.u.ttlm_tear_down);
> struct ieee80211_tx_info *info;
>
> skb = dev_alloc_skb(local->hw.extra_tx_headroom + frame_len);
> @@ -8226,8 +8221,7 @@ void ieee80211_send_teardown_neg_ttlm(struct ieee80211_vif *vif)
> memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
>
> mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
> - mgmt->u.action.u.ttlm_tear_down.action_code =
> - WLAN_PROTECTED_EHT_ACTION_TTLM_TEARDOWN;
> + mgmt->u.action.action_code = WLAN_PROTECTED_EHT_ACTION_TTLM_TEARDOWN;
>
> info = IEEE80211_SKB_CB(skb);
> info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
> @@ -8310,13 +8304,13 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
> case WLAN_CATEGORY_SPECTRUM_MGMT:
> ies_len = skb->len -
> offsetof(struct ieee80211_mgmt,
> - u.action.u.chan_switch.variable);
> + u.action.chan_switch.variable);
Ditto
>
> if (ies_len < 0)
> break;
>
> /* CSA IE cannot be overridden, no need for BSSID */
> - elems = ieee802_11_parse_elems(mgmt->u.action.u.chan_switch.variable,
> + elems = ieee802_11_parse_elems(mgmt->u.action.chan_switch.variable,
> ies_len,
> IEEE80211_FTYPE_MGMT |
> IEEE80211_STYPE_ACTION,
> @@ -8338,7 +8332,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
> case WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION:
> ies_len = skb->len -
> offsetof(struct ieee80211_mgmt,
> - u.action.u.ext_chan_switch.variable);
> + u.action.ext_chan_switch.variable);
Ditto
>
> if (ies_len < 0)
> break;
> @@ -8347,7 +8341,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
> * extended CSA IE can't be overridden, no need for
> * BSSID
> */
> - elems = ieee802_11_parse_elems(mgmt->u.action.u.ext_chan_switch.variable,
> + elems = ieee802_11_parse_elems(mgmt->u.action.ext_chan_switch.variable,
> ies_len,
> IEEE80211_FTYPE_MGMT |
> IEEE80211_STYPE_ACTION,
> @@ -8364,7 +8358,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
>
> /* for the handling code pretend it was an IE */
> elems->ext_chansw_ie =
> - &mgmt->u.action.u.ext_chan_switch.data;
> + &mgmt->u.action.ext_chan_switch.data;
>
> ieee80211_sta_process_chanswitch(link,
> rx_status->mactime,
> @@ -10356,25 +10350,25 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata,
> u8 *pos;
>
> if (!ieee80211_vif_is_mld(&sdata->vif) ||
> - len < offsetofend(typeof(*mgmt), u.action.u.ml_reconf_resp) ||
> - mgmt->u.action.u.ml_reconf_resp.dialog_token !=
> - sdata->u.mgd.reconf.dialog_token ||
> + len < IEEE80211_MIN_ACTION_SIZE(ml_reconf_resp) ||
> + mgmt->u.action.ml_reconf_resp.dialog_token !=
> + sdata->u.mgd.reconf.dialog_token ||
> !sta_changed_links)
> return;
>
> - pos = mgmt->u.action.u.ml_reconf_resp.variable;
> - len -= offsetofend(typeof(*mgmt), u.action.u.ml_reconf_resp);
> + pos = mgmt->u.action.ml_reconf_resp.variable;
> + len -= offsetofend(typeof(*mgmt), u.action.ml_reconf_resp);
`len -= IEEE80211_MIN_ACTION_SIZE(ml_reconf_resp);`
[...]
Pablo MG
^ permalink raw reply
* Re: [syzbot] [libertas?] INFO: task hung in lbs_remove_card
From: syzbot @ 2026-02-27 11:22 UTC (permalink / raw)
To: libertas-dev, linux-kernel, linux-usb, linux-wireless, netdev,
syzkaller-bugs
In-Reply-To: <689daf88.050a0220.2d37a5.0001.GAE@google.com>
syzbot has found a reproducer for the following issue on:
HEAD commit: bb375c251ab4 dt-bindings: usb: st,st-ohci-300x: convert to..
git tree: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
console output: https://syzkaller.appspot.com/x/log.txt?x=1141755a580000
kernel config: https://syzkaller.appspot.com/x/.config?x=f1500201919951cc
dashboard link: https://syzkaller.appspot.com/bug?extid=c99d17aa44dbdba16ad2
compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1191555a580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=114a15c6580000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/2475c3172471/disk-bb375c25.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/30449aa672dd/vmlinux-bb375c25.xz
kernel image: https://storage.googleapis.com/syzbot-assets/46d3937d1c16/bzImage-bb375c25.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+c99d17aa44dbdba16ad2@syzkaller.appspotmail.com
INFO: task kworker/0:1:10 blocked for more than 143 seconds.
Not tainted syzkaller #0
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
task:kworker/0:1 state:D stack:26840 pid:10 tgid:10 ppid:2 task_flags:0x4288060 flags:0x00080000
Workqueue: usb_hub_wq hub_event
Call Trace:
<TASK>
context_switch kernel/sched/core.c:5295 [inline]
__schedule+0xeb1/0x41f0 kernel/sched/core.c:6907
__schedule_loop kernel/sched/core.c:6989 [inline]
schedule+0xdd/0x390 kernel/sched/core.c:7004
lbs_wait_for_firmware_load+0x11e/0x1e0 drivers/net/wireless/marvell/libertas/firmware.c:116
lbs_remove_card+0x84/0x390 drivers/net/wireless/marvell/libertas/main.c:913
if_usb_disconnect+0xaf/0x2e0 drivers/net/wireless/marvell/libertas/if_usb.c:316
usb_unbind_interface+0x1dd/0x9e0 drivers/usb/core/driver.c:458
device_remove drivers/base/dd.c:573 [inline]
device_remove+0x12a/0x180 drivers/base/dd.c:565
__device_release_driver drivers/base/dd.c:1284 [inline]
device_release_driver_internal+0x42e/0x600 drivers/base/dd.c:1307
bus_remove_device+0x22f/0x440 drivers/base/bus.c:616
device_del+0x376/0x9b0 drivers/base/core.c:3878
usb_disable_device+0x367/0x810 drivers/usb/core/message.c:1418
usb_disconnect+0x2e2/0x9a0 drivers/usb/core/hub.c:2345
hub_port_connect drivers/usb/core/hub.c:5407 [inline]
hub_port_connect_change drivers/usb/core/hub.c:5707 [inline]
port_event drivers/usb/core/hub.c:5871 [inline]
hub_event+0x1d0c/0x4af0 drivers/usb/core/hub.c:5953
process_one_work+0x9d7/0x1920 kernel/workqueue.c:3275
process_scheduled_works kernel/workqueue.c:3358 [inline]
worker_thread+0x5da/0xe40 kernel/workqueue.c:3439
kthread+0x370/0x450 kernel/kthread.c:467
ret_from_fork+0x6c3/0xcb0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>
Showing all locks held in the system:
5 locks held by kworker/0:1/10:
#0: ffff8881056afd48 ((wq_completion)usb_hub_wq){+.+.}-{0:0}, at: process_one_work+0x1287/0x1920 kernel/workqueue.c:3250
#1: ffffc900000afd18 ((work_completion)(&hub->events)){+.+.}-{0:0}, at: process_one_work+0x93c/0x1920 kernel/workqueue.c:3251
#2: ffff88810b795198 (&dev->mutex){....}-{4:4}, at: device_lock include/linux/device.h:895 [inline]
#2: ffff88810b795198 (&dev->mutex){....}-{4:4}, at: hub_event+0x1bd/0x4af0 drivers/usb/core/hub.c:5899
#3: ffff88811c2c3198 (&dev->mutex){....}-{4:4}, at: device_lock include/linux/device.h:895 [inline]
#3: ffff88811c2c3198 (&dev->mutex){....}-{4:4}, at: usb_disconnect+0x10a/0x9a0 drivers/usb/core/hub.c:2336
#4: ffff88811bcbf160 (&dev->mutex){....}-{4:4}, at: device_lock include/linux/device.h:895 [inline]
#4: ffff88811bcbf160 (&dev->mutex){....}-{4:4}, at: __device_driver_lock drivers/base/dd.c:1106 [inline]
#4: ffff88811bcbf160 (&dev->mutex){....}-{4:4}, at: device_release_driver_internal+0xaa/0x600 drivers/base/dd.c:1304
2 locks held by kworker/1:0/23:
#0: ffff88810006b548 ((wq_completion)events){+.+.}-{0:0}, at: process_one_work+0x1287/0x1920 kernel/workqueue.c:3250
#1: ffffc9000018fd18 ((work_completion)(&fw_work->work)){+.+.}-{0:0}, at: process_one_work+0x93c/0x1920 kernel/workqueue.c:3251
1 lock held by khungtaskd/30:
#0: ffffffff896e05a0 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:312 [inline]
#0: ffffffff896e05a0 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:850 [inline]
#0: ffffffff896e05a0 (rcu_read_lock){....}-{1:3}, at: debug_show_all_locks+0x3d/0x184 kernel/locking/lockdep.c:6775
2 locks held by getty/2917:
#0: ffff888115dd90a0 (&tty->ldisc_sem){++++}-{0:0}, at: tty_ldisc_ref_wait+0x24/0x80 drivers/tty/tty_ldisc.c:243
#1: ffffc900000432f0 (&ldata->atomic_read_lock){+.+.}-{4:4}, at: n_tty_read+0x419/0x1500 drivers/tty/n_tty.c:2211
=============================================
NMI backtrace for cpu 0
CPU: 0 UID: 0 PID: 30 Comm: khungtaskd Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120
nmi_cpu_backtrace.cold+0x12d/0x151 lib/nmi_backtrace.c:113
nmi_trigger_cpumask_backtrace+0x1d7/0x230 lib/nmi_backtrace.c:62
trigger_all_cpu_backtrace include/linux/nmi.h:161 [inline]
__sys_info lib/sys_info.c:157 [inline]
sys_info+0x141/0x190 lib/sys_info.c:165
check_hung_uninterruptible_tasks kernel/hung_task.c:346 [inline]
watchdog+0xd25/0x1050 kernel/hung_task.c:515
kthread+0x370/0x450 kernel/kthread.c:467
ret_from_fork+0x6c3/0xcb0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>
Sending NMI from CPU 0 to CPUs 1:
NMI backtrace for cpu 1
CPU: 1 UID: 0 PID: 0 Comm: swapper/1 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026
RIP: 0010:pv_native_safe_halt+0xf/0x20 arch/x86/kernel/paravirt.c:63
Code: ae b1 01 e9 13 e8 02 00 0f 1f 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 66 90 0f 00 2d d3 e1 1d 00 fb f4 <c3> cc cc cc cc 66 2e 0f 1f 84 00 00 00 00 00 66 90 90 90 90 90 90
RSP: 0018:ffffc9000013fe00 EFLAGS: 00000242
RAX: 000000000007f00b RBX: ffff8881022a1d00 RCX: ffffffff876898d5
RDX: 0000000000000000 RSI: ffffffff8901db96 RDI: ffffffff87afa420
RBP: 0000000000000001 R08: 0000000000000001 R09: ffffed103eae6725
R10: ffff8881f573392b R11: 0000000000000000 R12: ffffed10204543a0
R13: 0000000000000001 R14: ffffffff8aefe2d0 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff8882687d3000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f983bef5900 CR3: 0000000116d22000 CR4: 00000000003506f0
Call Trace:
<TASK>
arch_safe_halt arch/x86/include/asm/paravirt.h:73 [inline]
default_idle+0x9/0x10 arch/x86/kernel/process.c:767
default_idle_call+0x6c/0xb0 kernel/sched/idle.c:122
cpuidle_idle_call kernel/sched/idle.c:191 [inline]
do_idle+0x35b/0x4b0 kernel/sched/idle.c:332
cpu_startup_entry+0x4f/0x60 kernel/sched/idle.c:430
start_secondary+0x21d/0x2d0 arch/x86/kernel/smpboot.c:312
common_startup_64+0x13e/0x148
</TASK>
---
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
^ permalink raw reply
* Re: [PATCH wireless-next 23/35] wifi: mm81x: add sdio.c
From: Krzysztof Kozlowski @ 2026-02-27 11:10 UTC (permalink / raw)
To: Lachlan Hodges
Cc: johannes, Dan Callaghan, Arien Judge, ayman.grais, linux-wireless,
linux-kernel
In-Reply-To: <20260227041108.66508-24-lachlan.hodges@morsemicro.com>
On Fri, Feb 27, 2026 at 03:10:33PM +1100, Lachlan Hodges wrote:
> (Patches split per file for review, see cover letter for more
> information)
>
So we should not commit this? Or you imagine such commit in kernel
history?
...
> +/*
> + * Value to indicate that the base address for bulk/register
> + * read/writes has yet to be set
> + */
> +#define MM81X_SDIO_BASE_ADDR_UNSET 0xFFFFFFFF
> +
> +#define MM81X_SDIO_ALIGNMENT (8)
> +
> +#define MM81X_SDIO_REG_ADDRESS_BASE 0x10000
> +#define MM81X_SDIO_REG_ADDRESS_WINDOW_0 MM81X_SDIO_REG_ADDRESS_BASE
> +#define MM81X_SDIO_REG_ADDRESS_WINDOW_1 (MM81X_SDIO_REG_ADDRESS_BASE + 1)
> +#define MM81X_SDIO_REG_ADDRESS_CONFIG (MM81X_SDIO_REG_ADDRESS_BASE + 2)
> +
> +struct mm81x_sdio {
> + bool enabled;
> + u32 bulk_addr_base;
> + u32 register_addr_base;
> + struct sdio_func *func;
> + const struct sdio_device_id *id;
> +};
> +
> +static void mm81x_sdio_of_probe(struct device *dev, struct mm81x_ps *ps,
> + const struct of_device_id *match_table)
> +{
> + struct device_node *np = dev->of_node;
> + const struct of_device_id *of_id;
> +
> + if (!np) {
> + dev_warn(dev, "Device node not found\n");
??? Why? How it can be not found? And if this is expected, then why this
is a warning?
> + return;
> + }
> +
> + of_id = of_match_node(match_table, np);
> + if (!of_id) {
> + dev_warn(dev, "Couldn't match device table\n");
Huh? How is this possible? Yet you continue the probe, so not an error?
> + return;
> + }
> +
> + ps->wake_gpio = devm_gpiod_get_optional(dev, "wake", GPIOD_OUT_HIGH);
> + ps->busy_gpio = devm_gpiod_get_optional(dev, "busy", GPIOD_IN);
> +
> + ps->gpios_supported = (!IS_ERR_OR_NULL(ps->wake_gpio) &&
> + !IS_ERR_OR_NULL(ps->busy_gpio));
> + if (!ps->gpios_supported) {
> + dev_warn(
> + dev,
Wrong wrapping. Please use Linux coding style.
> + "wake-gpios and busy-gpios not defined, powersave disabled\n");
Not a warn, these are completely optional. Drop the message completely,
this is not even worth debug. Either your hardware HAS or HAS NOT GPIOs
connected. If hardware has not, then why warning the user all the time?
What the user can do? Re-wire device?
Think how your driver will be used by actual users.
> + }
> +}
> +
> +static void mm81x_sdio_remove(struct sdio_func *func);
> +
> +static void sdio_log_err(struct mm81x_sdio *sdio, const char *operation,
> + unsigned int fn, unsigned int address,
> + unsigned int len, int ret)
> +{
> + struct mm81x *mm = sdio->func ? sdio_get_drvdata(sdio->func) : NULL;
> +
> + if (!mm)
> + return;
> +
> + mm81x_err(mm, "sdio: %s fn=%d 0x%08x:%d r=0x%08x b=0x%08x (ret:%d)",
> + operation, fn, address, len, sdio->register_addr_base,
> + sdio->bulk_addr_base, ret);
Even more wrappers over dev_err. NAK. More comments further.
> +}
> +
> +static void irq_handler(struct sdio_func *func1)
> +{
> + int handled;
> + struct sdio_func *func = func1->card->sdio_func[1];
> + struct mm81x *mm = sdio_get_drvdata(func);
> + struct mm81x_sdio *sdio = (struct mm81x_sdio *)mm->drv_priv;
> +
> + WARN_ON_ONCE(!mm);
NAK, you cannot panic kernels (and this does) on such case. Either your
code is buggy if this can happen, or this is not correct. Instead write
code which is correct, so this cannot happen.
> +
> + (void)sdio;
???
> +
> + handled = mm81x_hw_irq_handle(mm);
> + if (!handled)
> + mm81x_dbg(mm, MM81X_DBG_SDIO, "%s: nothing was handled\n",
> + __func__);
No, interrupt handles don't print anything. Maybe with "once" the do,
but you again do not use standard API but own custom abstraction layer.
This is poor design.
> +}
> +
> +static int mm81x_sdio_enable_irq(struct mm81x_sdio *sdio)
> +{
> + int ret;
> + struct sdio_func *func = sdio->func;
> + struct sdio_func *func1 = func->card->sdio_func[0];
> + struct mm81x *mm = sdio_get_drvdata(func);
> +
> + sdio_claim_host(func);
> + ret = sdio_claim_irq(func1, irq_handler);
> + if (ret)
> + mm81x_err(mm, "Failed to enable sdio irq: %d\n", ret);
> +
> + sdio_release_host(func);
> + return ret;
> +}
> +
> +static void mm81x_sdio_disable_irq(struct mm81x_sdio *sdio)
> +{
> + struct sdio_func *func = sdio->func;
> + struct sdio_func *func1 = func->card->sdio_func[0];
> +
> + sdio_claim_host(func);
> + sdio_release_irq(func1);
> + sdio_release_host(func);
> +}
> +
> +static void mm81x_sdio_set_irq(struct mm81x *mm, bool enable)
> +{
> + struct mm81x_sdio *sdio = (struct mm81x_sdio *)mm->drv_priv;
> +
> + if (enable)
> + mm81x_sdio_enable_irq(sdio);
> + else
> + mm81x_sdio_disable_irq(sdio);
> +}
> +
> +static u32 mm81x_sdio_calculate_base_address(u32 address, u8 access)
> +{
> + return (address & MM81X_SDIO_RW_ADDR_BOUNDARY_MASK) | (access & 0x3);
> +}
> +
> +static void mm81x_sdio_reset_base_address(struct mm81x_sdio *sdio)
> +{
> + sdio->bulk_addr_base = MM81X_SDIO_BASE_ADDR_UNSET;
> + sdio->register_addr_base = MM81X_SDIO_BASE_ADDR_UNSET;
> +}
> +
> +static int mm81x_sdio_set_func_address_base(struct mm81x_sdio *sdio,
> + u32 address, u8 access, bool bulk)
> +{
> + int ret = 0;
> + u8 base[4];
> + const char *operation = "set_address_base";
> + u32 calculated_addr_base =
> + mm81x_sdio_calculate_base_address(address, access);
> + u32 *current_addr_base = bulk ? &sdio->bulk_addr_base :
> + &sdio->register_addr_base;
> + bool base_addr_is_unset =
> + (*current_addr_base == MM81X_SDIO_BASE_ADDR_UNSET);
> + struct sdio_func *func2 = sdio->func;
> + struct sdio_func *func1 = sdio->func->card->sdio_func[0];
> + struct sdio_func *func_to_use = bulk ? func2 : func1;
> + struct mm81x *mm = sdio_get_drvdata(sdio->func);
This is completely unreadable code.
Ternary operators are heavily discouraged and are signs of
sloppy/unreadable coding.
> + return ret;
> +err:
> + retries++;
> + if (ret == -ETIMEDOUT && retries <= max_retries) {
> + mm81x_dbg(mm, MM81X_DBG_SDIO,
> + "%s failed (%d), retrying (%d/%d)\n", __func__, ret,
> + retries, max_retries);
> + goto retry;
> + }
> +
> + *current_addr_base = MM81X_SDIO_BASE_ADDR_UNSET;
> + return ret;
> +}
> +
> +static struct sdio_func *mm81x_sdio_get_func(struct mm81x_sdio *sdio,
> + u32 address, ssize_t size,
> + u8 access)
> +{
> + int ret = 0;
> + u32 calculated_base_address =
> + mm81x_sdio_calculate_base_address(address, access);
> + struct sdio_func *func2 = sdio->func;
> + struct sdio_func *func1 = sdio->func ? sdio->func->card->sdio_func[0] :
> + NULL;
> + struct mm81x *mm = sdio->func ? sdio_get_drvdata(sdio->func) : NULL;
All of these look wrong. Either you have func or not?
> + struct sdio_func *func_to_use;
> +
> + WARN_ON(!mm);
> +
NAK. Write correct code, not something which randomly is being executed
- sometimes with NULL, sometimes not. Coding is not random, unless you
wrote it with microslop copilot, but then I would simply NAK it.
> +
> +static int mm81x_sdio_probe(struct sdio_func *func,
> + const struct sdio_device_id *id)
> +{
> + int ret = 0;
> + u32 chip_id;
> + struct mm81x *mm = NULL;
> + struct mm81x_sdio *sdio;
> + struct device *dev = &func->dev;
> +
> + if (func->num == 1)
> + return 0;
> +
> + if (func->num != 2)
> + return -ENODEV;
> +
> + mm = mm81x_mac_create(sizeof(*sdio), dev);
> + if (!mm) {
> + dev_err(dev, "mm81x_mac_create failed\n");
No, you must not print here anything. Do you see code like that
anywhere?
> + return -ENOMEM;
> + }
> +
> + mm->bus_ops = &mm81x_sdio_ops;
> + mm->bus_type = MM81X_BUS_TYPE_SDIO;
> +
> + sdio = (struct mm81x_sdio *)mm->drv_priv;
> + sdio->func = func;
> + sdio->id = id;
> + sdio->enabled = true;
> + mm81x_sdio_reset_base_address(sdio);
> +
> + sdio_set_drvdata(func, mm);
> +
> + ret = mm81x_sdio_enable(sdio);
> + if (ret) {
> + mm81x_err(mm, "mm81x_sdio_enable failed: %d\n", ret);
> + goto err_destroy_mac;
> + }
> +
> + ret = mm81x_core_attach_regs(mm);
> + if (ret) {
> + mm81x_err(mm, "mm81x_core_attach_regs failed: %d\n", ret);
> + goto err_destroy_sdio;
All these are just poor coding style. Why are you not using standard
dev_err_probe?
> + }
> +
> + mm81x_claim_bus(mm);
> + ret = mm81x_reg32_read(mm, MM81X_REG_CHIP_ID(mm), &chip_id);
> + mm81x_release_bus(mm);
> + if (ret || chip_id != mm->chip_id) {
> + mm81x_err(mm, "Chip ID read failed: %d\n", ret);
> + goto err_destroy_sdio;
> + }
> +
> + mm81x_dbg(mm, MM81X_DBG_SDIO,
> + "Morse Micro SDIO device found, chip ID=0x%04x\n",
> + mm->chip_id);
> +
> + mm81x_sdio_of_probe(dev, &mm->ps, mm81x_of_match_table);
> + mm81x_sdio_config_burst_mode(mm, true);
> +
> + mm81x_core_init_mac_addr(mm);
> +
> + ret = mm81x_core_create(mm);
> + if (ret)
> + goto err_destroy_sdio;
> +
> + ret = mm81x_sdio_enable_irq(sdio);
> + if (ret) {
> + mm81x_err(mm, "mm81x_sdio_enable_irq failed: %d\n", ret);
No, use standard printing constructs. dev_err_probe, dev_err, not your
own API. Abstraction layers are in kernel heavily discouraged.
> + goto err_destroy_core;
> + }
> +
> + ret = mm81x_mac_register(mm);
> + if (ret) {
> + mm81x_err(mm, "mm81x_mac_register failed: %d\n", ret);
> + goto err_disable_irq;
> + }
> +
> + return 0;
> +
> +err_disable_irq:
> + mm81x_sdio_disable_irq(sdio);
> +err_destroy_core:
> + mm81x_core_destroy(mm);
> +err_destroy_sdio:
> + mm81x_sdio_release(sdio);
> +err_destroy_mac:
> + mm81x_mac_destroy(mm);
> + return ret;
> +}
> +
> +static void mm81x_sdio_remove(struct sdio_func *func)
> +{
> + struct mm81x *mm = sdio_get_drvdata(func);
> + struct mm81x_sdio *sdio = (struct mm81x_sdio *)mm->drv_priv;
> +
> + dev_info(&func->dev, "sdio removed func %d vendor 0x%x device 0x%x\n",
> + func->num, func->vendor, func->device);
Drop, drivers should be silent.
> +
> + if (!mm)
> + return;
> +
> + mm81x_mac_unregister(mm);
> + mm81x_sdio_disable_irq(sdio);
> + mm81x_core_destroy(mm);
> + mm81x_sdio_release(sdio);
> + mm81x_sdio_reset(func);
> + mm81x_mac_destroy(mm);
> + sdio_set_drvdata(func, NULL);
> +}
> +
> +static const struct sdio_device_id mm81x_sdio_devices[] = {
> + { SDIO_DEVICE(SDIO_VENDOR_ID_MORSEMICRO,
> + SDIO_VENDOR_ID_MORSEMICRO_MM81XB1) },
> + { SDIO_DEVICE(SDIO_VENDOR_ID_MORSEMICRO,
> + SDIO_VENDOR_ID_MORSEMICRO_MM81XB2) },
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(sdio, mm81x_sdio_devices);
> +
> +static struct sdio_driver mm81x_sdio_driver = {
> + .name = "mm81x_sdio",
> + .id_table = mm81x_sdio_devices,
> + .probe = mm81x_sdio_probe,
> + .remove = mm81x_sdio_remove,
> +};
> +
> +int __init mm81x_sdio_init(void)
Why aren't you using module sdio driver wrapper?
> +{
> + int ret;
> +
> + ret = sdio_register_driver(&mm81x_sdio_driver);
> + if (ret)
> + pr_err("sdio_register_driver() failed: %d\n", ret);
> +
> + return ret;
And you miss here module description. This patch organized per files,
not per logical pieces, makes it very difficult to review. I have
absolutely no clue whether this is module or not, whether this is built
or not, whether it is complete or not.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH ath-next v2] wifi: ath12k: Pass the correct value of each TID during a stop AMPDU session
From: Reshma Immaculate Rajkumar @ 2026-02-27 11:01 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Reshma Immaculate Rajkumar
With traffic ongoing for data TID [TID 0], an DELBA request to
stop AMPDU for the BA session was received on management TID [TID 4].
The corresponding TID number was incorrectly passed to stop the BA session,
resulting in the BA session for data TIDs being stopped and the BA size
being reduced to 1, causing an overall dip in TCP throughput.
Fix this issue by passing the correct argument from
ath12k_dp_rx_ampdu_stop() to ath12k_dp_arch_peer_rx_tid_reo_update()
during an AMPDU stop session. Instead of passing peer->dp_peer->rx_tid,
which is the base address of the array, corresponding to TID 0, pass
the value of &peer->dp_peer->rx_tid[params->tid]. With this, the
different TID numbers are accounted for.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Reshma Immaculate Rajkumar <reshma.rajkumar@oss.qualcomm.com>
---
v2:
* modify 'ADDBA' to 'DELBA' request in commit message
drivers/net/wireless/ath/ath12k/dp_rx.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index a32ee9f8061a..640f752eaa03 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -735,6 +735,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_dp_link_peer *peer;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
+ struct ath12k_dp_rx_tid *rx_tid;
struct ath12k_link_sta *arsta;
int vdev_id;
bool active;
@@ -770,7 +771,8 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
return 0;
}
- ret = ath12k_dp_arch_peer_rx_tid_reo_update(dp, peer, peer->dp_peer->rx_tid,
+ rx_tid = &peer->dp_peer->rx_tid[params->tid];
+ ret = ath12k_dp_arch_peer_rx_tid_reo_update(dp, peer, rx_tid,
1, 0, false);
spin_unlock_bh(&dp->dp_lock);
if (ret) {
base-commit: 8bf22c33e7a172fbc72464f4cc484d23a6b412ba
--
2.34.1
^ permalink raw reply related
* Re: [PATCH wireless-next 32/35] dt-bindings: net: wireless: morsemicro: add mm81x family
From: Krzysztof Kozlowski @ 2026-02-27 10:59 UTC (permalink / raw)
To: Lachlan Hodges
Cc: johannes, Dan Callaghan, Arien Judge, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, ayman.grais, linux-wireless,
devicetree, linux-kernel
In-Reply-To: <20260227041108.66508-33-lachlan.hodges@morsemicro.com>
On Fri, Feb 27, 2026 at 03:10:42PM +1100, Lachlan Hodges wrote:
> Add dt-bindings describing the Morse Micro mm81x family of
> chips.
Please organize the patch documenting the compatible (DT bindings)
before the patch using that compatible.
See also: https://elixir.bootlin.com/linux/v6.14-rc6/source/Documentation/devicetree/bindings/submitting-patches.rst#L46
>
> Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
> ---
> .../net/wireless/morsemicro,mm81x.yaml | 74 +++++++++++++++++++
> 1 file changed, 74 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/wireless/morsemicro,mm81x.yaml
>
> diff --git a/Documentation/devicetree/bindings/net/wireless/morsemicro,mm81x.yaml b/Documentation/devicetree/bindings/net/wireless/morsemicro,mm81x.yaml
> new file mode 100644
> index 000000000000..653a7476cf8f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/wireless/morsemicro,mm81x.yaml
> @@ -0,0 +1,74 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/wireless/morsemicro,mm81x.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Morse Micro MM81x
> +
> +maintainers:
> + - Lachlan Hodges <lachlan.hodges@morsemicro.com>
> + - Arien Judge <arien.judge@morsemicro.com>
> +
> +description: >
> + This node provides properties for configuring a Morse Micro MM81x device
> + connected via SDIO. The node shall be specified as a child node of an SDIO
> + controller.
Drop sentences, redunadnt. Explain the device/hardware, not the DT. We
all know how to construct DT.
> +
> + It is recommended to declare a mmc-pwrseq on SDIO host above MM81x. Without
No. It is not. Drop,.
> + it, you may encounter issues during reboot. The mmc-pwrseq should be
> + compatible with mmc-pwrseq-simple. Please consult
> + Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml for more
> + information.
Nothing here is relevant. You must explain the hardware, not quirks
specific to kernel.
> +
> +properties:
> + compatible:
> + items:
> + - const: morsemicro,mm81x
What is 'x'? Wild-cards are not allowed, see numerous talks and writing
bindings.
> +
> + reg:
> + description:
> + <reg> must be set to 2.
Why? No, drop description.
> + maxItems: 1
> +
> + wake-gpios:
> + description: Phandle of gpio that will be used to wake up the chip. Powersave
> + features disabled if property not present.
> + maxItems: 1
> +
> + busy-gpios:
> + description: Phandle of a gpio that is used to indicate the chip has data
> + ready.
Drop redundant "PHandle of a gpio that is". It cannot be anything else.
Same in the oter place.
OTOH, missing constraints/maxItems.
> +
> +required:
> + - compatible
> + - reg
You need $ref to wireless-controller.yaml.
> +
> +additionalProperties: false
and this becomes unevaluatedProperties
> +
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> +
> + mm81x_pwrseq: mm81x_pwrseq {
Drop entire node, not really correct and not needed.
> + compatible = "mmc-pwrseq-simple";
> + pinctrl-names = "default";
> + pinctrl-0 = <&mm81x_reset>;
> + reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>;
> + };
> +
> + mmc {
> + mmc-pwrseq = <&mm81x_pwrseq>;
Drop property irrelevant.
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + wifi@0 {
Not tested. You said before it has to be 2, not 0.
> + compatible = "morsemicro,mm81x";
> + pinctrl-names = "default";
> + pinctrl-0 = <&mm81x_busy>, <&mm81x_wake>;
> + reg = <2>;
Follow DTS coding style.
> + wake-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
> + busy-gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
> + };
> + };
> +...
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH wireless-next 31/35] dt-bindings: vendor-prefixes: add Morse Micro
From: Krzysztof Kozlowski @ 2026-02-27 10:50 UTC (permalink / raw)
To: Lachlan Hodges
Cc: johannes, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
arien.judge, dan.callaghan, ayman.grais, linux-wireless,
devicetree, linux-kernel
In-Reply-To: <20260227041108.66508-32-lachlan.hodges@morsemicro.com>
On Fri, Feb 27, 2026 at 03:10:41PM +1100, Lachlan Hodges wrote:
> Add vendor prefix for Morse Micro Pty Ltd
>
> Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
> ---
> Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
> 1 file changed, 2 insertions(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH wireless-next 33/35] mmc: sdio: add Morse Micro vendor ids
From: Krzysztof Kozlowski @ 2026-02-27 10:49 UTC (permalink / raw)
To: Lachlan Hodges
Cc: johannes, Ulf Hansson, arien.judge, dan.callaghan, ayman.grais,
linux-wireless, linux-mmc, linux-kernel
In-Reply-To: <20260227041108.66508-34-lachlan.hodges@morsemicro.com>
On Fri, Feb 27, 2026 at 03:10:43PM +1100, Lachlan Hodges wrote:
> Add the Morse Micro mm81x series vendor ids.
Without any user this is pointless commit. Organize your work in logical
chunks. Define alone is completely pointless and redundant. After
applying this patch we should immediately revert it, because you added
defines which are unused, so just bloat.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Enable monitor mode support on IPQ5332
From: Baochen Qiang @ 2026-02-27 10:38 UTC (permalink / raw)
To: Aaradhana Sahu, ath12k; +Cc: linux-wireless
In-Reply-To: <20260227033332.687805-1-aaradhana.sahu@oss.qualcomm.com>
On 2/27/2026 11:33 AM, Aaradhana Sahu wrote:
> Currently, rxdma1_enable and supports_monitor are set to false in
> IPQ5332 hardware parameters, which skips monitor ring configuration
> and removes NL80211_IFTYPE_MONITOR from the supported interface modes.
>
> Set rxdma1_enable and supports_monitor to true so that monitor rings are
> configured and monitor mode is enabled on IPQ5332.
>
> Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.7-00587-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Aaradhana Sahu <aaradhana.sahu@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath12k/wifi7/hw.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> index df045ddf42da..27acdfc35459 100644
> --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> @@ -617,7 +617,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
> ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332,
> .svc_to_ce_map_len = 18,
>
> - .rxdma1_enable = false,
> + .rxdma1_enable = true,
> .num_rxdma_per_pdev = 1,
> .num_rxdma_dst_ring = 0,
> .rx_mac_buf_ring = false,
> @@ -626,7 +626,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
> .interface_modes = BIT(NL80211_IFTYPE_STATION) |
> BIT(NL80211_IFTYPE_AP) |
> BIT(NL80211_IFTYPE_MESH_POINT),
> - .supports_monitor = false,
> + .supports_monitor = true,
>
> .idle_ps = false,
> .download_calib = true,
>
> base-commit: 20ad0d58517073b3b683ff786c65dd3142321707
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Fix the assignment of logical link index
From: Baochen Qiang @ 2026-02-27 10:37 UTC (permalink / raw)
To: Roopni Devanathan, ath12k; +Cc: linux-wireless, Manish Dharanenthiran
In-Reply-To: <20260226041911.2434999-1-roopni.devanathan@oss.qualcomm.com>
On 2/26/2026 12:19 PM, Roopni Devanathan wrote:
> From: Manish Dharanenthiran <manish.dharanenthiran@oss.qualcomm.com>
>
> Per-link logical index is assigned from the global counter,
> ahsta->num_peer. This logical index is sent to firmware during peer
> association. If there is a failure in creating a link station,
> ath12k_mac_free_unassign_link_sta() clears the link, but does not decrement
> the logical link index. This will result in a higher logical link index for
> the next link station created. Also, if there is a leak in logical link
> index as we assign the incremented num_peer, then the index can exceed the
> maximum valid value of 15.
>
> As an example, let's say we have a 2 GHz + 5 GHz + 6 GHz MLO setup. So the
> logical link indices that they have are 0, 1 and 2, respectively. If the
> 5 GHz link is removed, logical link index 1 becomes available, and num_peer
> is not reduced to 2 and still remains at 3. If a new 5 GHz link is added
> later, it gets the index 3, instead of reusing link index 1. Also,
> num_peer is increased to 4, though only 3 links are present.
>
> To resolve these, create a bitmap, free_logical_link_idx, that tracks the
> available logical link indices. When a link station is created, select the
> first free logical index and when a link station is removed, mark its
> logical link index as available by setting the bit.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01181-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Manish Dharanenthiran <manish.dharanenthiran@oss.qualcomm.com>
> Signed-off-by: Roopni Devanathan <roopni.devanathan@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath12k/core.h | 2 +-
> drivers/net/wireless/ath/ath12k/mac.c | 16 ++++++++++++++--
> 2 files changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
> index 990934ec92fc..5498ff285102 100644
> --- a/drivers/net/wireless/ath/ath12k/core.h
> +++ b/drivers/net/wireless/ath/ath12k/core.h
> @@ -522,7 +522,7 @@ struct ath12k_sta {
> u16 links_map;
> u8 assoc_link_id;
> u16 ml_peer_id;
> - u8 num_peer;
> + u16 free_logical_link_idx_map;
>
> enum ieee80211_sta_state state;
> };
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 68431a0e128e..db1b098b67d0 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -6784,6 +6784,8 @@ static void ath12k_mac_free_unassign_link_sta(struct ath12k_hw *ah,
> return;
>
> ahsta->links_map &= ~BIT(link_id);
> + ahsta->free_logical_link_idx_map |= BIT(arsta->link_idx);
> +
> rcu_assign_pointer(ahsta->link[link_id], NULL);
> synchronize_rcu();
>
> @@ -7102,6 +7104,7 @@ static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah,
> struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
> struct ieee80211_link_sta *link_sta;
> struct ath12k_link_vif *arvif;
> + int link_idx;
>
> lockdep_assert_wiphy(ah->hw->wiphy);
>
> @@ -7120,8 +7123,16 @@ static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah,
>
> ether_addr_copy(arsta->addr, link_sta->addr);
>
> - /* logical index of the link sta in order of creation */
> - arsta->link_idx = ahsta->num_peer++;
> + if (!ahsta->free_logical_link_idx_map)
> + return -ENOSPC;
> +
> + /*
> + * Allocate a logical link index by selecting the first available bit
> + * from the free logical index map
> + */
> + link_idx = __ffs(ahsta->free_logical_link_idx_map);
> + ahsta->free_logical_link_idx_map &= ~BIT(link_idx);
> + arsta->link_idx = link_idx;
>
> arsta->link_id = link_id;
> ahsta->links_map |= BIT(arsta->link_id);
> @@ -7630,6 +7641,7 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
> if (old_state == IEEE80211_STA_NOTEXIST &&
> new_state == IEEE80211_STA_NONE) {
> memset(ahsta, 0, sizeof(*ahsta));
> + ahsta->free_logical_link_idx_map = U16_MAX;
>
> arsta = &ahsta->deflink;
>
>
> base-commit: 62f9b9b19939138c34ce0ac1e5d4969d617ecbb6
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Set up MLO after SSR
From: Baochen Qiang @ 2026-02-27 10:35 UTC (permalink / raw)
To: Roopni Devanathan, ath12k; +Cc: linux-wireless, Ramya Gnanasekar
In-Reply-To: <20260227041127.3265879-1-roopni.devanathan@oss.qualcomm.com>
On 2/27/2026 12:11 PM, Roopni Devanathan wrote:
> From: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com>
>
> During recovery of an MLO setup from a core reset,
> ATH12K_GROUP_FLAG_REGISTERED is set because ath12k_mac_unregister is not
> called during core reset. So, when an MLO setup is recovering from a core
> reset, ath12k_core_mlo_setup() is skipped. Hence, the firmware will not
> have information about partner links. This makes MLO association fail
> after recovery.
>
> To resolve this, call ath12k_core_mlo_setup() during recovery, to set up
> MLO. Also, if MLO setup fails during recovery, call
> ath12k_mac_unregister() and ath12k_mac_destroy() to unregister mac and
> then tear down the mac structures.
>
> Also, initiate MLO teardown in the hardware group stop sequence to align
> with the hardware group start sequence.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01181-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com>
> Signed-off-by: Roopni Devanathan <roopni.devanathan@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath12k/core.c | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
> index 9dca1a0af73e..218c0a0c9699 100644
> --- a/drivers/net/wireless/ath/ath12k/core.c
> +++ b/drivers/net/wireless/ath/ath12k/core.c
> @@ -1017,6 +1017,8 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag)
>
> ath12k_mac_unregister(ag);
>
> + ath12k_mac_mlo_teardown(ag);
> +
> for (i = ag->num_devices - 1; i >= 0; i--) {
> ab = ag->ab[i];
> if (!ab)
> @@ -1134,8 +1136,14 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)
>
> lockdep_assert_held(&ag->mutex);
>
> - if (test_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags))
> + if (test_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags)) {
> + ret = ath12k_core_mlo_setup(ag);
> + if (WARN_ON(ret)) {
> + ath12k_mac_unregister(ag);
> + goto err_mac_destroy;
> + }
> goto core_pdev_create;
> + }
>
> ret = ath12k_mac_allocate(ag);
> if (WARN_ON(ret))
>
> base-commit: 20ad0d58517073b3b683ff786c65dd3142321707
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Fix the assignment of logical link index
From: Vasanthakumar Thiagarajan @ 2026-02-27 10:33 UTC (permalink / raw)
To: Roopni Devanathan, ath12k; +Cc: linux-wireless, Manish Dharanenthiran
In-Reply-To: <20260226041911.2434999-1-roopni.devanathan@oss.qualcomm.com>
On 2/26/2026 9:49 AM, Roopni Devanathan wrote:
> From: Manish Dharanenthiran <manish.dharanenthiran@oss.qualcomm.com>
>
> Per-link logical index is assigned from the global counter,
> ahsta->num_peer. This logical index is sent to firmware during peer
> association. If there is a failure in creating a link station,
> ath12k_mac_free_unassign_link_sta() clears the link, but does not decrement
> the logical link index. This will result in a higher logical link index for
> the next link station created. Also, if there is a leak in logical link
> index as we assign the incremented num_peer, then the index can exceed the
> maximum valid value of 15.
>
> As an example, let's say we have a 2 GHz + 5 GHz + 6 GHz MLO setup. So the
> logical link indices that they have are 0, 1 and 2, respectively. If the
> 5 GHz link is removed, logical link index 1 becomes available, and num_peer
> is not reduced to 2 and still remains at 3. If a new 5 GHz link is added
> later, it gets the index 3, instead of reusing link index 1. Also,
> num_peer is increased to 4, though only 3 links are present.
>
> To resolve these, create a bitmap, free_logical_link_idx, that tracks the
> available logical link indices. When a link station is created, select the
> first free logical index and when a link station is removed, mark its
> logical link index as available by setting the bit.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01181-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Manish Dharanenthiran <manish.dharanenthiran@oss.qualcomm.com>
> Signed-off-by: Roopni Devanathan <roopni.devanathan@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Set up MLO after SSR
From: Vasanthakumar Thiagarajan @ 2026-02-27 10:33 UTC (permalink / raw)
To: Roopni Devanathan, ath12k; +Cc: linux-wireless, Ramya Gnanasekar
In-Reply-To: <20260227041127.3265879-1-roopni.devanathan@oss.qualcomm.com>
On 2/27/2026 9:41 AM, Roopni Devanathan wrote:
> From: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com>
>
> During recovery of an MLO setup from a core reset,
> ATH12K_GROUP_FLAG_REGISTERED is set because ath12k_mac_unregister is not
> called during core reset. So, when an MLO setup is recovering from a core
> reset, ath12k_core_mlo_setup() is skipped. Hence, the firmware will not
> have information about partner links. This makes MLO association fail
> after recovery.
>
> To resolve this, call ath12k_core_mlo_setup() during recovery, to set up
> MLO. Also, if MLO setup fails during recovery, call
> ath12k_mac_unregister() and ath12k_mac_destroy() to unregister mac and
> then tear down the mac structures.
>
> Also, initiate MLO teardown in the hardware group stop sequence to align
> with the hardware group start sequence.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01181-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Ramya Gnanasekar <ramya.gnanasekar@oss.qualcomm.com>
> Signed-off-by: Roopni Devanathan <roopni.devanathan@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Enable monitor mode support on IPQ5332
From: Vasanthakumar Thiagarajan @ 2026-02-27 10:32 UTC (permalink / raw)
To: Aaradhana Sahu, ath12k; +Cc: linux-wireless
In-Reply-To: <20260227033332.687805-1-aaradhana.sahu@oss.qualcomm.com>
On 2/27/2026 9:03 AM, Aaradhana Sahu wrote:
> Currently, rxdma1_enable and supports_monitor are set to false in
> IPQ5332 hardware parameters, which skips monitor ring configuration
> and removes NL80211_IFTYPE_MONITOR from the supported interface modes.
>
> Set rxdma1_enable and supports_monitor to true so that monitor rings are
> configured and monitor mode is enabled on IPQ5332.
>
> Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.7-00587-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Aaradhana Sahu <aaradhana.sahu@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath12k/wifi7/hw.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> index df045ddf42da..27acdfc35459 100644
> --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> @@ -617,7 +617,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
> ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332,
> .svc_to_ce_map_len = 18,
>
> - .rxdma1_enable = false,
> + .rxdma1_enable = true,
> .num_rxdma_per_pdev = 1,
> .num_rxdma_dst_ring = 0,
> .rx_mac_buf_ring = false,
> @@ -626,7 +626,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
> .interface_modes = BIT(NL80211_IFTYPE_STATION) |
> BIT(NL80211_IFTYPE_AP) |
> BIT(NL80211_IFTYPE_MESH_POINT),
> - .supports_monitor = false,
> + .supports_monitor = true,
>
> .idle_ps = false,
> .download_calib = true,
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Remove the unused argument from the Rx data path
From: Vasanthakumar Thiagarajan @ 2026-02-27 10:32 UTC (permalink / raw)
To: Karthikeyan Periyasamy, ath12k; +Cc: linux-wireless
In-Reply-To: <20260227042128.3494167-1-karthikeyan.periyasamy@oss.qualcomm.com>
On 2/27/2026 9:51 AM, Karthikeyan Periyasamy wrote:
> Currently, the Rx path uses new infrastructure to extract the required HAL
> parameters. Consequently, the HAL Rx descriptor argument is no longer
> needed in the following helper functions. Remove the unused argument from
> the following helper functions.
>
> ath12k_dp_rx_h_undecap()
> ath12k_dp_rx_check_nwifi_hdr_len_valid()
> ath12k_wifi7_dp_rx_h_mpdu()
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Karthikeyan Periyasamy <karthikeyan.periyasamy@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH wireless-next v2 00/34] wifi: inffmac: introducing a driver for Infineon's new generation chipsets
From: Marek Vasut @ 2026-02-27 10:28 UTC (permalink / raw)
To: Gokul Sivakumar
Cc: linux-wireless, Johannes Berg, Arend van Spriel,
wlan-kernel-dev-list
In-Reply-To: <aWpoQs8rzqGUCsPO@ISCN5CG14747PP.infineon.com>
On 1/16/26 5:33 PM, Gokul Sivakumar wrote:
> On 01/15, Marek Vasut wrote:
>> On 1/14/26 9:12 AM, Gokul Sivakumar wrote:
>>> On 01/14, Marek Vasut wrote:
>>>> On 1/13/26 9:33 PM, Gokul Sivakumar wrote:
>>>>> Infineon(Cypress) is introducing a new INFFMAC (WLAN FULLMAC) Linux driver
>>>>> specifically for its new-generation AIROC family of Wi-Fi Connectivity
>>>>> Processor (CP) chipsets (CYW5591x), Wi-Fi + Bluetooth combo chipsets
>>>>> (CYW5557x, CYW5551x, CYW5591x, CYW43022), and also for all future chipsets.
>>>> Support for the CYW55572 can be easily added into the existing brcmfmac
>>>> driver, I already posted a patch over a year ago [1], but it was blocked
>>>> by an off-list email.
>>>
>>>> Frankly, I do not see any good reason why the brcmfmac driver shouldn't
>>>> be extended when it is clearly easily doable. Adding new fork of the
>>>> brcmfmac would only increase maintenance burden and prevent bugfixes
>>>> from reaching the brcmfmac.
>>>>
>>>> [1] https://lore.kernel.org/all/20240909203133.74777-2-marex@denx.de/
>>>
>>> There are multiple reasons behind Infineon's proposal for this new INFFMAC
>>> driver for its new-generation chips. Sharing a few here, and more info
>>> is available in the v1 cover-letter [1]. For Example, the CYW5591x family
>>> chipsets that is currently supported in this INFFMAC driver has a unique
>>> Connected-MCU / Connectivtiy Processor (CP) Architecture [2], primarly
>>> intended for IoT applications and it is completely different from any of
>>> the legacy Broadcom architecture chipsets of Infineon supported currently
>>> in upstream BRCMFMAC.
>>
>> This does not prevent them from being integrated in brcmfmac like many
>> of the other already supported chips, there seems to be no technical
>> reason here.
>
> I hope you would have got a chance to look into the elaborate info provided
> in v1 cover-letter about the challenges that we faced with that approach.
> In Infineon's new architecture CYW5591x family of chipsets coming with an
> onboard FLASH Memory, it does not follow the traditional Device firmware
> download sequence used by any of the legacy Broadcom chipsets and it would
> be appropriate to use a dedicated driver for Infineon's chipsets which were
> developed and intended mainly for IoT use-cases.
>
> Here it requires a Boot firmware download, and a host handshake with the
> downloaded RAM boot firmware, followed by a CP Firmware image Download and
> validation. Sharing here the sequence for coldboot image download to FLASH.
>
> Host Driver Device
> ___________ ____________
> | |
> | Power UP and execute CP Firmware
> | from FLASH if available
> Attempt to enable SDIO F2 |
> if fails, FLASH is empty, |
> Need to Download Firmware |
> | |
> Wait for |
> DFU_CP_D2H_MSG_BL_READY |
> |<<======== DFU_CP_D2H_MSG_BL_READY <<============|
> | |
> Fetch Boot Firmware |
> from Filesystem |
> |======>> DFU_CP_H2D_MSG_BOOT_FWLOAD_START =====>>|
> | |
> |======>> Transfer Boot Firmware over SDIO =====>>|
> | in multiple chunks |
> | |
> |======>> DFU_CP_H2D_MSG_BOOT_FWLOAD_DONE ======>>|
> | Execute the downloaded
> | RAM Bootloader
> Wait for |
> DFU_CP_D2H_MSG_BOOTFW_READY |
> |<<========= DFU_CP_D2H_MSG_BOOTFW_READY <<=======|
> | |
> Fetch CP Firmware |
> from Filesystem |
> |=======>> Transfer CP Firmware over SDIO ======>>|
> | in multiple chunks |
> | Download CP Firmware
> | to FLASH Memory
> | |
> |=======>> DFU_CP_H2D_MSG_BOOTFW_DATA_LOADED ====>|
> | |
> |=======>> DFU_CP_D2H_MSG_FW_VALIDAT_START ======>|
> | |
> Wait for Validate the CP Firmware
> DFU_CP_D2H_MSG_FW_VALIDAT_DONE |
> |<<======= DFU_CP_D2H_MSG_FW_VALIDAT_DONE <<======|
> | |
> | Execute the CP Firmware
> Proceed with |
> ctrl cmds to Device |
> | |
>
> Here there is no need to redownload the Device Firmware from the Host
> filesystem everyime the Host or Device goes through a power cycle. Also the
> device is capable of fully operating in an offloaded mode even when the
> host is in suspended state or even if fully powered off. This is critical
> to save power for extended durations in IoT use cases which are often
> battery operated.
This seems like a technical detail of the firmware loading, which can be
handled by the driver ?
>>> The CYW5591x family chipsets has dedicated MCU Core
>>> in addition to the WLAN core and an onboard FLASH memory for the Firmware.
>>
>> It seems all brcmfmac devices have a cortex-M core in them since a long
>> time.
>
> We were intending to mention that CYW5591x Cortex-M33 core is dedicated to
> function as a Co-Processor to the Host CPU/MCU and offload multiple wifi
> and network operations if configured by the user before host goes to sleep.
> You can refer the chipset block diagram in CYW55913/2/1 Product Brief [1]
> The CYW5591x SoC Backplane interconnects are also different from any of the
> legacy Broadcom chipsets.
Maybe the driver can be forked when it turns out this functionality
cannot be easily added into the existing driver ?
>>> And with respect to the support for the new-generation CYW5557x family of
>>> Secure chipsets, that requires a Secure boot handshake with the Bootloader.
>>
>> It seems like the TRX firmware loading is trivial to add, and parts of
>> it are already in the Linux kernel for other brcm components. It seems
>> this TRX was used since old broadcom MIPS SoCs.
>
> No, your understanding needs a correction. Infineon's TRXSE and TRXS Device
> Bootloader handshake and Firmware formats are quite different from the old
> Broadcom TRX formats that you are mentioning here. Being two individual
> WLAN vendors, the chipset internals, firmware formats, Device Bootloader
> handshake cannot be expected to be the same. Yet another reason why it is
> not practically feasible to use upstream BRCMFMAC for the new-generation
> chipsets and new firmware releases from Infineon.
Surely it is possible to do something like
if (wlan_id_needs_trxse)
load_trxse();
else
load_old_firmware_style();
?
It seems this was already done in the two patches I submitted about a
year ago, so this is clearly doable.
>>> Even if the enumeration and firmware download support for the CYW55572 is
>>> somehow retro-fitted into the existing upstream BRCMFMAC driver, there are
>>> multiple other features and aspects of the Driver-Device communication that
>>> are unique to each WLAN vendor, which are not always practically feasible
>>> to support in the same upstream driver.
>>
>> Why ?
>
> As mentioned before, various aspects of the Driver-Device communication are
> unique to each WLAN vendor. And it is not practically feasible to confine
> them into a common upstream driver, also not sustainable to maintain it that
> way througout the lifetime of the hardware.
The patches I submitted showed this was feasible, so I am not buying
that argument. Can you give that a try instead ?
>>> Because currently BRCMFMAC driver
>>> has a shared ownership with more than 3 WLAN vendor organizations and this
>>> approach has its limitations.
>>
>> Yes, this means it is necessary to cooperate and coordinate with other
>> people, on the mailing list.
>
> Infineon is committed to coordinate with other vendors in managing upstream
> BRCMFMAC driver and continuing the support for its legacy chipsets that
> still follows the legacy Broadcom architecture. Like for example, we have
> added support for CYW54591-PCIe in upstream BRCMFMAC few months back [2],
> because it has many things in common with other legacy Broadcom chips.
> But the same does not applies for all the new-generation Infineon chipsets.
>
>>> For Example, the version of the PCIe and SDIO
>>> BUS specific shared info in Device Memory is expected same from chipsets
>>> from all vendors. There would be a complex need to maintain vendor specifc
>>> as well as BUS specific Shared info version, vendor specific BUS Protocol
>>> layers, vendor specific firmware event header OUIs (currently always expects
>>> BRCM OUI even from other vendor chips) and even more.
>>
>> This sounds like code refactoring is necessary.
>>
>>> Confining different architecture chips from different WLAN vendors into the
>>> same legacy BRCMFMAC driver codebase, may not be sustainable and could
>>> potentially increase the maintainence effort and codebase complexity.
>>> And not practically feasible to continue splitting this driver with more
>>> vendor specific checks in the longer run. Since being different vendors,
>>> each will only naturally diverge even more in the future with their chipset
>>> Architecture, Driver-Device communication flow, etc. Infineon will continue
>>> to support its legacy chipsets, already supported in the upstream BRCMFMAC.
>> Maybe all the extra functionality can be added later, and the driver can
>> be forked later, when it becomes clear that refactoring is not an option
>> and it is becoming too difficult to maintain ?
>
> Refactoring the existing upstream BRCMFMAC driver for the new-architecture
> chipsets developed by Infineon is not a practical option now because these
> devices are fairly new. In the lifetime of these devices, the functionality
> of the Devices and Driver interaction are only going to evolve even more.
> Eventually, it would become more cumbersome to maintain as well as to avoid
> regressions for different architecture chips from different WLAN vendors
> if same upstream driver is used.
>
> We strongly believe that this is an appropriate time for thinking about a
> proposal to proceed with a dedicated driver for the new-generation chips
> developed individually by Infineon.
>
>> So far, it seems the current generation chips can be easily added to
>> brcmfmac, even if the feature set would be limited. Adding them would
>
> We are not in the same page here. As mentioned earlier and as you might
> know, there is infact much more to it than adding enumeration support for a
> chip in a driver. Certainly not easy when eventually Infineon is required
> to enable the end users with the actual capabilities of the chipset, also
> Infineon has the responsibility to ensure driver compatibility with all the
> newly shipped Device firmwares.
>
>> allow the maintainers to review such a smaller patchset and get at least
>> some hardware support in, step by step, instead of this mega-patchset.
>
> We understood that review bandwidth is limited and have taken the feedback
> received on v1 very seriously, so multiple features were already stripped
> off in v2. Willing to skip even more functionality in the upcoming versions
> and also ready to provide more information as needed to make the INFFMAC
> driver review as much easy as possible.
So, can you try and implement minimal TRXSE firmware loading and support
for the CYW555xx for brcmfmac as an example, so it would be clear
whether or not it can be added into the brcmfmac driver ?
Oh ... and I also noticed, that infineon recently fully rewrote the
history of the firmware repository [1], both the master branch history
and the tags now point to different commit SHAs.
[1] https://github.com/Infineon/ifx-linux-firmware
^ permalink raw reply
* Re: [PATCH 1/2] mt76: connac: fix txpower_cur not updated in mt76_connac_mcu_set_rate_txpower()
From: bryam vargas @ 2026-02-27 9:58 UTC (permalink / raw)
To: linux-wireless; +Cc: nbd, lorenzo
In-Reply-To: <CANAPQzi3BkfnRS4CEXAA560O5cO8e6MEYxeVVx1u+xUeXS-gmA@mail.gmail.com>
[PATCH 2/2] mt76: mt7921u: add USB reset on SEFI chip recovery
From 86976b5908219204f7719d947fd6c5f1c5e11c7f Mon Sep 17 00:00:00 2001
From: bryam <bryamestebanvargas@gmail.com>
Date: Fri, 27 Feb 2026 04:30:01 -0500
Subject: [PATCH 2/2] mt76: mt7921u: add USB reset on SEFI chip recovery
The MT7921U chip is susceptible to Single Event Functional Interrupts
(SEFIs) caused by cosmic radiation, particularly at high altitudes.
When a SEFI occurs, the chip becomes unresponsive and requires a USB
reset to recover.
Add usb_queue_reset_device() calls in the SEFI detection path to
trigger automatic recovery instead of leaving the interface hung.
Tested-on: Minisforum NAB9 (MT7921U USB adapter) at 2400m altitude,
Bogotá, Colombia. Cosmic radiation causes periodic SEFI
events; USB reset restores connectivity without intervention.
Signed-off-by: Bryam Vargas <bryamestebanvargas@gmail.com>
---
drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 12 ++++++++++++
drivers/net/wireless/mediatek/mt76/mt792x_usb.c | 10 ++++++++++
2 files changed, 22 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
index 100bdba..8c8c78f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
@@ -86,6 +86,7 @@ static int mt7921u_mcu_init(struct mt792x_dev *dev)
static int mt7921u_mac_reset(struct mt792x_dev *dev)
{
+ struct usb_interface *intf = to_usb_interface(dev->mt76.dev);
int err;
mt76_txq_schedule_all(&dev->mphy);
@@ -100,6 +101,17 @@ static int mt7921u_mac_reset(struct mt792x_dev *dev)
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
+ /* When the chip enters a latched state (SEFI - Single Event
+ * Functional Interrupt, e.g. from cosmic radiation at altitude),
+ * all register writes over USB become silent no-ops.
+ * usb_queue_reset_device() electrically resets the chip via the
+ * USB hub regardless of internal state -- identical to probe().
+ * Async variant required to avoid deadlock in workqueue context.
+ */
+ dev_warn(dev->mt76.dev,
+ "mt7921u: scheduling USB reset for chip recovery\n");
+ usb_queue_reset_device(intf);
+
mt792xu_wfsys_reset(dev);
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
index 76272a0..cfd385e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
@@ -269,6 +269,8 @@ EXPORT_SYMBOL_GPL(mt792xu_wfsys_reset);
int mt792xu_init_reset(struct mt792x_dev *dev)
{
+ struct usb_interface *intf = to_usb_interface(dev->mt76.dev);
+
set_bit(MT76_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
@@ -277,6 +279,14 @@ int mt792xu_init_reset(struct mt792x_dev *dev)
mt76u_stop_rx(&dev->mt76);
mt76u_stop_tx(&dev->mt76);
+ /* Same rationale as mt7921u_mac_reset(): if the chip is in a
+ * latched state (SEFI), register writes over USB are no-ops.
+ * Schedule a USB port reset before software reset sequence.
+ */
+ dev_warn(dev->mt76.dev,
+ "mt7921u: scheduling USB device reset (init_reset path)\n");
+ usb_queue_reset_device(intf);
+
mt792xu_wfsys_reset(dev);
clear_bit(MT76_RESET, &dev->mphy.state);
--
2.43.0
^ permalink raw reply related
* [PATCH ath-next v2] wifi: ath11k: Pass the correct value of each TID during a stop AMPDU session
From: Reshma Immaculate Rajkumar @ 2026-02-27 9:56 UTC (permalink / raw)
To: ath11k; +Cc: linux-wireless, Reshma Immaculate Rajkumar
During ongoing traffic, a request to stop an AMPDU session
for one TID could incorrectly affect other active sessions.
This can happen because an incorrect TID reference would be
passed when updating the BA session state, causing the wrong
session to be stopped. As a result, the affected session would
be reduced to a minimal BA size, leading to a noticeable
throughput degradation.
Fix this issue by passing the correct argument from
ath11k_dp_rx_ampdu_stop() to ath11k_peer_rx_tid_reo_update()
during a stop AMPDU session. Instead of passing peer->tx_tid, which
is the base address of the array, corresponding to TID 0; pass
the value of &peer->rx_tid[params->tid], where the different TID numbers
are accounted for.
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1
Fixes: d5c65159f2895 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Signed-off-by: Reshma Immaculate Rajkumar <reshma.rajkumar@oss.qualcomm.com>
---
v2:
* Added QTI yearless copyright
drivers/net/wireless/ath/ath11k/dp_rx.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index b9e976ddcbbf..00d27e0053b2 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/ieee80211.h>
@@ -1110,9 +1111,8 @@ int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
struct ath11k_base *ab = ar->ab;
struct ath11k_peer *peer;
struct ath11k_sta *arsta = ath11k_sta_to_arsta(params->sta);
+ struct dp_rx_tid *rx_tid;
int vdev_id = arsta->arvif->vdev_id;
- dma_addr_t paddr;
- bool active;
int ret;
spin_lock_bh(&ab->base_lock);
@@ -1124,15 +1124,14 @@ int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
return -ENOENT;
}
- paddr = peer->rx_tid[params->tid].paddr;
- active = peer->rx_tid[params->tid].active;
+ rx_tid = &peer->rx_tid[params->tid];
- if (!active) {
+ if (!rx_tid->active) {
spin_unlock_bh(&ab->base_lock);
return 0;
}
- ret = ath11k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false);
+ ret = ath11k_peer_rx_tid_reo_update(ar, peer, rx_tid, 1, 0, false);
spin_unlock_bh(&ab->base_lock);
if (ret) {
ath11k_warn(ab, "failed to update reo for rx tid %d: %d\n",
@@ -1141,7 +1140,7 @@ int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
}
ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id,
- params->sta->addr, paddr,
+ params->sta->addr, rx_tid->paddr,
params->tid, 1, 1);
if (ret)
ath11k_warn(ab, "failed to send wmi to delete rx tid %d\n",
base-commit: 8bf22c33e7a172fbc72464f4cc484d23a6b412ba
--
2.34.1
^ permalink raw reply related
* [PATCH 1/2] mt76: connac: fix txpower_cur not updated in mt76_connac_mcu_set_rate_txpower()
From: bryam vargas @ 2026-02-27 9:48 UTC (permalink / raw)
To: linux-wireless; +Cc: nbd, lorenzo
From 0a29ccaeb2211451b88ad71c4c0cdbc418b7d64d Mon Sep 17 00:00:00 2001
From: bryam <bryamestebanvargas@gmail.com>
Date: Fri, 27 Feb 2026 04:30:01 -0500
Subject: [PATCH 1/2] mt76: connac: fix txpower_cur not updated in
mt76_connac_mcu_set_rate_txpower()
mt76_connac_mcu_set_rate_txpower() sends the TX power SKU table to the
firmware but never updates mphy->txpower_cur. This causes mt76_get_txpower()
to always report 3 dBm regardless of the actual configured power level,
since txpower_cur remains at its zero-initialized value and only the
path delta for 2 chains (6 units of 0.5 dBm) gets applied.
Fix this by calculating the effective TX power using the same approach
as mt7915: mt76_get_power_bound() applies SAR constraints and chain
delta, then mt76_get_rate_power_limits() applies the per-rate EEPROM
limits, yielding the actual value the firmware will use.
Fixes: 3b4a3bdba808 ("mt76: mt7921: add support for reporting tx power")
Signed-off-by: Bryam Vargas <bryamestebanvargas@gmail.com>
---
.../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index fc3e672..4ed31ff 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -2272,6 +2272,20 @@ int mt76_connac_mcu_set_rate_txpower(struct
mt76_phy *phy)
return err;
}
+ /* Update txpower_cur so mt76_get_txpower() reports the actual
+ * configured TX power instead of always returning 3 dBm due to
+ * txpower_cur being left at its zero-initialized value.
+ * The value is stored in 0.5 dBm units as used by the SKU table.
+ */
+ if (phy->chandef.chan) {
+ struct mt76_power_limits limits;
+ s8 tx_power;
+
+ tx_power = mt76_get_power_bound(phy, phy->chandef.chan->max_power);
+ tx_power = mt76_get_rate_power_limits(phy, phy->chandef.chan,
+ &limits, tx_power);
+ phy->txpower_cur = tx_power;
+ }
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);
--
2.43.0
^ permalink raw reply related
* [wireless-next:main] BUILD SUCCESS 0314e382cf02983eb3c33ac537ad9701e7858bc9
From: kernel test robot @ 2026-02-27 9:04 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: Johannes Berg, linux-wireless
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
branch HEAD: 0314e382cf02983eb3c33ac537ad9701e7858bc9 Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
elapsed time: 844m
configs tested: 279
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha alldefconfig gcc-15.2.0
alpha allnoconfig gcc-15.2.0
alpha allyesconfig gcc-15.2.0
alpha defconfig gcc-15.2.0
arc allmodconfig clang-16
arc allmodconfig gcc-15.2.0
arc allnoconfig gcc-15.2.0
arc allyesconfig clang-23
arc allyesconfig gcc-15.2.0
arc defconfig gcc-15.2.0
arc nsimosci_hs_defconfig gcc-15.2.0
arc randconfig-001-20260227 gcc-8.5.0
arc randconfig-002-20260227 gcc-8.5.0
arm allnoconfig clang-23
arm allnoconfig gcc-15.2.0
arm allyesconfig clang-16
arm allyesconfig gcc-15.2.0
arm defconfig gcc-15.2.0
arm jornada720_defconfig clang-23
arm neponset_defconfig gcc-15.2.0
arm randconfig-001-20260227 gcc-14.3.0
arm randconfig-001-20260227 gcc-8.5.0
arm randconfig-002-20260227 clang-23
arm randconfig-002-20260227 gcc-8.5.0
arm randconfig-003-20260227 gcc-15.2.0
arm randconfig-003-20260227 gcc-8.5.0
arm randconfig-004-20260227 clang-23
arm randconfig-004-20260227 gcc-8.5.0
arm sama7_defconfig gcc-15.2.0
arm socfpga_defconfig gcc-15.2.0
arm wpcm450_defconfig gcc-15.2.0
arm64 allmodconfig clang-19
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-15.2.0
arm64 defconfig gcc-15.2.0
arm64 randconfig-001-20260227 clang-23
arm64 randconfig-002-20260227 clang-23
arm64 randconfig-002-20260227 gcc-15.2.0
arm64 randconfig-003-20260227 clang-23
arm64 randconfig-004-20260227 clang-23
arm64 randconfig-004-20260227 gcc-8.5.0
csky allmodconfig gcc-15.2.0
csky allnoconfig gcc-15.2.0
csky defconfig clang-23
csky defconfig gcc-15.2.0
csky randconfig-001-20260227 clang-23
csky randconfig-001-20260227 gcc-15.2.0
csky randconfig-002-20260227 clang-23
csky randconfig-002-20260227 gcc-10.5.0
hexagon alldefconfig gcc-15.2.0
hexagon allmodconfig clang-17
hexagon allmodconfig gcc-15.2.0
hexagon allnoconfig clang-23
hexagon allnoconfig gcc-15.2.0
hexagon defconfig gcc-15.2.0
hexagon randconfig-001-20260227 clang-23
hexagon randconfig-002-20260227 clang-23
i386 allmodconfig clang-20
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allnoconfig gcc-15.2.0
i386 allyesconfig clang-20
i386 allyesconfig gcc-14
i386 buildonly-randconfig-001-20260227 clang-20
i386 buildonly-randconfig-002-20260227 clang-20
i386 buildonly-randconfig-003-20260227 clang-20
i386 buildonly-randconfig-004-20260227 clang-20
i386 buildonly-randconfig-005-20260227 clang-20
i386 buildonly-randconfig-006-20260227 clang-20
i386 defconfig gcc-15.2.0
i386 randconfig-001-20260227 clang-20
i386 randconfig-002-20260227 clang-20
i386 randconfig-003-20260227 clang-20
i386 randconfig-003-20260227 gcc-14
i386 randconfig-004-20260227 clang-20
i386 randconfig-004-20260227 gcc-14
i386 randconfig-005-20260227 clang-20
i386 randconfig-005-20260227 gcc-12
i386 randconfig-006-20260227 clang-20
i386 randconfig-006-20260227 gcc-14
i386 randconfig-007-20260227 clang-20
i386 randconfig-011-20260227 gcc-14
i386 randconfig-012-20260227 gcc-14
i386 randconfig-013-20260227 gcc-14
i386 randconfig-014-20260227 gcc-14
i386 randconfig-015-20260227 gcc-14
i386 randconfig-016-20260227 gcc-14
i386 randconfig-017-20260227 gcc-14
loongarch alldefconfig clang-23
loongarch allmodconfig clang-19
loongarch allmodconfig clang-23
loongarch allnoconfig clang-23
loongarch allnoconfig gcc-15.2.0
loongarch defconfig clang-19
loongarch randconfig-001-20260227 clang-23
loongarch randconfig-001-20260227 gcc-15.2.0
loongarch randconfig-002-20260227 clang-20
loongarch randconfig-002-20260227 clang-23
m68k allmodconfig gcc-15.2.0
m68k allnoconfig gcc-15.2.0
m68k allyesconfig clang-16
m68k allyesconfig gcc-15.2.0
m68k amiga_defconfig gcc-15.2.0
m68k defconfig clang-19
m68k hp300_defconfig gcc-15.2.0
m68k m5272c3_defconfig gcc-15.2.0
m68k m5275evb_defconfig gcc-15.2.0
m68k sun3_defconfig clang-23
microblaze allnoconfig gcc-15.2.0
microblaze allyesconfig gcc-15.2.0
microblaze defconfig clang-19
mips allmodconfig gcc-15.2.0
mips allnoconfig gcc-15.2.0
mips allyesconfig gcc-15.2.0
mips bmips_be_defconfig clang-23
mips jazz_defconfig gcc-15.2.0
mips maltaup_xpa_defconfig gcc-15.2.0
mips sb1250_swarm_defconfig gcc-15.2.0
nios2 allmodconfig clang-23
nios2 allmodconfig gcc-11.5.0
nios2 allnoconfig clang-23
nios2 allnoconfig gcc-11.5.0
nios2 defconfig clang-19
nios2 randconfig-001-20260227 clang-23
nios2 randconfig-001-20260227 gcc-11.5.0
nios2 randconfig-002-20260227 clang-23
nios2 randconfig-002-20260227 gcc-11.5.0
openrisc allmodconfig clang-23
openrisc allmodconfig gcc-15.2.0
openrisc allnoconfig clang-23
openrisc allnoconfig gcc-15.2.0
openrisc de0_nano_defconfig gcc-15.2.0
openrisc defconfig gcc-15.2.0
openrisc or1ksim_defconfig gcc-15.2.0
openrisc simple_smp_defconfig clang-23
parisc allmodconfig gcc-15.2.0
parisc allnoconfig clang-23
parisc allnoconfig gcc-15.2.0
parisc allyesconfig clang-19
parisc allyesconfig gcc-15.2.0
parisc defconfig gcc-15.2.0
parisc randconfig-001-20260227 clang-17
parisc randconfig-001-20260227 gcc-8.5.0
parisc randconfig-002-20260227 clang-17
parisc64 defconfig clang-19
powerpc adder875_defconfig gcc-15.2.0
powerpc allmodconfig gcc-15.2.0
powerpc allnoconfig clang-23
powerpc allnoconfig gcc-15.2.0
powerpc canyonlands_defconfig gcc-15.2.0
powerpc holly_defconfig clang-23
powerpc icon_defconfig gcc-15.2.0
powerpc iss476-smp_defconfig gcc-15.2.0
powerpc kmeter1_defconfig gcc-15.2.0
powerpc motionpro_defconfig gcc-15.2.0
powerpc mpc834x_itx_defconfig gcc-15.2.0
powerpc mpc866_ads_defconfig gcc-15.2.0
powerpc pasemi_defconfig gcc-15.2.0
powerpc rainier_defconfig clang-23
powerpc randconfig-001-20260227 clang-17
powerpc randconfig-002-20260227 clang-17
powerpc socrates_defconfig clang-23
powerpc stx_gp3_defconfig gcc-15.2.0
powerpc taishan_defconfig gcc-15.2.0
powerpc tqm5200_defconfig gcc-15.2.0
powerpc tqm8555_defconfig clang-23
powerpc64 randconfig-001-20260227 clang-17
powerpc64 randconfig-002-20260227 clang-17
powerpc64 randconfig-002-20260227 gcc-14.3.0
riscv allmodconfig clang-23
riscv allnoconfig clang-23
riscv allnoconfig gcc-15.2.0
riscv allyesconfig clang-16
riscv defconfig clang-23
riscv defconfig gcc-15.2.0
riscv randconfig-001-20260227 gcc-12.5.0
riscv randconfig-002-20260227 gcc-12.5.0
s390 allmodconfig clang-18
s390 allmodconfig clang-19
s390 allnoconfig clang-23
s390 allyesconfig gcc-15.2.0
s390 defconfig clang-23
s390 defconfig gcc-15.2.0
s390 randconfig-001-20260227 gcc-12.5.0
s390 randconfig-002-20260227 gcc-12.5.0
sh allmodconfig gcc-15.2.0
sh allnoconfig clang-23
sh allnoconfig gcc-15.2.0
sh allyesconfig clang-19
sh allyesconfig gcc-15.2.0
sh defconfig gcc-14
sh defconfig gcc-15.2.0
sh kfr2r09_defconfig gcc-15.2.0
sh r7780mp_defconfig gcc-15.2.0
sh randconfig-001-20260227 gcc-12.5.0
sh randconfig-002-20260227 gcc-12.5.0
sh rsk7203_defconfig gcc-15.2.0
sh se7343_defconfig clang-23
sh se7705_defconfig clang-23
sh se7750_defconfig gcc-15.2.0
sh secureedge5410_defconfig gcc-15.2.0
sh sh2007_defconfig clang-23
sh sh7710voipgw_defconfig clang-23
sh sh7724_generic_defconfig clang-23
sparc allnoconfig clang-23
sparc allnoconfig gcc-15.2.0
sparc defconfig gcc-15.2.0
sparc randconfig-001-20260227 clang-23
sparc randconfig-002-20260227 clang-23
sparc64 allmodconfig clang-23
sparc64 defconfig clang-20
sparc64 defconfig gcc-14
sparc64 randconfig-001-20260227 clang-23
sparc64 randconfig-002-20260227 clang-23
um allmodconfig clang-19
um allnoconfig clang-23
um allyesconfig gcc-14
um allyesconfig gcc-15.2.0
um defconfig clang-23
um defconfig gcc-14
um i386_defconfig gcc-14
um randconfig-001-20260227 clang-23
um randconfig-002-20260227 clang-23
um x86_64_defconfig clang-23
um x86_64_defconfig gcc-14
x86_64 allmodconfig clang-20
x86_64 allnoconfig clang-20
x86_64 allnoconfig clang-23
x86_64 allyesconfig clang-20
x86_64 buildonly-randconfig-001-20260227 gcc-14
x86_64 buildonly-randconfig-002-20260227 gcc-14
x86_64 buildonly-randconfig-003-20260227 gcc-14
x86_64 buildonly-randconfig-004-20260227 gcc-14
x86_64 buildonly-randconfig-005-20260227 gcc-14
x86_64 buildonly-randconfig-006-20260227 gcc-14
x86_64 defconfig gcc-14
x86_64 kexec clang-20
x86_64 randconfig-001-20260227 clang-20
x86_64 randconfig-001-20260227 gcc-13
x86_64 randconfig-002-20260227 clang-20
x86_64 randconfig-002-20260227 gcc-13
x86_64 randconfig-003-20260227 gcc-13
x86_64 randconfig-003-20260227 gcc-14
x86_64 randconfig-004-20260227 gcc-13
x86_64 randconfig-005-20260227 gcc-13
x86_64 randconfig-005-20260227 gcc-14
x86_64 randconfig-006-20260227 gcc-13
x86_64 randconfig-006-20260227 gcc-14
x86_64 randconfig-011-20260227 gcc-14
x86_64 randconfig-012-20260227 gcc-14
x86_64 randconfig-013-20260227 clang-20
x86_64 randconfig-013-20260227 gcc-14
x86_64 randconfig-014-20260227 clang-20
x86_64 randconfig-014-20260227 gcc-14
x86_64 randconfig-015-20260227 clang-20
x86_64 randconfig-015-20260227 gcc-14
x86_64 randconfig-016-20260227 gcc-14
x86_64 randconfig-071-20260227 gcc-14
x86_64 randconfig-072-20260227 gcc-14
x86_64 randconfig-073-20260227 gcc-14
x86_64 randconfig-074-20260227 gcc-14
x86_64 randconfig-075-20260227 gcc-14
x86_64 randconfig-076-20260227 gcc-14
x86_64 rhel-9.4 clang-20
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-func clang-20
x86_64 rhel-9.4-kselftests clang-20
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-20
xtensa allnoconfig clang-23
xtensa allnoconfig gcc-15.2.0
xtensa allyesconfig clang-23
xtensa allyesconfig gcc-15.2.0
xtensa audio_kc705_defconfig gcc-15.2.0
xtensa cadence_csp_defconfig gcc-15.2.0
xtensa generic_kc705_defconfig gcc-15.2.0
xtensa randconfig-001-20260227 clang-23
xtensa randconfig-002-20260227 clang-23
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox