mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
wifi: mac80211: support NAN stations
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> Link: https://patch.msgid.link/20260326121156.9fdd37b8e755.I7a7bd6e8e751cab49c329419485839afd209cfc6@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
e43ec60220
commit
27e9b326b6
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user