diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-10-21 06:40:02 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-31 19:00:23 -0400 |
commit | e6a9854b05c1a6af1308fe2b8c68f35abf28a3ee (patch) | |
tree | 241f611f8194586ccabf61bacb060508773b9d05 /net/mac80211/rc80211_minstrel.c | |
parent | cb121bad67a32cde37adc2729b7e18aa4fd3063e (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.c | 72 |
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 | ||
236 | void | 226 | void |
237 | minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, | 227 | minstrel_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; |