aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rate.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/rate.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/rate.c')
-rw-r--r--net/mac80211/rate.c52
1 files changed, 24 insertions, 28 deletions
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 5d786720d935..3fa7ab285066 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -199,48 +199,44 @@ static void rate_control_release(struct kref *kref)
199} 199}
200 200
201void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, 201void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
202 struct ieee80211_supported_band *sband, 202 struct sta_info *sta,
203 struct sta_info *sta, struct sk_buff *skb, 203 struct ieee80211_tx_rate_control *txrc)
204 struct rate_selection *sel)
205{ 204{
206 struct rate_control_ref *ref = sdata->local->rate_ctrl; 205 struct rate_control_ref *ref = sdata->local->rate_ctrl;
207 void *priv_sta = NULL; 206 void *priv_sta = NULL;
208 struct ieee80211_sta *ista = NULL; 207 struct ieee80211_sta *ista = NULL;
208 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
209 int i; 209 int i;
210 210
211 sel->rate_idx = -1;
212 sel->nonerp_idx = -1;
213 sel->probe_idx = -1;
214 sel->max_rate_idx = sdata->max_ratectrl_rateidx;
215
216 if (sta) { 211 if (sta) {
217 ista = &sta->sta; 212 ista = &sta->sta;
218 priv_sta = sta->rate_ctrl_priv; 213 priv_sta = sta->rate_ctrl_priv;
219 } 214 }
220 215
216 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
217 info->control.rates[i].idx = -1;
218 info->control.rates[i].flags = 0;
219 info->control.rates[i].count = 1;
220 }
221
221 if (sta && sdata->force_unicast_rateidx > -1) 222 if (sta && sdata->force_unicast_rateidx > -1)
222 sel->rate_idx = sdata->force_unicast_rateidx; 223 info->control.rates[0].idx = sdata->force_unicast_rateidx;
223 else 224 else
224 ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); 225 ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
225 226
226 if (sdata->max_ratectrl_rateidx > -1 && 227 /*
227 sel->rate_idx > sdata->max_ratectrl_rateidx) 228 * try to enforce the maximum rate the user wanted
228 sel->rate_idx = sdata->max_ratectrl_rateidx; 229 */
229 230 if (sdata->max_ratectrl_rateidx > -1)
230 BUG_ON(sel->rate_idx < 0); 231 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
231 232 if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS)
232 /* Select a non-ERP backup rate. */ 233 continue;
233 if (sel->nonerp_idx < 0) { 234 info->control.rates[i].idx =
234 for (i = 0; i < sband->n_bitrates; i++) { 235 min_t(s8, info->control.rates[i].idx,
235 struct ieee80211_rate *rate = &sband->bitrates[i]; 236 sdata->max_ratectrl_rateidx);
236 if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate)
237 break;
238
239 if (rate_supported(ista, sband->band, i) &&
240 !(rate->flags & IEEE80211_RATE_ERP_G))
241 sel->nonerp_idx = i;
242 }
243 } 237 }
238
239 BUG_ON(info->control.rates[0].idx < 0);
244} 240}
245 241
246struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) 242struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)