diff options
author | Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> | 2015-08-06 17:47:31 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-08-14 11:49:50 -0400 |
commit | 90c66bd2232ae6d3c88c1f3378e3028fded642b3 (patch) | |
tree | 9271c2f858f7a083fab130de3309a3bfd80762ad /net/mac80211 | |
parent | 35225eb7a5589407299033bfa7e1ac723b17e2b5 (diff) |
mac80211: remove ieee80211_tx_rate dependency in rate mask code
Remove ieee80211_tx_rate dependency in rate_idx_match_legacy_mask(),
rate_idx_match_mcs_mask() and rate_idx_match_mask() in order to use the
previous logic to define a ratemask in rate_control_set_rates() for
station rate table. Moreover move rate mask definition logic in
rate_control_cap_mask()
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/rate.c | 139 |
1 files changed, 71 insertions, 68 deletions
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 4f02e07ecc7b..4f61ca026ecc 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -353,39 +353,37 @@ bool rate_control_send_low(struct ieee80211_sta *pubsta, | |||
353 | } | 353 | } |
354 | EXPORT_SYMBOL(rate_control_send_low); | 354 | EXPORT_SYMBOL(rate_control_send_low); |
355 | 355 | ||
356 | static bool rate_idx_match_legacy_mask(struct ieee80211_tx_rate *rate, | 356 | static bool rate_idx_match_legacy_mask(s8 *rate_idx, int n_bitrates, u32 mask) |
357 | int n_bitrates, u32 mask) | ||
358 | { | 357 | { |
359 | int j; | 358 | int j; |
360 | 359 | ||
361 | /* See whether the selected rate or anything below it is allowed. */ | 360 | /* See whether the selected rate or anything below it is allowed. */ |
362 | for (j = rate->idx; j >= 0; j--) { | 361 | for (j = *rate_idx; j >= 0; j--) { |
363 | if (mask & (1 << j)) { | 362 | if (mask & (1 << j)) { |
364 | /* Okay, found a suitable rate. Use it. */ | 363 | /* Okay, found a suitable rate. Use it. */ |
365 | rate->idx = j; | 364 | *rate_idx = j; |
366 | return true; | 365 | return true; |
367 | } | 366 | } |
368 | } | 367 | } |
369 | 368 | ||
370 | /* Try to find a higher rate that would be allowed */ | 369 | /* Try to find a higher rate that would be allowed */ |
371 | for (j = rate->idx + 1; j < n_bitrates; j++) { | 370 | for (j = *rate_idx + 1; j < n_bitrates; j++) { |
372 | if (mask & (1 << j)) { | 371 | if (mask & (1 << j)) { |
373 | /* Okay, found a suitable rate. Use it. */ | 372 | /* Okay, found a suitable rate. Use it. */ |
374 | rate->idx = j; | 373 | *rate_idx = j; |
375 | return true; | 374 | return true; |
376 | } | 375 | } |
377 | } | 376 | } |
378 | return false; | 377 | return false; |
379 | } | 378 | } |
380 | 379 | ||
381 | static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate, | 380 | static bool rate_idx_match_mcs_mask(s8 *rate_idx, u8 *mcs_mask) |
382 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) | ||
383 | { | 381 | { |
384 | int i, j; | 382 | int i, j; |
385 | int ridx, rbit; | 383 | int ridx, rbit; |
386 | 384 | ||
387 | ridx = rate->idx / 8; | 385 | ridx = *rate_idx / 8; |
388 | rbit = rate->idx % 8; | 386 | rbit = *rate_idx % 8; |
389 | 387 | ||
390 | /* sanity check */ | 388 | /* sanity check */ |
391 | if (ridx < 0 || ridx >= IEEE80211_HT_MCS_MASK_LEN) | 389 | if (ridx < 0 || ridx >= IEEE80211_HT_MCS_MASK_LEN) |
@@ -395,20 +393,20 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate, | |||
395 | for (i = ridx; i >= 0; i--) { | 393 | for (i = ridx; i >= 0; i--) { |
396 | for (j = rbit; j >= 0; j--) | 394 | for (j = rbit; j >= 0; j--) |
397 | if (mcs_mask[i] & BIT(j)) { | 395 | if (mcs_mask[i] & BIT(j)) { |
398 | rate->idx = i * 8 + j; | 396 | *rate_idx = i * 8 + j; |
399 | return true; | 397 | return true; |
400 | } | 398 | } |
401 | rbit = 7; | 399 | rbit = 7; |
402 | } | 400 | } |
403 | 401 | ||
404 | /* Try to find a higher rate that would be allowed */ | 402 | /* Try to find a higher rate that would be allowed */ |
405 | ridx = (rate->idx + 1) / 8; | 403 | ridx = (*rate_idx + 1) / 8; |
406 | rbit = (rate->idx + 1) % 8; | 404 | rbit = (*rate_idx + 1) % 8; |
407 | 405 | ||
408 | for (i = ridx; i < IEEE80211_HT_MCS_MASK_LEN; i++) { | 406 | for (i = ridx; i < IEEE80211_HT_MCS_MASK_LEN; i++) { |
409 | for (j = rbit; j < 8; j++) | 407 | for (j = rbit; j < 8; j++) |
410 | if (mcs_mask[i] & BIT(j)) { | 408 | if (mcs_mask[i] & BIT(j)) { |
411 | rate->idx = i * 8 + j; | 409 | *rate_idx = i * 8 + j; |
412 | return true; | 410 | return true; |
413 | } | 411 | } |
414 | rbit = 0; | 412 | rbit = 0; |
@@ -418,35 +416,30 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate, | |||
418 | 416 | ||
419 | 417 | ||
420 | 418 | ||
421 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | 419 | static void rate_idx_match_mask(s8 *rate_idx, u16 *rate_flags, |
422 | struct ieee80211_supported_band *sband, | 420 | struct ieee80211_supported_band *sband, |
423 | enum nl80211_chan_width chan_width, | 421 | enum nl80211_chan_width chan_width, |
424 | u32 mask, | 422 | u32 mask, |
425 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) | 423 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) |
426 | { | 424 | { |
427 | struct ieee80211_tx_rate alt_rate; | ||
428 | |||
429 | /* handle HT rates */ | 425 | /* handle HT rates */ |
430 | if (rate->flags & IEEE80211_TX_RC_MCS) { | 426 | if (*rate_flags & IEEE80211_TX_RC_MCS) { |
431 | if (rate_idx_match_mcs_mask(rate, mcs_mask)) | 427 | if (rate_idx_match_mcs_mask(rate_idx, mcs_mask)) |
432 | return; | 428 | return; |
433 | 429 | ||
434 | /* also try the legacy rates. */ | 430 | /* also try the legacy rates. */ |
435 | alt_rate.idx = 0; | 431 | *rate_idx = 0; |
436 | /* keep protection flags */ | 432 | /* keep protection flags */ |
437 | alt_rate.flags = rate->flags & | 433 | *rate_flags &= (IEEE80211_TX_RC_USE_RTS_CTS | |
438 | (IEEE80211_TX_RC_USE_RTS_CTS | | 434 | IEEE80211_TX_RC_USE_CTS_PROTECT | |
439 | IEEE80211_TX_RC_USE_CTS_PROTECT | | 435 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); |
440 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); | 436 | if (rate_idx_match_legacy_mask(rate_idx, sband->n_bitrates, |
441 | alt_rate.count = rate->count; | 437 | mask)) |
442 | if (rate_idx_match_legacy_mask(&alt_rate, | ||
443 | sband->n_bitrates, mask)) { | ||
444 | *rate = alt_rate; | ||
445 | return; | 438 | return; |
446 | } | 439 | } else if (!(*rate_flags & IEEE80211_TX_RC_VHT_MCS)) { |
447 | } else if (!(rate->flags & IEEE80211_TX_RC_VHT_MCS)) { | ||
448 | /* handle legacy rates */ | 440 | /* handle legacy rates */ |
449 | if (rate_idx_match_legacy_mask(rate, sband->n_bitrates, mask)) | 441 | if (rate_idx_match_legacy_mask(rate_idx, sband->n_bitrates, |
442 | mask)) | ||
450 | return; | 443 | return; |
451 | 444 | ||
452 | /* if HT BSS, and we handle a data frame, also try HT rates */ | 445 | /* if HT BSS, and we handle a data frame, also try HT rates */ |
@@ -459,23 +452,19 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
459 | break; | 452 | break; |
460 | } | 453 | } |
461 | 454 | ||
462 | alt_rate.idx = 0; | 455 | *rate_idx = 0; |
463 | /* keep protection flags */ | 456 | /* keep protection flags */ |
464 | alt_rate.flags = rate->flags & | 457 | *rate_flags &= (IEEE80211_TX_RC_USE_RTS_CTS | |
465 | (IEEE80211_TX_RC_USE_RTS_CTS | | 458 | IEEE80211_TX_RC_USE_CTS_PROTECT | |
466 | IEEE80211_TX_RC_USE_CTS_PROTECT | | 459 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); |
467 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); | ||
468 | alt_rate.count = rate->count; | ||
469 | 460 | ||
470 | alt_rate.flags |= IEEE80211_TX_RC_MCS; | 461 | *rate_flags |= IEEE80211_TX_RC_MCS; |
471 | 462 | ||
472 | if (chan_width == NL80211_CHAN_WIDTH_40) | 463 | if (chan_width == NL80211_CHAN_WIDTH_40) |
473 | alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | 464 | *rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
474 | 465 | ||
475 | if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { | 466 | if (rate_idx_match_mcs_mask(rate_idx, mcs_mask)) |
476 | *rate = alt_rate; | ||
477 | return; | 467 | return; |
478 | } | ||
479 | } | 468 | } |
480 | 469 | ||
481 | /* | 470 | /* |
@@ -628,6 +617,40 @@ static void rate_control_fill_sta_table(struct ieee80211_sta *sta, | |||
628 | } | 617 | } |
629 | } | 618 | } |
630 | 619 | ||
620 | static bool rate_control_cap_mask(struct ieee80211_sub_if_data *sdata, | ||
621 | struct ieee80211_supported_band *sband, | ||
622 | struct ieee80211_sta *sta, u32 *mask, | ||
623 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) | ||
624 | { | ||
625 | u32 i, flags; | ||
626 | |||
627 | *mask = sdata->rc_rateidx_mask[sband->band]; | ||
628 | flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
629 | for (i = 0; i < sband->n_bitrates; i++) { | ||
630 | if ((flags & sband->bitrates[i].flags) != flags) | ||
631 | *mask &= ~BIT(i); | ||
632 | } | ||
633 | |||
634 | if (*mask == (1 << sband->n_bitrates) - 1 && | ||
635 | !sdata->rc_has_mcs_mask[sband->band]) | ||
636 | return false; | ||
637 | |||
638 | if (sdata->rc_has_mcs_mask[sband->band]) | ||
639 | memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[sband->band], | ||
640 | IEEE80211_HT_MCS_MASK_LEN); | ||
641 | else | ||
642 | memset(mcs_mask, 0xff, IEEE80211_HT_MCS_MASK_LEN); | ||
643 | |||
644 | if (sta) { | ||
645 | /* Filter out rates that the STA does not support */ | ||
646 | *mask &= sta->supp_rates[sband->band]; | ||
647 | for (i = 0; i < sizeof(mcs_mask); i++) | ||
648 | mcs_mask[i] &= sta->ht_cap.mcs.rx_mask[i]; | ||
649 | } | ||
650 | |||
651 | return true; | ||
652 | } | ||
653 | |||
631 | static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | 654 | static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, |
632 | struct ieee80211_sta *sta, | 655 | struct ieee80211_sta *sta, |
633 | struct ieee80211_supported_band *sband, | 656 | struct ieee80211_supported_band *sband, |
@@ -636,9 +659,8 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | |||
636 | { | 659 | { |
637 | enum nl80211_chan_width chan_width; | 660 | enum nl80211_chan_width chan_width; |
638 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; | 661 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; |
639 | bool has_mcs_mask; | ||
640 | u32 mask; | 662 | u32 mask; |
641 | u32 rate_flags; | 663 | u16 rate_flags; |
642 | int i; | 664 | int i; |
643 | 665 | ||
644 | /* | 666 | /* |
@@ -646,30 +668,9 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | |||
646 | * default mask (allow all rates) is used to save some processing for | 668 | * default mask (allow all rates) is used to save some processing for |
647 | * the common case. | 669 | * the common case. |
648 | */ | 670 | */ |
649 | mask = sdata->rc_rateidx_mask[sband->band]; | 671 | if (!rate_control_cap_mask(sdata, sband, sta, &mask, mcs_mask)) |
650 | has_mcs_mask = sdata->rc_has_mcs_mask[sband->band]; | ||
651 | rate_flags = | ||
652 | ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
653 | for (i = 0; i < sband->n_bitrates; i++) | ||
654 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
655 | mask &= ~BIT(i); | ||
656 | |||
657 | if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask) | ||
658 | return; | 672 | return; |
659 | 673 | ||
660 | if (has_mcs_mask) | ||
661 | memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[sband->band], | ||
662 | sizeof(mcs_mask)); | ||
663 | else | ||
664 | memset(mcs_mask, 0xff, sizeof(mcs_mask)); | ||
665 | |||
666 | if (sta) { | ||
667 | /* Filter out rates that the STA does not support */ | ||
668 | mask &= sta->supp_rates[sband->band]; | ||
669 | for (i = 0; i < sizeof(mcs_mask); i++) | ||
670 | mcs_mask[i] &= sta->ht_cap.mcs.rx_mask[i]; | ||
671 | } | ||
672 | |||
673 | /* | 674 | /* |
674 | * Make sure the rate index selected for each TX rate is | 675 | * Make sure the rate index selected for each TX rate is |
675 | * included in the configured mask and change the rate indexes | 676 | * included in the configured mask and change the rate indexes |
@@ -681,8 +682,10 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | |||
681 | if (rates[i].idx < 0) | 682 | if (rates[i].idx < 0) |
682 | break; | 683 | break; |
683 | 684 | ||
684 | rate_idx_match_mask(&rates[i], sband, chan_width, mask, | 685 | rate_flags = rates[i].flags; |
685 | mcs_mask); | 686 | rate_idx_match_mask(&rates[i].idx, &rate_flags, sband, |
687 | chan_width, mask, mcs_mask); | ||
688 | rates[i].flags = rate_flags; | ||
686 | } | 689 | } |
687 | } | 690 | } |
688 | 691 | ||