diff options
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 71 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.h | 8 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_debugfs.c | 6 |
3 files changed, 49 insertions, 36 deletions
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index f8d99a54798f..1c36c9b4fa4a 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -69,14 +69,31 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) | |||
69 | return i; | 69 | return i; |
70 | } | 70 | } |
71 | 71 | ||
72 | /* find & sort topmost throughput rates */ | ||
73 | static inline void | ||
74 | minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) | ||
75 | { | ||
76 | int j = MAX_THR_RATES; | ||
77 | |||
78 | while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp) | ||
79 | j--; | ||
80 | if (j < MAX_THR_RATES - 1) | ||
81 | memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); | ||
82 | if (j < MAX_THR_RATES) | ||
83 | tp_list[j] = i; | ||
84 | } | ||
85 | |||
72 | static void | 86 | static void |
73 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | 87 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) |
74 | { | 88 | { |
75 | u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; | 89 | u8 tmp_tp_rate[MAX_THR_RATES]; |
76 | u32 max_prob = 0, index_max_prob = 0; | 90 | u8 tmp_prob_rate = 0; |
77 | u32 usecs; | 91 | u32 usecs; |
78 | int i; | 92 | int i; |
79 | 93 | ||
94 | for (i=0; i < MAX_THR_RATES; i++) | ||
95 | tmp_tp_rate[i] = 0; | ||
96 | |||
80 | for (i = 0; i < mi->n_rates; i++) { | 97 | for (i = 0; i < mi->n_rates; i++) { |
81 | struct minstrel_rate *mr = &mi->r[i]; | 98 | struct minstrel_rate *mr = &mi->r[i]; |
82 | 99 | ||
@@ -120,35 +137,27 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
120 | } | 137 | } |
121 | if (!mr->adjusted_retry_count) | 138 | if (!mr->adjusted_retry_count) |
122 | mr->adjusted_retry_count = 2; | 139 | mr->adjusted_retry_count = 2; |
123 | } | ||
124 | 140 | ||
125 | for (i = 0; i < mi->n_rates; i++) { | 141 | minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate); |
126 | struct minstrel_rate *mr = &mi->r[i]; | 142 | |
127 | if (max_tp < mr->cur_tp) { | 143 | /* To determine the most robust rate (max_prob_rate) used at |
128 | index_max_tp = i; | 144 | * 3rd mmr stage we distinct between two cases: |
129 | max_tp = mr->cur_tp; | 145 | * (1) if any success probabilitiy >= 95%, out of those rates |
130 | } | 146 | * choose the maximum throughput rate as max_prob_rate |
131 | if (max_prob < mr->probability) { | 147 | * (2) if all success probabilities < 95%, the rate with |
132 | index_max_prob = i; | 148 | * highest success probability is choosen as max_prob_rate */ |
133 | max_prob = mr->probability; | 149 | if (mr->probability >= MINSTREL_FRAC(95,100)) { |
150 | if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp) | ||
151 | tmp_prob_rate = i; | ||
152 | } else { | ||
153 | if (mr->probability >= mi->r[tmp_prob_rate].probability) | ||
154 | tmp_prob_rate = i; | ||
134 | } | 155 | } |
135 | } | 156 | } |
136 | 157 | ||
137 | max_tp = 0; | 158 | /* Assign the new rate set */ |
138 | for (i = 0; i < mi->n_rates; i++) { | 159 | memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); |
139 | struct minstrel_rate *mr = &mi->r[i]; | 160 | mi->max_prob_rate = tmp_prob_rate; |
140 | |||
141 | if (i == index_max_tp) | ||
142 | continue; | ||
143 | |||
144 | if (max_tp < mr->cur_tp) { | ||
145 | index_max_tp2 = i; | ||
146 | max_tp = mr->cur_tp; | ||
147 | } | ||
148 | } | ||
149 | mi->max_tp_rate = index_max_tp; | ||
150 | mi->max_tp_rate2 = index_max_tp2; | ||
151 | mi->max_prob_rate = index_max_prob; | ||
152 | 161 | ||
153 | /* Reset update timer */ | 162 | /* Reset update timer */ |
154 | mi->stats_update = jiffies; | 163 | mi->stats_update = jiffies; |
@@ -254,7 +263,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
254 | sampling_ratio = mp->lookaround_rate; | 263 | sampling_ratio = mp->lookaround_rate; |
255 | 264 | ||
256 | /* init rateindex [ndx] with max throughput rate */ | 265 | /* init rateindex [ndx] with max throughput rate */ |
257 | ndx = mi->max_tp_rate; | 266 | ndx = mi->max_tp_rate[0]; |
258 | 267 | ||
259 | /* increase sum packet counter */ | 268 | /* increase sum packet counter */ |
260 | mi->packet_count++; | 269 | mi->packet_count++; |
@@ -322,7 +331,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
322 | * to use it, as this only wastes precious airtime */ | 331 | * to use it, as this only wastes precious airtime */ |
323 | if (!mrr_capable && rate_sampling && | 332 | if (!mrr_capable && rate_sampling && |
324 | (mi->r[ndx].probability > MINSTREL_FRAC(95, 100))) | 333 | (mi->r[ndx].probability > MINSTREL_FRAC(95, 100))) |
325 | ndx = mi->max_tp_rate; | 334 | ndx = mi->max_tp_rate[0]; |
326 | 335 | ||
327 | /* mrr setup for 1st stage */ | 336 | /* mrr setup for 1st stage */ |
328 | ar[0].idx = mi->r[ndx].rix; | 337 | ar[0].idx = mi->r[ndx].rix; |
@@ -342,9 +351,9 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
342 | if (indirect_rate_sampling) | 351 | if (indirect_rate_sampling) |
343 | mrr_ndx[0] = sample_ndx; | 352 | mrr_ndx[0] = sample_ndx; |
344 | else | 353 | else |
345 | mrr_ndx[0] = mi->max_tp_rate; | 354 | mrr_ndx[0] = mi->max_tp_rate[0]; |
346 | } else { | 355 | } else { |
347 | mrr_ndx[0] = mi->max_tp_rate2; | 356 | mrr_ndx[0] = mi->max_tp_rate[1]; |
348 | } | 357 | } |
349 | 358 | ||
350 | /* mrr setup for 3rd & 4th stage */ | 359 | /* mrr setup for 3rd & 4th stage */ |
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index a0ccc5779910..85ebf42cb46d 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -18,6 +18,9 @@ | |||
18 | #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) | 18 | #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) |
19 | #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) | 19 | #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) |
20 | 20 | ||
21 | /* number of highest throughput rates to consider*/ | ||
22 | #define MAX_THR_RATES 4 | ||
23 | |||
21 | /* | 24 | /* |
22 | * Perform EWMA (Exponentially Weighted Moving Average) calculation | 25 | * Perform EWMA (Exponentially Weighted Moving Average) calculation |
23 | */ | 26 | */ |
@@ -65,9 +68,8 @@ struct minstrel_sta_info { | |||
65 | 68 | ||
66 | unsigned int lowest_rix; | 69 | unsigned int lowest_rix; |
67 | 70 | ||
68 | unsigned int max_tp_rate; | 71 | u8 max_tp_rate[MAX_THR_RATES]; |
69 | unsigned int max_tp_rate2; | 72 | u8 max_prob_rate; |
70 | unsigned int max_prob_rate; | ||
71 | unsigned int packet_count; | 73 | unsigned int packet_count; |
72 | unsigned int sample_count; | 74 | unsigned int sample_count; |
73 | int sample_deferred; | 75 | int sample_deferred; |
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index c0ebfaca6ba0..d1048348d399 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -73,8 +73,10 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
73 | for (i = 0; i < mi->n_rates; i++) { | 73 | for (i = 0; i < mi->n_rates; i++) { |
74 | struct minstrel_rate *mr = &mi->r[i]; | 74 | struct minstrel_rate *mr = &mi->r[i]; |
75 | 75 | ||
76 | *(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; | 76 | *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; |
77 | *(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; | 77 | *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; |
78 | *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; | ||
79 | *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; | ||
78 | *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; | 80 | *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; |
79 | p += sprintf(p, "%3u%s", mr->bitrate / 2, | 81 | p += sprintf(p, "%3u%s", mr->bitrate / 2, |
80 | (mr->bitrate & 1 ? ".5" : " ")); | 82 | (mr->bitrate & 1 ? ".5" : " ")); |