* [PATCH v4 9/9] arm64: dts: amlogic: t7: khadas-vim4: Add MMC nodes
From: Ronald Claveau @ 2026-03-25 9:15 UTC (permalink / raw)
To: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Johannes Berg, van Spriel
Cc: linux-arm-kernel, linux-amlogic, devicetree, linux-kernel,
linux-mmc, linux-wireless, Ronald Claveau
In-Reply-To: <20260325-add-emmc-t7-vim4-v4-0-44c7b4a5e459@aliel.fr>
Enable and configure the three MMC controllers for the Khadas VIM4 board:
- sd_emmc_a: SDIO interface for the BCM43752 Wi-Fi module
- sd_emmc_b: SD card slot
- sd_emmc_c: eMMC storage
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
.../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 90 +++++++++++++++++++++-
1 file changed, 89 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
index 770f06b0b16c7..5a73ae081036c 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
@@ -14,7 +14,10 @@ / {
compatible = "khadas,vim4", "amlogic,a311d2", "amlogic,t7";
aliases {
- serial0 = &uart_a;
+ serial0 = &uart_a;
+ mmc0 = &sd_emmc_c;
+ mmc1 = &sd_emmc_b;
+ mmc2 = &sd_emmc_a;
};
memory@0 {
@@ -159,6 +162,91 @@ &pwm_ab {
pinctrl-names = "default";
};
+/* SDIO */
+&sd_emmc_a {
+ status = "okay";
+ pinctrl-0 = <&sdio_pins>;
+ pinctrl-1 = <&sdio_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bus-width = <4>;
+ cap-sd-highspeed;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ cap-sdio-irq;
+ max-frequency = <200000000>;
+ non-removable;
+ disable-wp;
+ no-mmc;
+ no-sd;
+
+ power-domains = <&pwrc PWRC_T7_SDIO_A_ID>;
+
+ keep-power-in-suspend;
+
+ mmc-pwrseq = <&sdio_pwrseq>;
+
+ vmmc-supply = <&vddao_3v3>;
+ vqmmc-supply = <&vddao_1v8>;
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm43752-fmac", "brcm,bcm4329-fmac";
+ };
+};
+
+/* SD card */
+&sd_emmc_b {
+ status = "okay";
+ pinctrl-0 = <&sdcard_pins>;
+ pinctrl-1 = <&sdcard_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <4>;
+ cap-sd-highspeed;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ max-frequency = <200000000>;
+ disable-wp;
+ no-sdio;
+ no-mmc;
+
+ power-domains = <&pwrc PWRC_T7_SDIO_B_ID>;
+
+ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&sd_3v3>;
+ vqmmc-supply = <&vddio_c>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+ status = "okay";
+ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ max-frequency = <200000000>;
+ disable-wp;
+ non-removable;
+ no-sdio;
+ no-sd;
+
+ power-domains = <&pwrc PWRC_T7_EMMC_ID>;
+
+ vmmc-supply = <&vddio_3v3>;
+ vqmmc-supply = <&vddio_1v8>;
+};
+
&uart_a {
status = "okay";
clocks = <&xtal>, <&xtal>, <&xtal>;
--
2.49.0
^ permalink raw reply related
* Re: [PATCH] wifi: virt_wifi: remove SET_NETDEV_DEV to avoid use-after-free
From: Breno Leitao @ 2026-03-25 9:23 UTC (permalink / raw)
To: Alexander Popov
Cc: Andrew Lunn, Jakub Kicinski, David Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Maxime Chevallier, Michal Kubecek,
Gal Pressman, Kory Maincent, Oleksij Rempel, Ido Schimmel,
Heiner Kallweit, Greg KH, Johannes Berg, James Guan, Kees Cook,
Paul Moses, linux-wireless, netdev, linux-kernel, security,
notify
In-Reply-To: <20260324224607.374327-1-alex.popov@linux.com>
On Wed, Mar 25, 2026 at 01:46:02AM +0300, Alexander Popov wrote:
> Currently we execute `SET_NETDEV_DEV(dev, &priv->lowerdev->dev)` for
> the virt_wifi net devices. However, unregistering a virt_wifi device in
> netdev_run_todo() can happen together with the device referenced by
> SET_NETDEV_DEV().
>
> It can result in use-after-free during the ethtool operations performed
> on a virt_wifi device that is currently being unregistered. Such a net
> device can have the `dev.parent` field pointing to the freed memory,
> but ethnl_ops_begin() calls `pm_runtime_get_sync(dev->dev.parent)`.
>
> Let's remove SET_NETDEV_DEV for virt_wifi to avoid bugs like this:
>
> ==================================================================
> BUG: KASAN: slab-use-after-free in __pm_runtime_resume+0xe2/0xf0
> Read of size 2 at addr ffff88810cfc46f8 by task pm/606
>
> Call Trace:
> <TASK>
> dump_stack_lvl+0x4d/0x70
> print_report+0x170/0x4f3
> ? __pfx__raw_spin_lock_irqsave+0x10/0x10
> kasan_report+0xda/0x110
> ? __pm_runtime_resume+0xe2/0xf0
> ? __pm_runtime_resume+0xe2/0xf0
> __pm_runtime_resume+0xe2/0xf0
> ethnl_ops_begin+0x49/0x270
> ethnl_set_features+0x23c/0xab0
> ? __pfx_ethnl_set_features+0x10/0x10
> ? kvm_sched_clock_read+0x11/0x20
> ? local_clock_noinstr+0xf/0xf0
> ? local_clock+0x10/0x30
> ? kasan_save_track+0x25/0x60
> ? __kasan_kmalloc+0x7f/0x90
> ? genl_family_rcv_msg_attrs_parse.isra.0+0x150/0x2c0
> genl_family_rcv_msg_doit+0x1e7/0x2c0
> ? __pfx_genl_family_rcv_msg_doit+0x10/0x10
> ? __pfx_cred_has_capability.isra.0+0x10/0x10
> ? stack_trace_save+0x8e/0xc0
> genl_rcv_msg+0x411/0x660
> ? __pfx_genl_rcv_msg+0x10/0x10
> ? __pfx_ethnl_set_features+0x10/0x10
> netlink_rcv_skb+0x121/0x380
> ? __pfx_genl_rcv_msg+0x10/0x10
> ? __pfx_netlink_rcv_skb+0x10/0x10
> ? __pfx_down_read+0x10/0x10
> genl_rcv+0x23/0x30
> netlink_unicast+0x60f/0x830
> ? __pfx_netlink_unicast+0x10/0x10
> ? __pfx___alloc_skb+0x10/0x10
> netlink_sendmsg+0x6ea/0xbc0
> ? __pfx_netlink_sendmsg+0x10/0x10
> ? __futex_queue+0x10b/0x1f0
> ____sys_sendmsg+0x7a2/0x950
> ? copy_msghdr_from_user+0x26b/0x430
> ? __pfx_____sys_sendmsg+0x10/0x10
> ? __pfx_copy_msghdr_from_user+0x10/0x10
> ___sys_sendmsg+0xf8/0x180
> ? __pfx____sys_sendmsg+0x10/0x10
> ? __pfx_futex_wait+0x10/0x10
> ? fdget+0x2e4/0x4a0
> __sys_sendmsg+0x11f/0x1c0
> ? __pfx___sys_sendmsg+0x10/0x10
> do_syscall_64+0xe2/0x570
> ? exc_page_fault+0x66/0xb0
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
> </TASK>
>
> This fix may be combined with another one in the ethtool subsystem:
> https://lore.kernel.org/all/20260322075917.254874-1-alex.popov@linux.com/T/#u
>
> Fixes: d43c65b05b848e0b ("ethtool: runtime-resume netdev parent in ethnl_ops_begin")
> Cc: stable@vger.kernel.org
> Signed-off-by: Alexander Popov <alex.popov@linux.com>
Reviewed-by: Breno Leitao <leitao@debian.org>
^ permalink raw reply
* pull-request: wifi: iwlwifi: updates - 2026-03-25
From: Korenblit, Miriam Rachel @ 2026-03-25 9:37 UTC (permalink / raw)
To: Linux Wireless
The following changes since commit 7109310c5031075ecb9b5da75b1443557c232dcd:
Merge tag 'mt76-next-2026-03-23' of https://github.com/nbd168/wireless (2026-03-24 17:12:46 +0100)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git/ tags/iwlwifi-next-2026-03-25
for you to fetch changes up to 95d12fc4ef4522757c25cba866cc4b8a5f01760f:
wifi: iwlwifi: mld: set RX_FLAG_RADIOTAP_TLV_AT_END generically (2026-03-25 11:31:58 +0200)
----------------------------------------------------------------
wifi: iwlwifi: updates - 2026-03-25
----------------------------------------------------------------
Avinash Bhatt (3):
wifi: iwlwifi: add CQM event support for per-link RSSI changes
wifi: iwlwifi: handle NULL/ERR returns from ptp_clock_register()
wifi: iwlwifi: mld: block EMLSR during TDLS connections
Emmanuel Grumbach (27):
wifi: iwlwifi: mld: add support for iwl_mcc_allowed_ap_type_cmd v2
wifi: iwlwifi: ensure we don't read SAR values past the limit
wifi: iwlwifi: uefi: decouple UEFI and firmware APIs
wifi: iwlwifi: acpi: better use ARRAY_SIZE than a define
wifi: iwlwifi: uefi: open code the PPAG table store operation
wifi: iwlwifi: bring iwl_fill_ppag_table to the iwlmvm
wifi: iwlwifi: regulatory: support a new command for PPAG
wifi: iwlwifi: acpi: check the size of the ACPI PPAG tables
wifi: iwlwifi: acpi: add support for PPAG rev5
wifi: iwlwifi: uefi: add support for PPAG table rev5
wifi: iwlwifi: mvm: zero iwl_geo_tx_power_profiles_cmd before sending
wifi: iwlwifi: uefi: support the new WRDS and EWRD tables
wifi: iwlwifi: acpi: add support for WRDS rev 3 table
wifi: iwlwifi: acpi: add support for EWRD rev 3 table
wifi: iwlwifi: mld: support version 11 of REDUCE_TX_POWER_CMD
wifi: iwlwifi: uefi: open code the parsing of the WGDS table
wifi: iwlwifi: uefi: add support for WGDS rev4
wifi: iwlwifi: acpi: validate the WGDS table
wifi: iwlwifi: acpi: add support for WGDS revision 4
wifi: iwlwifi: support PER_CHAIN_LIMIT_OFFSET_CMD v6
wifi: iwlwifi: uefi: mode the comments valid kerneldoc comments
wifi: iwlwifi: remove IWL_MAX_WD_TIMEOUT
wifi: iwlwifi: mld: remove SCAN_TIMEOUT_MSEC
wifi: iwlwifi: mld: update the TLC when we deactivate a link
wifi: iwlwifi: TLC_MNG_CONFIG_CMD can use several structures
wifi: iwlwifi: fix the description of SESSION_PROTECTION_CMD
wifi: iwlwifi: reduce the number of prints upon firmware crash
Ilan Peer (2):
wifi: iwlwifi: mld: Refactor scan command handling
wifi: iwlwifi: mld: Introduce scan command version 18
Johannes Berg (13):
wifi: iwlwifi: restrict TOP reset to some devices
wifi: iwlwifi: mld: enable UHR in TLC
wifi: iwlwifi: mld: set UHR MCS in RX status
wifi: iwlwifi: mld: support changing iftype at runtime
wifi: iwlwifi: use IWL_FW_CHECK for sync timeout
wifi: iwlwifi: pcie: don't dump on reset handshake in dump
wifi: iwlwifi: mld: make iwl_mld_mac80211_iftype_to_fw() static
wifi: iwlwifi: mld: remove type argument from iwl_mld_add_sta()
wifi: iwlwifi: mld: rename iwl_mld_phy_from_mac80211() argument
wifi: iwlwifi: mld: make alloc functions not forced static
wifi: iwlwifi: mld: add double-include guards to nan.h
wifi: iwlwifi: add MAC context command version 4
wifi: iwlwifi: mld: set RX_FLAG_RADIOTAP_TLV_AT_END generically
Marco Crivellari (3):
wifi: iwlwifi: replace use of system_unbound_wq with system_dfl_wq
wifi: iwlwifi: fw: replace use of system_unbound_wq with system_dfl_wq
wifi: iwlwifi: mvm: replace use of system_wq with system_percpu_wq
Miri Korenblit (7):
wifi: iwlwifi: mld: add support for sta command version 3
wifi: iwlwifi: bump core version for BZ/SC/DR
wifi: iwlwifi: validate the channels received in iwl_mcc_update_resp_v*
wifi: iwlwifi: mld: use the dedicated helper to extract a link
wifi: iwlwifi: mld: always assign a fw id to a vif
wifi: iwlwifi: add a macro for max FW links
wifi: iwlwifi: mld: introduce iwl_mld_vif_fw_id_valid
Nidhish A N (1):
wifi: iwlwifi: mvm: cleanup some more MLO code
Pagadala Yesu Anjaneyulu (4):
wifi: iwlwifi: mld: remove unused scan expire time constants
wifi: iwlwifi: fw: Add TLV support for BIOS revision of command
wifi: iwlwifi: mld: eliminate duplicate WIDE_ID in PPAG command handling
wifi: iwlwifi: mld: add BIOS revision compatibility check for PPAG command
drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 132 ++++++++--
drivers/net/wireless/intel/iwlwifi/fw/acpi.h | 28 +-
.../net/wireless/intel/iwlwifi/fw/api/datapath.h | 3 +-
.../net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | 167 +++++++++++-
drivers/net/wireless/intel/iwlwifi/fw/api/mac.h | 6 +-
.../net/wireless/intel/iwlwifi/fw/api/nvm-reg.h | 18 +-
drivers/net/wireless/intel/iwlwifi/fw/api/power.h | 37 ++-
drivers/net/wireless/intel/iwlwifi/fw/api/scan.h | 45 ++++
drivers/net/wireless/intel/iwlwifi/fw/api/stats.h | 5 +-
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 +-
drivers/net/wireless/intel/iwlwifi/fw/dump.c | 69 +----
drivers/net/wireless/intel/iwlwifi/fw/file.h | 15 ++
drivers/net/wireless/intel/iwlwifi/fw/img.c | 32 ++-
drivers/net/wireless/intel/iwlwifi/fw/img.h | 8 +
drivers/net/wireless/intel/iwlwifi/fw/regulatory.c | 151 ++---------
drivers/net/wireless/intel/iwlwifi/fw/regulatory.h | 14 +-
drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 10 +-
drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 236 ++++++++++++++---
drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 141 +++++++---
drivers/net/wireless/intel/iwlwifi/iwl-config.h | 1 -
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 23 +-
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 9 +-
drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 10 +-
drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 20 +-
drivers/net/wireless/intel/iwlwifi/mld/constants.h | 1 -
drivers/net/wireless/intel/iwlwifi/mld/fw.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mld/iface.c | 22 +-
drivers/net/wireless/intel/iwlwifi/mld/iface.h | 15 +-
drivers/net/wireless/intel/iwlwifi/mld/link.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mld/link.h | 2 +
.../net/wireless/intel/iwlwifi/mld/low_latency.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 52 +++-
drivers/net/wireless/intel/iwlwifi/mld/mld.h | 6 +-
drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 4 +-
drivers/net/wireless/intel/iwlwifi/mld/nan.h | 5 +-
drivers/net/wireless/intel/iwlwifi/mld/phy.h | 4 +-
drivers/net/wireless/intel/iwlwifi/mld/power.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mld/ptp.c | 4 +-
.../net/wireless/intel/iwlwifi/mld/regulatory.c | 178 ++++++++++---
.../net/wireless/intel/iwlwifi/mld/regulatory.h | 2 +-
drivers/net/wireless/intel/iwlwifi/mld/rx.c | 25 +-
drivers/net/wireless/intel/iwlwifi/mld/scan.c | 224 ++++++++++++----
drivers/net/wireless/intel/iwlwifi/mld/scan.h | 2 +
drivers/net/wireless/intel/iwlwifi/mld/sta.c | 50 +++-
drivers/net/wireless/intel/iwlwifi/mld/sta.h | 4 +-
drivers/net/wireless/intel/iwlwifi/mld/stats.c | 31 ++-
.../net/wireless/intel/iwlwifi/mld/tests/utils.c | 8 +-
drivers/net/wireless/intel/iwlwifi/mld/tlc.c | 78 +++++-
drivers/net/wireless/intel/iwlwifi/mld/tlc.h | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 157 ++++++++++-
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 7 +-
drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c | 46 ----
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c | 18 +-
.../net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 132 ----------
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c | 291 +--------------------
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 5 -
drivers/net/wireless/intel/iwlwifi/mvm/ptp.c | 4 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 4 -
drivers/net/wireless/intel/iwlwifi/mvm/tdls.c | 6 +-
.../intel/iwlwifi/pcie/gen1_2/trans-gen2.c | 13 +-
.../net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 2 +-
64 files changed, 1624 insertions(+), 993 deletions(-)
^ permalink raw reply
* Re: [PATCH] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: Óscar Alfonso Díaz @ 2026-03-25 10:59 UTC (permalink / raw)
To: 傅继晗; +Cc: johannes, linux-wireless, linux-kernel, stable
In-Reply-To: <20260325001513.1303-1-fjhhz1997@gmail.com>
Hello everybody. I've tested this patch and I'm sorry to say this...
but, bad news. Same behaviour. I mean, as soon as the DoS window
appears during the evil twin attack, the VM is completely frozen.
I put the full report including screenshots on the github thread:
https://github.com/morrownr/USB-WiFi/issues/682
If you are interested in reproducing what I do, it is pretty simple.
You just need linux, one wireless adapter using an affected by the bug
Mediatek chipset (in my case chipset is MT7921U, also tested on
MT7921AUN), a wireless network and a client connected (your mobile
phone is enough). Use the airgeddon tool and launch the most simple
evil twin attack over it:
git clone https://github.com/v1s1t0r1sh3r3/airgeddon
cd airgeddon
bash airgeddon.sh
Navigate through menus selecting the Mediatek adapter, then evil twin
menu (option 7) and then scan for your target network (option 4).
After selecting it, Just launch the "Evil Twin attack just AP" (option
5) and wait until all the 4 windows of the attack appear, then check
if your client (mobile phone) is disconnected from the network. That's
it.
In my case, just 3 windows opened... the first one is the Fake AP, the
second is a DHCP server, the third one is the DoS window, and as I
said, as soon as it appears, everything hangs... so no time for the
4th window to be opened (the control window).
Kind regards.
--
Oscar
OpenPGP Key: DA9C60E9 ||
https://pgp.mit.edu/pks/lookup?op=get&search=0x79B17260DA9C60E9
4F74 B302 354D 817D DE38 0A43 79B1 7260 DA9C 60E9
--
El mié, 25 mar 2026 a las 1:15, 傅继晗 (<fjhhz1997@gmail.com>) escribió:
>
> Hi Oscar,
>
> Thank you for testing the v1 patch and reporting the VM hang -- your
> report was critical in identifying the root cause.
>
> Lucid-Duck did extensive debugging and reproduction work on this.
> The full discussion is here:
> https://github.com/morrownr/USB-WiFi/issues/682#issuecomment-4120751621
>
> Root cause of the crash:
>
> The v1 patch falls back to list_first_entry_or_null(&local->chanctx_list)
> when the monitor vif has no chanctx. In your Evil Twin + DoS scenario,
> the AP and monitor interfaces created multiple channel contexts. The
> fallback blindly grabbed whichever chanctx was first on the list --
> which could be the AP's chanctx that the firmware wasn't expecting
> monitor traffic on. Injecting frames on a chanctx where
> mt7921_mcu_config_sniffer() was never called is the likely trigger
> for the hard hang.
>
> The v2 patch adds a list_is_singular() guard: injection only proceeds
> when there is exactly one chanctx (unambiguous), and is refused when
> multiple chanctxs exist. This covers the common single-channel AP +
> monitor case while preventing the dangerous multi-chanctx path that
> caused your crash.
>
> Lucid-Duck tested v2 extensively on kernel 6.19.8 with the MT7921AU
> (ALFA AWUS036AXML) -- single-channel AP + monitor + injection,
> multi-chanctx via P2P-GO, heavy load injection floods (50k fps,
> 1.8M packets) -- all stable with zero crashes or kernel warnings.
>
> The v2 diff against net/mac80211/tx.c:
>
> chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
> - if (chanctx_conf)
> + if (chanctx_conf) {
> chandef = &chanctx_conf->def;
> - else if (local->emulate_chanctx)
> + } else if (local->emulate_chanctx) {
> chandef = &local->hw.conf.chandef;
> - else
> - goto fail_rcu;
> + } else {
> + struct ieee80211_chanctx *ctx;
> +
> + ctx = list_first_entry_or_null(&local->chanctx_list,
> + struct ieee80211_chanctx,
> + list);
> + if (ctx && list_is_singular(&local->chanctx_list))
> + chandef = &ctx->conf.def;
> + else
> + goto fail_rcu;
> + }
>
> If you have time, could you re-test with this v2 patch in your
> original Evil Twin + DoS setup? That would help confirm the fix
> before I send v2 to the list.
>
> Thanks again for your help!
>
> Best regards,
> 傅继晗
^ permalink raw reply
* Re: [PATCH 1/4] wifi: mac80211: factor out part of ieee80211_calc_expected_tx_airtime
From: Pablo MARTIN-GOMEZ @ 2026-03-25 11:21 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless; +Cc: johannes
In-Reply-To: <0f56f76d-7820-4392-88f7-78f24b9ff421@nbd.name>
On 25/03/2026 04:58, Felix Fietkau wrote:
> On 23.03.26 17:00, Pablo MARTIN-GOMEZ wrote:
>> Hello,
>>
[...]
>> I know this patch is just a refactoring, but I think this moved code is
>> bugged. If (and it's a big if) I understood correctly the chain of
>> macros and the comments, `ieee80211_get_rate_duration` return the
>> `duration` in 1024 µs of an average packet (which would imply
>> 1f38b8c564b8 is wrong) and the (PHY) `overhead` in µs for a (average)
>> packet. So I believe the code should be:
>> ```c
>> duration = ieee80211_get_rate_duration(hw, &stat, &overhead);
>> duration *= 1024; /* now duration is in µs */
>> /* the agg_shift calculation has to be fixed */
>> duration += (overhead >> agg_shift); /* for one packet, we
>> "assign" a
>> fraction of the overhead */
>> duration *= len/AVG_PKT_SIZE; /* we multiply by the number of
>> packets */
>> duration /= 1024; /* we go back to a duration in 1024 µs*/
>>
>> return duration;
>> ```
>
> The overhead (preamble, signal field, etc.) is a fixed per-frame PHY
> cost that doesn't depend on how many data bytes are in the frame. In the
> aggregated case, agg_shift amortizes that fixed cost across the
> estimated number of subframes in the aggregate. So the correct order is:
> scale the data duration to the actual packet size, then add the
> amortized overhead once.
My bad, I didn't understand that `len` was the byte size of a MPDU.
So I was wrong on where I put the overhead, but (a priori) not on the
rest of the calculation *if* my understanding of the units is correct.
If 1f38b8c564b8 is correct and so `duration` is in ns and `overhead` is
in µs, then your code is correct, but the commit message is wrong
because `ieee80211_rate_expected_tx_airtime` is returning a value in ns.
My snippet fixed if `duration` is in 1024 µs:
```c
duration = ieee80211_get_rate_duration(hw, &stat, &overhead); /*
duration of an average MPDU in 1024 µs */
duration *= 1024; /* duration in µs */
duration /= AVG_PKT_SIZE; /* duration in µs for a byte */
duration *= len; /* duration in µs for the actual MPDU */
duration += (overhead >> agg_shift); /* duration in µs for an
approximate PPDU aka airtime */
duration /= 1024; /* airtime duration in 1024 µs*/
return duration;
```
[`ieee80211_calc_expected_tx_airtime` has to be fixed too]
The current patch:
```c
duration·=·ieee80211_get_rate_duration(hw,·&stat,·&overhead); /*
duration of an average MPDU in ns */
duration·*=·len;
duration·/=·AVG_PKT_SIZE; /* duration in ns for the actual MPDU */
duration·+=·(overhead·*·1024·>>·agg_shift); /* adding the overhead in
µs to a duration in ns to get PPDU duration: overhead [µs] == overhead *
1024 [ns] */
return·duration; /* airtime duration in ns */
```
> This is the same pattern used in ieee80211_calc_rx_airtime:
>
> duration *= len;
> duration /= AVG_PKT_SIZE;
> duration /= 1024;
> return duration + overhead;
>
> Your proposed rewrite would multiply the overhead by len / AVG_PKT_SIZE,
> making it proportional to packet size, which is incorrect, because a
> 512-byte frame and a 1500-byte frame have the same PHY preamble duration.
>
> - Felix
Pablo MG
^ permalink raw reply
* Re: [PATCH 1/4] wifi: mac80211: factor out part of ieee80211_calc_expected_tx_airtime
From: Felix Fietkau @ 2026-03-25 11:41 UTC (permalink / raw)
To: Pablo MARTIN-GOMEZ, linux-wireless; +Cc: johannes
In-Reply-To: <0bbe540f-6a48-4d70-b6ca-4498f715963b@freebox.fr>
On 25.03.26 12:21, Pablo MARTIN-GOMEZ wrote:
> On 25/03/2026 04:58, Felix Fietkau wrote:
>> On 23.03.26 17:00, Pablo MARTIN-GOMEZ wrote:
>>> Hello,
>>>
> [...]
>>> I know this patch is just a refactoring, but I think this moved code is
>>> bugged. If (and it's a big if) I understood correctly the chain of
>>> macros and the comments, `ieee80211_get_rate_duration` return the
>>> `duration` in 1024 µs of an average packet (which would imply
>>> 1f38b8c564b8 is wrong) and the (PHY) `overhead` in µs for a (average)
>>> packet. So I believe the code should be:
>>> ```c
>>> duration = ieee80211_get_rate_duration(hw, &stat, &overhead);
>>> duration *= 1024; /* now duration is in µs */
>>> /* the agg_shift calculation has to be fixed */
>>> duration += (overhead >> agg_shift); /* for one packet, we
>>> "assign" a
>>> fraction of the overhead */
>>> duration *= len/AVG_PKT_SIZE; /* we multiply by the number of
>>> packets */
>>> duration /= 1024; /* we go back to a duration in 1024 µs*/
>>>
>>> return duration;
>>> ```
>>
>> The overhead (preamble, signal field, etc.) is a fixed per-frame PHY
>> cost that doesn't depend on how many data bytes are in the frame. In the
>> aggregated case, agg_shift amortizes that fixed cost across the
>> estimated number of subframes in the aggregate. So the correct order is:
>> scale the data duration to the actual packet size, then add the
>> amortized overhead once.
> My bad, I didn't understand that `len` was the byte size of a MPDU.
>
> So I was wrong on where I put the overhead, but (a priori) not on the
> rest of the calculation *if* my understanding of the units is correct.
> If 1f38b8c564b8 is correct and so `duration` is in ns and `overhead` is
> in µs, then your code is correct, but the commit message is wrong
> because `ieee80211_rate_expected_tx_airtime` is returning a value in ns.
>
> My snippet fixed if `duration` is in 1024 µs:
> ```c
> duration = ieee80211_get_rate_duration(hw, &stat, &overhead); /*
> duration of an average MPDU in 1024 µs */
> duration *= 1024; /* duration in µs */
> duration /= AVG_PKT_SIZE; /* duration in µs for a byte */
> duration *= len; /* duration in µs for the actual MPDU */
> duration += (overhead >> agg_shift); /* duration in µs for an
> approximate PPDU aka airtime */
> duration /= 1024; /* airtime duration in 1024 µs*/
>
> return duration;
> ```
> [`ieee80211_calc_expected_tx_airtime` has to be fixed too]
>
> The current patch:
> ```c
> duration·=·ieee80211_get_rate_duration(hw,·&stat,·&overhead); /*
> duration of an average MPDU in ns */
> duration·*=·len;
> duration·/=·AVG_PKT_SIZE; /* duration in ns for the actual MPDU */
> duration·+=·(overhead·*·1024·>>·agg_shift); /* adding the overhead in
> µs to a duration in ns to get PPDU duration: overhead [µs] == overhead *
> 1024 [ns] */
> return·duration; /* airtime duration in ns */
> ```
The formatting of your snippets is really weird. Are you using some kind
of LLM?
There is definitely an issue in the commit message, which I will fix in
v2. It says the unit is 1024 us, when in fact it should say that the
unit is 1/1024 us (approximately ns). Maybe that's what got you
confused. Either way, your 'fixed' snippet seems wrong to me and the
code should be fine as-is.
- Felix
^ permalink raw reply
* [PATCH 06/11 net-next v5] drivers: net: drop ipv6_stub usage and use direct function calls
From: Fernando Fernandez Mancera @ 2026-03-25 12:08 UTC (permalink / raw)
To: netdev
Cc: Fernando Fernandez Mancera, Ricardo B. Marlière,
Jason A. Donenfeld, Antonio Quartulli, Edward Cree,
Jason Gunthorpe, Leon Romanovsky, Zhu Yanjun, Saeed Mahameed,
Tariq Toukan, Mark Bloch, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Boris Pismenny,
Simon Horman, Pablo Neira Ayuso, Harald Welte, Sabrina Dubroca,
Oliver Neukum, Stanislav Yakovlev, Nikolay Aleksandrov,
Ido Schimmel, Vlad Dumitrescu, Edward Srouji, Parav Pandit,
Kees Cook, Guillaume Nault, Alexei Lazar, Gal Pressman,
Jianbo Liu, Cosmin Ratiu, Carolina Jubran, Alexandre Cassen,
Petr Machata, Stanislav Fomichev, linux-rdma, linux-kernel,
oss-drivers, linux-net-drivers, osmocom-net-gprs, linux-usb,
wireguard, linux-wireless, bridge
In-Reply-To: <20260325120928.15848-1-fmancera@suse.de>
As IPv6 is built-in only, the ipv6_stub infrastructure is no longer
necessary.
Convert all drivers currently utilizing ipv6_stub to make direct
function calls. The fallback functions introduced previously will
prevent linkage errors when CONFIG_IPV6 is disabled.
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
Tested-by: Ricardo B. Marlière <rbm@suse.com>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Antonio Quartulli <antonio@openvpn.net>
Reviewed-by: Edward Cree <ecree.xilinx@gmail.com>
---
drivers/infiniband/core/addr.c | 3 +--
drivers/infiniband/sw/rxe/rxe_net.c | 6 +++---
.../ethernet/mellanox/mlx5/core/en/rep/neigh.c | 9 +++++----
.../net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 3 +--
.../mellanox/mlx5/core/en/tc_tun_encap.c | 2 +-
.../mellanox/mlx5/core/en_accel/ipsec.c | 1 -
.../net/ethernet/mellanox/mlx5/core/en_rep.c | 1 -
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 1 -
.../net/ethernet/netronome/nfp/flower/action.c | 2 +-
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 7 +++----
drivers/net/ethernet/sfc/tc_counters.c | 2 +-
drivers/net/ethernet/sfc/tc_encap_actions.c | 5 ++---
drivers/net/geneve.c | 1 -
drivers/net/gtp.c | 2 +-
drivers/net/ovpn/peer.c | 3 +--
drivers/net/ovpn/udp.c | 3 +--
drivers/net/usb/cdc_mbim.c | 17 +++++++++--------
drivers/net/vxlan/vxlan_core.c | 11 +++++------
drivers/net/vxlan/vxlan_multicast.c | 6 ++----
drivers/net/wireguard/socket.c | 3 +--
drivers/net/wireless/intel/ipw2x00/ipw2100.c | 2 +-
net/bridge/br_arp_nd_proxy.c | 3 +--
22 files changed, 40 insertions(+), 53 deletions(-)
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 866746695712..48d4b06384ec 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -41,7 +41,6 @@
#include <net/neighbour.h>
#include <net/route.h>
#include <net/netevent.h>
-#include <net/ipv6_stubs.h>
#include <net/ip6_route.h>
#include <rdma/ib_addr.h>
#include <rdma/ib_cache.h>
@@ -411,7 +410,7 @@ static int addr6_resolve(struct sockaddr *src_sock,
fl6.saddr = src_in->sin6_addr;
fl6.flowi6_oif = addr->bound_dev_if;
- dst = ipv6_stub->ipv6_dst_lookup_flow(addr->net, NULL, &fl6, NULL);
+ dst = ip6_dst_lookup_flow(addr->net, NULL, &fl6, NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 0bd0902b11f7..cbc646a30003 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -138,9 +138,9 @@ static struct dst_entry *rxe_find_route6(struct rxe_qp *qp,
memcpy(&fl6.daddr, daddr, sizeof(*daddr));
fl6.flowi6_proto = IPPROTO_UDP;
- ndst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(recv_sockets.sk6->sk),
- recv_sockets.sk6->sk, &fl6,
- NULL);
+ ndst = ip6_dst_lookup_flow(sock_net(recv_sockets.sk6->sk),
+ recv_sockets.sk6->sk, &fl6,
+ NULL);
if (IS_ERR(ndst)) {
rxe_dbg_qp(qp, "no route to %pI6\n", daddr);
return NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
index d220b045b331..648f4521c096 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
@@ -10,6 +10,7 @@
#include <linux/notifier.h>
#include <net/netevent.h>
#include <net/arp.h>
+#include <net/ndisc.h>
#include "neigh.h"
#include "tc.h"
#include "en_rep.h"
@@ -18,8 +19,8 @@
static unsigned long mlx5e_rep_ipv6_interval(void)
{
- if (IS_ENABLED(CONFIG_IPV6) && ipv6_stub->nd_tbl)
- return NEIGH_VAR(&ipv6_stub->nd_tbl->parms, DELAY_PROBE_TIME);
+ if (IS_ENABLED(CONFIG_IPV6) && ipv6_mod_enabled())
+ return NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME);
return ~0UL;
}
@@ -217,7 +218,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
case NETEVENT_NEIGH_UPDATE:
n = ptr;
#if IS_ENABLED(CONFIG_IPV6)
- if (n->tbl != ipv6_stub->nd_tbl && n->tbl != &arp_tbl)
+ if (n->tbl != &nd_tbl && n->tbl != &arp_tbl)
#else
if (n->tbl != &arp_tbl)
#endif
@@ -238,7 +239,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
* done per device delay prob time parameter.
*/
#if IS_ENABLED(CONFIG_IPV6)
- if (!p->dev || (p->tbl != ipv6_stub->nd_tbl && p->tbl != &arp_tbl))
+ if (!p->dev || (p->tbl != &nd_tbl && p->tbl != &arp_tbl))
#else
if (!p->dev || p->tbl != &arp_tbl)
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
index a14f216048cd..de74dbfe7b20 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
@@ -453,8 +453,7 @@ static int mlx5e_route_lookup_ipv6_get(struct mlx5e_priv *priv,
if (tunnel && tunnel->get_remote_ifindex)
attr->fl.fl6.flowi6_oif = tunnel->get_remote_ifindex(dev);
- dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(dev), NULL, &attr->fl.fl6,
- NULL);
+ dst = ip6_dst_lookup_flow(dev_net(dev), NULL, &attr->fl.fl6, NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
index bfd401bee9e8..8b827201935e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
@@ -402,7 +402,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
tbl = &arp_tbl;
#if IS_ENABLED(CONFIG_IPV6)
else if (m_neigh->family == AF_INET6)
- tbl = ipv6_stub->nd_tbl;
+ tbl = &nd_tbl;
#endif
else
return;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
index 64e13747084e..a52e12c3c95a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -36,7 +36,6 @@
#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <net/netevent.h>
-#include <net/ipv6_stubs.h>
#include "en.h"
#include "eswitch.h"
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 8992f0f7a870..ba6c0f38cc73 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -38,7 +38,6 @@
#include <net/pkt_cls.h>
#include <net/act_api.h>
#include <net/devlink.h>
-#include <net/ipv6_stubs.h>
#include "eswitch.h"
#include "en.h"
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 397a93584fd6..a9001d1c902f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -41,7 +41,6 @@
#include <linux/refcount.h>
#include <linux/completion.h>
#include <net/arp.h>
-#include <net/ipv6_stubs.h>
#include <net/bareudp.h>
#include <net/bonding.h>
#include <net/dst_metadata.h>
diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c
index aca2a7417af3..ae2f8b31adfb 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/action.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/action.c
@@ -470,7 +470,7 @@ nfp_fl_set_tun(struct nfp_app *app, struct nfp_fl_set_tun *set_tun,
flow.daddr = ip_tun->key.u.ipv6.dst;
flow.flowi4_proto = IPPROTO_UDP;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow, NULL);
+ dst = ip6_dst_lookup_flow(net, NULL, &flow, NULL);
if (!IS_ERR(dst)) {
set_tun->ttl = ip6_dst_hoplimit(dst);
dst_release(dst);
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index 0cef0e2b85d0..ca30702f8878 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -650,7 +650,7 @@ static void nfp_tun_neigh_update(struct work_struct *work)
flow6.daddr = *(struct in6_addr *)n->primary_key;
if (!neigh_invalid) {
struct dst_entry *dst;
- /* Use ipv6_dst_lookup_flow to populate flow6->saddr
+ /* Use ip6_dst_lookup_flow to populate flow6->saddr
* and other fields. This information is only needed
* for new entries, lookup can be skipped when an entry
* gets invalidated - as only the daddr is needed for
@@ -730,7 +730,7 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
return NOTIFY_DONE;
}
#if IS_ENABLED(CONFIG_IPV6)
- if (n->tbl != ipv6_stub->nd_tbl && n->tbl != &arp_tbl)
+ if (n->tbl != &nd_tbl && n->tbl != &arp_tbl)
#else
if (n->tbl != &arp_tbl)
#endif
@@ -815,8 +815,7 @@ void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
flow.flowi6_proto = IPPROTO_UDP;
#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
- dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(netdev), NULL, &flow,
- NULL);
+ dst = ip6_dst_lookup_flow(dev_net(netdev), NULL, &flow, NULL);
if (IS_ERR(dst))
goto fail_rcu_unlock;
#else
diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c
index d168282f30bf..b84235e93ffe 100644
--- a/drivers/net/ethernet/sfc/tc_counters.c
+++ b/drivers/net/ethernet/sfc/tc_counters.c
@@ -112,7 +112,7 @@ static void efx_tc_counter_work(struct work_struct *work)
encap->neigh->egdev);
else
#if IS_ENABLED(CONFIG_IPV6)
- n = neigh_lookup(ipv6_stub->nd_tbl,
+ n = neigh_lookup(&nd_tbl,
&encap->neigh->dst_ip6,
encap->neigh->egdev);
#else
diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.c b/drivers/net/ethernet/sfc/tc_encap_actions.c
index da35705cc5e1..db222abef53b 100644
--- a/drivers/net/ethernet/sfc/tc_encap_actions.c
+++ b/drivers/net/ethernet/sfc/tc_encap_actions.c
@@ -149,8 +149,7 @@ static int efx_bind_neigh(struct efx_nic *efx,
#if IS_ENABLED(CONFIG_IPV6)
struct dst_entry *dst;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow6,
- NULL);
+ dst = ip6_dst_lookup_flow(net, NULL, &flow6, NULL);
rc = PTR_ERR_OR_ZERO(dst);
if (rc) {
NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for IPv6 encap");
@@ -531,7 +530,7 @@ static int efx_neigh_event(struct efx_nic *efx, struct neighbour *n)
if (n->tbl == &arp_tbl) {
keysize = sizeof(keys.dst_ip);
#if IS_ENABLED(CONFIG_IPV6)
- } else if (n->tbl == ipv6_stub->nd_tbl) {
+ } else if (n->tbl == &nd_tbl) {
ipv6 = true;
keysize = sizeof(keys.dst_ip6);
#endif
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 01cdd06102e0..c6563367d382 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -12,7 +12,6 @@
#include <linux/module.h>
#include <linux/etherdevice.h>
#include <linux/hash.h>
-#include <net/ipv6_stubs.h>
#include <net/dst_metadata.h>
#include <net/gro_cells.h>
#include <net/rtnetlink.h>
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index e8949f556209..70b9e58b9b78 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -374,7 +374,7 @@ static struct rt6_info *ip6_route_output_gtp(struct net *net,
fl6->saddr = *saddr;
fl6->flowi6_proto = sk->sk_protocol;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, sk, fl6, NULL);
+ dst = ip6_dst_lookup_flow(net, sk, fl6, NULL);
if (IS_ERR(dst))
return ERR_PTR(-ENETUNREACH);
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 26b55d813f0e..c02dfab51a6e 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -827,8 +827,7 @@ static struct in6_addr ovpn_nexthop_from_rt6(struct ovpn_priv *ovpn,
.daddr = dest,
};
- entry = ipv6_stub->ipv6_dst_lookup_flow(dev_net(ovpn->dev), NULL, &fl,
- NULL);
+ entry = ip6_dst_lookup_flow(dev_net(ovpn->dev), NULL, &fl, NULL);
if (IS_ERR(entry)) {
net_dbg_ratelimited("%s: no route to host %pI6c\n",
netdev_name(ovpn->dev), &dest);
diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c
index 272b535ecaad..059e896b4a2f 100644
--- a/drivers/net/ovpn/udp.c
+++ b/drivers/net/ovpn/udp.c
@@ -14,7 +14,6 @@
#include <net/addrconf.h>
#include <net/dst_cache.h>
#include <net/route.h>
-#include <net/ipv6_stubs.h>
#include <net/transp_v6.h>
#include <net/udp.h>
#include <net/udp_tunnel.h>
@@ -251,7 +250,7 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind,
dst_cache_reset(cache);
}
- dst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(sk), sk, &fl, NULL);
+ dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl, NULL);
if (IS_ERR(dst)) {
ret = PTR_ERR(dst);
net_dbg_ratelimited("%s: no route to host %pISpc: %d\n",
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index dbf01210b0e7..877fb0ed7d3d 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -20,7 +20,6 @@
#include <linux/usb/cdc_ncm.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
-#include <net/ipv6_stubs.h>
#include <net/ndisc.h>
/* alternative VLAN for IP session 0 if not untagged */
@@ -302,6 +301,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
return NULL;
}
+#if IS_ENABLED(CONFIG_IPV6)
/* Some devices are known to send Neighbor Solicitation messages and
* require Neighbor Advertisement replies. The IPv6 core will not
* respond since IFF_NOARP is set, so we must handle them ourselves.
@@ -342,12 +342,11 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
is_router = !!READ_ONCE(in6_dev->cnf.forwarding);
in6_dev_put(in6_dev);
- /* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */
- ipv6_stub->ndisc_send_na(netdev, &iph->saddr, &msg->target,
- is_router /* router */,
- true /* solicited */,
- false /* override */,
- true /* inc_opt */);
+ ndisc_send_na(netdev, &iph->saddr, &msg->target,
+ is_router /* router */,
+ true /* solicited */,
+ false /* override */,
+ true /* inc_opt */);
out:
dev_put(netdev);
}
@@ -362,7 +361,7 @@ static bool is_neigh_solicit(u8 *buf, size_t len)
msg->icmph.icmp6_code == 0 &&
msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION);
}
-
+#endif /* IPV6 */
static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
{
@@ -378,8 +377,10 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_
proto = htons(ETH_P_IP);
break;
case 0x60:
+#if IS_ENABLED(CONFIG_IPV6)
if (is_neigh_solicit(buf, len))
do_neigh_solicit(dev, buf, tci);
+#endif
proto = htons(ETH_P_IPV6);
break;
default:
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 17c941aac32d..b5fbd03418b6 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -19,7 +19,6 @@
#include <net/arp.h>
#include <net/ndisc.h>
#include <net/gro.h>
-#include <net/ipv6_stubs.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/rtnetlink.h>
@@ -2045,7 +2044,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
ipv6_addr_is_multicast(&msg->target))
goto out;
- n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev);
+ n = neigh_lookup(&nd_tbl, &msg->target, dev);
if (n) {
struct vxlan_rdst *rdst = NULL;
@@ -2130,15 +2129,15 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
{
struct ipv6hdr *pip6;
- /* check if nd_tbl is not initiliazed due to
- * ipv6.disable=1 set during boot
+ /* check if ipv6.disable=1 set during boot was set
+ * during booting so nd_tbl is not initialized
*/
- if (!ipv6_stub->nd_tbl)
+ if (!ipv6_mod_enabled())
return false;
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
return false;
pip6 = ipv6_hdr(skb);
- n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev);
+ n = neigh_lookup(&nd_tbl, &pip6->daddr, dev);
if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) {
union vxlan_addr ipa = {
.sin6.sin6_addr = pip6->daddr,
diff --git a/drivers/net/vxlan/vxlan_multicast.c b/drivers/net/vxlan/vxlan_multicast.c
index a7f2d67dc61b..b0e80bca855c 100644
--- a/drivers/net/vxlan/vxlan_multicast.c
+++ b/drivers/net/vxlan/vxlan_multicast.c
@@ -39,8 +39,7 @@ int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
sk = sock6->sock->sk;
lock_sock(sk);
- ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex,
- &ip->sin6.sin6_addr);
+ ret = ipv6_sock_mc_join(sk, ifindex, &ip->sin6.sin6_addr);
release_sock(sk);
#endif
}
@@ -73,8 +72,7 @@ int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
sk = sock6->sock->sk;
lock_sock(sk);
- ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex,
- &ip->sin6.sin6_addr);
+ ret = ipv6_sock_mc_drop(sk, ifindex, &ip->sin6.sin6_addr);
release_sock(sk);
#endif
}
diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c
index 253488f8c00f..c362c78d908e 100644
--- a/drivers/net/wireguard/socket.c
+++ b/drivers/net/wireguard/socket.c
@@ -136,8 +136,7 @@ static int send6(struct wg_device *wg, struct sk_buff *skb,
if (cache)
dst_cache_reset(cache);
}
- dst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(sock), sock, &fl,
- NULL);
+ dst = ip6_dst_lookup_flow(sock_net(sock), sock, &fl, NULL);
if (IS_ERR(dst)) {
ret = PTR_ERR(dst);
net_dbg_ratelimited("%s: No route to %pISpfsc, error %d\n",
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index 248a051da52d..c11428485dcc 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -4838,7 +4838,7 @@ static int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode)
/* If IPv6 is configured in the kernel then we don't want to filter out all
* of the multicast packets as IPv6 needs some. */
-#if !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE)
+#if !defined(CONFIG_IPV6)
cmd.host_command = ADD_MULTICAST;
cmd.host_command_sequence = 0;
cmd.host_command_length = 0;
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index 1e2b51769eec..c06386eda47f 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -17,7 +17,6 @@
#include <linux/if_vlan.h>
#include <linux/inetdevice.h>
#include <net/addrconf.h>
-#include <net/ipv6_stubs.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ip6_checksum.h>
#endif
@@ -455,7 +454,7 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
return;
}
- n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, vlandev);
+ n = neigh_lookup(&nd_tbl, &msg->target, vlandev);
if (n) {
struct net_bridge_fdb_entry *f;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH] wifi: virt_wifi: remove SET_NETDEV_DEV to avoid use-after-free
From: Andrew Lunn @ 2026-03-25 12:34 UTC (permalink / raw)
To: Alexander Popov
Cc: Jakub Kicinski, David Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Chevallier, Michal Kubecek, Gal Pressman,
Kory Maincent, Oleksij Rempel, Ido Schimmel, Heiner Kallweit,
Greg KH, Johannes Berg, James Guan, Kees Cook, Paul Moses,
linux-wireless, netdev, linux-kernel, security, notify
In-Reply-To: <20260324224607.374327-1-alex.popov@linux.com>
On Wed, Mar 25, 2026 at 01:46:02AM +0300, Alexander Popov wrote:
> Currently we execute `SET_NETDEV_DEV(dev, &priv->lowerdev->dev)` for
> the virt_wifi net devices. However, unregistering a virt_wifi device in
> netdev_run_todo() can happen together with the device referenced by
> SET_NETDEV_DEV().
>
> It can result in use-after-free during the ethtool operations performed
> on a virt_wifi device that is currently being unregistered. Such a net
> device can have the `dev.parent` field pointing to the freed memory,
> but ethnl_ops_begin() calls `pm_runtime_get_sync(dev->dev.parent)`.
>
> Let's remove SET_NETDEV_DEV for virt_wifi to avoid bugs like this:
Did you have a look at all user of SET_NETDEV_DEV() to see if there
are other examples of the same bug?
What i found was:
https://elixir.bootlin.com/linux/v6.19.9/source/drivers/net/ethernet/mellanox/mlx4/en_netdev.c#L3180
Does this have the same problem?
Andrew
^ permalink raw reply
* Re: ath12k: desc_va endianness problem
From: Alexander Wilhelm @ 2026-03-25 12:59 UTC (permalink / raw)
To: Baochen Qiang; +Cc: Jeff Johnson, ath12k, linux-wireless, linux-kernel
In-Reply-To: <1c20551c-2cc3-418d-ad18-3a0bcead8b73@oss.qualcomm.com>
On Wed, Mar 25, 2026 at 10:46:10AM +0800, Baochen Qiang wrote:
>
>
> On 3/23/2026 7:20 PM, Alexander Wilhelm wrote:
> > On Mon, Mar 23, 2026 at 05:31:03PM +0800, Baochen Qiang wrote:
> >>
> >>
> >> On 3/20/2026 5:52 PM, Alexander Wilhelm wrote:
> >>> Hello ath12k developers,
> >>>
> >>> I have another fix for the big endian platform, but unfortunately the data types
> >>> do not match here, so I need your support. The problem is the following: the
> >>> structs `hal_reo_dest_ring`, `hal_wbm_completion_ring`, and
> >>> `hal_wbm_release_ring_cc_rx` all define the members `buf_va_lo` and `buf_va_hi`
> >>> as `__le32`. At first glance this seems correct, because the entire structure
> >>> contains only little endian fields. The local variable `desc_va` in each
> >>> function (see patch below) is of type `u64`, so it makes sense that I would need
> >>> to convert from little endian to CPU endian. Unfortunately, this leads to the
> >>> following crashes, in `tx_completion` and `rx_process_wbm`, respectivally:
> >>>
> >>>
> >>> Kernel attempted to read user page (40dcdf) - exploit attempt? (uid: 0)
> >>> BUG: Unable to handle kernel data access on read at 0x0040dcdf
> >>> Faulting instruction address: 0xe209290c
> >>> Oops: Kernel access of bad area, sig: 11 [#1]
> >>> BE PAGE_SIZE=4K SMP NR_CPUS=4 CoreNet Generic
> >>> Modules linked in: ath12k(O) mac80211(O) cfg80211(O) compat(O) ...
> >>> CPU: 1 PID: 10200 Comm: jshn Tainted: G O 6.6.73 #0
> >>> Hardware name: CyBoxAP-A e5500 0x80241021 CoreNet Generic
> >>> NIP: e209290c LR: e2092854 CTR: c08d3190
> >>> REGS: dffe3d40 TRAP: 0300 Tainted: G O (6.6.73)
> >>> MSR: 00029002 <CE,EE,ME> CR: 44004804 XER: 00000000
> >>> DEAR: 0040dcdf ESR: 00000000
> >>> GPR00: e2092854 dffe3e30 c328a500 e2092854 0040dcce 00000008 00070000 cf900000
> >>> GPR08: 00000000 cf900004 40000000 c8e52c4c c08d3190 1002801c 0fcf5000 c0ab85f8
> >>> GPR16: d0d1f7a0 c12a9080 00000001 df7b7f80 00000003 cf900000 e1bc0000 e1ccb988
> >>> GPR24: ffffffff c8ed0000 e1cc0220 00000000 c8ec0000 c8ec0000 c8ec0f50 c8ec0000
> >>> NIP [e209290c] ath12k_dp_tx_completion_handler+0x22c/0x720 [ath12k]
> >>> LR [e2092854] ath12k_dp_tx_completion_handler+0x174/0x720 [ath12k]
> >>> Call Trace:
> >>> [dffe3e30] [e2092854] ath12k_dp_tx_completion_handler+0x174/0x720 [ath12k] (unreliable)
> >>> [dffe3e80] [e208fe18] ath12k_dp_service_srng+0x58/0x380 [ath12k]
> >>> [dffe3ed0] [e20a1490] ath12k_pci_hif_resume+0x520/0x8a0 [ath12k]
> >>> [dffe3f00] [c067404c] __napi_poll+0x4c/0x260
> >>> [dffe3f30] [c06746f8] net_rx_action+0x188/0x340
> >>> [dffe3fa0] [c003a3d8] handle_softirqs+0x128/0x280
> >>> [dffe3ff0] [c00045b0] do_softirq_own_stack+0x30/0x50
> >>> [d0f2fb70] [00000000] 0x0
> >>> [d0f2fb90] [c003a7d0] irq_exit+0x70/0xa0
> >>> [d0f2fba0] [c0000c84] ExternalInput+0x144/0x160
> >>> --- interrupt: 500 at percpu_counter_add_batch+0x9c/0x150
> >>> NIP: c0425e8c LR: c01a5964 CTR: c01764e0
> >>> REGS: d0f2fbb0 TRAP: 0500 Tainted: G O (6.6.73)
> >>> MSR: 00029002 <CE,EE,ME> CR: 48008802 XER: 20000000
> >>>
> >>> GPR00: c01a5a00 d0f2fca0 c328a500 c1db7300 dffc0f20 00000000 fffffffc 00021002
> >>> GPR08: 1e763000 e1091054 00000007 c12b0530 88002808 1002801c 0fcf5000 c0ab85f8
> >>> GPR16: d0d1f7a0 dffc0f20 00000000 000003fe 00000000 f92412bd 00000003 c9525480
> >>> GPR24: d0f2fd74 c8a501f8 c12b0530 00029002 00000007 00000000 0000000b c1db7300
> >>> NIP [c0425e8c] percpu_counter_add_batch+0x9c/0x150
> >>> LR [c01a5964] unmap_page_range+0x484/0x820
> >>> --- interrupt: 500
> >>> [d0f2fca0] [00000001] 0x1 (unreliable)
> >>> [d0f2fcd0] [c01a5a00] unmap_page_range+0x520/0x820
> >>> [d0f2fd60] [c01a5d9c] unmap_vmas+0x9c/0xe0
> >>> [d0f2fda0] [c01afef4] exit_mmap+0xb4/0x2a0
> >>> [d0f2fe40] [c0031610] mmput+0x40/0x140
> >>> [d0f2fe60] [c0038df4] do_exit+0x2b4/0x990
> >>> [d0f2feb0] [c00396c4] do_group_exit+0x34/0xa0
> >>> [d0f2fed0] [c0039748] sys_exit_group+0x18/0x20
> >>> [d0f2fee0] [c000dbac] system_call_exception+0xac/0x1f0
> >>> [d0f2ff00] [c00110e8] ret_from_syscall+0x0/0x28
> >>> --- interrupt: c00 at 0xfded438
> >>> NIP: 0fded438 LR: 0ff23958 CTR: 0fd94930
> >>> REGS: d0f2ff10 TRAP: 0c00 Tainted: G O (6.6.73)
> >>> MSR: 0002f902 <CE,EE,PR,FP,ME> CR: 28002402 XER: 20000000
> >>>
> >>> GPR00: 000000ea bff93390 b0316520 00000000 113e8af0 113e8af0 00000000 00000000
> >>> GPR08: 00000000 00000000 00000000 ffffffff b02ccb04 1002801c 100a0000 bfbc4260
> >>> GPR16: 114974b0 00000000 114a4de0 00000000 b02cc900 00000001 00000000 00000001
> >>> GPR24: 0ff239a0 00000000 00000001 00000000 b030f52c fffff000 0ff23958 00000000
> >>> NIP [0fded438] 0xfded438
> >>> LR [0ff23958] 0xff23958
> >>> --- interrupt: c00
> >>> Code: 512a421e 2e140000 512a463e 40f20008 555b9f3e 39350004 754a4000 7c804c2c 41c20224 7c87442c 2c040000 41c20230 <88a40011> 7fc3f378 83a40008 8a640010
> >>> ---[ end trace 0000000000000000 ]---
> >>>
> >>> Kernel panic - not syncing: Fatal exception
> >>> ---[ end Kernel panic - not syncing: Fatal exception ]---
> >>>
> >>>
> >>> user@root:~# Kernel attempted to read user page (c011de) - exploit attempt? (uid: 0)
> >>> BUG: Unable to handle kernel data access on read at 0x00c011de
> >>> Faulting instruction address: 0xe1e3dc44
> >>> Oops: Kernel access of bad area, sig: 11 [#1]
> >>> BE PAGE_SIZE=4K SMP NR_CPUS=4 CoreNet Generic
> >>> Modules linked in: ...
> >>> CPU: 1 PID: 0 Comm: swapper/1 Tainted: G O 6.6.73 #0
> >>> Hardware name: CyBoxAP-A e5500 0x80241021 CoreNet Generic
> >>> NIP: e1e3dc44 LR: e1e3dc30 CTR: c08d40e0
> >>> REGS: dffe3ce0 TRAP: 0300 Tainted: G O (6.6.73)
> >>> MSR: 00029002 <CE,EE,ME> CR: 44004402 XER: 00000000
> >>> DEAR: 00c011de ESR: 00000000
> >>> GPR00: e1e33154 dffe3dd0 c1870000 00000000 cebe0000 00000000 00000000 00c011ce
> >>> GPR08: 00000001 00000000 00020000 c30a294c c08d40e0 00000000 00000001 00000000
> >>> GPR16: e1ce2668 c9270000 c9269a18 c92664d0 e1ce26dc 00000000 babababa dffe3df4
> >>> GPR24: 00000040 00000000 c9266480 dffe3dec dffe3e04 c9260000 00c011ce c9269a18
> >>> NIP [e1e3dc44] ath12k_dp_rx_process_wbm_err+0x124/0x600 [ath12k]
> >>> LR [e1e3dc30] ath12k_dp_rx_process_wbm_err+0x110/0x600 [ath12k]
> >>> Call Trace:
> >>> [dffe3dd0] [c0ab8e30] 0xc0ab8e30 (unreliable)
> >>> [dffe3e80] [e1e33154] ath12k_dp_service_srng+0x314/0x380 [ath12k]
> >>> [dffe3ed0] [e1e44540] ath12k_pci_hif_resume+0x520/0x8a0 [ath12k]
> >>> [dffe3f00] [c0674c7c] __napi_poll+0x4c/0x260
> >>> [dffe3f30] [c0675328] net_rx_action+0x188/0x340
> >>> [dffe3fa0] [c003a3d8] handle_softirqs+0x128/0x280
> >>> [dffe3ff0] [c00045b0] do_softirq_own_stack+0x30/0x50
> >>> [c18c7e10] [c12b040c] 0xc12b040c
> >>> [c18c7e30] [c003a7d0] irq_exit+0x70/0xa0
> >>> [c18c7e40] [c0000c84] ExternalInput+0x144/0x160
> >>> --- interrupt: 500 at arch_cpu_idle+0x24/0x50
> >>> NIP: c00071f4 LR: c00071f4 CTR: c000fe14
> >>> REGS: c18c7e50 TRAP: 0500 Tainted: G O (6.6.73)
> >>> MSR: 0002b002 <CE,EE,FP,ME> CR: 84000402 XER: 00000000
> >>>
> >>> GPR00: c08cc978 c18c7f40 c1870000 00000005 00000001 40000000 c328becc c12b0530
> >>> GPR08: c12b0530 c000fe14 0098ca91 00154674 24000402 00000000 00000001 00000000
> >>> GPR16: 00000000 00000000 c00119a0 dffee5f0 00000001 00000000 ffffffff c1050254
> >>> GPR24: c12c0000 c0011970 c0011940 c12d0000 00000004 c12b040c c12b0000 00000001
> >>> NIP [c00071f4] arch_cpu_idle+0x24/0x50
> >>> LR [c00071f4] arch_cpu_idle+0x24/0x50
> >>> --- interrupt: 500
> >>> [c18c7f40] [c0a367e0] 0xc0a367e0 (unreliable)
> >>> [c18c7f50] [c08cc978] default_idle_call+0x38/0x58
> >>> [c18c7f60] [c007b3b0] do_idle+0xf0/0x130
> >>> [c18c7f80] [c007b580] cpu_startup_entry+0x30/0x40
> >>> [c18c7fa0] [c001325c] start_secondary+0x48c/0x930
> >>> [c18c7ff0] [c0002870] __secondary_start+0x90/0xdc
> >>> Code: 7fa3eb78 4bfcba59 7c641b79 41c20144 38a10044 7fa3eb78 4bfcdb85 7c651b79 40c2026c 83c10058 2c1e0000 41c202d0 <813e0010> 7c09b000 41c20010 7e84a378
> >>> ---[ end trace 0000000000000000 ]---
> >>>
> >>> Kernel panic - not syncing: Fatal exception
> >>> ---[ end Kernel panic - not syncing: Fatal exception ]---
> >>>
> >>>
> >>> My fix, as shown in the patch below, is to remove the conversion. But then the
> >>> member variables `buf_va_lo` and `buf_va_hi` must be `u32`, which is obviously
> >>> wrong. Alternatively, `desc_va` must be `__le64`, but that is likely also
> >>> incorrect, because the address is simply dereferenced, and this clearly requires
> >>> CPU endianness. What I also do not fully understand is who actually fills these
> >>> addresses and at which stage this happens. I hope you can help clarify this so
> >>> that I can provide a correct patch for this issue afterward.
> >>>
> >>>
> >>
> >> hmm, i am not sure here, but can you please try
> >>
> >> diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
> >> index 1c82d927d27b..f142759a217b 100644
> >> --- a/drivers/net/wireless/ath/ath12k/dp.c
> >> +++ b/drivers/net/wireless/ath/ath12k/dp.c
> >> @@ -1246,7 +1246,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
> >>
> >> /* Update descriptor VA in SPT */
> >> rx_desc_addr = ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, j);
> >> - *rx_desc_addr = &rx_descs[j];
> >> + *rx_desc_addr = (struct ath12k_rx_desc_info
> >> *)cpu_to_le64(&rx_descs[j]);
> >> }
> >> }
> >>
> >> @@ -1286,7 +1286,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
> >> /* Update descriptor VA in SPT */
> >> tx_desc_addr =
> >> ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, j);
> >> - *tx_desc_addr = &tx_descs[j];
> >> + *tx_desc_addr = (struct ath12k_tx_desc_info
> >> *)cpu_to_le64(&tx_descs[j]);
> >> }
> >> }
> >> spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
> >>
> >
> > Hi Baochen,
> >
> > It actually worked, although the solution isn't entirely clean. Sparse
> > consequently complains with:
> >
> > dp.c:1249:42: warning: cast from restricted __le64
> > dp.c:1289:50: warning: cast from restricted __le64
> >
> > To be honest, I also don't quite understand why the struct pointer has to be in
> > little endian at this point. The function `ath12k_dp_cc_get_desc_addr_ptr`
> > returns an offset from the `vaddr` inside the `spt_info` struct, stored as a
> > `u64`. But dereferencing it suddenly treats it as little endian. Shouldn't
> > `vaddr` itself perhaps be a `__le64`?
>
> that piece of memory is for direct access by the target, so yes I think 'vaddr' should be
> defined as __le64.
Thanks again, Baochen. I've prepared a patch now, and it's working. I'll send it
shortly.
Best regards
Alexander Wilhelm
^ permalink raw reply
* [PATCH] wifi: ath12k: fix SPT vaddr handling on big endian systems
From: Alexander Wilhelm @ 2026-03-25 13:01 UTC (permalink / raw)
To: Jeff Johnson, Baochen Qiang; +Cc: linux-wireless, ath12k, linux-kernel
SPT pages store descriptor addresses in their vaddr field as little endian
64 bit values. Treating these entries as native pointers produces invalid
addresses on big endian systems.
Convert vaddr to __le64 and update all access paths. Write descriptor
addresses as endian annotated 64 bit values and load them by converting
back to native pointers. Return __le64* instead of void* from the SPT
lookup and translate the stored value in the descriptor getters.
This ensures correct and consistent handling of descriptor addresses on big
endian systems, while little endian systems remain unaffected.
Signed-off-by: Alexander Wilhelm <alexander.wilhelm@westermo.com>
---
drivers/net/wireless/ath/ath12k/dp.c | 26 ++++++++++++++++----------
drivers/net/wireless/ath/ath12k/dp.h | 2 +-
2 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index 1c82d927d27b..2076ae65e9e7 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -1149,8 +1149,8 @@ static u32 ath12k_dp_cc_cookie_gen(u16 ppt_idx, u16 spt_idx)
return (u32)ppt_idx << ATH12K_CC_PPT_SHIFT | spt_idx;
}
-static void *ath12k_dp_cc_get_desc_addr_ptr(struct ath12k_dp *dp,
- u16 ppt_idx, u16 spt_idx)
+static __le64 *ath12k_dp_cc_get_desc_addr_ptr(struct ath12k_dp *dp,
+ u16 ppt_idx, u16 spt_idx)
{
return dp->spt_info[ppt_idx].vaddr + spt_idx;
}
@@ -1158,8 +1158,9 @@ static void *ath12k_dp_cc_get_desc_addr_ptr(struct ath12k_dp *dp,
struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_dp *dp,
u32 cookie)
{
- struct ath12k_rx_desc_info **desc_addr_ptr;
u16 start_ppt_idx, end_ppt_idx, ppt_idx, spt_idx;
+ __le64 *desc_addr_ptr;
+ uintptr_t desc_addr;
ppt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_PPT);
spt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_SPT);
@@ -1174,16 +1175,18 @@ struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_dp *dp,
ppt_idx = ppt_idx - dp->rx_ppt_base;
desc_addr_ptr = ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, spt_idx);
+ desc_addr = (uintptr_t)le64_to_cpu(*desc_addr_ptr);
- return *desc_addr_ptr;
+ return (struct ath12k_rx_desc_info *)desc_addr;
}
EXPORT_SYMBOL(ath12k_dp_get_rx_desc);
struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_dp *dp,
u32 cookie)
{
- struct ath12k_tx_desc_info **desc_addr_ptr;
u16 start_ppt_idx, end_ppt_idx, ppt_idx, spt_idx;
+ __le64 *desc_addr_ptr;
+ uintptr_t desc_addr;
ppt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_PPT);
spt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_SPT);
@@ -1198,19 +1201,22 @@ struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_dp *dp,
return NULL;
desc_addr_ptr = ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, spt_idx);
+ desc_addr = (uintptr_t)le64_to_cpu(*desc_addr_ptr);
- return *desc_addr_ptr;
+ return (struct ath12k_tx_desc_info *)desc_addr;
}
EXPORT_SYMBOL(ath12k_dp_get_tx_desc);
static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
{
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
- struct ath12k_rx_desc_info *rx_descs, **rx_desc_addr;
- struct ath12k_tx_desc_info *tx_descs, **tx_desc_addr;
+ struct ath12k_rx_desc_info *rx_descs;
+ struct ath12k_tx_desc_info *tx_descs;
u32 num_rx_spt_pages = ATH12K_NUM_RX_SPT_PAGES(ab);
u32 i, j, pool_id, tx_spt_page;
u32 ppt_idx, cookie_ppt_idx;
+ __le64 *rx_desc_addr;
+ __le64 *tx_desc_addr;
spin_lock_bh(&dp->rx_desc_lock);
@@ -1246,7 +1252,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
/* Update descriptor VA in SPT */
rx_desc_addr = ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, j);
- *rx_desc_addr = &rx_descs[j];
+ *rx_desc_addr = cpu_to_le64((u64)(uintptr_t)&rx_descs[j]);
}
}
@@ -1286,7 +1292,7 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
/* Update descriptor VA in SPT */
tx_desc_addr =
ath12k_dp_cc_get_desc_addr_ptr(dp, ppt_idx, j);
- *tx_desc_addr = &tx_descs[j];
+ *tx_desc_addr = cpu_to_le64((u64)(uintptr_t)&tx_descs[j]);
}
}
spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index f8cfc7bb29dd..0d7fc2aea241 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -357,7 +357,7 @@ struct ath12k_tx_desc_params {
struct ath12k_spt_info {
dma_addr_t paddr;
- u64 *vaddr;
+ __le64 *vaddr;
};
struct ath12k_reo_queue_ref {
---
base-commit: 988707e4b5a73aa78f2fa260727c36fe725fa816
change-id: 20260325-fix-rx-tx-description-virtual-address-91f511690671
Best regards,
--
Alexander Wilhelm <alexander.wilhelm@westermo.com>
^ permalink raw reply related
* Re: [PATCH 1/4] wifi: mac80211: factor out part of ieee80211_calc_expected_tx_airtime
From: Pablo MARTIN-GOMEZ @ 2026-03-25 13:05 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless; +Cc: johannes
In-Reply-To: <9b4e633e-133e-4ec2-959f-1fb25e706ede@nbd.name>
On 25/03/2026 12:41, Felix Fietkau wrote:
> On 25.03.26 12:21, Pablo MARTIN-GOMEZ wrote:
>> On 25/03/2026 04:58, Felix Fietkau wrote:
>>> On 23.03.26 17:00, Pablo MARTIN-GOMEZ wrote:
>>>> Hello,
>>>>
[...]
>> My bad, I didn't understand that `len` was the byte size of a MPDU.
>>
>> So I was wrong on where I put the overhead, but (a priori) not on the
>> rest of the calculation *if* my understanding of the units is correct.
>> If 1f38b8c564b8 is correct and so `duration` is in ns and `overhead` is
>> in µs, then your code is correct, but the commit message is wrong
>> because `ieee80211_rate_expected_tx_airtime` is returning a value in ns.
>>
>> My snippet fixed if `duration` is in 1024 µs:
>> ```c
>> duration = ieee80211_get_rate_duration(hw, &stat, &overhead); /*
>> duration of an average MPDU in 1024 µs */
>> duration *= 1024; /* duration in µs */
>> duration /= AVG_PKT_SIZE; /* duration in µs for a byte */
>> duration *= len; /* duration in µs for the actual MPDU */
>> duration += (overhead >> agg_shift); /* duration in µs for an
>> approximate PPDU aka airtime */
>> duration /= 1024; /* airtime duration in 1024 µs*/
>>
>> return duration;
>> ```
>> [`ieee80211_calc_expected_tx_airtime` has to be fixed too]
>>
>> The current patch:
>> ```c
>> duration·=·ieee80211_get_rate_duration(hw,·&stat,·&overhead); /*
>> duration of an average MPDU in ns */
>> duration·*=·len;
>> duration·/=·AVG_PKT_SIZE; /* duration in ns for the actual MPDU */
>> duration·+=·(overhead·*·1024·>>·agg_shift); /* adding the
>> overhead in
>> µs to a duration in ns to get PPDU duration: overhead [µs] == overhead *
>> 1024 [ns] */
>> return·duration; /* airtime duration in ns */
>> ```
>
> The formatting of your snippets is really weird. Are you using some kind
> of LLM?
That's handcrafted markdown, but then I have a MUA plugin that line
wraps everything, including code. I need to fix that, sorry about that.
>
> There is definitely an issue in the commit message, which I will fix in
> v2. It says the unit is 1024 us, when in fact it should say that the
> unit is 1/1024 us (approximately ns). Maybe that's what got you
> confused. Either way, your 'fixed' snippet seems wrong to me and the
> code should be fine as-is.
Ok then, with 1/1024 µs, the code looks fine. Now, I need to re-analyze
`airtime.c` to understand why `ieee80211_get_rate_duration` returns 1 /
1024 µs instead of 1024 µs like I though it was returning.
>
> - Felix
>
>
Pablo MG
^ permalink raw reply
* [PATCH v3 wireless-next] wifi: mac80211: ignore reserved bits in reconfiguration status
From: Miri Korenblit @ 2026-03-25 13:43 UTC (permalink / raw)
To: linux-wireless; +Cc: Benjamin Berg, Ilan Peer
From: Benjamin Berg <benjamin.berg@intel.com>
The Link ID Info field in the Reconfiguration Status Duple subfield of
the Reconfiguration Response frame only uses the lower four bits for the
link ID. The upper bits are reserved and should therefore be ignored.
Fixes: 36e05b0b8390 ("wifi: mac80211: Support dynamic link addition and removal")
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Reviewed-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
net/mac80211/mlme.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--
v2: added structs and macros, as required.
v3: fixed the Fixes tag
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 173a60360a45..51a259aa8568 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -10471,7 +10471,7 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < mgmt->u.action.ml_reconf_resp.count; i++) {
u16 status = get_unaligned_le16(pos + 1);
- link_id = *pos;
+ link_id = u8_get_bits(*pos, 0xf);
if (!(link_mask & BIT(link_id))) {
sdata_info(sdata,
--
2.34.1
^ permalink raw reply related
* [PATCH v2 wireless-next] wifi: mac80211: extract channel logic from link logic
From: Miri Korenblit @ 2026-03-25 13:46 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
The logic that tries to reuse an existing chanctx or create a new one if
such doesn't exist will be used for other types of chanctx users.
Extract this logic from _ieee80211_link_use_channel.
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
net/mac80211/chan.c | 54 ++++++++++++++++++++++++++++++++-------------
1 file changed, 39 insertions(+), 15 deletions(-)
---
v2: make the patch apply
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 1bcf501cfe8e..1669ebf77346 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -2031,6 +2031,36 @@ void __ieee80211_link_release_channel(struct ieee80211_link_data *link,
ieee80211_vif_use_reserved_switch(local);
}
+static struct ieee80211_chanctx *
+ieee80211_find_or_create_chanctx(struct ieee80211_sub_if_data *sdata,
+ const struct ieee80211_chan_req *chanreq,
+ enum ieee80211_chanctx_mode mode,
+ bool assign_on_failure,
+ bool *reused_ctx)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx *ctx;
+ int radio_idx;
+
+ lockdep_assert_wiphy(local->hw.wiphy);
+
+ ctx = ieee80211_find_chanctx(local, chanreq, mode);
+ if (ctx) {
+ *reused_ctx = true;
+ return ctx;
+ }
+
+ *reused_ctx = false;
+
+ if (!ieee80211_find_available_radio(local, chanreq,
+ sdata->wdev.radio_mask,
+ &radio_idx))
+ return ERR_PTR(-EBUSY);
+
+ return ieee80211_new_chanctx(local, chanreq, mode,
+ assign_on_failure, radio_idx);
+}
+
int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
const struct ieee80211_chan_req *chanreq,
enum ieee80211_chanctx_mode mode,
@@ -2039,9 +2069,8 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
struct ieee80211_chanctx *ctx;
- u8 radar_detect_width = 0;
- bool reserved = false;
- int radio_idx;
+ u8 radar_detect_width = 0;
+ bool reused_ctx = false;
int ret;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -2069,17 +2098,8 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
if (!local->in_reconfig)
__ieee80211_link_release_channel(link, false);
- ctx = ieee80211_find_chanctx(local, chanreq, mode);
- /* Note: context will_be_used flag is now set */
- if (ctx)
- reserved = true;
- else if (!ieee80211_find_available_radio(local, chanreq,
- sdata->wdev.radio_mask,
- &radio_idx))
- ctx = ERR_PTR(-EBUSY);
- else
- ctx = ieee80211_new_chanctx(local, chanreq, mode,
- assign_on_failure, radio_idx);
+ ctx = ieee80211_find_or_create_chanctx(sdata, chanreq, mode,
+ assign_on_failure, &reused_ctx);
if (IS_ERR(ctx)) {
ret = PTR_ERR(ctx);
goto out;
@@ -2089,7 +2109,11 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);
- if (reserved) {
+ /*
+ * In case an existing channel context is being used, we marked it as
+ * will_be_used, now that it is assigned - clear this indication
+ */
+ if (reused_ctx) {
WARN_ON(!ctx->will_be_used);
ctx->will_be_used = false;
}
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v10 00/21] wifi: nxpwifi: create nxpwifi to support
From: Jeff Chen @ 2026-03-25 13:45 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linux-kernel, francesco, wyatt.hsu, s.hauer
In-Reply-To: <075c9a062664609a81a722883ee17e7c728b08bc.camel@sipsolutions.net>
On Thu, Mar 12, 2026 at 10:13:07 AM +0100, Johannes Berg wrote:
> On Thu, 2026-03-12 at 16:56 +0800, Jeff Chen wrote:
> >
> > Right, understood. The IW61x SDIO IDs currently appear only in linux-next, not in wireless-next,
> > and the patchwork build logs confirm the build failure is exactly due to these IDs being
> > undefined.
> >
> > For v11, I’ll add a small temporary patch with local fallback #defines (guarded with #ifndef) so
> > that wireless-next can build independently without relying on any cross-tree merges. I’ll drop
> > that patch once the IDs reach mainline.
>
> That seems kind of ugly too.
>
> Ulf, do you rebase mmc.git's next branch?
>
> For whatever reason, Jeff sent you the requisite IDs for the driver
> rather than putting them into the same patchset and getting your ACK,
> and you have it as commit c0b68bc25efe ("mmc: sdio: add NXP vendor and
> IW61x device IDs").
>
> It _looks_ like that's in your next branch only, not mux or fixes (but
> I'm getting slightly confused by the branch structure), perhaps there's
> a chance you could drop that?
>
> Or maybe the less bad option would be to just have that commit twice in
> both trees? I'm nott a fan of a local define that we have to clean up
> later...
>
> johannes
>
Hi Johannes,
Ulf prefers not to rebase or drop the SDIO ID patch from the mmc tree,
and his suggestion is for me to include an identical copy of that patch
in the nxpwifi series for wireless-next, so that the driver can build
independently during review. Since the change is trivial, he expects git
to resolve the duplication automatically when the wireless and mmc trees
are merged.
Would this approach be acceptable for wireless-next?
For reference, please see Ulf’s feedback here:
https://patchwork.kernel.org/project/linux-mmc/patch/20260113031517.244714-1-jeff.chen_1@nxp.com/
thanks,
Jeff
^ permalink raw reply
* Re: [PATCH] wifi: virt_wifi: remove SET_NETDEV_DEV to avoid use-after-free
From: Greg KH @ 2026-03-25 13:47 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexander Popov, Jakub Kicinski, David Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Maxime Chevallier, Michal Kubecek,
Gal Pressman, Kory Maincent, Oleksij Rempel, Ido Schimmel,
Heiner Kallweit, Johannes Berg, James Guan, Kees Cook, Paul Moses,
linux-wireless, netdev, linux-kernel, security, notify
In-Reply-To: <fa3c91c3-9ceb-4fb2-9250-cc239fb0c1b6@lunn.ch>
On Wed, Mar 25, 2026 at 01:34:43PM +0100, Andrew Lunn wrote:
> On Wed, Mar 25, 2026 at 01:46:02AM +0300, Alexander Popov wrote:
> > Currently we execute `SET_NETDEV_DEV(dev, &priv->lowerdev->dev)` for
> > the virt_wifi net devices. However, unregistering a virt_wifi device in
> > netdev_run_todo() can happen together with the device referenced by
> > SET_NETDEV_DEV().
> >
> > It can result in use-after-free during the ethtool operations performed
> > on a virt_wifi device that is currently being unregistered. Such a net
> > device can have the `dev.parent` field pointing to the freed memory,
> > but ethnl_ops_begin() calls `pm_runtime_get_sync(dev->dev.parent)`.
> >
> > Let's remove SET_NETDEV_DEV for virt_wifi to avoid bugs like this:
>
> Did you have a look at all user of SET_NETDEV_DEV() to see if there
> are other examples of the same bug?
>
> What i found was:
>
> https://elixir.bootlin.com/linux/v6.19.9/source/drivers/net/ethernet/mellanox/mlx4/en_netdev.c#L3180
>
> Does this have the same problem?
That's not pointing to the "parent" device, but rather the actual device
under operation from what I can tell. Or am I mistaking what "pdev"
means here? Isn't that the pci device the driver is bound to?
thanks,
greg k-h
^ permalink raw reply
* [PATCH v2 wireless-next] wifi: mac80211: cleanup error path of ieee80211_do_open
From: Miri Korenblit @ 2026-03-25 13:48 UTC (permalink / raw)
To: linux-wireless
If we failed on drv_start, we currently cleanup AP_VLAN reference to
bss.
But this is not needed, since AP_VLAN must be tied to a pre-existing AP
interface, so open_count cannot be 0, so we will never call drv_start
for AP_VLAN interfaces.
Remove these cleanup and return immediately instead.
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
net/mac80211/iface.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
---
v2: make the commit apply
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 232fc0b80e44..234de4762be5 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1361,8 +1361,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
break;
}
case NL80211_IFTYPE_AP:
- sdata->bss = &sdata->u.ap;
- break;
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_MONITOR:
@@ -1387,8 +1385,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
local->reconfig_failure = false;
res = drv_start(local);
- if (res)
- goto err_del_bss;
+ if (res) {
+ /*
+ * no need to worry about AP_VLAN cleanup since in that
+ * case we can't have open_count == 0
+ */
+ return res;
+ }
ieee80211_led_radio(local, true);
ieee80211_mod_tpt_led_trig(local,
IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
@@ -1459,6 +1462,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
netif_carrier_on(dev);
list_add_tail_rcu(&sdata->u.mntr.list, &local->mon_list);
break;
+ case NL80211_IFTYPE_AP:
+ sdata->bss = &sdata->u.ap;
+ fallthrough;
default:
if (coming_up) {
ieee80211_del_virtual_monitor(local);
@@ -1547,10 +1553,10 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
err_stop:
if (!local->open_count)
drv_stop(local, false);
- err_del_bss:
- sdata->bss = NULL;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
list_del(&sdata->u.vlan.list);
+ /* Might not be initialized yet, but it is harmless */
+ sdata->bss = NULL;
return res;
}
--
2.34.1
^ permalink raw reply related
* Re: [PATCH net-next v3 03/13] net: introduce ndo_set_rx_mode_async and dev_rx_mode_work
From: Stanislav Fomichev @ 2026-03-25 15:06 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Stanislav Fomichev, netdev, davem, edumazet, pabeni, horms,
corbet, skhan, andrew+netdev, michael.chan, pavan.chebbi,
anthony.l.nguyen, przemyslaw.kitszel, saeedm, tariqt, mbloch,
alexanderduyck, kernel-team, johannes, sd, jianbol, dtatulea,
mohsin.bashr, jacob.e.keller, willemb, skhawaja, bestswngs,
aleksandr.loktionov, kees, linux-doc, linux-kernel,
intel-wired-lan, linux-rdma, linux-wireless, linux-kselftest,
leon
In-Reply-To: <20260324204440.1752423d@kernel.org>
On 03/24, Jakub Kicinski wrote:
> On Tue, 24 Mar 2026 15:49:27 -0700 Stanislav Fomichev wrote:
> > > > Not sure why cancel+release, maybe you're thinking about the unregister
> > > > path? This is rtnl_unlock -> netdev_run_todo -> __rtnl_unlock + some
> > > > extras.
> > > >
> > > > And the flush is here to plumb the addresses to the real devices
> > > > before we return to the callers. Mostly because of the following
> > > > things we have in the tests:
> > > >
> > > > # TEST: team cleanup mode lacp [FAIL]
> > > > # macvlan unicast address not found on a slave
> > > >
> > > > Can you explain a bit more on the suggestion?
> > >
> > > Oh, I thought it's here for unregister! Feels like it'd be cleaner to
> > > add the flush in dev_*c_add() and friends? How hard would it be to
> > > identify the callers in atomic context?
> >
> > Not sure we can do it in dev_xc_add because it runs under rtnl :-(
> > I currently do flush in netdev_run_todo because that's the place that
> > doesn't hold rtnl. Otherwise flush will get stuck because the work
> > handler grabs it...
>
> I was thinking of something a'la linkwatch. We can "steal" / "flush"
> the pending work inline. I guess linkwatch is a major source of races
> over the years...
>
> Does the macvlan + team problem still happens with the current
> implementation minus the flush? We are only flushing once so only
> pushing the addresses thru one layer of async callbacks.
Yes, it does happen consistently when I remove the flush. It also
happens with my internal v4, so I need to look again at what's going on.
Not sure whether it's my internal regression or I was just sloppy/lucky
(since you're correct in pointing out that we flush only once).
Before I went down the workqueue route, I had a simple
net_todo_list-like approach: `list_add_tail` on enqueue and
`while(!list_empty) run_work()` on rtnl_unlock. This had a nice properly of
tracking re-submissions (by checking whether the device's list_head is
linked into the list or not) and it was relatively easy to do the
recursive flush. Let me try get back to this approach and see whether
it solves the flush? Not sure what wq buys us at this point.
^ permalink raw reply
* Re: [PATCH 0/2] ath10k: WCN3990 firmware workarounds for WLAN.HL.3.2
From: Jeff Johnson @ 2026-03-25 15:54 UTC (permalink / raw)
To: Loic Poulain, Jeff Johnson, Baochen Qiang
Cc: Malte Schababerle, linux-wireless, ath10k
In-Reply-To: <CAFEp6-0xShGtpWEhmYmqs0156GHZDsF4Q7E5HOrMbnGSAb56wA@mail.gmail.com>
On 3/25/2026 1:41 AM, Loic Poulain wrote:
> Hi Jeff, Malte.
>
> On Sun, Mar 22, 2026 at 2:49 PM Malte Schababerle
> <m.schababerle@gmail.com> wrote:
>>
>> Two firmware workarounds for WCN3990 (QCA6174 integrated variant on
>> Qualcomm SM8150/SDM845 platforms) running WLAN.HL.3.2 firmware.
>>
>> Both issues are firmware bugs where WCN3990 advertises capabilities it
>> cannot handle correctly. Tested on OnePlus 7T (SM8150) with
>> WLAN.HL.3.2.0.c2-00006 and WLAN.HL.3.2.0.c2-00011.
>>
>> Patch 1 fixes a deterministic firmware crash caused by the quiet mode
>> WMI command. The existing guard from commit 53884577fbcef relied on
>> THERM_THROT not being advertised, but HL3.2 now advertises it despite
>> still crashing on the command.
>>
>> Patch 2 works around a bug where active scan does not tune the radio
>> on 5GHz non-DFS channels, making 5GHz networks invisible. Forcing
>> passive scan mode restores 5GHz discovery.
>>
>> Malte Schababerle (2):
>> ath10k: skip quiet mode for WCN3990 to prevent firmware crash
>> ath10k: force passive scan on 5GHz for WCN3990
>
> Jeff, is this something that could be addressed or worked around
> through the firmware or NV configuration? Applying this workaround to
> all WCN3990 devices feels a bit excessive if the issue is limited to
> specific variants.
+Baochen, can you look at this with the firmware team?
^ permalink raw reply
* [PATCH v3 1/3] dt-bindings: wireless: ath10k: Introduce quirk to skip host cap QMI requests
From: David Heidelberg via B4 Relay @ 2026-03-25 16:41 UTC (permalink / raw)
To: Johannes Berg, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jeff Johnson, Bjorn Andersson, Konrad Dybcio, Paul Sajna
Cc: Amit Pundir, linux-wireless, devicetree, ath10k, linux-kernel,
linux-arm-msm, phone-devel, David Heidelberg
In-Reply-To: <20260325-skip-host-cam-qmi-req-v3-0-b163cf7b3c81@ixit.cz>
From: Amit Pundir <amit.pundir@linaro.org>
Introducing this quirk to skip host capability QMI request for the firmware
versions which do not support this feature.
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
index f2440d39b7ebc..5120b3589ab57 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
@@ -171,6 +171,12 @@ properties:
Quirk specifying that the firmware expects the 8bit version
of the host capability QMI request
+ qcom,snoc-host-cap-skip-quirk:
+ type: boolean
+ description:
+ Quirk specifying that the firmware wants to skip the host
+ capability QMI request
+
qcom,xo-cal-data:
$ref: /schemas/types.yaml#/definitions/uint32
description:
--
2.53.0
^ permalink raw reply related
* [PATCH v3 2/3] ath10k: Introduce a device-tree quirk to skip host cap QMI requests
From: David Heidelberg via B4 Relay @ 2026-03-25 16:41 UTC (permalink / raw)
To: Johannes Berg, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jeff Johnson, Bjorn Andersson, Konrad Dybcio, Paul Sajna
Cc: Amit Pundir, linux-wireless, devicetree, ath10k, linux-kernel,
linux-arm-msm, phone-devel, David Heidelberg
In-Reply-To: <20260325-skip-host-cam-qmi-req-v3-0-b163cf7b3c81@ixit.cz>
From: Amit Pundir <amit.pundir@linaro.org>
There are firmware versions which do not support host capability QMI
request. We suspect either the host cap is not implemented or there may
be firmware specific issues, but apparently there seem to be a generation
of firmware that has this particular behavior.
For example, firmware build on Xiaomi Poco F1 (sdm845) phone:
"QC_IMAGE_VERSION_STRING=WLAN.HL.2.0.c3-00257-QCAHLSWMTPLZ-1"
If we do not skip the host cap QMI request on Poco F1, then we get a
QMI_ERR_MALFORMED_MSG_V01 error message before loading the firmware in the
ath10k_qmi_host_cap_send_sync(). This error message is not fatal to the
firmware nor to the ath10k driver and we can still bring up the WiFi
services successfully if we just ignore it.
Hence introducing this device-tree quirk to skip host capability
QMI request for the devices with firmware versions which do not support
this feature.
Suggested-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
---
drivers/net/wireless/ath/ath10k/qmi.c | 13 ++++++++++---
drivers/net/wireless/ath/ath10k/snoc.c | 3 +++
drivers/net/wireless/ath/ath10k/snoc.h | 1 +
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index eebd78e7ff6bc..e7f90fd9e9b83 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -808,6 +808,7 @@ ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
{
struct ath10k *ar = qmi->ar;
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
int ret;
ret = ath10k_qmi_ind_register_send_sync_msg(qmi);
@@ -819,9 +820,15 @@ static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
return;
}
- ret = ath10k_qmi_host_cap_send_sync(qmi);
- if (ret)
- return;
+ /*
+ * Skip the host capability request for the firmware versions which
+ * do not support this feature.
+ */
+ if (!test_bit(ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK, &ar_snoc->flags)) {
+ ret = ath10k_qmi_host_cap_send_sync(qmi);
+ if (ret)
+ return;
+ }
ret = ath10k_qmi_msa_mem_info_send_sync_msg(qmi);
if (ret)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index f72f236fb9eb3..3106502275781 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1362,6 +1362,9 @@ static void ath10k_snoc_quirks_init(struct ath10k *ar)
if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
+
+ if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-skip-quirk"))
+ set_bit(ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK, &ar_snoc->flags);
}
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index 1ecae34687c21..46574fd8f84ee 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -51,6 +51,7 @@ enum ath10k_snoc_flags {
ATH10K_SNOC_FLAG_MODEM_STOPPED,
ATH10K_SNOC_FLAG_RECOVERY,
ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
+ ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK,
};
struct clk_bulk_data;
--
2.53.0
^ permalink raw reply related
* [PATCH v3 0/3] ath10k: Introduce a devicetree quirk to skip host cap QMI requests
From: David Heidelberg via B4 Relay @ 2026-03-25 16:41 UTC (permalink / raw)
To: Johannes Berg, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jeff Johnson, Bjorn Andersson, Konrad Dybcio, Paul Sajna
Cc: Amit Pundir, linux-wireless, devicetree, ath10k, linux-kernel,
linux-arm-msm, phone-devel, David Heidelberg
This quirk is used so far used on:
- LG G7 ThinQ
- Xiaomi Poco F1
I'm resending it after ~ 4 years since initial send due to Snapdragon
845 being one of best supported platform for mobile phones running
Linux, so it would be shame to not have shiny support.
Original thread:
https://lore.kernel.org/all/b796bfee-b753-479a-a8d6-ba1fe3ee6222@ixit.cz/
I tried the embedding the information inside the firmware, but the
information is required *before* loading the firmware itself.
Firmware quirk thread:
https://lore.kernel.org/linux-wireless/20251111-xiaomi-beryllium-firmware-v1-0-836b9c51ad86@ixit.cz/
Until merged, available also at:
https://codeberg.org/sdm845/linux/commits/branch/b4/skip-host-cam-qmi-req
Signed-off-by: David Heidelberg <david@ixit.cz>
---
Changes in v3:
- Rebased on recent linux-next (next-20260325).
- Improved motivation and description. (Dmitry)
- Link to v2: https://lore.kernel.org/r/20251110-skip-host-cam-qmi-req-v2-0-0daf485a987a@ixit.cz
---
Amit Pundir (3):
dt-bindings: wireless: ath10k: Introduce quirk to skip host cap QMI requests
ath10k: Introduce a device-tree quirk to skip host cap QMI requests
arm64: dts: qcom: sdm845-xiaomi-beryllium: Enable ath10k host-cap skip quirk
.../devicetree/bindings/net/wireless/qcom,ath10k.yaml | 6 ++++++
.../arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi | 1 +
drivers/net/wireless/ath/ath10k/qmi.c | 13 ++++++++++---
drivers/net/wireless/ath/ath10k/snoc.c | 3 +++
drivers/net/wireless/ath/ath10k/snoc.h | 1 +
5 files changed, 21 insertions(+), 3 deletions(-)
---
base-commit: 85964cdcad0fac9a0eb7b87a0f9d88cc074b854c
change-id: 20251110-skip-host-cam-qmi-req-e155628ebc39
Best regards,
--
David Heidelberg <david@ixit.cz>
^ permalink raw reply
* [PATCH v3 3/3] arm64: dts: qcom: sdm845-xiaomi-beryllium: Enable ath10k host-cap skip quirk
From: David Heidelberg via B4 Relay @ 2026-03-25 16:41 UTC (permalink / raw)
To: Johannes Berg, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jeff Johnson, Bjorn Andersson, Konrad Dybcio, Paul Sajna
Cc: Amit Pundir, linux-wireless, devicetree, ath10k, linux-kernel,
linux-arm-msm, phone-devel, David Heidelberg
In-Reply-To: <20260325-skip-host-cam-qmi-req-v3-0-b163cf7b3c81@ixit.cz>
From: Amit Pundir <amit.pundir@linaro.org>
The WiFi firmware used on Xiaomi PocoPhone F1 (beryllium) phone
doesn't support the host-capability QMI request, hence enable
the skip quirk for this device.
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
index 1298485c42142..950bbcc3bf91f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
@@ -661,5 +661,6 @@ &wifi {
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
qcom,calibration-variant = "xiaomi_beryllium";
+ qcom,snoc-host-cap-skip-quirk;
};
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v4 8/9] dt-bindings: net: wireless: brcm: Add compatible for bcm43752
From: Rob Herring @ 2026-03-25 17:09 UTC (permalink / raw)
To: Ronald Claveau
Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Krzysztof Kozlowski, Conor Dooley, Ulf Hansson, Johannes Berg,
van Spriel, linux-arm-kernel, linux-amlogic, devicetree,
linux-kernel, linux-mmc, linux-wireless
In-Reply-To: <20260325-add-emmc-t7-vim4-v4-8-44c7b4a5e459@aliel.fr>
On Wed, Mar 25, 2026 at 10:15:26AM +0100, Ronald Claveau wrote:
> Add bcm43752 compatible with its bcm4329 compatible fallback.
>
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
Missing Conor's ack.
> ---
> Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> index 3be7576787644..81fd3e37452a6 100644
> --- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> +++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> @@ -42,6 +42,7 @@ properties:
> - brcm,bcm4356-fmac
> - brcm,bcm4359-fmac
> - brcm,bcm4366-fmac
> + - brcm,bcm43752-fmac
> - cypress,cyw4373-fmac
> - cypress,cyw43012-fmac
> - infineon,cyw43439-fmac
>
> --
> 2.49.0
>
^ permalink raw reply
* Re: [PATCH v3 2/3] ath10k: Introduce a device-tree quirk to skip host cap QMI requests
From: Dmitry Baryshkov @ 2026-03-25 17:15 UTC (permalink / raw)
To: david
Cc: Johannes Berg, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jeff Johnson, Bjorn Andersson, Konrad Dybcio, Paul Sajna,
Amit Pundir, linux-wireless, devicetree, ath10k, linux-kernel,
linux-arm-msm, phone-devel
In-Reply-To: <20260325-skip-host-cam-qmi-req-v3-2-b163cf7b3c81@ixit.cz>
On Wed, Mar 25, 2026 at 05:41:13PM +0100, David Heidelberg via B4 Relay wrote:
> From: Amit Pundir <amit.pundir@linaro.org>
>
> There are firmware versions which do not support host capability QMI
> request. We suspect either the host cap is not implemented or there may
> be firmware specific issues, but apparently there seem to be a generation
> of firmware that has this particular behavior.
It needs to be explicit that this happens _before_ firmware-N.bin and
board-M.bin loading. As such, you can't add a quirk to the firmware.bin
(a standard way to handle firmware issues).
> For example, firmware build on Xiaomi Poco F1 (sdm845) phone:
> "QC_IMAGE_VERSION_STRING=WLAN.HL.2.0.c3-00257-QCAHLSWMTPLZ-1"
>
> If we do not skip the host cap QMI request on Poco F1, then we get a
> QMI_ERR_MALFORMED_MSG_V01 error message before loading the firmware in the
> ath10k_qmi_host_cap_send_sync(). This error message is not fatal to the
> firmware nor to the ath10k driver and we can still bring up the WiFi
> services successfully if we just ignore it.
>
> Hence introducing this device-tree quirk to skip host capability
> QMI request for the devices with firmware versions which do not support
> this feature.
>
> Suggested-by: Bjorn Andersson <andersson@kernel.org>
> Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
You are sending the patch, but it misses your SoB.
> ---
> drivers/net/wireless/ath/ath10k/qmi.c | 13 ++++++++++---
> drivers/net/wireless/ath/ath10k/snoc.c | 3 +++
> drivers/net/wireless/ath/ath10k/snoc.h | 1 +
> 3 files changed, 14 insertions(+), 3 deletions(-)
--
With best wishes
Dmitry
^ permalink raw reply
* [PATCH v2] wifi: mt76: mt7996: disable UNI_BSS_INFO_PROTECT_INFO for mt7996
From: Ryder Lee @ 2026-03-25 17:17 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-mediatek, linux-wireless, Shayne Chen, Ryder Lee
The current MT7996 firmware causes TX failure and need further
investigation, so it is temporarily disabled.
MT7992 and MT7990 are working normally.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
v2 - add a comment to describe why this check is required.
---
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 16420375112d..ae068392b9dd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1281,6 +1281,10 @@ int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *li
PROT_NONGF_STA = BIT(7),
};
+ /* The current firmware causes TX failure. Need further investigation */
+ if (is_mt7996(&dev->mt76))
+ return 0;
+
skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76,
MT7996_BSS_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
--
2.45.2
^ permalink raw reply related
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