| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | From: Felix Fietkau <nbd@nbd.name> |
| 2 | Date: Sat, 26 Dec 2020 19:09:08 +0100 |
| 3 | Subject: [PATCH] mac80211: minstrel_ht: fix max probability rate selection |
| 4 | |
| 5 | - do not select rates faster than the max throughput rate if probability is lower |
| 6 | - reset previous rate before sorting again |
| 7 | |
| 8 | This ensures that the max prob rate gets set to a more reliable rate |
| 9 | |
| 10 | Signed-off-by: Felix Fietkau <nbd@nbd.name> |
| 11 | --- |
| 12 | |
| 13 | --- a/net/mac80211/rc80211_minstrel_ht.c |
| 14 | +++ b/net/mac80211/rc80211_minstrel_ht.c |
| 15 | @@ -495,12 +495,13 @@ minstrel_ht_sort_best_tp_rates(struct mi |
| 16 | * Find and set the topmost probability rate per sta and per group |
| 17 | */ |
| 18 | static void |
| 19 | -minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index) |
| 20 | +minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 *dest, u16 index) |
| 21 | { |
| 22 | struct minstrel_mcs_group_data *mg; |
| 23 | struct minstrel_rate_stats *mrs; |
| 24 | int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob; |
| 25 | - int max_tp_group, cur_tp_avg, cur_group, cur_idx; |
| 26 | + int max_tp_group, max_tp_idx, max_tp_prob; |
| 27 | + int cur_tp_avg, cur_group, cur_idx; |
| 28 | int max_gpr_group, max_gpr_idx; |
| 29 | int max_gpr_tp_avg, max_gpr_prob; |
| 30 | |
| 31 | @@ -509,18 +510,26 @@ minstrel_ht_set_best_prob_rate(struct mi |
| 32 | mg = &mi->groups[index / MCS_GROUP_RATES]; |
| 33 | mrs = &mg->rates[index % MCS_GROUP_RATES]; |
| 34 | |
| 35 | - tmp_group = mi->max_prob_rate / MCS_GROUP_RATES; |
| 36 | - tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES; |
| 37 | + tmp_group = *dest / MCS_GROUP_RATES; |
| 38 | + tmp_idx = *dest % MCS_GROUP_RATES; |
| 39 | tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; |
| 40 | tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); |
| 41 | |
| 42 | /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from |
| 43 | * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */ |
| 44 | max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES; |
| 45 | + max_tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES; |
| 46 | + max_tp_prob = mi->groups[max_tp_group].rates[max_tp_idx].prob_avg; |
| 47 | + |
| 48 | if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES) && |
| 49 | !minstrel_ht_is_legacy_group(max_tp_group)) |
| 50 | return; |
| 51 | |
| 52 | + /* skip rates faster than max tp rate with lower prob */ |
| 53 | + if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) && |
| 54 | + mrs->prob_avg < max_tp_prob) |
| 55 | + return; |
| 56 | + |
| 57 | max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; |
| 58 | max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; |
| 59 | max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg; |
| 60 | @@ -538,7 +547,7 @@ minstrel_ht_set_best_prob_rate(struct mi |
| 61 | mg->max_group_prob_rate = index; |
| 62 | } else { |
| 63 | if (mrs->prob_avg > tmp_prob) |
| 64 | - mi->max_prob_rate = index; |
| 65 | + *dest = index; |
| 66 | if (mrs->prob_avg > max_gpr_prob) |
| 67 | mg->max_group_prob_rate = index; |
| 68 | } |
| 69 | @@ -816,7 +825,8 @@ minstrel_ht_update_stats(struct minstrel |
| 70 | struct minstrel_rate_stats *mrs; |
| 71 | int group, i, j, cur_prob; |
| 72 | u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES]; |
| 73 | - u16 tmp_legacy_tp_rate[MAX_THR_RATES], index; |
| 74 | + u16 tmp_legacy_tp_rate[MAX_THR_RATES], tmp_max_prob_rate; |
| 75 | + u16 index; |
| 76 | bool ht_supported = mi->sta->ht_cap.ht_supported; |
| 77 | |
| 78 | mi->sample_mode = MINSTREL_SAMPLE_IDLE; |
| 79 | @@ -863,6 +873,7 @@ minstrel_ht_update_stats(struct minstrel |
| 80 | else |
| 81 | index = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; |
| 82 | |
| 83 | + tmp_max_prob_rate = index; |
| 84 | for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++) |
| 85 | tmp_mcs_tp_rate[j] = index; |
| 86 | |
| 87 | @@ -903,9 +914,6 @@ minstrel_ht_update_stats(struct minstrel |
| 88 | /* Find max throughput rate set within a group */ |
| 89 | minstrel_ht_sort_best_tp_rates(mi, index, |
| 90 | tmp_group_tp_rate); |
| 91 | - |
| 92 | - /* Find max probability rate per group and global */ |
| 93 | - minstrel_ht_set_best_prob_rate(mi, index); |
| 94 | } |
| 95 | |
| 96 | memcpy(mg->max_group_tp_rate, tmp_group_tp_rate, |
| 97 | @@ -917,6 +925,27 @@ minstrel_ht_update_stats(struct minstrel |
| 98 | tmp_legacy_tp_rate); |
| 99 | memcpy(mi->max_tp_rate, tmp_mcs_tp_rate, sizeof(mi->max_tp_rate)); |
| 100 | |
| 101 | + for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { |
| 102 | + if (!mi->supported[group]) |
| 103 | + continue; |
| 104 | + |
| 105 | + mg = &mi->groups[group]; |
| 106 | + mg->max_group_prob_rate = MCS_GROUP_RATES * group; |
| 107 | + |
| 108 | + for (i = 0; i < MCS_GROUP_RATES; i++) { |
| 109 | + if (!(mi->supported[group] & BIT(i))) |
| 110 | + continue; |
| 111 | + |
| 112 | + index = MCS_GROUP_RATES * group + i; |
| 113 | + |
| 114 | + /* Find max probability rate per group and global */ |
| 115 | + minstrel_ht_set_best_prob_rate(mi, &tmp_max_prob_rate, |
| 116 | + index); |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + mi->max_prob_rate = tmp_max_prob_rate; |
| 121 | + |
| 122 | /* Try to increase robustness of max_prob_rate*/ |
| 123 | minstrel_ht_prob_rate_reduce_streams(mi); |
| 124 | |