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

mac80211: add VHT support for IBSS

Add VHT support for IBSS. Drivers could activate
this feature by setting NL80211_EXT_FEATURE_VHT_IBSS
flag.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Janusz.Dziedzic@tieto.com and committed by
Johannes Berg
abcff6ef 76bed0f4

+80 -11
-2
net/mac80211/ht.c
··· 252 252 break; 253 253 } 254 254 255 - if (bw != sta->sta.bandwidth) 256 - changed = true; 257 255 sta->sta.bandwidth = bw; 258 256 259 257 sta->cur_max_bandwidth =
+40 -9
net/mac80211/ibss.c
··· 188 188 */ 189 189 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, 190 190 chandef, 0); 191 + 192 + /* add VHT capability and information IEs */ 193 + if (chandef->width != NL80211_CHAN_WIDTH_20 && 194 + chandef->width != NL80211_CHAN_WIDTH_40 && 195 + sband->vht_cap.vht_supported) { 196 + pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, 197 + sband->vht_cap.cap); 198 + pos = ieee80211_ie_build_vht_oper(pos, &sband->vht_cap, 199 + chandef); 200 + } 191 201 } 192 202 193 203 if (local->hw.queues >= IEEE80211_NUM_ACS) ··· 424 414 cfg80211_chandef_create(&chandef, cbss->channel, 425 415 NL80211_CHAN_WIDTH_20_NOHT); 426 416 chandef.width = sdata->u.ibss.chandef.width; 417 + break; 418 + case NL80211_CHAN_WIDTH_80: 419 + case NL80211_CHAN_WIDTH_160: 420 + chandef = sdata->u.ibss.chandef; 421 + chandef.chan = cbss->channel; 427 422 break; 428 423 default: 429 424 /* fall back to 20 MHz for unsupported modes */ ··· 1041 1026 /* we both use HT */ 1042 1027 struct ieee80211_ht_cap htcap_ie; 1043 1028 struct cfg80211_chan_def chandef; 1029 + enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth; 1044 1030 1045 1031 ieee80211_ht_oper_to_chandef(channel, 1046 1032 elems->ht_operation, 1047 1033 &chandef); 1048 1034 1049 1035 memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie)); 1050 - 1051 - /* 1052 - * fall back to HT20 if we don't use or use 1053 - * the other extension channel 1054 - */ 1055 - if (chandef.center_freq1 != sdata->u.ibss.chandef.center_freq1) 1056 - htcap_ie.cap_info &= 1057 - cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40); 1058 - 1059 1036 rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, 1060 1037 &htcap_ie, 1061 1038 sta); 1039 + 1040 + if (elems->vht_operation && elems->vht_cap_elem && 1041 + sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20 && 1042 + sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_40) { 1043 + /* we both use VHT */ 1044 + struct ieee80211_vht_cap cap_ie; 1045 + struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap; 1046 + 1047 + ieee80211_vht_oper_to_chandef(channel, 1048 + elems->vht_operation, 1049 + &chandef); 1050 + memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); 1051 + ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, 1052 + &cap_ie, sta); 1053 + if (memcmp(&cap, &sta->sta.vht_cap, sizeof(cap))) 1054 + rates_updated |= true; 1055 + } 1056 + 1057 + if (bw != sta->sta.bandwidth) 1058 + rates_updated |= true; 1059 + 1060 + if (!cfg80211_chandef_compatible(&sdata->u.ibss.chandef, 1061 + &chandef)) 1062 + WARN_ON_ONCE(1); 1062 1063 } 1063 1064 1064 1065 if (sta && rates_updated) {
+3
net/mac80211/ieee80211_i.h
··· 1960 1960 void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, 1961 1961 const struct ieee80211_ht_operation *ht_oper, 1962 1962 struct cfg80211_chan_def *chandef); 1963 + void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan, 1964 + const struct ieee80211_vht_operation *oper, 1965 + struct cfg80211_chan_def *chandef); 1963 1966 u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); 1964 1967 1965 1968 int __must_check
+4
net/mac80211/mesh_plink.c
··· 382 382 enum ieee80211_band band = ieee80211_get_sdata_band(sdata); 383 383 struct ieee80211_supported_band *sband; 384 384 u32 rates, basic_rates = 0, changed = 0; 385 + enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth; 385 386 386 387 sband = local->hw.wiphy->bands[band]; 387 388 rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates); ··· 400 399 401 400 if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, 402 401 elems->ht_cap_elem, sta)) 402 + changed |= IEEE80211_RC_BW_CHANGED; 403 + 404 + if (bw != sta->sta.bandwidth) 403 405 changed |= IEEE80211_RC_BW_CHANGED; 404 406 405 407 /* HT peer is operating 20MHz-only */
+33
net/mac80211/util.c
··· 2440 2440 cfg80211_chandef_create(chandef, control_chan, channel_type); 2441 2441 } 2442 2442 2443 + void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan, 2444 + const struct ieee80211_vht_operation *oper, 2445 + struct cfg80211_chan_def *chandef) 2446 + { 2447 + if (!oper) 2448 + return; 2449 + 2450 + chandef->chan = control_chan; 2451 + 2452 + switch (oper->chan_width) { 2453 + case IEEE80211_VHT_CHANWIDTH_USE_HT: 2454 + break; 2455 + case IEEE80211_VHT_CHANWIDTH_80MHZ: 2456 + chandef->width = NL80211_CHAN_WIDTH_80; 2457 + break; 2458 + case IEEE80211_VHT_CHANWIDTH_160MHZ: 2459 + chandef->width = NL80211_CHAN_WIDTH_160; 2460 + break; 2461 + case IEEE80211_VHT_CHANWIDTH_80P80MHZ: 2462 + chandef->width = NL80211_CHAN_WIDTH_80P80; 2463 + break; 2464 + default: 2465 + break; 2466 + } 2467 + 2468 + chandef->center_freq1 = 2469 + ieee80211_channel_to_frequency(oper->center_freq_seg1_idx, 2470 + control_chan->band); 2471 + chandef->center_freq2 = 2472 + ieee80211_channel_to_frequency(oper->center_freq_seg2_idx, 2473 + control_chan->band); 2474 + } 2475 + 2443 2476 int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, 2444 2477 const struct ieee80211_supported_band *sband, 2445 2478 const u8 *srates, int srates_len, u32 *rates)