aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rc80211_minstrel.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-21 06:40:02 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:23 -0400
commite6a9854b05c1a6af1308fe2b8c68f35abf28a3ee (patch)
tree241f611f8194586ccabf61bacb060508773b9d05 /net/mac80211/rc80211_minstrel.c
parentcb121bad67a32cde37adc2729b7e18aa4fd3063e (diff)
mac80211/drivers: rewrite the rate control API
So after the previous changes we were still unhappy with how convoluted the API is and decided to make things simpler for everybody. This completely changes the rate control API, now taking into account 802.11n with MCS rates and more control, most drivers don't support that though. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rc80211_minstrel.c')
-rw-r--r--net/mac80211/rc80211_minstrel.c72
1 files changed, 29 insertions, 43 deletions
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index f6d69dab07a3..759ddd8bf0f4 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -169,30 +169,20 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
169{ 169{
170 struct minstrel_sta_info *mi = priv_sta; 170 struct minstrel_sta_info *mi = priv_sta;
171 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 171 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
172 struct ieee80211_tx_altrate *ar = info->status.retries; 172 struct ieee80211_tx_rate *ar = info->status.rates;
173 struct minstrel_priv *mp = priv; 173 int i, ndx;
174 int i, ndx, tries; 174 int success;
175 int success = 0;
176 175
177 if (!info->status.excessive_retries) 176 success = !!(info->flags & IEEE80211_TX_STAT_ACK);
178 success = 1;
179 177
180 if (!mp->has_mrr || (ar[0].rate_idx < 0)) { 178 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
181 ndx = rix_to_ndx(mi, info->tx_rate_idx); 179 if (ar[i].idx < 0)
182 tries = info->status.retry_count + 1;
183 mi->r[ndx].success += success;
184 mi->r[ndx].attempts += tries;
185 return;
186 }
187
188 for (i = 0; i < 4; i++) {
189 if (ar[i].rate_idx < 0)
190 break; 180 break;
191 181
192 ndx = rix_to_ndx(mi, ar[i].rate_idx); 182 ndx = rix_to_ndx(mi, ar[i].idx);
193 mi->r[ndx].attempts += ar[i].limit + 1; 183 mi->r[ndx].attempts += ar[i].count;
194 184
195 if ((i != 3) && (ar[i + 1].rate_idx < 0)) 185 if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
196 mi->r[ndx].success += success; 186 mi->r[ndx].success += success;
197 } 187 }
198 188
@@ -210,9 +200,9 @@ minstrel_get_retry_count(struct minstrel_rate *mr,
210{ 200{
211 unsigned int retry = mr->adjusted_retry_count; 201 unsigned int retry = mr->adjusted_retry_count;
212 202
213 if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) 203 if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
214 retry = max(2U, min(mr->retry_count_rtscts, retry)); 204 retry = max(2U, min(mr->retry_count_rtscts, retry));
215 else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) 205 else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
216 retry = max(2U, min(mr->retry_count_cts, retry)); 206 retry = max(2U, min(mr->retry_count_cts, retry));
217 return retry; 207 return retry;
218} 208}
@@ -234,14 +224,15 @@ minstrel_get_next_sample(struct minstrel_sta_info *mi)
234} 224}
235 225
236void 226void
237minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, 227minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
238 struct ieee80211_sta *sta, void *priv_sta, 228 void *priv_sta, struct ieee80211_tx_rate_control *txrc)
239 struct sk_buff *skb, struct rate_selection *sel)
240{ 229{
230 struct sk_buff *skb = txrc->skb;
231 struct ieee80211_supported_band *sband = txrc->sband;
241 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 232 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
242 struct minstrel_sta_info *mi = priv_sta; 233 struct minstrel_sta_info *mi = priv_sta;
243 struct minstrel_priv *mp = priv; 234 struct minstrel_priv *mp = priv;
244 struct ieee80211_tx_altrate *ar = info->control.retries; 235 struct ieee80211_tx_rate *ar = info->control.rates;
245 unsigned int ndx, sample_ndx = 0; 236 unsigned int ndx, sample_ndx = 0;
246 bool mrr; 237 bool mrr;
247 bool sample_slower = false; 238 bool sample_slower = false;
@@ -251,16 +242,12 @@ minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband,
251 int sample_rate; 242 int sample_rate;
252 243
253 if (!sta || !mi || use_low_rate(skb)) { 244 if (!sta || !mi || use_low_rate(skb)) {
254 sel->rate_idx = rate_lowest_index(sband, sta); 245 ar[0].idx = rate_lowest_index(sband, sta);
246 ar[0].count = mp->max_retry;
255 return; 247 return;
256 } 248 }
257 249
258 mrr = mp->has_mrr; 250 mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot;
259
260 /* mac80211 does not allow mrr for RTS/CTS */
261 if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
262 (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
263 mrr = false;
264 251
265 if (time_after(jiffies, mi->stats_update + (mp->update_interval * 252 if (time_after(jiffies, mi->stats_update + (mp->update_interval *
266 HZ) / 1000)) 253 HZ) / 1000))
@@ -315,13 +302,12 @@ minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband,
315 mi->sample_deferred++; 302 mi->sample_deferred++;
316 } 303 }
317 } 304 }
318 sel->rate_idx = mi->r[ndx].rix; 305 ar[0].idx = mi->r[ndx].rix;
319 info->control.retry_limit = minstrel_get_retry_count(&mi->r[ndx], info); 306 ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);
320 307
321 if (!mrr) { 308 if (!mrr) {
322 ar[0].rate_idx = mi->lowest_rix; 309 ar[1].idx = mi->lowest_rix;
323 ar[0].limit = mp->max_retry; 310 ar[1].count = mp->max_retry;
324 ar[1].rate_idx = -1;
325 return; 311 return;
326 } 312 }
327 313
@@ -336,9 +322,9 @@ minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband,
336 } 322 }
337 mrr_ndx[1] = mi->max_prob_rate; 323 mrr_ndx[1] = mi->max_prob_rate;
338 mrr_ndx[2] = 0; 324 mrr_ndx[2] = 0;
339 for (i = 0; i < 3; i++) { 325 for (i = 1; i < 4; i++) {
340 ar[i].rate_idx = mi->r[mrr_ndx[i]].rix; 326 ar[i].idx = mi->r[mrr_ndx[i - 1]].rix;
341 ar[i].limit = mi->r[mrr_ndx[i]].adjusted_retry_count; 327 ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count;
342 } 328 }
343} 329}
344 330
@@ -532,13 +518,13 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
532 /* maximum time that the hw is allowed to stay in one MRR segment */ 518 /* maximum time that the hw is allowed to stay in one MRR segment */
533 mp->segment_size = 6000; 519 mp->segment_size = 6000;
534 520
535 if (hw->max_altrate_tries > 0) 521 if (hw->max_rate_tries > 0)
536 mp->max_retry = hw->max_altrate_tries; 522 mp->max_retry = hw->max_rate_tries;
537 else 523 else
538 /* safe default, does not necessarily have to match hw properties */ 524 /* safe default, does not necessarily have to match hw properties */
539 mp->max_retry = 7; 525 mp->max_retry = 7;
540 526
541 if (hw->max_altrates >= 3) 527 if (hw->max_rates >= 4)
542 mp->has_mrr = true; 528 mp->has_mrr = true;
543 529
544 mp->hw = hw; 530 mp->hw = hw;