* [PATCH wireless-next v5 01/13] wifi: cfg80211: restrict LMR feedback check to TB and non-TB ranging
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 02/13] wifi: cfg80211: Add MAC address filter to remain_on_channel Peddolla Harshavardhan Reddy
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
The lmr_feedback field is only applicable to TB and non-TB ranging.
Currently, pmsr_parse_ftm() enforces lmr_feedback for all RSTA
requests, incorrectly rejecting valid EDCA-based RSTA requests.
Fix this by limiting the lmr_feedback requirement to TB and non-TB
ranging only.
Fixes: 853800c746d3 ("wifi: nl80211/cfg80211: support operating as RSTA in PMSR FTM request")
Co-developed-by: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
Signed-off-by: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
net/wireless/pmsr.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 4c8ea0583f94..afc0e3f931ec 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -195,7 +195,9 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
return -EOPNOTSUPP;
}
- if (out->ftm.rsta && !out->ftm.lmr_feedback) {
+ if (out->ftm.rsta &&
+ (out->ftm.non_trigger_based || out->ftm.trigger_based) &&
+ !out->ftm.lmr_feedback) {
NL_SET_ERR_MSG_ATTR(info->extack,
tb[NL80211_PMSR_FTM_REQ_ATTR_RSTA],
"FTM: RSTA set without LMR feedback");
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 02/13] wifi: cfg80211: Add MAC address filter to remain_on_channel
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 01/13] wifi: cfg80211: restrict LMR feedback check to TB and non-TB ranging Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 03/13] wifi: cfg80211/mac80211: Add NL80211_IFTYPE_PD for PD PASN and PMSR operations Peddolla Harshavardhan Reddy
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Currently the remain_on_channel operation does not support
filtering incoming frames by destination MAC address. This
prevents use cases such as PASN authentication in the
responder side that need to receive frames addressed to a
specific MAC during the off-channel period.
Add an rx_addr parameter to the remain_on_channel operation
callback and propagate it through the call chain from nl80211
to driver implementations. Introduce the extended feature
NL80211_EXT_FEATURE_ROC_ADDR_FILTER as a capability gate so
that cfg80211 rejects the request if the driver does not
advertise support for address filtering. Extract the address
from the NL80211_ATTR_MAC attribute when provided in the
netlink message and update the tracing infrastructure to
include the address in remain_on_channel trace events. The
rx_addr parameter is optional and can be NULL, maintaining
backward compatibility with existing drivers.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 ++-
drivers/net/wireless/ath/wil6210/cfg80211.c | 3 ++-
.../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 4 +++-
.../net/wireless/broadcom/brcm80211/brcmfmac/p2p.h | 3 ++-
drivers/net/wireless/marvell/mwifiex/cfg80211.c | 3 ++-
drivers/net/wireless/microchip/wilc1000/cfg80211.c | 3 ++-
include/net/cfg80211.h | 2 +-
include/uapi/linux/nl80211.h | 11 ++++++++++-
net/mac80211/ieee80211_i.h | 3 ++-
net/mac80211/offchannel.c | 3 ++-
net/wireless/nl80211.c | 11 ++++++++++-
net/wireless/rdev-ops.h | 7 ++++---
net/wireless/trace.h | 12 ++++++++----
13 files changed, 50 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 739a24a6ad67..cc0f2c45fc3a 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004-2011 Atheros Communications Inc.
* Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -3033,7 +3034,7 @@ static int ath6kl_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
unsigned int duration,
- u64 *cookie)
+ u64 *cookie, const u8 *rx_addr)
{
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
struct ath6kl *ar = ath6kl_priv(vif->ndev);
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 3d6e5aad48b1..d6ef92cfcbaf 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/etherdevice.h>
@@ -1734,7 +1735,7 @@ static int wil_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
unsigned int duration,
- u64 *cookie)
+ u64 *cookie, const u8 *rx_addr)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
int rc;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index e1752a513c73..92c16a317328 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -970,10 +970,12 @@ brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
* @channel: channel to stay on.
* @duration: time in ms to remain on channel.
* @cookie: cookie.
+ * @rx_addr: Address to match against the destination of received frames
*/
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *channel,
- unsigned int duration, u64 *cookie)
+ unsigned int duration, u64 *cookie,
+ const u8 *rx_addr)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_p2p_info *p2p = &cfg->p2p;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
index d3137ebd7158..9f3f01ade2b7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
@@ -157,7 +157,8 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
struct brcmf_cfg80211_vif *vif);
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *channel,
- unsigned int duration, u64 *cookie);
+ unsigned int duration, u64 *cookie,
+ const u8 *rx_addr);
int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
const struct brcmf_event_msg *e,
void *data);
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index c9a651bdf882..c9daf893472f 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -304,7 +304,8 @@ static int
mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- unsigned int duration, u64 *cookie)
+ unsigned int duration, u64 *cookie,
+ const u8 *rx_addr)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
int ret;
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
index 3a774cc44b26..6654fce4ded8 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
@@ -1100,7 +1100,8 @@ static void wilc_wfi_remain_on_channel_expired(struct wilc_vif *vif, u64 cookie)
static int remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- unsigned int duration, u64 *cookie)
+ unsigned int duration, u64 *cookie,
+ const u8 *rx_addr)
{
int ret = 0;
struct wilc_vif *vif = netdev_priv(wdev->netdev);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9d3639ff9c28..25847230428e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5267,7 +5267,7 @@ struct cfg80211_ops {
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
unsigned int duration,
- u64 *cookie);
+ u64 *cookie, const u8 *rx_addr);
int (*cancel_remain_on_channel)(struct wiphy *wiphy,
struct wireless_dev *wdev,
u64 cookie);
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 3d55bf4be36f..7f3d6d60b8ea 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -729,7 +729,9 @@
* to remain on the channel. This command is also used as an event to
* notify when the requested duration starts (it may take a while for the
* driver to schedule this time due to other concurrent needs for the
- * radio).
+ * radio). An optional attribute %NL80211_ATTR_MAC can be used to filter
+ * incoming frames during remain-on-channel, such that frames
+ * addressed to the specified destination MAC are reported.
* When called, this operation returns a cookie (%NL80211_ATTR_COOKIE)
* that will be included with any events pertaining to this request;
* the cookie is also used to cancel the request.
@@ -7029,6 +7031,12 @@ enum nl80211_feature_flags {
* (NL80211_CMD_AUTHENTICATE) in non-AP STA mode, as specified in
* "IEEE P802.11bi/D4.0, 12.16.5".
*
+ * @NL80211_EXT_FEATURE_ROC_ADDR_FILTER: Driver supports MAC address
+ * filtering during remain-on-channel. When %NL80211_ATTR_MAC is
+ * provided with %NL80211_CMD_REMAIN_ON_CHANNEL, the driver will
+ * forward frames with a matching MAC address to userspace during
+ * the off-channel period.
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -7108,6 +7116,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_EPPKE,
NL80211_EXT_FEATURE_ASSOC_FRAME_ENCRYPTION,
NL80211_EXT_FEATURE_IEEE8021X_AUTH,
+ NL80211_EXT_FEATURE_ROC_ADDR_FILTER,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 2a693406294b..fca9852bff3b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2093,7 +2093,8 @@ void ieee80211_roc_purge(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
int ieee80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- unsigned int duration, u64 *cookie);
+ unsigned int duration, u64 *cookie,
+ const u8 *rx_addr);
int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
struct wireless_dev *wdev, u64 cookie);
int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index f60f6a58948b..5f398d38d1c9 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -706,7 +706,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
int ieee80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- unsigned int duration, u64 *cookie)
+ unsigned int duration, u64 *cookie,
+ const u8 *rx_addr)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
struct ieee80211_local *local = sdata->local;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f334cdef8958..541da67fafe1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14066,6 +14066,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
unsigned int link_id = nl80211_link_id(info->attrs);
struct wireless_dev *wdev = info->user_ptr[1];
struct cfg80211_chan_def chandef;
+ const u8 *rx_addr = NULL;
struct sk_buff *msg;
void *hdr;
u64 cookie;
@@ -14078,6 +14079,14 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
+ if (info->attrs[NL80211_ATTR_MAC])
+ rx_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+
+ if (rx_addr &&
+ !wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_ROC_ADDR_FILTER))
+ return -EOPNOTSUPP;
+
if (!rdev->ops->remain_on_channel ||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
return -EOPNOTSUPP;
@@ -14125,7 +14134,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
}
err = rdev_remain_on_channel(rdev, wdev, chandef.chan,
- duration, &cookie);
+ duration, &cookie, rx_addr);
if (err)
goto free_msg;
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index bba239a068f6..d97d5c08d135 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -736,12 +736,13 @@ static inline int
rdev_remain_on_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- unsigned int duration, u64 *cookie)
+ unsigned int duration, u64 *cookie, const u8 *rx_addr)
{
int ret;
- trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration);
+ trace_rdev_remain_on_channel(&rdev->wiphy, wdev, chan, duration,
+ rx_addr);
ret = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
- duration, cookie);
+ duration, cookie, rx_addr);
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
return ret;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index eb5bedf9c92a..938fea1fe9d8 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2155,22 +2155,26 @@ DEFINE_EVENT(rdev_pmksa, rdev_del_pmksa,
TRACE_EVENT(rdev_remain_on_channel,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- unsigned int duration),
- TP_ARGS(wiphy, wdev, chan, duration),
+ unsigned int duration, const u8 *rx_addr),
+ TP_ARGS(wiphy, wdev, chan, duration, rx_addr),
TP_STRUCT__entry(
WIPHY_ENTRY
WDEV_ENTRY
CHAN_ENTRY
__field(unsigned int, duration)
+ MAC_ENTRY(rx_addr)
),
TP_fast_assign(
WIPHY_ASSIGN;
WDEV_ASSIGN;
CHAN_ASSIGN(chan);
__entry->duration = duration;
+ MAC_ASSIGN(rx_addr, rx_addr);
),
- TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", duration: %u",
- WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->duration)
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT
+ ", duration: %u, %pM",
+ WIPHY_PR_ARG, WDEV_PR_ARG, CHAN_PR_ARG, __entry->duration,
+ __entry->rx_addr)
);
TRACE_EVENT(rdev_return_int_cookie,
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 03/13] wifi: cfg80211/mac80211: Add NL80211_IFTYPE_PD for PD PASN and PMSR operations
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 01/13] wifi: cfg80211: restrict LMR feedback check to TB and non-TB ranging Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 02/13] wifi: cfg80211: Add MAC address filter to remain_on_channel Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 04/13] wifi: cfg80211: add start/stop proximity detection commands Peddolla Harshavardhan Reddy
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Add a new wdev-only interface type NL80211_IFTYPE_PD to support
Proximity Detection (PD) operations such as PASN and peer measurement
operations. This interface type operates without a netdev, similar to
P2P_DEVICE and NAN interfaces.
Implement support across cfg80211 and mac80211 layers with PD-specific
checks gated by the NL80211_EXT_FEATURE_SECURE_RTT feature flag,
management frame registration and transmission capabilities, and proper
channel context handling where PD interfaces are excluded from bandwidth
calculations. Update mac80211 to recognize the new interface type in the
relevant paths for this management-only interface.
PD discovery can be performed on any available interface, such as
NL80211_IFTYPE_STATION.
If PD/PMSR uses the MAC address of an existing interface type, such as
NL80211_IFTYPE_STATION, then pairing and measurement shall use that
same interface. If PD/PMSR uses a different MAC address, such as a
random MAC address, then pairing and measurement can be performed on a
new NL80211_IFTYPE_PD interface created with that random MAC address.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/uapi/linux/nl80211.h | 2 ++
net/mac80211/cfg.c | 2 ++
net/mac80211/chan.c | 2 ++
net/mac80211/iface.c | 6 +++++-
net/mac80211/offchannel.c | 1 +
net/mac80211/rx.c | 6 ++++++
net/mac80211/util.c | 1 +
net/wireless/chan.c | 2 ++
net/wireless/core.c | 1 +
net/wireless/mlme.c | 1 +
net/wireless/nl80211.c | 27 +++++++++++++++++++++++++--
net/wireless/reg.c | 3 +++
net/wireless/util.c | 4 +++-
13 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7f3d6d60b8ea..7fb77091f863 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3831,6 +3831,7 @@ enum nl80211_attrs {
* @NL80211_IFTYPE_NAN_DATA: NAN data interface type (netdev); NAN data
* interfaces can only be brought up (IFF_UP) when a NAN interface
* already exists and NAN has been started (using %NL80211_CMD_START_NAN).
+ * @NL80211_IFTYPE_PD: PD device interface type (not a netdev)
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
* @NUM_NL80211_IFTYPES: number of defined interface types
*
@@ -3853,6 +3854,7 @@ enum nl80211_iftype {
NL80211_IFTYPE_OCB,
NL80211_IFTYPE_NAN,
NL80211_IFTYPE_NAN_DATA,
+ NL80211_IFTYPE_PD,
/* keep last */
NUM_NL80211_IFTYPES,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7b77d57c9f96..f984e3cbe3e8 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -716,6 +716,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_PD:
case NL80211_IFTYPE_UNSPECIFIED:
case NUM_NL80211_IFTYPES:
case NL80211_IFTYPE_P2P_CLIENT:
@@ -3335,6 +3336,7 @@ static int ieee80211_scan(struct wiphy *wiphy,
}
break;
case NL80211_IFTYPE_NAN:
+ case NL80211_IFTYPE_PD:
default:
return -EOPNOTSUPP;
}
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index fda692316f08..590f2511de53 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -551,6 +551,7 @@ ieee80211_get_width_of_link(struct ieee80211_link_data *link)
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_NAN_DATA:
+ case NL80211_IFTYPE_PD:
WARN_ON_ONCE(1);
break;
}
@@ -1546,6 +1547,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_NAN_DATA:
+ case NL80211_IFTYPE_PD:
case NUM_NL80211_IFTYPES:
WARN_ON(1);
break;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 95b779c4d627..87773022fe2b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1400,6 +1400,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_NAN:
+ case NL80211_IFTYPE_PD:
/* no special treatment */
break;
case NL80211_IFTYPE_NAN_DATA:
@@ -1532,7 +1533,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
FIF_PROBE_REQ);
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
- sdata->vif.type != NL80211_IFTYPE_NAN)
+ sdata->vif.type != NL80211_IFTYPE_NAN &&
+ sdata->vif.type != NL80211_IFTYPE_PD)
changed |= ieee80211_reset_erp_info(sdata);
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
changed);
@@ -1548,6 +1550,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
break;
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_NAN:
+ case NL80211_IFTYPE_PD:
break;
default:
/* not reached */
@@ -1988,6 +1991,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.bssid = sdata->vif.addr;
break;
case NL80211_IFTYPE_NAN_DATA:
+ case NL80211_IFTYPE_PD:
break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_WDS:
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 5f398d38d1c9..a2dda1e0ab3c 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -895,6 +895,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
}
break;
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_PD:
need_offchan = true;
break;
case NL80211_IFTYPE_NAN:
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3e5d1c47a5b0..f1bdae2314ed 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4664,6 +4664,12 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
/* Unicast secure management frames */
return ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
ieee80211_is_unicast_robust_mgmt_frame(skb);
+ case NL80211_IFTYPE_PD:
+ /* Accept only authentication frames (PASN) addressed to
+ * this interface.
+ */
+ return ieee80211_is_auth(hdr->frame_control) &&
+ ether_addr_equal(sdata->vif.addr, hdr->addr1);
default:
break;
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b093bc203c81..84d1fa498340 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2210,6 +2210,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_PD:
/* nothing to do */
break;
case NL80211_IFTYPE_UNSPECIFIED:
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 8b94c0de80ad..8954ac1659c1 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -817,6 +817,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_NAN_DATA:
+ case NL80211_IFTYPE_PD:
break;
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_UNSPECIFIED:
@@ -941,6 +942,7 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
/* Can NAN type be considered as beaconing interface? */
case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_NAN_DATA:
+ case NL80211_IFTYPE_PD:
break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_WDS:
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 6783e0672dcb..be2785812811 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1498,6 +1498,7 @@ void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_NAN_DATA:
+ case NL80211_IFTYPE_PD:
/* nothing to do */
break;
case NL80211_IFTYPE_UNSPECIFIED:
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index bd72317c4964..86ef34211de2 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -944,6 +944,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
* fall through, P2P device only supports
* public action frames
*/
+ case NL80211_IFTYPE_PD:
default:
err = -EOPNOTSUPP;
break;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 541da67fafe1..4b387bf1fe7a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1841,6 +1841,11 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
NL80211_EXT_FEATURE_SECURE_NAN))
return 0;
return -EINVAL;
+ case NL80211_IFTYPE_PD:
+ if (wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_RTT))
+ return 0;
+ return -EINVAL;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_MONITOR:
@@ -4937,6 +4942,7 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
return -EOPNOTSUPP;
if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
+ type == NL80211_IFTYPE_PD ||
rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
info->attrs[NL80211_ATTR_MAC]) {
nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
@@ -4993,8 +4999,9 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
break;
case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_PD:
/*
- * P2P Device and NAN do not have a netdev, so don't go
+ * P2P Device, NAN and PD do not have a netdev, so don't go
* through the netdev notifier and must be added here
*/
cfg80211_init_wdev(wdev);
@@ -10805,7 +10812,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
wiphy = &rdev->wiphy;
- if (wdev->iftype == NL80211_IFTYPE_NAN)
+ if (wdev->iftype == NL80211_IFTYPE_NAN ||
+ wdev->iftype == NL80211_IFTYPE_PD)
return -EOPNOTSUPP;
if (!rdev->ops->scan)
@@ -14223,6 +14231,11 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
WIPHY_NAN_FLAGS_USERSPACE_DE))
return -EOPNOTSUPP;
break;
+ case NL80211_IFTYPE_PD:
+ if (!wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_RTT))
+ return -EOPNOTSUPP;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -14287,6 +14300,11 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
WIPHY_NAN_FLAGS_USERSPACE_DE))
return -EOPNOTSUPP;
break;
+ case NL80211_IFTYPE_PD:
+ if (!wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_RTT))
+ return -EOPNOTSUPP;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -14412,6 +14430,11 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
NL80211_EXT_FEATURE_SECURE_NAN))
return -EOPNOTSUPP;
break;
+ case NL80211_IFTYPE_PD:
+ if (!wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_RTT))
+ return -EOPNOTSUPP;
+ break;
default:
return -EOPNOTSUPP;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5db2121c0b57..1e8214d6b6d8 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2412,6 +2412,9 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
case NL80211_IFTYPE_NAN_DATA:
/* NAN channels are checked in NL80211_IFTYPE_NAN interface */
break;
+ case NL80211_IFTYPE_PD:
+ /* we have no info, but PD is also pretty universal */
+ continue;
default:
/* others not implemented for now */
WARN_ON_ONCE(1);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index cff5a1bd95cc..df407ce9db3d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1201,7 +1201,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
/* cannot change into P2P device or NAN */
if (ntype == NL80211_IFTYPE_P2P_DEVICE ||
- ntype == NL80211_IFTYPE_NAN)
+ ntype == NL80211_IFTYPE_NAN ||
+ ntype == NL80211_IFTYPE_PD)
return -EOPNOTSUPP;
if (!rdev->ops->change_virtual_intf ||
@@ -1266,6 +1267,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_NAN:
+ case NL80211_IFTYPE_PD:
WARN_ON(1);
break;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 04/13] wifi: cfg80211: add start/stop proximity detection commands
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (2 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 03/13] wifi: cfg80211/mac80211: Add NL80211_IFTYPE_PD for PD PASN and PMSR operations Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 05/13] wifi: cfg80211: add proximity detection capabilities to PMSR Peddolla Harshavardhan Reddy
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Currently, the proximity detection (PD) interface type has no
start/stop commands defined, preventing user space from
controlling PD operations through the nl80211 interface.
Add NL80211_CMD_START_PD and NL80211_CMD_STOP_PD commands to
allow user space to start and stop a PD interface. Add the
corresponding start_pd and stop_pd operations to cfg80211_ops
and ieee80211_ops, along with nl80211 command handlers, rdev
wrappers, and tracing support. Validate that drivers advertising
PD interface support implement the required operations. Handle
PD interface teardown during device unregistration and when
the interface leaves the network.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 5 ++++
include/uapi/linux/nl80211.h | 9 ++++++
net/wireless/core.c | 35 ++++++++++++++++++++++-
net/wireless/core.h | 2 ++
net/wireless/nl80211.c | 54 ++++++++++++++++++++++++++++++++++++
net/wireless/rdev-ops.h | 19 +++++++++++++
net/wireless/trace.h | 10 +++++++
7 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 25847230428e..0ab0a99fa824 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5085,6 +5085,9 @@ struct mgmt_frame_regs {
* links by calling cfg80211_mlo_reconf_add_done(). When calling
* cfg80211_mlo_reconf_add_done() the bss pointer must be given for each
* link for which MLO reconfiguration 'add' operation was requested.
+ *
+ * @start_pd: Start the PD interface.
+ * @stop_pd: Stop the PD interface.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -5461,6 +5464,8 @@ struct cfg80211_ops {
struct cfg80211_ml_reconf_req *req);
int (*set_epcs)(struct wiphy *wiphy, struct net_device *dev,
bool val);
+ int (*start_pd)(struct wiphy *wiphy, struct wireless_dev *wdev);
+ void (*stop_pd)(struct wiphy *wiphy, struct wireless_dev *wdev);
};
/*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7fb77091f863..53d22194e75d 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1417,6 +1417,12 @@
* identifying the evacuated channel.
* User space may reconfigure the local schedule in response to this
* notification.
+ * @NL80211_CMD_START_PD: Start PD operation, identified by its
+ * %NL80211_ATTR_WDEV interface. This interface must have been previously
+ * created with %NL80211_CMD_NEW_INTERFACE.
+ * @NL80211_CMD_STOP_PD: Stop the PD operation, identified by
+ * its %NL80211_ATTR_WDEV interface.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1692,6 +1698,9 @@ enum nl80211_commands {
NL80211_CMD_NAN_CHANNEL_EVAC,
+ NL80211_CMD_START_PD,
+ NL80211_CMD_STOP_PD,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index be2785812811..55ad4d0bcc73 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -322,6 +322,28 @@ int cfg80211_nan_set_local_schedule(struct cfg80211_registered_device *rdev,
return 0;
}
+void cfg80211_stop_pd(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ lockdep_assert_held(&rdev->wiphy.mtx);
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_PD))
+ return;
+
+ if (!rdev->ops->stop_pd)
+ return;
+
+ if (!wdev_running(wdev))
+ return;
+
+ cfg80211_pmsr_wdev_down(wdev);
+
+ rdev_stop_pd(rdev, wdev);
+ wdev->is_running = false;
+
+ rdev->opencount--;
+}
+
void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -351,6 +373,9 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
case NL80211_IFTYPE_NAN:
cfg80211_stop_nan(rdev, wdev);
break;
+ case NL80211_IFTYPE_PD:
+ cfg80211_stop_pd(rdev, wdev);
+ break;
default:
break;
}
@@ -828,6 +853,9 @@ int wiphy_register(struct wiphy *wiphy)
(!rdev->ops->tdls_channel_switch ||
!rdev->ops->tdls_cancel_channel_switch)))
return -EINVAL;
+ if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_PD)) &&
+ (!rdev->ops->start_pd || !rdev->ops->stop_pd)))
+ return -EINVAL;
if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN)) &&
(!rdev->ops->start_nan || !rdev->ops->stop_nan ||
@@ -1387,6 +1415,9 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
case NL80211_IFTYPE_NAN:
cfg80211_stop_nan(rdev, wdev);
break;
+ case NL80211_IFTYPE_PD:
+ cfg80211_stop_pd(rdev, wdev);
+ break;
default:
break;
}
@@ -1495,10 +1526,12 @@ void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_NAN:
cfg80211_stop_nan(rdev, wdev);
break;
+ case NL80211_IFTYPE_PD:
+ cfg80211_stop_pd(rdev, wdev);
+ break;
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_NAN_DATA:
- case NL80211_IFTYPE_PD:
/* nothing to do */
break;
case NL80211_IFTYPE_UNSPECIFIED:
diff --git a/net/wireless/core.h b/net/wireless/core.h
index ae2d56d3ad90..cbea34005330 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -556,6 +556,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);
+void cfg80211_stop_pd(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev);
int cfg80211_nan_set_local_schedule(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4b387bf1fe7a..e40b1898ab02 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16571,6 +16571,46 @@ static int nl80211_nan_change_config(struct sk_buff *skb,
return rdev_nan_change_conf(rdev, wdev, &conf, changed);
}
+static int nl80211_start_pd(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+ int err;
+
+ if (wdev->iftype != NL80211_IFTYPE_PD)
+ return -EOPNOTSUPP;
+
+ if (wdev_running(wdev))
+ return -EEXIST;
+
+ if (rfkill_blocked(rdev->wiphy.rfkill))
+ return -ERFKILL;
+
+ if (!rdev->ops->start_pd)
+ return -EOPNOTSUPP;
+
+ err = rdev_start_pd(rdev, wdev);
+ if (err)
+ return err;
+ wdev->is_running = true;
+ rdev->opencount++;
+
+ return 0;
+}
+
+static int nl80211_stop_pd(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+
+ if (wdev->iftype != NL80211_IFTYPE_PD)
+ return -EOPNOTSUPP;
+
+ cfg80211_stop_pd(rdev, wdev);
+
+ return 0;
+}
+
void cfg80211_nan_match(struct wireless_dev *wdev,
struct cfg80211_nan_match_params *match, gfp_t gfp)
{
@@ -19733,6 +19773,20 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.flags = GENL_ADMIN_PERM,
.internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
+ {
+ .cmd = NL80211_CMD_START_PD,
+ .doit = nl80211_start_pd,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_NEED_RTNL),
+ },
+ {
+ .cmd = NL80211_CMD_STOP_PD,
+ .doit = nl80211_stop_pd,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL),
+ },
{
.cmd = NL80211_CMD_SET_MCAST_RATE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index d97d5c08d135..63c26e8b1139 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1093,6 +1093,25 @@ rdev_nan_set_peer_sched(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int rdev_start_pd(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ int ret;
+
+ trace_rdev_start_pd(&rdev->wiphy, wdev);
+ ret = rdev->ops->start_pd(&rdev->wiphy, wdev);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_stop_pd(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ trace_rdev_stop_pd(&rdev->wiphy, wdev);
+ rdev->ops->stop_pd(&rdev->wiphy, wdev);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_acl_data *params)
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 938fea1fe9d8..a68d356fe127 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2375,6 +2375,16 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_stop_nan,
TP_ARGS(wiphy, wdev)
);
+DEFINE_EVENT(wiphy_wdev_evt, rdev_start_pd,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_stop_pd,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
TRACE_EVENT(rdev_add_nan_func,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
const struct cfg80211_nan_func *func),
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 05/13] wifi: cfg80211: add proximity detection capabilities to PMSR
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (3 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 04/13] wifi: cfg80211: add start/stop proximity detection commands Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 06/13] wifi: cfg80211: add NTB continuous ranging and FTM request type support Peddolla Harshavardhan Reddy
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Introduce Proximity Detection (PD) capabilities in Peer Measurement
Service (PMSR) as defined in the Wi-Fi Alliance specification
"Proximity Ranging (PR) Implementation Consideration Draft 1.9 Rev 1
section 3.3". This enables devices to advertise peer to peer ranging
support.
Restructure FTM capabilities in cfg80211_pmsr_capabilities to replace
the single support_rsta flag with nested ista and rsta sub-structs,
each carrying per-mode flags for Non-Trigger Based (NTB), Trigger Based
(TB), and EDCA based ranging. This allows drivers to advertise detailed
role and protocol support for both initiator and responder roles.
Add support to pass additional ISTA and RSTA role capabilities to
userspace using new nested ISTA_CAPS and RSTA_CAPS attributes. The
legacy RSTA_SUPPORT flag is retained for backward compatibility.
Add NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS nested attribute using the
nl80211_peer_measurement_ftm_type_capa enum with two sub-flags:
NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT for STA-to-AP or
AP-to-STA ranging, and NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT
for peer-to-peer ranging.
Add CONCURRENT_ISTA_RSTA_SUPPORT as a FTM capability flag indicating
the device can simultaneously act as initiator and responder in a
multi-peer measurement request.
Extend FTM capabilities with antenna configuration fields
(max_no_of_tx_antennas, max_no_of_rx_antennas) for the PR Element
during PASN negotiation, and ranging interval limits
(min_allowed_ranging_interval_edca, min_allowed_ranging_interval_ntb)
to advertise device timing constraints for EDCA and NTB-based ranging.
Update the FTM request validation path in pmsr.c to check RSTA
requests against the per-mode rsta capabilities (NTB, TB, EDCA),
rejecting requests for modes the device does not support.
Co-developed-by: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
Signed-off-by: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 60 +++++++++++++++++++++++-
include/uapi/linux/nl80211.h | 78 +++++++++++++++++++++++++++++++
net/wireless/nl80211.c | 91 +++++++++++++++++++++++++++++++++++-
net/wireless/pmsr.c | 22 ++++++++-
4 files changed, 245 insertions(+), 6 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0ab0a99fa824..16b03a074f58 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5908,7 +5908,45 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type);
* (0 means unknown)
* @ftm.max_total_ltf_rx: maximum total number of LTFs that can be received
* (0 means unknown)
- * @ftm.support_rsta: supports operating as RSTA in PMSR FTM request
+ * @ftm.ista: initiator role capabilities
+ * @ftm.ista.support_ntb: supports operating as ISTA in PMSR FTM request for
+ * NTB ranging.
+ * @ftm.ista.support_tb: supports operating as ISTA in PMSR FTM request for
+ * TB ranging.
+ * @ftm.ista.support_edca: supports operating as ISTA in PMSR FTM request for
+ * EDCA based ranging.
+ * @ftm.rsta: responder role capabilities
+ * @ftm.rsta.support_ntb: supports operating as RSTA in PMSR FTM request for
+ * NTB ranging.
+ * @ftm.rsta.support_tb: supports operating as RSTA in PMSR FTM request for
+ * TB ranging.
+ * @ftm.rsta.support_edca: supports operating as RSTA in PMSR FTM request for
+ * EDCA based ranging.
+ * @ftm.max_no_of_tx_antennas: maximum number of transmit antennas supported for
+ * EDCA based ranging (0 means unknown)
+ * @ftm.max_no_of_rx_antennas: maximum number of receive antennas supported for
+ * EDCA based ranging (0 means unknown)
+ * @ftm.min_allowed_ranging_interval_edca: Minimum EDCA ranging
+ * interval supported by the device in milli seconds. (0 means unknown).
+ * Applications can use this value to estimate the burst period to be
+ * given in the FTM request for the EDCA based ranging case. If
+ * non-zero, this value will be used to validate the burst period in
+ * the FTM request.
+ * @ftm.min_allowed_ranging_interval_ntb: Minimum NTB ranging
+ * interval supported by the device in milli seconds. (0 means unknown).
+ * Applications can use this value to estimate the burst period to be
+ * given in the FTM request for the NTB ranging case. If non-zero,
+ * this value will be used to validate the nominal time in the FTM
+ * request.
+ * @ftm.type: ranging type capabilities
+ * @ftm.type.infra_support: supports infrastructure ranging (STA-to-AP or
+ * AP-to-STA) as part of Proximity Detection
+ * @ftm.type.pd_support: supports peer-to-peer ranging as mentioned in the
+ * specification "PR Implementation Consideration Draft 1.9 rev 1" where
+ * PD stands for proximity detection
+ * @ftm.concurrent_ista_rsta_support: indicates if the device can
+ * simultaneously act as initiator and responder in a multi-peer
+ * measurement request. Only valid if @ftm.rsta_support is set.
*/
struct cfg80211_pmsr_capabilities {
unsigned int max_peers;
@@ -5934,7 +5972,25 @@ struct cfg80211_pmsr_capabilities {
u8 max_rx_sts;
u8 max_total_ltf_tx;
u8 max_total_ltf_rx;
- u8 support_rsta:1;
+ struct {
+ u8 support_ntb:1,
+ support_tb:1,
+ support_edca:1;
+ } ista;
+ struct {
+ u8 support_ntb:1,
+ support_tb:1,
+ support_edca:1;
+ } rsta;
+ u8 max_no_of_tx_antennas;
+ u8 max_no_of_rx_antennas;
+ u32 min_allowed_ranging_interval_edca;
+ u32 min_allowed_ranging_interval_ntb;
+ struct {
+ u8 infra_support:1,
+ pd_support:1;
+ } type;
+ u8 concurrent_ista_rsta_support:1;
} ftm;
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 53d22194e75d..e540cd21b9e7 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8100,6 +8100,46 @@ enum nl80211_peer_measurement_attrs {
* This limits the allowed combinations of LTF repetitions and STS.
* @NL80211_PMSR_FTM_CAPA_ATTR_RSTA_SUPPORT: flag attribute indicating the
* device supports operating as the RSTA in PMSR FTM request
+ * @NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS: nested attribute containing ISTA
+ * (initiator) role capabilities. Uses the same sub-attributes as
+ * %NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS: nested attribute containing RSTA
+ * (responder) role capabilities.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB: flag attribute (used inside
+ * %NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS or
+ * %NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS) indicating NTB ranging support.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB: flag attribute (used inside
+ * %NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS or
+ * %NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS) indicating TB ranging support.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA: flag attribute (used inside
+ * %NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS or
+ * %NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS) indicating EDCA based ranging
+ * support.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS: nested attribute containing ranging
+ * type capabilities. Uses sub-attributes from
+ * &enum nl80211_peer_measurement_ftm_type_capa.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT: flag attribute
+ * indicating that the device can simultaneously act as initiator and
+ * responder in a multi-peer measurement request. Only valid if
+ * @NL80211_PMSR_FTM_CAPA_ATTR_RSTA_SUPPORT is set.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS: u32 attribute indicating
+ * the maximum number of transmit antennas supported for EDCA based ranging
+ * (0 means unknown)
+ * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS: u32 attribute indicating
+ * the maximum number of receive antennas supported for EDCA based ranging
+ * (0 means unknown)
+ * @NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA: u32 attribute indicating
+ * the minimum EDCA ranging interval supported by the device
+ * in milli seconds. (0 means unknown). Applications can use this value
+ * to estimate the burst period to be given in the FTM request for the
+ * EDCA based ranging case. If non-zero, this value will be used to
+ * validate the burst period in the FTM request.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB: u32 attribute indicating
+ * the minimum NTB ranging interval supported by the device
+ * in milli seconds. (0 means unknown). Applications can use this value
+ * to estimate the burst period to be given in the FTM request for the
+ * NTB ranging case. If non-zero, this value will be used to validate
+ * the nominal time in the FTM request.
*
* @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal
* @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number
@@ -8125,12 +8165,50 @@ enum nl80211_peer_measurement_ftm_capa {
NL80211_PMSR_FTM_CAPA_ATTR_MAX_TOTAL_LTF_TX,
NL80211_PMSR_FTM_CAPA_ATTR_MAX_TOTAL_LTF_RX,
NL80211_PMSR_FTM_CAPA_ATTR_RSTA_SUPPORT,
+ NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS,
+ NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS,
+ NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB,
+ NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB,
+ NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA,
+ NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS,
+ NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT,
+ NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS,
+ NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS,
+ NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA,
+ NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB,
/* keep last */
NUM_NL80211_PMSR_FTM_CAPA_ATTR,
NL80211_PMSR_FTM_CAPA_ATTR_MAX = NUM_NL80211_PMSR_FTM_CAPA_ATTR - 1
};
+/**
+ * enum nl80211_peer_measurement_ftm_type_capa - FTM ranging type capability
+ * sub-attributes, used inside %NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS
+ * @__NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INVALID: invalid
+ *
+ * @NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT: flag attribute indicating
+ * that the device supports infrastructure ranging (STA-to-AP or
+ * AP-to-STA) as part of Proximity Detection
+ * @NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT: flag attribute indicating that
+ * the device supports peer-to-peer ranging as mentioned in the
+ * specification "PR Implementation Consideration Draft 1.9 rev 1" where
+ * PD stands for proximity detection
+ *
+ * @NUM_NL80211_PMSR_FTM_TYPE_CAPA_ATTR: internal
+ * @NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX: highest attribute number
+ */
+enum nl80211_peer_measurement_ftm_type_capa {
+ __NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INVALID,
+
+ NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT,
+ NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT,
+
+ /* keep last */
+ NUM_NL80211_PMSR_FTM_TYPE_CAPA_ATTR,
+ NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX = NUM_NL80211_PMSR_FTM_TYPE_CAPA_ATTR - 1
+};
+
/**
* enum nl80211_peer_measurement_ftm_req - FTM request attributes
* @__NL80211_PMSR_FTM_REQ_ATTR_INVALID: invalid
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e40b1898ab02..51046d749581 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2502,10 +2502,97 @@ nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_TOTAL_LTF_RX,
cap->ftm.max_total_ltf_rx))
return -ENOBUFS;
- if (cap->ftm.support_rsta &&
- nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_RSTA_SUPPORT))
+
+ if (cap->ftm.ista.support_ntb || cap->ftm.ista.support_tb ||
+ cap->ftm.ista.support_edca) {
+ struct nlattr *ista_caps;
+
+ ista_caps = nla_nest_start_noflag(msg,
+ NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS);
+ if (!ista_caps)
+ return -ENOBUFS;
+ if (cap->ftm.ista.support_ntb &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB))
+ return -ENOBUFS;
+ if (cap->ftm.ista.support_tb &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB))
+ return -ENOBUFS;
+ if (cap->ftm.ista.support_edca &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA))
+ return -ENOBUFS;
+ nla_nest_end(msg, ista_caps);
+ }
+
+ if (cap->ftm.rsta.support_ntb || cap->ftm.rsta.support_tb ||
+ cap->ftm.rsta.support_edca) {
+ struct nlattr *rsta_caps;
+
+ /*
+ * Set the generic RSTA_SUPPORT flag if any of the specific
+ * ranging modes is supported to maintain the backward
+ * compatibility.
+ */
+ if (nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_RSTA_SUPPORT))
+ return -ENOBUFS;
+
+ rsta_caps = nla_nest_start_noflag(msg,
+ NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS);
+ if (!rsta_caps)
+ return -ENOBUFS;
+ if (cap->ftm.rsta.support_ntb &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB))
+ return -ENOBUFS;
+ if (cap->ftm.rsta.support_tb &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB))
+ return -ENOBUFS;
+ if (cap->ftm.rsta.support_edca &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA))
+ return -ENOBUFS;
+ nla_nest_end(msg, rsta_caps);
+ }
+
+ if (cap->ftm.max_no_of_tx_antennas &&
+ nla_put_u8(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS,
+ cap->ftm.max_no_of_tx_antennas))
+ return -ENOBUFS;
+
+ if (cap->ftm.max_no_of_rx_antennas &&
+ nla_put_u8(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS,
+ cap->ftm.max_no_of_rx_antennas))
+ return -ENOBUFS;
+
+ if (cap->ftm.min_allowed_ranging_interval_edca &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA,
+ cap->ftm.min_allowed_ranging_interval_edca))
return -ENOBUFS;
+ if (cap->ftm.min_allowed_ranging_interval_ntb &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB,
+ cap->ftm.min_allowed_ranging_interval_ntb))
+ return -ENOBUFS;
+
+ if (cap->ftm.type.infra_support || cap->ftm.type.pd_support) {
+ struct nlattr *pd_caps;
+
+ pd_caps = nla_nest_start_noflag(msg,
+ NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS);
+ if (!pd_caps)
+ return -ENOBUFS;
+
+ if (cap->ftm.type.infra_support &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT))
+ return -ENOBUFS;
+
+ if (cap->ftm.type.pd_support &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT))
+ return -ENOBUFS;
+
+ nla_nest_end(msg, pd_caps);
+ }
+
+ if (cap->ftm.concurrent_ista_rsta_support &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT))
+ return -ENOBUFS;
nla_nest_end(msg, ftm);
return 0;
}
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index afc0e3f931ec..c21f693fac29 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -188,10 +188,28 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
}
out->ftm.rsta = !!tb[NL80211_PMSR_FTM_REQ_ATTR_RSTA];
- if (out->ftm.rsta && !capa->ftm.support_rsta) {
+ if (out->ftm.rsta && out->ftm.non_trigger_based &&
+ !capa->ftm.rsta.support_ntb) {
NL_SET_ERR_MSG_ATTR(info->extack,
tb[NL80211_PMSR_FTM_REQ_ATTR_RSTA],
- "FTM: RSTA not supported by device");
+ "FTM: NTB RSTA not supported by device");
+ return -EOPNOTSUPP;
+ }
+
+ if (out->ftm.rsta && out->ftm.trigger_based &&
+ !capa->ftm.rsta.support_tb) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_FTM_REQ_ATTR_RSTA],
+ "FTM: TB RSTA not supported by device");
+ return -EOPNOTSUPP;
+ }
+
+ if (out->ftm.rsta && !out->ftm.non_trigger_based &&
+ !out->ftm.trigger_based &&
+ !capa->ftm.rsta.support_edca) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_FTM_REQ_ATTR_RSTA],
+ "FTM: EDCA RSTA not supported by device");
return -EOPNOTSUPP;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 06/13] wifi: cfg80211: add NTB continuous ranging and FTM request type support
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (4 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 05/13] wifi: cfg80211: add proximity detection capabilities to PMSR Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 07/13] wifi: cfg80211: extend PMSR FTM response for proximity ranging Peddolla Harshavardhan Reddy
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Enable NTB continuous ranging with configurable timing and measurement
parameters as per the Wi-Fi Alliance specification "Proximity Ranging
(PR) Implementation Consideration Draft 1.9 Rev 1, section 5.3". Add
new FTM request attributes for min/max time between measurements,
nominal time (mandatory for NTB), AW duration, and total measurement
count.
Add NL80211_PMSR_PEER_ATTR_REQ_TYPE attribute using the new
nl80211_peer_measurement_ftm_req_type enum to allow userspace to
specify the ranging request type per peer:
- NL80211_PMSR_FTM_REQ_TYPE_INFRA: STA-to-AP or AP-to-STA ranging
(default if attribute is absent)
- NL80211_PMSR_FTM_REQ_TYPE_PD: peer-to-peer ranging
Validate the request type against the device TYPE_CAPS capabilities
advertised via NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS. Reject PD
requests if the device does not advertise PD support.
Reject PD requests that set trigger-based ranging, as TB ranging is
not compatible with peer-to-peer proximity detection.
Add ftms_per_burst limit of 4 for PD NTB ranging requests.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 35 +++++++++++++++++++-
include/uapi/linux/nl80211.h | 62 ++++++++++++++++++++++++++++++++++--
net/wireless/nl80211.c | 11 +++++++
net/wireless/pmsr.c | 61 +++++++++++++++++++++++++++++++++--
4 files changed, 163 insertions(+), 6 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 16b03a074f58..ec82ca19470b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4524,7 +4524,8 @@ struct cfg80211_pmsr_result {
* @burst_duration: burst duration. If @trigger_based or @non_trigger_based is
* set, this is the burst duration in milliseconds, and zero means the
* device should pick an appropriate value based on @ftms_per_burst.
- * @ftms_per_burst: number of FTMs per burst
+ * @ftms_per_burst: number of FTMs per burst. If set to 0, the firmware or
+ * driver can automatically select an appropriate value.
* @ftmr_retries: number of retries for FTM request
* @request_lci: request LCI information
* @request_civicloc: request civic location information
@@ -4541,6 +4542,31 @@ struct cfg80211_pmsr_result {
* @bss_color: the bss color of the responder. Optional. Set to zero to
* indicate the driver should set the BSS color. Only valid if
* @non_trigger_based or @trigger_based is set.
+ * @request_type: ranging request type, one of
+ * &enum nl80211_peer_measurement_ftm_req_type. Defaults to
+ * %NL80211_PMSR_FTM_REQ_TYPE_INFRA if not specified.
+ * @min_time_between_measurements: minimum time between two consecutive range
+ * measurements in units of 100 microseconds, for non-trigger based
+ * ranging. Should be set as short as possible to minimize turnaround
+ * time, since two-way ranging with delayed LMR requires two measurements.
+ * Only valid if @non_trigger_based is set.
+ * @max_time_between_measurements: maximum time between two consecutive range
+ * measurements in units of 10 milliseconds, for non-trigger based
+ * ranging. Acts as a session timeout; if exceeded, the ranging session
+ * should be terminated. Only valid if @non_trigger_based is set.
+ * @availability_window: duration of the availability window (AW) in units of
+ * 1 millisecond (0-255 ms). Only valid if @non_trigger_based is set.
+ * If set to 0, the firmware or driver can automatically select an
+ * appropriate value.
+ * @nominal_time: Nominal duration between adjacent availability windows
+ * in units of milli seconds. Only valid if @non_trigger_based is set.
+ * If set to 0, the firmware or driver can automatically select an
+ * appropriate value.
+ * @num_measurements: number of Availability Windows (AWs) to schedule
+ * for non-trigger-based ranging. Each AW may contain multiple FTM
+ * exchanges as configured by @ftms_per_burst. Only valid if
+ * @non_trigger_based is set. If set to 0, the firmware or driver
+ * can automatically select an appropriate value.
*
* See also nl80211 for the respective attribute documentation.
*/
@@ -4560,6 +4586,13 @@ struct cfg80211_pmsr_ftm_request_peer {
u8 ftms_per_burst;
u8 ftmr_retries;
u8 bss_color;
+
+ u32 request_type;
+ u32 min_time_between_measurements;
+ u32 max_time_between_measurements;
+ u8 availability_window;
+ u32 nominal_time;
+ u32 num_measurements;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index e540cd21b9e7..4be04dea7938 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -7980,6 +7980,26 @@ enum nl80211_peer_measurement_resp {
NL80211_PMSR_RESP_ATTR_MAX = NUM_NL80211_PMSR_RESP_ATTRS - 1
};
+/**
+ * enum nl80211_peer_measurement_ftm_req_type - FTM ranging request type,
+ * used with %NL80211_PMSR_PEER_ATTR_REQ_TYPE
+ *
+ * @NL80211_PMSR_FTM_REQ_TYPE_INFRA: infrastructure ranging, i.e. STA-to-AP
+ * @NL80211_PMSR_FTM_REQ_TYPE_PD: peer-to-peer ranging as defined in the
+ * Wi-Fi Alliance specification "Proximity Ranging (PR) Implementation
+ * Consideration Draft 1.9 Rev 1"
+ * @NUM_NL80211_PMSR_FTM_REQ_TYPE: internal
+ * @NL80211_PMSR_FTM_REQ_TYPE_MAX: highest request type value
+ */
+enum nl80211_peer_measurement_ftm_req_type {
+ NL80211_PMSR_FTM_REQ_TYPE_INFRA,
+ NL80211_PMSR_FTM_REQ_TYPE_PD,
+
+ /* keep last */
+ NUM_NL80211_PMSR_FTM_REQ_TYPE,
+ NL80211_PMSR_FTM_REQ_TYPE_MAX = NUM_NL80211_PMSR_FTM_REQ_TYPE - 1
+};
+
/**
* enum nl80211_peer_measurement_peer_attrs - peer attributes for measurement
* @__NL80211_PMSR_PEER_ATTR_INVALID: invalid
@@ -7993,6 +8013,9 @@ enum nl80211_peer_measurement_resp {
* @NL80211_PMSR_PEER_ATTR_RESP: This is a nested attribute indexed by
* measurement type, with attributes from the
* &enum nl80211_peer_measurement_resp inside.
+ * @NL80211_PMSR_PEER_ATTR_REQ_TYPE: u32 attribute specifying the ranging
+ * request type, using values from &enum nl80211_peer_measurement_ftm_req_type.
+ * If absent, defaults to %NL80211_PMSR_FTM_REQ_TYPE_INFRA.
*
* @NUM_NL80211_PMSR_PEER_ATTRS: internal
* @NL80211_PMSR_PEER_ATTR_MAX: highest attribute number
@@ -8004,6 +8027,7 @@ enum nl80211_peer_measurement_peer_attrs {
NL80211_PMSR_PEER_ATTR_CHAN,
NL80211_PMSR_PEER_ATTR_REQ,
NL80211_PMSR_PEER_ATTR_RESP,
+ NL80211_PMSR_PEER_ATTR_REQ_TYPE,
/* keep last */
NUM_NL80211_PMSR_PEER_ATTRS,
@@ -8227,9 +8251,11 @@ enum nl80211_peer_measurement_ftm_type_capa {
* default 15 i.e. "no preference"). For non-EDCA ranging, this is the
* burst duration in milliseconds (optional with default 0, i.e. let the
* device decide).
- * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: number of successful FTM frames
- * requested per burst
+ * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: (Optional) number of successful
+ * FTM frames requested per burst
* (u8, 0-31, optional with default 0 i.e. "no preference")
+ * If the attribute is absent ("no preference"), the driver or firmware can
+ * choose a suitable value.
* @NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES: number of FTMR frame retries
* (u8, default 3)
* @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag)
@@ -8263,6 +8289,33 @@ enum nl80211_peer_measurement_ftm_type_capa {
* Only valid if %NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK is set (so the
* RSTA will have the measurement results to report back in the FTM
* response).
+ * @NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS: minimum time
+ * between two consecutive range measurements in units of 100 microseconds,
+ * for non-trigger based ranging (u32). Should be set as short as possible
+ * to minimize turnaround time, since two-way ranging with delayed LMR
+ * requires two measurements. Only valid if
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * @NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS: maximum time
+ * between two consecutive range measurements in units of 10 milliseconds,
+ * for non-trigger based ranging (u32). Acts as a session timeout; if
+ * exceeded, the ranging session should be terminated. Only valid if
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * @NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME: The nominal time field shall be
+ * set to the nominal duration between adjacent Availability Windows in
+ * units of milli seconds (u32). Mandatory if
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * @NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION: (Optional) The AW duration field
+ * shall be set to the duration of the AW in units of 1ms (0-255 ms) (u32).
+ * Only valid if %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * If the attribute is absent ("no preference"), the driver or firmware
+ * can choose a suitable value.
+ * @NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS: (Optional) number of
+ * Availability Windows (AWs) to schedule for non-trigger-based ranging.
+ * Each AW may contain multiple FTM exchanges as configured by
+ * %NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST. Only valid if
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * If the attribute is absent ("no preference"), the driver or firmware
+ * can choose a suitable value.
*
* @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
* @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
@@ -8284,6 +8337,11 @@ enum nl80211_peer_measurement_ftm_req {
NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK,
NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR,
NL80211_PMSR_FTM_REQ_ATTR_RSTA,
+ NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS,
+ NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS,
+ NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME,
+ NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION,
+ NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS,
/* keep last */
NUM_NL80211_PMSR_FTM_REQ_ATTR,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 51046d749581..3fb540c6adcf 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -476,6 +476,15 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK] = { .type = NLA_FLAG },
[NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR] = { .type = NLA_U8 },
[NL80211_PMSR_FTM_REQ_ATTR_RSTA] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS] = {
+ .type = NLA_U32
+ },
+ [NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS] = {
+ .type = NLA_U32
+ },
+ [NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION] = NLA_POLICY_MAX(NLA_U32, 255),
+ [NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS] = { .type = NLA_U32 },
};
static const struct nla_policy
@@ -498,6 +507,8 @@ nl80211_pmsr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
[NL80211_PMSR_PEER_ATTR_REQ] =
NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy),
[NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
+ [NL80211_PMSR_PEER_ATTR_REQ_TYPE] =
+ NLA_POLICY_MAX(NLA_U32, NL80211_PMSR_FTM_REQ_TYPE_MAX),
};
static const struct nla_policy
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index c21f693fac29..951ba0b96da2 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -91,11 +91,10 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]);
if (capa->ftm.max_ftms_per_burst &&
- (out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst ||
- out->ftm.ftms_per_burst == 0)) {
+ out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst) {
NL_SET_ERR_MSG_ATTR(info->extack,
tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST],
- "FTM: FTMs per burst must be set lower than the device limit but non-zero");
+ "FTM: FTMs per burst must be set lower than the device limit");
return -EINVAL;
}
@@ -128,6 +127,14 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
return -EINVAL;
}
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ out->ftm.trigger_based) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ ftmreq,
+ "FTM: TB ranging is not supported for PD request type");
+ return -EINVAL;
+ }
+
out->ftm.non_trigger_based =
!!tb[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED];
if (out->ftm.non_trigger_based && !capa->ftm.non_trigger_based) {
@@ -143,6 +150,14 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
return -EINVAL;
}
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ out->ftm.non_trigger_based && out->ftm.ftms_per_burst > 4) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST],
+ "FTM: FTMs per burst must not exceed 4 for PD NTB ranging");
+ return -ERANGE;
+ }
+
if (out->ftm.ftms_per_burst > 31 && !out->ftm.non_trigger_based &&
!out->ftm.trigger_based) {
NL_SET_ERR_MSG_ATTR(info->extack,
@@ -222,6 +237,33 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
return -EINVAL;
}
+ if (out->ftm.non_trigger_based) {
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ !tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]) {
+ NL_SET_ERR_MSG(info->extack,
+ "FTM: nominal time is required for PD NTB ranging");
+ return -EINVAL;
+ }
+ out->ftm.nominal_time =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS])
+ out->ftm.min_time_between_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS])
+ out->ftm.max_time_between_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION])
+ out->ftm.availability_window =
+ nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS])
+ out->ftm.num_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS]);
+ }
+
return 0;
}
@@ -249,6 +291,19 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev,
memcpy(out->addr, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]), ETH_ALEN);
+ if (tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE])
+ out->ftm.request_type =
+ nla_get_u32(tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE]);
+ else
+ out->ftm.request_type = NL80211_PMSR_FTM_REQ_TYPE_INFRA;
+
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ !rdev->wiphy.pmsr_capa->ftm.type.pd_support) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE],
+ "FTM: PD request type not supported by device");
+ return -EINVAL;
+ }
/* reuse info->attrs */
memset(info->attrs, 0, sizeof(*info->attrs) * (NL80211_ATTR_MAX + 1));
err = nla_parse_nested_deprecated(info->attrs, NL80211_ATTR_MAX,
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 07/13] wifi: cfg80211: extend PMSR FTM response for proximity ranging
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (5 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 06/13] wifi: cfg80211: add NTB continuous ranging and FTM request type support Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 08/13] wifi: cfg80211: add role-based peer limits to FTM capabilities Peddolla Harshavardhan Reddy
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Applications need negotiated session parameters to interpret
proximity ranging results and perform post-processing. Currently,
the FTM response lacks LTF repetition counts, time constraints,
spatial stream configuration, and availability window parameters.
Extend the FTM response structure to report these negotiated
parameters, enabling applications to track session configuration
and use them in post-processing to increase ranging precision.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 56 ++++++++++++++++++++++++++++++++++--
include/uapi/linux/nl80211.h | 38 ++++++++++++++++++++++++
net/wireless/pmsr.c | 15 ++++++++++
3 files changed, 107 insertions(+), 2 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ec82ca19470b..4f1f66a137ae 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4433,6 +4433,25 @@ struct cfg80211_ftm_responder_stats {
* (must have either this or @rtt_avg)
* @dist_variance: variance of distances measured (see also @rtt_variance)
* @dist_spread: spread of distances measured (see also @rtt_spread)
+ * @tx_ltf_repetition_count: negotiated value of number of tx ltf repetitions
+ * in NDP frames
+ * @rx_ltf_repetition_count: negotiated value of number of rx ltf repetitions
+ * in NDP frames
+ * @max_time_between_measurements: the negotiated maximum interval (in units of
+ * 10 ms) by which the ISTA must complete the next measurement cycle.
+ * @min_time_between_measurements: the negotiated minimum interval (in units of
+ * 100 us) between two consecutive range measurements initiated by the
+ * ISTA.
+ * @num_tx_spatial_streams: number of Tx space-time streams used in the NDP
+ * frame during the measurement sounding phase.
+ * @num_rx_spatial_streams: number of Rx space-time streams used in the NDP
+ * frame during the measurement sounding phase.
+ * @nominal_time: negotiated nominal duration between adjacent availability
+ * windows in units of milliseconds (u32).
+ * @availability_window: negotiated availability window time used in this
+ * session in units of milliseconds (u8).
+ * @chan_width: band width used for measurement.
+ * @preamble: preamble used for measurement.
* @num_ftmr_attempts_valid: @num_ftmr_attempts is valid
* @num_ftmr_successes_valid: @num_ftmr_successes is valid
* @rssi_avg_valid: @rssi_avg is valid
@@ -4445,6 +4464,18 @@ struct cfg80211_ftm_responder_stats {
* @dist_avg_valid: @dist_avg is valid
* @dist_variance_valid: @dist_variance is valid
* @dist_spread_valid: @dist_spread is valid
+ * @tx_ltf_repetition_count_valid: @tx_ltf_repetition_count is valid
+ * @rx_ltf_repetition_count_valid: @rx_ltf_repetition_count is valid
+ * @max_time_between_measurements_valid: @max_time_between_measurements is valid
+ * @min_time_between_measurements_valid: @min_time_between_measurements is valid
+ * @num_tx_spatial_streams_valid: @num_tx_spatial_streams is valid
+ * @num_rx_spatial_streams_valid: @num_rx_spatial_streams is valid
+ * @nominal_time_valid: @nominal_time is valid
+ * @availability_window_valid: @availability_window is valid
+ * @chan_width_valid: @chan_width is valid.
+ * @preamble_valid: @preamble is valid.
+ * @is_delayed_lmr: indicates if the reported LMR is of the current burst or the
+ * previous burst, flag.
*/
struct cfg80211_pmsr_ftm_result {
const u8 *lci;
@@ -4468,8 +4499,18 @@ struct cfg80211_pmsr_ftm_result {
s64 dist_avg;
s64 dist_variance;
s64 dist_spread;
+ u32 tx_ltf_repetition_count;
+ u32 rx_ltf_repetition_count;
+ u32 max_time_between_measurements;
+ u32 min_time_between_measurements;
+ u8 num_tx_spatial_streams;
+ u8 num_rx_spatial_streams;
+ u32 nominal_time;
+ u8 availability_window;
+ enum nl80211_chan_width chan_width;
+ enum nl80211_preamble preamble;
- u16 num_ftmr_attempts_valid:1,
+ u32 num_ftmr_attempts_valid:1,
num_ftmr_successes_valid:1,
rssi_avg_valid:1,
rssi_spread_valid:1,
@@ -4480,7 +4521,18 @@ struct cfg80211_pmsr_ftm_result {
rtt_spread_valid:1,
dist_avg_valid:1,
dist_variance_valid:1,
- dist_spread_valid:1;
+ dist_spread_valid:1,
+ tx_ltf_repetition_count_valid:1,
+ rx_ltf_repetition_count_valid:1,
+ max_time_between_measurements_valid:1,
+ min_time_between_measurements_valid:1,
+ num_tx_spatial_streams_valid:1,
+ num_rx_spatial_streams_valid:1,
+ nominal_time_valid:1,
+ availability_window_valid:1,
+ chan_width_valid:1,
+ preamble_valid:1,
+ is_delayed_lmr:1;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 4be04dea7938..cb55e8b69097 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8428,6 +8428,33 @@ enum nl80211_peer_measurement_ftm_failure_reasons {
* @NL80211_PMSR_FTM_RESP_ATTR_PAD: ignore, for u64/s64 padding only
* @NL80211_PMSR_FTM_RESP_ATTR_BURST_PERIOD: actual burst period used by
* the responder (similar to request, u16)
+ * @NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT: negotiated value of
+ * number of tx ltf repetitions in NDP frames (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT: negotiated value of
+ * number of rx ltf repetitions in NDP frames (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS: negotiated value
+ * where latest time by which the ISTA needs to complete the next round of
+ * measurements, in units of 10 ms (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS: negotiated
+ * minimum time between two consecutive range measurements initiated by an
+ * ISTA, in units of 100 us (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS: number of Tx space-time
+ * streams used in NDP frames during the measurement sounding phase
+ * (u32, optional).
+ * @NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS: number of Rx space-time
+ * streams used in the NDP frames during the measurement sounding phase
+ * (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME: negotiated nominal time used in
+ * this session in milliseconds. (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW: negotiated availability
+ * window time used in this session, in units of milli seconds.
+ * (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH: u32 attribute indicating channel
+ * width used for measurement, see &enum nl80211_chan_width (optional).
+ * @NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE: u32 attribute indicating the preamble
+ * type used for the measurement, see &enum nl80211_preamble (optional).
+ * @NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR: flag, indicates if the
+ * current result is delayed LMR data.
*
* @NUM_NL80211_PMSR_FTM_RESP_ATTR: internal
* @NL80211_PMSR_FTM_RESP_ATTR_MAX: highest attribute number
@@ -8457,6 +8484,17 @@ enum nl80211_peer_measurement_ftm_resp {
NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC,
NL80211_PMSR_FTM_RESP_ATTR_PAD,
NL80211_PMSR_FTM_RESP_ATTR_BURST_PERIOD,
+ NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT,
+ NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT,
+ NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS,
+ NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS,
+ NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS,
+ NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS,
+ NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME,
+ NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW,
+ NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH,
+ NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE,
+ NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR,
/* keep last */
NUM_NL80211_PMSR_FTM_RESP_ATTR,
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 951ba0b96da2..caffa2421c20 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -562,6 +562,21 @@ static int nl80211_pmsr_send_ftm_res(struct sk_buff *msg,
PUTOPT_U64(DIST_AVG, dist_avg);
PUTOPT_U64(DIST_VARIANCE, dist_variance);
PUTOPT_U64(DIST_SPREAD, dist_spread);
+ PUTOPT(u32, TX_LTF_REPETITION_COUNT, tx_ltf_repetition_count);
+ PUTOPT(u32, RX_LTF_REPETITION_COUNT, rx_ltf_repetition_count);
+ PUTOPT(u32, MAX_TIME_BETWEEN_MEASUREMENTS,
+ max_time_between_measurements);
+ PUTOPT(u32, MIN_TIME_BETWEEN_MEASUREMENTS,
+ min_time_between_measurements);
+ PUTOPT(u8, NUM_TX_SPATIAL_STREAMS, num_tx_spatial_streams);
+ PUTOPT(u8, NUM_RX_SPATIAL_STREAMS, num_rx_spatial_streams);
+ PUTOPT(u32, NOMINAL_TIME, nominal_time);
+ PUTOPT(u8, AVAILABILITY_WINDOW, availability_window);
+ PUTOPT(u32, CHANNEL_WIDTH, chan_width);
+ PUTOPT(u32, PREAMBLE, preamble);
+ if (res->ftm.is_delayed_lmr &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR))
+ goto error;
if (res->ftm.lci && res->ftm.lci_len &&
nla_put(msg, NL80211_PMSR_FTM_RESP_ATTR_LCI,
res->ftm.lci_len, res->ftm.lci))
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 08/13] wifi: cfg80211: add role-based peer limits to FTM capabilities
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (6 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 07/13] wifi: cfg80211: extend PMSR FTM response for proximity ranging Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 09/13] wifi: cfg80211: add ingress/egress distance thresholds for FTM Peddolla Harshavardhan Reddy
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Peer measurement capabilities currently advertise a single maximum
peer count regardless of device role. Some devices support different
peer limits when operating as initiator versus responder.
Add max_peers fields inside the ftm.ista and ftm.rsta sub-structs of
cfg80211_pmsr_capabilities to allow drivers to advertise per-role peer
limits. These limits are generic and not restricted to any specific
ranging type.
Expose these over nl80211 using new NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE
and NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE attributes inside the
ISTA_CAPS and RSTA_CAPS nested attributes respectively.
When a role limit is advertised, validate the number of peers in the
request separately for each role using the existing rsta flag in the
FTM request, and reject the request if the limit is exceeded.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 6 +++++
include/uapi/linux/nl80211.h | 14 +++++++++++
net/wireless/nl80211.c | 8 +++++++
net/wireless/pmsr.c | 46 ++++++++++++++++++++++++++++++++----
4 files changed, 70 insertions(+), 4 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4f1f66a137ae..8c82f33bfc40 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6000,6 +6000,8 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type);
* TB ranging.
* @ftm.ista.support_edca: supports operating as ISTA in PMSR FTM request for
* EDCA based ranging.
+ * @ftm.ista.max_peers: maximum number of peers supported in the ISTA role.
+ * If zero, no role-specific peer limit applies.
* @ftm.rsta: responder role capabilities
* @ftm.rsta.support_ntb: supports operating as RSTA in PMSR FTM request for
* NTB ranging.
@@ -6007,6 +6009,8 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type);
* TB ranging.
* @ftm.rsta.support_edca: supports operating as RSTA in PMSR FTM request for
* EDCA based ranging.
+ * @ftm.rsta.max_peers: maximum number of peers supported in the RSTA role.
+ * If zero, no role-specific peer limit applies.
* @ftm.max_no_of_tx_antennas: maximum number of transmit antennas supported for
* EDCA based ranging (0 means unknown)
* @ftm.max_no_of_rx_antennas: maximum number of receive antennas supported for
@@ -6061,11 +6065,13 @@ struct cfg80211_pmsr_capabilities {
u8 support_ntb:1,
support_tb:1,
support_edca:1;
+ u32 max_peers;
} ista;
struct {
u8 support_ntb:1,
support_tb:1,
support_edca:1;
+ u32 max_peers;
} rsta;
u8 max_no_of_tx_antennas;
u8 max_no_of_rx_antennas;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index cb55e8b69097..a42bae666d02 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8054,6 +8054,18 @@ enum nl80211_peer_measurement_peer_attrs {
* meaningless, just a list of peers to measure with, with the
* sub-attributes taken from
* &enum nl80211_peer_measurement_peer_attrs.
+ * @NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE: u32 attribute indicating the
+ * maximum number of peers supported when the device operates in the
+ * ISTA (Initiator STA) role. If absent, no role-specific peer limit
+ * applies. The sum of %NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE and
+ * %NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE is enforced when the device
+ * supports concurrent ISTA/RSTA operation.
+ * @NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE: u32 attribute indicating the
+ * maximum number of peers supported when the device operates in the
+ * RSTA (Responder STA) role. If absent, no role-specific peer limit
+ * applies. The sum of %NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE and
+ * %NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE is enforced when the device
+ * supports concurrent ISTA/RSTA operation.
*
* @NUM_NL80211_PMSR_ATTR: internal
* @NL80211_PMSR_ATTR_MAX: highest attribute number
@@ -8066,6 +8078,8 @@ enum nl80211_peer_measurement_attrs {
NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR,
NL80211_PMSR_ATTR_TYPE_CAPA,
NL80211_PMSR_ATTR_PEERS,
+ NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE,
+ NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE,
/* keep last */
NUM_NL80211_PMSR_ATTR,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3fb540c6adcf..4f6612311de3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2531,6 +2531,10 @@ nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
if (cap->ftm.ista.support_edca &&
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA))
return -ENOBUFS;
+ if (cap->ftm.ista.max_peers &&
+ nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE,
+ cap->ftm.ista.max_peers))
+ return -ENOBUFS;
nla_nest_end(msg, ista_caps);
}
@@ -2559,6 +2563,10 @@ nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
if (cap->ftm.rsta.support_edca &&
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA))
return -ENOBUFS;
+ if (cap->ftm.rsta.max_peers &&
+ nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE,
+ cap->ftm.rsta.max_peers))
+ return -ENOBUFS;
nla_nest_end(msg, rsta_caps);
}
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index caffa2421c20..432d34be7945 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -361,12 +361,15 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
{
struct nlattr *reqattr = info->attrs[NL80211_ATTR_PEER_MEASUREMENTS];
struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ int count, rem, err, idx, peer_count;
struct wireless_dev *wdev = info->user_ptr[1];
+ const struct cfg80211_pmsr_capabilities *capa;
struct cfg80211_pmsr_request *req;
struct nlattr *peers, *peer;
- int count, rem, err, idx;
- if (!rdev->wiphy.pmsr_capa)
+ capa = rdev->wiphy.pmsr_capa;
+
+ if (!capa)
return -EOPNOTSUPP;
if (!reqattr)
@@ -381,7 +384,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
nla_for_each_nested(peer, peers, rem) {
count++;
- if (count > rdev->wiphy.pmsr_capa->max_peers) {
+ if (count > capa->max_peers) {
NL_SET_ERR_MSG_ATTR(info->extack, peer,
"Too many peers used");
return -EINVAL;
@@ -397,7 +400,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
req->timeout = nla_get_u32(info->attrs[NL80211_ATTR_TIMEOUT]);
if (info->attrs[NL80211_ATTR_MAC]) {
- if (!rdev->wiphy.pmsr_capa->randomize_mac_addr) {
+ if (!capa->randomize_mac_addr) {
NL_SET_ERR_MSG_ATTR(info->extack,
info->attrs[NL80211_ATTR_MAC],
"device cannot randomize MAC address");
@@ -422,6 +425,41 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
goto out_err;
idx++;
}
+
+ /* Validate per-role peer limits if advertised */
+ if (capa->ftm.ista.max_peers) {
+ peer_count = 0;
+
+ for (idx = 0; idx < req->n_peers; idx++) {
+ if (!req->peers[idx].ftm.rsta) {
+ peer_count++;
+
+ if (peer_count > capa->ftm.ista.max_peers) {
+ NL_SET_ERR_MSG(info->extack,
+ "Too many ISTA peers for device limit");
+ err = -EINVAL;
+ goto out_err;
+ }
+ }
+ }
+ }
+
+ if (capa->ftm.rsta.max_peers) {
+ peer_count = 0;
+
+ for (idx = 0; idx < req->n_peers; idx++) {
+ if (req->peers[idx].ftm.rsta) {
+ peer_count++;
+
+ if (peer_count > capa->ftm.rsta.max_peers) {
+ NL_SET_ERR_MSG(info->extack,
+ "Too many RSTA peers for device limit");
+ err = -EINVAL;
+ goto out_err;
+ }
+ }
+ }
+ }
req->cookie = cfg80211_assign_cookie(rdev);
req->nl_portid = info->snd_portid;
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 09/13] wifi: cfg80211: add ingress/egress distance thresholds for FTM
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (7 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 08/13] wifi: cfg80211: add role-based peer limits to FTM capabilities Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 10/13] wifi: cfg80211: add PD-specific preamble and bandwidth capabilities Peddolla Harshavardhan Reddy
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Proximity detection applications need to receive measurement results
only when devices cross specific distance boundaries to avoid
unnecessary host wakeups and reduce power consumption.
Introduce configurable distance-based reporting thresholds that
drivers can use to implement selective result reporting. Add ingress
and egress distance parameters allowing applications to specify when
results should be reported as peers cross these boundaries.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 14 ++++++++++++++
include/uapi/linux/nl80211.h | 15 +++++++++++++++
net/wireless/nl80211.c | 2 ++
net/wireless/pmsr.c | 8 ++++++++
4 files changed, 39 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8c82f33bfc40..b16f36473b2f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4619,6 +4619,18 @@ struct cfg80211_pmsr_result {
* exchanges as configured by @ftms_per_burst. Only valid if
* @non_trigger_based is set. If set to 0, the firmware or driver
* can automatically select an appropriate value.
+ * @ingress_distancemm: optional ingress threshold in units of mm. When set,
+ * the measurement result of the peer needs to be indicated if the device
+ * moves into this range. Measurement results need to be sent on a burst
+ * index basis in this case.
+ * @egress_distancemm: optional egress threshold in units of mm. When set,
+ * the measurement result of the peer needs to be indicated if the device
+ * moves out of this range. Measurement results need to be sent on a burst
+ * index basis in this case.
+ * If neither or only one of @ingress_distancemm and @egress_distancemm
+ * is set, only the specified threshold is used. If both are set, both
+ * thresholds are applied. If neither is set, results are reported without
+ * threshold filtering.
*
* See also nl80211 for the respective attribute documentation.
*/
@@ -4645,6 +4657,8 @@ struct cfg80211_pmsr_ftm_request_peer {
u8 availability_window;
u32 nominal_time;
u32 num_measurements;
+ u64 ingress_distancemm;
+ u64 egress_distancemm;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index a42bae666d02..1400adfee10b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8330,6 +8330,18 @@ enum nl80211_peer_measurement_ftm_type_capa {
* %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
* If the attribute is absent ("no preference"), the driver or firmware
* can choose a suitable value.
+ * @NL80211_PMSR_FTM_REQ_ATTR_PAD: ignore, for u64/s64 padding only.
+ * @NL80211_PMSR_FTM_REQ_ATTR_INGRESS: optional u64 attribute in units of mm.
+ * When specified, the measurement result of the peer needs to be
+ * indicated if the device moves into this range.
+ * @NL80211_PMSR_FTM_REQ_ATTR_EGRESS: optional u64 attribute in units of mm.
+ * When specified, the measurement result of the peer needs to be
+ * indicated if the device moves out of this range.
+ * If neither or only one of @NL80211_PMSR_FTM_REQ_ATTR_INGRESS and
+ * @NL80211_PMSR_FTM_REQ_ATTR_EGRESS is specified, only the specified
+ * threshold is used. If both are specified, both thresholds are applied.
+ * If neither is specified, results are reported without threshold
+ * filtering.
*
* @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
* @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
@@ -8356,6 +8368,9 @@ enum nl80211_peer_measurement_ftm_req {
NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME,
NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION,
NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS,
+ NL80211_PMSR_FTM_REQ_ATTR_PAD,
+ NL80211_PMSR_FTM_REQ_ATTR_INGRESS,
+ NL80211_PMSR_FTM_REQ_ATTR_EGRESS,
/* keep last */
NUM_NL80211_PMSR_FTM_REQ_ATTR,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4f6612311de3..0e0c66fe39db 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -485,6 +485,8 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME] = { .type = NLA_U32 },
[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION] = NLA_POLICY_MAX(NLA_U32, 255),
[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_REQ_ATTR_INGRESS] = { .type = NLA_U64 },
+ [NL80211_PMSR_FTM_REQ_ATTR_EGRESS] = { .type = NLA_U64 },
};
static const struct nla_policy
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 432d34be7945..46c444d0327b 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -264,6 +264,14 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS]);
}
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_INGRESS])
+ out->ftm.ingress_distancemm =
+ nla_get_u64(tb[NL80211_PMSR_FTM_REQ_ATTR_INGRESS]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_EGRESS])
+ out->ftm.egress_distancemm =
+ nla_get_u64(tb[NL80211_PMSR_FTM_REQ_ATTR_EGRESS]);
+
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 10/13] wifi: cfg80211: add PD-specific preamble and bandwidth capabilities
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (8 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 09/13] wifi: cfg80211: add ingress/egress distance thresholds for FTM Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 11/13] wifi: cfg80211: allow suppressing FTM result reporting for PD requests Peddolla Harshavardhan Reddy
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Devices may support different preamble and bandwidth configurations
for proximity detection (PD) ranging versus standard ranging. Add
separate pd_preambles and pd_bandwidths fields to
cfg80211_pmsr_capabilities to allow drivers to advertise PD-specific
capabilities.
Expose these over nl80211 using new attributes
NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES and
NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS, advertised only when
pd_support is set.
For PD requests, validate bandwidth and preamble against pd_bandwidths
and pd_preambles. For non-PD requests, validate against the existing
bandwidths and preambles fields.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 6 ++++++
include/uapi/linux/nl80211.h | 10 ++++++++++
net/wireless/nl80211.c | 12 ++++++++++++
net/wireless/pmsr.c | 21 +++++++++++++++++++--
4 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b16f36473b2f..1d19cb2f14fa 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6050,6 +6050,10 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type);
* @ftm.concurrent_ista_rsta_support: indicates if the device can
* simultaneously act as initiator and responder in a multi-peer
* measurement request. Only valid if @ftm.rsta_support is set.
+ * @ftm.pd_preambles: bitmap of preambles supported (&enum nl80211_preamble)
+ * for PD ranging requests. Ignored if @ftm.type.pd_support is not set.
+ * @ftm.pd_bandwidths: bitmap of bandwidths supported (&enum nl80211_chan_width)
+ * for PD ranging requests. Ignored if @ftm.type.pd_support is not set.
*/
struct cfg80211_pmsr_capabilities {
unsigned int max_peers;
@@ -6096,6 +6100,8 @@ struct cfg80211_pmsr_capabilities {
pd_support:1;
} type;
u8 concurrent_ista_rsta_support:1;
+ u32 pd_preambles;
+ u32 pd_bandwidths;
} ftm;
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1400adfee10b..f701b862e50f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8178,6 +8178,14 @@ enum nl80211_peer_measurement_attrs {
* to estimate the burst period to be given in the FTM request for the
* NTB ranging case. If non-zero, this value will be used to validate
* the nominal time in the FTM request.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES: u32 bitmap of values from
+ * &enum nl80211_preamble indicating the supported preambles for PD
+ * ranging requests. Only valid if %NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT
+ * is set.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS: u32 bitmap of values from
+ * &enum nl80211_chan_width indicating the supported channel bandwidths
+ * for PD ranging requests. Only valid if
+ * %NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT is set.
*
* @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal
* @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number
@@ -8214,6 +8222,8 @@ enum nl80211_peer_measurement_ftm_capa {
NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS,
NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA,
NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB,
+ NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES,
+ NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS,
/* keep last */
NUM_NL80211_PMSR_FTM_CAPA_ATTR,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0e0c66fe39db..322c7ed881d8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2614,6 +2614,18 @@ nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
if (cap->ftm.concurrent_ista_rsta_support &&
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT))
return -ENOBUFS;
+
+ if (cap->ftm.type.pd_support) {
+ if (cap->ftm.pd_preambles &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES,
+ cap->ftm.pd_preambles))
+ return -ENOBUFS;
+ if (cap->ftm.pd_bandwidths &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS,
+ cap->ftm.pd_bandwidths))
+ return -ENOBUFS;
+ }
+
nla_nest_end(msg, ftm);
return 0;
}
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 46c444d0327b..202e2c46522b 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -17,11 +17,19 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
u32 preamble = NL80211_PREAMBLE_DMG; /* only optional in DMG */
/* validate existing data */
- if (!(rdev->wiphy.pmsr_capa->ftm.bandwidths & BIT(out->chandef.width))) {
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_INFRA &&
+ !(capa->ftm.bandwidths & BIT(out->chandef.width))) {
NL_SET_ERR_MSG(info->extack, "FTM: unsupported bandwidth");
return -EINVAL;
}
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ !(capa->ftm.pd_bandwidths & BIT(out->chandef.width))) {
+ NL_SET_ERR_MSG(info->extack,
+ "FTM: unsupported bandwidth for PD request");
+ return -EINVAL;
+ }
+
/* no validation needed - was already done via nested policy */
nla_parse_nested_deprecated(tb, NL80211_PMSR_FTM_REQ_ATTR_MAX, ftmreq,
NULL, NULL);
@@ -44,13 +52,22 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
}
}
- if (!(capa->ftm.preambles & BIT(preamble))) {
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_INFRA &&
+ !(capa->ftm.preambles & BIT(preamble))) {
NL_SET_ERR_MSG_ATTR(info->extack,
tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE],
"FTM: invalid preamble");
return -EINVAL;
}
+ if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ !(capa->ftm.pd_preambles & BIT(preamble))) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE],
+ "FTM: invalid preamble for PD request");
+ return -EINVAL;
+ }
+
out->ftm.preamble = preamble;
out->ftm.burst_period = 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 11/13] wifi: cfg80211: allow suppressing FTM result reporting for PD requests
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (9 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 10/13] wifi: cfg80211: add PD-specific preamble and bandwidth capabilities Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 12/13] wifi: cfg80211: add LTF keyseed support for secure ranging Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 13/13] wifi: mac80211_hwsim: Add support for extended FTM ranging Peddolla Harshavardhan Reddy
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Proximity detection often does not require detailed ranging
measurements, yet userspace currently receives full FTM results for
every request, causing unnecessary data transfer, host wakeups, and
processing overhead.
Add an optional control to suppress ranging result reporting for
peer-to-peer PD requests. Introduce the
NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS flag; when set with a
PD request, the device may perform the measurements (e.g. when acting
as RSTA) but must not report the measurement results to userspace.
Validate that the flag is only accepted when request_type is set to
NL80211_PMSR_FTM_REQ_TYPE_PD, reject otherwise.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 6 ++++++
include/uapi/linux/nl80211.h | 6 ++++++
net/wireless/nl80211.c | 1 +
net/wireless/pmsr.c | 11 +++++++++++
4 files changed, 24 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d19cb2f14fa..3efa8a124bba 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4631,6 +4631,11 @@ struct cfg80211_pmsr_result {
* is set, only the specified threshold is used. If both are set, both
* thresholds are applied. If neither is set, results are reported without
* threshold filtering.
+ * @pd_suppress_range_results: flag to suppress ranging results for PD
+ * requests. When set, the device performs ranging measurements to
+ * provide ranging services to a peer (e.g. in RSTA role) but does
+ * not report the measurement results to userspace. Only valid when
+ * @request_type is %NL80211_PMSR_FTM_REQ_TYPE_PD.
*
* See also nl80211 for the respective attribute documentation.
*/
@@ -4659,6 +4664,7 @@ struct cfg80211_pmsr_ftm_request_peer {
u32 num_measurements;
u64 ingress_distancemm;
u64 egress_distancemm;
+ u8 pd_suppress_range_results:1;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f701b862e50f..bbf1447162d8 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8352,6 +8352,11 @@ enum nl80211_peer_measurement_ftm_type_capa {
* threshold is used. If both are specified, both thresholds are applied.
* If neither is specified, results are reported without threshold
* filtering.
+ * @NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS: Flag to suppress ranging
+ * results for PD requests. When set, ranging measurements are performed
+ * but results are not reported to userspace, regardless of ranging role
+ * or type. Only valid when %NL80211_PMSR_PEER_ATTR_REQ_TYPE is set to
+ * %NL80211_PMSR_FTM_REQ_TYPE_PD.
*
* @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
* @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
@@ -8381,6 +8386,7 @@ enum nl80211_peer_measurement_ftm_req {
NL80211_PMSR_FTM_REQ_ATTR_PAD,
NL80211_PMSR_FTM_REQ_ATTR_INGRESS,
NL80211_PMSR_FTM_REQ_ATTR_EGRESS,
+ NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS,
/* keep last */
NUM_NL80211_PMSR_FTM_REQ_ATTR,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 322c7ed881d8..feb770fa6a87 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -487,6 +487,7 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS] = { .type = NLA_U32 },
[NL80211_PMSR_FTM_REQ_ATTR_INGRESS] = { .type = NLA_U64 },
[NL80211_PMSR_FTM_REQ_ATTR_EGRESS] = { .type = NLA_U64 },
+ [NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS] = { .type = NLA_FLAG },
};
static const struct nla_policy
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 202e2c46522b..1c2db1f5a615 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -289,6 +289,17 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
out->ftm.egress_distancemm =
nla_get_u64(tb[NL80211_PMSR_FTM_REQ_ATTR_EGRESS]);
+ out->ftm.pd_suppress_range_results =
+ nla_get_flag(tb[NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS]);
+
+ if (out->ftm.request_type != NL80211_PMSR_FTM_REQ_TYPE_PD &&
+ out->ftm.pd_suppress_range_results) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS],
+ "FTM: suppress range result flag only valid for PD requests");
+ return -EINVAL;
+ }
+
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 12/13] wifi: cfg80211: add LTF keyseed support for secure ranging
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (10 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 11/13] wifi: cfg80211: allow suppressing FTM result reporting for PD requests Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
2026-04-20 9:08 ` [PATCH wireless-next v5 13/13] wifi: mac80211_hwsim: Add support for extended FTM ranging Peddolla Harshavardhan Reddy
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
Currently there is no way to install an LTF key seed that can be
used in non-trigger-based (NTB) and trigger-based (TB) FTM ranging
to protect NDP frames. Without this, drivers cannot enable PHY-layer
security for peer measurement sessions, leaving ranging measurements
vulnerable to eavesdropping and manipulation.
Introduce NL80211_KEY_LTF_SEED attribute and the dedicated extended
feature flag NL80211_EXT_FEATURE_SET_KEY_LTF_SEED to allow drivers
to advertise and install LTF key seeds via nl80211. The key seed
must be configured beforehand to ensure the peer measurement session
is secure. The driver must advertise both NL80211_EXT_FEATURE_SECURE_LTF
and NL80211_EXT_FEATURE_SET_KEY_LTF_SEED for the key seed installation
to be permitted.
The LTF key seed is pairwise key material and must only be used with
pairwise key type. Reject attempts to use it with other key types.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/linux/ieee80211.h | 1 +
include/net/cfg80211.h | 4 ++++
include/uapi/linux/nl80211.h | 18 ++++++++++++++++++
net/wireless/nl80211.c | 7 +++++++
net/wireless/util.c | 15 +++++++++++++++
5 files changed, 45 insertions(+)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 23f9df9be837..11106589acc6 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2236,6 +2236,7 @@ struct ieee80211_multiple_bssid_configuration {
#define WLAN_AKM_SUITE_WFA_DPP SUITE(WLAN_OUI_WFA, 2)
#define WLAN_MAX_KEY_LEN 32
+#define WLAN_MAX_SECURE_LTF_KEYSEED_LEN 48
#define WLAN_PMK_NAME_LEN 16
#define WLAN_PMKID_LEN 16
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3efa8a124bba..1d5de82ad4c5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -830,6 +830,8 @@ struct vif_params {
* @seq_len: length of @seq.
* @vlan_id: vlan_id for VLAN group key (if nonzero)
* @mode: key install mode (RX_TX, NO_TX or SET_TX)
+ * @ltf_keyseed: LTF key seed material
+ * @ltf_keyseed_len: length of LTF key seed material
*/
struct key_params {
const u8 *key;
@@ -839,6 +841,8 @@ struct key_params {
u16 vlan_id;
u32 cipher;
enum nl80211_key_mode mode;
+ const u8 *ltf_keyseed;
+ size_t ltf_keyseed_len;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index bbf1447162d8..190bae9efdd9 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -5803,6 +5803,18 @@ enum nl80211_key_default_types {
* @NL80211_KEY_MODE: the mode from enum nl80211_key_mode.
* Defaults to @NL80211_KEY_RX_TX.
* @NL80211_KEY_DEFAULT_BEACON: flag indicating default Beacon frame key
+ * @NL80211_KEY_LTF_SEED: LTF key seed is used by the driver to generate
+ * secure LTF keys used in case of peer measurement request with FTM
+ * request type as either %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED
+ * or %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED. Secure LTF key seeds
+ * will help enable PHY security in peer measurement session.
+ * The LTF key seed is installed along with the TK (Temporal Key) using
+ * %NL80211_CMD_NEW_KEY. The TK is configured using the
+ * %NL80211_ATTR_KEY_DATA attribute, while the LTF key seed is configured
+ * using this attribute. Both keys must be configured before initiation
+ * of peer measurement to ensure peer measurement session is secure.
+ * Only valid if %NL80211_EXT_FEATURE_SET_KEY_LTF_SEED is set. This
+ * attribute is restricted to pairwise keys (%NL80211_KEYTYPE_PAIRWISE).
*
* @__NL80211_KEY_AFTER_LAST: internal
* @NL80211_KEY_MAX: highest key attribute
@@ -5819,6 +5831,7 @@ enum nl80211_key_attributes {
NL80211_KEY_DEFAULT_TYPES,
NL80211_KEY_MODE,
NL80211_KEY_DEFAULT_BEACON,
+ NL80211_KEY_LTF_SEED,
/* keep last */
__NL80211_KEY_AFTER_LAST,
@@ -7048,6 +7061,10 @@ enum nl80211_feature_flags {
* forward frames with a matching MAC address to userspace during
* the off-channel period.
*
+ * @NL80211_EXT_FEATURE_SET_KEY_LTF_SEED: Driver supports installing the
+ * LTF key seed via %NL80211_KEY_LTF_SEED. The seed is used to generate
+ * secure LTF keys for secure LTF measurement sessions.
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -7128,6 +7145,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_ASSOC_FRAME_ENCRYPTION,
NL80211_EXT_FEATURE_IEEE8021X_AUTH,
NL80211_EXT_FEATURE_ROC_ADDR_FILTER,
+ NL80211_EXT_FEATURE_SET_KEY_LTF_SEED,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index feb770fa6a87..9d6810cfb3d6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1103,6 +1103,8 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
[NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
[NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
[NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
+ [NL80211_KEY_LTF_SEED] = { .type = NLA_BINARY,
+ .len = WLAN_MAX_SECURE_LTF_KEYSEED_LEN },
};
/* policy for the key default flags */
@@ -1634,6 +1636,11 @@ static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
if (tb[NL80211_KEY_MODE])
k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);
+ if (tb[NL80211_KEY_LTF_SEED]) {
+ k->p.ltf_keyseed = nla_data(tb[NL80211_KEY_LTF_SEED]);
+ k->p.ltf_keyseed_len = nla_len(tb[NL80211_KEY_LTF_SEED]);
+ }
+
return 0;
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index df407ce9db3d..f5a95405280d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -424,6 +424,21 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher))
return -EINVAL;
+ if (params->ltf_keyseed) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_LTF) ||
+ !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_SET_KEY_LTF_SEED))
+ return -EOPNOTSUPP;
+
+ /*
+ * LTF key seed is pairwise key material and must only be
+ * used with a pairwise key
+ */
+ if (!pairwise)
+ return -EINVAL;
+ }
+
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH wireless-next v5 13/13] wifi: mac80211_hwsim: Add support for extended FTM ranging
2026-04-20 9:08 [PATCH wireless-next v5 00/13] wifi: Ranging support enhancements Peddolla Harshavardhan Reddy
` (11 preceding siblings ...)
2026-04-20 9:08 ` [PATCH wireless-next v5 12/13] wifi: cfg80211: add LTF keyseed support for secure ranging Peddolla Harshavardhan Reddy
@ 2026-04-20 9:08 ` Peddolla Harshavardhan Reddy
12 siblings, 0 replies; 14+ messages in thread
From: Peddolla Harshavardhan Reddy @ 2026-04-20 9:08 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita, peddolla.reddy
From: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
Introduce support for continuous ranging and advanced timing
parameters in the FTM request, response, and capability paths.
This enables more flexible ranging scenarios with improved control
over measurement timing and session management.
Co-developed-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
Signed-off-by: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 217 ++++++++++++++++++
1 file changed, 217 insertions(+)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 1fcf5d0d2e13..a06bb22dbdf0 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -848,6 +848,17 @@ hwsim_ftm_result_policy[NL80211_PMSR_FTM_RESP_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD] = { .type = NLA_U64 },
[NL80211_PMSR_FTM_RESP_ATTR_LCI] = { .type = NLA_STRING },
[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_STRING },
+ [NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS] = { .type = NLA_U8 },
+ [NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS] = { .type = NLA_U8 },
+ [NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR] = { .type = NLA_FLAG },
};
static const struct nla_policy
@@ -881,6 +892,19 @@ hwsim_pmsr_peers_result_policy[NL80211_PMSR_ATTR_MAX + 1] = {
[NL80211_PMSR_ATTR_PEERS] = NLA_POLICY_NESTED_ARRAY(hwsim_pmsr_peer_result_policy),
};
+static const struct nla_policy
+hwsim_ftm_role_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = {
+ [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA] = { .type = NLA_FLAG },
+};
+
+static const struct nla_policy
+hwsim_ftm_type_capa_policy[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX + 1] = {
+ [NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT] = { .type = NLA_FLAG },
+};
+
static const struct nla_policy
hwsim_ftm_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_CAPA_ATTR_ASAP] = { .type = NLA_FLAG },
@@ -893,6 +917,19 @@ hwsim_ftm_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST] = NLA_POLICY_MAX(NLA_U8, 31),
[NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
[NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS] = { .type = NLA_U8 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS] = { .type = NLA_U8 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS] =
+ NLA_POLICY_NESTED(hwsim_ftm_role_capa_policy),
+ [NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS] =
+ NLA_POLICY_NESTED(hwsim_ftm_role_capa_policy),
+ [NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS] =
+ NLA_POLICY_NESTED(hwsim_ftm_type_capa_policy),
+ [NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT] = { .type = NLA_FLAG },
};
static const struct nla_policy
@@ -3623,6 +3660,47 @@ static int mac80211_hwsim_send_pmsr_ftm_request_peer(struct sk_buff *msg,
if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR, request->bss_color))
return -ENOBUFS;
+ if (request->min_time_between_measurements &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS,
+ request->min_time_between_measurements))
+ return -ENOBUFS;
+
+ if (request->max_time_between_measurements &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS,
+ request->max_time_between_measurements))
+ return -ENOBUFS;
+
+ if (request->availability_window &&
+ nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION,
+ request->availability_window))
+ return -ENOBUFS;
+
+ if (request->nominal_time &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME,
+ request->nominal_time))
+ return -ENOBUFS;
+
+ if (request->num_measurements &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS,
+ request->num_measurements))
+ return -ENOBUFS;
+
+ if (request->ingress_distancemm &&
+ nla_put_u64_64bit(msg, NL80211_PMSR_FTM_REQ_ATTR_INGRESS,
+ request->ingress_distancemm,
+ NL80211_PMSR_FTM_REQ_ATTR_PAD))
+ return -ENOBUFS;
+
+ if (request->egress_distancemm &&
+ nla_put_u64_64bit(msg, NL80211_PMSR_FTM_REQ_ATTR_EGRESS,
+ request->egress_distancemm,
+ NL80211_PMSR_FTM_REQ_ATTR_PAD))
+ return -ENOBUFS;
+
+ if (request->pd_suppress_range_results &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS))
+ return -ENOBUFS;
+
nla_nest_end(msg, ftm);
return 0;
@@ -3992,6 +4070,69 @@ static int mac80211_hwsim_parse_ftm_result(struct nlattr *ftm,
result->civicloc_len = nla_len(tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]);
}
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT]) {
+ result->tx_ltf_repetition_count_valid = 1;
+ result->tx_ltf_repetition_count =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT]) {
+ result->rx_ltf_repetition_count_valid = 1;
+ result->rx_ltf_repetition_count =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]) {
+ result->max_time_between_measurements_valid = 1;
+ result->max_time_between_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]) {
+ result->min_time_between_measurements_valid = 1;
+ result->min_time_between_measurements =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS]) {
+ result->num_tx_spatial_streams_valid = 1;
+ result->num_tx_spatial_streams =
+ nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS]) {
+ result->num_rx_spatial_streams_valid = 1;
+ result->num_rx_spatial_streams =
+ nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME]) {
+ result->nominal_time_valid = 1;
+ result->nominal_time =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW]) {
+ result->availability_window_valid = 1;
+ result->availability_window =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH]) {
+ result->chan_width_valid = 1;
+ result->chan_width =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH]);
+ }
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE]) {
+ result->preamble_valid = 1;
+ result->preamble =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE]);
+ }
+
+ result->is_delayed_lmr =
+ nla_get_flag(tb[NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR]);
+
return 0;
}
@@ -6532,6 +6673,82 @@ static int parse_ftm_capa(const struct nlattr *ftm_capa, struct cfg80211_pmsr_ca
out->ftm.trigger_based = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED];
out->ftm.non_trigger_based = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED];
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS])
+ out->ftm.max_no_of_tx_antennas =
+ nla_get_u8(tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS])
+ out->ftm.max_no_of_rx_antennas =
+ nla_get_u8(tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA])
+ out->ftm.min_allowed_ranging_interval_edca =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB])
+ out->ftm.min_allowed_ranging_interval_ntb =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES])
+ out->ftm.pd_preambles =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS])
+ out->ftm.pd_bandwidths =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS]) {
+ struct nlattr *ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1];
+
+ if (!nla_parse_nested(ista_tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX,
+ tb[NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS],
+ hwsim_ftm_role_capa_policy, NULL)) {
+ out->ftm.ista.support_ntb =
+ !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB];
+ out->ftm.ista.support_tb =
+ !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB];
+ out->ftm.ista.support_edca =
+ !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA];
+ if (ista_tb[NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE])
+ out->ftm.ista.max_peers =
+ nla_get_u32(ista_tb[NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE]);
+ }
+ }
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS]) {
+ struct nlattr *rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1];
+
+ if (!nla_parse_nested(rsta_tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX,
+ tb[NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS],
+ hwsim_ftm_role_capa_policy, NULL)) {
+ out->ftm.rsta.support_ntb =
+ !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB];
+ out->ftm.rsta.support_tb =
+ !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB];
+ out->ftm.rsta.support_edca =
+ !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA];
+ if (rsta_tb[NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE])
+ out->ftm.rsta.max_peers =
+ nla_get_u32(rsta_tb[NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE]);
+ }
+ }
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS]) {
+ struct nlattr *type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX + 1];
+
+ if (!nla_parse_nested(type_tb, NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX,
+ tb[NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS],
+ hwsim_ftm_type_capa_policy, NULL)) {
+ out->ftm.type.infra_support =
+ !!type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT];
+ out->ftm.type.pd_support =
+ !!type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT];
+ }
+ }
+
+ out->ftm.concurrent_ista_rsta_support =
+ !!tb[NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT];
+
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread