public inbox for linux-wireless@vger.kernel.org
 help / color / mirror / Atom feed
From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
To: linux-wireless@vger.kernel.org
Cc: Johannes Berg <johannes.berg@intel.com>
Subject: [PATCH wireless-next 08/15] wifi: mac80211: support NAN stations
Date: Wed, 25 Mar 2026 23:15:29 +0200	[thread overview]
Message-ID: <20260325230443.32c5644ec4be.I7a7bd6e8e751cab49c329419485839afd209cfc6@changeid> (raw)
In-Reply-To: <20260325211536.910411-1-miriam.rachel.korenblit@intel.com>

Add support for both NMI and NDI stations.

The NDI station will be linked to the NMI station of the NAN peer for
which the NDI station is added.

A peer can choose to reuse its NMI address as the NDI address.
Since different keys might be in use for NAN management and for data
frames, we will have 2 different stations, even if they'll have the same
address.

Even though there are no links in NAN, sta->deflink will still be used
to store the one set of capabilities and SMPS mode.

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h  |  13 ++++-
 net/mac80211/cfg.c      | 103 ++++++++++++++++++++++++++++++++++++----
 net/mac80211/he.c       |   7 ++-
 net/mac80211/ht.c       |  19 ++++++--
 net/mac80211/iface.c    |  10 ++--
 net/mac80211/sta_info.c |  21 +++++++-
 net/mac80211/sta_info.h |   3 +-
 net/mac80211/util.c     |  41 ++++++++++++++++
 net/mac80211/vht.c      |  16 ++++++-
 9 files changed, 209 insertions(+), 24 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 24685f106757..8656e2cc2b75 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2534,11 +2534,15 @@ struct ieee80211_sta_aggregates {
  * @uhr_cap: UHR capabilities of this STA
  * @s1g_cap: S1G capabilities of this STA
  * @agg: per-link data for multi-link aggregation
- * @bandwidth: current bandwidth the station can receive with
+ * @bandwidth: current bandwidth the station can receive with.
+ *	This is the minimum between the peer's capabilities and our own
+ *	operating channel width; Invalid for NAN since that is operating on
+ *	multiple channels.
  * @rx_nss: in HT/VHT, the maximum number of spatial streams the
  *	station can receive at the moment, changed by operating mode
  *	notifications and capabilities. The value is only valid after
- *	the station moves to associated state.
+ *	the station moves to associated state. Invalid for NAN since it
+ *	operates on multiple configurations of rx_nss.
  * @txpwr: the station tx power configuration
  *
  */
@@ -2620,6 +2624,7 @@ struct ieee80211_link_sta {
  * @valid_links: bitmap of valid links, or 0 for non-MLO
  * @spp_amsdu: indicates whether the STA uses SPP A-MSDU or not.
  * @epp_peer: indicates that the peer is an EPP peer.
+ * @nmi: For NDI stations, pointer to the NMI station of the peer.
  */
 struct ieee80211_sta {
 	u8 addr[ETH_ALEN] __aligned(2);
@@ -2648,6 +2653,8 @@ struct ieee80211_sta {
 	struct ieee80211_link_sta deflink;
 	struct ieee80211_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
 
+	struct ieee80211_sta __rcu *nmi;
+
 	/* must be last */
 	u8 drv_priv[] __aligned(sizeof(void *));
 };
@@ -2881,6 +2888,8 @@ struct ieee80211_txq {
  *	station has a unique address, i.e. each station entry can be identified
  *	by just its MAC address; this prevents, for example, the same station
  *	from connecting to two virtual AP interfaces at the same time.
+ *	Note that this doesn't apply for NAN, in which the peer's NMI address
+ *	can be equal to its NDI address.
  *
  * @IEEE80211_HW_SUPPORTS_REORDERING_BUFFER: Hardware (or driver) manages the
  *	reordering buffer internally, guaranteeing mac80211 receives frames in
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 701b111db7df..a1089e3964bd 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2077,7 +2077,7 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
 				     enum sta_link_apply_mode mode,
 				     struct link_station_parameters *params)
 {
-	struct ieee80211_supported_band *sband;
+	struct ieee80211_supported_band *sband = NULL;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 	u32 link_id = params->link_id < 0 ? 0 : params->link_id;
 	struct ieee80211_link_data *link =
@@ -2085,6 +2085,9 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
 	struct link_sta_info *link_sta =
 		rcu_dereference_protected(sta->link[link_id],
 					  lockdep_is_held(&local->hw.wiphy->mtx));
+	const struct ieee80211_sta_ht_cap *own_ht_cap;
+	const struct ieee80211_sta_vht_cap *own_vht_cap;
+	const struct ieee80211_sta_he_cap *own_he_cap;
 	bool changes = params->link_mac ||
 		       params->txpwr_set ||
 		       params->supported_rates_len ||
@@ -2114,10 +2117,27 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
 	if (!link || !link_sta)
 		return -EINVAL;
 
-	sband = ieee80211_get_link_sband(link);
-	if (!sband)
+	/*
+	 * We should not have any changes in NDI station, its capabilities are
+	 * copied from the NMI sta
+	 */
+	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN_DATA))
 		return -EINVAL;
 
+	if (sdata->vif.type == NL80211_IFTYPE_NAN) {
+		own_ht_cap = &local->hw.wiphy->nan_capa.phy.ht;
+		own_vht_cap = &local->hw.wiphy->nan_capa.phy.vht;
+		own_he_cap = &local->hw.wiphy->nan_capa.phy.he;
+	} else {
+		sband = ieee80211_get_link_sband(link);
+		if (!sband)
+			return -EINVAL;
+
+		own_ht_cap = &sband->ht_cap;
+		own_vht_cap = &sband->vht_cap;
+		own_he_cap = ieee80211_get_he_iftype_cap_vif(sband, &sdata->vif);
+	}
+
 	if (params->link_mac) {
 		if (mode == STA_LINK_MODE_NEW) {
 			memcpy(link_sta->addr, params->link_mac, ETH_ALEN);
@@ -2139,6 +2159,27 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
 			return ret;
 	}
 
+	if (sdata->vif.type == NL80211_IFTYPE_NAN) {
+		static const u8 all_ofdm_rates[] = {
+			0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+		};
+
+		/* Set the same supported_rates for all bands */
+		for (int i = 0; i < NUM_NL80211_BANDS; i++) {
+			struct ieee80211_supported_band *tmp =
+				sdata->local->hw.wiphy->bands[i];
+
+			if ((i != NL80211_BAND_2GHZ && i != NL80211_BAND_5GHZ) ||
+			    !tmp)
+				continue;
+
+			if (!ieee80211_parse_bitrates(tmp, all_ofdm_rates,
+						      sizeof(all_ofdm_rates),
+						      &link_sta->pub->supp_rates[i]))
+				return -EINVAL;
+		}
+	}
+
 	if (params->supported_rates &&
 	    params->supported_rates_len &&
 	    !ieee80211_parse_bitrates(sband, params->supported_rates,
@@ -2147,22 +2188,24 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
 		return -EINVAL;
 
 	if (params->ht_capa)
-		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, &sband->ht_cap,
+		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, own_ht_cap,
 						  params->ht_capa, link_sta);
 
 	/* VHT can override some HT caps such as the A-MSDU max length */
 	if (params->vht_capa)
 		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-						    &sband->vht_cap,
+						    own_vht_cap,
 						    params->vht_capa, NULL,
 						    link_sta);
 
 	if (params->he_capa)
-		ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
-						  (void *)params->he_capa,
-						  params->he_capa_len,
-						  (void *)params->he_6ghz_capa,
-						  link_sta);
+		_ieee80211_he_cap_ie_to_sta_he_cap(sdata,
+						   own_he_cap,
+						   (void *)params->he_capa,
+						   params->he_capa_len,
+						   (sband && sband->band == NL80211_BAND_6GHZ) ?
+						   (void *)params->he_6ghz_capa : NULL,
+						   link_sta);
 
 	if (params->he_capa && params->eht_capa)
 		ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband,
@@ -2349,6 +2392,32 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 	if (params->airtime_weight)
 		sta->airtime_weight = params->airtime_weight;
 
+	if (params->nmi_mac) {
+		struct ieee80211_sub_if_data *nmi =
+			rcu_dereference_wiphy(local->hw.wiphy,
+					      sdata->u.nan_data.nmi);
+		struct sta_info *nmi_sta;
+
+		if (WARN_ON(!nmi))
+			return -EINVAL;
+
+		nmi_sta = sta_info_get(nmi, params->nmi_mac);
+		if (!nmi_sta)
+			return -ENOENT;
+		rcu_assign_pointer(sta->sta.nmi, &nmi_sta->sta);
+
+		/* For NAN_DATA stations, copy capabilities from the NMI station */
+		if (!nmi_sta->deflink.pub->ht_cap.ht_supported)
+			return -EINVAL;
+
+		sta->deflink.pub->ht_cap = nmi_sta->deflink.pub->ht_cap;
+		sta->deflink.pub->vht_cap = nmi_sta->deflink.pub->vht_cap;
+		sta->deflink.pub->he_cap = nmi_sta->deflink.pub->he_cap;
+		memcpy(&sta->deflink.pub->supp_rates,
+		       &nmi_sta->deflink.pub->supp_rates,
+		       sizeof(sta->deflink.pub->supp_rates));
+	}
+
 	/* set the STA state after all sta info from usermode has been set */
 	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) ||
 	    set & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
@@ -2494,6 +2563,12 @@ static int ieee80211_change_station(struct wiphy *wiphy,
 		else
 			statype = CFG80211_STA_AP_CLIENT_UNASSOC;
 		break;
+	case NL80211_IFTYPE_NAN:
+		statype = CFG80211_STA_NAN_MGMT;
+		break;
+	case NL80211_IFTYPE_NAN_DATA:
+		statype = CFG80211_STA_NAN_DATA;
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -2532,6 +2607,14 @@ static int ieee80211_change_station(struct wiphy *wiphy,
 		}
 	}
 
+	/* NAN capabilties should not change */
+	if (statype == CFG80211_STA_NAN_DATA &&
+	    sta->deflink.pub->ht_cap.ht_supported &&
+	    (params->link_sta_params.ht_capa ||
+	     params->link_sta_params.vht_capa ||
+	     params->link_sta_params.he_capa))
+		return -EINVAL;
+
 	err = sta_apply_parameters(local, sta, params);
 	if (err)
 		return err;
diff --git a/net/mac80211/he.c b/net/mac80211/he.c
index 93e0342cff4f..a3e16a5bec22 100644
--- a/net/mac80211/he.c
+++ b/net/mac80211/he.c
@@ -127,6 +127,10 @@ _ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
 	if (!he_cap_ie || !own_he_cap_ptr || !own_he_cap_ptr->has_he)
 		return;
 
+	/* NDI station are using the capabilities from the NMI station */
+	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_NAN_DATA))
+		return;
+
 	own_he_cap = *own_he_cap_ptr;
 
 	/* Make sure size is OK */
@@ -156,7 +160,8 @@ _ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
 	he_cap->has_he = true;
 
 	link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta);
-	link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
+	if (sdata->vif.type != NL80211_IFTYPE_NAN)
+		link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
 
 	if (he_6ghz_capa)
 		ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, link_sta);
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 410e2354f33a..97719298e038 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -154,6 +154,10 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 	if (!ht_cap_ie || !own_cap_ptr->ht_supported)
 		goto apply;
 
+	/* NDI station are using the capabilities from the NMI station */
+	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_NAN_DATA))
+		return 0;
+
 	ht_cap.ht_supported = true;
 
 	own_cap = *own_cap_ptr;
@@ -254,10 +258,17 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 
 	rcu_read_lock();
 	link_conf = rcu_dereference(sdata->vif.link_conf[link_sta->link_id]);
-	if (WARN_ON(!link_conf))
+	if (WARN_ON(!link_conf)) {
 		width = NL80211_CHAN_WIDTH_20_NOHT;
-	else
+	} else if (sdata->vif.type == NL80211_IFTYPE_NAN ||
+		   sdata->vif.type == NL80211_IFTYPE_NAN_DATA) {
+		/* In NAN, link_sta->bandwidth is invalid since NAN operates on
+		 * multiple channels. Just take the maximum.
+		 */
+		width = NL80211_CHAN_WIDTH_320;
+	} else {
 		width = link_conf->chanreq.oper.width;
+	}
 
 	switch (width) {
 	default:
@@ -285,7 +296,9 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 				IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
 
 	if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
-	    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+	    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+	    sta->sdata->vif.type == NL80211_IFTYPE_NAN ||
+	    sta->sdata->vif.type == NL80211_IFTYPE_NAN_DATA) {
 		enum ieee80211_smps_mode smps_mode;
 
 		switch ((ht_cap.cap & IEEE80211_HT_CAP_SM_PS)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 507c5e016ec8..f1ab85ff326d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -535,12 +535,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 	 * (because if we remove a STA after ops->remove_interface()
 	 * the driver will have removed the vif info already!)
 	 *
-	 * For AP_VLANs stations may exist since there's nothing else that
-	 * would have removed them, but in other modes there shouldn't
-	 * be any stations.
+	 * For AP_VLANs, NAN and NAN_DATA stations may exist since there's
+	 * nothing else that would have removed them, but in other modes there
+	 * shouldn't be any stations.
 	 */
 	flushed = sta_info_flush(sdata, -1);
-	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && flushed > 0);
+	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+		     sdata->vif.type != NL80211_IFTYPE_NAN &&
+		     sdata->vif.type != NL80211_IFTYPE_NAN_DATA && flushed > 0);
 
 	/* don't count this interface for allmulti while it is down */
 	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 4259e9c13ed7..017d91365920 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -795,6 +795,7 @@ struct sta_info *sta_info_alloc_with_link(struct ieee80211_sub_if_data *sdata,
 static int sta_info_insert_check(struct sta_info *sta)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+	struct ieee80211_sta *same_addr_sta;
 
 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
@@ -810,13 +811,18 @@ static int sta_info_insert_check(struct sta_info *sta)
 		    !is_valid_ether_addr(sta->sta.addr)))
 		return -EINVAL;
 
+	if (!ieee80211_hw_check(&sdata->local->hw, NEEDS_UNIQUE_STA_ADDR))
+		return 0;
+
 	/* The RCU read lock is required by rhashtable due to
 	 * asynchronous resize/rehash.  We also require the mutex
 	 * for correctness.
 	 */
 	rcu_read_lock();
-	if (ieee80211_hw_check(&sdata->local->hw, NEEDS_UNIQUE_STA_ADDR) &&
-	    ieee80211_find_sta_by_ifaddr(&sdata->local->hw, sta->addr, NULL)) {
+	same_addr_sta = ieee80211_find_sta_by_ifaddr(&sdata->local->hw,
+						     sta->addr, NULL);
+	/* For NAN, a peer can re-use */
+	if (same_addr_sta && same_addr_sta != rcu_access_pointer(sta->sta.nmi)) {
 		rcu_read_unlock();
 		return -ENOTUNIQ;
 	}
@@ -1294,6 +1300,17 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
 
 	lockdep_assert_wiphy(local->hw.wiphy);
 
+	if (sdata->vif.type == NL80211_IFTYPE_NAN) {
+		struct sta_info *sta_iter, *tmp;
+
+		/* Remove all NDI stations associated with this NMI STA */
+		list_for_each_entry_safe(sta_iter, tmp, &local->sta_list, list) {
+			if (rcu_access_pointer(sta_iter->sta.nmi) != &sta->sta)
+				continue;
+			sta_info_destroy_addr(sta_iter->sdata, sta_iter->addr);
+		}
+	}
+
 	/*
 	 * Before removing the station from the driver and
 	 * rate control, it might still start new aggregation
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 58ccbea7f6f6..3e5d003bd31f 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -505,7 +505,8 @@ struct ieee80211_fragment_cache {
  * @status_stats.ack_signal_filled: last ACK signal validity
  * @status_stats.avg_ack_signal: average ACK signal
  * @cur_max_bandwidth: maximum bandwidth to use for TX to the station,
- *	taken from HT/VHT capabilities or VHT operating mode notification
+ *	taken from HT/VHT capabilities or VHT operating mode notification.
+ *	Invalid for NAN since that is operating on multiple bands.
  * @rx_omi_bw_rx: RX OMI bandwidth restriction to apply for RX
  * @rx_omi_bw_tx: RX OMI bandwidth restriction to apply for TX
  * @rx_omi_bw_staging: RX OMI bandwidth restriction to apply later
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 925a09246ad9..a352f73a7ec4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1782,6 +1782,7 @@ static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_sub_if_data *ndi_sdata;
+	struct sta_info *sta;
 	int res;
 
 	res = drv_start_nan(local, sdata, &sdata->u.nan.conf);
@@ -1802,6 +1803,42 @@ static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)
 		}
 	}
 
+	/* Add NMI stations (stations on the NAN interface) */
+	list_for_each_entry(sta, &local->sta_list, list) {
+		enum ieee80211_sta_state state;
+
+		if (!sta->uploaded || sta->sdata != sdata)
+			continue;
+
+		for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state;
+		     state++) {
+			res = drv_sta_state(local, sdata, sta, state,
+					    state + 1);
+			if (WARN_ON(res))
+				return res;
+		}
+	}
+
+	/* Add NDI stations (stations on NAN_DATA interfaces) */
+	list_for_each_entry(sta, &local->sta_list, list) {
+		enum ieee80211_sta_state state;
+
+		if (!sta->uploaded ||
+		    sta->sdata->vif.type != NL80211_IFTYPE_NAN_DATA)
+			continue;
+
+		if (WARN_ON(!sta->sta.nmi))
+			continue;
+
+		for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state;
+		     state++) {
+			res = drv_sta_state(local, sta->sdata, sta, state,
+					    state + 1);
+			if (WARN_ON(res))
+				return res;
+		}
+	}
+
 	return 0;
 }
 
@@ -2060,6 +2097,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 		case NL80211_IFTYPE_AP_VLAN:
 		case NL80211_IFTYPE_MONITOR:
 			break;
+		case NL80211_IFTYPE_NAN:
+		case NL80211_IFTYPE_NAN_DATA:
+			/* NAN stations are handled later */
+			break;
 		case NL80211_IFTYPE_ADHOC:
 			if (sdata->vif.cfg.ibss_joined)
 				WARN_ON(drv_join_ibss(local, sdata));
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index a6570781740a..f3bb5a561a38 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -133,6 +133,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 	if (!vht_cap_ie || !own_vht_cap->vht_supported)
 		return;
 
+	/* NDI station are using the capabilities from the NMI station */
+	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_NAN_DATA))
+		return;
+
 	if (sband) {
 		/* Allow VHT if at least one channel on the sband supports 80 MHz */
 		bool have_80mhz = false;
@@ -320,7 +324,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 				IEEE80211_STA_RX_BW_160;
 	}
 
-	link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
+	if (sdata->vif.type != NL80211_IFTYPE_NAN)
+		link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
 
 	/*
 	 * Work around the Cisco 9115 FW 17.3 bug by taking the min of
@@ -373,6 +378,10 @@ __ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta,
 		} else {
 			struct ieee80211_bss_conf *link_conf;
 
+			if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_NAN_DATA ||
+					 sdata->vif.type == NL80211_IFTYPE_NAN))
+				return IEEE80211_STA_RX_BW_20;
+
 			rcu_read_lock();
 			link_conf = rcu_dereference(sdata->vif.link_conf[link_id]);
 			band = link_conf->chanreq.oper.chan->band;
@@ -518,6 +527,11 @@ _ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta,
 	} else {
 		struct ieee80211_bss_conf *link_conf;
 
+		/* NAN operates on multiple channels so a chandef must be given */
+		if (WARN_ON_ONCE(sta->sdata->vif.type == NL80211_IFTYPE_NAN ||
+				 sta->sdata->vif.type == NL80211_IFTYPE_NAN_DATA))
+			return IEEE80211_STA_RX_BW_20;
+
 		rcu_read_lock();
 		link_conf = rcu_dereference(sta->sdata->vif.link_conf[link_sta->link_id]);
 		if (WARN_ON_ONCE(!link_conf)) {
-- 
2.34.1


  parent reply	other threads:[~2026-03-25 21:16 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-25 21:15 [PATCH wireless-next 00/15] wifi: mac80211: add NAN support Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 01/15] wifi: mac80211: add a TXQ for management frames on NAN devices Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 02/15] wifi: ieee80211: add more NAN definitions Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 03/15] wifi: mac80211: export ieee80211_calculate_rx_timestamp Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 04/15] wifi: mac80211: run NAN DE code only when appropriate Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 05/15] wifi: mac80211: add NAN local schedule support Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 06/15] wifi: mac80211: support open and close for NAN_DATA interfaces Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 07/15] wifi: mac80211: handle reconfig for NAN DATA interfaces Miri Korenblit
2026-03-25 21:15 ` Miri Korenblit [this message]
2026-03-25 21:15 ` [PATCH wireless-next 09/15] wifi: mac80211: add NAN peer schedule support Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 10/15] wifi: mac80211: update NAN data path state on schedule changes Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 11/15] wifi: mac80211: add support for TX over NAN_DATA interfaces Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 12/15] wifi: mac80211: Accept frames on NAN DATA interfaces Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 13/15] wifi: mac80211: allow block ack agreements in NAN Data Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 14/15] wifi: mac80211: report and drop spurious NAN Data frames Miri Korenblit
2026-03-25 21:15 ` [PATCH wireless-next 15/15] wifi: mac80211: allow add_key on NAN interfaces Miri Korenblit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260325230443.32c5644ec4be.I7a7bd6e8e751cab49c329419485839afd209cfc6@changeid \
    --to=miriam.rachel.korenblit@intel.com \
    --cc=johannes.berg@intel.com \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox