diff options
Diffstat (limited to 'net/mac80211/rc80211_minstrel_ht.c')
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 138 |
1 files changed, 96 insertions, 42 deletions
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c5b465904e3b..333b5118be6d 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -259,7 +259,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
259 | } | 259 | } |
260 | } | 260 | } |
261 | 261 | ||
262 | /* try to sample up to half of the availble rates during each interval */ | 262 | /* try to sample up to half of the available rates during each interval */ |
263 | mi->sample_count *= 4; | 263 | mi->sample_count *= 4; |
264 | 264 | ||
265 | cur_prob = 0; | 265 | cur_prob = 0; |
@@ -371,7 +371,10 @@ minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, stru | |||
371 | if (likely(sta->ampdu_mlme.tid_tx[tid])) | 371 | if (likely(sta->ampdu_mlme.tid_tx[tid])) |
372 | return; | 372 | return; |
373 | 373 | ||
374 | ieee80211_start_tx_ba_session(pubsta, tid); | 374 | if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) |
375 | return; | ||
376 | |||
377 | ieee80211_start_tx_ba_session(pubsta, tid, 5000); | ||
375 | } | 378 | } |
376 | 379 | ||
377 | static void | 380 | static void |
@@ -397,8 +400,9 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
397 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 400 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
398 | return; | 401 | return; |
399 | 402 | ||
400 | if (!info->status.ampdu_len) { | 403 | if (!(info->flags & IEEE80211_TX_STAT_AMPDU)) { |
401 | info->status.ampdu_ack_len = 1; | 404 | info->status.ampdu_ack_len = |
405 | (info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0); | ||
402 | info->status.ampdu_len = 1; | 406 | info->status.ampdu_len = 1; |
403 | } | 407 | } |
404 | 408 | ||
@@ -406,15 +410,13 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
406 | mi->ampdu_len += info->status.ampdu_len; | 410 | mi->ampdu_len += info->status.ampdu_len; |
407 | 411 | ||
408 | if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { | 412 | if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { |
409 | mi->sample_wait = 4 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); | 413 | mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); |
410 | mi->sample_tries = 3; | 414 | mi->sample_tries = 2; |
411 | mi->sample_count--; | 415 | mi->sample_count--; |
412 | } | 416 | } |
413 | 417 | ||
414 | if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { | 418 | if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) |
415 | mi->sample_packets += info->status.ampdu_len; | 419 | mi->sample_packets += info->status.ampdu_len; |
416 | minstrel_next_sample_idx(mi); | ||
417 | } | ||
418 | 420 | ||
419 | for (i = 0; !last; i++) { | 421 | for (i = 0; !last; i++) { |
420 | last = (i == IEEE80211_TX_MAX_RATES - 1) || | 422 | last = (i == IEEE80211_TX_MAX_RATES - 1) || |
@@ -426,7 +428,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
426 | group = minstrel_ht_get_group_idx(&ar[i]); | 428 | group = minstrel_ht_get_group_idx(&ar[i]); |
427 | rate = &mi->groups[group].rates[ar[i].idx % 8]; | 429 | rate = &mi->groups[group].rates[ar[i].idx % 8]; |
428 | 430 | ||
429 | if (last && (info->flags & IEEE80211_TX_STAT_ACK)) | 431 | if (last) |
430 | rate->success += info->status.ampdu_ack_len; | 432 | rate->success += info->status.ampdu_ack_len; |
431 | 433 | ||
432 | rate->attempts += ar[i].count * info->status.ampdu_len; | 434 | rate->attempts += ar[i].count * info->status.ampdu_len; |
@@ -462,6 +464,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
462 | const struct mcs_group *group; | 464 | const struct mcs_group *group; |
463 | unsigned int tx_time, tx_time_rtscts, tx_time_data; | 465 | unsigned int tx_time, tx_time_rtscts, tx_time_data; |
464 | unsigned int cw = mp->cw_min; | 466 | unsigned int cw = mp->cw_min; |
467 | unsigned int ctime = 0; | ||
465 | unsigned int t_slot = 9; /* FIXME */ | 468 | unsigned int t_slot = 9; /* FIXME */ |
466 | unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len); | 469 | unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len); |
467 | 470 | ||
@@ -478,13 +481,27 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
478 | 481 | ||
479 | group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; | 482 | group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; |
480 | tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; | 483 | tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; |
481 | tx_time = 2 * (t_slot + mi->overhead + tx_time_data); | 484 | |
482 | tx_time_rtscts = 2 * (t_slot + mi->overhead_rtscts + tx_time_data); | 485 | /* Contention time for first 2 tries */ |
486 | ctime = (t_slot * cw) >> 1; | ||
487 | cw = min((cw << 1) | 1, mp->cw_max); | ||
488 | ctime += (t_slot * cw) >> 1; | ||
489 | cw = min((cw << 1) | 1, mp->cw_max); | ||
490 | |||
491 | /* Total TX time for data and Contention after first 2 tries */ | ||
492 | tx_time = ctime + 2 * (mi->overhead + tx_time_data); | ||
493 | tx_time_rtscts = ctime + 2 * (mi->overhead_rtscts + tx_time_data); | ||
494 | |||
495 | /* See how many more tries we can fit inside segment size */ | ||
483 | do { | 496 | do { |
484 | cw = (cw << 1) | 1; | 497 | /* Contention time for this try */ |
485 | cw = min(cw, mp->cw_max); | 498 | ctime = (t_slot * cw) >> 1; |
486 | tx_time += cw + t_slot + mi->overhead; | 499 | cw = min((cw << 1) | 1, mp->cw_max); |
487 | tx_time_rtscts += cw + t_slot + mi->overhead_rtscts; | 500 | |
501 | /* Total TX time after this try */ | ||
502 | tx_time += ctime + mi->overhead + tx_time_data; | ||
503 | tx_time_rtscts += ctime + mi->overhead_rtscts + tx_time_data; | ||
504 | |||
488 | if (tx_time_rtscts < mp->segment_size) | 505 | if (tx_time_rtscts < mp->segment_size) |
489 | mr->retry_count_rtscts++; | 506 | mr->retry_count_rtscts++; |
490 | } while ((tx_time < mp->segment_size) && | 507 | } while ((tx_time < mp->segment_size) && |
@@ -505,7 +522,9 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
505 | if (!mr->retry_updated) | 522 | if (!mr->retry_updated) |
506 | minstrel_calc_retransmit(mp, mi, index); | 523 | minstrel_calc_retransmit(mp, mi, index); |
507 | 524 | ||
508 | if (mr->probability < MINSTREL_FRAC(20, 100)) | 525 | if (sample) |
526 | rate->count = 1; | ||
527 | else if (mr->probability < MINSTREL_FRAC(20, 100)) | ||
509 | rate->count = 2; | 528 | rate->count = 2; |
510 | else if (rtscts) | 529 | else if (rtscts) |
511 | rate->count = mr->retry_count_rtscts; | 530 | rate->count = mr->retry_count_rtscts; |
@@ -513,9 +532,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
513 | rate->count = mr->retry_count; | 532 | rate->count = mr->retry_count; |
514 | 533 | ||
515 | rate->flags = IEEE80211_TX_RC_MCS | group->flags; | 534 | rate->flags = IEEE80211_TX_RC_MCS | group->flags; |
516 | if (txrc->short_preamble) | 535 | if (rtscts) |
517 | rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; | ||
518 | if (txrc->rts || rtscts) | ||
519 | rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; | 536 | rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; |
520 | rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES; | 537 | rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES; |
521 | } | 538 | } |
@@ -547,13 +564,14 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
547 | sample_idx = sample_table[mg->column][mg->index]; | 564 | sample_idx = sample_table[mg->column][mg->index]; |
548 | mr = &mg->rates[sample_idx]; | 565 | mr = &mg->rates[sample_idx]; |
549 | sample_idx += mi->sample_group * MCS_GROUP_RATES; | 566 | sample_idx += mi->sample_group * MCS_GROUP_RATES; |
567 | minstrel_next_sample_idx(mi); | ||
550 | 568 | ||
551 | /* | 569 | /* |
552 | * When not using MRR, do not sample if the probability is already | 570 | * When not using MRR, do not sample if the probability is already |
553 | * higher than 95% to avoid wasting airtime | 571 | * higher than 95% to avoid wasting airtime |
554 | */ | 572 | */ |
555 | if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100))) | 573 | if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100))) |
556 | goto next; | 574 | return -1; |
557 | 575 | ||
558 | /* | 576 | /* |
559 | * Make sure that lower rates get sampled only occasionally, | 577 | * Make sure that lower rates get sampled only occasionally, |
@@ -561,18 +579,14 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
561 | */ | 579 | */ |
562 | if (minstrel_get_duration(sample_idx) > | 580 | if (minstrel_get_duration(sample_idx) > |
563 | minstrel_get_duration(mi->max_tp_rate)) { | 581 | minstrel_get_duration(mi->max_tp_rate)) { |
564 | if (mr->sample_skipped < 10) | 582 | if (mr->sample_skipped < 20) |
565 | goto next; | 583 | return -1; |
566 | 584 | ||
567 | if (mi->sample_slow++ > 2) | 585 | if (mi->sample_slow++ > 2) |
568 | goto next; | 586 | return -1; |
569 | } | 587 | } |
570 | 588 | ||
571 | return sample_idx; | 589 | return sample_idx; |
572 | |||
573 | next: | ||
574 | minstrel_next_sample_idx(mi); | ||
575 | return -1; | ||
576 | } | 590 | } |
577 | 591 | ||
578 | static void | 592 | static void |
@@ -585,6 +599,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
585 | struct minstrel_ht_sta *mi = &msp->ht; | 599 | struct minstrel_ht_sta *mi = &msp->ht; |
586 | struct minstrel_priv *mp = priv; | 600 | struct minstrel_priv *mp = priv; |
587 | int sample_idx; | 601 | int sample_idx; |
602 | bool sample = false; | ||
588 | 603 | ||
589 | if (rate_control_send_low(sta, priv_sta, txrc)) | 604 | if (rate_control_send_low(sta, priv_sta, txrc)) |
590 | return; | 605 | return; |
@@ -595,21 +610,49 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
595 | info->flags |= mi->tx_flags; | 610 | info->flags |= mi->tx_flags; |
596 | sample_idx = minstrel_get_sample_rate(mp, mi); | 611 | sample_idx = minstrel_get_sample_rate(mp, mi); |
597 | if (sample_idx >= 0) { | 612 | if (sample_idx >= 0) { |
613 | sample = true; | ||
598 | minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, | 614 | minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, |
599 | txrc, true, false); | 615 | txrc, true, false); |
600 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate, | ||
601 | txrc, false, true); | ||
602 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 616 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
603 | } else { | 617 | } else { |
604 | minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, | 618 | minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, |
605 | txrc, false, false); | 619 | txrc, false, false); |
606 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2, | ||
607 | txrc, false, true); | ||
608 | } | 620 | } |
609 | minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, true); | ||
610 | 621 | ||
611 | ar[3].count = 0; | 622 | if (mp->hw->max_rates >= 3) { |
612 | ar[3].idx = -1; | 623 | /* |
624 | * At least 3 tx rates supported, use | ||
625 | * sample_rate -> max_tp_rate -> max_prob_rate for sampling and | ||
626 | * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default. | ||
627 | */ | ||
628 | if (sample_idx >= 0) | ||
629 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate, | ||
630 | txrc, false, false); | ||
631 | else | ||
632 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2, | ||
633 | txrc, false, true); | ||
634 | |||
635 | minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, | ||
636 | txrc, false, !sample); | ||
637 | |||
638 | ar[3].count = 0; | ||
639 | ar[3].idx = -1; | ||
640 | } else if (mp->hw->max_rates == 2) { | ||
641 | /* | ||
642 | * Only 2 tx rates supported, use | ||
643 | * sample_rate -> max_prob_rate for sampling and | ||
644 | * max_tp_rate -> max_prob_rate by default. | ||
645 | */ | ||
646 | minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate, | ||
647 | txrc, false, !sample); | ||
648 | |||
649 | ar[2].count = 0; | ||
650 | ar[2].idx = -1; | ||
651 | } else { | ||
652 | /* Not using MRR, only use the first rate */ | ||
653 | ar[1].count = 0; | ||
654 | ar[1].idx = -1; | ||
655 | } | ||
613 | 656 | ||
614 | mi->total_packets++; | 657 | mi->total_packets++; |
615 | 658 | ||
@@ -631,18 +674,14 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
631 | struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; | 674 | struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; |
632 | struct ieee80211_local *local = hw_to_local(mp->hw); | 675 | struct ieee80211_local *local = hw_to_local(mp->hw); |
633 | u16 sta_cap = sta->ht_cap.cap; | 676 | u16 sta_cap = sta->ht_cap.cap; |
677 | int n_supported = 0; | ||
634 | int ack_dur; | 678 | int ack_dur; |
635 | int stbc; | 679 | int stbc; |
636 | int i; | 680 | int i; |
637 | 681 | ||
638 | /* fall back to the old minstrel for legacy stations */ | 682 | /* fall back to the old minstrel for legacy stations */ |
639 | if (!sta->ht_cap.ht_supported) { | 683 | if (!sta->ht_cap.ht_supported) |
640 | msp->is_ht = false; | 684 | goto use_legacy; |
641 | memset(&msp->legacy, 0, sizeof(msp->legacy)); | ||
642 | msp->legacy.r = msp->ratelist; | ||
643 | msp->legacy.sample_table = msp->sample_table; | ||
644 | return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy); | ||
645 | } | ||
646 | 685 | ||
647 | BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != | 686 | BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != |
648 | MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS); | 687 | MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS); |
@@ -697,7 +736,22 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
697 | 736 | ||
698 | mi->groups[i].supported = | 737 | mi->groups[i].supported = |
699 | mcs->rx_mask[minstrel_mcs_groups[i].streams - 1]; | 738 | mcs->rx_mask[minstrel_mcs_groups[i].streams - 1]; |
739 | |||
740 | if (mi->groups[i].supported) | ||
741 | n_supported++; | ||
700 | } | 742 | } |
743 | |||
744 | if (!n_supported) | ||
745 | goto use_legacy; | ||
746 | |||
747 | return; | ||
748 | |||
749 | use_legacy: | ||
750 | msp->is_ht = false; | ||
751 | memset(&msp->legacy, 0, sizeof(msp->legacy)); | ||
752 | msp->legacy.r = msp->ratelist; | ||
753 | msp->legacy.sample_table = msp->sample_table; | ||
754 | return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy); | ||
701 | } | 755 | } |
702 | 756 | ||
703 | static void | 757 | static void |