aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJanusz.Dziedzic@tieto.com <Janusz.Dziedzic@tieto.com>2015-03-20 01:37:01 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-03-30 04:48:26 -0400
commitabcff6ef01f9ffa6958e50457574132f8f786308 (patch)
tree54c40e220974486318c8b5c4e3c1d0d45a4333ba /net/mac80211
parent76bed0f43b27d37cbe5fe9f3c27362db59451dea (diff)
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ht.c2
-rw-r--r--net/mac80211/ibss.c49
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/mesh_plink.c4
-rw-r--r--net/mac80211/util.c33
5 files changed, 80 insertions, 11 deletions
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index ff630be2ca75..7a76ce639d58 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -252,8 +252,6 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
252 break; 252 break;
253 } 253 }
254 254
255 if (bw != sta->sta.bandwidth)
256 changed = true;
257 sta->sta.bandwidth = bw; 255 sta->sta.bandwidth = bw;
258 256
259 sta->cur_max_bandwidth = 257 sta->cur_max_bandwidth =
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 8f8391e008ed..52d629d5e797 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -188,6 +188,16 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
188 */ 188 */
189 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, 189 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
190 chandef, 0); 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 if (local->hw.queues >= IEEE80211_NUM_ACS) 203 if (local->hw.queues >= IEEE80211_NUM_ACS)
@@ -415,6 +425,11 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
415 NL80211_CHAN_WIDTH_20_NOHT); 425 NL80211_CHAN_WIDTH_20_NOHT);
416 chandef.width = sdata->u.ibss.chandef.width; 426 chandef.width = sdata->u.ibss.chandef.width;
417 break; 427 break;
428 case NL80211_CHAN_WIDTH_80:
429 case NL80211_CHAN_WIDTH_160:
430 chandef = sdata->u.ibss.chandef;
431 chandef.chan = cbss->channel;
432 break;
418 default: 433 default:
419 /* fall back to 20 MHz for unsupported modes */ 434 /* fall back to 20 MHz for unsupported modes */
420 cfg80211_chandef_create(&chandef, cbss->channel, 435 cfg80211_chandef_create(&chandef, cbss->channel,
@@ -1026,24 +1041,40 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
1026 /* we both use HT */ 1041 /* we both use HT */
1027 struct ieee80211_ht_cap htcap_ie; 1042 struct ieee80211_ht_cap htcap_ie;
1028 struct cfg80211_chan_def chandef; 1043 struct cfg80211_chan_def chandef;
1044 enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth;
1029 1045
1030 ieee80211_ht_oper_to_chandef(channel, 1046 ieee80211_ht_oper_to_chandef(channel,
1031 elems->ht_operation, 1047 elems->ht_operation,
1032 &chandef); 1048 &chandef);
1033 1049
1034 memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie)); 1050 memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
1035
1036 /*
1037 * fall back to HT20 if we don't use or use
1038 * the other extension channel
1039 */
1040 if (chandef.center_freq1 != sdata->u.ibss.chandef.center_freq1)
1041 htcap_ie.cap_info &=
1042 cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40);
1043
1044 rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, 1051 rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
1045 &htcap_ie, 1052 &htcap_ie,
1046 sta); 1053 sta);
1054
1055 if (elems->vht_operation && elems->vht_cap_elem &&
1056 sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20 &&
1057 sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_40) {
1058 /* we both use VHT */
1059 struct ieee80211_vht_cap cap_ie;
1060 struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap;
1061
1062 ieee80211_vht_oper_to_chandef(channel,
1063 elems->vht_operation,
1064 &chandef);
1065 memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
1066 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
1067 &cap_ie, sta);
1068 if (memcmp(&cap, &sta->sta.vht_cap, sizeof(cap)))
1069 rates_updated |= true;
1070 }
1071
1072 if (bw != sta->sta.bandwidth)
1073 rates_updated |= true;
1074
1075 if (!cfg80211_chandef_compatible(&sdata->u.ibss.chandef,
1076 &chandef))
1077 WARN_ON_ONCE(1);
1047 } 1078 }
1048 1079
1049 if (sta && rates_updated) { 1080 if (sta && rates_updated) {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 3331c62b4433..81340abb3876 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1960,6 +1960,9 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
1960void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, 1960void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
1961 const struct ieee80211_ht_operation *ht_oper, 1961 const struct ieee80211_ht_operation *ht_oper,
1962 struct cfg80211_chan_def *chandef); 1962 struct cfg80211_chan_def *chandef);
1963void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan,
1964 const struct ieee80211_vht_operation *oper,
1965 struct cfg80211_chan_def *chandef);
1963u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); 1966u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c);
1964 1967
1965int __must_check 1968int __must_check
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 8465c055a371..60d737f144e3 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -382,6 +382,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
382 enum ieee80211_band band = ieee80211_get_sdata_band(sdata); 382 enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
383 struct ieee80211_supported_band *sband; 383 struct ieee80211_supported_band *sband;
384 u32 rates, basic_rates = 0, changed = 0; 384 u32 rates, basic_rates = 0, changed = 0;
385 enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth;
385 386
386 sband = local->hw.wiphy->bands[band]; 387 sband = local->hw.wiphy->bands[band];
387 rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates); 388 rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates);
@@ -401,6 +402,9 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
401 elems->ht_cap_elem, sta)) 402 elems->ht_cap_elem, sta))
402 changed |= IEEE80211_RC_BW_CHANGED; 403 changed |= IEEE80211_RC_BW_CHANGED;
403 404
405 if (bw != sta->sta.bandwidth)
406 changed |= IEEE80211_RC_BW_CHANGED;
407
404 /* HT peer is operating 20MHz-only */ 408 /* HT peer is operating 20MHz-only */
405 if (elems->ht_operation && 409 if (elems->ht_operation &&
406 !(elems->ht_operation->ht_param & 410 !(elems->ht_operation->ht_param &
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index e664b28821a2..256647cb1d24 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2440,6 +2440,39 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
2440 cfg80211_chandef_create(chandef, control_chan, channel_type); 2440 cfg80211_chandef_create(chandef, control_chan, channel_type);
2441} 2441}
2442 2442
2443void 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
2443int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, 2476int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
2444 const struct ieee80211_supported_band *sband, 2477 const struct ieee80211_supported_band *sband,
2445 const u8 *srates, int srates_len, u32 *rates) 2478 const u8 *srates, int srates_len, u32 *rates)