* [PATCH wireless-next v5 0/2] wifi: cfg80211/mac80211: add support to handle incumbent signal detected event
@ 2026-02-16 3:20 Amith A
2026-02-16 3:20 ` [PATCH wireless-next v5 1/2] wifi: cfg80211: add support to handle incumbent signal detected event from mac80211/driver Amith A
2026-02-16 3:20 ` [PATCH wireless-next v5 2/2] wifi: mac80211_hwsim: add incumbent signal interference detection support Amith A
0 siblings, 2 replies; 4+ messages in thread
From: Amith A @ 2026-02-16 3:20 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, amith.a
This patch series adds support to handle incumbent signal interference
detected event in 6 GHz band. When an incumbent signal is detected by an
AP/mesh interface operating in 6 GHz band, the AP/mesh is expected to
vacate the channels affected by it.
Driver is expected to call the newly introduced API with required
information to notify the interference detection. This information will be
ultimately sent to user space via NL802111 command. User space is expected
to process it and take further action - vacate the channel, or reduce the
bandwidth.
Aditya Kumar Singh (1):
wifi: mac80211_hwsim: add incumbent signal interference detection
support
Hari Chandrakanthan (1):
wifi: cfg80211: add support to handle incumbent signal detected event
from mac80211/driver
---
Changes in v5:
- Made chandef const in cfg80211_incumbent_signal_notify()
- Removed mac80211 wrapper ieee80211_incumbent_signal_detected().
Driver/hwsim calls cfg80211 notify directly.
- In mac80211_hwsim, switched debugfs to custom fops with .write that
accepts “freq_mhz bitmap”. Now 6 GHz chanctx is selected by primary
20 MHz center.
Changes in v4:
- Restored gfp_t in cfg80211_incumbent_signal_notify().
- Dropped incumbt_sig_intf_bmap from ieee80211_chanctx_conf and passed
bitmap directly.
- Updated trace/call path: api_incumbent_signal_detected() to take bitmap
- Simplified hwsim: removed helper struct.
Changes in v3:
- Removed the workqueue mechanism in ieee80211_incumbent_signal_detected(),
exported the cfg80211_ function that sends the NL80211 command and called
it from ieee80211_incumbent_signal_detected() directly.
- Renamed nl80211_incumbent_signal_notify() to
cfg80211_incumbent_signal_notify() and removed the gfp argument from it.
Changes in v2:
- Updated the kernel doc of NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP
to include details of how it interacts with puncturing.
- Rebased on ToT
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 80 +++++++++++++++++++
drivers/net/wireless/virtual/mac80211_hwsim.h | 2 +
include/net/cfg80211.h | 23 ++++++
include/uapi/linux/nl80211.h | 19 +++++
net/wireless/nl80211.c | 40 ++++++++++
net/wireless/trace.h | 19 +++++
6 files changed, 183 insertions(+)
base-commit: 333225e1e9ead7b06e5363389403bdac72ba3046
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH wireless-next v5 1/2] wifi: cfg80211: add support to handle incumbent signal detected event from mac80211/driver
2026-02-16 3:20 [PATCH wireless-next v5 0/2] wifi: cfg80211/mac80211: add support to handle incumbent signal detected event Amith A
@ 2026-02-16 3:20 ` Amith A
2026-02-16 3:20 ` [PATCH wireless-next v5 2/2] wifi: mac80211_hwsim: add incumbent signal interference detection support Amith A
1 sibling, 0 replies; 4+ messages in thread
From: Amith A @ 2026-02-16 3:20 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, amith.a, Hari Chandrakanthan
From: Hari Chandrakanthan <quic_haric@quicinc.com>
When any incumbent signal is detected by an AP/mesh interface operating
in 6 GHz band, FCC mandates the AP/mesh to vacate the channels affected
by it [1].
Add a new API cfg80211_incumbent_signal_notify() that can be used
by mac80211 or drivers to notify the higher layers about the signal
interference event with the interference bitmap in which each bit
denotes the affected 20 MHz in the operating channel.
Add support for the new nl80211 event and nl80211 attribute as well to
notify userspace on the details about the interference event. Userspace is
expected to process it and take further action - vacate the channel, or
reduce the bandwidth.
[1] - https://apps.fcc.gov/kdb/GetAttachment.html?id=nXQiRC%2B4mfiA54Zha%2BrW4Q%3D%3D&desc=987594%20D02%20U-NII%206%20GHz%20EMC%20Measurement%20v03&tracking_number=277034
Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
Signed-off-by: Amith A <amith.a@oss.qualcomm.com>
---
include/net/cfg80211.h | 23 +++++++++++++++++++++
include/uapi/linux/nl80211.h | 19 +++++++++++++++++
net/wireless/nl80211.c | 40 ++++++++++++++++++++++++++++++++++++
net/wireless/trace.h | 19 +++++++++++++++++
4 files changed, 101 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fc01de19c798..2311d852e19e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -10472,4 +10472,27 @@ cfg80211_s1g_get_primary_sibling(struct wiphy *wiphy,
return ieee80211_get_channel_khz(wiphy, sibling_1mhz_khz);
}
+
+/**
+ * cfg80211_incumbent_signal_notify - Notify userspace of incumbent signal detection
+ * @wiphy: the wiphy to use
+ * @chandef: channel definition in which the interference was detected
+ * @signal_interference_bitmap: bitmap indicating interference across 20 MHz segments
+ * @gfp: allocation context for message creation and multicast; pass GFP_ATOMIC
+ * if called from atomic context (e.g. firmware event handler), otherwise
+ * GFP_KERNEL
+ *
+ * Use this function to notify userspace when an incumbent signal is detected on
+ * the operating channel in the 6 GHz band. The notification includes the
+ * current channel definition and a bitmap representing interference across
+ * the operating bandwidth. Each bit in the bitmap corresponds to a 20 MHz
+ * segment, with the lowest bit representing the lowest frequency segment.
+ * Punctured sub-channels are included in the bitmap structure but are always
+ * set to zero since interference detection is not performed on them.
+ */
+void cfg80211_incumbent_signal_notify(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef,
+ u32 signal_interference_bitmap,
+ gfp_t gfp);
+
#endif /* __NET_CFG80211_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index b63f71850906..b53e2d78c7bb 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1361,6 +1361,12 @@
* user space that the NAN new cluster has been joined. The cluster ID is
* indicated by %NL80211_ATTR_MAC.
*
+ * @NL80211_CMD_INCUMBENT_SIGNAL_DETECT: Once any incumbent signal is detected
+ * on the operating channel in 6 GHz band, userspace is notified with the
+ * signal interference bitmap using
+ * %NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP. The current channel
+ * definition is also sent.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1624,6 +1630,8 @@ enum nl80211_commands {
NL80211_CMD_NAN_NEXT_DW_NOTIFICATION,
NL80211_CMD_NAN_CLUSTER_JOINED,
+ NL80211_CMD_INCUMBENT_SIGNAL_DETECT,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -2984,6 +2992,15 @@ enum nl80211_commands {
* this feature during association. This is a flag attribute.
* Currently only supported in mac80211 drivers.
*
+ * @NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP: u32 attribute specifying
+ * the signal interference bitmap detected on the operating bandwidth for
+ * %NL80211_CMD_INCUMBENT_SIGNAL_DETECT. Each bit represents a 20 MHz
+ * segment, lowest bit corresponds to the lowest 20 MHz segment, in the
+ * operating bandwidth where the interference is detected. Punctured
+ * sub-channels are included in the bitmap structure; however, since
+ * interference detection is not performed on these sub-channels, their
+ * corresponding bits are consistently set to zero.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3557,6 +3574,8 @@ enum nl80211_attrs {
NL80211_ATTR_UHR_CAPABILITY,
NL80211_ATTR_DISABLE_UHR,
+ NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6e58b238a1f8..6de846ae087f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -21129,6 +21129,46 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
}
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
+void cfg80211_incumbent_signal_notify(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef,
+ u32 signal_interference_bitmap,
+ gfp_t gfp)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ struct sk_buff *msg;
+ void *hdr;
+
+ trace_cfg80211_incumbent_signal_notify(wiphy, chandef, signal_interference_bitmap);
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_INCUMBENT_SIGNAL_DETECT);
+ if (!hdr)
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
+ goto nla_put_failure;
+
+ if (nl80211_send_chandef(msg, chandef))
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
+ signal_interference_bitmap))
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
+ return;
+
+nla_put_failure:
+ nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_incumbent_signal_notify);
+
void cfg80211_ch_switch_started_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
unsigned int link_id, u8 count,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 643ccf4f0227..352a57d8b968 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -4225,6 +4225,25 @@ TRACE_EVENT(cfg80211_nan_cluster_joined,
WDEV_PR_ARG, __entry->cluster_id,
__entry->new_cluster ? " [new]" : "")
);
+
+TRACE_EVENT(cfg80211_incumbent_signal_notify,
+ TP_PROTO(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef,
+ u32 signal_interference_bitmap),
+ TP_ARGS(wiphy, chandef, signal_interference_bitmap),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ CHAN_DEF_ENTRY
+ __field(u32, signal_interference_bitmap)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ CHAN_DEF_ASSIGN(chandef);
+ __entry->signal_interference_bitmap = signal_interference_bitmap;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", signal_interference_bitmap=0x%x",
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->signal_interference_bitmap)
+);
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH wireless-next v5 2/2] wifi: mac80211_hwsim: add incumbent signal interference detection support
2026-02-16 3:20 [PATCH wireless-next v5 0/2] wifi: cfg80211/mac80211: add support to handle incumbent signal detected event Amith A
2026-02-16 3:20 ` [PATCH wireless-next v5 1/2] wifi: cfg80211: add support to handle incumbent signal detected event from mac80211/driver Amith A
@ 2026-02-16 3:20 ` Amith A
2026-03-02 8:22 ` Johannes Berg
1 sibling, 1 reply; 4+ messages in thread
From: Amith A @ 2026-02-16 3:20 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, amith.a, Aditya Kumar Singh
From: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Add a debugfs ‘simulate_incumbent_signal_interference’ with custom
file_operations and a .write that accepts “<freq_mhz> <bitmap>”. The
handler selects the 6 GHz chanctx whose primary 20 MHz center matches
<freq_mhz> and reports the event via cfg80211_incumbent_signal_notify().
The bitmap marks affected 20 MHz segments within the current chandef
(lowest bit = lowest segment)
Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Signed-off-by: Amith A <amith.a@oss.qualcomm.com>
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 80 +++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 4d9f5f87e814..2a61997e8312 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -36,6 +36,9 @@
#include <linux/virtio.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
+#include <linux/uaccess.h>
+#include <linux/kstrtox.h>
+#include <linux/string.h>
#include "mac80211_hwsim.h"
#define WARN_QUEUE 100
@@ -1164,6 +1167,80 @@ static int hwsim_write_simulate_radar(void *dat, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(hwsim_simulate_radar, NULL,
hwsim_write_simulate_radar, "%llu\n");
+struct hwsim_chanctx_iter_arg {
+ struct ieee80211_chanctx_conf **out;
+ u32 freq_mhz;
+};
+
+static void hwsim_6ghz_chanctx_iter(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf,
+ void *data)
+{
+ struct hwsim_chanctx_iter_arg *arg = data;
+
+ if (conf->def.chan &&
+ conf->def.chan->band == NL80211_BAND_6GHZ &&
+ conf->def.chan->center_freq == arg->freq_mhz)
+ *arg->out = conf;
+}
+
+static ssize_t hwsim_simulate_incumbent_signal_write(struct file *file,
+ const char __user *ubuf,
+ size_t len, loff_t *ppos)
+{
+ struct mac80211_hwsim_data *data = file->private_data;
+ struct ieee80211_chanctx_conf *chanctx_conf = NULL;
+ struct hwsim_chanctx_iter_arg arg;
+ u32 freq_mhz, bitmap;
+ char *sptr, *token;
+ char buf[64];
+
+ if (!len || len >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(buf, ubuf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+
+ strim(buf);
+ sptr = buf;
+ token = strsep(&sptr, " \t");
+ if (!token)
+ return -EINVAL;
+ if (kstrtou32(token, 0, &freq_mhz))
+ return -EINVAL;
+
+ token = strsep(&sptr, " \t");
+ if (!token)
+ return -EINVAL;
+ if (kstrtou32(token, 0, &bitmap))
+ return -EINVAL;
+
+ if (!freq_mhz)
+ return -EINVAL;
+
+ arg.out = &chanctx_conf;
+ arg.freq_mhz = freq_mhz;
+ ieee80211_iter_chan_contexts_atomic(data->hw,
+ hwsim_6ghz_chanctx_iter,
+ &arg);
+
+ if (!chanctx_conf)
+ return -EINVAL;
+
+ cfg80211_incumbent_signal_notify(data->hw->wiphy,
+ &chanctx_conf->def,
+ bitmap,
+ GFP_KERNEL);
+
+ return len;
+}
+
+static const struct file_operations hwsim_simulate_incumbent_signal_fops = {
+ .open = simple_open,
+ .write = hwsim_simulate_incumbent_signal_write,
+};
+
static int hwsim_fops_group_read(void *dat, u64 *val)
{
struct mac80211_hwsim_data *data = dat;
@@ -5832,6 +5909,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
debugfs_create_file("dfs_simulate_radar", 0222,
data->debugfs,
data, &hwsim_simulate_radar);
+ debugfs_create_file("simulate_incumbent_signal_interference", 0200,
+ data->debugfs,
+ data, &hwsim_simulate_incumbent_signal_fops);
if (param->pmsr_capa) {
data->pmsr_capa = *param->pmsr_capa;
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH wireless-next v5 2/2] wifi: mac80211_hwsim: add incumbent signal interference detection support
2026-02-16 3:20 ` [PATCH wireless-next v5 2/2] wifi: mac80211_hwsim: add incumbent signal interference detection support Amith A
@ 2026-03-02 8:22 ` Johannes Berg
0 siblings, 0 replies; 4+ messages in thread
From: Johannes Berg @ 2026-03-02 8:22 UTC (permalink / raw)
To: Amith A; +Cc: linux-wireless, Aditya Kumar Singh
Hi,
FWIW, I'm applying patch 1 of this.
This didn't apply now due to some overlap with the radar patches, but
that's not really the issue.
> +static ssize_t hwsim_simulate_incumbent_signal_write(struct file *file,
> + const char __user *ubuf,
> + size_t len, loff_t *ppos)
> +{
> + struct mac80211_hwsim_data *data = file->private_data;
> + struct ieee80211_chanctx_conf *chanctx_conf = NULL;
> + struct hwsim_chanctx_iter_arg arg;
> + u32 freq_mhz, bitmap;
> + char *sptr, *token;
> + char buf[64];
> +
> + if (!len || len >= sizeof(buf))
> + return -EINVAL;
> +
> + if (copy_from_user(buf, ubuf, len))
> + return -EFAULT;
> + buf[len] = '\0';
If len == 64, then you have a bug here. Need to further restrict the
length check, e.g. by using sizeof(buf)-1 above.
> + strim(buf);
> + sptr = buf;
> + token = strsep(&sptr, " \t");
> + if (!token)
> + return -EINVAL;
> + if (kstrtou32(token, 0, &freq_mhz))
> + return -EINVAL;
> +
> + token = strsep(&sptr, " \t");
> + if (!token)
> + return -EINVAL;
> + if (kstrtou32(token, 0, &bitmap))
> + return -EINVAL;
> +
> + if (!freq_mhz)
> + return -EINVAL;
> +
> + arg.out = &chanctx_conf;
> + arg.freq_mhz = freq_mhz;
> + ieee80211_iter_chan_contexts_atomic(data->hw,
> + hwsim_6ghz_chanctx_iter,
> + &arg);
> +
> + if (!chanctx_conf)
> + return -EINVAL;
This seems overly complex? You can init "... arg = {}" and then you
don't need the freq_mhz or chanctx_conf variables, just use the "arg."
versions directly for all of the code.
I also think it might be nicer overall to use sscanf()? I don't really
think there's any reason for allowing space and \t, after all this is
specific userspace for testing, it can be made to write the precise
format the kernel expects.
johannes
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-03-02 8:22 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-16 3:20 [PATCH wireless-next v5 0/2] wifi: cfg80211/mac80211: add support to handle incumbent signal detected event Amith A
2026-02-16 3:20 ` [PATCH wireless-next v5 1/2] wifi: cfg80211: add support to handle incumbent signal detected event from mac80211/driver Amith A
2026-02-16 3:20 ` [PATCH wireless-next v5 2/2] wifi: mac80211_hwsim: add incumbent signal interference detection support Amith A
2026-03-02 8:22 ` Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox