diff options
Diffstat (limited to 'net/mac80211/rate.c')
-rw-r--r-- | net/mac80211/rate.c | 113 |
1 files changed, 95 insertions, 18 deletions
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index b33efc4fc267..6d0bd198af19 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
13 | #include <linux/slab.h> | ||
13 | #include "rate.h" | 14 | #include "rate.h" |
14 | #include "ieee80211_i.h" | 15 | #include "ieee80211_i.h" |
15 | #include "debugfs.h" | 16 | #include "debugfs.h" |
@@ -145,7 +146,7 @@ static const struct file_operations rcname_ops = { | |||
145 | }; | 146 | }; |
146 | #endif | 147 | #endif |
147 | 148 | ||
148 | struct rate_control_ref *rate_control_alloc(const char *name, | 149 | static struct rate_control_ref *rate_control_alloc(const char *name, |
149 | struct ieee80211_local *local) | 150 | struct ieee80211_local *local) |
150 | { | 151 | { |
151 | struct dentry *debugfsdir = NULL; | 152 | struct dentry *debugfsdir = NULL; |
@@ -163,8 +164,7 @@ struct rate_control_ref *rate_control_alloc(const char *name, | |||
163 | #ifdef CONFIG_MAC80211_DEBUGFS | 164 | #ifdef CONFIG_MAC80211_DEBUGFS |
164 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); | 165 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); |
165 | local->debugfs.rcdir = debugfsdir; | 166 | local->debugfs.rcdir = debugfsdir; |
166 | local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir, | 167 | debugfs_create_file("name", 0400, debugfsdir, ref, &rcname_ops); |
167 | ref, &rcname_ops); | ||
168 | #endif | 168 | #endif |
169 | 169 | ||
170 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); | 170 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); |
@@ -188,9 +188,7 @@ static void rate_control_release(struct kref *kref) | |||
188 | ctrl_ref->ops->free(ctrl_ref->priv); | 188 | ctrl_ref->ops->free(ctrl_ref->priv); |
189 | 189 | ||
190 | #ifdef CONFIG_MAC80211_DEBUGFS | 190 | #ifdef CONFIG_MAC80211_DEBUGFS |
191 | debugfs_remove(ctrl_ref->local->debugfs.rcname); | 191 | debugfs_remove_recursive(ctrl_ref->local->debugfs.rcdir); |
192 | ctrl_ref->local->debugfs.rcname = NULL; | ||
193 | debugfs_remove(ctrl_ref->local->debugfs.rcdir); | ||
194 | ctrl_ref->local->debugfs.rcdir = NULL; | 192 | ctrl_ref->local->debugfs.rcdir = NULL; |
195 | #endif | 193 | #endif |
196 | 194 | ||
@@ -210,6 +208,27 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) | |||
210 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); | 208 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); |
211 | } | 209 | } |
212 | 210 | ||
211 | static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx) | ||
212 | { | ||
213 | u8 i; | ||
214 | |||
215 | if (basic_rates == 0) | ||
216 | return; /* assume basic rates unknown and accept rate */ | ||
217 | if (*idx < 0) | ||
218 | return; | ||
219 | if (basic_rates & (1 << *idx)) | ||
220 | return; /* selected rate is a basic rate */ | ||
221 | |||
222 | for (i = *idx + 1; i <= max_rate_idx; i++) { | ||
223 | if (basic_rates & (1 << i)) { | ||
224 | *idx = i; | ||
225 | return; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | /* could not find a basic rate; use original selection */ | ||
230 | } | ||
231 | |||
213 | bool rate_control_send_low(struct ieee80211_sta *sta, | 232 | bool rate_control_send_low(struct ieee80211_sta *sta, |
214 | void *priv_sta, | 233 | void *priv_sta, |
215 | struct ieee80211_tx_rate_control *txrc) | 234 | struct ieee80211_tx_rate_control *txrc) |
@@ -221,12 +240,48 @@ bool rate_control_send_low(struct ieee80211_sta *sta, | |||
221 | info->control.rates[0].count = | 240 | info->control.rates[0].count = |
222 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | 241 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
223 | 1 : txrc->hw->max_rate_tries; | 242 | 1 : txrc->hw->max_rate_tries; |
243 | if (!sta && txrc->ap) | ||
244 | rc_send_low_broadcast(&info->control.rates[0].idx, | ||
245 | txrc->bss_conf->basic_rates, | ||
246 | txrc->sband->n_bitrates); | ||
224 | return true; | 247 | return true; |
225 | } | 248 | } |
226 | return false; | 249 | return false; |
227 | } | 250 | } |
228 | EXPORT_SYMBOL(rate_control_send_low); | 251 | EXPORT_SYMBOL(rate_control_send_low); |
229 | 252 | ||
253 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | ||
254 | int n_bitrates, u32 mask) | ||
255 | { | ||
256 | int j; | ||
257 | |||
258 | /* See whether the selected rate or anything below it is allowed. */ | ||
259 | for (j = rate->idx; j >= 0; j--) { | ||
260 | if (mask & (1 << j)) { | ||
261 | /* Okay, found a suitable rate. Use it. */ | ||
262 | rate->idx = j; | ||
263 | return; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | /* Try to find a higher rate that would be allowed */ | ||
268 | for (j = rate->idx + 1; j < n_bitrates; j++) { | ||
269 | if (mask & (1 << j)) { | ||
270 | /* Okay, found a suitable rate. Use it. */ | ||
271 | rate->idx = j; | ||
272 | return; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * Uh.. No suitable rate exists. This should not really happen with | ||
278 | * sane TX rate mask configurations. However, should someone manage to | ||
279 | * configure supported rates and TX rate mask in incompatible way, | ||
280 | * allow the frame to be transmitted with whatever the rate control | ||
281 | * selected. | ||
282 | */ | ||
283 | } | ||
284 | |||
230 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 285 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
231 | struct sta_info *sta, | 286 | struct sta_info *sta, |
232 | struct ieee80211_tx_rate_control *txrc) | 287 | struct ieee80211_tx_rate_control *txrc) |
@@ -236,6 +291,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
236 | struct ieee80211_sta *ista = NULL; | 291 | struct ieee80211_sta *ista = NULL; |
237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | 292 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
238 | int i; | 293 | int i; |
294 | u32 mask; | ||
239 | 295 | ||
240 | if (sta) { | 296 | if (sta) { |
241 | ista = &sta->sta; | 297 | ista = &sta->sta; |
@@ -248,23 +304,34 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
248 | info->control.rates[i].count = 1; | 304 | info->control.rates[i].count = 1; |
249 | } | 305 | } |
250 | 306 | ||
251 | if (sta && sdata->force_unicast_rateidx > -1) { | 307 | if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) |
252 | info->control.rates[0].idx = sdata->force_unicast_rateidx; | 308 | return; |
253 | } else { | 309 | |
254 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); | 310 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); |
255 | info->flags |= IEEE80211_TX_INTFL_RCALGO; | ||
256 | } | ||
257 | 311 | ||
258 | /* | 312 | /* |
259 | * try to enforce the maximum rate the user wanted | 313 | * Try to enforce the rateidx mask the user wanted. skip this if the |
314 | * default mask (allow all rates) is used to save some processing for | ||
315 | * the common case. | ||
260 | */ | 316 | */ |
261 | if (sdata->max_ratectrl_rateidx > -1) | 317 | mask = sdata->rc_rateidx_mask[info->band]; |
318 | if (mask != (1 << txrc->sband->n_bitrates) - 1) { | ||
319 | if (sta) { | ||
320 | /* Filter out rates that the STA does not support */ | ||
321 | mask &= sta->sta.supp_rates[info->band]; | ||
322 | } | ||
323 | /* | ||
324 | * Make sure the rate index selected for each TX rate is | ||
325 | * included in the configured mask and change the rate indexes | ||
326 | * if needed. | ||
327 | */ | ||
262 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 328 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
329 | /* Rate masking supports only legacy rates for now */ | ||
263 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) | 330 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) |
264 | continue; | 331 | continue; |
265 | info->control.rates[i].idx = | 332 | rate_idx_match_mask(&info->control.rates[i], |
266 | min_t(s8, info->control.rates[i].idx, | 333 | txrc->sband->n_bitrates, mask); |
267 | sdata->max_ratectrl_rateidx); | 334 | } |
268 | } | 335 | } |
269 | 336 | ||
270 | BUG_ON(info->control.rates[0].idx < 0); | 337 | BUG_ON(info->control.rates[0].idx < 0); |
@@ -287,9 +354,16 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
287 | struct rate_control_ref *ref, *old; | 354 | struct rate_control_ref *ref, *old; |
288 | 355 | ||
289 | ASSERT_RTNL(); | 356 | ASSERT_RTNL(); |
357 | |||
290 | if (local->open_count) | 358 | if (local->open_count) |
291 | return -EBUSY; | 359 | return -EBUSY; |
292 | 360 | ||
361 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { | ||
362 | if (WARN_ON(!local->ops->set_rts_threshold)) | ||
363 | return -EINVAL; | ||
364 | return 0; | ||
365 | } | ||
366 | |||
293 | ref = rate_control_alloc(name, local); | 367 | ref = rate_control_alloc(name, local); |
294 | if (!ref) { | 368 | if (!ref) { |
295 | printk(KERN_WARNING "%s: Failed to select rate control " | 369 | printk(KERN_WARNING "%s: Failed to select rate control " |
@@ -308,7 +382,6 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
308 | "algorithm '%s'\n", wiphy_name(local->hw.wiphy), | 382 | "algorithm '%s'\n", wiphy_name(local->hw.wiphy), |
309 | ref->ops->name); | 383 | ref->ops->name); |
310 | 384 | ||
311 | |||
312 | return 0; | 385 | return 0; |
313 | } | 386 | } |
314 | 387 | ||
@@ -317,6 +390,10 @@ void rate_control_deinitialize(struct ieee80211_local *local) | |||
317 | struct rate_control_ref *ref; | 390 | struct rate_control_ref *ref; |
318 | 391 | ||
319 | ref = local->rate_ctrl; | 392 | ref = local->rate_ctrl; |
393 | |||
394 | if (!ref) | ||
395 | return; | ||
396 | |||
320 | local->rate_ctrl = NULL; | 397 | local->rate_ctrl = NULL; |
321 | rate_control_put(ref); | 398 | rate_control_put(ref); |
322 | } | 399 | } |