Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: minstrel_ht: significantly redesign the rate probing strategy

The biggest flaw in current minstrel_ht is the fact that it needs way too
many probing packets to be able to quickly find the best rate.
Depending on the wifi hardware and operating mode, this can significantly
reduce throughput when not operating at the highest available data rate.

In order to be able to significantly reduce the amount of rate sampling,
we need a much smarter selection of probing rates.

The new approach introduced by this patch maintains a limited set of
available rates to be tested during a statistics window.

They are split into distinct categories:
- MINSTREL_SAMPLE_TYPE_INC - incremental rate upgrade:
Pick the next rate group and find the first rate that is faster than
the current max. throughput rate
- MINSTREL_SAMPLE_TYPE_JUMP - random testing of higher rates:
Pick a random rate from the next group that is faster than the current
max throughput rate. This allows faster adaptation when the link changes
significantly
- MINSTREL_SAMPLE_TYPE_SLOW - test a rate between max_prob, max_tp2 and
max_tp in order to reduce the gap between them

In order to prioritize sampling, every 6 attempts are split into 3x INC,
2x JUMP, 1x SLOW.

Available rates are checked and refilled on every stats window update.

With this approach, we finally get a very small delta in throughput when
comparing setting the optimal data rate as a fixed rate vs normal rate
control operation.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20210127055735.78599-4-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Felix Fietkau and committed by
Johannes Berg
80d55154 7aece471

+336 -239
+317 -233
net/mac80211/rc80211_minstrel_ht.c
··· 266 266 const s16 minstrel_cck_bitrates[4] = { 10, 20, 55, 110 }; 267 267 const s16 minstrel_ofdm_bitrates[8] = { 60, 90, 120, 180, 240, 360, 480, 540 }; 268 268 static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; 269 + static const u8 minstrel_sample_seq[] = { 270 + MINSTREL_SAMPLE_TYPE_INC, 271 + MINSTREL_SAMPLE_TYPE_JUMP, 272 + MINSTREL_SAMPLE_TYPE_INC, 273 + MINSTREL_SAMPLE_TYPE_JUMP, 274 + MINSTREL_SAMPLE_TYPE_INC, 275 + MINSTREL_SAMPLE_TYPE_SLOW, 276 + }; 269 277 270 278 static void 271 279 minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); ··· 628 620 } 629 621 } 630 622 631 - static bool 632 - minstrel_ht_probe_group(struct minstrel_ht_sta *mi, const struct mcs_group *tp_group, 633 - int tp_idx, const struct mcs_group *group) 623 + static u16 624 + __minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi, 625 + enum minstrel_sample_type type) 634 626 { 635 - if (group->bw < tp_group->bw) 636 - return false; 627 + u16 *rates = mi->sample[type].sample_rates; 628 + u16 cur; 629 + int i; 637 630 638 - if (group->streams == tp_group->streams) 639 - return true; 640 - 641 - if (tp_idx < 4 && group->streams == tp_group->streams - 1) 642 - return true; 643 - 644 - return group->streams == tp_group->streams + 1; 645 - } 646 - 647 - static void 648 - minstrel_ht_find_probe_rates(struct minstrel_ht_sta *mi, u16 *rates, int *n_rates, 649 - bool faster_rate) 650 - { 651 - const struct mcs_group *group, *tp_group; 652 - int i, g, max_dur; 653 - int tp_idx; 654 - 655 - tp_group = &minstrel_mcs_groups[MI_RATE_GROUP(mi->max_tp_rate[0])]; 656 - tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]); 657 - 658 - max_dur = minstrel_get_duration(mi->max_tp_rate[0]); 659 - if (faster_rate) 660 - max_dur -= max_dur / 16; 661 - 662 - for (g = 0; g < MINSTREL_GROUPS_NB; g++) { 663 - u16 supported = mi->supported[g]; 664 - 665 - if (!supported) 631 + for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) { 632 + if (!rates[i]) 666 633 continue; 667 634 668 - group = &minstrel_mcs_groups[g]; 669 - if (!minstrel_ht_probe_group(mi, tp_group, tp_idx, group)) 670 - continue; 671 - 672 - for (i = 0; supported; supported >>= 1, i++) { 673 - int idx; 674 - 675 - if (!(supported & 1)) 676 - continue; 677 - 678 - if ((group->duration[i] << group->shift) > max_dur) 679 - continue; 680 - 681 - idx = MI_RATE(g, i); 682 - if (idx == mi->max_tp_rate[0]) 683 - continue; 684 - 685 - rates[(*n_rates)++] = idx; 686 - break; 687 - } 635 + cur = rates[i]; 636 + rates[i] = 0; 637 + return cur; 688 638 } 639 + 640 + return 0; 689 641 } 690 642 691 643 static void 692 644 minstrel_ht_rate_sample_switch(struct minstrel_priv *mp, 693 645 struct minstrel_ht_sta *mi) 694 646 { 695 - struct minstrel_rate_stats *mrs; 696 - u16 rates[MINSTREL_GROUPS_NB]; 697 - int n_rates = 0; 698 - int probe_rate = 0; 699 - bool faster_rate; 700 - int i; 701 - u8 random; 647 + u16 rate; 702 648 703 649 /* 704 650 * Use rate switching instead of probing packets for devices with ··· 661 699 if (mp->hw->max_rates > 1) 662 700 return; 663 701 664 - /* 665 - * If the current EWMA prob is >75%, look for a rate that's 6.25% 666 - * faster than the max tp rate. 667 - * If that fails, look again for a rate that is at least as fast 668 - */ 669 - mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); 670 - faster_rate = mrs->prob_avg > MINSTREL_FRAC(75, 100); 671 - minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate); 672 - if (!n_rates && faster_rate) 673 - minstrel_ht_find_probe_rates(mi, rates, &n_rates, false); 674 - 675 - /* If no suitable rate was found, try to pick the next one in the group */ 676 - if (!n_rates) { 677 - int g_idx = MI_RATE_GROUP(mi->max_tp_rate[0]); 678 - u16 supported = mi->supported[g_idx]; 679 - 680 - supported >>= MI_RATE_IDX(mi->max_tp_rate[0]); 681 - for (i = 0; supported; supported >>= 1, i++) { 682 - if (!(supported & 1)) 683 - continue; 684 - 685 - probe_rate = mi->max_tp_rate[0] + i; 686 - goto out; 687 - } 688 - 702 + rate = __minstrel_ht_get_sample_rate(mi, MINSTREL_SAMPLE_TYPE_INC); 703 + if (!rate) 689 704 return; 690 - } 691 705 692 - i = 0; 693 - if (n_rates > 1) { 694 - random = prandom_u32(); 695 - i = random % n_rates; 696 - } 697 - probe_rate = rates[i]; 698 - 699 - out: 700 - mi->sample_rate = probe_rate; 706 + mi->sample_rate = rate; 701 707 mi->sample_mode = MINSTREL_SAMPLE_ACTIVE; 702 708 } 703 709 ··· 734 804 mrs->attempts = 0; 735 805 } 736 806 807 + static bool 808 + minstrel_ht_find_sample_rate(struct minstrel_ht_sta *mi, int type, int idx) 809 + { 810 + int i; 811 + 812 + for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) { 813 + u16 cur = mi->sample[type].sample_rates[i]; 814 + 815 + if (cur == idx) 816 + return true; 817 + 818 + if (!cur) 819 + break; 820 + } 821 + 822 + return false; 823 + } 824 + 825 + static int 826 + minstrel_ht_move_sample_rates(struct minstrel_ht_sta *mi, int type, 827 + u32 fast_rate_dur, u32 slow_rate_dur) 828 + { 829 + u16 *rates = mi->sample[type].sample_rates; 830 + int i, j; 831 + 832 + for (i = 0, j = 0; i < MINSTREL_SAMPLE_RATES; i++) { 833 + u32 duration; 834 + bool valid = false; 835 + u16 cur; 836 + 837 + cur = rates[i]; 838 + if (!cur) 839 + continue; 840 + 841 + duration = minstrel_get_duration(cur); 842 + switch (type) { 843 + case MINSTREL_SAMPLE_TYPE_SLOW: 844 + valid = duration > fast_rate_dur && 845 + duration < slow_rate_dur; 846 + break; 847 + case MINSTREL_SAMPLE_TYPE_INC: 848 + case MINSTREL_SAMPLE_TYPE_JUMP: 849 + valid = duration < fast_rate_dur; 850 + break; 851 + default: 852 + valid = false; 853 + break; 854 + } 855 + 856 + if (!valid) { 857 + rates[i] = 0; 858 + continue; 859 + } 860 + 861 + if (i == j) 862 + continue; 863 + 864 + rates[j++] = cur; 865 + rates[i] = 0; 866 + } 867 + 868 + return j; 869 + } 870 + 871 + static int 872 + minstrel_ht_group_min_rate_offset(struct minstrel_ht_sta *mi, int group, 873 + u32 max_duration) 874 + { 875 + u16 supported = mi->supported[group]; 876 + int i; 877 + 878 + for (i = 0; i < MCS_GROUP_RATES && supported; i++, supported >>= 1) { 879 + if (!(supported & BIT(0))) 880 + continue; 881 + 882 + if (minstrel_get_duration(MI_RATE(group, i)) >= max_duration) 883 + continue; 884 + 885 + return i; 886 + } 887 + 888 + return -1; 889 + } 890 + 891 + /* 892 + * Incremental update rates: 893 + * Flip through groups and pick the first group rate that is faster than the 894 + * highest currently selected rate 895 + */ 896 + static u16 897 + minstrel_ht_next_inc_rate(struct minstrel_ht_sta *mi, u32 fast_rate_dur) 898 + { 899 + struct minstrel_mcs_group_data *mg; 900 + u8 type = MINSTREL_SAMPLE_TYPE_INC; 901 + int i, index = 0; 902 + u8 group; 903 + 904 + group = mi->sample[type].sample_group; 905 + for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) { 906 + group = (group + 1) % ARRAY_SIZE(minstrel_mcs_groups); 907 + mg = &mi->groups[group]; 908 + 909 + index = minstrel_ht_group_min_rate_offset(mi, group, 910 + fast_rate_dur); 911 + if (index < 0) 912 + continue; 913 + 914 + index = MI_RATE(group, index & 0xf); 915 + if (!minstrel_ht_find_sample_rate(mi, type, index)) 916 + goto out; 917 + } 918 + index = 0; 919 + 920 + out: 921 + mi->sample[type].sample_group = group; 922 + 923 + return index; 924 + } 925 + 926 + static int 927 + minstrel_ht_next_group_sample_rate(struct minstrel_ht_sta *mi, int group, 928 + u16 supported, int offset) 929 + { 930 + struct minstrel_mcs_group_data *mg = &mi->groups[group]; 931 + u16 idx; 932 + int i; 933 + 934 + for (i = 0; i < MCS_GROUP_RATES; i++) { 935 + idx = sample_table[mg->column][mg->index]; 936 + if (++mg->index >= MCS_GROUP_RATES) { 937 + mg->index = 0; 938 + if (++mg->column >= ARRAY_SIZE(sample_table)) 939 + mg->column = 0; 940 + } 941 + 942 + if (idx < offset) 943 + continue; 944 + 945 + if (!(supported & BIT(idx))) 946 + continue; 947 + 948 + return MI_RATE(group, idx); 949 + } 950 + 951 + return -1; 952 + } 953 + 954 + /* 955 + * Jump rates: 956 + * Sample random rates, use those that are faster than the highest 957 + * currently selected rate. Rates between the fastest and the slowest 958 + * get sorted into the slow sample bucket, but only if it has room 959 + */ 960 + static u16 961 + minstrel_ht_next_jump_rate(struct minstrel_ht_sta *mi, u32 fast_rate_dur, 962 + u32 slow_rate_dur, int *slow_rate_ofs) 963 + { 964 + struct minstrel_mcs_group_data *mg; 965 + struct minstrel_rate_stats *mrs; 966 + u32 max_duration = slow_rate_dur; 967 + int i, index, offset; 968 + u16 *slow_rates; 969 + u16 supported; 970 + u32 duration; 971 + u8 group; 972 + 973 + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES) 974 + max_duration = fast_rate_dur; 975 + 976 + slow_rates = mi->sample[MINSTREL_SAMPLE_TYPE_SLOW].sample_rates; 977 + group = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group; 978 + for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) { 979 + u8 type; 980 + 981 + group = (group + 1) % ARRAY_SIZE(minstrel_mcs_groups); 982 + mg = &mi->groups[group]; 983 + 984 + supported = mi->supported[group]; 985 + if (!supported) 986 + continue; 987 + 988 + offset = minstrel_ht_group_min_rate_offset(mi, group, 989 + max_duration); 990 + if (offset < 0) 991 + continue; 992 + 993 + index = minstrel_ht_next_group_sample_rate(mi, group, supported, 994 + offset); 995 + if (index < 0) 996 + continue; 997 + 998 + duration = minstrel_get_duration(index); 999 + if (duration < fast_rate_dur) 1000 + type = MINSTREL_SAMPLE_TYPE_JUMP; 1001 + else 1002 + type = MINSTREL_SAMPLE_TYPE_SLOW; 1003 + 1004 + if (minstrel_ht_find_sample_rate(mi, type, index)) 1005 + continue; 1006 + 1007 + if (type == MINSTREL_SAMPLE_TYPE_JUMP) 1008 + goto found; 1009 + 1010 + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES) 1011 + continue; 1012 + 1013 + if (duration >= slow_rate_dur) 1014 + continue; 1015 + 1016 + /* skip slow rates with high success probability */ 1017 + mrs = minstrel_get_ratestats(mi, index); 1018 + if (mrs->prob_avg > MINSTREL_FRAC(95, 100)) 1019 + continue; 1020 + 1021 + slow_rates[(*slow_rate_ofs)++] = index; 1022 + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES) 1023 + max_duration = fast_rate_dur; 1024 + } 1025 + index = 0; 1026 + 1027 + found: 1028 + mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group = group; 1029 + 1030 + return index; 1031 + } 1032 + 1033 + static void 1034 + minstrel_ht_refill_sample_rates(struct minstrel_ht_sta *mi) 1035 + { 1036 + u32 prob_dur = minstrel_get_duration(mi->max_prob_rate); 1037 + u32 tp_dur = minstrel_get_duration(mi->max_tp_rate[0]); 1038 + u32 tp2_dur = minstrel_get_duration(mi->max_tp_rate[1]); 1039 + u32 fast_rate_dur = min(min(tp_dur, tp2_dur), prob_dur); 1040 + u32 slow_rate_dur = max(max(tp_dur, tp2_dur), prob_dur); 1041 + u16 *rates; 1042 + int i, j; 1043 + 1044 + rates = mi->sample[MINSTREL_SAMPLE_TYPE_INC].sample_rates; 1045 + i = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_INC, 1046 + fast_rate_dur, slow_rate_dur); 1047 + while (i < MINSTREL_SAMPLE_RATES) { 1048 + rates[i] = minstrel_ht_next_inc_rate(mi, tp_dur); 1049 + if (!rates[i]) 1050 + break; 1051 + 1052 + i++; 1053 + } 1054 + 1055 + rates = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_rates; 1056 + i = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_JUMP, 1057 + fast_rate_dur, slow_rate_dur); 1058 + j = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_SLOW, 1059 + fast_rate_dur, slow_rate_dur); 1060 + while (i < MINSTREL_SAMPLE_RATES) { 1061 + rates[i] = minstrel_ht_next_jump_rate(mi, fast_rate_dur, 1062 + slow_rate_dur, &j); 1063 + if (!rates[i]) 1064 + break; 1065 + 1066 + i++; 1067 + } 1068 + 1069 + for (i = 0; i < ARRAY_SIZE(mi->sample); i++) 1070 + memcpy(mi->sample[i].cur_sample_rates, mi->sample[i].sample_rates, 1071 + sizeof(mi->sample[i].cur_sample_rates)); 1072 + } 1073 + 1074 + 737 1075 /* 738 1076 * Update rate statistics and select new primary rates 739 1077 * ··· 1046 848 mi->ampdu_packets = 0; 1047 849 } 1048 850 1049 - mi->sample_count = 0; 1050 - 1051 851 if (mi->supported[MINSTREL_CCK_GROUP]) 1052 852 group = MINSTREL_CCK_GROUP; 1053 853 else if (mi->supported[MINSTREL_OFDM_GROUP]) ··· 1079 883 mg = &mi->groups[group]; 1080 884 if (!mi->supported[group]) 1081 885 continue; 1082 - 1083 - mi->sample_count++; 1084 886 1085 887 /* (re)Initialize group rate indexes */ 1086 888 for(j = 0; j < MAX_THR_RATES; j++) ··· 1146 952 1147 953 /* Try to increase robustness of max_prob_rate*/ 1148 954 minstrel_ht_prob_rate_reduce_streams(mi); 1149 - 1150 - /* try to sample half of all available rates during each interval */ 1151 - mi->sample_count *= 4; 955 + minstrel_ht_refill_sample_rates(mi); 1152 956 1153 957 if (sample) 1154 958 minstrel_ht_rate_sample_switch(mp, mi); ··· 1163 971 1164 972 /* Reset update timer */ 1165 973 mi->last_stats_update = jiffies; 974 + mi->sample_time = jiffies; 1166 975 } 1167 976 1168 977 static bool ··· 1191 998 return true; 1192 999 1193 1000 return false; 1194 - } 1195 - 1196 - static void 1197 - minstrel_set_next_sample_idx(struct minstrel_ht_sta *mi) 1198 - { 1199 - struct minstrel_mcs_group_data *mg; 1200 - 1201 - for (;;) { 1202 - mi->sample_group++; 1203 - mi->sample_group %= ARRAY_SIZE(minstrel_mcs_groups); 1204 - mg = &mi->groups[mi->sample_group]; 1205 - 1206 - if (!mi->supported[mi->sample_group]) 1207 - continue; 1208 - 1209 - if (++mg->index >= MCS_GROUP_RATES) { 1210 - mg->index = 0; 1211 - if (++mg->column >= ARRAY_SIZE(sample_table)) 1212 - mg->column = 0; 1213 - } 1214 - break; 1215 - } 1216 1001 } 1217 1002 1218 1003 static void ··· 1277 1106 1278 1107 mi->ampdu_packets++; 1279 1108 mi->ampdu_len += info->status.ampdu_len; 1280 - 1281 - if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { 1282 - int avg_ampdu_len = minstrel_ht_avg_ampdu_len(mi); 1283 - 1284 - mi->sample_wait = 16 + 2 * avg_ampdu_len; 1285 - mi->sample_tries = 1; 1286 - mi->sample_count--; 1287 - } 1288 1109 1289 1110 if (mi->sample_mode != MINSTREL_SAMPLE_IDLE) 1290 1111 rate_sample = minstrel_get_ratestats(mi, mi->sample_rate); ··· 1549 1386 rate_control_set_rates(mp->hw, mi->sta, rates); 1550 1387 } 1551 1388 1552 - static int 1553 - minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) 1389 + static u16 1390 + minstrel_ht_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) 1554 1391 { 1555 - struct minstrel_rate_stats *mrs; 1556 - struct minstrel_mcs_group_data *mg; 1557 - unsigned int sample_dur, sample_group, cur_max_tp_streams; 1558 - int tp_rate1, tp_rate2; 1559 - int sample_idx = 0; 1392 + u8 seq; 1560 1393 1561 - if (mp->hw->max_rates == 1 && mp->sample_switch && 1562 - (mi->total_packets_cur >= SAMPLE_SWITCH_THR || 1563 - mp->sample_switch == 1)) 1564 - return -1; 1565 - 1566 - if (mi->sample_wait > 0) { 1567 - mi->sample_wait--; 1568 - return -1; 1569 - } 1570 - 1571 - if (!mi->sample_tries) 1572 - return -1; 1573 - 1574 - sample_group = mi->sample_group; 1575 - mg = &mi->groups[sample_group]; 1576 - sample_idx = sample_table[mg->column][mg->index]; 1577 - minstrel_set_next_sample_idx(mi); 1578 - 1579 - if (!(mi->supported[sample_group] & BIT(sample_idx))) 1580 - return -1; 1581 - 1582 - mrs = &mg->rates[sample_idx]; 1583 - sample_idx += MI_RATE(sample_group, 0); 1584 - 1585 - tp_rate1 = mi->max_tp_rate[0]; 1586 - 1587 - /* Set tp_rate2 to the second highest max_tp_rate */ 1588 - if (minstrel_get_duration(mi->max_tp_rate[0]) > 1589 - minstrel_get_duration(mi->max_tp_rate[1])) { 1590 - tp_rate2 = mi->max_tp_rate[0]; 1394 + if (mp->hw->max_rates > 1) { 1395 + seq = mi->sample_seq; 1396 + mi->sample_seq = (seq + 1) % ARRAY_SIZE(minstrel_sample_seq); 1397 + seq = minstrel_sample_seq[seq]; 1591 1398 } else { 1592 - tp_rate2 = mi->max_tp_rate[1]; 1399 + seq = MINSTREL_SAMPLE_TYPE_INC; 1593 1400 } 1594 1401 1595 - /* 1596 - * Sampling might add some overhead (RTS, no aggregation) 1597 - * to the frame. Hence, don't use sampling for the highest currently 1598 - * used highest throughput or probability rate. 1599 - */ 1600 - if (sample_idx == mi->max_tp_rate[0] || sample_idx == mi->max_prob_rate) 1601 - return -1; 1602 - 1603 - /* 1604 - * Do not sample if the probability is already higher than 95%, 1605 - * or if the rate is 3 times slower than the current max probability 1606 - * rate, to avoid wasting airtime. 1607 - */ 1608 - sample_dur = minstrel_get_duration(sample_idx); 1609 - if (mrs->prob_avg > MINSTREL_FRAC(95, 100) || 1610 - minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur) 1611 - return -1; 1612 - 1613 - 1614 - /* 1615 - * For devices with no configurable multi-rate retry, skip sampling 1616 - * below the per-group max throughput rate, and only use one sampling 1617 - * attempt per rate 1618 - */ 1619 - if (mp->hw->max_rates == 1 && 1620 - (minstrel_get_duration(mg->max_group_tp_rate[0]) < sample_dur || 1621 - mrs->attempts)) 1622 - return -1; 1623 - 1624 - /* Skip already sampled slow rates */ 1625 - if (sample_dur >= minstrel_get_duration(tp_rate1) && mrs->attempts) 1626 - return -1; 1627 - 1628 - /* 1629 - * Make sure that lower rates get sampled only occasionally, 1630 - * if the link is working perfectly. 1631 - */ 1632 - 1633 - cur_max_tp_streams = minstrel_mcs_groups[MI_RATE_GROUP(tp_rate1)].streams; 1634 - if (sample_dur >= minstrel_get_duration(tp_rate2) && 1635 - (cur_max_tp_streams - 1 < 1636 - minstrel_mcs_groups[sample_group].streams || 1637 - sample_dur >= minstrel_get_duration(mi->max_prob_rate))) 1638 - return -1; 1639 - 1640 - mi->sample_tries--; 1641 - 1642 - return sample_idx; 1402 + return __minstrel_ht_get_sample_rate(mi, seq); 1643 1403 } 1644 1404 1645 1405 static void ··· 1574 1488 struct ieee80211_tx_rate *rate = &info->status.rates[0]; 1575 1489 struct minstrel_ht_sta *mi = priv_sta; 1576 1490 struct minstrel_priv *mp = priv; 1577 - int sample_idx; 1491 + u16 sample_idx; 1578 1492 1579 1493 if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && 1580 1494 !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate))) ··· 1590 1504 /* Don't use EAPOL frames for sampling on non-mrr hw */ 1591 1505 if (mp->hw->max_rates == 1 && 1592 1506 (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) 1593 - sample_idx = -1; 1594 - else 1595 - sample_idx = minstrel_get_sample_rate(mp, mi); 1507 + return; 1596 1508 1597 - if (sample_idx < 0) 1509 + if (mp->hw->max_rates == 1 && mp->sample_switch && 1510 + (mi->total_packets_cur >= SAMPLE_SWITCH_THR || 1511 + mp->sample_switch == 1)) 1512 + return; 1513 + 1514 + if (time_is_before_jiffies(mi->sample_time)) 1515 + return; 1516 + 1517 + mi->sample_time = jiffies + MINSTREL_SAMPLE_INTERVAL; 1518 + sample_idx = minstrel_ht_get_sample_rate(mp, mi); 1519 + if (!sample_idx) 1598 1520 return; 1599 1521 1600 1522 sample_group = &minstrel_mcs_groups[MI_RATE_GROUP(sample_idx)]; ··· 1722 1628 mi->overhead_legacy_rtscts = mi->overhead_legacy + 2 * ack_dur; 1723 1629 1724 1630 mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); 1725 - 1726 - /* When using MRR, sample more on the first attempt, without delay */ 1727 - if (mp->has_mrr) { 1728 - mi->sample_count = 16; 1729 - mi->sample_wait = 0; 1730 - } else { 1731 - mi->sample_count = 8; 1732 - mi->sample_wait = 8; 1733 - } 1734 - mi->sample_tries = 4; 1735 1631 1736 1632 if (!use_vht) { 1737 1633 stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >>
+19 -6
net/mac80211/rc80211_minstrel_ht.h
··· 69 69 #define MI_RATE_IDX(_rate) FIELD_GET(MI_RATE_IDX_MASK, _rate) 70 70 #define MI_RATE_GROUP(_rate) FIELD_GET(MI_RATE_GROUP_MASK, _rate) 71 71 72 + #define MINSTREL_SAMPLE_RATES 5 /* rates per sample type */ 73 + #define MINSTREL_SAMPLE_INTERVAL (HZ / 50) 72 74 73 75 struct minstrel_priv { 74 76 struct ieee80211_hw *hw; ··· 128 126 bool retry_updated; 129 127 }; 130 128 129 + enum minstrel_sample_type { 130 + MINSTREL_SAMPLE_TYPE_INC, 131 + MINSTREL_SAMPLE_TYPE_JUMP, 132 + MINSTREL_SAMPLE_TYPE_SLOW, 133 + __MINSTREL_SAMPLE_TYPE_MAX 134 + }; 135 + 131 136 struct minstrel_mcs_group_data { 132 137 u8 index; 133 138 u8 column; ··· 151 142 MINSTREL_SAMPLE_IDLE, 152 143 MINSTREL_SAMPLE_ACTIVE, 153 144 MINSTREL_SAMPLE_PENDING, 145 + }; 146 + 147 + struct minstrel_sample_category { 148 + u8 sample_group; 149 + u16 sample_rates[MINSTREL_SAMPLE_RATES]; 150 + u16 cur_sample_rates[MINSTREL_SAMPLE_RATES]; 154 151 }; 155 152 156 153 struct minstrel_ht_sta { ··· 190 175 /* tx flags to add for frames for this sta */ 191 176 u32 tx_flags; 192 177 193 - u8 sample_wait; 194 - u8 sample_tries; 195 - u8 sample_count; 178 + unsigned long sample_time; 179 + struct minstrel_sample_category sample[__MINSTREL_SAMPLE_TYPE_MAX]; 180 + 181 + u8 sample_seq; 196 182 197 183 enum minstrel_sample_mode sample_mode; 198 184 u16 sample_rate; 199 - 200 - /* current MCS group to be sampled */ 201 - u8 sample_group; 202 185 203 186 u8 band; 204 187