diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 45 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 81 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 7 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 95 | ||||
-rw-r--r-- | net/mac80211/rate.c | 46 | ||||
-rw-r--r-- | net/mac80211/rx.c | 7 | ||||
-rw-r--r-- | net/mac80211/scan.c | 27 | ||||
-rw-r--r-- | net/mac80211/status.c | 18 | ||||
-rw-r--r-- | net/mac80211/tx.c | 21 | ||||
-rw-r--r-- | net/mac80211/util.c | 159 |
12 files changed, 352 insertions, 159 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8184d121ff09..b82fff6c0b30 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -395,9 +395,13 @@ void sta_set_rate_info_tx(struct sta_info *sta, | |||
395 | rinfo->nss = ieee80211_rate_get_vht_nss(rate); | 395 | rinfo->nss = ieee80211_rate_get_vht_nss(rate); |
396 | } else { | 396 | } else { |
397 | struct ieee80211_supported_band *sband; | 397 | struct ieee80211_supported_band *sband; |
398 | int shift = ieee80211_vif_get_shift(&sta->sdata->vif); | ||
399 | u16 brate; | ||
400 | |||
398 | sband = sta->local->hw.wiphy->bands[ | 401 | sband = sta->local->hw.wiphy->bands[ |
399 | ieee80211_get_sdata_band(sta->sdata)]; | 402 | ieee80211_get_sdata_band(sta->sdata)]; |
400 | rinfo->legacy = sband->bitrates[rate->idx].bitrate; | 403 | brate = sband->bitrates[rate->idx].bitrate; |
404 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); | ||
401 | } | 405 | } |
402 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | 406 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) |
403 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 407 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
@@ -422,11 +426,13 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | |||
422 | rinfo->mcs = sta->last_rx_rate_idx; | 426 | rinfo->mcs = sta->last_rx_rate_idx; |
423 | } else { | 427 | } else { |
424 | struct ieee80211_supported_band *sband; | 428 | struct ieee80211_supported_band *sband; |
429 | int shift = ieee80211_vif_get_shift(&sta->sdata->vif); | ||
430 | u16 brate; | ||
425 | 431 | ||
426 | sband = sta->local->hw.wiphy->bands[ | 432 | sband = sta->local->hw.wiphy->bands[ |
427 | ieee80211_get_sdata_band(sta->sdata)]; | 433 | ieee80211_get_sdata_band(sta->sdata)]; |
428 | rinfo->legacy = | 434 | brate = sband->bitrates[sta->last_rx_rate_idx].bitrate; |
429 | sband->bitrates[sta->last_rx_rate_idx].bitrate; | 435 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); |
430 | } | 436 | } |
431 | 437 | ||
432 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) | 438 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) |
@@ -1190,8 +1196,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1190 | struct station_parameters *params) | 1196 | struct station_parameters *params) |
1191 | { | 1197 | { |
1192 | int ret = 0; | 1198 | int ret = 0; |
1193 | u32 rates; | ||
1194 | int i, j; | ||
1195 | struct ieee80211_supported_band *sband; | 1199 | struct ieee80211_supported_band *sband; |
1196 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1200 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1197 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 1201 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
@@ -1284,16 +1288,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1284 | sta->listen_interval = params->listen_interval; | 1288 | sta->listen_interval = params->listen_interval; |
1285 | 1289 | ||
1286 | if (params->supported_rates) { | 1290 | if (params->supported_rates) { |
1287 | rates = 0; | 1291 | ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef, |
1288 | 1292 | sband, params->supported_rates, | |
1289 | for (i = 0; i < params->supported_rates_len; i++) { | 1293 | params->supported_rates_len, |
1290 | int rate = (params->supported_rates[i] & 0x7f) * 5; | 1294 | &sta->sta.supp_rates[band]); |
1291 | for (j = 0; j < sband->n_bitrates; j++) { | ||
1292 | if (sband->bitrates[j].bitrate == rate) | ||
1293 | rates |= BIT(j); | ||
1294 | } | ||
1295 | } | ||
1296 | sta->sta.supp_rates[band] = rates; | ||
1297 | } | 1295 | } |
1298 | 1296 | ||
1299 | if (params->ht_capa) | 1297 | if (params->ht_capa) |
@@ -1956,18 +1954,11 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1956 | } | 1954 | } |
1957 | 1955 | ||
1958 | if (params->basic_rates) { | 1956 | if (params->basic_rates) { |
1959 | int i, j; | 1957 | ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef, |
1960 | u32 rates = 0; | 1958 | wiphy->bands[band], |
1961 | struct ieee80211_supported_band *sband = wiphy->bands[band]; | 1959 | params->basic_rates, |
1962 | 1960 | params->basic_rates_len, | |
1963 | for (i = 0; i < params->basic_rates_len; i++) { | 1961 | &sdata->vif.bss_conf.basic_rates); |
1964 | int rate = (params->basic_rates[i] & 0x7f) * 5; | ||
1965 | for (j = 0; j < sband->n_bitrates; j++) { | ||
1966 | if (sband->bitrates[j].bitrate == rate) | ||
1967 | rates |= BIT(j); | ||
1968 | } | ||
1969 | } | ||
1970 | sdata->vif.bss_conf.basic_rates = rates; | ||
1971 | changed |= BSS_CHANGED_BASIC_RATES; | 1962 | changed |= BSS_CHANGED_BASIC_RATES; |
1972 | } | 1963 | } |
1973 | 1964 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 7f290a8562ef..272a3b37615c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -43,16 +43,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
43 | { | 43 | { |
44 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 44 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
45 | struct ieee80211_local *local = sdata->local; | 45 | struct ieee80211_local *local = sdata->local; |
46 | int rates, i; | 46 | int rates_n = 0, i, ri; |
47 | struct ieee80211_mgmt *mgmt; | 47 | struct ieee80211_mgmt *mgmt; |
48 | u8 *pos; | 48 | u8 *pos; |
49 | struct ieee80211_supported_band *sband; | 49 | struct ieee80211_supported_band *sband; |
50 | struct cfg80211_bss *bss; | 50 | struct cfg80211_bss *bss; |
51 | u32 bss_change; | 51 | u32 bss_change, rate_flags, rates = 0, rates_added = 0; |
52 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 52 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
53 | struct cfg80211_chan_def chandef; | 53 | struct cfg80211_chan_def chandef; |
54 | struct beacon_data *presp; | 54 | struct beacon_data *presp; |
55 | int frame_len; | 55 | int frame_len; |
56 | int shift; | ||
56 | 57 | ||
57 | sdata_assert_lock(sdata); | 58 | sdata_assert_lock(sdata); |
58 | 59 | ||
@@ -99,6 +100,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
99 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 100 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
100 | 101 | ||
101 | sband = local->hw.wiphy->bands[chan->band]; | 102 | sband = local->hw.wiphy->bands[chan->band]; |
103 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
102 | 104 | ||
103 | /* Build IBSS probe response */ | 105 | /* Build IBSS probe response */ |
104 | frame_len = sizeof(struct ieee80211_hdr_3addr) + | 106 | frame_len = sizeof(struct ieee80211_hdr_3addr) + |
@@ -134,15 +136,29 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
134 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); | 136 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); |
135 | pos += ifibss->ssid_len; | 137 | pos += ifibss->ssid_len; |
136 | 138 | ||
137 | rates = min_t(int, 8, sband->n_bitrates); | 139 | rate_flags = ieee80211_chandef_rate_flags(&chandef); |
140 | for (i = 0; i < sband->n_bitrates; i++) { | ||
141 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
142 | continue; | ||
143 | |||
144 | rates |= BIT(i); | ||
145 | rates_n++; | ||
146 | } | ||
147 | |||
138 | *pos++ = WLAN_EID_SUPP_RATES; | 148 | *pos++ = WLAN_EID_SUPP_RATES; |
139 | *pos++ = rates; | 149 | *pos++ = min_t(int, 8, rates_n); |
140 | for (i = 0; i < rates; i++) { | 150 | for (ri = 0; ri < sband->n_bitrates; ri++) { |
141 | int rate = sband->bitrates[i].bitrate; | 151 | int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate, |
152 | 5 * (1 << shift)); | ||
142 | u8 basic = 0; | 153 | u8 basic = 0; |
143 | if (basic_rates & BIT(i)) | 154 | if (!(rates & BIT(ri))) |
155 | continue; | ||
156 | |||
157 | if (basic_rates & BIT(ri)) | ||
144 | basic = 0x80; | 158 | basic = 0x80; |
145 | *pos++ = basic | (u8) (rate / 5); | 159 | *pos++ = basic | (u8) rate; |
160 | if (++rates_added == 8) | ||
161 | break; | ||
146 | } | 162 | } |
147 | 163 | ||
148 | if (sband->band == IEEE80211_BAND_2GHZ) { | 164 | if (sband->band == IEEE80211_BAND_2GHZ) { |
@@ -157,15 +173,20 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
157 | *pos++ = 0; | 173 | *pos++ = 0; |
158 | *pos++ = 0; | 174 | *pos++ = 0; |
159 | 175 | ||
160 | if (sband->n_bitrates > 8) { | 176 | /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */ |
177 | if (rates_n > 8) { | ||
161 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 178 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
162 | *pos++ = sband->n_bitrates - 8; | 179 | *pos++ = rates_n - 8; |
163 | for (i = 8; i < sband->n_bitrates; i++) { | 180 | for (; ri < sband->n_bitrates; ri++) { |
164 | int rate = sband->bitrates[i].bitrate; | 181 | int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate, |
182 | 5 * (1 << shift)); | ||
165 | u8 basic = 0; | 183 | u8 basic = 0; |
166 | if (basic_rates & BIT(i)) | 184 | if (!(rates & BIT(ri))) |
185 | continue; | ||
186 | |||
187 | if (basic_rates & BIT(ri)) | ||
167 | basic = 0x80; | 188 | basic = 0x80; |
168 | *pos++ = basic | (u8) (rate / 5); | 189 | *pos++ = basic | (u8) rate; |
169 | } | 190 | } |
170 | } | 191 | } |
171 | 192 | ||
@@ -244,7 +265,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
244 | sdata->vif.bss_conf.ibss_creator = creator; | 265 | sdata->vif.bss_conf.ibss_creator = creator; |
245 | ieee80211_bss_info_change_notify(sdata, bss_change); | 266 | ieee80211_bss_info_change_notify(sdata, bss_change); |
246 | 267 | ||
247 | ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); | 268 | ieee80211_sta_def_wmm_params(sdata, rates, supp_rates); |
248 | 269 | ||
249 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; | 270 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; |
250 | mod_timer(&ifibss->timer, | 271 | mod_timer(&ifibss->timer, |
@@ -268,6 +289,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
268 | u16 beacon_int = cbss->beacon_interval; | 289 | u16 beacon_int = cbss->beacon_interval; |
269 | const struct cfg80211_bss_ies *ies; | 290 | const struct cfg80211_bss_ies *ies; |
270 | u64 tsf; | 291 | u64 tsf; |
292 | u32 rate_flags; | ||
293 | int shift; | ||
271 | 294 | ||
272 | sdata_assert_lock(sdata); | 295 | sdata_assert_lock(sdata); |
273 | 296 | ||
@@ -275,15 +298,24 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
275 | beacon_int = 10; | 298 | beacon_int = 10; |
276 | 299 | ||
277 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; | 300 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; |
301 | rate_flags = ieee80211_chandef_rate_flags(&sdata->u.ibss.chandef); | ||
302 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
278 | 303 | ||
279 | basic_rates = 0; | 304 | basic_rates = 0; |
280 | 305 | ||
281 | for (i = 0; i < bss->supp_rates_len; i++) { | 306 | for (i = 0; i < bss->supp_rates_len; i++) { |
282 | int rate = (bss->supp_rates[i] & 0x7f) * 5; | 307 | int rate = bss->supp_rates[i] & 0x7f; |
283 | bool is_basic = !!(bss->supp_rates[i] & 0x80); | 308 | bool is_basic = !!(bss->supp_rates[i] & 0x80); |
284 | 309 | ||
285 | for (j = 0; j < sband->n_bitrates; j++) { | 310 | for (j = 0; j < sband->n_bitrates; j++) { |
286 | if (sband->bitrates[j].bitrate == rate) { | 311 | int brate; |
312 | if ((rate_flags & sband->bitrates[j].flags) | ||
313 | != rate_flags) | ||
314 | continue; | ||
315 | |||
316 | brate = DIV_ROUND_UP(sband->bitrates[j].bitrate, | ||
317 | 5 * (1 << shift)); | ||
318 | if (brate == rate) { | ||
287 | if (is_basic) | 319 | if (is_basic) |
288 | basic_rates |= BIT(j); | 320 | basic_rates |= BIT(j); |
289 | break; | 321 | break; |
@@ -465,7 +497,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
465 | sta = sta_info_get(sdata, mgmt->sa); | 497 | sta = sta_info_get(sdata, mgmt->sa); |
466 | 498 | ||
467 | if (elems->supp_rates) { | 499 | if (elems->supp_rates) { |
468 | supp_rates = ieee80211_sta_get_rates(local, elems, | 500 | supp_rates = ieee80211_sta_get_rates(sdata, elems, |
469 | band, NULL); | 501 | band, NULL); |
470 | if (sta) { | 502 | if (sta) { |
471 | u32 prev_rates; | 503 | u32 prev_rates; |
@@ -589,7 +621,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
589 | "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n", | 621 | "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n", |
590 | mgmt->bssid); | 622 | mgmt->bssid); |
591 | ieee80211_sta_join_ibss(sdata, bss); | 623 | ieee80211_sta_join_ibss(sdata, bss); |
592 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); | 624 | supp_rates = ieee80211_sta_get_rates(sdata, elems, band, NULL); |
593 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 625 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
594 | supp_rates); | 626 | supp_rates); |
595 | rcu_read_unlock(); | 627 | rcu_read_unlock(); |
@@ -1024,6 +1056,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1024 | struct cfg80211_ibss_params *params) | 1056 | struct cfg80211_ibss_params *params) |
1025 | { | 1057 | { |
1026 | u32 changed = 0; | 1058 | u32 changed = 0; |
1059 | u32 rate_flags; | ||
1060 | struct ieee80211_supported_band *sband; | ||
1061 | int i; | ||
1027 | 1062 | ||
1028 | if (params->bssid) { | 1063 | if (params->bssid) { |
1029 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); | 1064 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); |
@@ -1034,6 +1069,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1034 | sdata->u.ibss.privacy = params->privacy; | 1069 | sdata->u.ibss.privacy = params->privacy; |
1035 | sdata->u.ibss.control_port = params->control_port; | 1070 | sdata->u.ibss.control_port = params->control_port; |
1036 | sdata->u.ibss.basic_rates = params->basic_rates; | 1071 | sdata->u.ibss.basic_rates = params->basic_rates; |
1072 | |||
1073 | /* fix basic_rates if channel does not support these rates */ | ||
1074 | rate_flags = ieee80211_chandef_rate_flags(¶ms->chandef); | ||
1075 | sband = sdata->local->hw.wiphy->bands[params->chandef.chan->band]; | ||
1076 | for (i = 0; i < sband->n_bitrates; i++) { | ||
1077 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
1078 | sdata->u.ibss.basic_rates &= ~BIT(i); | ||
1079 | } | ||
1037 | memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, | 1080 | memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, |
1038 | sizeof(params->mcast_rate)); | 1081 | sizeof(params->mcast_rate)); |
1039 | 1082 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 338e7ca21ea5..6596da66bfaf 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1601,7 +1601,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1601 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1601 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1602 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1602 | size_t buffer_len, const u8 *ie, size_t ie_len, |
1603 | enum ieee80211_band band, u32 rate_mask, | 1603 | enum ieee80211_band band, u32 rate_mask, |
1604 | u8 channel); | 1604 | struct cfg80211_chan_def *chandef); |
1605 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1605 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1606 | u8 *dst, u32 ratemask, | 1606 | u8 *dst, u32 ratemask, |
1607 | struct ieee80211_channel *chan, | 1607 | struct ieee80211_channel *chan, |
@@ -1617,7 +1617,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1617 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1617 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
1618 | const size_t supp_rates_len, | 1618 | const size_t supp_rates_len, |
1619 | const u8 *supp_rates); | 1619 | const u8 *supp_rates); |
1620 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1620 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, |
1621 | struct ieee802_11_elems *elems, | 1621 | struct ieee802_11_elems *elems, |
1622 | enum ieee80211_band band, u32 *basic_rates); | 1622 | enum ieee80211_band band, u32 *basic_rates); |
1623 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | 1623 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, |
@@ -1634,6 +1634,9 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1634 | u16 prot_mode); | 1634 | u16 prot_mode); |
1635 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 1635 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, |
1636 | u32 cap); | 1636 | u32 cap); |
1637 | int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, | ||
1638 | const struct ieee80211_supported_band *sband, | ||
1639 | const u8 *srates, int srates_len, u32 *rates); | ||
1637 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 1640 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
1638 | struct sk_buff *skb, bool need_basic, | 1641 | struct sk_buff *skb, bool need_basic, |
1639 | enum ieee80211_band band); | 1642 | enum ieee80211_band band); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 447f41bbe744..e536f22fbeca 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -62,7 +62,6 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
62 | struct ieee802_11_elems *ie) | 62 | struct ieee802_11_elems *ie) |
63 | { | 63 | { |
64 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 64 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
65 | struct ieee80211_local *local = sdata->local; | ||
66 | u32 basic_rates = 0; | 65 | u32 basic_rates = 0; |
67 | struct cfg80211_chan_def sta_chan_def; | 66 | struct cfg80211_chan_def sta_chan_def; |
68 | 67 | ||
@@ -85,7 +84,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
85 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) | 84 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) |
86 | return false; | 85 | return false; |
87 | 86 | ||
88 | ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata), | 87 | ieee80211_sta_get_rates(sdata, ie, ieee80211_get_sdata_band(sdata), |
89 | &basic_rates); | 88 | &basic_rates); |
90 | 89 | ||
91 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | 90 | if (sdata->vif.bss_conf.basic_rates != basic_rates) |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 02c05fa15c20..6b65d5055f5b 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -379,7 +379,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, | |||
379 | u32 rates, basic_rates = 0, changed = 0; | 379 | u32 rates, basic_rates = 0, changed = 0; |
380 | 380 | ||
381 | sband = local->hw.wiphy->bands[band]; | 381 | sband = local->hw.wiphy->bands[band]; |
382 | rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates); | 382 | rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates); |
383 | 383 | ||
384 | spin_lock_bh(&sta->lock); | 384 | spin_lock_bh(&sta->lock); |
385 | sta->last_rx = jiffies; | 385 | sta->last_rx = jiffies; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ae31968d42d3..f7552c2b74eb 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -478,27 +478,6 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
478 | 478 | ||
479 | /* frame sending functions */ | 479 | /* frame sending functions */ |
480 | 480 | ||
481 | static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | ||
482 | struct ieee80211_supported_band *sband, | ||
483 | u32 *rates) | ||
484 | { | ||
485 | int i, j, count; | ||
486 | *rates = 0; | ||
487 | count = 0; | ||
488 | for (i = 0; i < supp_rates_len; i++) { | ||
489 | int rate = (supp_rates[i] & 0x7F) * 5; | ||
490 | |||
491 | for (j = 0; j < sband->n_bitrates; j++) | ||
492 | if (sband->bitrates[j].bitrate == rate) { | ||
493 | *rates |= BIT(j); | ||
494 | count++; | ||
495 | break; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | return count; | ||
500 | } | ||
501 | |||
502 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | 481 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, |
503 | struct sk_buff *skb, u8 ap_ht_param, | 482 | struct sk_buff *skb, u8 ap_ht_param, |
504 | struct ieee80211_supported_band *sband, | 483 | struct ieee80211_supported_band *sband, |
@@ -617,12 +596,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
617 | struct ieee80211_mgmt *mgmt; | 596 | struct ieee80211_mgmt *mgmt; |
618 | u8 *pos, qos_info; | 597 | u8 *pos, qos_info; |
619 | size_t offset = 0, noffset; | 598 | size_t offset = 0, noffset; |
620 | int i, count, rates_len, supp_rates_len; | 599 | int i, count, rates_len, supp_rates_len, shift; |
621 | u16 capab; | 600 | u16 capab; |
622 | struct ieee80211_supported_band *sband; | 601 | struct ieee80211_supported_band *sband; |
623 | struct ieee80211_chanctx_conf *chanctx_conf; | 602 | struct ieee80211_chanctx_conf *chanctx_conf; |
624 | struct ieee80211_channel *chan; | 603 | struct ieee80211_channel *chan; |
625 | u32 rates = 0; | 604 | u32 rate_flags, rates = 0; |
626 | 605 | ||
627 | sdata_assert_lock(sdata); | 606 | sdata_assert_lock(sdata); |
628 | 607 | ||
@@ -633,8 +612,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
633 | return; | 612 | return; |
634 | } | 613 | } |
635 | chan = chanctx_conf->def.chan; | 614 | chan = chanctx_conf->def.chan; |
615 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | ||
636 | rcu_read_unlock(); | 616 | rcu_read_unlock(); |
637 | sband = local->hw.wiphy->bands[chan->band]; | 617 | sband = local->hw.wiphy->bands[chan->band]; |
618 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
638 | 619 | ||
639 | if (assoc_data->supp_rates_len) { | 620 | if (assoc_data->supp_rates_len) { |
640 | /* | 621 | /* |
@@ -643,17 +624,24 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
643 | * in the association request (e.g. D-Link DAP 1353 in | 624 | * in the association request (e.g. D-Link DAP 1353 in |
644 | * b-only mode)... | 625 | * b-only mode)... |
645 | */ | 626 | */ |
646 | rates_len = ieee80211_compatible_rates(assoc_data->supp_rates, | 627 | rates_len = ieee80211_parse_bitrates(&chanctx_conf->def, sband, |
647 | assoc_data->supp_rates_len, | 628 | assoc_data->supp_rates, |
648 | sband, &rates); | 629 | assoc_data->supp_rates_len, |
630 | &rates); | ||
649 | } else { | 631 | } else { |
650 | /* | 632 | /* |
651 | * In case AP not provide any supported rates information | 633 | * In case AP not provide any supported rates information |
652 | * before association, we send information element(s) with | 634 | * before association, we send information element(s) with |
653 | * all rates that we support. | 635 | * all rates that we support. |
654 | */ | 636 | */ |
655 | rates = ~0; | 637 | rates_len = 0; |
656 | rates_len = sband->n_bitrates; | 638 | for (i = 0; i < sband->n_bitrates; i++) { |
639 | if ((rate_flags & sband->bitrates[i].flags) | ||
640 | != rate_flags) | ||
641 | continue; | ||
642 | rates |= BIT(i); | ||
643 | rates_len++; | ||
644 | } | ||
657 | } | 645 | } |
658 | 646 | ||
659 | skb = alloc_skb(local->hw.extra_tx_headroom + | 647 | skb = alloc_skb(local->hw.extra_tx_headroom + |
@@ -730,8 +718,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
730 | count = 0; | 718 | count = 0; |
731 | for (i = 0; i < sband->n_bitrates; i++) { | 719 | for (i = 0; i < sband->n_bitrates; i++) { |
732 | if (BIT(i) & rates) { | 720 | if (BIT(i) & rates) { |
733 | int rate = sband->bitrates[i].bitrate; | 721 | int rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
734 | *pos++ = (u8) (rate / 5); | 722 | 5 * (1 << shift)); |
723 | *pos++ = (u8) rate; | ||
735 | if (++count == 8) | 724 | if (++count == 8) |
736 | break; | 725 | break; |
737 | } | 726 | } |
@@ -744,8 +733,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
744 | 733 | ||
745 | for (i++; i < sband->n_bitrates; i++) { | 734 | for (i++; i < sband->n_bitrates; i++) { |
746 | if (BIT(i) & rates) { | 735 | if (BIT(i) & rates) { |
747 | int rate = sband->bitrates[i].bitrate; | 736 | int rate; |
748 | *pos++ = (u8) (rate / 5); | 737 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
738 | 5 * (1 << shift)); | ||
739 | *pos++ = (u8) rate; | ||
749 | } | 740 | } |
750 | } | 741 | } |
751 | } | 742 | } |
@@ -2432,15 +2423,16 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, | |||
2432 | u8 *supp_rates, unsigned int supp_rates_len, | 2423 | u8 *supp_rates, unsigned int supp_rates_len, |
2433 | u32 *rates, u32 *basic_rates, | 2424 | u32 *rates, u32 *basic_rates, |
2434 | bool *have_higher_than_11mbit, | 2425 | bool *have_higher_than_11mbit, |
2435 | int *min_rate, int *min_rate_index) | 2426 | int *min_rate, int *min_rate_index, |
2427 | int shift, u32 rate_flags) | ||
2436 | { | 2428 | { |
2437 | int i, j; | 2429 | int i, j; |
2438 | 2430 | ||
2439 | for (i = 0; i < supp_rates_len; i++) { | 2431 | for (i = 0; i < supp_rates_len; i++) { |
2440 | int rate = (supp_rates[i] & 0x7f) * 5; | 2432 | int rate = supp_rates[i] & 0x7f; |
2441 | bool is_basic = !!(supp_rates[i] & 0x80); | 2433 | bool is_basic = !!(supp_rates[i] & 0x80); |
2442 | 2434 | ||
2443 | if (rate > 110) | 2435 | if ((rate * 5 * (1 << shift)) > 110) |
2444 | *have_higher_than_11mbit = true; | 2436 | *have_higher_than_11mbit = true; |
2445 | 2437 | ||
2446 | /* | 2438 | /* |
@@ -2456,12 +2448,20 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, | |||
2456 | continue; | 2448 | continue; |
2457 | 2449 | ||
2458 | for (j = 0; j < sband->n_bitrates; j++) { | 2450 | for (j = 0; j < sband->n_bitrates; j++) { |
2459 | if (sband->bitrates[j].bitrate == rate) { | 2451 | struct ieee80211_rate *br; |
2452 | int brate; | ||
2453 | |||
2454 | br = &sband->bitrates[j]; | ||
2455 | if ((rate_flags & br->flags) != rate_flags) | ||
2456 | continue; | ||
2457 | |||
2458 | brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); | ||
2459 | if (brate == rate) { | ||
2460 | *rates |= BIT(j); | 2460 | *rates |= BIT(j); |
2461 | if (is_basic) | 2461 | if (is_basic) |
2462 | *basic_rates |= BIT(j); | 2462 | *basic_rates |= BIT(j); |
2463 | if (rate < *min_rate) { | 2463 | if ((rate * 5) < *min_rate) { |
2464 | *min_rate = rate; | 2464 | *min_rate = rate * 5; |
2465 | *min_rate_index = j; | 2465 | *min_rate_index = j; |
2466 | } | 2466 | } |
2467 | break; | 2467 | break; |
@@ -3884,27 +3884,40 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3884 | if (!new_sta) | 3884 | if (!new_sta) |
3885 | return -ENOMEM; | 3885 | return -ENOMEM; |
3886 | } | 3886 | } |
3887 | |||
3888 | if (new_sta) { | 3887 | if (new_sta) { |
3889 | u32 rates = 0, basic_rates = 0; | 3888 | u32 rates = 0, basic_rates = 0; |
3890 | bool have_higher_than_11mbit; | 3889 | bool have_higher_than_11mbit; |
3891 | int min_rate = INT_MAX, min_rate_index = -1; | 3890 | int min_rate = INT_MAX, min_rate_index = -1; |
3891 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3892 | struct ieee80211_supported_band *sband; | 3892 | struct ieee80211_supported_band *sband; |
3893 | const struct cfg80211_bss_ies *ies; | 3893 | const struct cfg80211_bss_ies *ies; |
3894 | int shift; | ||
3895 | u32 rate_flags; | ||
3894 | 3896 | ||
3895 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 3897 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
3896 | 3898 | ||
3897 | err = ieee80211_prep_channel(sdata, cbss); | 3899 | err = ieee80211_prep_channel(sdata, cbss); |
3898 | if (err) { | 3900 | if (err) { |
3899 | sta_info_free(local, new_sta); | 3901 | sta_info_free(local, new_sta); |
3900 | return err; | 3902 | return -EINVAL; |
3901 | } | 3903 | } |
3904 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
3905 | |||
3906 | rcu_read_lock(); | ||
3907 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3908 | if (WARN_ON(!chanctx_conf)) { | ||
3909 | rcu_read_unlock(); | ||
3910 | return -EINVAL; | ||
3911 | } | ||
3912 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | ||
3913 | rcu_read_unlock(); | ||
3902 | 3914 | ||
3903 | ieee80211_get_rates(sband, bss->supp_rates, | 3915 | ieee80211_get_rates(sband, bss->supp_rates, |
3904 | bss->supp_rates_len, | 3916 | bss->supp_rates_len, |
3905 | &rates, &basic_rates, | 3917 | &rates, &basic_rates, |
3906 | &have_higher_than_11mbit, | 3918 | &have_higher_than_11mbit, |
3907 | &min_rate, &min_rate_index); | 3919 | &min_rate, &min_rate_index, |
3920 | shift, rate_flags); | ||
3908 | 3921 | ||
3909 | /* | 3922 | /* |
3910 | * This used to be a workaround for basic rates missing | 3923 | * This used to be a workaround for basic rates missing |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 30d58d2d13e2..ba63ac851c2b 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -232,37 +232,28 @@ static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, | |||
232 | /* could not find a basic rate; use original selection */ | 232 | /* could not find a basic rate; use original selection */ |
233 | } | 233 | } |
234 | 234 | ||
235 | static inline s8 | 235 | static void __rate_control_send_low(struct ieee80211_hw *hw, |
236 | rate_lowest_non_cck_index(struct ieee80211_supported_band *sband, | 236 | struct ieee80211_supported_band *sband, |
237 | struct ieee80211_sta *sta) | 237 | struct ieee80211_sta *sta, |
238 | struct ieee80211_tx_info *info) | ||
238 | { | 239 | { |
239 | int i; | 240 | int i; |
241 | u32 rate_flags = | ||
242 | ieee80211_chandef_rate_flags(&hw->conf.chandef); | ||
240 | 243 | ||
244 | if ((sband->band == IEEE80211_BAND_2GHZ) && | ||
245 | (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) | ||
246 | rate_flags |= IEEE80211_RATE_ERP_G; | ||
247 | |||
248 | info->control.rates[0].idx = 0; | ||
241 | for (i = 0; i < sband->n_bitrates; i++) { | 249 | for (i = 0; i < sband->n_bitrates; i++) { |
242 | struct ieee80211_rate *srate = &sband->bitrates[i]; | 250 | if (!rate_supported(sta, sband->band, i)) |
243 | if ((srate->bitrate == 10) || (srate->bitrate == 20) || | ||
244 | (srate->bitrate == 55) || (srate->bitrate == 110)) | ||
245 | continue; | 251 | continue; |
246 | 252 | ||
247 | if (rate_supported(sta, sband->band, i)) | 253 | info->control.rates[0].idx = i; |
248 | return i; | 254 | break; |
249 | } | 255 | } |
250 | 256 | WARN_ON_ONCE(i == sband->n_bitrates); | |
251 | /* No matching rate found */ | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static void __rate_control_send_low(struct ieee80211_hw *hw, | ||
256 | struct ieee80211_supported_band *sband, | ||
257 | struct ieee80211_sta *sta, | ||
258 | struct ieee80211_tx_info *info) | ||
259 | { | ||
260 | if ((sband->band != IEEE80211_BAND_2GHZ) || | ||
261 | !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) | ||
262 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | ||
263 | else | ||
264 | info->control.rates[0].idx = | ||
265 | rate_lowest_non_cck_index(sband, sta); | ||
266 | 257 | ||
267 | info->control.rates[0].count = | 258 | info->control.rates[0].count = |
268 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | 259 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
@@ -585,6 +576,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | |||
585 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; | 576 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; |
586 | bool has_mcs_mask; | 577 | bool has_mcs_mask; |
587 | u32 mask; | 578 | u32 mask; |
579 | u32 rate_flags; | ||
588 | int i; | 580 | int i; |
589 | 581 | ||
590 | /* | 582 | /* |
@@ -594,6 +586,12 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | |||
594 | */ | 586 | */ |
595 | mask = sdata->rc_rateidx_mask[info->band]; | 587 | mask = sdata->rc_rateidx_mask[info->band]; |
596 | has_mcs_mask = sdata->rc_has_mcs_mask[info->band]; | 588 | has_mcs_mask = sdata->rc_has_mcs_mask[info->band]; |
589 | rate_flags = | ||
590 | ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
591 | for (i = 0; i < sband->n_bitrates; i++) | ||
592 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
593 | mask &= ~BIT(i); | ||
594 | |||
597 | if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask) | 595 | if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask) |
598 | return; | 596 | return; |
599 | 597 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index deeeca1299bd..0ac75127b7d2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -236,8 +236,13 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
236 | */ | 236 | */ |
237 | *pos = 0; | 237 | *pos = 0; |
238 | } else { | 238 | } else { |
239 | int shift = 0; | ||
239 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | 240 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); |
240 | *pos = rate->bitrate / 5; | 241 | if (status->flag & RX_FLAG_10MHZ) |
242 | shift = 1; | ||
243 | else if (status->flag & RX_FLAG_5MHZ) | ||
244 | shift = 2; | ||
245 | *pos = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift)); | ||
241 | } | 246 | } |
242 | pos++; | 247 | pos++; |
243 | 248 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 1b122a79b0d8..819d0956eb3b 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -204,10 +204,29 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
204 | ieee80211_rx_bss_put(local, bss); | 204 | ieee80211_rx_bss_put(local, bss); |
205 | } | 205 | } |
206 | 206 | ||
207 | static void | ||
208 | ieee80211_prepare_scan_chandef(struct cfg80211_chan_def *chandef, | ||
209 | enum nl80211_bss_scan_width scan_width) | ||
210 | { | ||
211 | memset(chandef, 0, sizeof(*chandef)); | ||
212 | switch (scan_width) { | ||
213 | case NL80211_BSS_CHAN_WIDTH_5: | ||
214 | chandef->width = NL80211_CHAN_WIDTH_5; | ||
215 | break; | ||
216 | case NL80211_BSS_CHAN_WIDTH_10: | ||
217 | chandef->width = NL80211_CHAN_WIDTH_10; | ||
218 | break; | ||
219 | default: | ||
220 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
207 | /* return false if no more work */ | 225 | /* return false if no more work */ |
208 | static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | 226 | static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) |
209 | { | 227 | { |
210 | struct cfg80211_scan_request *req = local->scan_req; | 228 | struct cfg80211_scan_request *req = local->scan_req; |
229 | struct cfg80211_chan_def chandef; | ||
211 | enum ieee80211_band band; | 230 | enum ieee80211_band band; |
212 | int i, ielen, n_chans; | 231 | int i, ielen, n_chans; |
213 | 232 | ||
@@ -229,11 +248,12 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
229 | } while (!n_chans); | 248 | } while (!n_chans); |
230 | 249 | ||
231 | local->hw_scan_req->n_channels = n_chans; | 250 | local->hw_scan_req->n_channels = n_chans; |
251 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | ||
232 | 252 | ||
233 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, | 253 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, |
234 | local->hw_scan_ies_bufsize, | 254 | local->hw_scan_ies_bufsize, |
235 | req->ie, req->ie_len, band, | 255 | req->ie, req->ie_len, band, |
236 | req->rates[band], 0); | 256 | req->rates[band], &chandef); |
237 | local->hw_scan_req->ie_len = ielen; | 257 | local->hw_scan_req->ie_len = ielen; |
238 | local->hw_scan_req->no_cck = req->no_cck; | 258 | local->hw_scan_req->no_cck = req->no_cck; |
239 | 259 | ||
@@ -912,6 +932,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
912 | { | 932 | { |
913 | struct ieee80211_local *local = sdata->local; | 933 | struct ieee80211_local *local = sdata->local; |
914 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; | 934 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; |
935 | struct cfg80211_chan_def chandef; | ||
915 | int ret, i, iebufsz; | 936 | int ret, i, iebufsz; |
916 | 937 | ||
917 | iebufsz = 2 + IEEE80211_MAX_SSID_LEN + | 938 | iebufsz = 2 + IEEE80211_MAX_SSID_LEN + |
@@ -939,10 +960,12 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
939 | goto out_free; | 960 | goto out_free; |
940 | } | 961 | } |
941 | 962 | ||
963 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | ||
964 | |||
942 | sched_scan_ies.len[i] = | 965 | sched_scan_ies.len[i] = |
943 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], | 966 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], |
944 | iebufsz, req->ie, req->ie_len, | 967 | iebufsz, req->ie, req->ie_len, |
945 | i, (u32) -1, 0); | 968 | i, (u32) -1, &chandef); |
946 | } | 969 | } |
947 | 970 | ||
948 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 971 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 43439203f4e4..6ad4c14385ef 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -252,9 +252,10 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info) | |||
252 | return len; | 252 | return len; |
253 | } | 253 | } |
254 | 254 | ||
255 | static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | 255 | static void |
256 | *sband, struct sk_buff *skb, | 256 | ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband, |
257 | int retry_count, int rtap_len) | 257 | struct sk_buff *skb, int retry_count, |
258 | int rtap_len, int shift) | ||
258 | { | 259 | { |
259 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 260 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
260 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 261 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -280,8 +281,11 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | |||
280 | /* IEEE80211_RADIOTAP_RATE */ | 281 | /* IEEE80211_RADIOTAP_RATE */ |
281 | if (info->status.rates[0].idx >= 0 && | 282 | if (info->status.rates[0].idx >= 0 && |
282 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { | 283 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { |
284 | u16 rate; | ||
285 | |||
283 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | 286 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); |
284 | *pos = sband->bitrates[info->status.rates[0].idx].bitrate / 5; | 287 | rate = sband->bitrates[info->status.rates[0].idx].bitrate; |
288 | *pos = DIV_ROUND_UP(rate, 5 * (1 << shift)); | ||
285 | /* padding for tx flags */ | 289 | /* padding for tx flags */ |
286 | pos += 2; | 290 | pos += 2; |
287 | } | 291 | } |
@@ -424,6 +428,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
424 | bool acked; | 428 | bool acked; |
425 | struct ieee80211_bar *bar; | 429 | struct ieee80211_bar *bar; |
426 | int rtap_len; | 430 | int rtap_len; |
431 | int shift = 0; | ||
427 | 432 | ||
428 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 433 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
429 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 434 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
@@ -458,6 +463,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
458 | if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr)) | 463 | if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr)) |
459 | continue; | 464 | continue; |
460 | 465 | ||
466 | shift = ieee80211_vif_get_shift(&sta->sdata->vif); | ||
467 | |||
461 | if (info->flags & IEEE80211_TX_STATUS_EOSP) | 468 | if (info->flags & IEEE80211_TX_STATUS_EOSP) |
462 | clear_sta_flag(sta, WLAN_STA_SP); | 469 | clear_sta_flag(sta, WLAN_STA_SP); |
463 | 470 | ||
@@ -624,7 +631,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
624 | dev_kfree_skb(skb); | 631 | dev_kfree_skb(skb); |
625 | return; | 632 | return; |
626 | } | 633 | } |
627 | ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len); | 634 | ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len, |
635 | shift); | ||
628 | 636 | ||
629 | /* XXX: is this sufficient for BPF? */ | 637 | /* XXX: is this sufficient for BPF? */ |
630 | skb_set_mac_header(skb, 0); | 638 | skb_set_mac_header(skb, 0); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3523daa0b15c..f82301b6cef2 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -40,12 +40,22 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
40 | struct sk_buff *skb, int group_addr, | 40 | struct sk_buff *skb, int group_addr, |
41 | int next_frag_len) | 41 | int next_frag_len) |
42 | { | 42 | { |
43 | int rate, mrate, erp, dur, i, shift; | 43 | int rate, mrate, erp, dur, i, shift = 0; |
44 | struct ieee80211_rate *txrate; | 44 | struct ieee80211_rate *txrate; |
45 | struct ieee80211_local *local = tx->local; | 45 | struct ieee80211_local *local = tx->local; |
46 | struct ieee80211_supported_band *sband; | 46 | struct ieee80211_supported_band *sband; |
47 | struct ieee80211_hdr *hdr; | 47 | struct ieee80211_hdr *hdr; |
48 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 48 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
49 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
50 | u32 rate_flags = 0; | ||
51 | |||
52 | rcu_read_lock(); | ||
53 | chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf); | ||
54 | if (chanctx_conf) { | ||
55 | shift = ieee80211_chandef_get_shift(&chanctx_conf->def); | ||
56 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | ||
57 | } | ||
58 | rcu_read_unlock(); | ||
49 | 59 | ||
50 | /* assume HW handles this */ | 60 | /* assume HW handles this */ |
51 | if (tx->rate.flags & IEEE80211_TX_RC_MCS) | 61 | if (tx->rate.flags & IEEE80211_TX_RC_MCS) |
@@ -122,8 +132,11 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
122 | if (r->bitrate > txrate->bitrate) | 132 | if (r->bitrate > txrate->bitrate) |
123 | break; | 133 | break; |
124 | 134 | ||
135 | if ((rate_flags & r->flags) != rate_flags) | ||
136 | continue; | ||
137 | |||
125 | if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) | 138 | if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) |
126 | rate = r->bitrate; | 139 | rate = DIV_ROUND_UP(r->bitrate, 1 << shift); |
127 | 140 | ||
128 | switch (sband->band) { | 141 | switch (sband->band) { |
129 | case IEEE80211_BAND_2GHZ: { | 142 | case IEEE80211_BAND_2GHZ: { |
@@ -150,11 +163,9 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
150 | if (rate == -1) { | 163 | if (rate == -1) { |
151 | /* No matching basic rate found; use highest suitable mandatory | 164 | /* No matching basic rate found; use highest suitable mandatory |
152 | * PHY rate */ | 165 | * PHY rate */ |
153 | rate = mrate; | 166 | rate = DIV_ROUND_UP(mrate, 1 << shift); |
154 | } | 167 | } |
155 | 168 | ||
156 | shift = ieee80211_vif_get_shift(&tx->sdata->vif); | ||
157 | |||
158 | /* Don't calculate ACKs for QoS Frames with NoAck Policy set */ | 169 | /* Don't calculate ACKs for QoS Frames with NoAck Policy set */ |
159 | if (ieee80211_is_data_qos(hdr->frame_control) && | 170 | if (ieee80211_is_data_qos(hdr->frame_control) && |
160 | *(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK) | 171 | *(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK) |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 61856e17a1e4..1e45891ca219 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -141,14 +141,18 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | |||
141 | dur = 16; /* SIFS + signal ext */ | 141 | dur = 16; /* SIFS + signal ext */ |
142 | dur += 16; /* IEEE 802.11-2012 18.3.2.4: T_PREAMBLE = 16 usec */ | 142 | dur += 16; /* IEEE 802.11-2012 18.3.2.4: T_PREAMBLE = 16 usec */ |
143 | dur += 4; /* IEEE 802.11-2012 18.3.2.4: T_SIGNAL = 4 usec */ | 143 | dur += 4; /* IEEE 802.11-2012 18.3.2.4: T_SIGNAL = 4 usec */ |
144 | dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, | ||
145 | 4 * rate); /* T_SYM x N_SYM */ | ||
146 | 144 | ||
147 | /* IEEE 802.11-2012 18.3.2.4: all values above are: | 145 | /* IEEE 802.11-2012 18.3.2.4: all values above are: |
148 | * * times 4 for 5 MHz | 146 | * * times 4 for 5 MHz |
149 | * * times 2 for 10 MHz | 147 | * * times 2 for 10 MHz |
150 | */ | 148 | */ |
151 | dur *= 1 << shift; | 149 | dur *= 1 << shift; |
150 | |||
151 | /* rates should already consider the channel bandwidth, | ||
152 | * don't apply divisor again. | ||
153 | */ | ||
154 | dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, | ||
155 | 4 * rate); /* T_SYM x N_SYM */ | ||
152 | } else { | 156 | } else { |
153 | /* | 157 | /* |
154 | * 802.11b or 802.11g with 802.11b compatibility: | 158 | * 802.11b or 802.11g with 802.11b compatibility: |
@@ -205,7 +209,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
205 | struct ieee80211_rate *rate; | 209 | struct ieee80211_rate *rate; |
206 | struct ieee80211_sub_if_data *sdata; | 210 | struct ieee80211_sub_if_data *sdata; |
207 | bool short_preamble; | 211 | bool short_preamble; |
208 | int erp, shift = 0; | 212 | int erp, shift = 0, bitrate; |
209 | u16 dur; | 213 | u16 dur; |
210 | struct ieee80211_supported_band *sband; | 214 | struct ieee80211_supported_band *sband; |
211 | 215 | ||
@@ -224,14 +228,16 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
224 | shift = ieee80211_vif_get_shift(vif); | 228 | shift = ieee80211_vif_get_shift(vif); |
225 | } | 229 | } |
226 | 230 | ||
231 | bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift); | ||
232 | |||
227 | /* CTS duration */ | 233 | /* CTS duration */ |
228 | dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 234 | dur = ieee80211_frame_duration(sband->band, 10, bitrate, |
229 | erp, short_preamble, shift); | 235 | erp, short_preamble, shift); |
230 | /* Data frame duration */ | 236 | /* Data frame duration */ |
231 | dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, | 237 | dur += ieee80211_frame_duration(sband->band, frame_len, bitrate, |
232 | erp, short_preamble, shift); | 238 | erp, short_preamble, shift); |
233 | /* ACK duration */ | 239 | /* ACK duration */ |
234 | dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 240 | dur += ieee80211_frame_duration(sband->band, 10, bitrate, |
235 | erp, short_preamble, shift); | 241 | erp, short_preamble, shift); |
236 | 242 | ||
237 | return cpu_to_le16(dur); | 243 | return cpu_to_le16(dur); |
@@ -247,7 +253,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
247 | struct ieee80211_rate *rate; | 253 | struct ieee80211_rate *rate; |
248 | struct ieee80211_sub_if_data *sdata; | 254 | struct ieee80211_sub_if_data *sdata; |
249 | bool short_preamble; | 255 | bool short_preamble; |
250 | int erp, shift = 0; | 256 | int erp, shift = 0, bitrate; |
251 | u16 dur; | 257 | u16 dur; |
252 | struct ieee80211_supported_band *sband; | 258 | struct ieee80211_supported_band *sband; |
253 | 259 | ||
@@ -265,12 +271,14 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
265 | shift = ieee80211_vif_get_shift(vif); | 271 | shift = ieee80211_vif_get_shift(vif); |
266 | } | 272 | } |
267 | 273 | ||
274 | bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift); | ||
275 | |||
268 | /* Data frame duration */ | 276 | /* Data frame duration */ |
269 | dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, | 277 | dur = ieee80211_frame_duration(sband->band, frame_len, bitrate, |
270 | erp, short_preamble, shift); | 278 | erp, short_preamble, shift); |
271 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { | 279 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { |
272 | /* ACK duration */ | 280 | /* ACK duration */ |
273 | dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 281 | dur += ieee80211_frame_duration(sband->band, 10, bitrate, |
274 | erp, short_preamble, shift); | 282 | erp, short_preamble, shift); |
275 | } | 283 | } |
276 | 284 | ||
@@ -1175,7 +1183,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1175 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1183 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1176 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1184 | size_t buffer_len, const u8 *ie, size_t ie_len, |
1177 | enum ieee80211_band band, u32 rate_mask, | 1185 | enum ieee80211_band band, u32 rate_mask, |
1178 | u8 channel) | 1186 | struct cfg80211_chan_def *chandef) |
1179 | { | 1187 | { |
1180 | struct ieee80211_supported_band *sband; | 1188 | struct ieee80211_supported_band *sband; |
1181 | u8 *pos = buffer, *end = buffer + buffer_len; | 1189 | u8 *pos = buffer, *end = buffer + buffer_len; |
@@ -1184,16 +1192,26 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1184 | u8 rates[32]; | 1192 | u8 rates[32]; |
1185 | int num_rates; | 1193 | int num_rates; |
1186 | int ext_rates_len; | 1194 | int ext_rates_len; |
1195 | int shift; | ||
1196 | u32 rate_flags; | ||
1187 | 1197 | ||
1188 | sband = local->hw.wiphy->bands[band]; | 1198 | sband = local->hw.wiphy->bands[band]; |
1189 | if (WARN_ON_ONCE(!sband)) | 1199 | if (WARN_ON_ONCE(!sband)) |
1190 | return 0; | 1200 | return 0; |
1191 | 1201 | ||
1202 | rate_flags = ieee80211_chandef_rate_flags(chandef); | ||
1203 | shift = ieee80211_chandef_get_shift(chandef); | ||
1204 | |||
1192 | num_rates = 0; | 1205 | num_rates = 0; |
1193 | for (i = 0; i < sband->n_bitrates; i++) { | 1206 | for (i = 0; i < sband->n_bitrates; i++) { |
1194 | if ((BIT(i) & rate_mask) == 0) | 1207 | if ((BIT(i) & rate_mask) == 0) |
1195 | continue; /* skip rate */ | 1208 | continue; /* skip rate */ |
1196 | rates[num_rates++] = (u8) (sband->bitrates[i].bitrate / 5); | 1209 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) |
1210 | continue; | ||
1211 | |||
1212 | rates[num_rates++] = | ||
1213 | (u8) DIV_ROUND_UP(sband->bitrates[i].bitrate, | ||
1214 | (1 << shift) * 5); | ||
1197 | } | 1215 | } |
1198 | 1216 | ||
1199 | supp_rates_len = min_t(int, num_rates, 8); | 1217 | supp_rates_len = min_t(int, num_rates, 8); |
@@ -1233,12 +1251,13 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1233 | pos += ext_rates_len; | 1251 | pos += ext_rates_len; |
1234 | } | 1252 | } |
1235 | 1253 | ||
1236 | if (channel && sband->band == IEEE80211_BAND_2GHZ) { | 1254 | if (chandef->chan && sband->band == IEEE80211_BAND_2GHZ) { |
1237 | if (end - pos < 3) | 1255 | if (end - pos < 3) |
1238 | goto out_err; | 1256 | goto out_err; |
1239 | *pos++ = WLAN_EID_DS_PARAMS; | 1257 | *pos++ = WLAN_EID_DS_PARAMS; |
1240 | *pos++ = 1; | 1258 | *pos++ = 1; |
1241 | *pos++ = channel; | 1259 | *pos++ = ieee80211_frequency_to_channel( |
1260 | chandef->chan->center_freq); | ||
1242 | } | 1261 | } |
1243 | 1262 | ||
1244 | /* insert custom IEs that go before HT */ | 1263 | /* insert custom IEs that go before HT */ |
@@ -1303,9 +1322,9 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1303 | bool directed) | 1322 | bool directed) |
1304 | { | 1323 | { |
1305 | struct ieee80211_local *local = sdata->local; | 1324 | struct ieee80211_local *local = sdata->local; |
1325 | struct cfg80211_chan_def chandef; | ||
1306 | struct sk_buff *skb; | 1326 | struct sk_buff *skb; |
1307 | struct ieee80211_mgmt *mgmt; | 1327 | struct ieee80211_mgmt *mgmt; |
1308 | u8 chan_no; | ||
1309 | int ies_len; | 1328 | int ies_len; |
1310 | 1329 | ||
1311 | /* | 1330 | /* |
@@ -1313,10 +1332,11 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1313 | * in order to maximize the chance that we get a response. Some | 1332 | * in order to maximize the chance that we get a response. Some |
1314 | * badly-behaved APs don't respond when this parameter is included. | 1333 | * badly-behaved APs don't respond when this parameter is included. |
1315 | */ | 1334 | */ |
1335 | chandef.width = sdata->vif.bss_conf.chandef.width; | ||
1316 | if (directed) | 1336 | if (directed) |
1317 | chan_no = 0; | 1337 | chandef.chan = NULL; |
1318 | else | 1338 | else |
1319 | chan_no = ieee80211_frequency_to_channel(chan->center_freq); | 1339 | chandef.chan = chan; |
1320 | 1340 | ||
1321 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1341 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
1322 | ssid, ssid_len, 100 + ie_len); | 1342 | ssid, ssid_len, 100 + ie_len); |
@@ -1326,7 +1346,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1326 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), | 1346 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), |
1327 | skb_tailroom(skb), | 1347 | skb_tailroom(skb), |
1328 | ie, ie_len, chan->band, | 1348 | ie, ie_len, chan->band, |
1329 | ratemask, chan_no); | 1349 | ratemask, &chandef); |
1330 | skb_put(skb, ies_len); | 1350 | skb_put(skb, ies_len); |
1331 | 1351 | ||
1332 | if (dst) { | 1352 | if (dst) { |
@@ -1360,16 +1380,19 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1360 | } | 1380 | } |
1361 | } | 1381 | } |
1362 | 1382 | ||
1363 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1383 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, |
1364 | struct ieee802_11_elems *elems, | 1384 | struct ieee802_11_elems *elems, |
1365 | enum ieee80211_band band, u32 *basic_rates) | 1385 | enum ieee80211_band band, u32 *basic_rates) |
1366 | { | 1386 | { |
1367 | struct ieee80211_supported_band *sband; | 1387 | struct ieee80211_supported_band *sband; |
1368 | struct ieee80211_rate *bitrates; | 1388 | struct ieee80211_rate *bitrates; |
1369 | size_t num_rates; | 1389 | size_t num_rates; |
1370 | u32 supp_rates; | 1390 | u32 supp_rates, rate_flags; |
1371 | int i, j; | 1391 | int i, j, shift; |
1372 | sband = local->hw.wiphy->bands[band]; | 1392 | sband = sdata->local->hw.wiphy->bands[band]; |
1393 | |||
1394 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
1395 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
1373 | 1396 | ||
1374 | if (WARN_ON(!sband)) | 1397 | if (WARN_ON(!sband)) |
1375 | return 1; | 1398 | return 1; |
@@ -1394,7 +1417,15 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
1394 | continue; | 1417 | continue; |
1395 | 1418 | ||
1396 | for (j = 0; j < num_rates; j++) { | 1419 | for (j = 0; j < num_rates; j++) { |
1397 | if (bitrates[j].bitrate == own_rate) { | 1420 | int brate; |
1421 | if ((rate_flags & sband->bitrates[j].flags) | ||
1422 | != rate_flags) | ||
1423 | continue; | ||
1424 | |||
1425 | brate = DIV_ROUND_UP(sband->bitrates[j].bitrate, | ||
1426 | 1 << shift); | ||
1427 | |||
1428 | if (brate == own_rate) { | ||
1398 | supp_rates |= BIT(j); | 1429 | supp_rates |= BIT(j); |
1399 | if (basic_rates && is_basic) | 1430 | if (basic_rates && is_basic) |
1400 | *basic_rates |= BIT(j); | 1431 | *basic_rates |= BIT(j); |
@@ -2017,18 +2048,56 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, | |||
2017 | cfg80211_chandef_create(chandef, control_chan, channel_type); | 2048 | cfg80211_chandef_create(chandef, control_chan, channel_type); |
2018 | } | 2049 | } |
2019 | 2050 | ||
2051 | int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, | ||
2052 | const struct ieee80211_supported_band *sband, | ||
2053 | const u8 *srates, int srates_len, u32 *rates) | ||
2054 | { | ||
2055 | u32 rate_flags = ieee80211_chandef_rate_flags(chandef); | ||
2056 | int shift = ieee80211_chandef_get_shift(chandef); | ||
2057 | struct ieee80211_rate *br; | ||
2058 | int brate, rate, i, j, count = 0; | ||
2059 | |||
2060 | *rates = 0; | ||
2061 | |||
2062 | for (i = 0; i < srates_len; i++) { | ||
2063 | rate = srates[i] & 0x7f; | ||
2064 | |||
2065 | for (j = 0; j < sband->n_bitrates; j++) { | ||
2066 | br = &sband->bitrates[j]; | ||
2067 | if ((rate_flags & br->flags) != rate_flags) | ||
2068 | continue; | ||
2069 | |||
2070 | brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); | ||
2071 | if (brate == rate) { | ||
2072 | *rates |= BIT(j); | ||
2073 | count++; | ||
2074 | break; | ||
2075 | } | ||
2076 | } | ||
2077 | } | ||
2078 | return count; | ||
2079 | } | ||
2080 | |||
2020 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 2081 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
2021 | struct sk_buff *skb, bool need_basic, | 2082 | struct sk_buff *skb, bool need_basic, |
2022 | enum ieee80211_band band) | 2083 | enum ieee80211_band band) |
2023 | { | 2084 | { |
2024 | struct ieee80211_local *local = sdata->local; | 2085 | struct ieee80211_local *local = sdata->local; |
2025 | struct ieee80211_supported_band *sband; | 2086 | struct ieee80211_supported_band *sband; |
2026 | int rate; | 2087 | int rate, shift; |
2027 | u8 i, rates, *pos; | 2088 | u8 i, rates, *pos; |
2028 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 2089 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
2090 | u32 rate_flags; | ||
2029 | 2091 | ||
2092 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
2093 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
2030 | sband = local->hw.wiphy->bands[band]; | 2094 | sband = local->hw.wiphy->bands[band]; |
2031 | rates = sband->n_bitrates; | 2095 | rates = 0; |
2096 | for (i = 0; i < sband->n_bitrates; i++) { | ||
2097 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
2098 | continue; | ||
2099 | rates++; | ||
2100 | } | ||
2032 | if (rates > 8) | 2101 | if (rates > 8) |
2033 | rates = 8; | 2102 | rates = 8; |
2034 | 2103 | ||
@@ -2040,10 +2109,15 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
2040 | *pos++ = rates; | 2109 | *pos++ = rates; |
2041 | for (i = 0; i < rates; i++) { | 2110 | for (i = 0; i < rates; i++) { |
2042 | u8 basic = 0; | 2111 | u8 basic = 0; |
2112 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
2113 | continue; | ||
2114 | |||
2043 | if (need_basic && basic_rates & BIT(i)) | 2115 | if (need_basic && basic_rates & BIT(i)) |
2044 | basic = 0x80; | 2116 | basic = 0x80; |
2045 | rate = sband->bitrates[i].bitrate; | 2117 | rate = sband->bitrates[i].bitrate; |
2046 | *pos++ = basic | (u8) (rate / 5); | 2118 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
2119 | 5 * (1 << shift)); | ||
2120 | *pos++ = basic | (u8) rate; | ||
2047 | } | 2121 | } |
2048 | 2122 | ||
2049 | return 0; | 2123 | return 0; |
@@ -2055,12 +2129,22 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
2055 | { | 2129 | { |
2056 | struct ieee80211_local *local = sdata->local; | 2130 | struct ieee80211_local *local = sdata->local; |
2057 | struct ieee80211_supported_band *sband; | 2131 | struct ieee80211_supported_band *sband; |
2058 | int rate; | 2132 | int rate, skip, shift; |
2059 | u8 i, exrates, *pos; | 2133 | u8 i, exrates, *pos; |
2060 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 2134 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
2135 | u32 rate_flags; | ||
2136 | |||
2137 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
2138 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
2061 | 2139 | ||
2062 | sband = local->hw.wiphy->bands[band]; | 2140 | sband = local->hw.wiphy->bands[band]; |
2063 | exrates = sband->n_bitrates; | 2141 | exrates = 0; |
2142 | for (i = 0; i < sband->n_bitrates; i++) { | ||
2143 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
2144 | continue; | ||
2145 | exrates++; | ||
2146 | } | ||
2147 | |||
2064 | if (exrates > 8) | 2148 | if (exrates > 8) |
2065 | exrates -= 8; | 2149 | exrates -= 8; |
2066 | else | 2150 | else |
@@ -2073,12 +2157,19 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
2073 | pos = skb_put(skb, exrates + 2); | 2157 | pos = skb_put(skb, exrates + 2); |
2074 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 2158 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
2075 | *pos++ = exrates; | 2159 | *pos++ = exrates; |
2160 | skip = 0; | ||
2076 | for (i = 8; i < sband->n_bitrates; i++) { | 2161 | for (i = 8; i < sband->n_bitrates; i++) { |
2077 | u8 basic = 0; | 2162 | u8 basic = 0; |
2163 | if ((rate_flags & sband->bitrates[i].flags) | ||
2164 | != rate_flags) | ||
2165 | continue; | ||
2166 | if (skip++ < 8) | ||
2167 | continue; | ||
2078 | if (need_basic && basic_rates & BIT(i)) | 2168 | if (need_basic && basic_rates & BIT(i)) |
2079 | basic = 0x80; | 2169 | basic = 0x80; |
2080 | rate = sband->bitrates[i].bitrate; | 2170 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
2081 | *pos++ = basic | (u8) (rate / 5); | 2171 | 5 * (1 << shift)); |
2172 | *pos++ = basic | (u8) rate; | ||
2082 | } | 2173 | } |
2083 | } | 2174 | } |
2084 | return 0; | 2175 | return 0; |
@@ -2162,9 +2253,17 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2162 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2253 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
2163 | } else { | 2254 | } else { |
2164 | struct ieee80211_supported_band *sband; | 2255 | struct ieee80211_supported_band *sband; |
2256 | int shift = 0; | ||
2257 | int bitrate; | ||
2258 | |||
2259 | if (status->flag & RX_FLAG_10MHZ) | ||
2260 | shift = 1; | ||
2261 | if (status->flag & RX_FLAG_5MHZ) | ||
2262 | shift = 2; | ||
2165 | 2263 | ||
2166 | sband = local->hw.wiphy->bands[status->band]; | 2264 | sband = local->hw.wiphy->bands[status->band]; |
2167 | ri.legacy = sband->bitrates[status->rate_idx].bitrate; | 2265 | bitrate = sband->bitrates[status->rate_idx].bitrate; |
2266 | ri.legacy = DIV_ROUND_UP(bitrate, (1 << shift)); | ||
2168 | } | 2267 | } |
2169 | 2268 | ||
2170 | rate = cfg80211_calculate_bitrate(&ri); | 2269 | rate = cfg80211_calculate_bitrate(&ri); |