diff options
Diffstat (limited to 'net/mac80211/tdls.c')
| -rw-r--r-- | net/mac80211/tdls.c | 95 |
1 files changed, 55 insertions, 40 deletions
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index dbbfe2d6842f..f663d28d9209 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -6,7 +6,7 @@ * Copyright 2014, Intel Corporation * Copyright 2014 Intel Mobile Communications GmbH * Copyright 2015 - 2016 Intel Deutschland GmbH - * Copyright (C) 2019, 2021-2025 Intel Corporation + * Copyright (C) 2019, 2021-2026 Intel Corporation */ #include <linux/ieee80211.h> @@ -311,17 +311,21 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata, /* IEEE802.11ac-2013 Table E-4 */ static const u16 centers_80mhz[] = { 5210, 5290, 5530, 5610, 5690, 5775 }; struct cfg80211_chan_def uc = sta->tdls_chandef; - enum nl80211_chan_width max_width = - ieee80211_sta_cap_chan_bw(&sta->deflink); + enum nl80211_chan_width max_width; int i; - /* only support upgrading non-narrow channels up to 80Mhz */ - if (max_width == NL80211_CHAN_WIDTH_5 || - max_width == NL80211_CHAN_WIDTH_10) - return; - - if (max_width > NL80211_CHAN_WIDTH_80) + switch (ieee80211_sta_current_bw(&sta->deflink, &uc, + IEEE80211_STA_BW_RX_FROM_STA)) { + case IEEE80211_STA_RX_BW_20: + max_width = NL80211_CHAN_WIDTH_20; + break; + case IEEE80211_STA_RX_BW_40: + max_width = NL80211_CHAN_WIDTH_40; + break; + default: /* 80 or higher, only support upgrade to 80 */ max_width = NL80211_CHAN_WIDTH_80; + break; + } if (uc.width >= max_width) return; @@ -879,28 +883,23 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_mgmt *mgmt; - mgmt = skb_put_zero(skb, 24); + if (action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES) + return -EINVAL; + + mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(tdls_discover_resp)); memcpy(mgmt->da, peer, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, link->u.mgd.bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); - switch (action_code) { - case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); - mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; - mgmt->u.action.u.tdls_discover_resp.action_code = - WLAN_PUB_ACTION_TDLS_DISCOVER_RES; - mgmt->u.action.u.tdls_discover_resp.dialog_token = - dialog_token; - mgmt->u.action.u.tdls_discover_resp.capability = - cpu_to_le16(ieee80211_get_tdls_sta_capab(link, - status_code)); - break; - default: - return -EINVAL; - } + mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; + mgmt->u.action.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES; + + mgmt->u.action.tdls_discover_resp.dialog_token = dialog_token; + mgmt->u.action.tdls_discover_resp.capability = + cpu_to_le16(ieee80211_get_tdls_sta_capab(link, + status_code)); return 0; } @@ -1122,7 +1121,7 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, /* disable bottom halves when entering the Tx path */ local_bh_disable(); __ieee80211_subif_start_xmit(skb, dev, flags, - IEEE80211_TX_CTRL_MLO_LINK_UNSPEC, NULL); + IEEE80211_TX_CTRL_MLO_LINK_UNSPEC, 0); local_bh_enable(); return ret; @@ -1143,6 +1142,7 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_local *local = sdata->local; enum ieee80211_smps_mode smps_mode = sdata->deflink.u.mgd.driver_smps_mode; + struct sta_info *sta; int ret; /* don't support setup with forced SMPS mode that's not off */ @@ -1169,14 +1169,10 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, * Allow error packets to be sent - sometimes we don't even add a STA * before failing the setup. */ - if (status_code == 0) { - rcu_read_lock(); - if (!sta_info_get(sdata, peer)) { - rcu_read_unlock(); - ret = -ENOLINK; - goto out_unlock; - } - rcu_read_unlock(); + sta = sta_info_get(sdata, peer); + if ((status_code == 0 && !sta) || (sta && !sta->sta.tdls)) { + ret = -ENOLINK; + goto out_unlock; } ieee80211_flush_queues(local, sdata, false); @@ -1285,6 +1281,24 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, peer_capability, initiator, extra_ies, extra_ies_len); break; + case WLAN_TDLS_SETUP_CONFIRM: { + struct sta_info *sta; + + sta = sta_info_get(sdata, peer); + if (!sta || !sta->sta.tdls) { + ret = -ENOLINK; + break; + } + + ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, + link_id, action_code, + dialog_token, + status_code, + peer_capability, + initiator, extra_ies, + extra_ies_len, 0, NULL); + break; + } case WLAN_TDLS_DISCOVERY_REQUEST: /* * Protect the discovery so we can hear the TDLS discovery @@ -1293,7 +1307,6 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, */ drv_mgd_protect_tdls_discover(sdata->local, sdata, link_id); fallthrough; - case WLAN_TDLS_SETUP_CONFIRM: case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: /* no special handling */ ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, @@ -1339,7 +1352,9 @@ static void iee80211_tdls_recalc_chanctx(struct ieee80211_sub_if_data *sdata, enum ieee80211_sta_rx_bandwidth bw; bw = ieee80211_chan_width_to_rx_bw(conf->def.width); - bw = min(bw, ieee80211_sta_cap_rx_bw(&sta->deflink)); + bw = min(bw, ieee80211_sta_current_bw(&sta->deflink, + &conf->def, + IEEE80211_STA_BW_RX_FROM_STA)); if (bw != sta->sta.deflink.bandwidth) { sta->sta.deflink.bandwidth = bw; rate_control_rate_update(local, sband, @@ -1441,6 +1456,10 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, */ tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); + sta = sta_info_get(sdata, peer); + if (!sta || !sta->sta.tdls) + return -ENOLINK; + switch (oper) { case NL80211_TDLS_ENABLE_LINK: if (sdata->vif.bss_conf.csa_active) { @@ -1448,10 +1467,6 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, return -EBUSY; } - sta = sta_info_get(sdata, peer); - if (!sta) - return -ENOLINK; - iee80211_tdls_recalc_chanctx(sdata, sta); iee80211_tdls_recalc_ht_protection(sdata, sta); |
