* Re: [PATCH wireless-next] wifi: cfg80211: make cluster id an array
From: kernel test robot @ 2026-03-01 14:26 UTC (permalink / raw)
To: Miri Korenblit, linux-wireless; +Cc: oe-kbuild-all
In-Reply-To: <20260301131848.b0085a6b4eb3.Ib16bf5cca55463d4c89e18099cf1dfe4de95d405@changeid>
Hi Miri,
kernel test robot noticed the following build warnings:
[auto build test WARNING on wireless-next/main]
[also build test WARNING on wireless/main linus/master v7.0-rc1 next-20260227]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Miri-Korenblit/wifi-cfg80211-make-cluster-id-an-array/20260301-192010
base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
patch link: https://lore.kernel.org/r/20260301131848.b0085a6b4eb3.Ib16bf5cca55463d4c89e18099cf1dfe4de95d405%40changeid
patch subject: [PATCH wireless-next] wifi: cfg80211: make cluster id an array
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20260301/202603012218.ucVoRBov-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260301/202603012218.ucVoRBov-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603012218.ucVoRBov-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/net/wireless/virtual/mac80211_hwsim.c: In function 'mac80211_hwsim_start_nan':
>> drivers/net/wireless/virtual/mac80211_hwsim.c:4081:13: warning: the comparison will always evaluate as 'true' for the address of 'cluster_id' will never be NULL [-Waddress]
4081 | if (conf->cluster_id && !is_zero_ether_addr(conf->cluster_id) &&
| ^~~~
In file included from include/net/mac80211.h:22,
from drivers/net/wireless/virtual/mac80211_hwsim.c:22:
include/net/cfg80211.h:4038:12: note: 'cluster_id' declared here
4038 | u8 cluster_id[ETH_ALEN] __aligned(2);
| ^~~~~~~~~~
vim +4081 drivers/net/wireless/virtual/mac80211_hwsim.c
a37a6f54439bf8 Ilan Peer 2025-09-08 4052
a37a6f54439bf8 Ilan Peer 2025-09-08 4053 static int mac80211_hwsim_start_nan(struct ieee80211_hw *hw,
a37a6f54439bf8 Ilan Peer 2025-09-08 4054 struct ieee80211_vif *vif,
a37a6f54439bf8 Ilan Peer 2025-09-08 4055 struct cfg80211_nan_conf *conf)
a37a6f54439bf8 Ilan Peer 2025-09-08 4056 {
a37a6f54439bf8 Ilan Peer 2025-09-08 4057 struct mac80211_hwsim_data *data = hw->priv;
a37a6f54439bf8 Ilan Peer 2025-09-08 4058 u64 tsf = mac80211_hwsim_get_tsf(hw, NULL);
a37a6f54439bf8 Ilan Peer 2025-09-08 4059 u32 dw_int = 512 * 1000;
a37a6f54439bf8 Ilan Peer 2025-09-08 4060 u64 until_dw = dw_int - do_div(tsf, dw_int);
a37a6f54439bf8 Ilan Peer 2025-09-08 4061 struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif);
a37a6f54439bf8 Ilan Peer 2025-09-08 4062
a37a6f54439bf8 Ilan Peer 2025-09-08 4063 if (vif->type != NL80211_IFTYPE_NAN)
a37a6f54439bf8 Ilan Peer 2025-09-08 4064 return -EINVAL;
a37a6f54439bf8 Ilan Peer 2025-09-08 4065
a37a6f54439bf8 Ilan Peer 2025-09-08 4066 if (data->nan_device_vif)
a37a6f54439bf8 Ilan Peer 2025-09-08 4067 return -EALREADY;
a37a6f54439bf8 Ilan Peer 2025-09-08 4068
a37a6f54439bf8 Ilan Peer 2025-09-08 4069 /* set this before starting the timer, as preemption might occur */
a37a6f54439bf8 Ilan Peer 2025-09-08 4070 data->nan_device_vif = vif;
a37a6f54439bf8 Ilan Peer 2025-09-08 4071 data->nan_bands = conf->bands;
a37a6f54439bf8 Ilan Peer 2025-09-08 4072 data->nan_curr_dw_band = NL80211_BAND_2GHZ;
a37a6f54439bf8 Ilan Peer 2025-09-08 4073
a37a6f54439bf8 Ilan Peer 2025-09-08 4074 wiphy_debug(hw->wiphy, "nan_started, next_dw=%llu\n",
a37a6f54439bf8 Ilan Peer 2025-09-08 4075 until_dw);
a37a6f54439bf8 Ilan Peer 2025-09-08 4076
a37a6f54439bf8 Ilan Peer 2025-09-08 4077 hrtimer_start(&data->nan_timer,
a37a6f54439bf8 Ilan Peer 2025-09-08 4078 ns_to_ktime(until_dw * NSEC_PER_USEC),
a37a6f54439bf8 Ilan Peer 2025-09-08 4079 HRTIMER_MODE_REL_SOFT);
a37a6f54439bf8 Ilan Peer 2025-09-08 4080
a37a6f54439bf8 Ilan Peer 2025-09-08 @4081 if (conf->cluster_id && !is_zero_ether_addr(conf->cluster_id) &&
a37a6f54439bf8 Ilan Peer 2025-09-08 4082 is_zero_ether_addr(hwsim_nan_cluster_id)) {
a37a6f54439bf8 Ilan Peer 2025-09-08 4083 memcpy(hwsim_nan_cluster_id, conf->cluster_id, ETH_ALEN);
a37a6f54439bf8 Ilan Peer 2025-09-08 4084 } else if (is_zero_ether_addr(hwsim_nan_cluster_id)) {
a37a6f54439bf8 Ilan Peer 2025-09-08 4085 hwsim_nan_cluster_id[0] = 0x50;
a37a6f54439bf8 Ilan Peer 2025-09-08 4086 hwsim_nan_cluster_id[1] = 0x6f;
a37a6f54439bf8 Ilan Peer 2025-09-08 4087 hwsim_nan_cluster_id[2] = 0x9a;
a37a6f54439bf8 Ilan Peer 2025-09-08 4088 hwsim_nan_cluster_id[3] = 0x01;
a37a6f54439bf8 Ilan Peer 2025-09-08 4089 hwsim_nan_cluster_id[4] = get_random_u8();
a37a6f54439bf8 Ilan Peer 2025-09-08 4090 hwsim_nan_cluster_id[5] = get_random_u8();
a37a6f54439bf8 Ilan Peer 2025-09-08 4091 }
a37a6f54439bf8 Ilan Peer 2025-09-08 4092
a37a6f54439bf8 Ilan Peer 2025-09-08 4093 data->notify_dw = conf->enable_dw_notification;
a37a6f54439bf8 Ilan Peer 2025-09-08 4094
a37a6f54439bf8 Ilan Peer 2025-09-08 4095 cfg80211_nan_cluster_joined(wdev, hwsim_nan_cluster_id, true,
a37a6f54439bf8 Ilan Peer 2025-09-08 4096 GFP_KERNEL);
a37a6f54439bf8 Ilan Peer 2025-09-08 4097
a37a6f54439bf8 Ilan Peer 2025-09-08 4098 return 0;
a37a6f54439bf8 Ilan Peer 2025-09-08 4099 }
a37a6f54439bf8 Ilan Peer 2025-09-08 4100
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH wireless-next] wifi: cfg80211: make cluster id an array
From: Miri Korenblit @ 2026-03-01 11:18 UTC (permalink / raw)
To: linux-wireless
cfg80211_nan_conf::cluster_id is currently a pointer, but there is no real
reason to not have it an array. It makes things easier as there is no
need to check the pointer validity each time.
If a cluster ID wasn't provided by user space it will be randomized.
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mld/nan.c | 5 ++---
include/net/cfg80211.h | 3 +--
net/mac80211/cfg.c | 12 ++----------
net/wireless/nl80211.c | 14 +++++++++++---
4 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.c b/drivers/net/wireless/intel/iwlwifi/mld/nan.c
index 2dbd3d58b0c6..4d8e85f2bd7c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/nan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.c
@@ -54,9 +54,8 @@ static int iwl_mld_nan_config(struct iwl_mld *mld,
ether_addr_copy(cmd.nmi_addr, vif->addr);
cmd.master_pref = conf->master_pref;
- if (conf->cluster_id)
- memcpy(cmd.cluster_id, conf->cluster_id + 4,
- sizeof(cmd.cluster_id));
+ memcpy(cmd.cluster_id, conf->cluster_id + 4,
+ sizeof(cmd.cluster_id));
cmd.scan_period = conf->scan_period < 255 ? conf->scan_period : 255;
cmd.dwell_time =
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fc01de19c798..73f4aa15c956 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4020,7 +4020,6 @@ struct cfg80211_nan_band_config {
* (i.e. BIT(NL80211_BAND_2GHZ)).
* @cluster_id: cluster ID used for NAN synchronization. This is a MAC address
* that can take a value from 50-6F-9A-01-00-00 to 50-6F-9A-01-FF-FF.
- * If NULL, the device will pick a random Cluster ID.
* @scan_period: period (in seconds) between NAN scans.
* @scan_dwell_time: dwell time (in milliseconds) for NAN scans.
* @discovery_beacon_interval: interval (in TUs) for discovery beacons.
@@ -4036,7 +4035,7 @@ struct cfg80211_nan_band_config {
struct cfg80211_nan_conf {
u8 master_pref;
u8 bands;
- const u8 *cluster_id;
+ u8 cluster_id[ETH_ALEN] __aligned(2);
u16 scan_period;
u16 scan_dwell_time;
u8 discovery_beacon_interval;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b92b4a5c2636..490e2d9b1720 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -330,7 +330,6 @@ static void ieee80211_stop_p2p_device(struct wiphy *wiphy,
static void ieee80211_nan_conf_free(struct cfg80211_nan_conf *conf)
{
- kfree(conf->cluster_id);
kfree(conf->extra_nan_attrs);
kfree(conf->vendor_elems);
memset(conf, 0, sizeof(*conf));
@@ -372,9 +371,6 @@ static int ieee80211_nan_conf_copy(struct cfg80211_nan_conf *dst,
memcpy(&dst->band_cfgs, &src->band_cfgs,
sizeof(dst->band_cfgs));
- kfree(dst->cluster_id);
- dst->cluster_id = NULL;
-
kfree(dst->extra_nan_attrs);
dst->extra_nan_attrs = NULL;
dst->extra_nan_attrs_len = 0;
@@ -383,12 +379,8 @@ static int ieee80211_nan_conf_copy(struct cfg80211_nan_conf *dst,
dst->vendor_elems = NULL;
dst->vendor_elems_len = 0;
- if (src->cluster_id) {
- dst->cluster_id = kmemdup(src->cluster_id, ETH_ALEN,
- GFP_KERNEL);
- if (!dst->cluster_id)
- goto no_mem;
- }
+ if (is_zero_ether_addr(dst->cluster_id))
+ ether_addr_copy(dst->cluster_id, src->cluster_id);
if (src->extra_nan_attrs && src->extra_nan_attrs_len) {
dst->extra_nan_attrs = kmemdup(src->extra_nan_attrs,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b94231c8441c..e220ccbba91b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -21,6 +21,7 @@
#include <linux/nospec.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
+#include <linux/random.h>
#include <net/net_namespace.h>
#include <net/genetlink.h>
#include <net/cfg80211.h>
@@ -15725,9 +15726,16 @@ static int nl80211_parse_nan_conf(struct wiphy *wiphy,
return err;
changed |= CFG80211_NAN_CONF_CHANGED_CONFIG;
- if (attrs[NL80211_NAN_CONF_CLUSTER_ID] && start)
- conf->cluster_id =
- nla_data(attrs[NL80211_NAN_CONF_CLUSTER_ID]);
+ if (attrs[NL80211_NAN_CONF_CLUSTER_ID] && start) {
+ ether_addr_copy(conf->cluster_id,
+ nla_data(attrs[NL80211_NAN_CONF_CLUSTER_ID]));
+ } else if (start) {
+ conf->cluster_id[0] = 0x50;
+ conf->cluster_id[1] = 0x6f;
+ conf->cluster_id[2] = 0x9a;
+ conf->cluster_id[3] = 0x01;
+ get_random_bytes(&conf->cluster_id[4], 2);
+ }
if (attrs[NL80211_NAN_CONF_EXTRA_ATTRS]) {
conf->extra_nan_attrs =
--
2.34.1
^ permalink raw reply related
* [syzbot] Monthly wireless report (Mar 2026)
From: syzbot @ 2026-03-01 6:22 UTC (permalink / raw)
To: linux-kernel, linux-wireless, netdev, syzkaller-bugs
Hello wireless maintainers/developers,
This is a 31-day syzbot report for the wireless subsystem.
All related reports/information can be found at:
https://syzkaller.appspot.com/upstream/s/wireless
During the period, 4 new issues were detected and 1 were fixed.
In total, 51 issues are still open and 172 have already been fixed.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 26998 Yes WARNING in rate_control_rate_init (3)
https://syzkaller.appspot.com/bug?extid=9bdc0c5998ab45b05030
<2> 10549 Yes WARNING in __rate_control_send_low (3)
https://syzkaller.appspot.com/bug?extid=34463a129786910405dd
<3> 10251 No WARNING in kcov_remote_start (6)
https://syzkaller.appspot.com/bug?extid=3f51ad7ac3ae57a6fdcc
<4> 6932 Yes WARNING in __cfg80211_ibss_joined (2)
https://syzkaller.appspot.com/bug?extid=7f064ba1704c2466e36d
<5> 1226 Yes WARNING in ieee80211_start_next_roc
https://syzkaller.appspot.com/bug?extid=c3a167b5615df4ccd7fb
<6> 1043 Yes INFO: task hung in reg_process_self_managed_hints
https://syzkaller.appspot.com/bug?extid=1f16507d9ec05f64210a
<7> 864 Yes INFO: task hung in reg_check_chans_work (7)
https://syzkaller.appspot.com/bug?extid=a2de4763f84f61499210
<8> 790 Yes INFO: rcu detected stall in ieee80211_handle_queued_frames
https://syzkaller.appspot.com/bug?extid=1c991592da3ef18957c0
<9> 691 Yes WARNING in ieee80211_tx_h_rate_ctrl
https://syzkaller.appspot.com/bug?extid=0d516b33238bd97ee864
<10> 354 Yes WARNING in ieee80211_tx_skb_tid
https://syzkaller.appspot.com/bug?extid=8bd4574e8c52c48c2595
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
You may send multiple commands in a single email message.
^ permalink raw reply
* [PATCH] wifi: rtw89: retry efuse physical map dump on transient failure
From: Christian Hewitt @ 2026-03-01 4:24 UTC (permalink / raw)
To: Ping-Ke Shih, Bitterblue Smith, linux-wireless, linux-kernel
On Radxa Rock 5B with a RTL8852BE combo WiFi/BT card, the efuse
physical map dump intermittently fails with -EBUSY during probe.
The failure occurs in rtw89_dump_physical_efuse_map_ddv() where
read_poll_timeout_atomic() times out waiting for the B_AX_EF_RDY
bit after 1 second.
The root cause is a timing race during boot: the WiFi driver's
chip initialization (firmware download via PCIe) overlaps with the
Bluetooth firmware download to the same combo chip over USB. This
can leave the efuse controller temporarily unavailable when the
WiFi driver attempts to read the efuse map.
Add a retry loop (up to 3 attempts with 500ms delays) around the
physical efuse map dump in rtw89_parse_efuse_map_ax(). The firmware
download path already retries up to 5 times, but the efuse read
that follows has no retry logic, making it the weak link in the
probe sequence.
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
---
The LibreELEC distro is minimalist and fast-booting with some
history of exposing racy probing and timing issues that don't
show up on the mainstream distros. Below are some before/after
dmesg prints to support the patch:
Before:
ROCK5B:~ # dmesg | grep rtw89
[ 6.575383] rtw89_8852be 0002:21:00.0: loaded firmware rtw89/rtw8852b_fw-1.bin
[ 6.575538] rtw89_8852be 0002:21:00.0: enabling device (0000 -> 0003)
[ 6.585763] rtw89_8852be 0002:21:00.0: Firmware version 0.29.29.15 (6fb3ec41), cmd version 0, type 5
[ 6.585779] rtw89_8852be 0002:21:00.0: Firmware version 0.29.29.15 (6fb3ec41), cmd version 0, type 3
[ 10.174946] rtw89_8852be 0002:21:00.0: failed to dump efuse physical map
[ 10.176584] rtw89_8852be 0002:21:00.0: failed to setup chip information
[ 10.178173] rtw89_8852be 0002:21:00.0: probe with driver rtw89_8852be failed with error -16
After:
ROCK5B:~ # dmesg | grep rtw89
[ 7.393558] rtw89_8852be 0002:21:00.0: loaded firmware rtw89/rtw8852b_fw-1.bin
[ 7.393729] rtw89_8852be 0002:21:00.0: enabling device (0000 -> 0003)
[ 7.406341] rtw89_8852be 0002:21:00.0: Firmware version 0.29.29.15 (6fb3ec41), cmd version 0, type 5
[ 7.406363] rtw89_8852be 0002:21:00.0: Firmware version 0.29.29.15 (6fb3ec41), cmd version 0, type 3
[ 11.041563] rtw89_8852be 0002:21:00.0: efuse dump failed, retrying (1)
[ 11.798390] rtw89_8852be 0002:21:00.0: chip info CID: 0, CV: 1, AID: 0, ACV: 1, RFE: 1
[ 11.801013] rtw89_8852be 0002:21:00.0: rfkill hardware state changed to enable
For context, firmware also fails (and recovers) sometimes:
ROCK5B:~ # dmesg | grep rtw89
[ 6.436873] rtw89_8852be 0002:21:00.0: loaded firmware rtw89/rtw8852b_fw-1.bin
[ 6.437165] rtw89_8852be 0002:21:00.0: enabling device (0000 -> 0003)
[ 6.450228] rtw89_8852be 0002:21:00.0: Firmware version 0.29.29.15 (6fb3ec41), cmd version 0, type 5
[ 6.450239] rtw89_8852be 0002:21:00.0: Firmware version 0.29.29.15 (6fb3ec41), cmd version 0, type 3
[ 7.864148] rtw89_8852be 0002:21:00.0: fw security fail
[ 7.864154] rtw89_8852be 0002:21:00.0: download firmware fail
[ 7.864160] rtw89_8852be 0002:21:00.0: [ERR]fwdl 0x1E0 = 0x62
[ 7.864165] rtw89_8852be 0002:21:00.0: [ERR]fwdl 0x83F0 = 0x80011
[ 7.864173] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931150
[ 7.864188] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931150
[ 7.864203] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 7.864219] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 7.864234] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 7.864250] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931150
[ 7.864265] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931150
[ 7.864281] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931150
[ 7.864296] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 7.864311] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 7.864327] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 7.864342] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931150
[ 7.864358] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 7.864373] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 7.864387] rtw89_8852be 0002:21:00.0: [ERR]fw PC = 0xb8931154
[ 8.181342] rtw89_8852be 0002:21:00.0: chip info CID: 0, CV: 1, AID: 0, ACV: 1, RFE: 1
[ 8.184322] rtw89_8852be 0002:21:00.0: rfkill hardware state changed to enable
drivers/net/wireless/realtek/rtw89/efuse.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c
index a2757a88d55d..d506f04ffd6c 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse.c
@@ -270,6 +270,7 @@ int rtw89_parse_efuse_map_ax(struct rtw89_dev *rtwdev)
u8 *log_map = NULL;
u8 *dav_phy_map = NULL;
u8 *dav_log_map = NULL;
+ int retry;
int ret;
if (rtw89_read16(rtwdev, R_AX_SYS_WL_EFUSE_CTRL) & B_AX_AUTOLOAD_SUS)
@@ -289,7 +290,17 @@ int rtw89_parse_efuse_map_ax(struct rtw89_dev *rtwdev)
goto out_free;
}
- ret = rtw89_dump_physical_efuse_map(rtwdev, phy_map, 0, phy_size, false);
+ for (retry = 0; retry < 3; retry++) {
+ if (retry) {
+ rtw89_warn(rtwdev, "efuse dump failed, retrying (%d)\n",
+ retry);
+ fsleep(500000);
+ }
+ ret = rtw89_dump_physical_efuse_map(rtwdev, phy_map, 0,
+ phy_size, false);
+ if (!ret)
+ break;
+ }
if (ret) {
rtw89_warn(rtwdev, "failed to dump efuse physical map\n");
goto out_free;
--
2.43.0
^ permalink raw reply related
* FAILED: Patch "net: intel: fix PCI device ID conflict between i40e and ipw2200" failed to apply to 5.10-stable tree
From: Sasha Levin @ 2026-03-01 2:05 UTC (permalink / raw)
To: stable, enelsonmoore
Cc: Johannes Berg, Aleksandr Loktionov, Jakub Kicinski,
intel-wired-lan, netdev, linux-wireless
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From d03e094473ecdeb68d853752ba467abe13e1de44 Mon Sep 17 00:00:00 2001
From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Date: Mon, 9 Feb 2026 18:12:34 -0800
Subject: [PATCH] net: intel: fix PCI device ID conflict between i40e and
ipw2200
The ID 8086:104f is matched by both i40e and ipw2200. The same device
ID should not be in more than one driver, because in that case, which
driver is used is unpredictable. Fix this by taking advantage of the
fact that i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
devices use PCI_CLASS_NETWORK_OTHER to differentiate the devices.
Fixes: 2e45d3f4677a ("i40e: Add support for X710 B/P & SFP+ cards")
Cc: stable@vger.kernel.org
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20260210021235.16315-1-enelsonmoore@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++++++-
drivers/net/wireless/intel/ipw2x00/ipw2200.c | 8 +++++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d3bc3207054f9..02de186dcc8f5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -75,7 +75,13 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_BC), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_SFP), 0},
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_B), 0},
+ /*
+ * This ID conflicts with ipw2200, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_10G_B),
+ PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0},
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 09035a77e775f..b0e769da94156 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -11387,7 +11387,13 @@ static const struct pci_device_id card_ids[] = {
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
- {PCI_VDEVICE(INTEL, 0x104f), 0},
+ /*
+ * This ID conflicts with i40e, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x104f),
+ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */
--
2.51.0
^ permalink raw reply related
* FAILED: Patch "net: intel: fix PCI device ID conflict between i40e and ipw2200" failed to apply to 5.15-stable tree
From: Sasha Levin @ 2026-03-01 1:55 UTC (permalink / raw)
To: stable, enelsonmoore
Cc: Johannes Berg, Aleksandr Loktionov, Jakub Kicinski,
intel-wired-lan, netdev, linux-wireless
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From d03e094473ecdeb68d853752ba467abe13e1de44 Mon Sep 17 00:00:00 2001
From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Date: Mon, 9 Feb 2026 18:12:34 -0800
Subject: [PATCH] net: intel: fix PCI device ID conflict between i40e and
ipw2200
The ID 8086:104f is matched by both i40e and ipw2200. The same device
ID should not be in more than one driver, because in that case, which
driver is used is unpredictable. Fix this by taking advantage of the
fact that i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
devices use PCI_CLASS_NETWORK_OTHER to differentiate the devices.
Fixes: 2e45d3f4677a ("i40e: Add support for X710 B/P & SFP+ cards")
Cc: stable@vger.kernel.org
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20260210021235.16315-1-enelsonmoore@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++++++-
drivers/net/wireless/intel/ipw2x00/ipw2200.c | 8 +++++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d3bc3207054f9..02de186dcc8f5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -75,7 +75,13 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_BC), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_SFP), 0},
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_B), 0},
+ /*
+ * This ID conflicts with ipw2200, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_10G_B),
+ PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0},
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 09035a77e775f..b0e769da94156 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -11387,7 +11387,13 @@ static const struct pci_device_id card_ids[] = {
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
- {PCI_VDEVICE(INTEL, 0x104f), 0},
+ /*
+ * This ID conflicts with i40e, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x104f),
+ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */
--
2.51.0
^ permalink raw reply related
* FAILED: Patch "net: intel: fix PCI device ID conflict between i40e and ipw2200" failed to apply to 6.1-stable tree
From: Sasha Levin @ 2026-03-01 1:47 UTC (permalink / raw)
To: stable, enelsonmoore
Cc: Johannes Berg, Aleksandr Loktionov, Jakub Kicinski,
intel-wired-lan, netdev, linux-wireless
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From d03e094473ecdeb68d853752ba467abe13e1de44 Mon Sep 17 00:00:00 2001
From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Date: Mon, 9 Feb 2026 18:12:34 -0800
Subject: [PATCH] net: intel: fix PCI device ID conflict between i40e and
ipw2200
The ID 8086:104f is matched by both i40e and ipw2200. The same device
ID should not be in more than one driver, because in that case, which
driver is used is unpredictable. Fix this by taking advantage of the
fact that i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
devices use PCI_CLASS_NETWORK_OTHER to differentiate the devices.
Fixes: 2e45d3f4677a ("i40e: Add support for X710 B/P & SFP+ cards")
Cc: stable@vger.kernel.org
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20260210021235.16315-1-enelsonmoore@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++++++-
drivers/net/wireless/intel/ipw2x00/ipw2200.c | 8 +++++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d3bc3207054f9..02de186dcc8f5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -75,7 +75,13 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_BC), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_SFP), 0},
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_B), 0},
+ /*
+ * This ID conflicts with ipw2200, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_10G_B),
+ PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0},
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 09035a77e775f..b0e769da94156 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -11387,7 +11387,13 @@ static const struct pci_device_id card_ids[] = {
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
- {PCI_VDEVICE(INTEL, 0x104f), 0},
+ /*
+ * This ID conflicts with i40e, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x104f),
+ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */
--
2.51.0
^ permalink raw reply related
* FAILED: Patch "net: qrtr: Drop the MHI auto_queue feature for IPCR DL channels" failed to apply to 6.1-stable tree
From: Sasha Levin @ 2026-03-01 1:40 UTC (permalink / raw)
To: stable, manivannan.sadhasivam
Cc: Johan Hovold, Chris Lew, Jeff Hugo, Loic Poulain, Jeff Johnson,
Paolo Abeni, linux-arm-msm, dri-devel, mhi, linux-wireless,
ath11k, ath12k, netdev
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 51731792a25cb312ca94cdccfa139eb46de1b2ef Mon Sep 17 00:00:00 2001
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Date: Thu, 18 Dec 2025 22:21:44 +0530
Subject: [PATCH] net: qrtr: Drop the MHI auto_queue feature for IPCR DL
channels
MHI stack offers the 'auto_queue' feature, which allows the MHI stack to
auto queue the buffers for the RX path (DL channel). Though this feature
simplifies the client driver design, it introduces race between the client
drivers and the MHI stack. For instance, with auto_queue, the 'dl_callback'
for the DL channel may get called before the client driver is fully probed.
This means, by the time the dl_callback gets called, the client driver's
structures might not be initialized, leading to NULL ptr dereference.
Currently, the drivers have to workaround this issue by initializing the
internal structures before calling mhi_prepare_for_transfer_autoqueue().
But even so, there is a chance that the client driver's internal code path
may call the MHI queue APIs before mhi_prepare_for_transfer_autoqueue() is
called, leading to similar NULL ptr dereference. This issue has been
reported on the Qcom X1E80100 CRD machines affecting boot.
So to properly fix all these races, drop the MHI 'auto_queue' feature
altogether and let the client driver (QRTR) manage the RX buffers manually.
In the QRTR driver, queue the RX buffers based on the ring length during
probe and recycle the buffers in 'dl_callback' once they are consumed. This
also warrants removing the setting of 'auto_queue' flag from controller
drivers.
Currently, this 'auto_queue' feature is only enabled for IPCR DL channel.
So only the QRTR client driver requires the modification.
Fixes: 227fee5fc99e ("bus: mhi: core: Add an API for auto queueing buffers for DL channel")
Fixes: 68a838b84eff ("net: qrtr: start MHI channel after endpoit creation")
Reported-by: Johan Hovold <johan@kernel.org>
Closes: https://lore.kernel.org/linux-arm-msm/ZyTtVdkCCES0lkl4@hovoldconsulting.com
Suggested-by: Chris Lew <quic_clew@quicinc.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Acked-by: Jeff Johnson <jjohnson@kernel.org> # drivers/net/wireless/ath/...
Acked-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20251218-qrtr-fix-v2-1-c7499bfcfbe0@oss.qualcomm.com
---
drivers/accel/qaic/mhi_controller.c | 44 -----------------
drivers/bus/mhi/host/pci_generic.c | 20 +-------
drivers/net/wireless/ath/ath11k/mhi.c | 4 --
drivers/net/wireless/ath/ath12k/mhi.c | 4 --
net/qrtr/mhi.c | 69 ++++++++++++++++++++++-----
5 files changed, 60 insertions(+), 81 deletions(-)
diff --git a/drivers/accel/qaic/mhi_controller.c b/drivers/accel/qaic/mhi_controller.c
index 13a14c6c61689..4d787f77ce419 100644
--- a/drivers/accel/qaic/mhi_controller.c
+++ b/drivers/accel/qaic/mhi_controller.c
@@ -39,7 +39,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -55,7 +54,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -71,7 +69,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -87,7 +84,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -103,7 +99,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -119,7 +114,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -135,7 +129,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -151,7 +144,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -167,7 +159,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -183,7 +174,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -199,7 +189,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -215,7 +204,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -231,7 +219,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -247,7 +234,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -263,7 +249,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -279,7 +264,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -295,7 +279,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -311,7 +294,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -327,7 +309,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -343,7 +324,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -359,7 +339,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -375,7 +354,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -391,7 +369,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -407,7 +384,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -423,7 +399,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -439,7 +414,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
@@ -458,7 +432,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -474,7 +447,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -490,7 +462,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -506,7 +477,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -522,7 +492,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -538,7 +507,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -554,7 +522,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -570,7 +537,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -586,7 +552,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -602,7 +567,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -618,7 +582,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -634,7 +597,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -650,7 +612,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -666,7 +627,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -682,7 +642,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -698,7 +657,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -714,7 +672,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -730,7 +687,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index e3bc737313a2f..0884a384b77fc 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -94,22 +94,6 @@ struct mhi_pci_dev_info {
.doorbell_mode_switch = false, \
}
-#define MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(ch_num, ch_name, el_count, ev_ring) \
- { \
- .num = ch_num, \
- .name = ch_name, \
- .num_elements = el_count, \
- .event_ring = ev_ring, \
- .dir = DMA_FROM_DEVICE, \
- .ee_mask = BIT(MHI_EE_AMSS), \
- .pollcfg = 0, \
- .doorbell = MHI_DB_BRST_DISABLE, \
- .lpm_notify = false, \
- .offload_channel = false, \
- .doorbell_mode_switch = false, \
- .auto_queue = true, \
- }
-
#define MHI_EVENT_CONFIG_CTRL(ev_ring, el_count) \
{ \
.num_elements = el_count, \
@@ -329,7 +313,7 @@ static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 8, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 64, 2),
@@ -762,7 +746,7 @@ static const struct mhi_channel_config mhi_telit_fn980_hw_v1_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 16, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 16, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 16, 0),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
};
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index acd76e9392d31..d2c44f7f9b622 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -34,7 +34,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -48,7 +47,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -99,7 +97,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -113,7 +110,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index 08f44baf182a5..2dbdb95ae7bea 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -31,7 +31,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -45,7 +44,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -96,7 +94,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -110,7 +107,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c
index 69f53625a049d..80e341d2f8a45 100644
--- a/net/qrtr/mhi.c
+++ b/net/qrtr/mhi.c
@@ -24,13 +24,25 @@ static void qcom_mhi_qrtr_dl_callback(struct mhi_device *mhi_dev,
struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
int rc;
- if (!qdev || mhi_res->transaction_status)
+ if (!qdev || (mhi_res->transaction_status && mhi_res->transaction_status != -ENOTCONN))
return;
+ /* Channel got reset. So just free the buffer */
+ if (mhi_res->transaction_status == -ENOTCONN) {
+ devm_kfree(&mhi_dev->dev, mhi_res->buf_addr);
+ return;
+ }
+
rc = qrtr_endpoint_post(&qdev->ep, mhi_res->buf_addr,
mhi_res->bytes_xferd);
if (rc == -EINVAL)
dev_err(qdev->dev, "invalid ipcrouter packet\n");
+
+ /* Done with the buffer, now recycle it for future use */
+ rc = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, mhi_res->buf_addr,
+ mhi_dev->mhi_cntrl->buffer_len, MHI_EOT);
+ if (rc)
+ dev_err(&mhi_dev->dev, "Failed to recycle the buffer: %d\n", rc);
}
/* From QRTR to MHI */
@@ -72,6 +84,29 @@ static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
return rc;
}
+static int qcom_mhi_qrtr_queue_dl_buffers(struct mhi_device *mhi_dev)
+{
+ u32 free_desc;
+ void *buf;
+ int ret;
+
+ free_desc = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE);
+ while (free_desc--) {
+ buf = devm_kmalloc(&mhi_dev->dev, mhi_dev->mhi_cntrl->buffer_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, buf, mhi_dev->mhi_cntrl->buffer_len,
+ MHI_EOT);
+ if (ret) {
+ dev_err(&mhi_dev->dev, "Failed to queue buffer: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
const struct mhi_device_id *id)
{
@@ -87,20 +122,30 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
qdev->ep.xmit = qcom_mhi_qrtr_send;
dev_set_drvdata(&mhi_dev->dev, qdev);
- rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
- if (rc)
- return rc;
/* start channels */
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc) {
- qrtr_endpoint_unregister(&qdev->ep);
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc)
return rc;
- }
+
+ rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
+ if (rc)
+ goto err_unprepare;
+
+ rc = qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
+ if (rc)
+ goto err_unregister;
dev_dbg(qdev->dev, "Qualcomm MHI QRTR driver probed\n");
return 0;
+
+err_unregister:
+ qrtr_endpoint_unregister(&qdev->ep);
+err_unprepare:
+ mhi_unprepare_from_transfer(mhi_dev);
+
+ return rc;
}
static void qcom_mhi_qrtr_remove(struct mhi_device *mhi_dev)
@@ -151,11 +196,13 @@ static int __maybe_unused qcom_mhi_qrtr_pm_resume_early(struct device *dev)
if (state == MHI_STATE_M3)
return 0;
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc)
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc) {
dev_err(dev, "failed to prepare for autoqueue transfer %d\n", rc);
+ return rc;
+ }
- return rc;
+ return qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
}
static const struct dev_pm_ops qcom_mhi_qrtr_pm_ops = {
--
2.51.0
^ permalink raw reply related
* FAILED: Patch "net: intel: fix PCI device ID conflict between i40e and ipw2200" failed to apply to 6.6-stable tree
From: Sasha Levin @ 2026-03-01 1:38 UTC (permalink / raw)
To: stable, enelsonmoore
Cc: Johannes Berg, Aleksandr Loktionov, Jakub Kicinski,
intel-wired-lan, netdev, linux-wireless
The patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From d03e094473ecdeb68d853752ba467abe13e1de44 Mon Sep 17 00:00:00 2001
From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Date: Mon, 9 Feb 2026 18:12:34 -0800
Subject: [PATCH] net: intel: fix PCI device ID conflict between i40e and
ipw2200
The ID 8086:104f is matched by both i40e and ipw2200. The same device
ID should not be in more than one driver, because in that case, which
driver is used is unpredictable. Fix this by taking advantage of the
fact that i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
devices use PCI_CLASS_NETWORK_OTHER to differentiate the devices.
Fixes: 2e45d3f4677a ("i40e: Add support for X710 B/P & SFP+ cards")
Cc: stable@vger.kernel.org
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20260210021235.16315-1-enelsonmoore@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++++++-
drivers/net/wireless/intel/ipw2x00/ipw2200.c | 8 +++++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d3bc3207054f9..02de186dcc8f5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -75,7 +75,13 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_BC), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_SFP), 0},
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_B), 0},
+ /*
+ * This ID conflicts with ipw2200, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_10G_B),
+ PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0},
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 09035a77e775f..b0e769da94156 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -11387,7 +11387,13 @@ static const struct pci_device_id card_ids[] = {
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
- {PCI_VDEVICE(INTEL, 0x104f), 0},
+ /*
+ * This ID conflicts with i40e, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x104f),
+ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */
--
2.51.0
^ permalink raw reply related
* FAILED: Patch "net: qrtr: Drop the MHI auto_queue feature for IPCR DL channels" failed to apply to 6.6-stable tree
From: Sasha Levin @ 2026-03-01 1:30 UTC (permalink / raw)
To: stable, manivannan.sadhasivam
Cc: Johan Hovold, Chris Lew, Jeff Hugo, Loic Poulain, Jeff Johnson,
Paolo Abeni, linux-arm-msm, dri-devel, mhi, linux-wireless,
ath11k, ath12k, netdev
The patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 51731792a25cb312ca94cdccfa139eb46de1b2ef Mon Sep 17 00:00:00 2001
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Date: Thu, 18 Dec 2025 22:21:44 +0530
Subject: [PATCH] net: qrtr: Drop the MHI auto_queue feature for IPCR DL
channels
MHI stack offers the 'auto_queue' feature, which allows the MHI stack to
auto queue the buffers for the RX path (DL channel). Though this feature
simplifies the client driver design, it introduces race between the client
drivers and the MHI stack. For instance, with auto_queue, the 'dl_callback'
for the DL channel may get called before the client driver is fully probed.
This means, by the time the dl_callback gets called, the client driver's
structures might not be initialized, leading to NULL ptr dereference.
Currently, the drivers have to workaround this issue by initializing the
internal structures before calling mhi_prepare_for_transfer_autoqueue().
But even so, there is a chance that the client driver's internal code path
may call the MHI queue APIs before mhi_prepare_for_transfer_autoqueue() is
called, leading to similar NULL ptr dereference. This issue has been
reported on the Qcom X1E80100 CRD machines affecting boot.
So to properly fix all these races, drop the MHI 'auto_queue' feature
altogether and let the client driver (QRTR) manage the RX buffers manually.
In the QRTR driver, queue the RX buffers based on the ring length during
probe and recycle the buffers in 'dl_callback' once they are consumed. This
also warrants removing the setting of 'auto_queue' flag from controller
drivers.
Currently, this 'auto_queue' feature is only enabled for IPCR DL channel.
So only the QRTR client driver requires the modification.
Fixes: 227fee5fc99e ("bus: mhi: core: Add an API for auto queueing buffers for DL channel")
Fixes: 68a838b84eff ("net: qrtr: start MHI channel after endpoit creation")
Reported-by: Johan Hovold <johan@kernel.org>
Closes: https://lore.kernel.org/linux-arm-msm/ZyTtVdkCCES0lkl4@hovoldconsulting.com
Suggested-by: Chris Lew <quic_clew@quicinc.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Acked-by: Jeff Johnson <jjohnson@kernel.org> # drivers/net/wireless/ath/...
Acked-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20251218-qrtr-fix-v2-1-c7499bfcfbe0@oss.qualcomm.com
---
drivers/accel/qaic/mhi_controller.c | 44 -----------------
drivers/bus/mhi/host/pci_generic.c | 20 +-------
drivers/net/wireless/ath/ath11k/mhi.c | 4 --
drivers/net/wireless/ath/ath12k/mhi.c | 4 --
net/qrtr/mhi.c | 69 ++++++++++++++++++++++-----
5 files changed, 60 insertions(+), 81 deletions(-)
diff --git a/drivers/accel/qaic/mhi_controller.c b/drivers/accel/qaic/mhi_controller.c
index 13a14c6c61689..4d787f77ce419 100644
--- a/drivers/accel/qaic/mhi_controller.c
+++ b/drivers/accel/qaic/mhi_controller.c
@@ -39,7 +39,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -55,7 +54,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -71,7 +69,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -87,7 +84,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -103,7 +99,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -119,7 +114,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -135,7 +129,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -151,7 +144,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -167,7 +159,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -183,7 +174,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -199,7 +189,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -215,7 +204,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -231,7 +219,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -247,7 +234,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -263,7 +249,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -279,7 +264,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -295,7 +279,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -311,7 +294,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -327,7 +309,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -343,7 +324,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -359,7 +339,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -375,7 +354,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -391,7 +369,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -407,7 +384,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -423,7 +399,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -439,7 +414,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
@@ -458,7 +432,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -474,7 +447,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -490,7 +462,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -506,7 +477,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -522,7 +492,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -538,7 +507,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -554,7 +522,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -570,7 +537,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -586,7 +552,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -602,7 +567,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -618,7 +582,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -634,7 +597,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -650,7 +612,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -666,7 +627,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -682,7 +642,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -698,7 +657,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -714,7 +672,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -730,7 +687,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index e3bc737313a2f..0884a384b77fc 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -94,22 +94,6 @@ struct mhi_pci_dev_info {
.doorbell_mode_switch = false, \
}
-#define MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(ch_num, ch_name, el_count, ev_ring) \
- { \
- .num = ch_num, \
- .name = ch_name, \
- .num_elements = el_count, \
- .event_ring = ev_ring, \
- .dir = DMA_FROM_DEVICE, \
- .ee_mask = BIT(MHI_EE_AMSS), \
- .pollcfg = 0, \
- .doorbell = MHI_DB_BRST_DISABLE, \
- .lpm_notify = false, \
- .offload_channel = false, \
- .doorbell_mode_switch = false, \
- .auto_queue = true, \
- }
-
#define MHI_EVENT_CONFIG_CTRL(ev_ring, el_count) \
{ \
.num_elements = el_count, \
@@ -329,7 +313,7 @@ static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 8, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 64, 2),
@@ -762,7 +746,7 @@ static const struct mhi_channel_config mhi_telit_fn980_hw_v1_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 16, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 16, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 16, 0),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
};
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index acd76e9392d31..d2c44f7f9b622 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -34,7 +34,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -48,7 +47,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -99,7 +97,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -113,7 +110,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index 08f44baf182a5..2dbdb95ae7bea 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -31,7 +31,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -45,7 +44,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -96,7 +94,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -110,7 +107,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c
index 69f53625a049d..80e341d2f8a45 100644
--- a/net/qrtr/mhi.c
+++ b/net/qrtr/mhi.c
@@ -24,13 +24,25 @@ static void qcom_mhi_qrtr_dl_callback(struct mhi_device *mhi_dev,
struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
int rc;
- if (!qdev || mhi_res->transaction_status)
+ if (!qdev || (mhi_res->transaction_status && mhi_res->transaction_status != -ENOTCONN))
return;
+ /* Channel got reset. So just free the buffer */
+ if (mhi_res->transaction_status == -ENOTCONN) {
+ devm_kfree(&mhi_dev->dev, mhi_res->buf_addr);
+ return;
+ }
+
rc = qrtr_endpoint_post(&qdev->ep, mhi_res->buf_addr,
mhi_res->bytes_xferd);
if (rc == -EINVAL)
dev_err(qdev->dev, "invalid ipcrouter packet\n");
+
+ /* Done with the buffer, now recycle it for future use */
+ rc = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, mhi_res->buf_addr,
+ mhi_dev->mhi_cntrl->buffer_len, MHI_EOT);
+ if (rc)
+ dev_err(&mhi_dev->dev, "Failed to recycle the buffer: %d\n", rc);
}
/* From QRTR to MHI */
@@ -72,6 +84,29 @@ static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
return rc;
}
+static int qcom_mhi_qrtr_queue_dl_buffers(struct mhi_device *mhi_dev)
+{
+ u32 free_desc;
+ void *buf;
+ int ret;
+
+ free_desc = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE);
+ while (free_desc--) {
+ buf = devm_kmalloc(&mhi_dev->dev, mhi_dev->mhi_cntrl->buffer_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, buf, mhi_dev->mhi_cntrl->buffer_len,
+ MHI_EOT);
+ if (ret) {
+ dev_err(&mhi_dev->dev, "Failed to queue buffer: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
const struct mhi_device_id *id)
{
@@ -87,20 +122,30 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
qdev->ep.xmit = qcom_mhi_qrtr_send;
dev_set_drvdata(&mhi_dev->dev, qdev);
- rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
- if (rc)
- return rc;
/* start channels */
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc) {
- qrtr_endpoint_unregister(&qdev->ep);
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc)
return rc;
- }
+
+ rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
+ if (rc)
+ goto err_unprepare;
+
+ rc = qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
+ if (rc)
+ goto err_unregister;
dev_dbg(qdev->dev, "Qualcomm MHI QRTR driver probed\n");
return 0;
+
+err_unregister:
+ qrtr_endpoint_unregister(&qdev->ep);
+err_unprepare:
+ mhi_unprepare_from_transfer(mhi_dev);
+
+ return rc;
}
static void qcom_mhi_qrtr_remove(struct mhi_device *mhi_dev)
@@ -151,11 +196,13 @@ static int __maybe_unused qcom_mhi_qrtr_pm_resume_early(struct device *dev)
if (state == MHI_STATE_M3)
return 0;
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc)
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc) {
dev_err(dev, "failed to prepare for autoqueue transfer %d\n", rc);
+ return rc;
+ }
- return rc;
+ return qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
}
static const struct dev_pm_ops qcom_mhi_qrtr_pm_ops = {
--
2.51.0
^ permalink raw reply related
* FAILED: Patch "net: intel: fix PCI device ID conflict between i40e and ipw2200" failed to apply to 6.12-stable tree
From: Sasha Levin @ 2026-03-01 1:28 UTC (permalink / raw)
To: stable, enelsonmoore
Cc: Johannes Berg, Aleksandr Loktionov, Jakub Kicinski,
intel-wired-lan, netdev, linux-wireless
The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From d03e094473ecdeb68d853752ba467abe13e1de44 Mon Sep 17 00:00:00 2001
From: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Date: Mon, 9 Feb 2026 18:12:34 -0800
Subject: [PATCH] net: intel: fix PCI device ID conflict between i40e and
ipw2200
The ID 8086:104f is matched by both i40e and ipw2200. The same device
ID should not be in more than one driver, because in that case, which
driver is used is unpredictable. Fix this by taking advantage of the
fact that i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
devices use PCI_CLASS_NETWORK_OTHER to differentiate the devices.
Fixes: 2e45d3f4677a ("i40e: Add support for X710 B/P & SFP+ cards")
Cc: stable@vger.kernel.org
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Link: https://patch.msgid.link/20260210021235.16315-1-enelsonmoore@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++++++-
drivers/net/wireless/intel/ipw2x00/ipw2200.c | 8 +++++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d3bc3207054f9..02de186dcc8f5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -75,7 +75,13 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_BC), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_SFP), 0},
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_B), 0},
+ /*
+ * This ID conflicts with ipw2200, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_10G_B),
+ PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0},
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 09035a77e775f..b0e769da94156 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -11387,7 +11387,13 @@ static const struct pci_device_id card_ids[] = {
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
- {PCI_VDEVICE(INTEL, 0x104f), 0},
+ /*
+ * This ID conflicts with i40e, but the devices can be differentiated
+ * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200
+ * devices use PCI_CLASS_NETWORK_OTHER.
+ */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x104f),
+ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0},
{PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */
{PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */
--
2.51.0
^ permalink raw reply related
* FAILED: Patch "net: qrtr: Drop the MHI auto_queue feature for IPCR DL channels" failed to apply to 6.12-stable tree
From: Sasha Levin @ 2026-03-01 1:18 UTC (permalink / raw)
To: stable, manivannan.sadhasivam
Cc: Johan Hovold, Chris Lew, Jeff Hugo, Loic Poulain, Jeff Johnson,
Paolo Abeni, linux-arm-msm, dri-devel, mhi, linux-wireless,
ath11k, ath12k, netdev
The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 51731792a25cb312ca94cdccfa139eb46de1b2ef Mon Sep 17 00:00:00 2001
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Date: Thu, 18 Dec 2025 22:21:44 +0530
Subject: [PATCH] net: qrtr: Drop the MHI auto_queue feature for IPCR DL
channels
MHI stack offers the 'auto_queue' feature, which allows the MHI stack to
auto queue the buffers for the RX path (DL channel). Though this feature
simplifies the client driver design, it introduces race between the client
drivers and the MHI stack. For instance, with auto_queue, the 'dl_callback'
for the DL channel may get called before the client driver is fully probed.
This means, by the time the dl_callback gets called, the client driver's
structures might not be initialized, leading to NULL ptr dereference.
Currently, the drivers have to workaround this issue by initializing the
internal structures before calling mhi_prepare_for_transfer_autoqueue().
But even so, there is a chance that the client driver's internal code path
may call the MHI queue APIs before mhi_prepare_for_transfer_autoqueue() is
called, leading to similar NULL ptr dereference. This issue has been
reported on the Qcom X1E80100 CRD machines affecting boot.
So to properly fix all these races, drop the MHI 'auto_queue' feature
altogether and let the client driver (QRTR) manage the RX buffers manually.
In the QRTR driver, queue the RX buffers based on the ring length during
probe and recycle the buffers in 'dl_callback' once they are consumed. This
also warrants removing the setting of 'auto_queue' flag from controller
drivers.
Currently, this 'auto_queue' feature is only enabled for IPCR DL channel.
So only the QRTR client driver requires the modification.
Fixes: 227fee5fc99e ("bus: mhi: core: Add an API for auto queueing buffers for DL channel")
Fixes: 68a838b84eff ("net: qrtr: start MHI channel after endpoit creation")
Reported-by: Johan Hovold <johan@kernel.org>
Closes: https://lore.kernel.org/linux-arm-msm/ZyTtVdkCCES0lkl4@hovoldconsulting.com
Suggested-by: Chris Lew <quic_clew@quicinc.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Acked-by: Jeff Johnson <jjohnson@kernel.org> # drivers/net/wireless/ath/...
Acked-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20251218-qrtr-fix-v2-1-c7499bfcfbe0@oss.qualcomm.com
---
drivers/accel/qaic/mhi_controller.c | 44 -----------------
drivers/bus/mhi/host/pci_generic.c | 20 +-------
drivers/net/wireless/ath/ath11k/mhi.c | 4 --
drivers/net/wireless/ath/ath12k/mhi.c | 4 --
net/qrtr/mhi.c | 69 ++++++++++++++++++++++-----
5 files changed, 60 insertions(+), 81 deletions(-)
diff --git a/drivers/accel/qaic/mhi_controller.c b/drivers/accel/qaic/mhi_controller.c
index 13a14c6c61689..4d787f77ce419 100644
--- a/drivers/accel/qaic/mhi_controller.c
+++ b/drivers/accel/qaic/mhi_controller.c
@@ -39,7 +39,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -55,7 +54,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -71,7 +69,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -87,7 +84,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -103,7 +99,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -119,7 +114,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -135,7 +129,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -151,7 +144,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -167,7 +159,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -183,7 +174,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -199,7 +189,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -215,7 +204,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -231,7 +219,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -247,7 +234,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -263,7 +249,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -279,7 +264,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -295,7 +279,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -311,7 +294,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -327,7 +309,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -343,7 +324,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -359,7 +339,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -375,7 +354,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -391,7 +369,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -407,7 +384,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -423,7 +399,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -439,7 +414,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
@@ -458,7 +432,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -474,7 +447,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -490,7 +462,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -506,7 +477,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -522,7 +492,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -538,7 +507,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -554,7 +522,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -570,7 +537,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -586,7 +552,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -602,7 +567,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -618,7 +582,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -634,7 +597,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -650,7 +612,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -666,7 +627,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -682,7 +642,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -698,7 +657,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -714,7 +672,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -730,7 +687,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index e3bc737313a2f..0884a384b77fc 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -94,22 +94,6 @@ struct mhi_pci_dev_info {
.doorbell_mode_switch = false, \
}
-#define MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(ch_num, ch_name, el_count, ev_ring) \
- { \
- .num = ch_num, \
- .name = ch_name, \
- .num_elements = el_count, \
- .event_ring = ev_ring, \
- .dir = DMA_FROM_DEVICE, \
- .ee_mask = BIT(MHI_EE_AMSS), \
- .pollcfg = 0, \
- .doorbell = MHI_DB_BRST_DISABLE, \
- .lpm_notify = false, \
- .offload_channel = false, \
- .doorbell_mode_switch = false, \
- .auto_queue = true, \
- }
-
#define MHI_EVENT_CONFIG_CTRL(ev_ring, el_count) \
{ \
.num_elements = el_count, \
@@ -329,7 +313,7 @@ static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 8, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 64, 2),
@@ -762,7 +746,7 @@ static const struct mhi_channel_config mhi_telit_fn980_hw_v1_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 16, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 16, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 16, 0),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
};
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index acd76e9392d31..d2c44f7f9b622 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -34,7 +34,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -48,7 +47,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -99,7 +97,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -113,7 +110,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index 08f44baf182a5..2dbdb95ae7bea 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -31,7 +31,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -45,7 +44,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -96,7 +94,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -110,7 +107,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c
index 69f53625a049d..80e341d2f8a45 100644
--- a/net/qrtr/mhi.c
+++ b/net/qrtr/mhi.c
@@ -24,13 +24,25 @@ static void qcom_mhi_qrtr_dl_callback(struct mhi_device *mhi_dev,
struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
int rc;
- if (!qdev || mhi_res->transaction_status)
+ if (!qdev || (mhi_res->transaction_status && mhi_res->transaction_status != -ENOTCONN))
return;
+ /* Channel got reset. So just free the buffer */
+ if (mhi_res->transaction_status == -ENOTCONN) {
+ devm_kfree(&mhi_dev->dev, mhi_res->buf_addr);
+ return;
+ }
+
rc = qrtr_endpoint_post(&qdev->ep, mhi_res->buf_addr,
mhi_res->bytes_xferd);
if (rc == -EINVAL)
dev_err(qdev->dev, "invalid ipcrouter packet\n");
+
+ /* Done with the buffer, now recycle it for future use */
+ rc = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, mhi_res->buf_addr,
+ mhi_dev->mhi_cntrl->buffer_len, MHI_EOT);
+ if (rc)
+ dev_err(&mhi_dev->dev, "Failed to recycle the buffer: %d\n", rc);
}
/* From QRTR to MHI */
@@ -72,6 +84,29 @@ static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
return rc;
}
+static int qcom_mhi_qrtr_queue_dl_buffers(struct mhi_device *mhi_dev)
+{
+ u32 free_desc;
+ void *buf;
+ int ret;
+
+ free_desc = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE);
+ while (free_desc--) {
+ buf = devm_kmalloc(&mhi_dev->dev, mhi_dev->mhi_cntrl->buffer_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, buf, mhi_dev->mhi_cntrl->buffer_len,
+ MHI_EOT);
+ if (ret) {
+ dev_err(&mhi_dev->dev, "Failed to queue buffer: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
const struct mhi_device_id *id)
{
@@ -87,20 +122,30 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
qdev->ep.xmit = qcom_mhi_qrtr_send;
dev_set_drvdata(&mhi_dev->dev, qdev);
- rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
- if (rc)
- return rc;
/* start channels */
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc) {
- qrtr_endpoint_unregister(&qdev->ep);
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc)
return rc;
- }
+
+ rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
+ if (rc)
+ goto err_unprepare;
+
+ rc = qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
+ if (rc)
+ goto err_unregister;
dev_dbg(qdev->dev, "Qualcomm MHI QRTR driver probed\n");
return 0;
+
+err_unregister:
+ qrtr_endpoint_unregister(&qdev->ep);
+err_unprepare:
+ mhi_unprepare_from_transfer(mhi_dev);
+
+ return rc;
}
static void qcom_mhi_qrtr_remove(struct mhi_device *mhi_dev)
@@ -151,11 +196,13 @@ static int __maybe_unused qcom_mhi_qrtr_pm_resume_early(struct device *dev)
if (state == MHI_STATE_M3)
return 0;
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc)
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc) {
dev_err(dev, "failed to prepare for autoqueue transfer %d\n", rc);
+ return rc;
+ }
- return rc;
+ return qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
}
static const struct dev_pm_ops qcom_mhi_qrtr_pm_ops = {
--
2.51.0
^ permalink raw reply related
* FAILED: Patch "net: qrtr: Drop the MHI auto_queue feature for IPCR DL channels" failed to apply to 6.18-stable tree
From: Sasha Levin @ 2026-03-01 1:15 UTC (permalink / raw)
To: stable, manivannan.sadhasivam
Cc: Johan Hovold, Chris Lew, Jeff Hugo, Loic Poulain, Jeff Johnson,
Paolo Abeni, linux-arm-msm, dri-devel, mhi, linux-wireless,
ath11k, ath12k, netdev
The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 51731792a25cb312ca94cdccfa139eb46de1b2ef Mon Sep 17 00:00:00 2001
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Date: Thu, 18 Dec 2025 22:21:44 +0530
Subject: [PATCH] net: qrtr: Drop the MHI auto_queue feature for IPCR DL
channels
MHI stack offers the 'auto_queue' feature, which allows the MHI stack to
auto queue the buffers for the RX path (DL channel). Though this feature
simplifies the client driver design, it introduces race between the client
drivers and the MHI stack. For instance, with auto_queue, the 'dl_callback'
for the DL channel may get called before the client driver is fully probed.
This means, by the time the dl_callback gets called, the client driver's
structures might not be initialized, leading to NULL ptr dereference.
Currently, the drivers have to workaround this issue by initializing the
internal structures before calling mhi_prepare_for_transfer_autoqueue().
But even so, there is a chance that the client driver's internal code path
may call the MHI queue APIs before mhi_prepare_for_transfer_autoqueue() is
called, leading to similar NULL ptr dereference. This issue has been
reported on the Qcom X1E80100 CRD machines affecting boot.
So to properly fix all these races, drop the MHI 'auto_queue' feature
altogether and let the client driver (QRTR) manage the RX buffers manually.
In the QRTR driver, queue the RX buffers based on the ring length during
probe and recycle the buffers in 'dl_callback' once they are consumed. This
also warrants removing the setting of 'auto_queue' flag from controller
drivers.
Currently, this 'auto_queue' feature is only enabled for IPCR DL channel.
So only the QRTR client driver requires the modification.
Fixes: 227fee5fc99e ("bus: mhi: core: Add an API for auto queueing buffers for DL channel")
Fixes: 68a838b84eff ("net: qrtr: start MHI channel after endpoit creation")
Reported-by: Johan Hovold <johan@kernel.org>
Closes: https://lore.kernel.org/linux-arm-msm/ZyTtVdkCCES0lkl4@hovoldconsulting.com
Suggested-by: Chris Lew <quic_clew@quicinc.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Reviewed-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Acked-by: Jeff Johnson <jjohnson@kernel.org> # drivers/net/wireless/ath/...
Acked-by: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20251218-qrtr-fix-v2-1-c7499bfcfbe0@oss.qualcomm.com
---
drivers/accel/qaic/mhi_controller.c | 44 -----------------
drivers/bus/mhi/host/pci_generic.c | 20 +-------
drivers/net/wireless/ath/ath11k/mhi.c | 4 --
drivers/net/wireless/ath/ath12k/mhi.c | 4 --
net/qrtr/mhi.c | 69 ++++++++++++++++++++++-----
5 files changed, 60 insertions(+), 81 deletions(-)
diff --git a/drivers/accel/qaic/mhi_controller.c b/drivers/accel/qaic/mhi_controller.c
index 13a14c6c61689..4d787f77ce419 100644
--- a/drivers/accel/qaic/mhi_controller.c
+++ b/drivers/accel/qaic/mhi_controller.c
@@ -39,7 +39,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -55,7 +54,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -71,7 +69,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -87,7 +84,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -103,7 +99,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -119,7 +114,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -135,7 +129,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -151,7 +144,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -167,7 +159,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -183,7 +174,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -199,7 +189,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -215,7 +204,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -231,7 +219,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -247,7 +234,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -263,7 +249,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -279,7 +264,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -295,7 +279,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -311,7 +294,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -327,7 +309,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -343,7 +324,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -359,7 +339,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -375,7 +354,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -391,7 +369,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -407,7 +384,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -423,7 +399,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -439,7 +414,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
@@ -458,7 +432,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -474,7 +447,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -490,7 +462,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -506,7 +477,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -522,7 +492,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -538,7 +507,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -554,7 +522,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -570,7 +537,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -586,7 +552,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -602,7 +567,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -618,7 +582,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -634,7 +597,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -650,7 +612,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -666,7 +627,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -682,7 +642,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -698,7 +657,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -714,7 +672,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -730,7 +687,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index e3bc737313a2f..0884a384b77fc 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -94,22 +94,6 @@ struct mhi_pci_dev_info {
.doorbell_mode_switch = false, \
}
-#define MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(ch_num, ch_name, el_count, ev_ring) \
- { \
- .num = ch_num, \
- .name = ch_name, \
- .num_elements = el_count, \
- .event_ring = ev_ring, \
- .dir = DMA_FROM_DEVICE, \
- .ee_mask = BIT(MHI_EE_AMSS), \
- .pollcfg = 0, \
- .doorbell = MHI_DB_BRST_DISABLE, \
- .lpm_notify = false, \
- .offload_channel = false, \
- .doorbell_mode_switch = false, \
- .auto_queue = true, \
- }
-
#define MHI_EVENT_CONFIG_CTRL(ev_ring, el_count) \
{ \
.num_elements = el_count, \
@@ -329,7 +313,7 @@ static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 8, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 64, 2),
@@ -762,7 +746,7 @@ static const struct mhi_channel_config mhi_telit_fn980_hw_v1_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 16, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 16, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 16, 0),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
};
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index acd76e9392d31..d2c44f7f9b622 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -34,7 +34,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -48,7 +47,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -99,7 +97,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -113,7 +110,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index 08f44baf182a5..2dbdb95ae7bea 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -31,7 +31,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -45,7 +44,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -96,7 +94,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -110,7 +107,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c
index 69f53625a049d..80e341d2f8a45 100644
--- a/net/qrtr/mhi.c
+++ b/net/qrtr/mhi.c
@@ -24,13 +24,25 @@ static void qcom_mhi_qrtr_dl_callback(struct mhi_device *mhi_dev,
struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
int rc;
- if (!qdev || mhi_res->transaction_status)
+ if (!qdev || (mhi_res->transaction_status && mhi_res->transaction_status != -ENOTCONN))
return;
+ /* Channel got reset. So just free the buffer */
+ if (mhi_res->transaction_status == -ENOTCONN) {
+ devm_kfree(&mhi_dev->dev, mhi_res->buf_addr);
+ return;
+ }
+
rc = qrtr_endpoint_post(&qdev->ep, mhi_res->buf_addr,
mhi_res->bytes_xferd);
if (rc == -EINVAL)
dev_err(qdev->dev, "invalid ipcrouter packet\n");
+
+ /* Done with the buffer, now recycle it for future use */
+ rc = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, mhi_res->buf_addr,
+ mhi_dev->mhi_cntrl->buffer_len, MHI_EOT);
+ if (rc)
+ dev_err(&mhi_dev->dev, "Failed to recycle the buffer: %d\n", rc);
}
/* From QRTR to MHI */
@@ -72,6 +84,29 @@ static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
return rc;
}
+static int qcom_mhi_qrtr_queue_dl_buffers(struct mhi_device *mhi_dev)
+{
+ u32 free_desc;
+ void *buf;
+ int ret;
+
+ free_desc = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE);
+ while (free_desc--) {
+ buf = devm_kmalloc(&mhi_dev->dev, mhi_dev->mhi_cntrl->buffer_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, buf, mhi_dev->mhi_cntrl->buffer_len,
+ MHI_EOT);
+ if (ret) {
+ dev_err(&mhi_dev->dev, "Failed to queue buffer: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
const struct mhi_device_id *id)
{
@@ -87,20 +122,30 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
qdev->ep.xmit = qcom_mhi_qrtr_send;
dev_set_drvdata(&mhi_dev->dev, qdev);
- rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
- if (rc)
- return rc;
/* start channels */
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc) {
- qrtr_endpoint_unregister(&qdev->ep);
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc)
return rc;
- }
+
+ rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
+ if (rc)
+ goto err_unprepare;
+
+ rc = qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
+ if (rc)
+ goto err_unregister;
dev_dbg(qdev->dev, "Qualcomm MHI QRTR driver probed\n");
return 0;
+
+err_unregister:
+ qrtr_endpoint_unregister(&qdev->ep);
+err_unprepare:
+ mhi_unprepare_from_transfer(mhi_dev);
+
+ return rc;
}
static void qcom_mhi_qrtr_remove(struct mhi_device *mhi_dev)
@@ -151,11 +196,13 @@ static int __maybe_unused qcom_mhi_qrtr_pm_resume_early(struct device *dev)
if (state == MHI_STATE_M3)
return 0;
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc)
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc) {
dev_err(dev, "failed to prepare for autoqueue transfer %d\n", rc);
+ return rc;
+ }
- return rc;
+ return qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
}
static const struct dev_pm_ops qcom_mhi_qrtr_pm_ops = {
--
2.51.0
^ permalink raw reply related
* [PATCH] wifi: ath12k: allow user regulatory hints when firmware reports world domain
From: Luis @ 2026-02-28 20:10 UTC (permalink / raw)
To: linux-wireless; +Cc: jjohnson, ath12k, Luis
Some WCN7850 firmware versions (e.g. WLAN.HMT.1.1.c5-00284.1) report
alpha2 "00" (world domain) during initialization instead of a valid
country code. When ath12k applies this via regulatory_set_wiphy_regd(),
cfg80211 marks all 5 GHz channels as no-IR, which prevents active
scanning and makes 5 GHz networks completely invisible to userspace.
Without CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS, the reg_notifier
unconditionally rejects user hints, leaving no way to recover from
the broken world domain without reverting to an older firmware.
Fix this by allowing user hints when the current regulatory domain is
"00". If the firmware has not provided a valid country code, accepting
a user hint via iw reg set lets the driver send a WMI set-country
command to the firmware. The firmware then responds with a proper
WMI_REG_CHAN_LIST_CC event, restoring 5 GHz channel availability.
Once the firmware acknowledges a valid country code, ath12k_regdom_changes()
returns true for "00" and subsequent user hints are blocked again,
preserving the original security intent of the CONFIG guard.
Tested on WCN7850 hw2.0 (ath12k_pci) with linux-firmware
20240318.git3b128b60-0ubuntu2.25 under Ubuntu 24.04 / kernel 6.17.
Signed-off-by: Luis <lxluxo23@gmail.com>
Assisted-by: Claude:claude-sonnet-4-6
---
drivers/net/wireless/ath/ath12k/reg.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
index 7898f6981..0c52d559d 100644
--- a/drivers/net/wireless/ath/ath12k/reg.c
+++ b/drivers/net/wireless/ath/ath12k/reg.c
@@ -87,9 +87,20 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
}
if (!IS_ENABLED(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) {
- ath12k_dbg(ar->ab, ATH12K_DBG_REG,
- "Country Setting is not allowed\n");
- return;
+ /* Allow user hints when firmware reports world domain ("00").
+ * Some firmware versions default to alpha2 "00" on init, which
+ * causes cfg80211 to mark all 5 GHz channels as no-IR, blocking
+ * active scanning and making 5 GHz networks invisible. When the
+ * firmware has not provided a valid country code, accept a user
+ * hint so the correct regulatory domain can be applied.
+ * Once the firmware responds with a valid country, subsequent
+ * user hints are blocked again as usual.
+ */
+ if (ath12k_regdom_changes(hw, "00")) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_REG,
+ "Country Setting is not allowed\n");
+ return;
+ }
}
if (!ath12k_regdom_changes(hw, request->alpha2)) {
--
2.43.0
^ permalink raw reply related
* Re: [DESIGN RFC v3] AP Architecture for Wi-Fi-8 Multi-AP Coordination (MAPC)
From: Abhishek Rajkapur Suryawanshi @ 2026-02-28 17:34 UTC (permalink / raw)
To: Johannes Berg, Jeff Johnson, ath12k, hostap; +Cc: linux-wireless
In-Reply-To: <9ea4b65c3fa5750ef57e93dd04b70cc4ec5df445.camel@sipsolutions.net>
On 1/27/2026 5:57 AM, Johannes Berg wrote:
> On Thu, 2026-01-22 at 00:42 -0800, Abhishek Rajkapur Suryawanshi wrote:
>>> Taking this specific example, it basically says "FW sends a request to
>>> hostapd, hostapd does the handshake and installs the MAPC station. This
>>> is how we think we should handle the MAPC stations."
>>
>> hostapd controls and manages all MAPC related discovery and MAPC peer
>> creation part. No trigger from firmware for MAPC Discovery Phase.
>
> Seems to me you're splitting hairs. Clearly you have the *negotiation*
> trigger (NL80211_CMD_MAPC_NEGOTIATION_TRIGGER) prominently featured in
> the diagrams etc. Sure, it maybe that doesn't explicitly trigger
> *discovery*, but if hostapd doesn't already know about the station that
> the FW/driver is requesting a negotiation with, it probably also has to
> do discovery...
>
> Anyway. I went to write a long email replying to some of your individual
> points but deleted it again, I feel it's not worth your and my time.
>
>
> Clearly, you have already decided on the architecture, and aren't
> sharing all of it, based on reasons you aren't really sharing either.
> Which is fine, I can't claim that we always share the full reasoning
> behind architecture decisions.
>
> We should all still make it transparent _how_ it's intended to work, but
> that could also be just part of the documentation added to the kernel
> when adding the necessary APIs.
>
>
> Which then means that really in all the hundreds of lines of text you
> just wanted to ask whether or not "Option-A" or "Option-B" for handling
> the MAPC peers should be used, and I'd agree that duplicating APIs isn't
> good, i.e. taking "Option-A". Note we did something similar for NAN
> stations, even if they have different sets of attributes than regular AP
> client stations or mesh peers etc.
>
> johannes
Based on your feedback, we re-evaluated and modified the architecture.
Here hostapd along with MAPC discovery, will initiate MAPC negotiation
with discovered APs based on programmed rules(hostapd.conf / hostapd_cli)
& the criteria specified in IEEE P802.11bn/D1.3, sections 37.14.1.3 and 37.14.2.
Additionally, a hostapd CLI command will be added to trigger MAPC negotiation
for controller-managed APs.
Figure 1: MAPC Negotiation Sequence (ESTABLISHMENT/UPDATE)
---------------------------------------------------------
+----------------------------------------------------------------------+
| UHR AP-1 |
| +---------+ +---------+ +---------+ +---------+ | +---------+
| | | | | | | | | | | |
| | hostapd | | cfg80211| | mac80211| | wlan | | | UHR |
| | | | | | | | driver | | | AP-2 |
| +----+----+ +----+----+ +----+----+ +----+----+ | +----+----+
| | | | | | |
| +----+---------------+ | | | | |
| | init hostapd & HW | | | | | |
| | MAPC support update| | | | | |
| +----+---------------+ | MAPC Discovery | | | |
| | | Request | | | |
| | |(MAPC capability)| | | |
| +-----------------+-----------------+-----------------+--------|------>
| | | MAPC Discovery | | | |
| | | Response | | | |
| | |(MAPC capability)| | | |
| <-----------------+-----------------+-----------------+--------|------+
| | | | | | |
| +----+---------------+ | | | | |
| |alloc sta_info store| | | | | |
| |MAPC capa & params | | | | | |
| +----+---------------+ | | | | |
| | | | | | |
| +--+-----------------+-----------------+-----------------+---+ | |
| | MAPC PEER CREATE | | |
| +--+-----------------------------------+-----------------+---+ | |
| | | | | | |
| +----+---------------+ | | | | |
| | Based on configs | | | | | |
| | and spec criteria | | | | | |
| | Initiate MAPC | | | | | |
| | Negotiation | | | | | |
| +----+---------------+ | | | | |
| | |MAPC Negotiation | | | |
| | | Request | | | |
| | (scheme params & APID1) | | |
| +-----------------+-----------------+-----------------+--------|------>
| | | | | | |
| | |MAPC Negotiation | | | |
| | | Response | | | |
| | (scheme params & APID2) | | |
| <-----------------+-----------------+-----------------+--------|------+
| | | | | | |
| +--+-----------------+-----------------+-----------------+---+ | |
| | MAPC PEER UPDATE | | |
| +--+-----------------+-----------------+-----------------+---+ | |
| | | | | | |
| | | | | | |
| | | | | | |
| v v v v | v
+----------------------------------------------------------------------+
Figure 2: MAPC Negotiation Sequence (TEARDOWN)
-----------------------------------------------------
+----------------------------------------------------------------------+
| UHR AP-1 |
| +---------+ +---------+ +---------+ +---------+ | +---------+
| | | | | | | | | | | |
| | hostapd | | cfg80211| | mac80211| | wlan | | | UHR |
| | | | | | | | driver | | | AP2 |
| +---+-----+ +---+-----+ +---+-----+ +---+-----+ | +----+----+
| | | | | | |
| | | | | | |
| | | | | | |
| +----+---------------+ | | | | |
| | Based on configs | | | | | |
| | and spec criteria | | | | | |
| | Initiate MAPC | | | | | |
| | Negotiation | | | | | |
| +----+---------------+ | | | | |
| | |MAPC Negotiation | | | |
| | | Request | | | |
| | | (TEARDOWN) | | | |
| +-----------------+-----------------+-----------------+---------+------>
| | | | | | |
| | |MAPC Negotiation | | | |
| | | Response | | | |
| | | (ACCEPT) | | | |
| <-----------------+-----------------+-----------------+---------+------+
| | | | | | |
| +----+----------------+| | | | |
| |If agreement count || | | | |
| |is zero for MAPC peer|| | | | |
| |then initiate MAPC || | | | |
| |peer delete || | | | |
| +----+----------------+| | | | |
| | | | | | |
| +--+-----------------+-----------------+-----------------+---+ | |
| | MAPC PEER DELETE | | |
| +--+-----------------+-----------------+-----------------+---+ | |
| | | | | | |
| | | | | | |
| | | | | | |
| v v v v | v
| |
+----------------------------------------------------------------------+
Abhishek
^ permalink raw reply
* 6.18.14+: use-after-free in debugfs, kasan splat
From: Ben Greear @ 2026-02-28 14:18 UTC (permalink / raw)
To: linux-wireless@vger.kernel.org
Hello,
I've been hunting this crash for a while, finally got it to trigger in
a KASAN enabled kernel.
This is with a kernel with local patches, including debugging to try to
catch this problem in earlier attempts.
gdb says [ 767.773845] simple_recursive_removal+0x1e/0x50 points to the
WARN_ON_ONCE line I had added, but probably it is dget(dentry) with dentry being already
freed.
static void __simple_recursive_removal(struct dentry *dentry,
void (*callback)(struct dentry *),
bool locked)
{
struct dentry *this = dget(dentry);
if (WARN_ON_ONCE((unsigned long)(this) < 8000)) {
pr_err("simple-recursive-removal, bad 'this': %px\n",
this);
return;
}
I am guessing this is some tangle related to how vif.debugfs_dir and link
debugfs_dir sometimes are the same pointer and sometimes not. I'm going to
try to make that code more safe somehow... This test system is using MLO (with be200 radios).
If someone has ideas to try or is working on the same problem I'd be happy
to compare notes.
[ 767.745519] wlan8: mgd_auth, prep connection failed: -22
[ 767.745545] wlan8: mgd_auth failed, err: -22
[ 767.747684] wlan8: prep-connection, no-have-sta, valid-links: 0x4 active-links: 0x4
[ 767.754165] wlan8: mgd_auth, prep connection failed: -22
[ 767.754183] wlan8: mgd_auth failed, err: -22
[ 767.756145] wlan8: ieee80211_vif_set_links: new_links=0x0; dormant_links=0x0
[ 767.756159] ==================================================================
[ 767.762099] BUG: KASAN: slab-use-after-free in _raw_spin_lock+0x2c/0x40
[ 767.767435] Read of size 1 at addr ffff888127660e08 by task wpa_supplicant/23758
[ 767.773544]
[ 767.773759] CPU: 2 UID: 0 PID: 23758 Comm: wpa_supplicant Kdump: loaded Tainted: G W 6.18.14+ #23 PREEMPT(full)
[ 767.773766] Tainted: [W]=WARN
[ 767.773767] Hardware name: Default string Default string/SKYBAY, BIOS 5.12 02/21/2023
[ 767.773770] Call Trace:
[ 767.773772] <TASK>
[ 767.773774] dump_stack_lvl+0x73/0xa0
[ 767.773780] print_report+0xce/0x620
[ 767.773786] ? __virt_addr_valid+0x205/0x3f0
[ 767.773791] ? _raw_spin_lock+0x2c/0x40
[ 767.773795] kasan_report+0xc6/0xf0
[ 767.773801] ? _raw_spin_lock+0x2c/0x40
[ 767.773806] ? _raw_spin_lock+0x2c/0x40
[ 767.773809] __kasan_check_byte+0x2e/0x40
[ 767.773814] lock_acquire+0xdc/0x2e0
[ 767.773819] ? simple_pin_fs+0x85/0x150
[ 767.773823] ? lock_release+0xce/0x290
[ 767.773827] ? debugfs_init_fs_context+0x110/0x110
[ 767.773833] _raw_spin_lock+0x2c/0x40
[ 767.773837] ? lockref_get+0x9/0x40
[ 767.773841] lockref_get+0x9/0x40
[ 767.773845] simple_recursive_removal+0x1e/0x50
[ 767.773849] debugfs_remove+0x49/0x80
[ 767.773854] ieee80211_vif_update_links+0x9df/0x1500 [mac80211]
[ 767.773980] ? irq_work_queue+0x69/0xa0
[ 767.773986] ? ieee80211_apvlan_link_clear+0x60/0x60 [mac80211]
[ 767.774099] ? vprintk_emit+0x2e4/0x3e0
[ 767.774103] ? wake_up_klogd_work_func+0x80/0x80
[ 767.774110] ? _printk+0xb2/0xe0
[ 767.774113] ? printk_get_console_flush_type+0x2d0/0x2d0
[ 767.774127] ieee80211_vif_set_links+0xa8/0x130 [mac80211]
[ 767.774241] ? ieee80211_find_best_sta_link+0x430/0x430 [mac80211]
[ 767.774356] ? lock_is_held_type+0xa5/0x110
[ 767.774361] ? ieee80211_send_teardown_neg_ttlm+0x2e0/0x2e0 [mac80211]
[ 767.774473] ieee80211_prep_connection+0xe3/0x1550 [mac80211]
[ 767.774586] ieee80211_mgd_auth+0xeba/0x1960 [mac80211]
[ 767.774698] ? ieee80211_mlme_notify_scan_completed+0x300/0x300 [mac80211]
[ 767.774809] ? mark_held_locks+0x49/0x70
[ 767.774815] ? __cfg80211_get_bss+0x429/0xa50 [cfg80211]
[ 767.774923] ? __cfg80211_get_bss+0x429/0xa50 [cfg80211]
[ 767.775025] ? __cfg80211_get_bss+0x46f/0xa50 [cfg80211]
[ 767.775126] ? lock_is_held_type+0xa5/0x110
[ 767.775132] cfg80211_mlme_auth+0x458/0x7f0 [cfg80211]
[ 767.775238] nl80211_authenticate+0xa90/0x1180 [cfg80211]
[ 767.775342] ? __rtnl_unlock+0x65/0xf0
[ 767.775348] ? nl80211_parse_key+0xe60/0xe60 [cfg80211]
[ 767.775452] ? __kasan_kmalloc+0x83/0x90
[ 767.775461] ? nl80211_pre_doit+0x3f3/0x750 [cfg80211]
[ 767.775564] genl_family_rcv_msg_doit+0x1cb/0x2a0
[ 767.775570] ? genl_family_rcv_msg_attrs_parse.constprop.0+0x230/0x230
[ 767.775579] ? security_capable+0x2d/0x80
[ 767.775586] genl_rcv_msg+0x3f7/0x6b0
[ 767.775590] ? genl_family_rcv_msg_dumpit+0x2a0/0x2a0
[ 767.775595] ? nl80211_get_reg_dump+0x450/0x450 [cfg80211]
[ 767.775697] ? nl80211_parse_key+0xe60/0xe60 [cfg80211]
[ 767.775798] ? nlmsg_trim+0x60/0x60 [cfg80211]
[ 767.775902] ? __lock_acquire+0x432/0x23b0
[ 767.775908] netlink_rcv_skb+0x125/0x380
[ 767.775911] ? genl_family_rcv_msg_dumpit+0x2a0/0x2a0
[ 767.775915] ? netlink_ack+0xda0/0xda0
[ 767.775922] ? netlink_deliver_tap+0x14f/0xb60
[ 767.775927] genl_rcv+0x24/0x40
[ 767.775930] netlink_unicast+0x5dd/0x9d0
[ 767.775935] ? netlink_attachskb+0x9b0/0x9b0
[ 767.775939] ? __virt_addr_valid+0x205/0x3f0
[ 767.775943] ? __check_object_size+0x489/0x640
[ 767.775948] netlink_sendmsg+0x749/0xc00
[ 767.775953] ? netlink_unicast+0x9d0/0x9d0
[ 767.775955] ? find_held_lock+0x2b/0x80
[ 767.775960] ? lock_release+0xce/0x290
[ 767.775965] ? netlink_unicast+0x9d0/0x9d0
[ 767.775968] __sock_sendmsg+0xc1/0x150
[ 767.775974] ____sys_sendmsg+0x5f4/0x8f0
[ 767.775979] ? kernel_sendmsg+0x30/0x30
[ 767.775983] ? __copy_msghdr+0x400/0x400
[ 767.775990] ___sys_sendmsg+0xed/0x170
[ 767.775995] ? copy_msghdr_from_user+0x110/0x110
[ 767.775998] ? __might_fault+0x113/0x170
[ 767.776004] ? _copy_from_user+0x4f/0x90
[ 767.776008] ? ___sys_sendmsg+0x170/0x170
[ 767.776011] ? netlink_setsockopt+0x32d/0x650
[ 767.776015] ? lock_release+0xce/0x290
[ 767.776019] ? kfree+0x2ae/0x580
[ 767.776025] ? do_sock_setsockopt+0x1c2/0x3b0
[ 767.776029] ? do_sock_setsockopt+0x1c2/0x3b0
[ 767.776033] ? move_addr_to_user+0x150/0x150
[ 767.776039] __sys_sendmsg+0x107/0x1a0
[ 767.776042] ? __sys_sendmsg_sock+0x20/0x20
[ 767.776052] do_syscall_64+0x69/0x1210
[ 767.776057] entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 767.776061] RIP: 0033:0x7f3fcd3f4e24
[ 767.776064] Code: 15 f1 ff 0b 00 f7 d8 64 89 02 b8 ff ff ff ff eb bf 0f 1f 44 00 00 f3 0f 1e fa 80 3d 45 85 0c 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0
ff ff 77 4c c3 0f 1f 00 55 48 89 e5 48 83 ec 20 89 55
[ 767.776068] RSP: 002b:00007ffeea2fac78 EFLAGS: 00000202 ORIG_RAX: 000000000000002e
[ 767.776073] RAX: ffffffffffffffda RBX: 000000001a1e8400 RCX: 00007f3fcd3f4e24
[ 767.776076] RDX: 0000000000000000 RSI: 00007ffeea2facd0 RDI: 0000000000000007
[ 767.776078] RBP: 000000001a25e740 R08: 0000000000000004 R09: 000000000000000d
[ 767.776080] R10: 00007ffeea2fad9c R11: 0000000000000202 R12: 000000001a1e8310
[ 767.776082] R13: 00007ffeea2facd0 R14: 00007f3fcd5f0000 R15: 00000000007e3d78
[ 767.776090] </TASK>
[ 767.776091]
[ 768.112216] Allocated by task 25666:
[ 768.114508] kasan_save_stack+0x1c/0x40
[ 768.114517] kasan_save_track+0x10/0x30
[ 768.114522] __kasan_slab_alloc+0x62/0x70
[ 768.114527] kmem_cache_alloc_lru_noprof+0x1ce/0x6d0
[ 768.114533] __d_alloc+0x31/0xa30
[ 768.114539] d_alloc_parallel+0xfb/0x1150
[ 768.114543] lookup_open.isra.0+0x53c/0x1620
[ 768.114547] path_openat+0xf1c/0x2c10
[ 768.114551] do_filp_open+0x1d3/0x420
[ 768.114556] do_sys_openat2+0xd3/0x160
[ 768.114560] __x64_sys_openat+0x134/0x1d0
[ 768.114565] do_syscall_64+0x69/0x1210
[ 768.114570] entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 768.114575]
[ 768.114781] Freed by task 25666:
[ 768.116725] kasan_save_stack+0x1c/0x40
[ 768.116730] kasan_save_track+0x10/0x30
[ 768.116735] __kasan_save_free_info+0x37/0x50
[ 768.116739] __kasan_slab_free+0x3b/0x60
[ 768.116744] kmem_cache_free+0x164/0x680
[ 768.116748] rcu_core+0x7d0/0x1710
[ 768.116753] handle_softirqs+0x1c6/0x810
[ 768.116758] __irq_exit_rcu+0xcc/0x100
[ 768.116763] irq_exit_rcu+0xa/0x20
[ 768.116769] sysvec_apic_timer_interrupt+0x6e/0x90
[ 768.116774] asm_sysvec_apic_timer_interrupt+0x16/0x20
[ 768.116778]
[ 768.116984] Last potentially related work creation:
[ 768.120575] kasan_save_stack+0x1c/0x40
[ 768.120580] kasan_record_aux_stack+0x88/0x90
[ 768.120584] __call_rcu_common.constprop.0+0x76/0x790
[ 768.120589] __dentry_kill+0x3a7/0x4f0
[ 768.120593] dput.part.0+0x31e/0x670
[ 768.120597] lookup_open.isra.0+0x4a4/0x1620
[ 768.120601] path_openat+0xf1c/0x2c10
[ 768.120605] do_filp_open+0x1d3/0x420
[ 768.120609] do_sys_openat2+0xd3/0x160
[ 768.120613] __x64_sys_openat+0x134/0x1d0
[ 768.120618] do_syscall_64+0x69/0x1210
[ 768.120623] entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 768.120627]
[ 768.120833] The buggy address belongs to the object at ffff888127660d38
which belongs to the cache dentry of size 312
[ 768.130322] The buggy address is located 208 bytes inside of
freed 312-byte region [ffff888127660d38, ffff888127660e70)
[ 768.139985]
[ 768.140194] The buggy address belongs to the physical page:
[ 768.144479] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x127660
[ 768.144485] head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 768.144489] flags: 0x5fff8000000040(head|node=0|zone=2|lastcpupid=0x3fff)
[ 768.144495] page_type: f5(slab)
[ 768.144500] raw: 005fff8000000040 ffff8881202b9cc0 ffffea0005737400 dead000000000002
[ 768.144504] raw: 0000000000000000 0000000000150015 00000000f5000000 0000000000000000
[ 768.144509] head: 005fff8000000040 ffff8881202b9cc0 ffffea0005737400 dead000000000002
[ 768.144513] head: 0000000000000000 0000000000150015 00000000f5000000 0000000000000000
[ 768.144517] head: 005fff8000000001 ffffea00049d9801 00000000ffffffff 00000000ffffffff
[ 768.144521] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000000
[ 768.144524] page dumped because: kasan: bad access detected
[ 768.144527]
[ 768.144733] Memory state around the buggy address:
[ 768.148240] ffff888127660d00: fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb fb
[ 768.154179] ffff888127660d80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 768.160116] >ffff888127660e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fc fc
[ 768.166051] ^
[ 768.168257] ffff888127660e80: fc fc fc fc fc fc 00 00 00 00 00 00 00 00 00 00
[ 768.174190] ffff888127660f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 768.180125] ==================================================================
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: Maybe problem with ieee80211_tear_down_links return value.
From: Ben Greear @ 2026-02-28 12:58 UTC (permalink / raw)
To: Rameshkumar Sundaram, linux-wireless
In-Reply-To: <0e276fba-7a1a-4d2f-a3da-1f3ad53a8a56@oss.qualcomm.com>
On 2/27/26 22:45, Rameshkumar Sundaram wrote:
>
>
> On 2/28/2026 6:28 AM, Ben Greear wrote:
>> While checking on some other problems, I ended up adding logging to the code path
>> below from net/mac80211/link.c. This path is hit very often on my system, and if I understand
>> the code correctly, it should only hit in error cases where MLO links have duplicated
>> MAC addresses.
>>
>> ret = ieee80211_check_dup_link_addrs(sdata);
>> if (!ret) {
>> /* for keys we will not be able to undo this */
>> ieee80211_tear_down_links(sdata, to_free, rem);
>>
>> The ieee80211_check_dup_link_addrs method appears to return 0 when there are no duplicates,
>> and -EALREADY when there are duplicates. So maybe the check above should be reversed to be:
>>
>> if (ret) {
>> ??
>>
>
>
> The ieee80211_check_dup_link_addrs() helper returns 0 when no duplicates are found and -EALREADY on duplicates, as you described.
>
> However, in the caller the pattern:
>
> if (!ret) {
> /* for keys we will not be able to undo this */
> ieee80211_tear_down_links(sdata, to_free, rem);
>
> ieee80211_set_vif_links_bitmaps(sdata, new_links, dormant_links);
>
> /* tell the driver */
> if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
> ret = drv_change_vif_links(sdata->local, sdata,
> old_links & old_active,
> new_links & sdata->vif.active_links,
> old);
> if (!new_links)
> ieee80211_debugfs_recreate_netdev(sdata, false);
>
> if (sdata->vif.type == NL80211_IFTYPE_AP)
> ieee80211_update_apvlan_links(sdata);
> }
>
> treats ret == 0 as the success/commit path (i.e., only proceed with tearing down removed links, updating link bitmaps, and notifying the driver after validating
> the new link configuration)
>
>
> So I don’t think the condition should be reversed. If it were changed to if (ret), we’d end up committing the update only when duplicates are detected
> (-EALREADY), which seems backwards given the current flow (and the later rollback handling when ret is non-zero).
Hello Ramesh,
Thanks for the response. Yes, I was confused...I thought that branch of code was the error case,
but it is actually expected case.
I'm seeing some rare debugfs corruption/crash in that code branch and started thinking it was
error handling.
Thanks,
Ben
--Ben
>
> --
> Ramesh
>
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* CMA allocation fails with default 128M on X1E80100 (Lenovo 21N1CT01WW) for ath12k
From: René Mérou @ 2026-02-28 9:29 UTC (permalink / raw)
To: linux-arm-msm@vger.kernel.org; +Cc: linux-wireless@vger.kernel.org
Hi,
I'm experiencing CMA allocation failures with the ath12k WiFi driver on my new Lenovo 21N1CT01WW (Snapdragon X1E80100).
Error in dmesg
cma: __cma_alloc: reserved: alloc failed, req-size: 257 pages, ret: -16
cma: => 1042 free of 32768 total pages
System details
Kernel: 6.17.0-8-qcom-x1e (Ubuntu)
Default CMA size: 128M (set by the distribution for this hardware)
WiFi chip: ath12k_pci (Qualcomm WCN685x)
What I found
With the default 128M CMA, the allocation of 257 pages (~1MB) fails
After increasing CMA to 256M (by adding cma=256M to the kernel command line), the error disappears and WiFi works correctly
My questions
Is 128M expected to be sufficient for ath12k on this platform?
Could the driver be optimized to need less contiguous memory?
Should the default CMA size be increased to 256M for X1E80100 devices?
Happy to provide more logs or test patches if needed.
Thanks,
Jean-René Mérou
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Fix the assignment of logical link index
From: Rameshkumar Sundaram @ 2026-02-28 6:46 UTC (permalink / raw)
To: Roopni Devanathan, ath12k; +Cc: linux-wireless, Manish Dharanenthiran
In-Reply-To: <20260226041911.2434999-1-roopni.devanathan@oss.qualcomm.com>
On 2/26/2026 9:49 AM, Roopni Devanathan wrote:
> From: Manish Dharanenthiran <manish.dharanenthiran@oss.qualcomm.com>
>
> Per-link logical index is assigned from the global counter,
> ahsta->num_peer. This logical index is sent to firmware during peer
> association. If there is a failure in creating a link station,
> ath12k_mac_free_unassign_link_sta() clears the link, but does not decrement
> the logical link index. This will result in a higher logical link index for
> the next link station created. Also, if there is a leak in logical link
> index as we assign the incremented num_peer, then the index can exceed the
> maximum valid value of 15.
>
> As an example, let's say we have a 2 GHz + 5 GHz + 6 GHz MLO setup. So the
> logical link indices that they have are 0, 1 and 2, respectively. If the
> 5 GHz link is removed, logical link index 1 becomes available, and num_peer
> is not reduced to 2 and still remains at 3. If a new 5 GHz link is added
> later, it gets the index 3, instead of reusing link index 1. Also,
> num_peer is increased to 4, though only 3 links are present.
>
> To resolve these, create a bitmap, free_logical_link_idx, that tracks the
> available logical link indices. When a link station is created, select the
> first free logical index and when a link station is removed, mark its
> logical link index as available by setting the bit.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01181-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Manish Dharanenthiran <manish.dharanenthiran@oss.qualcomm.com>
> Signed-off-by: Roopni Devanathan <roopni.devanathan@oss.qualcomm.com>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
^ permalink raw reply
* Re: Maybe problem with ieee80211_tear_down_links return value.
From: Rameshkumar Sundaram @ 2026-02-28 6:45 UTC (permalink / raw)
To: Ben Greear, linux-wireless
In-Reply-To: <40a9eca2-17fb-b839-e31f-eb4aecb2ca41@candelatech.com>
On 2/28/2026 6:28 AM, Ben Greear wrote:
> While checking on some other problems, I ended up adding logging to the
> code path
> below from net/mac80211/link.c. This path is hit very often on my
> system, and if I understand
> the code correctly, it should only hit in error cases where MLO links
> have duplicated
> MAC addresses.
>
> ret = ieee80211_check_dup_link_addrs(sdata);
> if (!ret) {
> /* for keys we will not be able to undo this */
> ieee80211_tear_down_links(sdata, to_free, rem);
>
> The ieee80211_check_dup_link_addrs method appears to return 0 when there
> are no duplicates,
> and -EALREADY when there are duplicates. So maybe the check above
> should be reversed to be:
>
> if (ret) {
> ??
>
The ieee80211_check_dup_link_addrs() helper returns 0 when no duplicates
are found and -EALREADY on duplicates, as you described.
However, in the caller the pattern:
if (!ret) {
/* for keys we will not be able to undo this */
ieee80211_tear_down_links(sdata, to_free, rem);
ieee80211_set_vif_links_bitmaps(sdata, new_links,
dormant_links);
/* tell the driver */
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
ret = drv_change_vif_links(sdata->local, sdata,
old_links & old_active,
new_links &
sdata->vif.active_links,
old);
if (!new_links)
ieee80211_debugfs_recreate_netdev(sdata, false);
if (sdata->vif.type == NL80211_IFTYPE_AP)
ieee80211_update_apvlan_links(sdata);
}
treats ret == 0 as the success/commit path (i.e., only proceed with
tearing down removed links, updating link bitmaps, and notifying the
driver after validating the new link configuration)
So I don’t think the condition should be reversed. If it were changed to
if (ret), we’d end up committing the update only when duplicates are
detected (-EALREADY), which seems backwards given the current flow (and
the later rollback handling when ret is non-zero).
--
Ramesh
^ permalink raw reply
* [PATCH v2] wifi: mac80211: update outdated comment
From: Kexin Sun @ 2026-02-28 6:19 UTC (permalink / raw)
To: johannes
Cc: linux-wireless, linux-kernel, lachlan.hodges, julia.lawall,
xutong.ma, yunbolyu, ratnadiraw, Kexin Sun
In-Reply-To: <20260224021548.1394-1-kexinsun@smail.nju.edu.cn>
The function ieee80211_start_scan() was refactored and replaced by
__ieee80211_start_scan() in commit f3b85252f081 ("mac80211: fix scan
races and rework scanning"). Update the comment in
ieee80211_tx_h_check_assoc() accordingly.
Additionally, remove the broken gmane.org link in the comment.
Suggested-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
Suggested-by: Johannes Berg <johannes@sipsolutions.net>
Assisted-by: unnamed:deepseek-v3.2 coccinelle
Signed-off-by: Kexin Sun <kexinsun@smail.nju.edu.cn>
---
v2:
- Removed the dead gmane.org link from the comment as suggested by
Lachlan Hodges <lachlan.hodges@morsemicro.com>
and Johannes Berg <johannes@sipsolutions.net>.
net/mac80211/tx.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8cdbd417d7be..6dbe17f7aa74 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -287,10 +287,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
* active scan) are allowed, all other frames should not be
* sent and we should not get here, but if we do
* nonetheless, drop them to avoid sending them
- * off-channel. See the link below and
- * ieee80211_start_scan() for more.
- *
- * http://article.gmane.org/gmane.linux.kernel.wireless.general/30089
+ * off-channel. See __ieee80211_start_scan() for more.
*/
return TX_DROP;
--
2.25.1
^ permalink raw reply related
* Maybe problem with ieee80211_tear_down_links return value.
From: Ben Greear @ 2026-02-28 0:58 UTC (permalink / raw)
To: linux-wireless
While checking on some other problems, I ended up adding logging to the code path
below from net/mac80211/link.c. This path is hit very often on my system, and if I understand
the code correctly, it should only hit in error cases where MLO links have duplicated
MAC addresses.
ret = ieee80211_check_dup_link_addrs(sdata);
if (!ret) {
/* for keys we will not be able to undo this */
ieee80211_tear_down_links(sdata, to_free, rem);
The ieee80211_check_dup_link_addrs method appears to return 0 when there are no duplicates,
and -EALREADY when there are duplicates. So maybe the check above should be reversed to be:
if (ret) {
??
static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata)
{
unsigned int i, j;
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
struct ieee80211_link_data *link1;
link1 = sdata_dereference(sdata->link[i], sdata);
if (!link1)
continue;
for (j = i + 1; j < IEEE80211_MLD_MAX_NUM_LINKS; j++) {
struct ieee80211_link_data *link2;
link2 = sdata_dereference(sdata->link[j], sdata);
if (!link2)
continue;
if (ether_addr_equal(link1->conf->addr,
link2->conf->addr))
return -EALREADY;
}
}
return 0;
}
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH ath-next v2] wifi: ath12k: Pass the correct value of each TID during a stop AMPDU session
From: Vasanthakumar Thiagarajan @ 2026-02-27 17:57 UTC (permalink / raw)
To: Reshma Immaculate Rajkumar, ath12k; +Cc: linux-wireless
In-Reply-To: <20260227110123.3726354-1-reshma.rajkumar@oss.qualcomm.com>
On 2/27/2026 4:31 PM, Reshma Immaculate Rajkumar wrote:
> With traffic ongoing for data TID [TID 0], an DELBA request to
> stop AMPDU for the BA session was received on management TID [TID 4].
> The corresponding TID number was incorrectly passed to stop the BA session,
> resulting in the BA session for data TIDs being stopped and the BA size
> being reduced to 1, causing an overall dip in TCP throughput.
>
> Fix this issue by passing the correct argument from
> ath12k_dp_rx_ampdu_stop() to ath12k_dp_arch_peer_rx_tid_reo_update()
> during an AMPDU stop session. Instead of passing peer->dp_peer->rx_tid,
> which is the base address of the array, corresponding to TID 0, pass
> the value of &peer->dp_peer->rx_tid[params->tid]. With this, the
> different TID numbers are accounted for.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1
>
> Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
> Signed-off-by: Reshma Immaculate Rajkumar <reshma.rajkumar@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: account TX stats only when ACK/BA status is present
From: Vasanthakumar Thiagarajan @ 2026-02-27 17:53 UTC (permalink / raw)
To: Sarika Sharma, ath12k; +Cc: linux-wireless
In-Reply-To: <20260226051947.1379716-1-sarika.sharma@oss.qualcomm.com>
On 2/26/2026 10:49 AM, Sarika Sharma wrote:
> The fields tx_retry_failed, tx_retry_count, and tx_duration are
> currently updated outside the HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS
> flag check. In certain scenarios, firmware delivers multiple PPDU
> statistics for the same PPDU, first without BA/ACK information, and
> later with BA/ACK status once it becomes available. As the same PPDU
> is processed again, these counters are updated a second time,
> resulting in duplicate TX statistics.
>
> To address this, move the accounting of tx_retry_failed and
> tx_retry_count under the ACK/BA status flag check, and similarly gate
> tx_duration on the same path. This ensures that each PPDU contributes
> to these counters exactly once, avoids double counting, and provides
> consistent reporting in userspace tools such as station dump.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1
>
> Fixes: a0b963e1da5b ("wifi: ath12k: fetch tx_retry and tx_failed from htt_ppdu_stats_user_cmpltn_common_tlv")
> Signed-off-by: Sarika Sharma <sarika.sharma@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next v2] wifi: ath11k: Pass the correct value of each TID during a stop AMPDU session
From: Jeff Johnson @ 2026-02-27 17:39 UTC (permalink / raw)
To: Reshma Immaculate Rajkumar, ath11k; +Cc: linux-wireless
In-Reply-To: <20260227095609.3691546-1-reshma.rajkumar@oss.qualcomm.com>
On 2/27/2026 1:56 AM, Reshma Immaculate Rajkumar wrote:
> v2:
> * Added QTI yearless copyright
> drivers/net/wireless/ath/ath11k/dp_rx.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
> index b9e976ddcbbf..00d27e0053b2 100644
> --- a/drivers/net/wireless/ath/ath11k/dp_rx.c
> +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
> @@ -2,6 +2,7 @@
> /*
> * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
> * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
Per current guidance, which I shared privately, you should have removed the
Qualcomm Innovation Center copyright since it is now covered by the QTI one.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> */
^ permalink raw reply
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