| 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 |  |