diff options
Diffstat (limited to 'net/mac80211/util.c')
| -rw-r--r-- | net/mac80211/util.c | 218 |
1 files changed, 152 insertions, 66 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22654452a561..e1b34a18b243 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -107,7 +107,8 @@ void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) | |||
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | 109 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, |
| 110 | int rate, int erp, int short_preamble) | 110 | int rate, int erp, int short_preamble, |
| 111 | int shift) | ||
| 111 | { | 112 | { |
| 112 | int dur; | 113 | int dur; |
| 113 | 114 | ||
| @@ -118,6 +119,9 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | |||
| 118 | * | 119 | * |
| 119 | * rate is in 100 kbps, so divident is multiplied by 10 in the | 120 | * rate is in 100 kbps, so divident is multiplied by 10 in the |
| 120 | * DIV_ROUND_UP() operations. | 121 | * DIV_ROUND_UP() operations. |
| 122 | * | ||
| 123 | * shift may be 2 for 5 MHz channels or 1 for 10 MHz channels, and | ||
| 124 | * is assumed to be 0 otherwise. | ||
| 121 | */ | 125 | */ |
| 122 | 126 | ||
| 123 | if (band == IEEE80211_BAND_5GHZ || erp) { | 127 | if (band == IEEE80211_BAND_5GHZ || erp) { |
| @@ -130,13 +134,23 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | |||
| 130 | * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext | 134 | * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext |
| 131 | * | 135 | * |
| 132 | * T_SYM = 4 usec | 136 | * T_SYM = 4 usec |
| 133 | * 802.11a - 17.5.2: aSIFSTime = 16 usec | 137 | * 802.11a - 18.5.2: aSIFSTime = 16 usec |
| 134 | * 802.11g - 19.8.4: aSIFSTime = 10 usec + | 138 | * 802.11g - 19.8.4: aSIFSTime = 10 usec + |
| 135 | * signal ext = 6 usec | 139 | * signal ext = 6 usec |
| 136 | */ | 140 | */ |
| 137 | dur = 16; /* SIFS + signal ext */ | 141 | dur = 16; /* SIFS + signal ext */ |
| 138 | dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ | 142 | dur += 16; /* IEEE 802.11-2012 18.3.2.4: T_PREAMBLE = 16 usec */ |
| 139 | dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ | 143 | dur += 4; /* IEEE 802.11-2012 18.3.2.4: T_SIGNAL = 4 usec */ |
| 144 | |||
| 145 | /* IEEE 802.11-2012 18.3.2.4: all values above are: | ||
| 146 | * * times 4 for 5 MHz | ||
| 147 | * * times 2 for 10 MHz | ||
| 148 | */ | ||
| 149 | dur *= 1 << shift; | ||
| 150 | |||
| 151 | /* rates should already consider the channel bandwidth, | ||
| 152 | * don't apply divisor again. | ||
| 153 | */ | ||
| 140 | dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, | 154 | dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, |
| 141 | 4 * rate); /* T_SYM x N_SYM */ | 155 | 4 * rate); /* T_SYM x N_SYM */ |
| 142 | } else { | 156 | } else { |
| @@ -168,7 +182,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
| 168 | { | 182 | { |
| 169 | struct ieee80211_sub_if_data *sdata; | 183 | struct ieee80211_sub_if_data *sdata; |
| 170 | u16 dur; | 184 | u16 dur; |
| 171 | int erp; | 185 | int erp, shift = 0; |
| 172 | bool short_preamble = false; | 186 | bool short_preamble = false; |
| 173 | 187 | ||
| 174 | erp = 0; | 188 | erp = 0; |
| @@ -177,10 +191,11 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
| 177 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 191 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
| 178 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 192 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
| 179 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 193 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
| 194 | shift = ieee80211_vif_get_shift(vif); | ||
| 180 | } | 195 | } |
| 181 | 196 | ||
| 182 | dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp, | 197 | dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp, |
| 183 | short_preamble); | 198 | short_preamble, shift); |
| 184 | 199 | ||
| 185 | return cpu_to_le16(dur); | 200 | return cpu_to_le16(dur); |
| 186 | } | 201 | } |
| @@ -194,7 +209,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
| 194 | struct ieee80211_rate *rate; | 209 | struct ieee80211_rate *rate; |
| 195 | struct ieee80211_sub_if_data *sdata; | 210 | struct ieee80211_sub_if_data *sdata; |
| 196 | bool short_preamble; | 211 | bool short_preamble; |
| 197 | int erp; | 212 | int erp, shift = 0, bitrate; |
| 198 | u16 dur; | 213 | u16 dur; |
| 199 | struct ieee80211_supported_band *sband; | 214 | struct ieee80211_supported_band *sband; |
| 200 | 215 | ||
| @@ -210,17 +225,20 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
| 210 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 225 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
| 211 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 226 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
| 212 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 227 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
| 228 | shift = ieee80211_vif_get_shift(vif); | ||
| 213 | } | 229 | } |
| 214 | 230 | ||
| 231 | bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift); | ||
| 232 | |||
| 215 | /* CTS duration */ | 233 | /* CTS duration */ |
| 216 | dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 234 | dur = ieee80211_frame_duration(sband->band, 10, bitrate, |
| 217 | erp, short_preamble); | 235 | erp, short_preamble, shift); |
| 218 | /* Data frame duration */ | 236 | /* Data frame duration */ |
| 219 | dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, | 237 | dur += ieee80211_frame_duration(sband->band, frame_len, bitrate, |
| 220 | erp, short_preamble); | 238 | erp, short_preamble, shift); |
| 221 | /* ACK duration */ | 239 | /* ACK duration */ |
| 222 | dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 240 | dur += ieee80211_frame_duration(sband->band, 10, bitrate, |
| 223 | erp, short_preamble); | 241 | erp, short_preamble, shift); |
| 224 | 242 | ||
| 225 | return cpu_to_le16(dur); | 243 | return cpu_to_le16(dur); |
| 226 | } | 244 | } |
| @@ -235,7 +253,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
| 235 | struct ieee80211_rate *rate; | 253 | struct ieee80211_rate *rate; |
| 236 | struct ieee80211_sub_if_data *sdata; | 254 | struct ieee80211_sub_if_data *sdata; |
| 237 | bool short_preamble; | 255 | bool short_preamble; |
| 238 | int erp; | 256 | int erp, shift = 0, bitrate; |
| 239 | u16 dur; | 257 | u16 dur; |
| 240 | struct ieee80211_supported_band *sband; | 258 | struct ieee80211_supported_band *sband; |
| 241 | 259 | ||
| @@ -250,15 +268,18 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
| 250 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 268 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
| 251 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 269 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
| 252 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 270 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
| 271 | shift = ieee80211_vif_get_shift(vif); | ||
| 253 | } | 272 | } |
| 254 | 273 | ||
| 274 | bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift); | ||
| 275 | |||
| 255 | /* Data frame duration */ | 276 | /* Data frame duration */ |
| 256 | dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, | 277 | dur = ieee80211_frame_duration(sband->band, frame_len, bitrate, |
| 257 | erp, short_preamble); | 278 | erp, short_preamble, shift); |
| 258 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { | 279 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { |
| 259 | /* ACK duration */ | 280 | /* ACK duration */ |
| 260 | dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 281 | dur += ieee80211_frame_duration(sband->band, 10, bitrate, |
| 261 | erp, short_preamble); | 282 | erp, short_preamble, shift); |
| 262 | } | 283 | } |
| 263 | 284 | ||
| 264 | return cpu_to_le16(dur); | 285 | return cpu_to_le16(dur); |
| @@ -1052,32 +1073,6 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
| 1052 | } | 1073 | } |
| 1053 | } | 1074 | } |
| 1054 | 1075 | ||
| 1055 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | ||
| 1056 | const size_t supp_rates_len, | ||
| 1057 | const u8 *supp_rates) | ||
| 1058 | { | ||
| 1059 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
| 1060 | int i, have_higher_than_11mbit = 0; | ||
| 1061 | |||
| 1062 | /* cf. IEEE 802.11 9.2.12 */ | ||
| 1063 | for (i = 0; i < supp_rates_len; i++) | ||
| 1064 | if ((supp_rates[i] & 0x7f) * 5 > 110) | ||
| 1065 | have_higher_than_11mbit = 1; | ||
| 1066 | |||
| 1067 | rcu_read_lock(); | ||
| 1068 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
| 1069 | |||
| 1070 | if (chanctx_conf && | ||
| 1071 | chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ && | ||
| 1072 | have_higher_than_11mbit) | ||
| 1073 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
| 1074 | else | ||
| 1075 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
| 1076 | rcu_read_unlock(); | ||
| 1077 | |||
| 1078 | ieee80211_set_wmm_default(sdata, true); | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1076 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
| 1082 | u16 transaction, u16 auth_alg, u16 status, | 1077 | u16 transaction, u16 auth_alg, u16 status, |
| 1083 | const u8 *extra, size_t extra_len, const u8 *da, | 1078 | const u8 *extra, size_t extra_len, const u8 *da, |
| @@ -1162,7 +1157,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
| 1162 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1157 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
| 1163 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1158 | size_t buffer_len, const u8 *ie, size_t ie_len, |
| 1164 | enum ieee80211_band band, u32 rate_mask, | 1159 | enum ieee80211_band band, u32 rate_mask, |
| 1165 | u8 channel) | 1160 | struct cfg80211_chan_def *chandef) |
| 1166 | { | 1161 | { |
| 1167 | struct ieee80211_supported_band *sband; | 1162 | struct ieee80211_supported_band *sband; |
| 1168 | u8 *pos = buffer, *end = buffer + buffer_len; | 1163 | u8 *pos = buffer, *end = buffer + buffer_len; |
| @@ -1171,16 +1166,26 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
| 1171 | u8 rates[32]; | 1166 | u8 rates[32]; |
| 1172 | int num_rates; | 1167 | int num_rates; |
| 1173 | int ext_rates_len; | 1168 | int ext_rates_len; |
| 1169 | int shift; | ||
| 1170 | u32 rate_flags; | ||
| 1174 | 1171 | ||
| 1175 | sband = local->hw.wiphy->bands[band]; | 1172 | sband = local->hw.wiphy->bands[band]; |
| 1176 | if (WARN_ON_ONCE(!sband)) | 1173 | if (WARN_ON_ONCE(!sband)) |
| 1177 | return 0; | 1174 | return 0; |
| 1178 | 1175 | ||
| 1176 | rate_flags = ieee80211_chandef_rate_flags(chandef); | ||
| 1177 | shift = ieee80211_chandef_get_shift(chandef); | ||
| 1178 | |||
| 1179 | num_rates = 0; | 1179 | num_rates = 0; |
| 1180 | for (i = 0; i < sband->n_bitrates; i++) { | 1180 | for (i = 0; i < sband->n_bitrates; i++) { |
| 1181 | if ((BIT(i) & rate_mask) == 0) | 1181 | if ((BIT(i) & rate_mask) == 0) |
| 1182 | continue; /* skip rate */ | 1182 | continue; /* skip rate */ |
| 1183 | rates[num_rates++] = (u8) (sband->bitrates[i].bitrate / 5); | 1183 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) |
| 1184 | continue; | ||
| 1185 | |||
| 1186 | rates[num_rates++] = | ||
| 1187 | (u8) DIV_ROUND_UP(sband->bitrates[i].bitrate, | ||
| 1188 | (1 << shift) * 5); | ||
| 1184 | } | 1189 | } |
| 1185 | 1190 | ||
| 1186 | supp_rates_len = min_t(int, num_rates, 8); | 1191 | supp_rates_len = min_t(int, num_rates, 8); |
| @@ -1220,12 +1225,13 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
| 1220 | pos += ext_rates_len; | 1225 | pos += ext_rates_len; |
| 1221 | } | 1226 | } |
| 1222 | 1227 | ||
| 1223 | if (channel && sband->band == IEEE80211_BAND_2GHZ) { | 1228 | if (chandef->chan && sband->band == IEEE80211_BAND_2GHZ) { |
| 1224 | if (end - pos < 3) | 1229 | if (end - pos < 3) |
| 1225 | goto out_err; | 1230 | goto out_err; |
| 1226 | *pos++ = WLAN_EID_DS_PARAMS; | 1231 | *pos++ = WLAN_EID_DS_PARAMS; |
| 1227 | *pos++ = 1; | 1232 | *pos++ = 1; |
| 1228 | *pos++ = channel; | 1233 | *pos++ = ieee80211_frequency_to_channel( |
| 1234 | chandef->chan->center_freq); | ||
| 1229 | } | 1235 | } |
| 1230 | 1236 | ||
| 1231 | /* insert custom IEs that go before HT */ | 1237 | /* insert custom IEs that go before HT */ |
| @@ -1290,9 +1296,9 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
| 1290 | bool directed) | 1296 | bool directed) |
| 1291 | { | 1297 | { |
| 1292 | struct ieee80211_local *local = sdata->local; | 1298 | struct ieee80211_local *local = sdata->local; |
| 1299 | struct cfg80211_chan_def chandef; | ||
| 1293 | struct sk_buff *skb; | 1300 | struct sk_buff *skb; |
| 1294 | struct ieee80211_mgmt *mgmt; | 1301 | struct ieee80211_mgmt *mgmt; |
| 1295 | u8 chan_no; | ||
| 1296 | int ies_len; | 1302 | int ies_len; |
| 1297 | 1303 | ||
| 1298 | /* | 1304 | /* |
| @@ -1300,10 +1306,11 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
| 1300 | * in order to maximize the chance that we get a response. Some | 1306 | * in order to maximize the chance that we get a response. Some |
| 1301 | * badly-behaved APs don't respond when this parameter is included. | 1307 | * badly-behaved APs don't respond when this parameter is included. |
| 1302 | */ | 1308 | */ |
| 1309 | chandef.width = sdata->vif.bss_conf.chandef.width; | ||
| 1303 | if (directed) | 1310 | if (directed) |
| 1304 | chan_no = 0; | 1311 | chandef.chan = NULL; |
| 1305 | else | 1312 | else |
| 1306 | chan_no = ieee80211_frequency_to_channel(chan->center_freq); | 1313 | chandef.chan = chan; |
| 1307 | 1314 | ||
| 1308 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1315 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
| 1309 | ssid, ssid_len, 100 + ie_len); | 1316 | ssid, ssid_len, 100 + ie_len); |
| @@ -1313,7 +1320,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
| 1313 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), | 1320 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), |
| 1314 | skb_tailroom(skb), | 1321 | skb_tailroom(skb), |
| 1315 | ie, ie_len, chan->band, | 1322 | ie, ie_len, chan->band, |
| 1316 | ratemask, chan_no); | 1323 | ratemask, &chandef); |
| 1317 | skb_put(skb, ies_len); | 1324 | skb_put(skb, ies_len); |
| 1318 | 1325 | ||
| 1319 | if (dst) { | 1326 | if (dst) { |
| @@ -1347,16 +1354,19 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
| 1347 | } | 1354 | } |
| 1348 | } | 1355 | } |
| 1349 | 1356 | ||
| 1350 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1357 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, |
| 1351 | struct ieee802_11_elems *elems, | 1358 | struct ieee802_11_elems *elems, |
| 1352 | enum ieee80211_band band, u32 *basic_rates) | 1359 | enum ieee80211_band band, u32 *basic_rates) |
| 1353 | { | 1360 | { |
| 1354 | struct ieee80211_supported_band *sband; | 1361 | struct ieee80211_supported_band *sband; |
| 1355 | struct ieee80211_rate *bitrates; | 1362 | struct ieee80211_rate *bitrates; |
| 1356 | size_t num_rates; | 1363 | size_t num_rates; |
| 1357 | u32 supp_rates; | 1364 | u32 supp_rates, rate_flags; |
| 1358 | int i, j; | 1365 | int i, j, shift; |
| 1359 | sband = local->hw.wiphy->bands[band]; | 1366 | sband = sdata->local->hw.wiphy->bands[band]; |
| 1367 | |||
| 1368 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
| 1369 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
| 1360 | 1370 | ||
| 1361 | if (WARN_ON(!sband)) | 1371 | if (WARN_ON(!sband)) |
| 1362 | return 1; | 1372 | return 1; |
| @@ -1381,7 +1391,15 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
| 1381 | continue; | 1391 | continue; |
| 1382 | 1392 | ||
| 1383 | for (j = 0; j < num_rates; j++) { | 1393 | for (j = 0; j < num_rates; j++) { |
| 1384 | if (bitrates[j].bitrate == own_rate) { | 1394 | int brate; |
| 1395 | if ((rate_flags & sband->bitrates[j].flags) | ||
| 1396 | != rate_flags) | ||
| 1397 | continue; | ||
| 1398 | |||
| 1399 | brate = DIV_ROUND_UP(sband->bitrates[j].bitrate, | ||
| 1400 | 1 << shift); | ||
| 1401 | |||
| 1402 | if (brate == own_rate) { | ||
| 1385 | supp_rates |= BIT(j); | 1403 | supp_rates |= BIT(j); |
| 1386 | if (basic_rates && is_basic) | 1404 | if (basic_rates && is_basic) |
| 1387 | *basic_rates |= BIT(j); | 1405 | *basic_rates |= BIT(j); |
| @@ -1435,8 +1453,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1435 | local->resuming = true; | 1453 | local->resuming = true; |
| 1436 | 1454 | ||
| 1437 | if (local->wowlan) { | 1455 | if (local->wowlan) { |
| 1438 | local->wowlan = false; | ||
| 1439 | res = drv_resume(local); | 1456 | res = drv_resume(local); |
| 1457 | local->wowlan = false; | ||
| 1440 | if (res < 0) { | 1458 | if (res < 0) { |
| 1441 | local->resuming = false; | 1459 | local->resuming = false; |
| 1442 | return res; | 1460 | return res; |
| @@ -2004,18 +2022,56 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, | |||
| 2004 | cfg80211_chandef_create(chandef, control_chan, channel_type); | 2022 | cfg80211_chandef_create(chandef, control_chan, channel_type); |
| 2005 | } | 2023 | } |
| 2006 | 2024 | ||
| 2025 | int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, | ||
| 2026 | const struct ieee80211_supported_band *sband, | ||
| 2027 | const u8 *srates, int srates_len, u32 *rates) | ||
| 2028 | { | ||
| 2029 | u32 rate_flags = ieee80211_chandef_rate_flags(chandef); | ||
| 2030 | int shift = ieee80211_chandef_get_shift(chandef); | ||
| 2031 | struct ieee80211_rate *br; | ||
| 2032 | int brate, rate, i, j, count = 0; | ||
| 2033 | |||
| 2034 | *rates = 0; | ||
| 2035 | |||
| 2036 | for (i = 0; i < srates_len; i++) { | ||
| 2037 | rate = srates[i] & 0x7f; | ||
| 2038 | |||
| 2039 | for (j = 0; j < sband->n_bitrates; j++) { | ||
| 2040 | br = &sband->bitrates[j]; | ||
| 2041 | if ((rate_flags & br->flags) != rate_flags) | ||
| 2042 | continue; | ||
| 2043 | |||
| 2044 | brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); | ||
| 2045 | if (brate == rate) { | ||
| 2046 | *rates |= BIT(j); | ||
| 2047 | count++; | ||
| 2048 | break; | ||
| 2049 | } | ||
| 2050 | } | ||
| 2051 | } | ||
| 2052 | return count; | ||
| 2053 | } | ||
| 2054 | |||
| 2007 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 2055 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
| 2008 | struct sk_buff *skb, bool need_basic, | 2056 | struct sk_buff *skb, bool need_basic, |
| 2009 | enum ieee80211_band band) | 2057 | enum ieee80211_band band) |
| 2010 | { | 2058 | { |
| 2011 | struct ieee80211_local *local = sdata->local; | 2059 | struct ieee80211_local *local = sdata->local; |
| 2012 | struct ieee80211_supported_band *sband; | 2060 | struct ieee80211_supported_band *sband; |
| 2013 | int rate; | 2061 | int rate, shift; |
| 2014 | u8 i, rates, *pos; | 2062 | u8 i, rates, *pos; |
| 2015 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 2063 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
| 2064 | u32 rate_flags; | ||
| 2016 | 2065 | ||
| 2066 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
| 2067 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
| 2017 | sband = local->hw.wiphy->bands[band]; | 2068 | sband = local->hw.wiphy->bands[band]; |
| 2018 | rates = sband->n_bitrates; | 2069 | rates = 0; |
| 2070 | for (i = 0; i < sband->n_bitrates; i++) { | ||
| 2071 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
| 2072 | continue; | ||
| 2073 | rates++; | ||
| 2074 | } | ||
| 2019 | if (rates > 8) | 2075 | if (rates > 8) |
| 2020 | rates = 8; | 2076 | rates = 8; |
| 2021 | 2077 | ||
| @@ -2027,10 +2083,15 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
| 2027 | *pos++ = rates; | 2083 | *pos++ = rates; |
| 2028 | for (i = 0; i < rates; i++) { | 2084 | for (i = 0; i < rates; i++) { |
| 2029 | u8 basic = 0; | 2085 | u8 basic = 0; |
| 2086 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
| 2087 | continue; | ||
| 2088 | |||
| 2030 | if (need_basic && basic_rates & BIT(i)) | 2089 | if (need_basic && basic_rates & BIT(i)) |
| 2031 | basic = 0x80; | 2090 | basic = 0x80; |
| 2032 | rate = sband->bitrates[i].bitrate; | 2091 | rate = sband->bitrates[i].bitrate; |
| 2033 | *pos++ = basic | (u8) (rate / 5); | 2092 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
| 2093 | 5 * (1 << shift)); | ||
| 2094 | *pos++ = basic | (u8) rate; | ||
| 2034 | } | 2095 | } |
| 2035 | 2096 | ||
| 2036 | return 0; | 2097 | return 0; |
| @@ -2042,12 +2103,22 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
| 2042 | { | 2103 | { |
| 2043 | struct ieee80211_local *local = sdata->local; | 2104 | struct ieee80211_local *local = sdata->local; |
| 2044 | struct ieee80211_supported_band *sband; | 2105 | struct ieee80211_supported_band *sband; |
| 2045 | int rate; | 2106 | int rate, skip, shift; |
| 2046 | u8 i, exrates, *pos; | 2107 | u8 i, exrates, *pos; |
| 2047 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 2108 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
| 2109 | u32 rate_flags; | ||
| 2110 | |||
| 2111 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
| 2112 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
| 2048 | 2113 | ||
| 2049 | sband = local->hw.wiphy->bands[band]; | 2114 | sband = local->hw.wiphy->bands[band]; |
| 2050 | exrates = sband->n_bitrates; | 2115 | exrates = 0; |
| 2116 | for (i = 0; i < sband->n_bitrates; i++) { | ||
| 2117 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
| 2118 | continue; | ||
| 2119 | exrates++; | ||
| 2120 | } | ||
| 2121 | |||
| 2051 | if (exrates > 8) | 2122 | if (exrates > 8) |
| 2052 | exrates -= 8; | 2123 | exrates -= 8; |
| 2053 | else | 2124 | else |
| @@ -2060,12 +2131,19 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
| 2060 | pos = skb_put(skb, exrates + 2); | 2131 | pos = skb_put(skb, exrates + 2); |
| 2061 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 2132 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
| 2062 | *pos++ = exrates; | 2133 | *pos++ = exrates; |
| 2134 | skip = 0; | ||
| 2063 | for (i = 8; i < sband->n_bitrates; i++) { | 2135 | for (i = 8; i < sband->n_bitrates; i++) { |
| 2064 | u8 basic = 0; | 2136 | u8 basic = 0; |
| 2137 | if ((rate_flags & sband->bitrates[i].flags) | ||
| 2138 | != rate_flags) | ||
| 2139 | continue; | ||
| 2140 | if (skip++ < 8) | ||
| 2141 | continue; | ||
| 2065 | if (need_basic && basic_rates & BIT(i)) | 2142 | if (need_basic && basic_rates & BIT(i)) |
| 2066 | basic = 0x80; | 2143 | basic = 0x80; |
| 2067 | rate = sband->bitrates[i].bitrate; | 2144 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
| 2068 | *pos++ = basic | (u8) (rate / 5); | 2145 | 5 * (1 << shift)); |
| 2146 | *pos++ = basic | (u8) rate; | ||
| 2069 | } | 2147 | } |
| 2070 | } | 2148 | } |
| 2071 | return 0; | 2149 | return 0; |
| @@ -2149,9 +2227,17 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
| 2149 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2227 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 2150 | } else { | 2228 | } else { |
| 2151 | struct ieee80211_supported_band *sband; | 2229 | struct ieee80211_supported_band *sband; |
| 2230 | int shift = 0; | ||
| 2231 | int bitrate; | ||
| 2232 | |||
| 2233 | if (status->flag & RX_FLAG_10MHZ) | ||
| 2234 | shift = 1; | ||
| 2235 | if (status->flag & RX_FLAG_5MHZ) | ||
| 2236 | shift = 2; | ||
| 2152 | 2237 | ||
| 2153 | sband = local->hw.wiphy->bands[status->band]; | 2238 | sband = local->hw.wiphy->bands[status->band]; |
| 2154 | ri.legacy = sband->bitrates[status->rate_idx].bitrate; | 2239 | bitrate = sband->bitrates[status->rate_idx].bitrate; |
| 2240 | ri.legacy = DIV_ROUND_UP(bitrate, (1 << shift)); | ||
| 2155 | } | 2241 | } |
| 2156 | 2242 | ||
| 2157 | rate = cfg80211_calculate_bitrate(&ri); | 2243 | rate = cfg80211_calculate_bitrate(&ri); |
