diff options
author | Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de> | 2012-01-28 11:25:33 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-30 15:48:26 -0500 |
commit | 19468413e8d98d44be8daf0acaf8d576dfc53fa2 (patch) | |
tree | 99d7df720566824c4588ccff03c65e60c381e60d /net/mac80211 | |
parent | 24db78c05b1e3ccb5a78aedd17aa1008c91dab5a (diff) |
mac80211: add support for mcs masks
* Handle MCS masks set by the user.
* Match rates provided by the rate control algorithm to the mask set,
also in HT mode, and switch back to legacy mode if necessary.
* add debugfs files to observate the rate selection
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 5 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 34 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/iface.c | 7 | ||||
-rw-r--r-- | net/mac80211/rate.c | 124 | ||||
-rw-r--r-- | net/mac80211/tx.c | 5 |
6 files changed, 167 insertions, 9 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index dc7420441574..d15ba0d0de94 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1902,8 +1902,11 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1902 | return ret; | 1902 | return ret; |
1903 | } | 1903 | } |
1904 | 1904 | ||
1905 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | 1905 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1906 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; | 1906 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
1907 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, | ||
1908 | sizeof(mask->control[i].mcs)); | ||
1909 | } | ||
1907 | 1910 | ||
1908 | return 0; | 1911 | return 0; |
1909 | } | 1912 | } |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 81d12e65a23c..510ed1dab3c7 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -87,6 +87,21 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
87 | #define IEEE80211_IF_FMT_SIZE(name, field) \ | 87 | #define IEEE80211_IF_FMT_SIZE(name, field) \ |
88 | IEEE80211_IF_FMT(name, field, "%zd\n") | 88 | IEEE80211_IF_FMT(name, field, "%zd\n") |
89 | 89 | ||
90 | #define IEEE80211_IF_FMT_HEXARRAY(name, field) \ | ||
91 | static ssize_t ieee80211_if_fmt_##name( \ | ||
92 | const struct ieee80211_sub_if_data *sdata, \ | ||
93 | char *buf, int buflen) \ | ||
94 | { \ | ||
95 | char *p = buf; \ | ||
96 | int i; \ | ||
97 | for (i = 0; i < sizeof(sdata->field); i++) { \ | ||
98 | p += scnprintf(p, buflen + buf - p, "%.2x ", \ | ||
99 | sdata->field[i]); \ | ||
100 | } \ | ||
101 | p += scnprintf(p, buflen + buf - p, "\n"); \ | ||
102 | return p - buf; \ | ||
103 | } | ||
104 | |||
90 | #define IEEE80211_IF_FMT_ATOMIC(name, field) \ | 105 | #define IEEE80211_IF_FMT_ATOMIC(name, field) \ |
91 | static ssize_t ieee80211_if_fmt_##name( \ | 106 | static ssize_t ieee80211_if_fmt_##name( \ |
92 | const struct ieee80211_sub_if_data *sdata, \ | 107 | const struct ieee80211_sub_if_data *sdata, \ |
@@ -148,6 +163,11 @@ IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], | |||
148 | HEX); | 163 | HEX); |
149 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | 164 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], |
150 | HEX); | 165 | HEX); |
166 | IEEE80211_IF_FILE(rc_rateidx_mcs_mask_2ghz, | ||
167 | rc_rateidx_mcs_mask[IEEE80211_BAND_2GHZ], HEXARRAY); | ||
168 | IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz, | ||
169 | rc_rateidx_mcs_mask[IEEE80211_BAND_5GHZ], HEXARRAY); | ||
170 | |||
151 | IEEE80211_IF_FILE(flags, flags, HEX); | 171 | IEEE80211_IF_FILE(flags, flags, HEX); |
152 | IEEE80211_IF_FILE(state, state, LHEX); | 172 | IEEE80211_IF_FILE(state, state, LHEX); |
153 | IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); | 173 | IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); |
@@ -442,6 +462,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
442 | DEBUGFS_ADD(channel_type); | 462 | DEBUGFS_ADD(channel_type); |
443 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 463 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
444 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 464 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
465 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
466 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
445 | 467 | ||
446 | DEBUGFS_ADD(bssid); | 468 | DEBUGFS_ADD(bssid); |
447 | DEBUGFS_ADD(aid); | 469 | DEBUGFS_ADD(aid); |
@@ -459,6 +481,8 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
459 | DEBUGFS_ADD(channel_type); | 481 | DEBUGFS_ADD(channel_type); |
460 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 482 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
461 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 483 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
484 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
485 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
462 | 486 | ||
463 | DEBUGFS_ADD(num_sta_authorized); | 487 | DEBUGFS_ADD(num_sta_authorized); |
464 | DEBUGFS_ADD(num_sta_ps); | 488 | DEBUGFS_ADD(num_sta_ps); |
@@ -469,6 +493,12 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
469 | 493 | ||
470 | static void add_ibss_files(struct ieee80211_sub_if_data *sdata) | 494 | static void add_ibss_files(struct ieee80211_sub_if_data *sdata) |
471 | { | 495 | { |
496 | DEBUGFS_ADD(channel_type); | ||
497 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | ||
498 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | ||
499 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
500 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
501 | |||
472 | DEBUGFS_ADD_MODE(tsf, 0600); | 502 | DEBUGFS_ADD_MODE(tsf, 0600); |
473 | } | 503 | } |
474 | 504 | ||
@@ -480,6 +510,8 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) | |||
480 | DEBUGFS_ADD(channel_type); | 510 | DEBUGFS_ADD(channel_type); |
481 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 511 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
482 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 512 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
513 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
514 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
483 | 515 | ||
484 | DEBUGFS_ADD(peer); | 516 | DEBUGFS_ADD(peer); |
485 | } | 517 | } |
@@ -492,6 +524,8 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
492 | DEBUGFS_ADD(channel_type); | 524 | DEBUGFS_ADD(channel_type); |
493 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 525 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
494 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 526 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
527 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
528 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
495 | } | 529 | } |
496 | 530 | ||
497 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 531 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ca6486b941b6..d47e8c110b16 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -646,6 +646,7 @@ struct ieee80211_sub_if_data { | |||
646 | 646 | ||
647 | /* bitmap of allowed (non-MCS) rate indexes for rate control */ | 647 | /* bitmap of allowed (non-MCS) rate indexes for rate control */ |
648 | u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; | 648 | u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; |
649 | u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN]; | ||
649 | 650 | ||
650 | union { | 651 | union { |
651 | struct ieee80211_if_ap ap; | 652 | struct ieee80211_if_ap ap; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6b0d70e960d4..c33feede5dca 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1181,6 +1181,13 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1181 | sband = local->hw.wiphy->bands[i]; | 1181 | sband = local->hw.wiphy->bands[i]; |
1182 | sdata->rc_rateidx_mask[i] = | 1182 | sdata->rc_rateidx_mask[i] = |
1183 | sband ? (1 << sband->n_bitrates) - 1 : 0; | 1183 | sband ? (1 << sband->n_bitrates) - 1 : 0; |
1184 | if (sband) | ||
1185 | memcpy(sdata->rc_rateidx_mcs_mask[i], | ||
1186 | sband->ht_cap.mcs.rx_mask, | ||
1187 | sizeof(sdata->rc_rateidx_mcs_mask[i])); | ||
1188 | else | ||
1189 | memset(sdata->rc_rateidx_mcs_mask[i], 0, | ||
1190 | sizeof(sdata->rc_rateidx_mcs_mask[i])); | ||
1184 | } | 1191 | } |
1185 | 1192 | ||
1186 | /* setup type-dependent data */ | 1193 | /* setup type-dependent data */ |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index a21110aecd1a..3fef26d8898a 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -289,8 +289,8 @@ bool rate_control_send_low(struct ieee80211_sta *sta, | |||
289 | } | 289 | } |
290 | EXPORT_SYMBOL(rate_control_send_low); | 290 | EXPORT_SYMBOL(rate_control_send_low); |
291 | 291 | ||
292 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | 292 | static bool rate_idx_match_legacy_mask(struct ieee80211_tx_rate *rate, |
293 | int n_bitrates, u32 mask) | 293 | int n_bitrates, u32 mask) |
294 | { | 294 | { |
295 | int j; | 295 | int j; |
296 | 296 | ||
@@ -299,7 +299,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
299 | if (mask & (1 << j)) { | 299 | if (mask & (1 << j)) { |
300 | /* Okay, found a suitable rate. Use it. */ | 300 | /* Okay, found a suitable rate. Use it. */ |
301 | rate->idx = j; | 301 | rate->idx = j; |
302 | return; | 302 | return true; |
303 | } | 303 | } |
304 | } | 304 | } |
305 | 305 | ||
@@ -308,6 +308,112 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
308 | if (mask & (1 << j)) { | 308 | if (mask & (1 << j)) { |
309 | /* Okay, found a suitable rate. Use it. */ | 309 | /* Okay, found a suitable rate. Use it. */ |
310 | rate->idx = j; | 310 | rate->idx = j; |
311 | return true; | ||
312 | } | ||
313 | } | ||
314 | return false; | ||
315 | } | ||
316 | |||
317 | static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate, | ||
318 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) | ||
319 | { | ||
320 | int i, j; | ||
321 | int ridx, rbit; | ||
322 | |||
323 | ridx = rate->idx / 8; | ||
324 | rbit = rate->idx % 8; | ||
325 | |||
326 | /* sanity check */ | ||
327 | if (ridx < 0 || ridx > IEEE80211_HT_MCS_MASK_LEN) | ||
328 | return false; | ||
329 | |||
330 | /* See whether the selected rate or anything below it is allowed. */ | ||
331 | for (i = ridx; i >= 0; i--) { | ||
332 | for (j = rbit; j >= 0; j--) | ||
333 | if (mcs_mask[i] & BIT(j)) { | ||
334 | rate->idx = i * 8 + j; | ||
335 | return true; | ||
336 | } | ||
337 | rbit = 7; | ||
338 | } | ||
339 | |||
340 | /* Try to find a higher rate that would be allowed */ | ||
341 | ridx = (rate->idx + 1) / 8; | ||
342 | rbit = (rate->idx + 1) % 8; | ||
343 | |||
344 | for (i = ridx; i < IEEE80211_HT_MCS_MASK_LEN; i++) { | ||
345 | for (j = rbit; j < 8; j++) | ||
346 | if (mcs_mask[i] & BIT(j)) { | ||
347 | rate->idx = i * 8 + j; | ||
348 | return true; | ||
349 | } | ||
350 | rbit = 0; | ||
351 | } | ||
352 | return false; | ||
353 | } | ||
354 | |||
355 | |||
356 | |||
357 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | ||
358 | struct ieee80211_tx_rate_control *txrc, | ||
359 | u32 mask, | ||
360 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) | ||
361 | { | ||
362 | struct ieee80211_tx_rate alt_rate; | ||
363 | |||
364 | /* handle HT rates */ | ||
365 | if (rate->flags & IEEE80211_TX_RC_MCS) { | ||
366 | if (rate_idx_match_mcs_mask(rate, mcs_mask)) | ||
367 | return; | ||
368 | |||
369 | /* also try the legacy rates. */ | ||
370 | alt_rate.idx = 0; | ||
371 | /* keep protection flags */ | ||
372 | alt_rate.flags = rate->flags & | ||
373 | (IEEE80211_TX_RC_USE_RTS_CTS | | ||
374 | IEEE80211_TX_RC_USE_CTS_PROTECT | | ||
375 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); | ||
376 | alt_rate.count = rate->count; | ||
377 | if (rate_idx_match_legacy_mask(&alt_rate, | ||
378 | txrc->sband->n_bitrates, | ||
379 | mask)) { | ||
380 | *rate = alt_rate; | ||
381 | return; | ||
382 | } | ||
383 | } else { | ||
384 | struct sk_buff *skb = txrc->skb; | ||
385 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
386 | __le16 fc; | ||
387 | |||
388 | /* handle legacy rates */ | ||
389 | if (rate_idx_match_legacy_mask(rate, txrc->sband->n_bitrates, | ||
390 | mask)) | ||
391 | return; | ||
392 | |||
393 | /* if HT BSS, and we handle a data frame, also try HT rates */ | ||
394 | if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT) | ||
395 | return; | ||
396 | |||
397 | fc = hdr->frame_control; | ||
398 | if (!ieee80211_is_data(fc)) | ||
399 | return; | ||
400 | |||
401 | alt_rate.idx = 0; | ||
402 | /* keep protection flags */ | ||
403 | alt_rate.flags = rate->flags & | ||
404 | (IEEE80211_TX_RC_USE_RTS_CTS | | ||
405 | IEEE80211_TX_RC_USE_CTS_PROTECT | | ||
406 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); | ||
407 | alt_rate.count = rate->count; | ||
408 | |||
409 | alt_rate.flags |= IEEE80211_TX_RC_MCS; | ||
410 | |||
411 | if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) || | ||
412 | (txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS)) | ||
413 | alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
414 | |||
415 | if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { | ||
416 | *rate = alt_rate; | ||
311 | return; | 417 | return; |
312 | } | 418 | } |
313 | } | 419 | } |
@@ -331,6 +437,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
331 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | 437 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
332 | int i; | 438 | int i; |
333 | u32 mask; | 439 | u32 mask; |
440 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; | ||
334 | 441 | ||
335 | if (sta) { | 442 | if (sta) { |
336 | ista = &sta->sta; | 443 | ista = &sta->sta; |
@@ -354,10 +461,14 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
354 | * the common case. | 461 | * the common case. |
355 | */ | 462 | */ |
356 | mask = sdata->rc_rateidx_mask[info->band]; | 463 | mask = sdata->rc_rateidx_mask[info->band]; |
464 | memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band], | ||
465 | sizeof(mcs_mask)); | ||
357 | if (mask != (1 << txrc->sband->n_bitrates) - 1) { | 466 | if (mask != (1 << txrc->sband->n_bitrates) - 1) { |
358 | if (sta) { | 467 | if (sta) { |
359 | /* Filter out rates that the STA does not support */ | 468 | /* Filter out rates that the STA does not support */ |
360 | mask &= sta->sta.supp_rates[info->band]; | 469 | mask &= sta->sta.supp_rates[info->band]; |
470 | for (i = 0; i < sizeof(mcs_mask); i++) | ||
471 | mcs_mask[i] &= sta->sta.ht_cap.mcs.rx_mask[i]; | ||
361 | } | 472 | } |
362 | /* | 473 | /* |
363 | * Make sure the rate index selected for each TX rate is | 474 | * Make sure the rate index selected for each TX rate is |
@@ -368,11 +479,8 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
368 | /* Skip invalid rates */ | 479 | /* Skip invalid rates */ |
369 | if (info->control.rates[i].idx < 0) | 480 | if (info->control.rates[i].idx < 0) |
370 | break; | 481 | break; |
371 | /* Rate masking supports only legacy rates for now */ | 482 | rate_idx_match_mask(&info->control.rates[i], txrc, |
372 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) | 483 | mask, mcs_mask); |
373 | continue; | ||
374 | rate_idx_match_mask(&info->control.rates[i], | ||
375 | txrc->sband->n_bitrates, mask); | ||
376 | } | 484 | } |
377 | } | 485 | } |
378 | 486 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e05667cd5e76..1be0ca2b5936 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -635,6 +635,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
635 | txrc.max_rate_idx = -1; | 635 | txrc.max_rate_idx = -1; |
636 | else | 636 | else |
637 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 637 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
638 | memcpy(txrc.rate_idx_mcs_mask, | ||
639 | tx->sdata->rc_rateidx_mcs_mask[tx->channel->band], | ||
640 | sizeof(txrc.rate_idx_mcs_mask)); | ||
638 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || | 641 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || |
639 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || | 642 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || |
640 | tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); | 643 | tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); |
@@ -2431,6 +2434,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2431 | txrc.max_rate_idx = -1; | 2434 | txrc.max_rate_idx = -1; |
2432 | else | 2435 | else |
2433 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 2436 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
2437 | memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band], | ||
2438 | sizeof(txrc.rate_idx_mcs_mask)); | ||
2434 | txrc.bss = true; | 2439 | txrc.bss = true; |
2435 | rate_control_get_rate(sdata, NULL, &txrc); | 2440 | rate_control_get_rate(sdata, NULL, &txrc); |
2436 | 2441 | ||