Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: define TDLS wider BW support bits

Allow a device to specify support for the TDLS wider-bandwidth feature.
Indicate this support during TDLS setup in the ext-capab IE and set an
appropriate station flag when our TDLS peer supports it.
This feature gives TDLS peers the ability to use a wider channel than
the base width of the BSS. For instance VHT capable TDLS peers connected
on a 20MHz channel can extend the channel to 80MHz, if regulatory
considerations allow it.

Do not cap the bandwidth of such stations by the current BSS channel width
in mac80211.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Arik Nemtsov and committed by
Johannes Berg
b98fb44f 7584f88f

+33 -7
+4
include/net/mac80211.h
··· 1887 1887 * @IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands 1888 1888 * in one command, mac80211 doesn't have to run separate scans per band. 1889 1889 * 1890 + * @IEEE80211_HW_TDLS_WIDER_BW: The device/driver supports wider bandwidth 1891 + * than then BSS bandwidth for a TDLS link on the base channel. 1892 + * 1890 1893 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays 1891 1894 */ 1892 1895 enum ieee80211_hw_flags { ··· 1922 1919 IEEE80211_HW_CHANCTX_STA_CSA, 1923 1920 IEEE80211_HW_SUPPORTS_CLONED_SKBS, 1924 1921 IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS, 1922 + IEEE80211_HW_TDLS_WIDER_BW, 1925 1923 1926 1924 /* keep last, obviously */ 1927 1925 NUM_IEEE80211_HW_FLAGS
+6
net/mac80211/cfg.c
··· 1155 1155 params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) 1156 1156 set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH); 1157 1157 1158 + if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && 1159 + ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) && 1160 + params->ext_capab_len >= 8 && 1161 + params->ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) 1162 + set_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW); 1163 + 1158 1164 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) { 1159 1165 sta->sta.uapsd_queues = params->uapsd_queues; 1160 1166 sta->sta.max_sp = params->max_sp;
+1
net/mac80211/debugfs.c
··· 122 122 FLAG(CHANCTX_STA_CSA), 123 123 FLAG(SUPPORTS_CLONED_SKBS), 124 124 FLAG(SINGLE_SCAN_ON_ALL_BANDS), 125 + FLAG(TDLS_WIDER_BW), 125 126 126 127 /* keep last for the build bug below */ 127 128 (void *)0x1
+3
net/mac80211/sta_info.h
··· 53 53 * @WLAN_STA_TDLS_CHAN_SWITCH: This TDLS peer supports TDLS channel-switching 54 54 * @WLAN_STA_TDLS_OFF_CHANNEL: The local STA is currently off-channel with this 55 55 * TDLS peer 56 + * @WLAN_STA_TDLS_WIDER_BW: This TDLS peer supports working on a wider bw on 57 + * the BSS base channel. 56 58 * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was 57 59 * keeping station in power-save mode, reply when the driver 58 60 * unblocks the station. ··· 86 84 WLAN_STA_TDLS_INITIATOR, 87 85 WLAN_STA_TDLS_CHAN_SWITCH, 88 86 WLAN_STA_TDLS_OFF_CHANNEL, 87 + WLAN_STA_TDLS_WIDER_BW, 89 88 WLAN_STA_UAPSD, 90 89 WLAN_STA_SP, 91 90 WLAN_STA_4ADDR_EVENT,
+13 -5
net/mac80211/tdls.c
··· 35 35 mutex_unlock(&local->mtx); 36 36 } 37 37 38 - static void ieee80211_tdls_add_ext_capab(struct ieee80211_local *local, 38 + static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata, 39 39 struct sk_buff *skb) 40 40 { 41 - u8 *pos = (void *)skb_put(skb, 7); 41 + struct ieee80211_local *local = sdata->local; 42 42 bool chan_switch = local->hw.wiphy->features & 43 43 NL80211_FEATURE_TDLS_CHANNEL_SWITCH; 44 + bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW); 45 + enum ieee80211_band band = ieee80211_get_sdata_band(sdata); 46 + struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; 47 + bool vht = sband && sband->vht_cap.vht_supported; 48 + u8 *pos = (void *)skb_put(skb, 10); 44 49 45 50 *pos++ = WLAN_EID_EXT_CAPABILITY; 46 - *pos++ = 5; /* len */ 51 + *pos++ = 8; /* len */ 47 52 *pos++ = 0x0; 48 53 *pos++ = 0x0; 49 54 *pos++ = 0x0; 50 55 *pos++ = chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0; 51 56 *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; 57 + *pos++ = 0; 58 + *pos++ = 0; 59 + *pos++ = (vht && wider_band) ? WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED : 0; 52 60 } 53 61 54 62 static u8 ··· 328 320 offset = noffset; 329 321 } 330 322 331 - ieee80211_tdls_add_ext_capab(local, skb); 323 + ieee80211_tdls_add_ext_capab(sdata, skb); 332 324 333 325 /* add the QoS element if we support it */ 334 326 if (local->hw.queues >= IEEE80211_NUM_ACS && ··· 792 784 max(sizeof(struct ieee80211_mgmt), 793 785 sizeof(struct ieee80211_tdls_data)) + 794 786 50 + /* supported rates */ 795 - 7 + /* ext capab */ 787 + 10 + /* ext capab */ 796 788 26 + /* max(WMM-info, WMM-param) */ 797 789 2 + max(sizeof(struct ieee80211_ht_cap), 798 790 sizeof(struct ieee80211_ht_operation)) +
+6 -2
net/mac80211/vht.c
··· 308 308 { 309 309 struct ieee80211_sub_if_data *sdata = sta->sdata; 310 310 enum ieee80211_sta_rx_bandwidth bw; 311 + enum nl80211_chan_width bss_width = sdata->vif.bss_conf.chandef.width; 311 312 312 - bw = ieee80211_chan_width_to_rx_bw(sdata->vif.bss_conf.chandef.width); 313 - bw = min(bw, ieee80211_sta_cap_rx_bw(sta)); 313 + bw = ieee80211_sta_cap_rx_bw(sta); 314 314 bw = min(bw, sta->cur_max_bandwidth); 315 + 316 + /* do not cap the BW of TDLS WIDER_BW peers by the bss */ 317 + if (!test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW)) 318 + bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width)); 315 319 316 320 return bw; 317 321 }