* Re: [PATCH wireless-next v3 13/15] wifi: cfg80211: add result reporting control for PD requests
From: Peddolla Harshavardhan Reddy @ 2026-03-20 19:04 UTC (permalink / raw)
To: Stern, Avraham, johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, kavita.kavita@oss.qualcomm.com
In-Reply-To: <CH3PR11MB8383F6C4E5840702AF996AB9FF44A@CH3PR11MB8383.namprd11.prod.outlook.com>
On 13-Mar-26 2:46 AM, Stern, Avraham wrote:
>
>> From: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
>> Sent: Thursday, March 5, 2026 6:07 PM
>> To: johannes@sipsolutions.net
>> Cc: linux-wireless@vger.kernel.org; kavita.kavita@oss.qualcomm.com
>> Subject: [PATCH wireless-next v3 13/15] wifi: cfg80211: add result reporting control for PD requests
>> Proximity detection applications may not need detailed ranging measurements for every request, yet currently receive all results causing unnecessary data transfer, host wakeups, and processing overhead. Currently, there is no mechanism for applications to suppress result reporting when only proximity detection is needed.
>> Introduce optional result suppression control that drivers can use to implement selective result reporting. Add a flag allowing applications to disable ranging reports when only proximity detection is needed, enabling drivers to reduce unnecessary data transfer and host wakeups. This flag cannot be combined > with range report or LMR feedback requests in RSTA mode as these require result reporting.
> As commented on previous patch, LMR feedback and range report are mandatory for PD ranging. Results can be not reported regardless.
yes you are right, fixed in the next version.
>
>> + * @pd_suppress_range_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 @pd_request is set. Cannot be used with @range_report
> The title said "applications may not need detailed ranging measurements for every request", but here it says no results at all...
> So this is intended for providing ranging services to another peer?
Updated in the next version.
>
>
> ---------------------------------------------------------------------
> A member of the Intel Corporation group of companies
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
^ permalink raw reply
* [PATCH 06/11 net-next v4] drivers: net: drop ipv6_stub usage and use direct function calls
From: Fernando Fernandez Mancera @ 2026-03-20 18:56 UTC (permalink / raw)
To: netdev
Cc: Fernando Fernandez Mancera, Ricardo B. Marlière,
Jason A. Donenfeld, Antonio Quartulli, Edward Cree,
Jason Gunthorpe, Leon Romanovsky, Zhu Yanjun, Saeed Mahameed,
Tariq Toukan, Mark Bloch, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Boris Pismenny,
Simon Horman, Pablo Neira Ayuso, Harald Welte, Sabrina Dubroca,
Oliver Neukum, Stanislav Yakovlev, Nikolay Aleksandrov,
Ido Schimmel, Edward Srouji, Parav Pandit, Vlad Dumitrescu,
Kees Cook, Jianbo Liu, Gal Pressman, Guillaume Nault,
Alexei Lazar, Cosmin Ratiu, Carolina Jubran, Alexandre Cassen,
Petr Machata, Stanislav Fomichev, linux-rdma, linux-kernel,
oss-drivers, linux-net-drivers, osmocom-net-gprs, linux-usb,
wireguard, linux-wireless, bridge
In-Reply-To: <20260320185649.5411-1-fmancera@suse.de>
As IPv6 is built-in only, the ipv6_stub infrastructure is no longer
necessary.
Convert all drivers currently utilizing ipv6_stub to make direct
function calls. The fallback functions introduced previously will
prevent linkage errors when CONFIG_IPV6 is disabled.
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
Tested-by: Ricardo B. Marlière <rbm@suse.com>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Antonio Quartulli <antonio@openvpn.net>
Reviewed-by: Edward Cree <ecree.xilinx@gmail.com>
---
drivers/infiniband/core/addr.c | 3 +--
drivers/infiniband/sw/rxe/rxe_net.c | 6 +++---
.../ethernet/mellanox/mlx5/core/en/rep/neigh.c | 9 +++++----
.../net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 3 +--
.../mellanox/mlx5/core/en/tc_tun_encap.c | 2 +-
.../mellanox/mlx5/core/en_accel/ipsec.c | 1 -
.../net/ethernet/mellanox/mlx5/core/en_rep.c | 1 -
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 1 -
.../net/ethernet/netronome/nfp/flower/action.c | 2 +-
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 7 +++----
drivers/net/ethernet/sfc/tc_counters.c | 2 +-
drivers/net/ethernet/sfc/tc_encap_actions.c | 5 ++---
drivers/net/geneve.c | 1 -
drivers/net/gtp.c | 2 +-
drivers/net/ovpn/peer.c | 3 +--
drivers/net/ovpn/udp.c | 3 +--
drivers/net/usb/cdc_mbim.c | 17 +++++++++--------
drivers/net/vxlan/vxlan_core.c | 11 +++++------
drivers/net/vxlan/vxlan_multicast.c | 6 ++----
drivers/net/wireguard/socket.c | 3 +--
drivers/net/wireless/intel/ipw2x00/ipw2100.c | 2 +-
net/bridge/br_arp_nd_proxy.c | 3 +--
22 files changed, 40 insertions(+), 53 deletions(-)
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 866746695712..48d4b06384ec 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -41,7 +41,6 @@
#include <net/neighbour.h>
#include <net/route.h>
#include <net/netevent.h>
-#include <net/ipv6_stubs.h>
#include <net/ip6_route.h>
#include <rdma/ib_addr.h>
#include <rdma/ib_cache.h>
@@ -411,7 +410,7 @@ static int addr6_resolve(struct sockaddr *src_sock,
fl6.saddr = src_in->sin6_addr;
fl6.flowi6_oif = addr->bound_dev_if;
- dst = ipv6_stub->ipv6_dst_lookup_flow(addr->net, NULL, &fl6, NULL);
+ dst = ip6_dst_lookup_flow(addr->net, NULL, &fl6, NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 0bd0902b11f7..cbc646a30003 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -138,9 +138,9 @@ static struct dst_entry *rxe_find_route6(struct rxe_qp *qp,
memcpy(&fl6.daddr, daddr, sizeof(*daddr));
fl6.flowi6_proto = IPPROTO_UDP;
- ndst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(recv_sockets.sk6->sk),
- recv_sockets.sk6->sk, &fl6,
- NULL);
+ ndst = ip6_dst_lookup_flow(sock_net(recv_sockets.sk6->sk),
+ recv_sockets.sk6->sk, &fl6,
+ NULL);
if (IS_ERR(ndst)) {
rxe_dbg_qp(qp, "no route to %pI6\n", daddr);
return NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
index d220b045b331..648f4521c096 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
@@ -10,6 +10,7 @@
#include <linux/notifier.h>
#include <net/netevent.h>
#include <net/arp.h>
+#include <net/ndisc.h>
#include "neigh.h"
#include "tc.h"
#include "en_rep.h"
@@ -18,8 +19,8 @@
static unsigned long mlx5e_rep_ipv6_interval(void)
{
- if (IS_ENABLED(CONFIG_IPV6) && ipv6_stub->nd_tbl)
- return NEIGH_VAR(&ipv6_stub->nd_tbl->parms, DELAY_PROBE_TIME);
+ if (IS_ENABLED(CONFIG_IPV6) && ipv6_mod_enabled())
+ return NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME);
return ~0UL;
}
@@ -217,7 +218,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
case NETEVENT_NEIGH_UPDATE:
n = ptr;
#if IS_ENABLED(CONFIG_IPV6)
- if (n->tbl != ipv6_stub->nd_tbl && n->tbl != &arp_tbl)
+ if (n->tbl != &nd_tbl && n->tbl != &arp_tbl)
#else
if (n->tbl != &arp_tbl)
#endif
@@ -238,7 +239,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
* done per device delay prob time parameter.
*/
#if IS_ENABLED(CONFIG_IPV6)
- if (!p->dev || (p->tbl != ipv6_stub->nd_tbl && p->tbl != &arp_tbl))
+ if (!p->dev || (p->tbl != &nd_tbl && p->tbl != &arp_tbl))
#else
if (!p->dev || p->tbl != &arp_tbl)
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
index a14f216048cd..de74dbfe7b20 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
@@ -453,8 +453,7 @@ static int mlx5e_route_lookup_ipv6_get(struct mlx5e_priv *priv,
if (tunnel && tunnel->get_remote_ifindex)
attr->fl.fl6.flowi6_oif = tunnel->get_remote_ifindex(dev);
- dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(dev), NULL, &attr->fl.fl6,
- NULL);
+ dst = ip6_dst_lookup_flow(dev_net(dev), NULL, &attr->fl.fl6, NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
index bfd401bee9e8..8b827201935e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
@@ -402,7 +402,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
tbl = &arp_tbl;
#if IS_ENABLED(CONFIG_IPV6)
else if (m_neigh->family == AF_INET6)
- tbl = ipv6_stub->nd_tbl;
+ tbl = &nd_tbl;
#endif
else
return;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
index 64e13747084e..a52e12c3c95a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -36,7 +36,6 @@
#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <net/netevent.h>
-#include <net/ipv6_stubs.h>
#include "en.h"
#include "eswitch.h"
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 1db4ecb2356f..5ec5cae8d229 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -38,7 +38,6 @@
#include <net/pkt_cls.h>
#include <net/act_api.h>
#include <net/devlink.h>
-#include <net/ipv6_stubs.h>
#include "eswitch.h"
#include "en.h"
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 397a93584fd6..a9001d1c902f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -41,7 +41,6 @@
#include <linux/refcount.h>
#include <linux/completion.h>
#include <net/arp.h>
-#include <net/ipv6_stubs.h>
#include <net/bareudp.h>
#include <net/bonding.h>
#include <net/dst_metadata.h>
diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c
index aca2a7417af3..ae2f8b31adfb 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/action.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/action.c
@@ -470,7 +470,7 @@ nfp_fl_set_tun(struct nfp_app *app, struct nfp_fl_set_tun *set_tun,
flow.daddr = ip_tun->key.u.ipv6.dst;
flow.flowi4_proto = IPPROTO_UDP;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow, NULL);
+ dst = ip6_dst_lookup_flow(net, NULL, &flow, NULL);
if (!IS_ERR(dst)) {
set_tun->ttl = ip6_dst_hoplimit(dst);
dst_release(dst);
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index 0cef0e2b85d0..ca30702f8878 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -650,7 +650,7 @@ static void nfp_tun_neigh_update(struct work_struct *work)
flow6.daddr = *(struct in6_addr *)n->primary_key;
if (!neigh_invalid) {
struct dst_entry *dst;
- /* Use ipv6_dst_lookup_flow to populate flow6->saddr
+ /* Use ip6_dst_lookup_flow to populate flow6->saddr
* and other fields. This information is only needed
* for new entries, lookup can be skipped when an entry
* gets invalidated - as only the daddr is needed for
@@ -730,7 +730,7 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
return NOTIFY_DONE;
}
#if IS_ENABLED(CONFIG_IPV6)
- if (n->tbl != ipv6_stub->nd_tbl && n->tbl != &arp_tbl)
+ if (n->tbl != &nd_tbl && n->tbl != &arp_tbl)
#else
if (n->tbl != &arp_tbl)
#endif
@@ -815,8 +815,7 @@ void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
flow.flowi6_proto = IPPROTO_UDP;
#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
- dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(netdev), NULL, &flow,
- NULL);
+ dst = ip6_dst_lookup_flow(dev_net(netdev), NULL, &flow, NULL);
if (IS_ERR(dst))
goto fail_rcu_unlock;
#else
diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c
index d168282f30bf..b84235e93ffe 100644
--- a/drivers/net/ethernet/sfc/tc_counters.c
+++ b/drivers/net/ethernet/sfc/tc_counters.c
@@ -112,7 +112,7 @@ static void efx_tc_counter_work(struct work_struct *work)
encap->neigh->egdev);
else
#if IS_ENABLED(CONFIG_IPV6)
- n = neigh_lookup(ipv6_stub->nd_tbl,
+ n = neigh_lookup(&nd_tbl,
&encap->neigh->dst_ip6,
encap->neigh->egdev);
#else
diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.c b/drivers/net/ethernet/sfc/tc_encap_actions.c
index da35705cc5e1..db222abef53b 100644
--- a/drivers/net/ethernet/sfc/tc_encap_actions.c
+++ b/drivers/net/ethernet/sfc/tc_encap_actions.c
@@ -149,8 +149,7 @@ static int efx_bind_neigh(struct efx_nic *efx,
#if IS_ENABLED(CONFIG_IPV6)
struct dst_entry *dst;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow6,
- NULL);
+ dst = ip6_dst_lookup_flow(net, NULL, &flow6, NULL);
rc = PTR_ERR_OR_ZERO(dst);
if (rc) {
NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for IPv6 encap");
@@ -531,7 +530,7 @@ static int efx_neigh_event(struct efx_nic *efx, struct neighbour *n)
if (n->tbl == &arp_tbl) {
keysize = sizeof(keys.dst_ip);
#if IS_ENABLED(CONFIG_IPV6)
- } else if (n->tbl == ipv6_stub->nd_tbl) {
+ } else if (n->tbl == &nd_tbl) {
ipv6 = true;
keysize = sizeof(keys.dst_ip6);
#endif
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 01cdd06102e0..c6563367d382 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -12,7 +12,6 @@
#include <linux/module.h>
#include <linux/etherdevice.h>
#include <linux/hash.h>
-#include <net/ipv6_stubs.h>
#include <net/dst_metadata.h>
#include <net/gro_cells.h>
#include <net/rtnetlink.h>
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index e8949f556209..70b9e58b9b78 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -374,7 +374,7 @@ static struct rt6_info *ip6_route_output_gtp(struct net *net,
fl6->saddr = *saddr;
fl6->flowi6_proto = sk->sk_protocol;
- dst = ipv6_stub->ipv6_dst_lookup_flow(net, sk, fl6, NULL);
+ dst = ip6_dst_lookup_flow(net, sk, fl6, NULL);
if (IS_ERR(dst))
return ERR_PTR(-ENETUNREACH);
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 26b55d813f0e..c02dfab51a6e 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -827,8 +827,7 @@ static struct in6_addr ovpn_nexthop_from_rt6(struct ovpn_priv *ovpn,
.daddr = dest,
};
- entry = ipv6_stub->ipv6_dst_lookup_flow(dev_net(ovpn->dev), NULL, &fl,
- NULL);
+ entry = ip6_dst_lookup_flow(dev_net(ovpn->dev), NULL, &fl, NULL);
if (IS_ERR(entry)) {
net_dbg_ratelimited("%s: no route to host %pI6c\n",
netdev_name(ovpn->dev), &dest);
diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c
index 272b535ecaad..059e896b4a2f 100644
--- a/drivers/net/ovpn/udp.c
+++ b/drivers/net/ovpn/udp.c
@@ -14,7 +14,6 @@
#include <net/addrconf.h>
#include <net/dst_cache.h>
#include <net/route.h>
-#include <net/ipv6_stubs.h>
#include <net/transp_v6.h>
#include <net/udp.h>
#include <net/udp_tunnel.h>
@@ -251,7 +250,7 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind,
dst_cache_reset(cache);
}
- dst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(sk), sk, &fl, NULL);
+ dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl, NULL);
if (IS_ERR(dst)) {
ret = PTR_ERR(dst);
net_dbg_ratelimited("%s: no route to host %pISpc: %d\n",
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index dbf01210b0e7..877fb0ed7d3d 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -20,7 +20,6 @@
#include <linux/usb/cdc_ncm.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
-#include <net/ipv6_stubs.h>
#include <net/ndisc.h>
/* alternative VLAN for IP session 0 if not untagged */
@@ -302,6 +301,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
return NULL;
}
+#if IS_ENABLED(CONFIG_IPV6)
/* Some devices are known to send Neighbor Solicitation messages and
* require Neighbor Advertisement replies. The IPv6 core will not
* respond since IFF_NOARP is set, so we must handle them ourselves.
@@ -342,12 +342,11 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
is_router = !!READ_ONCE(in6_dev->cnf.forwarding);
in6_dev_put(in6_dev);
- /* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */
- ipv6_stub->ndisc_send_na(netdev, &iph->saddr, &msg->target,
- is_router /* router */,
- true /* solicited */,
- false /* override */,
- true /* inc_opt */);
+ ndisc_send_na(netdev, &iph->saddr, &msg->target,
+ is_router /* router */,
+ true /* solicited */,
+ false /* override */,
+ true /* inc_opt */);
out:
dev_put(netdev);
}
@@ -362,7 +361,7 @@ static bool is_neigh_solicit(u8 *buf, size_t len)
msg->icmph.icmp6_code == 0 &&
msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION);
}
-
+#endif /* IPV6 */
static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
{
@@ -378,8 +377,10 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_
proto = htons(ETH_P_IP);
break;
case 0x60:
+#if IS_ENABLED(CONFIG_IPV6)
if (is_neigh_solicit(buf, len))
do_neigh_solicit(dev, buf, tci);
+#endif
proto = htons(ETH_P_IPV6);
break;
default:
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 17c941aac32d..b5fbd03418b6 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -19,7 +19,6 @@
#include <net/arp.h>
#include <net/ndisc.h>
#include <net/gro.h>
-#include <net/ipv6_stubs.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/rtnetlink.h>
@@ -2045,7 +2044,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
ipv6_addr_is_multicast(&msg->target))
goto out;
- n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev);
+ n = neigh_lookup(&nd_tbl, &msg->target, dev);
if (n) {
struct vxlan_rdst *rdst = NULL;
@@ -2130,15 +2129,15 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
{
struct ipv6hdr *pip6;
- /* check if nd_tbl is not initiliazed due to
- * ipv6.disable=1 set during boot
+ /* check if ipv6.disable=1 set during boot was set
+ * during booting so nd_tbl is not initialized
*/
- if (!ipv6_stub->nd_tbl)
+ if (!ipv6_mod_enabled())
return false;
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
return false;
pip6 = ipv6_hdr(skb);
- n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev);
+ n = neigh_lookup(&nd_tbl, &pip6->daddr, dev);
if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) {
union vxlan_addr ipa = {
.sin6.sin6_addr = pip6->daddr,
diff --git a/drivers/net/vxlan/vxlan_multicast.c b/drivers/net/vxlan/vxlan_multicast.c
index a7f2d67dc61b..b0e80bca855c 100644
--- a/drivers/net/vxlan/vxlan_multicast.c
+++ b/drivers/net/vxlan/vxlan_multicast.c
@@ -39,8 +39,7 @@ int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
sk = sock6->sock->sk;
lock_sock(sk);
- ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex,
- &ip->sin6.sin6_addr);
+ ret = ipv6_sock_mc_join(sk, ifindex, &ip->sin6.sin6_addr);
release_sock(sk);
#endif
}
@@ -73,8 +72,7 @@ int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
sk = sock6->sock->sk;
lock_sock(sk);
- ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex,
- &ip->sin6.sin6_addr);
+ ret = ipv6_sock_mc_drop(sk, ifindex, &ip->sin6.sin6_addr);
release_sock(sk);
#endif
}
diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c
index 253488f8c00f..c362c78d908e 100644
--- a/drivers/net/wireguard/socket.c
+++ b/drivers/net/wireguard/socket.c
@@ -136,8 +136,7 @@ static int send6(struct wg_device *wg, struct sk_buff *skb,
if (cache)
dst_cache_reset(cache);
}
- dst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(sock), sock, &fl,
- NULL);
+ dst = ip6_dst_lookup_flow(sock_net(sock), sock, &fl, NULL);
if (IS_ERR(dst)) {
ret = PTR_ERR(dst);
net_dbg_ratelimited("%s: No route to %pISpfsc, error %d\n",
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index 248a051da52d..c11428485dcc 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -4838,7 +4838,7 @@ static int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode)
/* If IPv6 is configured in the kernel then we don't want to filter out all
* of the multicast packets as IPv6 needs some. */
-#if !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE)
+#if !defined(CONFIG_IPV6)
cmd.host_command = ADD_MULTICAST;
cmd.host_command_sequence = 0;
cmd.host_command_length = 0;
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index 1e2b51769eec..c06386eda47f 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -17,7 +17,6 @@
#include <linux/if_vlan.h>
#include <linux/inetdevice.h>
#include <net/addrconf.h>
-#include <net/ipv6_stubs.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ip6_checksum.h>
#endif
@@ -455,7 +454,7 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
return;
}
- n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, vlandev);
+ n = neigh_lookup(&nd_tbl, &msg->target, vlandev);
if (n) {
struct net_bridge_fdb_entry *f;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH wireless-next v3 12/15] wifi: cfg80211: add FTM range report negotiation support
From: Peddolla Harshavardhan Reddy @ 2026-03-20 19:00 UTC (permalink / raw)
To: Stern, Avraham, johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, kavita.kavita@oss.qualcomm.com
In-Reply-To: <CH3PR11MB838301E435C801AF69C87B96FF44A@CH3PR11MB8383.namprd11.prod.outlook.com>
On 13-Mar-26 2:45 AM, Stern, Avraham wrote:
>
>> From: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
>> Sent: Thursday, March 5, 2026 6:07 PM
>> To: johannes@sipsolutions.net
>> Cc: linux-wireless@vger.kernel.org; kavita.kavita@oss.qualcomm.com
>> Subject: [PATCH wireless-next v3 12/15] wifi: cfg80211: add FTM range report negotiation support
>> + * @range_report: negotiate for FTM range report. Only valid for
>> + * EDCA based ranging.
> FTM range report is not negotiated. It is mandatory for PD EDCA based ranging. So this is implied by the pd_request and is redundant.
Yes you are right, we dropped this patch.
>
> ---------------------------------------------------------------------
> A member of the Intel Corporation group of companies
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
^ permalink raw reply
* Re: [PATCH wireless-next v3 07/15] wifi: cfg80211: add continuous ranging and PD request support
From: Peddolla Harshavardhan Reddy @ 2026-03-20 18:53 UTC (permalink / raw)
To: Stern, Avraham, johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, kavita.kavita@oss.qualcomm.com
In-Reply-To: <CH3PR11MB8383BA2E902BF1359F4E050BFF44A@CH3PR11MB8383.namprd11.prod.outlook.com>
On 13-Mar-26 2:41 AM, Stern, Avraham wrote:
>
>> From: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
>> Sent: Thursday, March 5, 2026 6:07 PM
>> To: johannes@sipsolutions.net
>> Cc: linux-wireless@vger.kernel.org; kavita.kavita@oss.qualcomm.com
>> Subject: [PATCH wireless-next v3 07/15] wifi: cfg80211: add continuous ranging and PD request support
>> Proximity detection (PD) applications require sustained measurement sessions without repeated FTM negotiation overhead. Currently, each ranging session requires separate negotiation.
> There are already NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD, NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION and NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST, which are practically the same as nominal_time, availability_window and measurements_per_aw, respectively. These are used for pd_request with EDCA.
> Maybe these can be reused for pd_request with NTB as well (with clarifying the usage in their description?)
These need to be different as they are different size w.r.t EDCA params as per specification and are of different units and have very different Max values.
>
>
>> + * @min_time_between_measurements: minimum time between two consecutive range
>> + * measurements in units of 100 micro seconds, applicable for
>> + * non trigger based ranging. Only valid if @non_trigger_based is set.
>> + * @max_time_between_measurements: maximum time between two consecutive range
>> + * measurements in units of 10 milli seconds, to avoid FTM negotiation
>> + * applicable for non trigger based ranging. Only valid
>> + * if @non_trigger_based is set.
> The user doesn't need to control these. Only the periodicity parameters below.
These below parameters could be optional based on these.
>
>> + * @availability_window: duration of the availability window (AW) in units of
>> + * 1 millisecond (0-255 ms). Only valid if @non_trigger_based is set.
>> + * @nominal_time: Nominal duration between adjacent availability windows
>> + * in units of milli seconds. Only valid if @non_trigger_based is set.
>> + * @measurements_per_aw: number of measurement attempts per availability window
>> + * with a maximum value of 4. Only valid if @non_trigger_based is set.
> All these should be valid only if repeated periodic measurements are requested. But there is no indication for that...
> Need to add number_of_measurements (similar to NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP) to indicate how many repetitions are requested.
We added this parameter in the new version.
>
>> + u32 availability_window;
> u8 will keep the 255 limit.
>
>> + u32 measurements_per_aw;
> u8 is enough for a maximum of 4.
>
>> + pd_request:1;
>> struct cfg80211_pmsr_ftm_request_peer ftm; };
> Should be part of the ftm data. Not really needed. The device only cares if multi repetitions are requested.
Moved this, pd_request flag would be really helpful to driver/Firmware to distinguish the type of request.
>
>
>> + if (!out->ftm.trigger_based && !out->ftm.non_trigger_based &&
>> + capa->ftm.max_ftms_per_burst &&
>> + (out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst ||
>> + out->ftm.ftms_per_burst == 0)) {
>> + 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");
>> + return -EINVAL;
> If ftms_per_burst is not applicable for trigger_based and non_trigger_based, they must not be set together, not ignored.
Yes, updated in next version.
>
>
>> + if (out->pd_request && out->ftm.non_trigger_based && !out->ftm.rsta &&
>> + out->ftm.measurements_per_aw == 0) {
>> + NL_SET_ERR_MSG_ATTR(info->extack,
>> + ftmreq,
>> + "FTM: Invalid parameters:measurements per avail window is zero for NTB PD request");
>> + return -EINVAL;
> measurement_per_aw is required for rsta as well.
made it as optional, if this attribute is not present or set to zero then let Firmware/driver choose the value.
>
>
>
> ---------------------------------------------------------------------
> A member of the Intel Corporation group of companies
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
^ permalink raw reply
* Re: [PATCH wireless-next v3 06/15] wifi: cfg80211: add proximity detection capabilities to PMSR
From: Peddolla Harshavardhan Reddy @ 2026-03-20 18:33 UTC (permalink / raw)
To: Stern, Avraham, johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, kavita.kavita@oss.qualcomm.com
In-Reply-To: <CH3PR11MB8383D7E5CA78D822A9FD8A1EFF44A@CH3PR11MB8383.namprd11.prod.outlook.com>
On 13-Mar-26 2:38 AM, Stern, Avraham wrote:
>
>> From: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
>> Sent: Thursday, March 5, 2026 6:07 PM
>> To: johannes@sipsolutions.net
>> Cc: linux-wireless@vger.kernel.org; kavita.kavita@oss.qualcomm.com
>> Subject: [PATCH wireless-next v3 06/15] wifi: cfg80211: add proximity detection capabilities to PMSR
>> + * @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
>> + * @pd_concurrent_ista_rsta_support: As the peer measurement request can be a
>> + * multi-peer request this will indicate if the device can act
>> + * simultaneously as initiator and a responder. Only valid if @pd_support
>> + * is set.
>> * @ftm: FTM measurement data
> These should be part of the FTM data.
> pd_concurrent_ista_rsta_support is only valid if ftm.support_rsta is set.
Fixed it in the next version.
>
>> + * @ftm.max_no_of_tx_antennas: maximum number of transmit antennas supported for
>> + * ranging
>> + * @ftm.max_no_of_rx_antennas: maximum number of receive antennas supported for
>> + * ranging
> Supported for EDCA based ranging
Fixed it in the next version.
>
>> + * @ftm.min_allowed_ranging_interval_edca: Minimum EDCA ranging
>> + * interval supported by the device in milli seconds. (0 means unknown)
>> + * @ftm.min_allowed_ranging_interval_ntb: Minimum NTB ranging
>> + * interval supported by the device in milli seconds. (0 means unknown)
> These are not advertised anywhere, and time between measurements is not part of the measurement request from the user.
> So why this capability is needed?
User space can use this to calculate Nominal time or burst period as needed based on how quickly can the driver/ Firmware can do the ranging.
>
>> * @ftm.support_rsta: supports operating as RSTA in PMSR FTM request
>> + * @ftm.support_edca_responder: supports operating as FTM responder in PMSR FTM
>> + * request for EDCA-based ranging
> So support rsta means supports RSTA for NTB only now? Do we also need support TB RSTA?
Updated in the next version.
>
> struct {
> u32 preambles;
>> + u32 max_no_of_tx_antennas;
>> + u32 max_no_of_rx_antennas;
> u8 should be enough
Updated in the next version.
>
> * @NUM_NL80211_PMSR_ATTR: internal
>> * @NL80211_PMSR_ATTR_MAX: highest attribute number @@ -7841,6 +7850,8 @@ enum nl80211_peer_measurement_attrs {
>> NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR,
>> NL80211_PMSR_ATTR_TYPE_CAPA,
>> NL80211_PMSR_ATTR_PEERS,
>> + NL80211_PMSR_ATTR_PD_SUPPORT,
>> + NL80211_PMSR_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT,
>
> These should be under nl80211_peer_measurement_ftm_capa
Updated in the next version.
>
>> - if (out->ftm.rsta && !capa->ftm.support_rsta) {
>> + if (out->ftm.rsta && !capa->ftm.support_rsta &&
>> + !capa->ftm.support_edca_responder) {
>> NL_SET_ERR_MSG_ATTR(info->extack,
>> tb[NL80211_PMSR_FTM_REQ_ATTR_RSTA],
>> "FTM: RSTA not supported by device");
> capa->ftm.support_edca_responder is only needed if out->ftm.non_trigger_based is not set
removed support_edca_responder and added separate ISTA and RSTA based capabilities for TB, NTB, EDCA, and added new validation checks in PMSR request path for all three.
>
> ---------------------------------------------------------------------
> A member of the Intel Corporation group of companies
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
^ permalink raw reply
* Re: [PATCH wireless-next v3 04/15] wifi: cfg80211/mac80211: Add NL80211_IFTYPE_PD for PD PASN and PMSR operations
From: Peddolla Harshavardhan Reddy @ 2026-03-20 18:25 UTC (permalink / raw)
To: Stern, Avraham, johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, kavita.kavita@oss.qualcomm.com
In-Reply-To: <CH3PR11MB8383B129375415AB3B50C4DCFF44A@CH3PR11MB8383.namprd11.prod.outlook.com>
On 13-Mar-26 2:36 AM, Stern, Avraham wrote:
>> From: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com> > Sent: Thursday, March 5, 2026 6:07 PM
>> To: johannes@sipsolutions.net
>> Cc: linux-wireless@vger.kernel.org; kavita.kavita@oss.qualcomm.com
>> Subject: [PATCH wireless-next v3 04/15] wifi: cfg80211/mac80211: Add NL80211_IFTYPE_PD for PD PASN and PMSR operations
>> Add a new wdev-only interface type NL80211_IFTYPE_PD to support Proximity Detection (PD) operations such as PASN, key install and peer measurement operations. This interface type operates without a netdev, similar to P2P_DEVICE and NAN interfaces.
> What about PD discovery?
PD discovery can happen on any interface. So we are not restricting it.
>
>> The PD interface provides isolated functionality for PD PASN and PMSR without affecting existing network operations.
> So PMSR will be allowed on station interface (for sta to AP measurements, when possibly associated and have security context already), and on the new interface type for non-AP ranging?
Yes, This is correct.
>
>> @@ -1935,6 +1938,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
>> break;
>> case NL80211_IFTYPE_AP_VLAN:
>> case NL80211_IFTYPE_P2P_DEVICE:
>> + case NL80211_IFTYPE_PD:
>> sdata->vif.bss_conf.bssid = sdata->vif.addr;
>> break;
>
> bss_conf is irrelevant for PD interface
Fixed it in next version.
>
>> @@ -898,6 +898,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
>> need_offchan = true;
>> break;
>> case NL80211_IFTYPE_NAN:
>> + case NL80211_IFTYPE_PD:
>> break;
> PD interface doesn't have a channel context, so set need_offchan = true?
Fixed it in the next version.
>
>> @@ -4621,6 +4621,7 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
>> (ieee80211_is_public_action(hdr, skb->len) ||
>> (ieee80211_is_auth(hdr->frame_control) &&
>> ether_addr_equal(sdata->vif.addr, hdr->addr1)));
>> + case NL80211_IFTYPE_PD:
>> default:
>> break;
>
> At least check addr1, and accept only auth frames (PASN) and if used for discovery, also public action.
Added check for addr1 and accept only auth frames but support of public action can be added if needed.
>
>> @@ -13954,6 +13962,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;
> So not used for PD discovery, why?
This is not restricted for this interface, support can be added in the future.
>
> ---------------------------------------------------------------------
> A member of the Intel Corporation group of companies
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
^ permalink raw reply
* Re: [PATCH wireless-next v3 02/15] wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down
From: Peddolla Harshavardhan Reddy @ 2026-03-20 18:20 UTC (permalink / raw)
To: Stern, Avraham, johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, kavita.kavita@oss.qualcomm.com
In-Reply-To: <CH3PR11MB83834872AA2767B19587549DFF44A@CH3PR11MB8383.namprd11.prod.outlook.com>
On 13-Mar-26 2:34 AM, Stern, Avraham wrote:
>
>> From: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
>> Sent: Thursday, March 5, 2026 6:07 PM
>> To: johannes@sipsolutions.net
>> Cc: linux-wireless@vger.kernel.org; kavita.kavita@oss.qualcomm.com
>> Subject: [PATCH wireless-next v3 02/15] wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down
>> When the nl80211 socket that originated a PMSR request is closed, cfg80211_release_pmsr() sets the request's nl_portid to zero and schedules pmsr_free_wk to process the abort asynchronously. If the interface is concurrently torn down before that work runs, cfg80211_pmsr_wdev_down() calls
>> cfg80211_pmsr_process_abort() directly. However, the already- scheduled pmsr_free_wk work item remains pending and may run after the interface has been removed from the driver. This could cause the driver's abort_pmsr callback to operate on a torn-down interface, leading to undefined behavior and potential crashes.
> pmsr_free_wk work is cancelled on NETDEV_GOING_DOWN, so this makes sure wdev is still valid when it runs.
> Why isn't it sufficient?
The work can be queued after NETDEV_GOING_DOWN has already run (e.g., due to nl80211 socket close).
In that case, the pending work may still run after the interface is torn down and invoke abort_pmsr on an invalid context.
Hence the pending work must also be canceled on wdev teardown. This is a genuine issue in the existing code and needs to fixed.
>
>
> ---------------------------------------------------------------------
> A member of the Intel Corporation group of companies
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
^ permalink raw reply
* Re: [PATCH wireless-next v3 01/15] wifi: cfg80211: Allow RSTA role without LMR request
From: Peddolla Harshavardhan Reddy @ 2026-03-20 18:07 UTC (permalink / raw)
To: Stern, Avraham, johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, kavita.kavita@oss.qualcomm.com
In-Reply-To: <CH3PR11MB8383C2D2AFE618B66A92B698FF44A@CH3PR11MB8383.namprd11.prod.outlook.com>
On 13-Mar-26 2:33 AM, Stern, Avraham wrote:
>
> Hi Peddolla
>
>> From: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
>> Sent: Thursday, March 5, 2026 6:07 PM
>> To: johannes@sipsolutions.net
>> Cc: linux-wireless@vger.kernel.org; kavita.kavita@oss.qualcomm.com
>> Subject: [PATCH wireless-next v3 01/15] wifi: cfg80211: Allow RSTA
>> role without LMR request
>> Currently when enabling RSTA role in PMSR FTM requests,
>> pmsr_parse_ftm() mandates LMR feedback to be requested. This
> I2R LMR is mandatory when the RSTA is not continuously available on-channel:
> I2R LMR is required for ISTA to request AW changes (NNW bit) and to terminate the session.
>
Yes, I agree with you, in the next version we added additonal checks for NTB and TB.
So it should not reject valid EDCA based ranging request.
>> prevents valid use cases where devices need to operate as RSTA without
>> waking the host for measurement reports.
> Devices can decide not to wake the host although I2R LMR was used over the air.
> But with current API, cfg80211_pmsr_report() is expected to be called in response.
> So maybe need a different flag to indicate no response?
>
> Avi
This flag is present in later patches.
> ---------------------------------------------------------------------
> A member of the Intel Corporation group of companies
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
^ permalink raw reply
* [PATCH wireless-next v4 14/14] wifi: mac80211_hwsim: Add support for extended FTM ranging
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
From: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
Introduce support for continuous ranging and advanced timing parameters
in the FTM (Fine Timing Measurement) 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 | 200 ++++++++++++++++++
1 file changed, 200 insertions(+)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 82adcc848189..6f0788c3f4cf 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -848,6 +848,18 @@ 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_U32 },
+ [NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS] = { .type = NLA_U32 },
+ [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_MEASUREMENTS_PER_AW] = { .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 +893,13 @@ 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_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_CAPA_ATTR_ASAP] = { .type = NLA_FLAG },
@@ -893,6 +912,18 @@ 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_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS] = { .type = NLA_U32 },
+ [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_EDCA_PREAMBLES] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_PREAMBLES] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_BANDWIDTHS] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_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_PD_SUPPORT] = { .type = NLA_FLAG },
+ [NL80211_PMSR_FTM_CAPA_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT] = { .type = NLA_FLAG },
};
static const struct nla_policy
@@ -907,6 +938,8 @@ hwsim_pmsr_capa_policy[NL80211_PMSR_ATTR_MAX + 1] = {
[NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_FLAG },
[NL80211_PMSR_ATTR_TYPE_CAPA] = NLA_POLICY_NESTED(hwsim_pmsr_capa_type_policy),
[NL80211_PMSR_ATTR_PEERS] = { .type = NLA_REJECT }, // only for request.
+ [NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE] = { .type = NLA_U32 },
+ [NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE] = { .type = NLA_U32 },
};
static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
@@ -3624,6 +3657,50 @@ 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_u32(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->measurements_per_aw &&
+ nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_MEAS_PER_AW,
+ request->measurements_per_aw))
+ 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;
@@ -3993,6 +4070,57 @@ 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 =
+ 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 =
+ 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 =
+ 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 =
+ 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 =
+ nla_get_u32(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 =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS]);
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME])
+ 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 =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW]);
+
+ if (tb[NL80211_PMSR_FTM_RESP_ATTR_MEASUREMENTS_PER_AW])
+ result->measurements_per_aw =
+ nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_MEASUREMENTS_PER_AW]);
+
+ 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;
}
@@ -6498,6 +6626,72 @@ 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_u32(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_u32(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_EDCA_PREAMBLES])
+ out->ftm.pd_edca_preambles =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_PREAMBLES]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_PREAMBLES])
+ out->ftm.pd_ntb_preambles =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_PREAMBLES]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_BANDWIDTHS])
+ out->ftm.pd_edca_bandwidths =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_BANDWIDTHS]);
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_BANDWIDTHS])
+ out->ftm.pd_ntb_bandwidths =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_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 (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];
+ }
+ }
+
+ out->ftm.pd_support = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_SUPPORT];
+ out->ftm.pd_concurrent_ista_rsta_support =
+ !!tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT];
+
return 0;
}
@@ -6519,6 +6713,12 @@ static int parse_pmsr_capa(const struct nlattr *pmsr_capa, struct cfg80211_pmsr_
out->max_peers = nla_get_u32(tb[NL80211_PMSR_ATTR_MAX_PEERS]);
out->report_ap_tsf = !!tb[NL80211_PMSR_ATTR_REPORT_AP_TSF];
out->randomize_mac_addr = !!tb[NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR];
+ if (tb[NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE])
+ out->pd_max_peer_ista_role =
+ nla_get_u32(tb[NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE]);
+ if (tb[NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE])
+ out->pd_max_peer_rsta_role =
+ nla_get_u32(tb[NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE]);
if (!tb[NL80211_PMSR_ATTR_TYPE_CAPA]) {
NL_SET_ERR_MSG_ATTR(info->extack, tb[NL80211_PMSR_ATTR_TYPE_CAPA],
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next v4 13/14] wifi: cfg80211: add LTF keyseed support for secure ranging
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
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 52db36120314..51eec09166d1 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2224,6 +2224,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 96abe2eb28bb..d11c10b38b96 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 d5ac40a385f0..049e82b79efc 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -5608,6 +5608,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
@@ -5624,6 +5636,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,
@@ -6853,6 +6866,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.
*/
@@ -6933,6 +6950,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 cd4129ae61eb..6a0bbf832cc9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -989,6 +989,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 */
@@ -1520,6 +1522,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 d558c4bc00f0..c38ef5e3846b 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
* [PATCH wireless-next v4 12/14] wifi: cfg80211: allow suppressing FTM result reporting for PD requests
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
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 a PD request is present,
reject otherwise.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 8 +++++++-
include/uapi/linux/nl80211.h | 6 +++++-
net/wireless/nl80211.c | 1 +
net/wireless/pmsr.c | 10 ++++++++++
4 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d841ada4ddc1..96abe2eb28bb 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4427,6 +4427,11 @@ struct cfg80211_pmsr_result {
* indicate the driver should set the BSS color. Only valid if
* @non_trigger_based or @trigger_based is set.
* @pd_request: indicates a peer-to-peer PD request.
+ * @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
+ * @pd_request is set.
* @min_time_between_measurements: minimum time between two consecutive range
* measurements in units of 100 micro seconds, applicable for
* non trigger based ranging. Only valid if @non_trigger_based is set.
@@ -4477,7 +4482,8 @@ struct cfg80211_pmsr_ftm_request_peer {
u8 ftmr_retries;
u8 bss_color;
- u8 pd_request:1;
+ u8 pd_request:1,
+ pd_suppress_range_results:1;
u32 min_time_between_measurements;
u32 max_time_between_measurements;
u32 availability_window;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f6bd944fea1b..d5ac40a385f0 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8118,7 +8118,10 @@ enum nl80211_peer_measurement_ftm_capa {
* @NL80211_PMSR_FTM_REQ_ATTR_EGRESS: the measurement result of the peer
* needs to be indicated in case the device moves out of this range.
* (units mm, u64).
- *
+ * @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_PD_REQUEST is set.
* @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
* @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
*/
@@ -8148,6 +8151,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 74b7c4651061..cd4129ae61eb 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -397,6 +397,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 d010d19d148f..21df12680839 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -288,6 +288,16 @@ 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.pd_request && 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
* [PATCH wireless-next v4 11/14] wifi: cfg80211: add PD-specific preamble and bandwidth capabilities
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
Some devices support different preamble and bandwidth configurations
for proximity detection (PD) versus standard ranging, but capabilities
currently report only a single set for all FTM measurements.
Introduce separate preamble and bandwidth capability reporting for PD
requests with EDCA and NTB-based ranging, allowing devices to advertise
different supported preambles and bandwidths for PD operations.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 16 ++++++++++++++++
include/uapi/linux/nl80211.h | 22 ++++++++++++++++++++++
net/wireless/nl80211.c | 14 ++++++++++++++
net/wireless/pmsr.c | 21 +++++++++++++++++++--
4 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 651d1645bc32..d841ada4ddc1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5855,6 +5855,18 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type);
* a multi-peer request this will indicate if the device can act
* simultaneously as initiator and a responder. Only valid if
* @ftm.rsta_support is set.
+ * @ftm.pd_edca_preambles: bitmap of preambles supported
+ * (&enum nl80211_preamble) in case of PD request with EDCA based
+ * initiator or responder role. ignored if @pd_support is not set.
+ * @ftm.pd_ntb_preambles: bitmap of preambles supported
+ * (&enum nl80211_preamble) in case of PD request with NTB based
+ * initiator or responder role. ignored if @pd_support is not set.
+ * @ftm.pd_edca_bandwidths: bitmap of bandwidths supported
+ * (&enum nl80211_chan_width) in case of PD request with EDCA based
+ * initiator or responder role. ignored if @pd_support is not set.
+ * @ftm.pd_ntb_bandwidths: bitmap of bandwidths supported
+ * (&enum nl80211_chan_width) in case of PD request with NTB based
+ * initiator or responder role. ignored if @pd_support is not set.
*/
struct cfg80211_pmsr_capabilities {
unsigned int max_peers;
@@ -5899,6 +5911,10 @@ struct cfg80211_pmsr_capabilities {
u32 min_allowed_ranging_interval_ntb;
u8 pd_support:1,
pd_concurrent_ista_rsta_support:1;
+ u32 pd_edca_preambles;
+ u32 pd_ntb_preambles;
+ u32 pd_edca_bandwidths;
+ u32 pd_ntb_bandwidths;
} ftm;
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c1ecf61a9563..f6bd944fea1b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -7960,6 +7960,24 @@ enum nl80211_peer_measurement_attrs {
* @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)
+ * @NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_PREAMBLES: u32 bitmap of values from
+ * &enum nl80211_preamble indicating the supported preambles for FTM in
+ * case of PD based EDCA initiator or responder role.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_PREAMBLES: u32 bitmap of values from
+ * &enum nl80211_preamble indicating the supported preambles for FTM in
+ * case of PD based NTB initiator or responder role.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_BANDWIDTHS: u32 bitmap of values from
+ * &enum nl80211_chan_width indicating the supported channel
+ * bandwidths for FTM in case of PD based EDCA initiator or responder role.
+ * Note that a higher channel bandwidth may be configured to allow for
+ * other measurements types with different bandwidth requirement in the
+ * same measurement.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_BANDWIDTHS: u32 bitmap of values from
+ * &enum nl80211_chan_width indicating the supported channel
+ * bandwidths for FTM in case of PD based NTB initiator or responder role.
+ * Note that a higher channel bandwidth may be configured to allow for
+ * other measurements types with different bandwidth requirement in the
+ * same measurement.
*
* @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal
* @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number
@@ -7997,6 +8015,10 @@ 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_EDCA_PREAMBLES,
+ NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_PREAMBLES,
+ NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_BANDWIDTHS,
+ NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_BANDWIDTHS,
/* keep last */
NUM_NL80211_PMSR_FTM_CAPA_ATTR,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 25e5d9d5c72a..74b7c4651061 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2482,6 +2482,20 @@ nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
cap->pd_max_peer_rsta_role))
return -ENOBUFS;
}
+
+ if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_PREAMBLES,
+ cap->ftm.pd_edca_preambles))
+ return -ENOBUFS;
+ if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_PREAMBLES,
+ cap->ftm.pd_ntb_preambles))
+ return -ENOBUFS;
+ if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_EDCA_BANDWIDTHS,
+ cap->ftm.pd_edca_bandwidths))
+ return -ENOBUFS;
+ if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_NTB_BANDWIDTHS,
+ cap->ftm.pd_ntb_bandwidths))
+ return -ENOBUFS;
+
nla_nest_end(msg, ftm);
return 0;
}
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 183b5cac015e..d010d19d148f 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.pd_request &&
+ !(rdev->wiphy.pmsr_capa->ftm.bandwidths & BIT(out->chandef.width))) {
NL_SET_ERR_MSG(info->extack, "FTM: unsupported bandwidth");
return -EINVAL;
}
+ if (out->ftm.pd_request &&
+ !(rdev->wiphy.pmsr_capa->ftm.pd_edca_bandwidths & BIT(out->chandef.width)) &&
+ !(rdev->wiphy.pmsr_capa->ftm.pd_ntb_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.pd_request && !(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.pd_request &&
+ !(capa->ftm.pd_ntb_preambles & BIT(preamble)) &&
+ !(capa->ftm.pd_edca_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
* [PATCH wireless-next v4 10/14] wifi: cfg80211: add ingress/egress distance thresholds for FTM
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
Proximity detection applications need to receive measurement results
only when devices cross specific distance boundaries to avoid
unnecessary host wakeups and reduce power consumption. Currently,
there is no mechanism for applications to specify these distance
thresholds.
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, enabling drivers to reduce unnecessary data transfer
and host wakeups.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 10 ++++++++++
include/uapi/linux/nl80211.h | 10 ++++++++++
net/wireless/nl80211.c | 2 ++
net/wireless/pmsr.c | 8 ++++++++
4 files changed, 30 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9437533d0edf..651d1645bc32 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4449,6 +4449,14 @@ struct cfg80211_pmsr_result {
* @num_measurements: number of measurements to be performed in total.
* Only valid if @non_trigger_based is set. If set to 0, the firmware or
* driver can automatically select an appropriate value.
+ * @ingress_distancemm: the measurement result of the peer needs
+ * to be indicated in case the device moves into this range.
+ * (units mm, u64) measurement results need to be sent on a burst index
+ * basis in this case.
+ * @egress_distancemm: the measurement result of the peer needs
+ * to be indicated in case the device moves out of this range.
+ * (units mm, u64). measurement results need to be sent on a burst index
+ * basis in this case.
*
* See also nl80211 for the respective attribute documentation.
*/
@@ -4476,6 +4484,8 @@ struct cfg80211_pmsr_ftm_request_peer {
u32 nominal_time;
u32 measurements_per_aw;
u32 num_measurements;
+ u64 ingress_distancemm;
+ u64 egress_distancemm;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1217fe492af7..c1ecf61a9563 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8089,6 +8089,13 @@ enum nl80211_peer_measurement_ftm_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: the measurement result of the peer
+ * needs to be indicated in case the device moves into this range.
+ * (units mm, u64).
+ * @NL80211_PMSR_FTM_REQ_ATTR_EGRESS: the measurement result of the peer
+ * needs to be indicated in case the device moves out of this range.
+ * (units mm, u64).
*
* @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
* @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
@@ -8116,6 +8123,9 @@ enum nl80211_peer_measurement_ftm_req {
NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION,
NL80211_PMSR_FTM_REQ_ATTR_MEAS_PER_AW,
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 98eef98939c1..25e5d9d5c72a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -395,6 +395,8 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION] = NLA_POLICY_MAX(NLA_U32, 255),
[NL80211_PMSR_FTM_REQ_ATTR_MEAS_PER_AW] = NLA_POLICY_MAX(NLA_U32, 4),
[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 d2b43bf584a9..183b5cac015e 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -263,6 +263,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
* [PATCH wireless-next v4 09/14] wifi: cfg80211: add role-based PD peer limits
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
Peer measurement capabilities currently advertise a single maximum
peer count regardless of device role for proximity detection (PD).
Some devices support different peer limits when operating as PD
initiator versus PD responder.
Introduce separate peer limit capabilities for each PD role. When a
device supports concurrent initiator and responder operation,
enforce the sum of both limits to prevent resource oversubscription.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 13 +++++++++++++
include/uapi/linux/nl80211.h | 16 ++++++++++++++++
net/wireless/nl80211.c | 10 ++++++++++
net/wireless/pmsr.c | 32 ++++++++++++++++++++++++++++----
4 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9e1593ca8a1f..9437533d0edf 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5780,6 +5780,16 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type);
* @max_peers: maximum number of peers in a single measurement
* @report_ap_tsf: can report assoc AP's TSF for radio resource measurement
* @randomize_mac_addr: can randomize MAC address for measurement
+ * @pd_max_peer_ista_role: Maximum number of peers allowed for a device
+ * operating in the ISTA role under proximity detection. Only valid if
+ * @pd_support is set. Sum of both @pd_max_peer_ista_role and
+ * @pd_max_peer_rsta_role is considered to enforce the max peers supported
+ * in case the request is of peer-to-peer PD type.
+ * @pd_max_peer_rsta_role: Maximum number of peers allowed for a device
+ * operating in the RSTA role under proximity detection. Only valid if
+ * @pd_support is set. Sum of both @pd_max_peer_ista_role and
+ * @pd_max_peer_rsta_role is considered to enforce the max peers supported
+ * in case the request is of peer-to-peer PD type.
* @ftm: FTM measurement data
* @ftm.supported: FTM measurement is supported
* @ftm.asap: ASAP-mode is supported
@@ -5841,6 +5851,9 @@ struct cfg80211_pmsr_capabilities {
u8 report_ap_tsf:1,
randomize_mac_addr:1;
+ u32 pd_max_peer_ista_role;
+ u32 pd_max_peer_rsta_role;
+
struct {
u32 preambles;
u32 bandwidths;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 4b6f555ca850..1217fe492af7 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -7838,6 +7838,20 @@ 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_PD_MAX_PEER_ISTA_ROLE: u32 attribute indicating the
+ * maximum number of peers allowed for a device operating in the ISTA
+ * (Initiator STA) role under proximity detection. Only valid if
+ * %NL80211_PMSR_FTM_CAPA_ATTR_PD_SUPPORT is set. Sum of both
+ * %NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE and
+ * %NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE is considered to enforce the
+ * max peers supported in case the request is of peer-to-peer PD type.
+ * @NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE: u32 attribute indicating the
+ * maximum number of peers allowed for a device operating in the RSTA
+ * (Responder STA) role under proximity detection. Only valid if
+ * %NL80211_PMSR_FTM_CAPA_ATTR_PD_SUPPORT is set. Sum of both
+ * %NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE and
+ * %NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE is considered to enforce the
+ * max peers supported in case the request is of peer-to-peer PD type.
*
* @NUM_NL80211_PMSR_ATTR: internal
* @NL80211_PMSR_ATTR_MAX: highest attribute number
@@ -7850,6 +7864,8 @@ enum nl80211_peer_measurement_attrs {
NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR,
NL80211_PMSR_ATTR_TYPE_CAPA,
NL80211_PMSR_ATTR_PEERS,
+ NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE,
+ NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE,
/* keep last */
NUM_NL80211_PMSR_ATTR,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8bcc4aa6514e..98eef98939c1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2469,6 +2469,16 @@ nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
if (cap->ftm.pd_concurrent_ista_rsta_support &&
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT))
return -ENOBUFS;
+
+ if (cap->pd_max_peer_ista_role &&
+ nla_put_u32(msg, NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE,
+ cap->pd_max_peer_ista_role))
+ return -ENOBUFS;
+
+ if (cap->pd_max_peer_rsta_role &&
+ nla_put_u32(msg, NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE,
+ cap->pd_max_peer_rsta_role))
+ return -ENOBUFS;
}
nla_nest_end(msg, ftm);
return 0;
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index a4348535d2ed..d2b43bf584a9 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -355,12 +355,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, pd_count, max_pd_peers;
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)
@@ -375,7 +378,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;
@@ -391,7 +394,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");
@@ -416,6 +419,27 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
goto out_err;
idx++;
}
+
+ /* Count PD requests and validate against PD peer limits */
+ if (capa->ftm.pd_support) {
+ pd_count = 0;
+
+ max_pd_peers = capa->pd_max_peer_ista_role +
+ capa->pd_max_peer_rsta_role;
+
+ for (idx = 0; idx < req->n_peers; idx++) {
+ if (req->peers[idx].ftm.pd_request) {
+ pd_count++;
+
+ if (pd_count > max_pd_peers) {
+ NL_SET_ERR_MSG(info->extack,
+ "Too many PD peers used");
+ err = -EINVAL;
+ goto out_err;
+ }
+ }
+ }
+ }
req->cookie = cfg80211_assign_cookie(rdev);
req->nl_portid = info->snd_portid;
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next v4 08/14] wifi: cfg80211: extend PMSR FTM response for proximity ranging
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
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 | 61 ++++++++++++++++++++++++++++++++++--
include/uapi/linux/nl80211.h | 42 ++++++++++++++++++++++++-
net/wireless/pmsr.c | 16 ++++++++++
3 files changed, 116 insertions(+), 3 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fb9191449886..9e1593ca8a1f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4260,6 +4260,27 @@ 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 (u32).
+ * @measurements_per_aw: negotiated number of measurement attempts per
+ * availability window.
+ * @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
@@ -4272,6 +4293,19 @@ 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
+ * @measurements_per_aw_valid: @measurements_per_aw 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;
@@ -4295,8 +4329,19 @@ 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;
+ u32 availability_window;
+ u32 measurements_per_aw;
+ 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,
@@ -4307,7 +4352,19 @@ 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,
+ measurements_per_aw_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 b271a9629b0f..4b6f555ca850 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8186,7 +8186,35 @@ 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_MEASUREMENTS_PER_AW: negotiated measurements
+ * per availability window (u32, optional, max value 4)
+ * @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
*/
@@ -8215,6 +8243,18 @@ 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_MEASUREMENTS_PER_AW,
+ 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 9432cd645f2f..a4348535d2ed 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -556,6 +556,22 @@ 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(u32, AVAILABILITY_WINDOW, availability_window);
+ PUTOPT(u32, MEASUREMENTS_PER_AW, measurements_per_aw);
+ 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
* [PATCH wireless-next v4 06/14] wifi: cfg80211: add proximity detection capabilities to PMSR
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
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 PD support and
concurrent ISTA/RSTA operation for simultaneous initiator and
responder roles.
Extend FTM capabilities to support PASN negotiation and device timing
constraints. Add antenna configuration for the PR Element during PASN
negotiation as per the specification. Add ranging interval limits to
advertise device timing capabilities for EDCA and NTB-based ranging.
The existing support_rsta flag provides only a generic indication of
RSTA capability without distinguishing between different ranging
protocols, and there is no equivalent capability advertisement for the
ISTA role.
Restructure the FTM capabilities to use nested ista and rsta
sub-structs, each carrying per-mode flags for Non-Trigger Based,
Trigger Based, and EDCA based ranging.
Expose these capabilities over nl80211 using new nested ISTA_CAPS and
RSTA_CAPS attributes. The legacy RSTA_SUPPORT flag is retained for
backward compatibility and is set whenever any per-mode RSTA capability
is supported.
Update the FTM request validation path to check RSTA requests against
the per-mode capabilities, 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 | 47 ++++++++++++++++++++++-
include/uapi/linux/nl80211.h | 48 +++++++++++++++++++++++
net/wireless/nl80211.c | 74 ++++++++++++++++++++++++++++++++++--
net/wireless/pmsr.c | 22 ++++++++++-
4 files changed, 184 insertions(+), 7 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7bc4fff024d6..986775cd4502 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5717,7 +5717,35 @@ 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
+ * @ftm.max_no_of_rx_antennas: maximum number of receive antennas supported for
+ * EDCA based ranging
+ * @ftm.min_allowed_ranging_interval_edca: Minimum EDCA ranging
+ * interval supported by the device in milli seconds. (0 means unknown)
+ * @ftm.min_allowed_ranging_interval_ntb: Minimum NTB ranging
+ * interval supported by the device in milli seconds. (0 means unknown)
+ * @ftm.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.pd_concurrent_ista_rsta_support: As the peer measurement request can be
+ * a multi-peer request this will indicate if the device can act
+ * simultaneously as initiator and a responder. Only valid if
+ * @ftm.rsta_support is set.
*/
struct cfg80211_pmsr_capabilities {
unsigned int max_peers;
@@ -5743,7 +5771,22 @@ 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;
+ u8 pd_support:1,
+ pd_concurrent_ista_rsta_support:1;
} ftm;
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 4fd2d3fb84ec..a1a5bc21ab6f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -7905,6 +7905,42 @@ 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_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
+ * @NL80211_PMSR_FTM_CAPA_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT: flag attribute
+ * indicating that as the peer measurement request can be a multi-peer
+ * request, the device can act simultaneously as initiator and a responder,
+ * where the multiple requests are being processed simultaneously. Only
+ * valid if @NL80211_PMSR_FTM_CAPA_ATTR_RSTA_SUPPORT is set.
+ * @NL80211_PMSR_FTM_CAPA_ATTR_6GHZ_RSTA_SUPPORT: flag attribute indicating
+ * the device supports operating as RSTA in the 6 GHz band
+ * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS: u32 attribute indicating
+ * the maximum number of transmit antennas supported for EDCA based ranging
+ * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS: u32 attribute indicating
+ * the maximum number of receive antennas supported for EDCA based ranging
+ * @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)
+ * @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)
*
* @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal
* @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number
@@ -7930,6 +7966,18 @@ 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_PD_SUPPORT,
+ NL80211_PMSR_FTM_CAPA_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT,
+ NL80211_PMSR_FTM_CAPA_ATTR_6GHZ_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,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 90953194d0e3..8e06ff02c5cc 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2387,10 +2387,78 @@ 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))
- return -ENOBUFS;
+ 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.pd_support) {
+ if (nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_SUPPORT))
+ return -ENOBUFS;
+ if (cap->ftm.pd_concurrent_ista_rsta_support &&
+ nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_PD_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
* [PATCH wireless-next v4 07/14] wifi: cfg80211: add NTB continuous ranging and FTM PD request support
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
Proximity detection (PD) applications require sustained measurement
sessions without repeated FTM negotiation overhead. Currently, each
ranging session requires separate negotiation.
Enable NTB continuous ranging with configurable timing and measurement
parameters as per the specification "Proximity Ranging (PR)
Implementation Consideration Draft 1.9 Rev 1, section 5.3".
Introduce "pd_request" field in the FTM request structure to support
peer-to-peer proximity detection requests. Validate that PD request
is not compatible with trigger-based (TB) ranging.
Mark %NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST as optional. If absent,
treat it as no preference and let the driver or firmware choose a
suitable value.
Burst parameters (ftms_per_burst) are not applicable for trigger-based
or non-trigger-based ranging. Add validation to reject burst parameters
when NTB or TB ranging is requested.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
include/net/cfg80211.h | 34 +++++++++++++++++-
include/uapi/linux/nl80211.h | 45 ++++++++++++++++++++++--
net/wireless/nl80211.c | 11 ++++++
net/wireless/pmsr.c | 67 +++++++++++++++++++++++++++++++-----
4 files changed, 145 insertions(+), 12 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 986775cd4502..fb9191449886 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4351,7 +4351,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
@@ -4368,6 +4369,29 @@ 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.
+ * @pd_request: indicates a peer-to-peer PD request.
+ * @min_time_between_measurements: minimum time between two consecutive range
+ * measurements in units of 100 micro seconds, applicable for
+ * non trigger based ranging. Only valid if @non_trigger_based is set.
+ * @max_time_between_measurements: maximum time between two consecutive range
+ * measurements in units of 10 milli seconds, to avoid FTM negotiation
+ * applicable for non trigger based ranging. 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.
+ * @measurements_per_aw: number of measurement attempts per availability window
+ * with a maximum value of 4. 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 measurements to be performed in total.
+ * 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.
*/
@@ -4387,6 +4411,14 @@ struct cfg80211_pmsr_ftm_request_peer {
u8 ftms_per_burst;
u8 ftmr_retries;
u8 bss_color;
+
+ u8 pd_request:1;
+ u32 min_time_between_measurements;
+ u32 max_time_between_measurements;
+ u32 availability_window;
+ u32 nominal_time;
+ u32 measurements_per_aw;
+ u32 num_measurements;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index a1a5bc21ab6f..b271a9629b0f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -7798,6 +7798,8 @@ 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_PD_REQUEST: flag attribute indicating this is a
+ * peer-to-peer PD request
*
* @NUM_NL80211_PMSR_PEER_ATTRS: internal
* @NL80211_PMSR_PEER_ATTR_MAX: highest attribute number
@@ -7809,6 +7811,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_PD_REQUEST,
/* keep last */
NUM_NL80211_PMSR_PEER_ATTRS,
@@ -8002,9 +8005,11 @@ enum nl80211_peer_measurement_ftm_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)
@@ -8038,6 +8043,36 @@ enum nl80211_peer_measurement_ftm_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,
+ * applicable for non-trigger based ranging (u32). 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,
+ * to avoid FTM negotiation, applicable for non-trigger based ranging (u32)
+ * . Only valid if %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
+ * @NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME: (Optional) The nominal time field
+ * shall be set to the nominal duration between adjacent Availability
+ * Windows in units of milli seconds (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_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_MEAS_PER_AW: (Optional) This field shall
+ * indicate the number of measurements attempts per AW with a maximum value
+ * of 4 (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
+ * measurements to be performed in total. 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
@@ -8059,6 +8094,12 @@ 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_MEAS_PER_AW,
+ 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 8e06ff02c5cc..8bcc4aa6514e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -385,6 +385,16 @@ 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_MEAS_PER_AW] = NLA_POLICY_MAX(NLA_U32, 4),
+ [NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS] = { .type = NLA_U32 },
};
static const struct nla_policy
@@ -407,6 +417,7 @@ 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_PD_REQUEST] = { .type = NLA_FLAG },
};
static const struct nla_policy
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index c21f693fac29..9432cd645f2f 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -90,15 +90,6 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
out->ftm.ftms_per_burst =
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)) {
- 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");
- return -EINVAL;
- }
-
out->ftm.ftmr_retries = 3;
if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES])
out->ftm.ftmr_retries =
@@ -128,6 +119,13 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
return -EINVAL;
}
+ if (out->ftm.pd_request && out->ftm.trigger_based) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ ftmreq,
+ "FTM: TB ranging is not supported by Proximity Detection");
+ 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 +141,23 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
return -EINVAL;
}
+ if ((out->ftm.trigger_based || out->ftm.non_trigger_based) &&
+ tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST],
+ "FTM: FTMs per burst cannot be set for trigger based or non trigger based ranging");
+ return -EINVAL;
+ }
+
+ if (!out->ftm.trigger_based && !out->ftm.non_trigger_based &&
+ capa->ftm.max_ftms_per_burst &&
+ 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");
+ return -EINVAL;
+ }
+
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,32 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
return -EINVAL;
}
+ if (out->ftm.non_trigger_based) {
+ 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_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME])
+ out->ftm.nominal_time =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]);
+
+ if (tb[NL80211_PMSR_FTM_REQ_ATTR_MEAS_PER_AW])
+ out->ftm.measurements_per_aw =
+ nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MEAS_PER_AW]);
+
+ 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 +290,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev,
memcpy(out->addr, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]), ETH_ALEN);
+ out->ftm.pd_request = !!tb[NL80211_PMSR_PEER_ATTR_PD_REQUEST];
+
+ if (out->ftm.pd_request && !rdev->wiphy.pmsr_capa->ftm.pd_support) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[NL80211_PMSR_PEER_ATTR_PD_REQUEST],
+ "PD request 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
* [PATCH wireless-next v4 05/14] wifi: cfg80211: add start/stop proximity detection commands
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
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 | 32 ++++++++++++++++++++-
net/wireless/core.h | 2 ++
net/wireless/nl80211.c | 54 ++++++++++++++++++++++++++++++++++++
net/wireless/rdev-ops.h | 19 +++++++++++++
net/wireless/trace.h | 10 +++++++
7 files changed, 130 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ce5ed86161bc..7bc4fff024d6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4899,6 +4899,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);
@@ -5270,6 +5273,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 62e461ffa0ce..4fd2d3fb84ec 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1369,6 +1369,12 @@
* %NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP. The current channel
* definition is also sent.
*
+ * @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
*/
@@ -1634,6 +1640,9 @@ enum nl80211_commands {
NL80211_CMD_INCUMBENT_SIGNAL_DETECT,
+ 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 67a603129c42..7bab8c4fb873 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -270,6 +270,25 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
rdev->opencount--;
}
+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 (!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);
@@ -294,6 +313,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;
}
@@ -760,6 +782,9 @@ int wiphy_register(struct wiphy *wiphy)
!rdev->ops->add_nan_func || !rdev->ops->del_nan_func ||
!(wiphy->nan_supported_bands & BIT(NL80211_BAND_2GHZ)))))
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_WDS)))
return -EINVAL;
@@ -1309,6 +1334,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;
}
@@ -1418,9 +1446,11 @@ void cfg80211_leave(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_PD:
/* nothing to do */
break;
case NL80211_IFTYPE_UNSPECIFIED:
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 6cace846d7a3..f631b6997988 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -550,6 +550,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);
struct cfg80211_internal_bss *
cfg80211_bss_update(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 75933f7865ad..90953194d0e3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16307,6 +16307,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)
{
@@ -18988,6 +19028,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 3c0fff3cb5ac..921566fa802d 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1061,6 +1061,25 @@ rdev_nan_change_conf(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 56718e250d31..1ebb6e90cf8f 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
* [PATCH wireless-next v4 04/14] wifi: cfg80211/mac80211: Add NL80211_IFTYPE_PD for PD PASN and PMSR operations
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
Add a new wdev-only interface type NL80211_IFTYPE_PD to support
Proximity Detection (PD) operations such as PASN, key install 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 key
management 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.
The PD interface provides isolated functionality for PD PASN
and PMSR without affecting existing network operations.
PD discovery can be performed on any available interface, such as
NL80211_IFTYPE_STATION, NL80211_IFTYPE_AP etc.
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 | 7 ++++++-
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, 55 insertions(+), 4 deletions(-)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7e139c746c32..62e461ffa0ce 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3677,6 +3677,7 @@ enum nl80211_attrs {
* @NL80211_IFTYPE_OCB: Outside Context of a BSS
* This mode corresponds to the MIB variable dot11OCBActivated=true
* @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev)
+ * @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
*
@@ -3698,6 +3699,7 @@ enum nl80211_iftype {
NL80211_IFTYPE_P2P_DEVICE,
NL80211_IFTYPE_OCB,
NL80211_IFTYPE_NAN,
+ NL80211_IFTYPE_PD,
/* keep last */
NUM_NL80211_IFTYPES,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ee64ac8e0f61..dac211f9a438 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -713,6 +713,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_NAN:
+ case NL80211_IFTYPE_PD:
case NL80211_IFTYPE_UNSPECIFIED:
case NUM_NL80211_IFTYPES:
case NL80211_IFTYPE_P2P_CLIENT:
@@ -3183,6 +3184,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 2f0c93f3ace6..79124ab31d0c 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -494,6 +494,7 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
break;
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_NAN:
+ case NL80211_IFTYPE_PD:
continue;
case NL80211_IFTYPE_MONITOR:
WARN_ON_ONCE(!ieee80211_hw_check(&local->hw,
@@ -1436,6 +1437,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_NAN:
+ 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 40ce0bb72726..bdb806647362 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1369,6 +1369,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_UNSPECIFIED:
@@ -1489,7 +1490,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);
@@ -1504,6 +1506,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 */
@@ -1940,6 +1943,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
case NL80211_IFTYPE_P2P_DEVICE:
sdata->vif.bss_conf.bssid = sdata->vif.addr;
break;
+ case NL80211_IFTYPE_PD:
+ break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_WDS:
case NUM_NL80211_IFTYPES:
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 19c33f7a8193..b7ff16ece252 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4607,6 +4607,12 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
(ieee80211_is_public_action(hdr, skb->len) ||
(ieee80211_is_auth(hdr->frame_control) &&
ether_addr_equal(sdata->vif.addr, hdr->addr1)));
+ 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 55054de62508..2094ed366695 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2121,6 +2121,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 fa0764ede9c5..1eb4f8722016 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -816,6 +816,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_PD:
break;
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_UNSPECIFIED:
@@ -939,6 +940,7 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
case NL80211_IFTYPE_P2P_DEVICE:
/* Can NAN type be considered as beaconing interface? */
case NL80211_IFTYPE_NAN:
+ 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 23afc250bc10..67a603129c42 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1420,6 +1420,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
break;
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
+ 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 5cd86253a62e..6d13093ce449 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -939,6 +939,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
* public action frames
*/
case NL80211_IFTYPE_NAN:
+ case NL80211_IFTYPE_PD:
default:
err = -EOPNOTSUPP;
break;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8547209dd504..75933f7865ad 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1726,6 +1726,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:
@@ -4757,6 +4762,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],
@@ -4813,8 +4819,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);
@@ -10548,7 +10555,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)
@@ -13965,6 +13973,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;
}
@@ -14028,6 +14041,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;
}
@@ -14153,6 +14171,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 20bba7e491c5..22bbf6d958de 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2400,6 +2400,9 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
case NL80211_IFTYPE_NAN:
/* we have no info, but NAN is also pretty universal */
continue;
+ 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 0a0cea018fc5..d558c4bc00f0 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1186,7 +1186,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 ||
@@ -1250,6 +1251,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
* [PATCH wireless-next v4 03/14] wifi: cfg80211: Add MAC address filter to remain_on_channel
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
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 8cd870ece351..ce5ed86161bc 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5081,7 +5081,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 67d764023988..7e139c746c32 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.
@@ -6834,6 +6836,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.
*/
@@ -6913,6 +6921,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 d71e0c6d2165..09819cc801f5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2068,7 +2068,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 e15cd26f3a79..8547209dd504 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -13809,6 +13809,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;
@@ -13821,6 +13822,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;
@@ -13868,7 +13877,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 2bad8b60b7c9..3c0fff3cb5ac 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 af23f4fca90a..56718e250d31 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
* [PATCH wireless-next v4 02/14] wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
When the nl80211 socket that originated a PMSR request is
closed, cfg80211_release_pmsr() sets the request's nl_portid
to zero and schedules pmsr_free_wk to process the abort
asynchronously. If the interface is concurrently torn down
before that work runs, cfg80211_pmsr_wdev_down() calls
cfg80211_pmsr_process_abort() directly. However, the already-
scheduled pmsr_free_wk work item remains pending and may run
after the interface has been removed from the driver. This
could cause the driver's abort_pmsr callback to operate on a
torn-down interface, leading to undefined behavior and
potential crashes.
Cancel pmsr_free_wk synchronously in cfg80211_pmsr_wdev_down()
before calling cfg80211_pmsr_process_abort(). This ensures any
pending or in-progress work is drained before interface teardown
proceeds, preventing the work from invoking the driver abort
callback after the interface is gone.
Fixes: 9bb7e0f24e7e ("cfg80211: add peer measurement with FTM initiator API")
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
---
net/wireless/pmsr.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 936c16d80cc9..afc0e3f931ec 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -667,6 +667,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
}
spin_unlock_bh(&wdev->pmsr_lock);
+ cancel_work_sync(&wdev->pmsr_free_wk);
if (found)
cfg80211_pmsr_process_abort(wdev);
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next v4 01/14] wifi: cfg80211: restrict LMR feedback check to TB and non-TB ranging
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
In-Reply-To: <20260320175938.2547288-1-peddolla.reddy@oss.qualcomm.com>
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 556f30f5d60a..936c16d80cc9 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
* [PATCH wireless-next v4 00/14] wifi: Ranging support enhancements
From: Peddolla Harshavardhan Reddy @ 2026-03-20 17:59 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, kavita.kavita
This patch series introduces Fine Timing Measurement (FTM)
enhancements and Proximity Detection (PD) capabilities. The
implementation follows the Wi-Fi Alliance "PR Implementation
Consideration Draft 1.9 Rev 1" specification and extends the
existing peer measurement framework with advanced ranging
features.
---
Changes in v4:
- Addressed comments.
- Dropped patch "[PATCH wireless-next v3 12/15] wifi: cfg80211: add
FTM range report negotiation support" as it is no longer needed since
FTM range report is mandatory for PD EDCA based ranging.
- Added a new attribute for number of measurements to be performed in
total for NTB ranging.
---
Changes in v3:
- Addressed comments.
- Dropped patch "wifi: cfg80211: add MAC randomization support for PD
requests" as it is no longer needed with the introduction of PD iface
type.
- Restored altered checks in "wifi: cfg80211: add continuous ranging
and PD request support" and added additional conditions to ensure
backward compatibility.
- Added a new extended feature flag to support Secure LTF keyseed
installation.
---
Changes in v2:
- Addressed comments.
- Removed ABORT command implementation as it is not needed.
- Added a patch for enhancement of Remain on channel command.
- Intoduced a new interface type PD.
- Added a patch for suppressing ranging results when requested.
---
Kavita Kavita (1):
wifi: mac80211_hwsim: Add support for extended FTM ranging
Peddolla Harshavardhan Reddy (13):
wifi: cfg80211: restrict LMR feedback check to TB and non-TB ranging
wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down
wifi: cfg80211: Add MAC address filter to remain_on_channel
wifi: cfg80211/mac80211: Add NL80211_IFTYPE_PD for PD PASN and PMSR
operations
wifi: cfg80211: add start/stop proximity detection commands
wifi: cfg80211: add proximity detection capabilities to PMSR
wifi: cfg80211: add NTB continuous ranging and FTM PD request support
wifi: cfg80211: extend PMSR FTM response for proximity ranging
wifi: cfg80211: add role-based PD peer limits
wifi: cfg80211: add ingress/egress distance thresholds for FTM
wifi: cfg80211: add PD-specific preamble and bandwidth capabilities
wifi: cfg80211: allow suppressing FTM result reporting for PD requests
wifi: cfg80211: add LTF keyseed support for secure ranging
drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 +-
drivers/net/wireless/ath/wil6210/cfg80211.c | 3 +-
.../broadcom/brcm80211/brcmfmac/p2p.c | 4 +-
.../broadcom/brcm80211/brcmfmac/p2p.h | 3 +-
.../net/wireless/marvell/mwifiex/cfg80211.c | 3 +-
.../wireless/microchip/wilc1000/cfg80211.c | 3 +-
drivers/net/wireless/virtual/mac80211_hwsim.c | 200 +++++++++++++++
include/linux/ieee80211.h | 1 +
include/net/cfg80211.h | 198 ++++++++++++++-
include/uapi/linux/nl80211.h | 229 +++++++++++++++++-
net/mac80211/cfg.c | 2 +
net/mac80211/chan.c | 2 +
net/mac80211/ieee80211_i.h | 3 +-
net/mac80211/iface.c | 7 +-
net/mac80211/offchannel.c | 4 +-
net/mac80211/rx.c | 6 +
net/mac80211/util.c | 1 +
net/wireless/chan.c | 2 +
net/wireless/core.c | 31 +++
net/wireless/core.h | 2 +
net/wireless/mlme.c | 1 +
net/wireless/nl80211.c | 209 +++++++++++++++-
net/wireless/pmsr.c | 181 ++++++++++++--
net/wireless/rdev-ops.h | 26 +-
net/wireless/reg.c | 3 +
net/wireless/trace.h | 22 +-
net/wireless/util.c | 19 +-
27 files changed, 1117 insertions(+), 51 deletions(-)
base-commit: 9ac76f3d0bb2940db3a9684d596b9c8f301ef315
--
2.34.1
^ permalink raw reply
* Re: [Intel-wired-lan] [PATCH net-next v3 03/13] net: introduce ndo_set_rx_mode_async and dev_rx_mode_work
From: Stanislav Fomichev @ 2026-03-20 15:49 UTC (permalink / raw)
To: Loktionov, Aleksandr
Cc: Stanislav Fomichev, netdev@vger.kernel.org, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
horms@kernel.org, corbet@lwn.net, skhan@linuxfoundation.org,
andrew+netdev@lunn.ch, michael.chan@broadcom.com,
pavan.chebbi@broadcom.com, Nguyen, Anthony L, Kitszel, Przemyslaw,
saeedm@nvidia.com, tariqt@nvidia.com, mbloch@nvidia.com,
alexanderduyck@fb.com, kernel-team@meta.com,
johannes@sipsolutions.net, sd@queasysnail.net, jianbol@nvidia.com,
dtatulea@nvidia.com, mohsin.bashr@gmail.com, Keller, Jacob E,
willemb@google.com, skhawaja@google.com, bestswngs@gmail.com,
kees@kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, intel-wired-lan@lists.osuosl.org,
linux-rdma@vger.kernel.org, linux-wireless@vger.kernel.org,
linux-kselftest@vger.kernel.org, leon@kernel.org
In-Reply-To: <IA3PR11MB89865C96824F6518F4A01B9CE54CA@IA3PR11MB8986.namprd11.prod.outlook.com>
On 03/20, Loktionov, Aleksandr wrote:
>
>
> > -----Original Message-----
> > From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> > Of Stanislav Fomichev
> > Sent: Friday, March 20, 2026 2:25 AM
> > To: netdev@vger.kernel.org
> > Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> > pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> > skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> > michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> > L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> > <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> > mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> > johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> > dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> > Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> > skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> > <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> > doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> > lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> > wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> > leon@kernel.org
> > Subject: [Intel-wired-lan] [PATCH net-next v3 03/13] net: introduce
> > ndo_set_rx_mode_async and dev_rx_mode_work
> >
> > Add ndo_set_rx_mode_async callback that drivers can implement instead
> > of the legacy ndo_set_rx_mode. The legacy callback runs under the
> > netif_addr_lock spinlock with BHs disabled, preventing drivers from
> > sleeping. The async variant runs from a work queue with rtnl_lock and
> > netdev_lock_ops held, in fully sleepable context.
> >
> > When __dev_set_rx_mode() sees ndo_set_rx_mode_async, it schedules
> > dev_rx_mode_work instead of calling the driver inline. The work
> > function takes two snapshots of each address list (uc/mc) under the
> > addr_lock, then drops the lock and calls the driver with the work
> > copies. After the driver returns, it reconciles the snapshots back to
> > the real lists under the lock.
> >
> > Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> > Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> > ---
> > Documentation/networking/netdevices.rst | 8 +++
> > include/linux/netdevice.h | 20 ++++++
> > net/core/dev.c | 95 +++++++++++++++++++++++-
> > -
> > 3 files changed, 116 insertions(+), 7 deletions(-)
> >
> > diff --git a/Documentation/networking/netdevices.rst
> > b/Documentation/networking/netdevices.rst
> > index 35704d115312..dc83d78d3b27 100644
> > --- a/Documentation/networking/netdevices.rst
> > +++ b/Documentation/networking/netdevices.rst
> > @@ -289,6 +289,14 @@ struct net_device synchronization rules
> > ndo_set_rx_mode:
> > Synchronization: netif_addr_lock spinlock.
> > Context: BHs disabled
>
> ...
>
> > to
> > +device
> > + * and configure RX filtering.
> > + * @dev: device
> > + *
> > + * When the device doesn't support unicast filtering it is put in
> > +promiscuous
> > + * mode while unicast addresses are present.
> > */
> > void __dev_set_rx_mode(struct net_device *dev) {
> > const struct net_device_ops *ops = dev->netdev_ops;
> >
> > /* dev_open will call this function so the list will stay sane.
> > */
> > - if (!(dev->flags&IFF_UP))
> > + if (!netif_up_and_present(dev))
> > return;
> >
> > - if (!netif_device_present(dev))
> > + if (ops->ndo_set_rx_mode_async) {
> > + queue_work(rx_mode_wq, &dev->rx_mode_work);
> > return;
> This early return skips the legacy core fallback below.
> Before this patch, __dev_set_rx_mode() continued into the
> existing unicast-filter handling when the device did not
> advertise IFF_UNICAST_FLT.
>
> After this patch, any driver that implements
> ndo_set_rx_mode_async but does not set IFF_UNICAST_FLT
> will never hit that fallback path.
I believe this is addressed later in "net: move promiscuity handling into
dev_rx_mode_work"? That should take care of doing __dev_set_promiscuity
for !IFF_UNICAST_FLT+ndo_set_rx_mode_async. Not sure if there is a
better way to rearrange the chunks in the patches.
if (ops->ndo_set_rx_mode_async) {
...
+ promisc_inc = dev_uc_promisc_update(dev);
+
+ netif_addr_unlock_bh(dev);
+ } else {
+ netif_addr_lock_bh(dev);
+ promisc_inc = dev_uc_promisc_update(dev);
+ netif_addr_unlock_bh(dev);
+ }
+
+ if (promisc_inc)
+ __dev_set_promiscuity(dev, promisc_inc, false);
+
^ permalink raw reply
* Re: [PATCH net-next v3 06/13] mlx5: convert to ndo_set_rx_mode_async
From: Stanislav Fomichev @ 2026-03-20 15:42 UTC (permalink / raw)
To: Cosmin Ratiu
Cc: netdev@vger.kernel.org, sdf@fomichev.me,
intel-wired-lan@lists.osuosl.org, bestswngs@gmail.com,
kernel-team@meta.com, przemyslaw.kitszel@intel.com,
davem@davemloft.net, pabeni@redhat.com, horms@kernel.org,
corbet@lwn.net, anthony.l.nguyen@intel.com, willemb@google.com,
linux-kernel@vger.kernel.org, skhawaja@google.com, Dragos Tatulea,
kees@kernel.org, Jianbo Liu, alexanderduyck@fb.com,
kuba@kernel.org, leon@kernel.org, Saeed Mahameed,
andrew+netdev@lunn.ch, michael.chan@broadcom.com, Mark Bloch,
sd@queasysnail.net, Tariq Toukan, jacob.e.keller@intel.com,
skhan@linuxfoundation.org, mohsin.bashr@gmail.com,
edumazet@google.com, pavan.chebbi@broadcom.com,
linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org,
johannes@sipsolutions.net, linux-doc@vger.kernel.org,
aleksandr.loktionov@intel.com, linux-wireless@vger.kernel.org
In-Reply-To: <c0915086dc876f59e3c69886a8629efa3540d737.camel@nvidia.com>
On 03/20, Cosmin Ratiu wrote:
> On Thu, 2026-03-19 at 18:24 -0700, Stanislav Fomichev wrote:
> > Convert mlx5 from ndo_set_rx_mode to ndo_set_rx_mode_async. The
> > driver's mlx5e_set_rx_mode now receives uc/mc snapshots and calls
> > mlx5e_fs_set_rx_mode_work directly instead of queueing work.
> >
> > mlx5e_sync_netdev_addr and mlx5e_handle_netdev_addr now take
> > explicit uc/mc list parameters and iterate with
> > netdev_hw_addr_list_for_each instead of netdev_for_each_{uc,mc}_addr.
> >
> > Fallback to netdev's uc/mc in a few places and grab addr lock.
> >
> > Cc: Saeed Mahameed <saeedm@nvidia.com>
> > Cc: Tariq Toukan <tariqt@nvidia.com>
> > Cc: Cosmin Ratiu <cratiu@nvidia.com>
> > Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> > Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> > ---
> > .../net/ethernet/mellanox/mlx5/core/en/fs.h | 5 +++-
> > .../net/ethernet/mellanox/mlx5/core/en_fs.c | 30 ++++++++++++-----
> > --
> > .../net/ethernet/mellanox/mlx5/core/en_main.c | 16 +++++++---
> > 3 files changed, 36 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
> > b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
> > index c3408b3f7010..091b80a67189 100644
> > --- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
> > @@ -201,7 +201,10 @@ int mlx5e_add_vlan_trap(struct
> > mlx5e_flow_steering *fs, int trap_id, int tir_nu
> > void mlx5e_remove_vlan_trap(struct mlx5e_flow_steering *fs);
> > int mlx5e_add_mac_trap(struct mlx5e_flow_steering *fs, int trap_id,
> > int tir_num);
> > void mlx5e_remove_mac_trap(struct mlx5e_flow_steering *fs);
> > -void mlx5e_fs_set_rx_mode_work(struct mlx5e_flow_steering *fs,
> > struct net_device *netdev);
> > +void mlx5e_fs_set_rx_mode_work(struct mlx5e_flow_steering *fs,
> > + struct net_device *netdev,
> > + struct netdev_hw_addr_list *uc,
> > + struct netdev_hw_addr_list *mc);
> > int mlx5e_fs_vlan_rx_add_vid(struct mlx5e_flow_steering *fs,
> > struct net_device *netdev,
> > __be16 proto, u16 vid);
> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
> > b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
> > index 55255fe6e415..a9daefbd8f8f 100644
> > --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
> > @@ -609,20 +609,26 @@ static void mlx5e_execute_l2_action(struct
> > mlx5e_flow_steering *fs,
> > }
> >
> > static void mlx5e_sync_netdev_addr(struct mlx5e_flow_steering *fs,
> > - struct net_device *netdev)
> > + struct net_device *netdev,
> > + struct netdev_hw_addr_list *uc,
> > + struct netdev_hw_addr_list *mc)
> > {
> > struct netdev_hw_addr *ha;
> >
> > - netif_addr_lock_bh(netdev);
> > + if (!uc || !mc) {
> > + netif_addr_lock_bh(netdev);
> > + mlx5e_sync_netdev_addr(fs, netdev, &netdev->uc,
> > &netdev->mc);
> > + netif_addr_unlock_bh(netdev);
> > + return;
> > + }
> >
> > mlx5e_add_l2_to_hash(fs->l2.netdev_uc, netdev->dev_addr);
> > - netdev_for_each_uc_addr(ha, netdev)
> > +
> > + netdev_hw_addr_list_for_each(ha, uc)
> > mlx5e_add_l2_to_hash(fs->l2.netdev_uc, ha->addr);
> >
> > - netdev_for_each_mc_addr(ha, netdev)
> > + netdev_hw_addr_list_for_each(ha, mc)
> > mlx5e_add_l2_to_hash(fs->l2.netdev_mc, ha->addr);
> > -
> > - netif_addr_unlock_bh(netdev);
> > }
> >
> > static void mlx5e_fill_addr_array(struct mlx5e_flow_steering *fs,
> > int list_type,
> > @@ -724,7 +730,9 @@ static void mlx5e_apply_netdev_addr(struct
> > mlx5e_flow_steering *fs)
> > }
> >
> > static void mlx5e_handle_netdev_addr(struct mlx5e_flow_steering *fs,
> > - struct net_device *netdev)
> > + struct net_device *netdev,
> > + struct netdev_hw_addr_list *uc,
> > + struct netdev_hw_addr_list *mc)
> > {
> > struct mlx5e_l2_hash_node *hn;
> > struct hlist_node *tmp;
> > @@ -736,7 +744,7 @@ static void mlx5e_handle_netdev_addr(struct
> > mlx5e_flow_steering *fs,
> > hn->action = MLX5E_ACTION_DEL;
> >
> > if (fs->state_destroy)
> > - mlx5e_sync_netdev_addr(fs, netdev);
> > + mlx5e_sync_netdev_addr(fs, netdev, uc, mc);
> >
> > mlx5e_apply_netdev_addr(fs);
> > }
> > @@ -820,7 +828,9 @@ static void mlx5e_destroy_promisc_table(struct
> > mlx5e_flow_steering *fs)
> > }
> >
> > void mlx5e_fs_set_rx_mode_work(struct mlx5e_flow_steering *fs,
> > - struct net_device *netdev)
> > + struct net_device *netdev,
> > + struct netdev_hw_addr_list *uc,
> > + struct netdev_hw_addr_list *mc)
> > {
> > struct mlx5e_l2_table *ea = &fs->l2;
> >
> > @@ -850,7 +860,7 @@ void mlx5e_fs_set_rx_mode_work(struct
> > mlx5e_flow_steering *fs,
> > if (enable_broadcast)
> > mlx5e_add_l2_flow_rule(fs, &ea->broadcast,
> > MLX5E_FULLMATCH);
> >
> > - mlx5e_handle_netdev_addr(fs, netdev);
> > + mlx5e_handle_netdev_addr(fs, netdev, uc, mc);
> >
> > if (disable_broadcast)
> > mlx5e_del_l2_flow_rule(fs, &ea->broadcast);
> > diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> > b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> > index f7009da94f0b..e86cf1ee108d 100644
> > --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> > +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> > @@ -4108,11 +4108,16 @@ static void mlx5e_nic_set_rx_mode(struct
> > mlx5e_priv *priv)
> > queue_work(priv->wq, &priv->set_rx_mode_work);
> > }
> >
> > -static void mlx5e_set_rx_mode(struct net_device *dev)
> > +static void mlx5e_set_rx_mode(struct net_device *dev,
> > + struct netdev_hw_addr_list *uc,
> > + struct netdev_hw_addr_list *mc)
> > {
> > struct mlx5e_priv *priv = netdev_priv(dev);
> >
> > - mlx5e_nic_set_rx_mode(priv);
> > + if (mlx5e_is_uplink_rep(priv))
> > + return; /* no rx mode for uplink rep */
> > +
> > + mlx5e_fs_set_rx_mode_work(priv->fs, dev, uc, mc);
>
> While this chunk is correct, I think there's a logical conflict waiting
> to happen with Saeed's pending patch touching this area ([1]).
>
> You have inlined mlx5e_nic_set_rx_mode here, but after Saeed's patch
> the mlx5e_is_uplink_rep condition added here should be dropped.
>
> Not sure the automatic merge will do that.
>
> [1]
> https://lore.kernel.org/netdev/20260319005456.82745-1-saeed@kernel.org/T/#u
Thanks for the heads up, will try to wait for this to be pulled before
reposting!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox