* [PATCH wireless-next 01/14] wifi: mac80211_hwsim: limit TX of frames to the NAN DW
From: Miri Korenblit @ 2026-05-05 16:42 UTC (permalink / raw)
To: linux-wireless; +Cc: Benjamin Berg
In-Reply-To: <20260505164219.2806117-1-miriam.rachel.korenblit@intel.com>
From: Benjamin Berg <benjamin.berg@intel.com>
Frames submitted on the NAN device interface should only be transmitted
during one of the discovery windows (DWs). It is assumed that software
submits frames from the DW end notifications for the next DW period.
Simulate this behaviour by checking that we are currently in a DW before
transmitting from ieee80211_hwsim_wake_tx_queue. As frames will be
queued up at the start of a DW, wake the management TX queue every time
a DW is started. Do so with a randomized offset just to avoid every
client transmitting at the same time.
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
.../net/wireless/virtual/mac80211_hwsim_i.h | 3 +
.../wireless/virtual/mac80211_hwsim_main.c | 11 ++-
.../net/wireless/virtual/mac80211_hwsim_nan.c | 79 +++++++++++++++++++
.../net/wireless/virtual/mac80211_hwsim_nan.h | 6 ++
4 files changed, 97 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_i.h b/drivers/net/wireless/virtual/mac80211_hwsim_i.h
index 6b2a5dccb106..5432de92beab 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_i.h
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_i.h
@@ -136,4 +136,7 @@ u64 mac80211_hwsim_boottime_to_tsf(struct mac80211_hwsim_data *data,
u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
+void ieee80211_hwsim_wake_tx_queue(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq);
+
#endif /* __MAC80211_HWSIM_I_H */
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_main.c b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
index 3a0c4366dfdb..6740504b30e6 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_main.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
@@ -2235,14 +2235,18 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
ieee80211_tx_status_irqsafe(hw, skb);
}
-static void ieee80211_hwsim_wake_tx_queue(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq)
+void ieee80211_hwsim_wake_tx_queue(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq)
{
struct ieee80211_tx_control control = {
.sta = txq->sta,
};
struct sk_buff *skb;
+ if (txq->vif->type == NL80211_IFTYPE_NAN &&
+ !mac80211_hwsim_nan_txq_transmitting(hw, txq))
+ return;
+
while ((skb = ieee80211_tx_dequeue(hw, txq)))
mac80211_hwsim_tx(hw, &control, skb);
}
@@ -5603,6 +5607,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
hrtimer_setup(&data->nan.slot_timer,
mac80211_hwsim_nan_slot_timer,
CLOCK_BOOTTIME, HRTIMER_MODE_ABS_SOFT);
+ hrtimer_setup(&data->nan.resume_txqs_timer,
+ mac80211_hwsim_nan_resume_txqs_timer,
+ CLOCK_BOOTTIME, HRTIMER_MODE_ABS_SOFT);
}
data->if_combination.radar_detect_widths =
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_nan.c b/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
index aa4aef0920f4..22805c3723e6 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
@@ -26,8 +26,13 @@
static_assert(16 * DWST_TU * 1024 == 8192 * 1024);
static_assert(DW0_TSF_MASK + 1 == 8192 * 1024);
+/* Quiet time at the end of each slot where TX is suppressed */
+#define NAN_CHAN_SWITCH_TIME_US 256
+
static u8 hwsim_nan_cluster_id[ETH_ALEN];
+static void mac80211_hwsim_nan_resume_txqs(struct mac80211_hwsim_data *data);
+
static u64 hwsim_nan_get_timer_tsf(struct mac80211_hwsim_data *data)
{
ktime_t expires = hrtimer_get_expires(&data->nan.slot_timer);
@@ -130,6 +135,8 @@ mac80211_hwsim_nan_slot_timer(struct hrtimer *timer)
cfg80211_next_nan_dw_notif(wdev, notify_dw_chan, GFP_ATOMIC);
}
+ mac80211_hwsim_nan_resume_txqs(data);
+
mac80211_hwsim_nan_schedule_slot(data, slot + 1);
return HRTIMER_RESTART;
@@ -190,6 +197,7 @@ int mac80211_hwsim_nan_stop(struct ieee80211_hw *hw,
return -EINVAL;
hrtimer_cancel(&data->nan.slot_timer);
+ hrtimer_cancel(&data->nan.resume_txqs_timer);
data->nan.device_vif = NULL;
spin_lock_bh(&hwsim_radio_lock);
@@ -231,3 +239,74 @@ int mac80211_hwsim_nan_change_config(struct ieee80211_hw *hw,
return 0;
}
+
+static void mac80211_hwsim_nan_resume_txqs(struct mac80211_hwsim_data *data)
+{
+ u32 timeout_ns;
+
+ /* Nothing to do if we are not in a DW */
+ if (!mac80211_hwsim_nan_txq_transmitting(data->hw,
+ data->nan.device_vif->txq_mgmt))
+ return;
+
+ /*
+ * Wait a bit and also randomize things so that not everyone is TXing
+ * at the same time. Each slot is 16 TU long, this waits between 100 us
+ * and 5 ms before starting to TX (unless a new frame arrives).
+ */
+ timeout_ns = get_random_u32_inclusive(100 * NSEC_PER_USEC,
+ 5 * NSEC_PER_MSEC);
+
+ hrtimer_start(&data->nan.resume_txqs_timer,
+ ns_to_ktime(timeout_ns),
+ HRTIMER_MODE_REL_SOFT);
+}
+
+enum hrtimer_restart
+mac80211_hwsim_nan_resume_txqs_timer(struct hrtimer *timer)
+{
+ struct mac80211_hwsim_data *data =
+ container_of(timer, struct mac80211_hwsim_data,
+ nan.resume_txqs_timer);
+
+ guard(rcu)();
+
+ /* Wake TX queue for management frames on the NAN device interface */
+ if (mac80211_hwsim_nan_txq_transmitting(data->hw,
+ data->nan.device_vif->txq_mgmt))
+ ieee80211_hwsim_wake_tx_queue(data->hw,
+ data->nan.device_vif->txq_mgmt);
+
+ return HRTIMER_NORESTART;
+}
+
+bool mac80211_hwsim_nan_txq_transmitting(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq)
+{
+ struct mac80211_hwsim_data *data = hw->priv;
+ u64 tsf;
+ u8 slot;
+
+ if (WARN_ON_ONCE(!data->nan.device_vif))
+ return true;
+
+ tsf = mac80211_hwsim_get_tsf(hw, data->nan.device_vif);
+ slot = hwsim_nan_slot_from_tsf(tsf);
+
+ /* Enforce a maximum channel switch time and guard against TX delays */
+ if (slot != hwsim_nan_slot_from_tsf(tsf + NAN_CHAN_SWITCH_TIME_US))
+ return false;
+
+ /* Check NAN device interface management frame transmission */
+ if (!txq->sta) {
+ /* Only transmit these during one of the DWs */
+ if (slot == SLOT_24GHZ_DW ||
+ (slot == SLOT_5GHZ_DW &&
+ (data->nan.bands & BIT(NL80211_BAND_5GHZ))))
+ return true;
+
+ return false;
+ }
+
+ return true;
+}
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_nan.h b/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
index e86e7f9e9a3c..6a0780797273 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
@@ -15,11 +15,14 @@ struct mac80211_hwsim_nan_data {
struct ieee80211_channel *channel;
struct hrtimer slot_timer;
+ struct hrtimer resume_txqs_timer;
bool notify_dw;
};
enum hrtimer_restart
mac80211_hwsim_nan_slot_timer(struct hrtimer *timer);
+enum hrtimer_restart
+mac80211_hwsim_nan_resume_txqs_timer(struct hrtimer *timer);
int mac80211_hwsim_nan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -33,4 +36,7 @@ int mac80211_hwsim_nan_change_config(struct ieee80211_hw *hw,
struct cfg80211_nan_conf *conf,
u32 changes);
+bool mac80211_hwsim_nan_txq_transmitting(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq);
+
#endif /* __MAC80211_HWSIM_NAN_H */
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 00/14] wifi: mac80211_hwsim: some more NAN patches
From: Miri Korenblit @ 2026-05-05 16:42 UTC (permalink / raw)
To: linux-wireless
Hi,
This series completes the hwsim support for NAN.
Thanks,
Miri
---
Benjamin Berg (5):
wifi: mac80211_hwsim: limit TX of frames to the NAN DW
wifi: mac80211_hwsim: select NAN TX channel based on current TSF
wifi: mac80211_hwsim: only RX on NAN when active on a slot
wifi: mac80211_hwsim: protect tsf_offset using a spinlock
wifi: mac80211_hwsim: implement NAN synchronization
Daniel Gabay (7):
wifi: mac80211_hwsim: add NAN_DATA interface limits
wifi: mac80211_hwsim: add NAN PHY capabilities
wifi: mac80211_hwsim: implement NAN schedule callbacks
wifi: mac80211_hwsim: set HAS_RATE_CONTROL when using NAN
wifi: mac80211_hwsim: add NAN data path TX/RX support
wifi: mac80211_hwsim: Declare support for secure NAN
wifi: mac80211_hwsim: enable NAN_DATA interface simulation support
Ilan Peer (2):
wifi: mac80211_hwsim: Do not declare support for NDPE
wifi: mac80211_hwsim: Support Tx of multicast data on NAN
.../net/wireless/virtual/mac80211_hwsim_i.h | 33 +-
.../wireless/virtual/mac80211_hwsim_main.c | 263 +++-
.../net/wireless/virtual/mac80211_hwsim_nan.c | 1191 ++++++++++++++++-
.../net/wireless/virtual/mac80211_hwsim_nan.h | 74 +-
4 files changed, 1454 insertions(+), 107 deletions(-)
--
2.34.1
^ permalink raw reply
* Re: [PATCH] wifi: ath11k: fix use after free in ath11k_dp_rx_msdu_coalesce.
From: Rameshkumar Sundaram @ 2026-05-05 16:38 UTC (permalink / raw)
To: Jeff Johnson, Willmar Knikker, jjohnson; +Cc: linux-wireless, ath11k
In-Reply-To: <7d3c5eae-233a-4c31-b64e-70f0afe74da6@oss.qualcomm.com>
On 5/5/2026 8:38 PM, Jeff Johnson wrote:
> On 5/5/2026 7:30 AM, Willmar Knikker wrote:
>> In ath11k_dp_rx_msdu_coalesce the loop uses ->is_continuation after
>> the dev_kfree_skb_any. This can cause a use after free kfence.
>>
>> Move the use after the dev_kfree_skb_any after use of ->is_continuation
>> inline with the while in the while loop above this one.
>>
>> Signed-off-by: Willmar Knikker <willmar@met-dubbel-l.nl>
>> ---
>> drivers/net/wireless/ath/ath11k/dp_rx.c | 7 ++++---
>> 1 file changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
>> index fe79109adc70..02bd9787d6b4 100644
>> --- a/drivers/net/wireless/ath/ath11k/dp_rx.c
>> +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
>> @@ -1825,11 +1825,12 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
>> skb_pull(skb, hal_rx_desc_sz);
>> skb_copy_from_linear_data(skb, skb_put(first, buf_len),
>> buf_len);
>> - dev_kfree_skb_any(skb);
>> -
>> rem_len -= buf_len;
>> - if (!rxcb->is_continuation)
>> + if (!rxcb->is_continuation) {
>> + dev_kfree_skb_any(skb);
>> break;
>> + }
>> + dev_kfree_skb_any(skb);
>
> rather than repeating code imo it would be "better" to cache the flag before
> freeing and then test the cached flag.
>
> however as you note this proposed logic matches the logic already present in
> the "Free up all buffers of the MSDU" portion of the function, so from that
> perspective the proposal is consistent with that logic.
>
> let's see if anyone else has an opinion...
IMO a cached flag is a little easier to read and harder to regress.
Also please add a Fixes tag. This appears to go back to the initial
ath11k commit.
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
--
Ramesh
^ permalink raw reply
* Re: [PATCH v2 3/3] mmc: sdhci-esdhc-imx: consolidate imx25/35 data and add Kingston CID
From: Frank Li @ 2026-05-05 16:28 UTC (permalink / raw)
To: Adrián García Casado
Cc: Ulf Hansson, Adrian Hunter, Andreas Hindborg, Jens Axboe,
Miri Korenblit, Miguel Ojeda, Haibo Chen, Sascha Hauer,
Boqun Feng, linux-mmc, imx, linux-arm-kernel, linux-block,
rust-for-linux, linux-wireless, linux-kernel,
Adrián García Casado
In-Reply-To: <20260315172746.270734-4-adriangarciacasado42@gmail.com>
On Sun, Mar 15, 2026 at 06:26:40PM +0100, Adrián García Casado wrote:
> Consolidate esdhc_imx25 and esdhc_imx35 soc data into a single shared
> struct since they share the same flags. This reduces redundancy. Also
> add the CID_MANFID_KINGSTON definition to quirks.h for centralized
> management.
>
> Signed-off-by: Adrián García Casado <adriangarciacicuelo@gmail.com>
> ---
> drivers/mmc/core/quirks.h | 4 ++++
> drivers/mmc/host/sdhci-esdhc-imx.c | 12 ++++--------
> 2 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
> index c417ed34c..d736bb4be 100644
> --- a/drivers/mmc/core/quirks.h
> +++ b/drivers/mmc/core/quirks.h
> @@ -15,6 +15,10 @@
>
> #include "card.h"
>
> +#ifndef CID_MANFID_KINGSTON
> +#define CID_MANFID_KINGSTON 0x70
> +#endif
> +
Where use it? It is un-related change with sdhci-esdhc-imx.c. Please split
it.
Frank
> static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = {
> /*
> * Kingston Canvas Go! Plus microSD cards never finish SD cache flush.
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index a7a5df673..9cfa26722 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -256,11 +256,7 @@ struct esdhc_soc_data {
> u32 quirks;
> };
>
> -static const struct esdhc_soc_data esdhc_imx25_data = {
> - .flags = ESDHC_FLAG_ERR004536,
> -};
> -
> -static const struct esdhc_soc_data esdhc_imx35_data = {
> +static const struct esdhc_soc_data esdhc_imx25_35_data = {
> .flags = ESDHC_FLAG_ERR004536,
> };
>
> @@ -391,8 +387,8 @@ struct pltfm_imx_data {
> };
>
> static const struct of_device_id imx_esdhc_dt_ids[] = {
> - { .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, },
> - { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, },
> + { .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_35_data, },
> + { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx25_35_data, },
> { .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, },
> { .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, },
> { .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, },
> @@ -414,7 +410,7 @@ MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
>
> static inline int is_imx25_esdhc(struct pltfm_imx_data *data)
> {
> - return data->socdata == &esdhc_imx25_data;
> + return data->socdata == &esdhc_imx25_35_data;
> }
>
> static inline int is_imx53_esdhc(struct pltfm_imx_data *data)
> --
> 2.47.3
>
^ permalink raw reply
* Re: [PATCH wireless-next] wifi: mac80211: check stations are removed before MLD change
From: Johannes Berg @ 2026-05-05 15:55 UTC (permalink / raw)
To: Ben Greear, linux-wireless
In-Reply-To: <d50bc7a2-352d-43ff-b3c7-b5b13ce7112b@candelatech.com>
On Tue, 2026-05-05 at 07:17 -0700, Ben Greear wrote:
>
> > @@ -307,6 +307,9 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
> > if (old_links == new_links && dormant_links == sdata->vif.dormant_links)
> > return 0;
> >
> > + if (!old_links || !new_links)
> > + WARN_ON(sta_info_flush(sdata, -1) > 0);
>
> Maybe WARN_ON_ONCE to keep log spam to a minimum?
Maybe ... It's never really _supposed_ to happen though, and if it does
then I doubt it would happen twice, at least not in close succession,
since it flushes here. It's a trade-off between the extra state and
potential extra warnings, so not sure the _ONCE is worth it here.
johannes
^ permalink raw reply
* Re: [PATCH v2] wifi: ath12k: fix incorrect HT/VHT/HE/EHT MCS reporting in monitor mode
From: Jeff Johnson @ 2026-05-05 15:38 UTC (permalink / raw)
To: kwan1996, ath12k; +Cc: linux-wireless
In-Reply-To: <20260505040920.57521-1-laicheehou9@gmail.com>
On 5/4/2026 9:09 PM, kwan1996 wrote:
> In monitor mode, the driver incorrectly assigns the legacy rate
> to the rate_idx field of the radiotap header for HT/VHT/HE/EHT
> frames, ignoring the actual MCS value parsed from the hardware.
>
> This causes packet analyzers (like Wireshark) to display incorrect
> MCS values (e.g., legacy base rates instead of the true MCS).
>
> Fix this by assigning ppdu_info->mcs instead of ppdu_info->rate
> for HT/VHT/HE/EHT frame types in ath12k_dp_mon_fill_rx_rate()
> and ath12k_dp_mon_update_radiotap().
>
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=220864
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ
>
> Signed-off-by: kwan1996 <laicheehou9@gmail.com>
Is this your "known identity" as required by:
https://www.kernel.org/doc/html/latest/process/submitting-patches.html#developer-s-certificate-of-origin-1-1
/jeff
^ permalink raw reply
* Re: [PATCH] wifi: ath11k: fix use after free in ath11k_dp_rx_msdu_coalesce.
From: Jeff Johnson @ 2026-05-05 15:13 UTC (permalink / raw)
To: Willmar Knikker, jjohnson; +Cc: linux-wireless, ath11k
In-Reply-To: <20260505143025.234292-1-willmar@met-dubbel-l.nl>
On 5/5/2026 7:30 AM, Willmar Knikker wrote:
> In ath11k_dp_rx_msdu_coalesce the loop uses ->is_continuation after
> the dev_kfree_skb_any. This can cause a use after free kfence.
>
> Move the use after the dev_kfree_skb_any after use of ->is_continuation
> inline with the while in the while loop above this one.
>
> Signed-off-by: Willmar Knikker <willmar@met-dubbel-l.nl>
This issue is present since day 1...
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
^ permalink raw reply
* Re: [PATCH] wifi: ath11k: fix use after free in ath11k_dp_rx_msdu_coalesce.
From: Jeff Johnson @ 2026-05-05 15:08 UTC (permalink / raw)
To: Willmar Knikker, jjohnson; +Cc: linux-wireless, ath11k
In-Reply-To: <20260505143025.234292-1-willmar@met-dubbel-l.nl>
On 5/5/2026 7:30 AM, Willmar Knikker wrote:
> In ath11k_dp_rx_msdu_coalesce the loop uses ->is_continuation after
> the dev_kfree_skb_any. This can cause a use after free kfence.
>
> Move the use after the dev_kfree_skb_any after use of ->is_continuation
> inline with the while in the while loop above this one.
>
> Signed-off-by: Willmar Knikker <willmar@met-dubbel-l.nl>
> ---
> drivers/net/wireless/ath/ath11k/dp_rx.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
> index fe79109adc70..02bd9787d6b4 100644
> --- a/drivers/net/wireless/ath/ath11k/dp_rx.c
> +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
> @@ -1825,11 +1825,12 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
> skb_pull(skb, hal_rx_desc_sz);
> skb_copy_from_linear_data(skb, skb_put(first, buf_len),
> buf_len);
> - dev_kfree_skb_any(skb);
> -
> rem_len -= buf_len;
> - if (!rxcb->is_continuation)
> + if (!rxcb->is_continuation) {
> + dev_kfree_skb_any(skb);
> break;
> + }
> + dev_kfree_skb_any(skb);
rather than repeating code imo it would be "better" to cache the flag before
freeing and then test the cached flag.
however as you note this proposed logic matches the logic already present in
the "Free up all buffers of the MSDU" portion of the function, so from that
perspective the proposal is consistent with that logic.
let's see if anyone else has an opinion...
/jeff
^ permalink raw reply
* Re: [PATCH v5 14/16] wifi: ath12k: Switch to generic PAS TZ APIs
From: Jeff Johnson @ 2026-05-05 14:50 UTC (permalink / raw)
To: Sumit Garg, andersson, konradybcio, Sowmiya Sree Elavalagan
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, robh, krzk+dt,
conor+dt, robin.clark, sean, akhilpo, lumag, abhinav.kumar,
jesszhan0024, marijn.suijten, airlied, simona, vikash.garodia,
dikshita.agarwal, bod, mchehab, elder, andrew+netdev, davem,
edumazet, kuba, pabeni, jjohnson, mathieu.poirier,
trilokkumar.soni, mukesh.ojha, pavan.kondeti, jorge.ramirez,
tonyh, vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, linux-kernel, Sumit Garg
In-Reply-To: <3bfdc11c-115f-45ab-b0ab-75ad88dc6f31@oss.qualcomm.com>
On 5/5/2026 7:27 AM, Jeff Johnson wrote:
> On 5/4/2026 6:06 AM, Sumit Garg wrote:
>> @@ -485,9 +485,9 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend)
>> pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
>> ATH12K_AHB_UPD_SWID;
>> /* Release the firmware */
>> - ret = qcom_scm_pas_shutdown(pasid);
>> + ret = qcom_pas_shutdown(pasid);
>> if (ret)
>> - ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
>> + ath12k_err(ab, "pas shutdown failed for userPD%d: %d\n",
>> ab_ahb->userpd_id);
>
> at some point the "ret" param was dropped, and this now generates build warnings
The 'ret' param was dropped by:
8fb66931fe31 ("wifi: ath12k: Enable IPQ5424 WiFi device support")
Not sure if that was on purpose or accidental. Sowmiya?
- if (ret)
- ath12k_err(ab, "scm pas shutdown failed for userPD%d: %d\n",
- ab_ahb->userpd_id, ret);
...
+ if (ret)
+ ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
+ ab_ahb->userpd_id);
^ permalink raw reply
* [PATCH ath-next 2/2] wifi: ath12k: Add debugfs support to simulate incumbent signal interference
From: Amith A @ 2026-05-05 14:38 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, amith.a, Aishwarya R
In-Reply-To: <20260505143853.295368-1-amith.a@oss.qualcomm.com>
From: Aishwarya R <aishwarya.r@oss.qualcomm.com>
Add debugfs support to simulate incumbent signal interference from the
host for testing purposes. The debugfs entry is created only for 6 GHz
radio when firmware advertises the support through
WMI_TLV_SERVICE_DCS_INCUMBENT_SIGNAL_INTERFERENCE_SUPPORT flag.
Debugfs command:
echo <interference_bitmap> > /sys/kernel/debug/ath12k/pci-000X/macX/simulate_incumbent_signal_interference
Each bit in the interference_bitmap represents a 20 MHz segment. Bit 0
corresponds to the primary 20 MHz segment, regardless of its position
within the operating bandwidth. Bit 1 represents the next adjacent 20 MHz
segment, bit 2 the lower 20 MHz segment of the adjacent 40 MHz segment,
and so on-progressing sequentially across the bandwidth..
Example:
echo 0xF0 > /sys/kernel/debug/ath12k/pci-0002:01:00.0/mac0/simulate_incumbent_signal_interference
This indicates that all the subchannels in the secondary 80 MHz segment
were affected.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1
Signed-off-by: Aishwarya R <aishwarya.r@oss.qualcomm.com>
Signed-off-by: Amith A <amith.a@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/debugfs.c | 46 +++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wmi.c | 36 ++++++++++++++++++
drivers/net/wireless/ath/ath12k/wmi.h | 14 +++++++
3 files changed, 96 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index 8c81a1c22449..d17d4a8f1cb7 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1450,6 +1450,44 @@ static const struct file_operations fops_pdev_stats = {
.llseek = default_llseek,
};
+static ssize_t
+ath12k_write_simulate_incumbent_signal_interference(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath12k *ar = file->private_data;
+ struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
+ struct wiphy *wiphy = ath12k_ar_to_hw(ar)->wiphy;
+ u32 chan_bw_interference_bitmap;
+ int ret;
+
+ if (ah->state != ATH12K_HW_STATE_ON)
+ return -ENETDOWN;
+
+ /*
+ * Bitmap uses the firmware primary-based ordering documented in
+ * ath12k_wmi_transform_interference_bitmap() & intf_map_80.
+ */
+ if (kstrtou32_from_user(user_buf, count, 0, &chan_bw_interference_bitmap))
+ return -EINVAL;
+
+ wiphy_lock(wiphy);
+ ret = ath12k_wmi_simulate_incumbent_signal_interference(ar, chan_bw_interference_bitmap);
+ if (ret)
+ goto exit;
+
+ ret = count;
+
+exit:
+ wiphy_unlock(wiphy);
+ return ret;
+}
+
+static const struct file_operations fops_simulate_incumbent_signal_interference = {
+ .write = ath12k_write_simulate_incumbent_signal_interference,
+ .open = simple_open,
+};
+
static
void ath12k_debugfs_fw_stats_register(struct ath12k *ar)
{
@@ -1515,6 +1553,14 @@ void ath12k_debugfs_register(struct ath12k *ar)
ar, &fops_tpc_stats_type);
init_completion(&ar->debug.tpc_complete);
+ if (ar->mac.sbands[NL80211_BAND_6GHZ].channels &&
+ test_bit(WMI_TLV_SERVICE_DCS_INCUMBENT_SIGNAL_INTERFERENCE_SUPPORT,
+ ar->ab->wmi_ab.svc_map)) {
+ debugfs_create_file("simulate_incumbent_signal_interference", 0200,
+ ar->debug.debugfs_pdev, ar,
+ &fops_simulate_incumbent_signal_interference);
+ }
+
ath12k_debugfs_htt_stats_register(ar);
ath12k_debugfs_fw_stats_register(ar);
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index b9e107cfd869..4ec5b12f703b 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -10561,6 +10561,42 @@ int ath12k_wmi_send_tpc_stats_request(struct ath12k *ar,
return ret;
}
+int ath12k_wmi_simulate_incumbent_signal_interference(struct ath12k *ar,
+ u32 chan_bw_interference_bitmap)
+{
+ struct wmi_unit_test_arg wmi_ut = {};
+ struct ath12k_link_vif *arvif;
+ struct ath12k_vif *ahvif;
+ bool arvif_found = false;
+
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ ahvif = arvif->ahvif;
+ if (arvif->is_started && ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ arvif_found = true;
+ break;
+ }
+ }
+
+ if (!arvif_found)
+ return -EINVAL;
+
+ wmi_ut.args[ATH12K_WMI_INCUMBENT_SIGNAL_TEST_INTF] =
+ ATH12K_WMI_UNIT_TEST_INCUMBENT_SIGNAL_INTF_TYPE;
+ wmi_ut.args[ATH12K_WMI_INCUMBENT_SIGNAL_TEST_BITMAP] =
+ chan_bw_interference_bitmap;
+
+ wmi_ut.vdev_id = arvif->vdev_id;
+ wmi_ut.module_id = ATH12K_WMI_INCUMBENT_SIGNAL_UNIT_TEST_MODULE;
+ wmi_ut.num_args = ATH12K_WMI_INCUMBENT_SIGNAL_MAX_TEST_ARGS;
+ wmi_ut.diag_token = ATH12K_WMI_INCUMBENT_SIGNAL_UNIT_TEST_TOKEN;
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "Triggering incumbent signal interference simulation, interference bitmap: 0x%x\n",
+ chan_bw_interference_bitmap);
+
+ return ath12k_wmi_send_unit_test_cmd(ar, &wmi_ut);
+}
+
int ath12k_wmi_connect(struct ath12k_base *ab)
{
u32 i;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index d74f7fca7678..b5b3e472631c 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2269,6 +2269,8 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
+ WMI_TLV_SERVICE_DCS_INCUMBENT_SIGNAL_INTERFERENCE_SUPPORT = 286,
+
WMI_TLV_SERVICE_11BE = 289,
WMI_TLV_SERVICE_WMSK_COMPACTION_RX_TLVS = 361,
@@ -4244,6 +4246,10 @@ struct wmi_addba_clear_resp_cmd {
#define DFS_UNIT_TEST_MODULE 0x2b
#define DFS_UNIT_TEST_TOKEN 0xAA
+#define ATH12K_WMI_INCUMBENT_SIGNAL_UNIT_TEST_MODULE 0x18
+#define ATH12K_WMI_INCUMBENT_SIGNAL_UNIT_TEST_TOKEN 0
+#define ATH12K_WMI_UNIT_TEST_INCUMBENT_SIGNAL_INTF_TYPE 1
+
enum dfs_test_args_idx {
DFS_TEST_CMDID = 0,
DFS_TEST_PDEV_ID,
@@ -4251,6 +4257,12 @@ enum dfs_test_args_idx {
DFS_MAX_TEST_ARGS,
};
+enum ath12k_wmi_incumbent_signal_test_args_idx {
+ ATH12K_WMI_INCUMBENT_SIGNAL_TEST_INTF,
+ ATH12K_WMI_INCUMBENT_SIGNAL_TEST_BITMAP,
+ ATH12K_WMI_INCUMBENT_SIGNAL_MAX_TEST_ARGS,
+};
+
/* update if another test command requires more */
#define WMI_UNIT_TEST_ARGS_MAX DFS_MAX_TEST_ARGS
@@ -6682,6 +6694,8 @@ int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar,
struct ath12k_reg_tpc_power_info *param);
int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
struct wmi_mlo_link_set_active_arg *param);
+int ath12k_wmi_simulate_incumbent_signal_interference(struct ath12k *ar,
+ u32 chan_bw_interference_bitmap);
int ath12k_wmi_alloc(void);
void ath12k_wmi_free(void);
--
2.34.1
^ permalink raw reply related
* [PATCH ath-next 1/2] wifi: ath12k: Add support for handling incumbent signal interference in 6 GHz
From: Amith A @ 2026-05-05 14:38 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, amith.a, Aishwarya R, Hari Chandrakanthan
In-Reply-To: <20260505143853.295368-1-amith.a@oss.qualcomm.com>
From: Aishwarya R <aishwarya.r@oss.qualcomm.com>
When incumbent signal interference is detected by an AP/mesh interface
operating in the 6 GHz band, as mandated by the FCC, it is expected to
vacate the affected channels. The firmware indicates the interference to
the host using the WMI_DCS_INTERFERENCE_EVENT.
To handle the new WMI event, first parse it to retrieve the interference
information. Next, validate the interference-detected channel and
the interference bitmap. The interference bitmap received from the
firmware uses a mapping where bit 0 corresponds to the primary
20 MHz segment, regardless of its position within the operating
bandwidth. Bit 1 represents the next adjacent 20 MHz segment, bit 2
the lower 20 MHz segment of the adjacent 40 MHz segment, and so
on, progressing sequentially across the bandwidth. However, for userspace
consumption via mac80211, this bitmap must be transformed into a
standardized format such that each bit position directly maps to the
corresponding sub-channel index within the operating bandwidth.
Finally, indicate the transformed interference bitmap to mac80211, which
then notifies userspace of the interference. Once the incumbent signal
interference is detected, firmware suspends TX internally on the affected
operating channel while userspace decides the mitigation action. Userspace
is expected to trigger a channel switch or bandwidth reduction to mitigate
the interference. Also, add a flag handling_in_progress to indicate that
handling of interference is in progress. Set it to true after
indicating to mac80211 about the interference. Reset the flag to false
after the operating channel is switched by userspace. This prevents
processing any further interference events when there is already a
previous event being handled. Hence, further events are processed only
after a channel switch request is received from userspace for the
previous event.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1
Signed-off-by: Aishwarya R <aishwarya.r@oss.qualcomm.com>
Co-developed-by: Hari Chandrakanthan <quic_haric@quicinc.com>
Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
Signed-off-by: Amith A <amith.a@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/core.h | 8 +
drivers/net/wireless/ath/ath12k/mac.c | 46 +++
drivers/net/wireless/ath/ath12k/wmi.c | 382 +++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wmi.h | 58 +++-
4 files changed, 493 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 8be435535a4e..3aa25db9264e 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -763,6 +763,14 @@ struct ath12k {
struct ath12k_pdev_rssi_offsets rssi_info;
struct ath12k_thermal thermal;
+
+ /* Protected by ar->data_lock */
+ struct ath12k_incumbent_signal_interference {
+ u32 center_freq;
+ enum nl80211_chan_width width;
+ u32 chan_bw_interference_bitmap;
+ bool handling_in_progress;
+ } incumbent_signal_interference;
};
struct ath12k_hw {
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 9ce759626f18..75881fccd175 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -9637,6 +9637,10 @@ static int ath12k_mac_start(struct ath12k *ar)
ar->allocated_vdev_map = 0;
ar->chan_tx_pwr = ATH12K_PDEV_TX_POWER_INVALID;
+ spin_lock_bh(&ar->data_lock);
+ ar->incumbent_signal_interference.handling_in_progress = false;
+ spin_unlock_bh(&ar->data_lock);
+
/* Configure monitor status ring with default rx_filter to get rx status
* such as rssi, rx_duration.
*/
@@ -9850,6 +9854,10 @@ static void ath12k_mac_stop(struct ath12k *ar)
synchronize_rcu();
atomic_set(&ar->num_pending_mgmt_tx, 0);
+
+ spin_lock_bh(&ar->data_lock);
+ ar->incumbent_signal_interference.handling_in_progress = false;
+ spin_unlock_bh(&ar->data_lock);
}
void ath12k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
@@ -11436,8 +11444,10 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs)
{
+ struct ath12k_incumbent_signal_interference *incumbent;
struct ath12k_wmi_vdev_up_params params = {};
struct ieee80211_bss_conf *link_conf;
+ struct cfg80211_chan_def *chandef;
struct ath12k_base *ab = ar->ab;
struct ath12k_link_vif *arvif;
struct ieee80211_vif *vif;
@@ -11549,6 +11559,42 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
if (!ath12k_mac_monitor_stop(ar))
ath12k_mac_monitor_start(ar);
}
+
+ incumbent = &ar->incumbent_signal_interference;
+ spin_lock_bh(&ar->data_lock);
+ if (incumbent->handling_in_progress) {
+ chandef = &vifs[0].new_ctx->def;
+ if (incumbent->chan_bw_interference_bitmap &
+ ATH12K_WMI_DCS_SEG_PRI20) {
+ if (incumbent->center_freq !=
+ chandef->chan->center_freq) {
+ incumbent->chan_bw_interference_bitmap = 0;
+ incumbent->handling_in_progress = false;
+ ath12k_dbg(ab, ATH12K_DBG_MAC,
+ "incumbent signal interference chan switch completed\n");
+ } else {
+ ath12k_warn(ab,
+ "incumbent signal interference chan switch not done, freq %u\n",
+ incumbent->center_freq);
+ }
+ } else {
+ if (incumbent->center_freq !=
+ chandef->chan->center_freq ||
+ incumbent->width != chandef->width) {
+ incumbent->chan_bw_interference_bitmap = 0;
+ incumbent->handling_in_progress = false;
+ ath12k_dbg(ab, ATH12K_DBG_MAC,
+ "Bandwidth/channel change due to incumbent signal interference completed\n");
+ } else {
+ ath12k_warn(ab, "Bandwidth/channel change due to incumbent sig intf not done intf_freq %u chan_freq %u intf_width %u chan_width %u\n",
+ incumbent->center_freq,
+ chandef->chan->center_freq,
+ incumbent->width,
+ chandef->width);
+ }
+ }
+ }
+ spin_unlock_bh(&ar->data_lock);
}
static void
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index c7559938564c..b9e107cfd869 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -234,6 +234,68 @@ static const int ath12k_hw_mode_pri_map[] = {
PRIMAP(WMI_HOST_HW_MODE_MAX),
};
+/*
+ * Interference bitmap transform maps used by
+ * ath12k_wmi_transform_interference_bitmap().
+ *
+ * Firmware reports bitmap bits in a primary-based order where:
+ * - bit 0 is always the primary 20 MHz segment,
+ * - bit 1 is the adjacent 20 MHz in the same 40 MHz block,
+ * - bit 2 is the lower 20 MHz segment of the adjacent 40 MHz segment
+ * - bit 3 is the higher 20 MHz segment of the adjacent 40 MHz segment
+ * - remaining bits continue outward in 80/160/320 MHz groups.
+ *
+ * cfg80211 userspace notification expects absolute frequency order where:
+ * - bit 0 is the lowest-frequency 20 MHz segment in the current chandef,
+ * - bit N increases monotonically toward higher frequency.
+ *
+ * For each bandwidth-specific map:
+ * - row index = primary 20 MHz index in absolute (low->high) order,
+ * - column index = source bit position from firmware bitmap,
+ * - value = destination bit position in absolute order bitmap.
+ *
+ * Example for 80 MHz: if primary index is 2 (third 20 MHz chunk from low
+ * frequency), row intf_map_80[2] = { 2, 3, 0, 1 } means firmware bits {0,1,2,3}
+ * are remapped to destination bits {2,3,0,1} before notifying cfg80211.
+ */
+
+static const int intf_map_80[4][4] = {
+ { 0, 1, 2, 3 },
+ { 1, 0, 2, 3 },
+ { 2, 3, 0, 1 },
+ { 3, 2, 0, 1 }
+};
+
+static const int intf_map_160[8][8] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 1, 0, 2, 3, 4, 5, 6, 7 },
+ { 2, 3, 0, 1, 4, 5, 6, 7 },
+ { 3, 2, 0, 1, 4, 5, 6, 7 },
+ { 4, 5, 6, 7, 0, 1, 2, 3 },
+ { 5, 4, 6, 7, 0, 1, 2, 3 },
+ { 6, 7, 4, 5, 0, 1, 2, 3 },
+ { 7, 6, 4, 5, 0, 1, 2, 3 }
+};
+
+static const int intf_map_320[16][16] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 2, 3, 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 3, 2, 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 4, 5, 6, 7, 0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 5, 4, 6, 7, 0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 6, 7, 4, 5, 0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 7, 6, 4, 5, 0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 9, 8, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 10, 11, 8, 9, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 11, 10, 8, 9, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 12, 13, 14, 15, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 13, 12, 14, 15, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 14, 15, 12, 13, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 15, 14, 12, 13, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7 }
+};
+
static int
ath12k_wmi_tlv_iter(struct ath12k_base *ab, const void *ptr, size_t len,
int (*iter)(struct ath12k_base *ab, u16 tag, u16 len,
@@ -8597,6 +8659,323 @@ static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,
ev->ctl_failsafe_status);
}
+static int
+ath12k_wmi_incumbent_signal_interference_subtlv_parser(struct ath12k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr,
+ void *data)
+{
+ const struct ath12k_wmi_incumbent_signal_interference_params *info;
+ struct ath12k_wmi_incumbent_signal_interference_arg *arg = data;
+
+ switch (tag) {
+ case WMI_TAG_DCS_INCUMBENT_SIGNAL_INTERFERENCE_TYPE:
+ info = ptr;
+
+ arg->chan_width = le32_to_cpu(info->chan_width);
+ arg->chan_freq = le32_to_cpu(info->chan_freq);
+ arg->center_freq0 = le32_to_cpu(info->center_freq0);
+ arg->center_freq1 = le32_to_cpu(info->center_freq1);
+ arg->chan_bw_interference_bitmap =
+ le32_to_cpu(info->chan_bw_interference_bitmap);
+
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "incumbent signal interference chan width %u freq %u center_freq0 %u center_freq1 %u bitmap 0x%x\n",
+ arg->chan_width, arg->chan_freq,
+ arg->center_freq0, arg->center_freq1,
+ arg->chan_bw_interference_bitmap);
+ break;
+ default:
+ ath12k_warn(ab, "Received invalid tag 0x%x for WMI DCS interference in subtlvs\n",
+ tag);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ath12k_wmi_dcs_interference_event_parser(struct ath12k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr, void *data)
+{
+ int ret = 0;
+
+ switch (tag) {
+ case WMI_TAG_DCS_INTERFERENCE_EVENT:
+ /* Fixed param should already be processed */
+ break;
+ case WMI_TAG_ARRAY_STRUCT:
+ ret = ath12k_wmi_tlv_iter(ab, ptr, len,
+ ath12k_wmi_incumbent_signal_interference_subtlv_parser,
+ data);
+ break;
+ default:
+ ath12k_warn(ab, "Received invalid tag 0x%x for WMI DCS interference event\n",
+ tag);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static bool
+ath12k_wmi_validate_interference_info(struct ath12k *ar,
+ struct ath12k_wmi_incumbent_signal_interference_arg *info)
+{
+ switch (info->chan_width) {
+ case WMI_CHAN_WIDTH_20:
+ if (info->chan_bw_interference_bitmap > ATH12K_WMI_DCS_SEG_PRI20) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "DCS interference event received with wrong chan width bmap 0x%x for 20 MHz",
+ info->chan_bw_interference_bitmap);
+ return false;
+ }
+ break;
+ case WMI_CHAN_WIDTH_40:
+ if (info->chan_bw_interference_bitmap > (ATH12K_WMI_DCS_SEG_PRI20 |
+ ATH12K_WMI_DCS_SEG_SEC20)) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "DCS interference event received with wrong chan width bmap 0x%x for 40 MHz",
+ info->chan_bw_interference_bitmap);
+ return false;
+ }
+ break;
+ case WMI_CHAN_WIDTH_80:
+ if (info->chan_bw_interference_bitmap > (ATH12K_WMI_DCS_SEG_PRI20 |
+ ATH12K_WMI_DCS_SEG_SEC20 |
+ ATH12K_WMI_DCS_SEG_SEC40)) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "DCS interference event received with wrong chan width bmap 0x%x for 80 MHz",
+ info->chan_bw_interference_bitmap);
+ return false;
+ }
+ break;
+ case WMI_CHAN_WIDTH_160:
+ if (info->chan_bw_interference_bitmap > (ATH12K_WMI_DCS_SEG_PRI20 |
+ ATH12K_WMI_DCS_SEG_SEC20 |
+ ATH12K_WMI_DCS_SEG_SEC40 |
+ ATH12K_WMI_DCS_SEG_SEC80)) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "DCS interference event received with wrong chan width bmap 0x%x for 160 MHz",
+ info->chan_bw_interference_bitmap);
+ return false;
+ }
+ break;
+ case WMI_CHAN_WIDTH_320:
+ if (info->chan_bw_interference_bitmap > (ATH12K_WMI_DCS_SEG_PRI20 |
+ ATH12K_WMI_DCS_SEG_SEC20 |
+ ATH12K_WMI_DCS_SEG_SEC40 |
+ ATH12K_WMI_DCS_SEG_SEC80 |
+ ATH12K_WMI_DCS_SEG_SEC160)) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "DCS interference event received with wrong chan width bmap 0x%x for 320 MHz",
+ info->chan_bw_interference_bitmap);
+ return false;
+ }
+ break;
+ default:
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "DCS interference event received with unknown channel width %u",
+ info->chan_width);
+ return false;
+ }
+ return true;
+}
+
+static u32
+ath12k_wmi_transform_interference_bitmap(int input_bitmap,
+ struct cfg80211_chan_def *chandef)
+{
+ u16 output_bits[ATH12K_MAX_20MHZ_SEGMENTS] = {};
+ u16 input_bits[ATH12K_MAX_20MHZ_SEGMENTS] = {};
+ u32 start_freq, segment_freq;
+ int primary_index = -1;
+ u32 output_bitmap = 0;
+ u16 num_sub_chans;
+ int bandwidth;
+
+ bandwidth = nl80211_chan_width_to_mhz(chandef->width);
+ if (bandwidth < 0)
+ return 0;
+
+ /*
+ * Firmware reports bit 0 as primary 20 MHz irrespective of absolute
+ * frequency position. Convert to standardized lowest-to-highest 20 MHz
+ * ordering expected by cfg80211/mac80211 userspace consumers.
+ */
+ num_sub_chans = bandwidth / 20;
+ start_freq = (chandef->center_freq1 - bandwidth / 2) + 10;
+
+ for (int i = 0; i < ATH12K_MAX_20MHZ_SEGMENTS; i++) {
+ segment_freq = start_freq + (i * 20);
+ if (segment_freq == chandef->chan->center_freq) {
+ primary_index = i;
+ break;
+ }
+ }
+ if (primary_index == -1)
+ return 0;
+
+ for (int i = 0; i < ATH12K_MAX_20MHZ_SEGMENTS; ++i)
+ input_bits[i] = BIT(i) & input_bitmap;
+
+ for (int i = 0; i < num_sub_chans; ++i) {
+ int src = i, dst = i;
+
+ switch (bandwidth) {
+ case 40:
+ if (primary_index == 1)
+ dst = 1 - i;
+ break;
+ case 80:
+ dst = intf_map_80[primary_index][i];
+ break;
+ case 160:
+ dst = intf_map_160[primary_index][i];
+ break;
+ case 320:
+ dst = intf_map_320[primary_index][i];
+ break;
+ }
+ output_bits[dst] = input_bits[src];
+ }
+
+ for (int i = 0; i < ATH12K_MAX_20MHZ_SEGMENTS; ++i)
+ output_bitmap |= output_bits[i] ? BIT(i) : 0;
+
+ return output_bitmap;
+}
+
+static void
+ath12k_wmi_process_incumbent_signal_interference_evt(struct ath12k_base *ab,
+ struct sk_buff *skb,
+ const struct ath12k_wmi_intf_arg *intf_arg)
+{
+ struct ath12k_wmi_incumbent_signal_interference_arg info = {};
+ struct ath12k_incumbent_signal_interference *incumbent;
+ struct ath12k_mac_get_any_chanctx_conf_arg arg;
+ u32 transformed_intf_bitmap;
+ struct ieee80211_hw *hw;
+ struct ath12k *ar;
+ int ret;
+
+ guard(rcu)();
+
+ ar = ath12k_mac_get_ar_by_pdev_id(ab, intf_arg->pdev_id);
+ if (!ar) {
+ ath12k_warn(ab, "incumbent signal interference detected on invalid pdev %d\n",
+ intf_arg->pdev_id);
+ return;
+ }
+ if (!ar->supports_6ghz) {
+ ath12k_warn(ab, "pdev does not support 6 GHz, dropping DCS interference event\n");
+ return;
+ }
+
+ incumbent = &ar->incumbent_signal_interference;
+ spin_lock_bh(&ar->data_lock);
+ if (incumbent->handling_in_progress) {
+ spin_unlock_bh(&ar->data_lock);
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "incumbent signal interference handling ongoing, dropping DCS interference event");
+ return;
+ }
+ spin_unlock_bh(&ar->data_lock);
+
+ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
+ ath12k_wmi_dcs_interference_event_parser,
+ &info);
+ if (ret) {
+ ath12k_warn(ab,
+ "failed to parse incumbent signal interference TLV. Error %d\n",
+ ret);
+ return;
+ }
+
+ if (!ath12k_wmi_validate_interference_info(ar, &info)) {
+ ath12k_warn(ab, "invalid DCS incumbent signal interference TLV - Skipping event");
+ return;
+ }
+
+ arg.ar = ar;
+ arg.chanctx_conf = NULL;
+ hw = ath12k_ar_to_hw(ar);
+ ieee80211_iter_chan_contexts_atomic(hw,
+ ath12k_mac_get_any_chanctx_conf_iter,
+ &arg);
+ if (!arg.chanctx_conf) {
+ ath12k_warn(ab, "failed to find valid chanctx_conf in incumbent signal intf detected event\n");
+ return;
+ }
+
+ if (info.chan_freq != arg.chanctx_conf->def.chan->center_freq) {
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "dcs interference event received with wrong channel %d (ctx freq %d)",
+ info.chan_freq, arg.chanctx_conf->def.chan->center_freq);
+ return;
+ }
+
+ spin_lock_bh(&ar->data_lock);
+ incumbent->center_freq = arg.chanctx_conf->def.chan->center_freq;
+ incumbent->width = arg.chanctx_conf->def.width;
+ incumbent->chan_bw_interference_bitmap = info.chan_bw_interference_bitmap;
+ incumbent->handling_in_progress = true;
+ spin_unlock_bh(&ar->data_lock);
+ transformed_intf_bitmap =
+ ath12k_wmi_transform_interference_bitmap(info.chan_bw_interference_bitmap,
+ &arg.chanctx_conf->def);
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "incumbent signal interference bitmap 0x%x (transformed 0x%x)\n",
+ info.chan_bw_interference_bitmap, transformed_intf_bitmap);
+ cfg80211_incumbent_signal_notify(hw->wiphy,
+ &arg.chanctx_conf->def,
+ transformed_intf_bitmap,
+ GFP_ATOMIC);
+}
+
+static void
+ath12k_wmi_dcs_interference_event(struct ath12k_base *ab,
+ struct sk_buff *skb)
+{
+ const struct ath12k_wmi_dcs_interference_ev_fixed_params *dcs_intf_ev;
+ struct ath12k_wmi_intf_arg dcs_intf_arg;
+ const struct wmi_tlv *tlv;
+ u16 tlv_tag;
+ u8 *ptr;
+
+ if (skb->len < (sizeof(*dcs_intf_ev) + TLV_HDR_SIZE)) {
+ ath12k_warn(ab, "DCS interference event is of incorrect length\n");
+ return;
+ }
+
+ ptr = skb->data;
+ tlv = (struct wmi_tlv *)ptr;
+ tlv_tag = le32_get_bits(tlv->header, WMI_TLV_TAG);
+ ptr += sizeof(*tlv);
+
+ if (tlv_tag != WMI_TAG_DCS_INTERFERENCE_EVENT) {
+ ath12k_warn(ab, "DCS interference event received with wrong tag\n");
+ return;
+ }
+
+ dcs_intf_ev = (struct ath12k_wmi_dcs_interference_ev_fixed_params *)ptr;
+
+ dcs_intf_arg.interference_type =
+ le32_to_cpu(dcs_intf_ev->interference_type);
+ dcs_intf_arg.pdev_id = le32_to_cpu(dcs_intf_ev->pdev_id);
+
+ if (dcs_intf_arg.interference_type ==
+ ATH12K_WMI_DCS_INCUMBENT_SIGNAL_INTERFERENCE) {
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "incumbent signal interference (Type %u) detected on pdev %u.",
+ dcs_intf_arg.interference_type,
+ dcs_intf_arg.pdev_id);
+ ath12k_wmi_process_incumbent_signal_interference_evt(ab, skb,
+ &dcs_intf_arg);
+ }
+}
+
static void
ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
const struct ath12k_wmi_pdev_csa_event *ev,
@@ -9961,6 +10340,9 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
case WMI_OBSS_COLOR_COLLISION_DETECTION_EVENTID:
ath12k_wmi_obss_color_collision_event(ab, skb);
break;
+ case WMI_DCS_INTERFERENCE_EVENTID:
+ ath12k_wmi_dcs_interference_event(ab, skb);
+ break;
/* add Unsupported events (rare) here */
case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index c644604c1426..d74f7fca7678 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2015,7 +2015,7 @@ enum wmi_tlv_tag {
WMI_TAG_VDEV_CH_POWER_INFO,
WMI_TAG_MLO_LINK_SET_ACTIVE_CMD = 0x3BE,
WMI_TAG_EHT_RATE_SET = 0x3C4,
- WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5,
+ WMI_TAG_DCS_INCUMBENT_SIGNAL_INTERFERENCE_TYPE = 0x3C5,
WMI_TAG_MLO_TX_SEND_PARAMS,
WMI_TAG_MLO_PARTNER_LINK_PARAMS,
WMI_TAG_MLO_PARTNER_LINK_PARAMS_PEER_ASSOC,
@@ -4535,6 +4535,62 @@ struct ath12k_wmi_pdev_radar_event {
a_sle32 sidx;
} __packed;
+#define ATH12K_WMI_DCS_INCUMBENT_SIGNAL_INTERFERENCE 0x04
+
+struct ath12k_wmi_dcs_interference_ev_fixed_params {
+ __le32 interference_type;
+ __le32 pdev_id;
+} __packed;
+
+struct ath12k_wmi_incumbent_signal_interference_params {
+ __le32 chan_width;
+ __le32 chan_freq;
+ __le32 center_freq0;
+ __le32 center_freq1;
+ __le32 chan_bw_interference_bitmap;
+} __packed;
+
+struct ath12k_wmi_incumbent_signal_interference_arg {
+ u32 chan_width;
+ u32 chan_freq;
+ u32 center_freq0;
+ u32 center_freq1;
+ u32 chan_bw_interference_bitmap;
+};
+
+struct ath12k_wmi_intf_arg {
+ u32 interference_type;
+ u32 pdev_id;
+};
+
+enum ath12k_wmi_dcs_interference_chan_segment {
+ /*
+ * Firmware reports interference bitmap in primary-based order.
+ * Bit 0 is the primary 20 MHz, bit 1 is the adjacent 20 MHz within
+ * the primary 40 MHz. Bits 2-3 cover the secondary 40 MHz, bits 4-7
+ * cover the secondary 80 MHz, and bits 8-15 cover the secondary 160 MHz.
+ */
+ ATH12K_WMI_DCS_SEG_PRI20 = 0x1,
+ ATH12K_WMI_DCS_SEG_SEC20 = 0x2,
+ ATH12K_WMI_DCS_SEG_SEC40_LOW = 0x4,
+ ATH12K_WMI_DCS_SEG_SEC40_UP = 0x8,
+ ATH12K_WMI_DCS_SEG_SEC40 = 0xC,
+ ATH12K_WMI_DCS_SEG_SEC80_LOW = 0x10,
+ ATH12K_WMI_DCS_SEG_SEC80_LOW_UP = 0x20,
+ ATH12K_WMI_DCS_SEG_SEC80_UP_LOW = 0x40,
+ ATH12K_WMI_DCS_SEG_SEC80_UP = 0x80,
+ ATH12K_WMI_DCS_SEG_SEC80 = 0xF0,
+ ATH12K_WMI_DCS_SEG_SEC160_LOW = 0x0100,
+ ATH12K_WMI_DCS_SEG_SEC160_LOW_UP = 0x0200,
+ ATH12K_WMI_DCS_SEG_SEC160_LOW_UP_UP = 0x0400,
+ ATH12K_WMI_DCS_SEG_SEC160_LOW_UP_UP_UP = 0x0800,
+ ATH12K_WMI_DCS_SEG_SEC160_UP_LOW_LOW_LOW = 0x1000,
+ ATH12K_WMI_DCS_SEG_SEC160_UP_LOW_LOW = 0x2000,
+ ATH12K_WMI_DCS_SEG_SEC160_UP_LOW = 0x4000,
+ ATH12K_WMI_DCS_SEG_SEC160_UP = 0x8000,
+ ATH12K_WMI_DCS_SEG_SEC160 = 0xFF00,
+};
+
struct wmi_pdev_temperature_event {
/* temperature value in Celsius degree */
a_sle32 temp;
--
2.34.1
^ permalink raw reply related
* [PATCH ath-next 0/2] wifi: ath12k: Add support for handling incumbent signal interference in 6 GHz
From: Amith A @ 2026-05-05 14:38 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, amith.a
This patch series adds the implementation of handling of interferences
due to incumbent signals in 6 GHz channels. When an interference is
detected, the firmware indicates it to the host using the
WMI_DCS_INTERFERENCE_EVENT.
The driver is expected to parse the new WMI event to retrieve the
interference information, validate the interference detected channel and
bitmap, and indicate the interference to mac80211, which then notifies
this interference to the userspace.
Aishwarya R (2):
wifi: ath12k: Add support for handling incumbent signal interference
in 6 GHz
wifi: ath12k: Add debugfs support to simulate incumbent signal
interference
drivers/net/wireless/ath/ath12k/core.h | 8 +
drivers/net/wireless/ath/ath12k/debugfs.c | 46 +++
drivers/net/wireless/ath/ath12k/mac.c | 46 +++
drivers/net/wireless/ath/ath12k/wmi.c | 418 ++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wmi.h | 72 +++-
5 files changed, 589 insertions(+), 1 deletion(-)
base-commit: e12d2d3983acb150fd987d19ec6a2a530da110df
--
2.34.1
^ permalink raw reply
* [PATCH] wifi: ath11k: fix use after free in ath11k_dp_rx_msdu_coalesce.
From: Willmar Knikker @ 2026-05-05 14:30 UTC (permalink / raw)
To: jjohnson; +Cc: linux-wireless, ath11k
In ath11k_dp_rx_msdu_coalesce the loop uses ->is_continuation after
the dev_kfree_skb_any. This can cause a use after free kfence.
Move the use after the dev_kfree_skb_any after use of ->is_continuation
inline with the while in the while loop above this one.
Signed-off-by: Willmar Knikker <willmar@met-dubbel-l.nl>
---
drivers/net/wireless/ath/ath11k/dp_rx.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index fe79109adc70..02bd9787d6b4 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1825,11 +1825,12 @@ static int ath11k_dp_rx_msdu_coalesce(struct ath11k *ar,
skb_pull(skb, hal_rx_desc_sz);
skb_copy_from_linear_data(skb, skb_put(first, buf_len),
buf_len);
- dev_kfree_skb_any(skb);
-
rem_len -= buf_len;
- if (!rxcb->is_continuation)
+ if (!rxcb->is_continuation) {
+ dev_kfree_skb_any(skb);
break;
+ }
+ dev_kfree_skb_any(skb);
}
return 0;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v5 14/16] wifi: ath12k: Switch to generic PAS TZ APIs
From: Jeff Johnson @ 2026-05-05 14:27 UTC (permalink / raw)
To: Sumit Garg, andersson, konradybcio
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, robh, krzk+dt,
conor+dt, robin.clark, sean, akhilpo, lumag, abhinav.kumar,
jesszhan0024, marijn.suijten, airlied, simona, vikash.garodia,
dikshita.agarwal, bod, mchehab, elder, andrew+netdev, davem,
edumazet, kuba, pabeni, jjohnson, mathieu.poirier,
trilokkumar.soni, mukesh.ojha, pavan.kondeti, jorge.ramirez,
tonyh, vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, linux-kernel, Sumit Garg
In-Reply-To: <20260504130603.1474043-15-sumit.garg@kernel.org>
On 5/4/2026 6:06 AM, Sumit Garg wrote:
> @@ -485,9 +485,9 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend)
> pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
> ATH12K_AHB_UPD_SWID;
> /* Release the firmware */
> - ret = qcom_scm_pas_shutdown(pasid);
> + ret = qcom_pas_shutdown(pasid);
> if (ret)
> - ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
> + ath12k_err(ab, "pas shutdown failed for userPD%d: %d\n",
> ab_ahb->userpd_id);
at some point the "ret" param was dropped, and this now generates build warnings
> }
> }
^ permalink raw reply
* Re: [PATCH wireless-next] wifi: mac80211: check stations are removed before MLD change
From: Ben Greear @ 2026-05-05 14:17 UTC (permalink / raw)
To: Johannes Berg, linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260505151731.3d7cbb8b952c.I4ce7b536e8af26d7b115e82fd733734446cc56a4@changeid>
On 5/5/26 06:17, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> If an interface changes to/from MLD, then all stations related
> to it must have been removed first. This is just natural since
> we go from having links to not (or vice versa), but not doing
> so also causes crashes in debugfs since vif changing to/from
> MLD removes the entire debugfs for the vif, including stations.
>
> Delete all stations but warn in this case, other code should
> be handling it, in effect fail fast rather than doing a double
> free or use-after-free in debugfs.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
> This basically makes sure that the bug I fixed in
> https://lore.kernel.org/linux-wireless/20260505151533.c4e52deb06ad.Iafe56cec7de8512626169496b134bce3a6c17010@changeid/
> is noticed quickly. I'll probably merge this only
> after the fix lands in wireless-next via net/net-next.
> ---
> net/mac80211/link.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/net/mac80211/link.c b/net/mac80211/link.c
> index 93e290dd783f..e81dd02de12e 100644
> --- a/net/mac80211/link.c
> +++ b/net/mac80211/link.c
> @@ -2,7 +2,7 @@
> /*
> * MLO link handling
> *
> - * Copyright (C) 2022-2025 Intel Corporation
> + * Copyright (C) 2022-2026 Intel Corporation
> */
> #include <linux/slab.h>
> #include <linux/kernel.h>
> @@ -307,6 +307,9 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
> if (old_links == new_links && dormant_links == sdata->vif.dormant_links)
> return 0;
>
> + if (!old_links || !new_links)
> + WARN_ON(sta_info_flush(sdata, -1) > 0);
Maybe WARN_ON_ONCE to keep log spam to a minimum?
Thanks,
Ben
> +
> /* if there were no old links, need to clear the pointers to deflink */
> if (!old_links)
> rem |= BIT(0);
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* pull-request: ath-current-20260505
From: Jeff Johnson @ 2026-05-05 14:02 UTC (permalink / raw)
To: linux-wireless, Johannes Berg; +Cc: ath10k, ath11k, ath12k, jjohnson
The following changes since commit d997c32157d2ca06e9f3f00ba6c4bf06593b49e7:
Merge tag 'ath-current-20260427' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath (2026-04-28 10:41:51 +0200)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git tags/ath-current-20260505
for you to fetch changes up to d748603f12baff112caa3ab7d39f50100f010dbd:
wifi: ath5k: do not access array OOB (2026-05-04 07:15:20 -0700)
----------------------------------------------------------------
ath.git update for v7.1-rc3
Fix an ath5k potential stack buffer overwrite.
Fix several issues in ath12k:
- WMI buffer leaks on error conditions
- use of uninitialized stack data when processing RSSI events
- incorrect logic for determining the peer ID in the RX path
----------------------------------------------------------------
Baochen Qiang (1):
wifi: ath12k: fix peer_id usage in normal RX path
Jiri Slaby (SUSE) (1):
wifi: ath5k: do not access array OOB
Nicolas Escande (1):
wifi: ath12k: fix leak in some ath12k_wmi_xxx() functions
Rameshkumar Sundaram (1):
wifi: ath12k: initialize RSSI dBm conversion event state
drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +-
drivers/net/wireless/ath/ath12k/wmi.c | 105 +++++++++++++++++++++++++++-----
drivers/net/wireless/ath/ath5k/base.c | 3 +-
3 files changed, 92 insertions(+), 18 deletions(-)
^ permalink raw reply
* [PATCH] wifi: iwlwifi: add retry loop for firmware reload on resume
From: Ashwin Gundarapu @ 2026-05-05 13:59 UTC (permalink / raw)
To: miriam.rachel.korenblit, johannes.berg; +Cc: linux-wireless, linux-kernel
From 48670d4341d2a9187e8368a2a929d155c4ffd003 Mon Sep 17 00:00:00 2001
From: Ashwin Gundarapu <linuxuser509@zohomail.in>
Date: Tue, 5 May 2026 19:12:48 +0530
Subject: [PATCH] wifi: iwlwifi: add retry loop for firmware reload on resume
After suspend, the PCIe link may not be fully ready when the driver
attempts to reload firmware. This causes iwlwifi to fail silently,
leaving users with no WiFi until reboot.
Add a retry loop that attempts firmware reload up to 3 times with
a 100ms delay between attempts, replacing the previous single attempt
that the code itself described as 'hope for the best here.'
---
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index dc99e7ac4726..2208b06d7e63 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1257,14 +1257,20 @@ static int _iwl_pci_resume(struct device
*device, bool restore)
if (restore || device_was_powered_off) {
trans->state = IWL_TRANS_NO_FW;
- /* Hope for the best here ... If one of those steps fails we
- * won't really know how to recover.
+ /* Retry firmware reload up to 3 times.
+ * The PCIe link may not be fully ready on the first attempt
+ * after resume, causing iwlwifi to fail silently.
*/
- iwl_pcie_prepare_card_hw(trans);
- iwl_trans_activate_nic(trans);
+ int retry;
+ for (retry = 0; retry < 3; retry++) {
+ iwl_pcie_prepare_card_hw(trans);
+ iwl_trans_activate_nic(trans);
+ if (trans->state != IWL_TRANS_NO_FW)
+ break;
+ msleep(100);
+ }
iwl_op_mode_device_powered_off(trans->op_mode);
}
-
/* In WOWLAN, let iwl_trans_pcie_d3_resume do the rest of the
work */
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
return 0;
base-commit: 26fd6bff2c050196005312d1d306889220952a99
prerequisite-patch-id: 039ce4200f5ab50b86e8ef1fea9d93294ae43517
--
2.43.0
^ permalink raw reply related
* [PATCH wireless] wifi: mac80211: use safe list iteration in radar detect work
From: Benjamin Berg @ 2026-05-05 13:15 UTC (permalink / raw)
To: linux-wireless; +Cc: Benjamin Berg
From: Benjamin Berg <benjamin.berg@intel.com>
The call to ieee80211_dfs_cac_cancel can cause the iterated chanctx to
be freed and removed from the list. Guard against this to avoid a
slab-use-after-free error.
Fixes: bca8bc0399ac ("wifi: mac80211: handle ieee80211_radar_detected() for MLO")
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
---
net/mac80211/util.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b093bc203c81..2529b01e2cd5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3700,11 +3700,11 @@ void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, radar_detected_work);
struct cfg80211_chan_def chandef;
- struct ieee80211_chanctx *ctx;
+ struct ieee80211_chanctx *ctx, *tmp;
lockdep_assert_wiphy(local->hw.wiphy);
- list_for_each_entry(ctx, &local->chanctx_list, list) {
+ list_for_each_entry_safe(ctx, tmp, &local->chanctx_list, list) {
if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
continue;
--
2.54.0
^ permalink raw reply related
* [PATCH wireless-next] wifi: mac80211: check stations are removed before MLD change
From: Johannes Berg @ 2026-05-05 13:17 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
If an interface changes to/from MLD, then all stations related
to it must have been removed first. This is just natural since
we go from having links to not (or vice versa), but not doing
so also causes crashes in debugfs since vif changing to/from
MLD removes the entire debugfs for the vif, including stations.
Delete all stations but warn in this case, other code should
be handling it, in effect fail fast rather than doing a double
free or use-after-free in debugfs.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
This basically makes sure that the bug I fixed in
https://lore.kernel.org/linux-wireless/20260505151533.c4e52deb06ad.Iafe56cec7de8512626169496b134bce3a6c17010@changeid/
is noticed quickly. I'll probably merge this only
after the fix lands in wireless-next via net/net-next.
---
net/mac80211/link.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index 93e290dd783f..e81dd02de12e 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -2,7 +2,7 @@
/*
* MLO link handling
*
- * Copyright (C) 2022-2025 Intel Corporation
+ * Copyright (C) 2022-2026 Intel Corporation
*/
#include <linux/slab.h>
#include <linux/kernel.h>
@@ -307,6 +307,9 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
if (old_links == new_links && dormant_links == sdata->vif.dormant_links)
return 0;
+ if (!old_links || !new_links)
+ WARN_ON(sta_info_flush(sdata, -1) > 0);
+
/* if there were no old links, need to clear the pointers to deflink */
if (!old_links)
rem |= BIT(0);
--
2.53.0
^ permalink raw reply related
* [PATCH wireless] wifi: mac80211: remove station if connection prep fails
From: Johannes Berg @ 2026-05-05 13:15 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, stable, Miriam Rachel Korenblit
From: Johannes Berg <johannes.berg@intel.com>
If connection preparation fails for MLO connections, then the
interface is completely reset to non-MLD. In this case, we must
not keep the station since it's related to the link of the vif
being removed. Delete an existing station. Any "new_sta" is
already being removed, so that doesn't need changes.
This fixes a use-after-free/double-free in debugfs if that's
enabled, because a vif going from MLD (and to MLD, but that's
not relevant here) recreates its entire debugfs.
Cc: stable@vger.kernel.org
Fixes: 81151ce462e5 ("wifi: mac80211: support MLO authentication/association with one link")
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/mlme.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 298ebff6bbf8..0a0f27836d57 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -9149,7 +9149,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
struct ieee80211_bss *bss = (void *)cbss->priv;
struct sta_info *new_sta = NULL;
struct ieee80211_link_data *link;
- bool have_sta = false;
+ struct sta_info *have_sta = NULL;
bool mlo;
int err;
u16 new_links;
@@ -9168,11 +9168,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
mlo = false;
}
- if (assoc) {
- rcu_read_lock();
+ if (assoc)
have_sta = sta_info_get(sdata, ap_mld_addr);
- rcu_read_unlock();
- }
if (mlo && !have_sta &&
WARN_ON(sdata->vif.valid_links || sdata->vif.active_links))
@@ -9336,6 +9333,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
out_release_chan:
ieee80211_link_release_channel(link);
out_err:
+ if (mlo && have_sta)
+ WARN_ON(__sta_info_destroy(have_sta));
ieee80211_vif_set_links(sdata, 0, 0);
return err;
}
--
2.53.0
^ permalink raw reply related
* [PATCH wireless-next 2/2] wifi: mac80211: explicitly disable FTM responder on AP stop
From: Johannes Berg @ 2026-05-05 13:12 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260505151241.285da8fbf7f4.I1b6922ca8d06d592356d7a5d190e6118fec1d5b5@changeid>
From: Johannes Berg <johannes.berg@intel.com>
When stopping the AP, explicitly disable FTM responder while
disabling beaconing.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/cfg.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0ebc58a768a4..0b1291ff7a2c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1990,6 +1990,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_link_data *link =
sdata_dereference(sdata->link[link_id], sdata);
struct ieee80211_bss_conf *link_conf = link->conf;
+ u64 changes = BSS_CHANGED_BEACON_ENABLED;
LIST_HEAD(keys);
lockdep_assert_wiphy(local->hw.wiphy);
@@ -2039,6 +2040,11 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
if (old_s1g_short_beacon)
kfree_rcu(old_s1g_short_beacon, rcu_head);
+ if (link_conf->ftm_responder) {
+ link_conf->ftm_responder = false;
+ changes |= BSS_CHANGED_FTM_RESPONDER;
+ }
+
kfree(link_conf->ftmr_params);
link_conf->ftmr_params = NULL;
@@ -2060,8 +2066,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.cfg.ssid_len = 0;
sdata->vif.cfg.s1g = false;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
- ieee80211_link_info_change_notify(sdata, link,
- BSS_CHANGED_BEACON_ENABLED);
+ ieee80211_link_info_change_notify(sdata, link, changes);
ieee80211_remove_link_keys(link, &keys);
if (!list_empty(&keys)) {
--
2.53.0
^ permalink raw reply related
* [PATCH wireless-next 1/2] wifi: iwlwifi: don't blindly start the responder upon BSS_CHANGED_FTM_RESPONDER
From: Johannes Berg @ 2026-05-05 13:12 UTC (permalink / raw)
To: linux-wireless; +Cc: Emmanuel Grumbach, Miriam Rachel Korenblit
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
mac80211 may just want to stop it, so check the ftm_responder boolean
before starting the responder.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 ++--
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 214e6d10081b..c256cbc6602e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -3144,7 +3144,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
iwl_mvm_mac_ctxt_beacon_changed(mvm, vif, &vif->bss_conf))
IWL_WARN(mvm, "Failed updating beacon data\n");
- if (changes & BSS_CHANGED_FTM_RESPONDER) {
+ if ((changes & BSS_CHANGED_FTM_RESPONDER) && bss_conf->ftm_responder) {
int ret = iwl_mvm_ftm_start_responder(mvm, vif, &vif->bss_conf);
if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index f1dbfeae20bc..6ea9a7c8da0c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022-2025 Intel Corporation
+ * Copyright (C) 2022-2026 Intel Corporation
*/
#include "mvm.h"
@@ -729,7 +729,7 @@ iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
IWL_WARN(mvm, "Failed updating beacon data\n");
/* FIXME: need to decide if we need FTM responder per link */
- if (changes & BSS_CHANGED_FTM_RESPONDER) {
+ if (changes & BSS_CHANGED_FTM_RESPONDER && link_conf->ftm_responder) {
int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf);
if (ret)
--
2.53.0
^ permalink raw reply related
* Re: [PATCH wireless-next v2 3/4] wifi: mac80211: add per-link PROBE_PEER support
From: Johannes Berg @ 2026-05-05 12:44 UTC (permalink / raw)
To: Priyansha Tiwari; +Cc: linux-wireless, quic_drohan
In-Reply-To: <20260417133124.3412752-4-pritiwa@qti.qualcomm.com>
On Fri, 2026-04-17 at 19:01 +0530, Priyansha Tiwari wrote:
>
> - u8 pad2;
> + u8 link_valid:1, link_id:4, pad2:3;
You don't need to pad bitfields.
> + if (sdata->vif.type == NL80211_IFTYPE_STATION ||
> + sdata->vif.type == NL80211_IFTYPE_P2P_CLIENT) {
Err ...
> + /* STA/P2P: userspace must NOT provide peer MAC, AP is implied. */
> + if (peer)
> + return -EINVAL;
That check belongs into cfg80211, not here?
> + if (!sdata->u.mgd.associated)
> + return -ENOTCONN;
maybe be consistent, cfg80211 returns -ENOLINK?
> + } else if (!peer) {
> + /* AP/GO: must have a peer MAC. */
> + return -EINVAL;
> }
>
> - qos = sta->sta.wme;
> + guard(rcu)();
>
> - if (ieee80211_vif_is_mld(&sdata->vif)) {
> - if (sta->sta.mlo) {
> - link_id = IEEE80211_LINK_UNSPECIFIED;
> - } else {
> - /*
> - * For non-MLO clients connected to an AP MLD, band
> - * information is not used; instead, sta->deflink is
> - * used to send packets.
> - */
> - link_id = sta->deflink.link_id;
> + if (sdata->vif.type == NL80211_IFTYPE_AP ||
> + sdata->vif.type == NL80211_IFTYPE_P2P_GO) {
Again, what?
And unrelated, maybe this would all be better as a switch statement?
> + sta = sta_info_get_bss(sdata, peer);
> + if (!sta)
> + return -ENOLINK;
>
> - conf = rcu_dereference(sdata->vif.link_conf[link_id]);
> + qos = sta->sta.wme;
>
> - if (unlikely(!conf)) {
> - ret = -ENOLINK;
> - goto unlock;
> + if (ieee80211_vif_is_mld(&sdata->vif)) {
> + if (sta->sta.mlo) {
> + link_id = IEEE80211_LINK_UNSPECIFIED;
> + } else {
> + /*
> + * For non-MLO clients connected to an AP MLD,
> + * use the link address for the client's link.
> + */
> + link_id = sta->deflink.link_id;
> + conf = rcu_dereference(sdata->vif.link_conf[link_id]);
> + if (unlikely(!conf))
> + return -ENOLINK;
> }
> + /* MLD transmissions must not rely on the band */
> + band = 0;
> + } else {
> + chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
> + if (WARN_ON(!chanctx_conf))
> + return -EINVAL;
> + band = chanctx_conf->def.chan->band;
> + link_id = 0;
> + }
> +
> + size = sizeof(*nullfunc);
> + fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
> + (qos ? IEEE80211_STYPE_QOS_NULLFUNC
> + : IEEE80211_STYPE_NULLFUNC) |
> + IEEE80211_FCTL_FROMDS);
> + if (!qos)
> + size -= 2;
> +
> + skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
> + if (!skb)
> + return -ENOMEM;
> +
> + skb->dev = dev;
> + skb_reserve(skb, local->hw.extra_tx_headroom);
> +
> + nullfunc = skb_put(skb, size);
> + memset(nullfunc, 0, size);
> + nullfunc->frame_control = fc;
> +
> + memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
> + if (ieee80211_vif_is_mld(&sdata->vif) && !sta->sta.mlo) {
> + memcpy(nullfunc->addr2, conf->addr, ETH_ALEN);
> + memcpy(nullfunc->addr3, conf->addr, ETH_ALEN);
> + } else {
> + memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
> + memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
> + }
> +
> + info = IEEE80211_SKB_CB(skb);
> + info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
> + IEEE80211_TX_INTFL_NL80211_FRAME_TX;
> + info->band = band;
> + info->control.flags |= u32_encode_bits(link_id,
> + IEEE80211_TX_CTRL_MLO_LINK);
> +
> + skb_set_queue_mapping(skb, IEEE80211_AC_VO);
> + skb->priority = 7;
> + if (qos)
> + nullfunc->qos_ctrl = cpu_to_le16(7);
> +
> + ret = ieee80211_attach_ack_skb(local, skb, cookie, GFP_ATOMIC);
> + if (ret) {
> + kfree_skb(skb);
> + return ret;
> }
> - /* MLD transmissions must not rely on the band */
> +
> + local_bh_disable();
> + ieee80211_xmit(sdata, sta, skb);
> + local_bh_enable();
> +
> + return 0;
> + }
> +
> + /*
> + * STA/P2P: send a nullfunc to probe the AP/peer.
> + * For MLO, let the driver/firmware decide which link to use.
> + */
> + if (ieee80211_vif_is_mld(&sdata->vif)) {
> + link_id = IEEE80211_LINK_UNSPECIFIED;
> + peer_addr = sdata->vif.cfg.ap_addr;
> + src_addr = sdata->vif.addr;
> band = 0;
> + sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
> } else {
> - chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
> - if (WARN_ON(!chanctx_conf)) {
> - ret = -EINVAL;
> - goto unlock;
> - }
> - band = chanctx_conf->def.chan->band;
> link_id = 0;
> + conf = rcu_dereference(sdata->vif.link_conf[0]);
> + if (!conf)
> + return -ENOLINK;
> + band = conf->chanreq.oper.chan->band;
> + peer_addr = conf->bssid;
> + src_addr = conf->addr;
> + sta = sta_info_get_bss(sdata, peer_addr);
> }
I really don't like the layout and code duplication here. Off-hand I'd
think the duplication isn't needed, but otherwise perhaps it should be
in separate functions or so.
johannes
^ permalink raw reply
* Re: [PATCH wireless-next v2 2/4] wifi: cfg80211/nl80211: rename to probe_peer(), extend probe status, and update in-tree users
From: Johannes Berg @ 2026-05-05 12:39 UTC (permalink / raw)
To: Priyansha Tiwari; +Cc: linux-wireless, quic_drohan
In-Reply-To: <20260417133124.3412752-3-pritiwa@qti.qualcomm.com>
Your subject lines are way too long, you really don't need to spell out
everything, and if there's a list of things, probably better to break
into multiple patches.
> Update in-tree users (wil6210, mwifiex) and mac80211 so the tree continues
> to build after this change.
That's also pretty obvious.
> mac80211 switches cfg80211_ops to .probe_peer and passes link_id = -1
> at the probe status callsite to preserve existing behavior.
>
> This change is otherwise behavior-neutral, per-link STA reporting will
> follow in a subsequent patch.
I think you really should split this differently - perhaps first an
internal API change, that just does all the renaming, then the actual
logic change including the nl80211 API, and finally the mac80211
implementation?
johannes
^ permalink raw reply
* Re: [PATCH wireless-next v2 1/4] wifi: nl80211: rename PROBE_CLIENT to PROBE_PEER and add STA-side probing support
From: Johannes Berg @ 2026-05-05 12:37 UTC (permalink / raw)
To: Priyansha Tiwari; +Cc: linux-wireless, quic_drohan
In-Reply-To: <20260417133124.3412752-2-pritiwa@qti.qualcomm.com>
On Fri, 2026-04-17 at 19:01 +0530, Priyansha Tiwari wrote:
> From: Priyansha Tiwari <priyansha.tiwari@oss.qualcomm.com>
>
> Rename NL80211_CMD_PROBE_CLIENT to NL80211_CMD_PROBE_PEER to generalize
> peer probing, AP/GO continue to probe associated STAs (legacy PROBE_CLIENT
> behavior) while, when the driver advertises NL80211_EXT_FEATURE_PROBE_AP,
> a STA/P2P-client may probe its currently associated AP to quickly verify link
> responsiveness without waiting for traffic or long timeouts.
>
> Userspace and cfg80211 rely on this feature flag to determine whether
> STA-mode probing is supported. The command returns a cookie in the direct
> reply and delivers an event that indicates ACK (and, if available,
> signed-dBm ACK_SIGNAL).
>
> For MLO connections the event carries MLO_LINK_ID identifying the link on
> which the probe was ACKed. In AP/GO mode the peer MAC is required, while in
> STA/P2P-client mode the MAC is omitted (AP implied).
> NL80211_CMD_PROBE_CLIENT is retained as a compatibility alias.
This doesn't actually do what the subject says. You also don't need to
describe the existing behaviour like MLO stuff.
johannes
^ 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