Root/
1 | /* |
2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/rtnetlink.h> |
13 | #include <linux/module.h> |
14 | #include <linux/slab.h> |
15 | #include "rate.h" |
16 | #include "ieee80211_i.h" |
17 | #include "debugfs.h" |
18 | |
19 | struct rate_control_alg { |
20 | struct list_head list; |
21 | const struct rate_control_ops *ops; |
22 | }; |
23 | |
24 | static LIST_HEAD(rate_ctrl_algs); |
25 | static DEFINE_MUTEX(rate_ctrl_mutex); |
26 | |
27 | static char *ieee80211_default_rc_algo = CONFIG_MAC80211_RC_DEFAULT; |
28 | module_param(ieee80211_default_rc_algo, charp, 0644); |
29 | MODULE_PARM_DESC(ieee80211_default_rc_algo, |
30 | "Default rate control algorithm for mac80211 to use"); |
31 | |
32 | int ieee80211_rate_control_register(const struct rate_control_ops *ops) |
33 | { |
34 | struct rate_control_alg *alg; |
35 | |
36 | if (!ops->name) |
37 | return -EINVAL; |
38 | |
39 | mutex_lock(&rate_ctrl_mutex); |
40 | list_for_each_entry(alg, &rate_ctrl_algs, list) { |
41 | if (!strcmp(alg->ops->name, ops->name)) { |
42 | /* don't register an algorithm twice */ |
43 | WARN_ON(1); |
44 | mutex_unlock(&rate_ctrl_mutex); |
45 | return -EALREADY; |
46 | } |
47 | } |
48 | |
49 | alg = kzalloc(sizeof(*alg), GFP_KERNEL); |
50 | if (alg == NULL) { |
51 | mutex_unlock(&rate_ctrl_mutex); |
52 | return -ENOMEM; |
53 | } |
54 | alg->ops = ops; |
55 | |
56 | list_add_tail(&alg->list, &rate_ctrl_algs); |
57 | mutex_unlock(&rate_ctrl_mutex); |
58 | |
59 | return 0; |
60 | } |
61 | EXPORT_SYMBOL(ieee80211_rate_control_register); |
62 | |
63 | void ieee80211_rate_control_unregister(const struct rate_control_ops *ops) |
64 | { |
65 | struct rate_control_alg *alg; |
66 | |
67 | mutex_lock(&rate_ctrl_mutex); |
68 | list_for_each_entry(alg, &rate_ctrl_algs, list) { |
69 | if (alg->ops == ops) { |
70 | list_del(&alg->list); |
71 | kfree(alg); |
72 | break; |
73 | } |
74 | } |
75 | mutex_unlock(&rate_ctrl_mutex); |
76 | } |
77 | EXPORT_SYMBOL(ieee80211_rate_control_unregister); |
78 | |
79 | static const struct rate_control_ops * |
80 | ieee80211_try_rate_control_ops_get(const char *name) |
81 | { |
82 | struct rate_control_alg *alg; |
83 | const struct rate_control_ops *ops = NULL; |
84 | |
85 | if (!name) |
86 | return NULL; |
87 | |
88 | mutex_lock(&rate_ctrl_mutex); |
89 | list_for_each_entry(alg, &rate_ctrl_algs, list) { |
90 | if (!strcmp(alg->ops->name, name)) { |
91 | ops = alg->ops; |
92 | break; |
93 | } |
94 | } |
95 | mutex_unlock(&rate_ctrl_mutex); |
96 | return ops; |
97 | } |
98 | |
99 | /* Get the rate control algorithm. */ |
100 | static const struct rate_control_ops * |
101 | ieee80211_rate_control_ops_get(const char *name) |
102 | { |
103 | const struct rate_control_ops *ops; |
104 | const char *alg_name; |
105 | |
106 | kparam_block_sysfs_write(ieee80211_default_rc_algo); |
107 | if (!name) |
108 | alg_name = ieee80211_default_rc_algo; |
109 | else |
110 | alg_name = name; |
111 | |
112 | ops = ieee80211_try_rate_control_ops_get(alg_name); |
113 | if (!ops && name) |
114 | /* try default if specific alg requested but not found */ |
115 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); |
116 | |
117 | /* try built-in one if specific alg requested but not found */ |
118 | if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) |
119 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); |
120 | kparam_unblock_sysfs_write(ieee80211_default_rc_algo); |
121 | |
122 | return ops; |
123 | } |
124 | |
125 | #ifdef CONFIG_MAC80211_DEBUGFS |
126 | static ssize_t rcname_read(struct file *file, char __user *userbuf, |
127 | size_t count, loff_t *ppos) |
128 | { |
129 | struct rate_control_ref *ref = file->private_data; |
130 | int len = strlen(ref->ops->name); |
131 | |
132 | return simple_read_from_buffer(userbuf, count, ppos, |
133 | ref->ops->name, len); |
134 | } |
135 | |
136 | static const struct file_operations rcname_ops = { |
137 | .read = rcname_read, |
138 | .open = simple_open, |
139 | .llseek = default_llseek, |
140 | }; |
141 | #endif |
142 | |
143 | static struct rate_control_ref *rate_control_alloc(const char *name, |
144 | struct ieee80211_local *local) |
145 | { |
146 | struct dentry *debugfsdir = NULL; |
147 | struct rate_control_ref *ref; |
148 | |
149 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
150 | if (!ref) |
151 | return NULL; |
152 | ref->local = local; |
153 | ref->ops = ieee80211_rate_control_ops_get(name); |
154 | if (!ref->ops) |
155 | goto free; |
156 | |
157 | #ifdef CONFIG_MAC80211_DEBUGFS |
158 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); |
159 | local->debugfs.rcdir = debugfsdir; |
160 | debugfs_create_file("name", 0400, debugfsdir, ref, &rcname_ops); |
161 | #endif |
162 | |
163 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); |
164 | if (!ref->priv) |
165 | goto free; |
166 | return ref; |
167 | |
168 | free: |
169 | kfree(ref); |
170 | return NULL; |
171 | } |
172 | |
173 | static void rate_control_free(struct rate_control_ref *ctrl_ref) |
174 | { |
175 | ctrl_ref->ops->free(ctrl_ref->priv); |
176 | |
177 | #ifdef CONFIG_MAC80211_DEBUGFS |
178 | debugfs_remove_recursive(ctrl_ref->local->debugfs.rcdir); |
179 | ctrl_ref->local->debugfs.rcdir = NULL; |
180 | #endif |
181 | |
182 | kfree(ctrl_ref); |
183 | } |
184 | |
185 | static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) |
186 | { |
187 | struct sk_buff *skb = txrc->skb; |
188 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
189 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
190 | __le16 fc; |
191 | |
192 | fc = hdr->frame_control; |
193 | |
194 | return (info->flags & (IEEE80211_TX_CTL_NO_ACK | |
195 | IEEE80211_TX_CTL_USE_MINRATE)) || |
196 | !ieee80211_is_data(fc); |
197 | } |
198 | |
199 | static void rc_send_low_basicrate(s8 *idx, u32 basic_rates, |
200 | struct ieee80211_supported_band *sband) |
201 | { |
202 | u8 i; |
203 | |
204 | if (basic_rates == 0) |
205 | return; /* assume basic rates unknown and accept rate */ |
206 | if (*idx < 0) |
207 | return; |
208 | if (basic_rates & (1 << *idx)) |
209 | return; /* selected rate is a basic rate */ |
210 | |
211 | for (i = *idx + 1; i <= sband->n_bitrates; i++) { |
212 | if (basic_rates & (1 << i)) { |
213 | *idx = i; |
214 | return; |
215 | } |
216 | } |
217 | |
218 | /* could not find a basic rate; use original selection */ |
219 | } |
220 | |
221 | static void __rate_control_send_low(struct ieee80211_hw *hw, |
222 | struct ieee80211_supported_band *sband, |
223 | struct ieee80211_sta *sta, |
224 | struct ieee80211_tx_info *info, |
225 | u32 rate_mask) |
226 | { |
227 | int i; |
228 | u32 rate_flags = |
229 | ieee80211_chandef_rate_flags(&hw->conf.chandef); |
230 | |
231 | if ((sband->band == IEEE80211_BAND_2GHZ) && |
232 | (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) |
233 | rate_flags |= IEEE80211_RATE_ERP_G; |
234 | |
235 | info->control.rates[0].idx = 0; |
236 | for (i = 0; i < sband->n_bitrates; i++) { |
237 | if (!(rate_mask & BIT(i))) |
238 | continue; |
239 | |
240 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) |
241 | continue; |
242 | |
243 | if (!rate_supported(sta, sband->band, i)) |
244 | continue; |
245 | |
246 | info->control.rates[0].idx = i; |
247 | break; |
248 | } |
249 | WARN_ON_ONCE(i == sband->n_bitrates); |
250 | |
251 | info->control.rates[0].count = |
252 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
253 | 1 : hw->max_rate_tries; |
254 | |
255 | info->control.skip_table = 1; |
256 | } |
257 | |
258 | |
259 | bool rate_control_send_low(struct ieee80211_sta *pubsta, |
260 | void *priv_sta, |
261 | struct ieee80211_tx_rate_control *txrc) |
262 | { |
263 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
264 | struct ieee80211_supported_band *sband = txrc->sband; |
265 | struct sta_info *sta; |
266 | int mcast_rate; |
267 | bool use_basicrate = false; |
268 | |
269 | if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { |
270 | __rate_control_send_low(txrc->hw, sband, pubsta, info, |
271 | txrc->rate_idx_mask); |
272 | |
273 | if (!pubsta && txrc->bss) { |
274 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; |
275 | if (mcast_rate > 0) { |
276 | info->control.rates[0].idx = mcast_rate - 1; |
277 | return true; |
278 | } |
279 | use_basicrate = true; |
280 | } else if (pubsta) { |
281 | sta = container_of(pubsta, struct sta_info, sta); |
282 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
283 | use_basicrate = true; |
284 | } |
285 | |
286 | if (use_basicrate) |
287 | rc_send_low_basicrate(&info->control.rates[0].idx, |
288 | txrc->bss_conf->basic_rates, |
289 | sband); |
290 | |
291 | return true; |
292 | } |
293 | return false; |
294 | } |
295 | EXPORT_SYMBOL(rate_control_send_low); |
296 | |
297 | static bool rate_idx_match_legacy_mask(struct ieee80211_tx_rate *rate, |
298 | int n_bitrates, u32 mask) |
299 | { |
300 | int j; |
301 | |
302 | /* See whether the selected rate or anything below it is allowed. */ |
303 | for (j = rate->idx; j >= 0; j--) { |
304 | if (mask & (1 << j)) { |
305 | /* Okay, found a suitable rate. Use it. */ |
306 | rate->idx = j; |
307 | return true; |
308 | } |
309 | } |
310 | |
311 | /* Try to find a higher rate that would be allowed */ |
312 | for (j = rate->idx + 1; j < n_bitrates; j++) { |
313 | if (mask & (1 << j)) { |
314 | /* Okay, found a suitable rate. Use it. */ |
315 | rate->idx = j; |
316 | return true; |
317 | } |
318 | } |
319 | return false; |
320 | } |
321 | |
322 | static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate, |
323 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) |
324 | { |
325 | int i, j; |
326 | int ridx, rbit; |
327 | |
328 | ridx = rate->idx / 8; |
329 | rbit = rate->idx % 8; |
330 | |
331 | /* sanity check */ |
332 | if (ridx < 0 || ridx >= IEEE80211_HT_MCS_MASK_LEN) |
333 | return false; |
334 | |
335 | /* See whether the selected rate or anything below it is allowed. */ |
336 | for (i = ridx; i >= 0; i--) { |
337 | for (j = rbit; j >= 0; j--) |
338 | if (mcs_mask[i] & BIT(j)) { |
339 | rate->idx = i * 8 + j; |
340 | return true; |
341 | } |
342 | rbit = 7; |
343 | } |
344 | |
345 | /* Try to find a higher rate that would be allowed */ |
346 | ridx = (rate->idx + 1) / 8; |
347 | rbit = (rate->idx + 1) % 8; |
348 | |
349 | for (i = ridx; i < IEEE80211_HT_MCS_MASK_LEN; i++) { |
350 | for (j = rbit; j < 8; j++) |
351 | if (mcs_mask[i] & BIT(j)) { |
352 | rate->idx = i * 8 + j; |
353 | return true; |
354 | } |
355 | rbit = 0; |
356 | } |
357 | return false; |
358 | } |
359 | |
360 | |
361 | |
362 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, |
363 | struct ieee80211_supported_band *sband, |
364 | enum nl80211_chan_width chan_width, |
365 | u32 mask, |
366 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) |
367 | { |
368 | struct ieee80211_tx_rate alt_rate; |
369 | |
370 | /* handle HT rates */ |
371 | if (rate->flags & IEEE80211_TX_RC_MCS) { |
372 | if (rate_idx_match_mcs_mask(rate, mcs_mask)) |
373 | return; |
374 | |
375 | /* also try the legacy rates. */ |
376 | alt_rate.idx = 0; |
377 | /* keep protection flags */ |
378 | alt_rate.flags = rate->flags & |
379 | (IEEE80211_TX_RC_USE_RTS_CTS | |
380 | IEEE80211_TX_RC_USE_CTS_PROTECT | |
381 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); |
382 | alt_rate.count = rate->count; |
383 | if (rate_idx_match_legacy_mask(&alt_rate, |
384 | sband->n_bitrates, mask)) { |
385 | *rate = alt_rate; |
386 | return; |
387 | } |
388 | } else { |
389 | /* handle legacy rates */ |
390 | if (rate_idx_match_legacy_mask(rate, sband->n_bitrates, mask)) |
391 | return; |
392 | |
393 | /* if HT BSS, and we handle a data frame, also try HT rates */ |
394 | switch (chan_width) { |
395 | case NL80211_CHAN_WIDTH_20_NOHT: |
396 | case NL80211_CHAN_WIDTH_5: |
397 | case NL80211_CHAN_WIDTH_10: |
398 | return; |
399 | default: |
400 | break; |
401 | } |
402 | |
403 | alt_rate.idx = 0; |
404 | /* keep protection flags */ |
405 | alt_rate.flags = rate->flags & |
406 | (IEEE80211_TX_RC_USE_RTS_CTS | |
407 | IEEE80211_TX_RC_USE_CTS_PROTECT | |
408 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE); |
409 | alt_rate.count = rate->count; |
410 | |
411 | alt_rate.flags |= IEEE80211_TX_RC_MCS; |
412 | |
413 | if (chan_width == NL80211_CHAN_WIDTH_40) |
414 | alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
415 | |
416 | if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { |
417 | *rate = alt_rate; |
418 | return; |
419 | } |
420 | } |
421 | |
422 | /* |
423 | * Uh.. No suitable rate exists. This should not really happen with |
424 | * sane TX rate mask configurations. However, should someone manage to |
425 | * configure supported rates and TX rate mask in incompatible way, |
426 | * allow the frame to be transmitted with whatever the rate control |
427 | * selected. |
428 | */ |
429 | } |
430 | |
431 | static void rate_fixup_ratelist(struct ieee80211_vif *vif, |
432 | struct ieee80211_supported_band *sband, |
433 | struct ieee80211_tx_info *info, |
434 | struct ieee80211_tx_rate *rates, |
435 | int max_rates) |
436 | { |
437 | struct ieee80211_rate *rate; |
438 | bool inval = false; |
439 | int i; |
440 | |
441 | /* |
442 | * Set up the RTS/CTS rate as the fastest basic rate |
443 | * that is not faster than the data rate unless there |
444 | * is no basic rate slower than the data rate, in which |
445 | * case we pick the slowest basic rate |
446 | * |
447 | * XXX: Should this check all retry rates? |
448 | */ |
449 | if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) { |
450 | u32 basic_rates = vif->bss_conf.basic_rates; |
451 | s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0; |
452 | |
453 | rate = &sband->bitrates[rates[0].idx]; |
454 | |
455 | for (i = 0; i < sband->n_bitrates; i++) { |
456 | /* must be a basic rate */ |
457 | if (!(basic_rates & BIT(i))) |
458 | continue; |
459 | /* must not be faster than the data rate */ |
460 | if (sband->bitrates[i].bitrate > rate->bitrate) |
461 | continue; |
462 | /* maximum */ |
463 | if (sband->bitrates[baserate].bitrate < |
464 | sband->bitrates[i].bitrate) |
465 | baserate = i; |
466 | } |
467 | |
468 | info->control.rts_cts_rate_idx = baserate; |
469 | } |
470 | |
471 | for (i = 0; i < max_rates; i++) { |
472 | /* |
473 | * make sure there's no valid rate following |
474 | * an invalid one, just in case drivers don't |
475 | * take the API seriously to stop at -1. |
476 | */ |
477 | if (inval) { |
478 | rates[i].idx = -1; |
479 | continue; |
480 | } |
481 | if (rates[i].idx < 0) { |
482 | inval = true; |
483 | continue; |
484 | } |
485 | |
486 | /* |
487 | * For now assume MCS is already set up correctly, this |
488 | * needs to be fixed. |
489 | */ |
490 | if (rates[i].flags & IEEE80211_TX_RC_MCS) { |
491 | WARN_ON(rates[i].idx > 76); |
492 | |
493 | if (!(rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) && |
494 | info->control.use_cts_prot) |
495 | rates[i].flags |= |
496 | IEEE80211_TX_RC_USE_CTS_PROTECT; |
497 | continue; |
498 | } |
499 | |
500 | if (rates[i].flags & IEEE80211_TX_RC_VHT_MCS) { |
501 | WARN_ON(ieee80211_rate_get_vht_mcs(&rates[i]) > 9); |
502 | continue; |
503 | } |
504 | |
505 | /* set up RTS protection if desired */ |
506 | if (info->control.use_rts) { |
507 | rates[i].flags |= IEEE80211_TX_RC_USE_RTS_CTS; |
508 | info->control.use_cts_prot = false; |
509 | } |
510 | |
511 | /* RC is busted */ |
512 | if (WARN_ON_ONCE(rates[i].idx >= sband->n_bitrates)) { |
513 | rates[i].idx = -1; |
514 | continue; |
515 | } |
516 | |
517 | rate = &sband->bitrates[rates[i].idx]; |
518 | |
519 | /* set up short preamble */ |
520 | if (info->control.short_preamble && |
521 | rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) |
522 | rates[i].flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; |
523 | |
524 | /* set up G protection */ |
525 | if (!(rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) && |
526 | info->control.use_cts_prot && |
527 | rate->flags & IEEE80211_RATE_ERP_G) |
528 | rates[i].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; |
529 | } |
530 | } |
531 | |
532 | |
533 | static void rate_control_fill_sta_table(struct ieee80211_sta *sta, |
534 | struct ieee80211_tx_info *info, |
535 | struct ieee80211_tx_rate *rates, |
536 | int max_rates) |
537 | { |
538 | struct ieee80211_sta_rates *ratetbl = NULL; |
539 | int i; |
540 | |
541 | if (sta && !info->control.skip_table) |
542 | ratetbl = rcu_dereference(sta->rates); |
543 | |
544 | /* Fill remaining rate slots with data from the sta rate table. */ |
545 | max_rates = min_t(int, max_rates, IEEE80211_TX_RATE_TABLE_SIZE); |
546 | for (i = 0; i < max_rates; i++) { |
547 | if (i < ARRAY_SIZE(info->control.rates) && |
548 | info->control.rates[i].idx >= 0 && |
549 | info->control.rates[i].count) { |
550 | if (rates != info->control.rates) |
551 | rates[i] = info->control.rates[i]; |
552 | } else if (ratetbl) { |
553 | rates[i].idx = ratetbl->rate[i].idx; |
554 | rates[i].flags = ratetbl->rate[i].flags; |
555 | if (info->control.use_rts) |
556 | rates[i].count = ratetbl->rate[i].count_rts; |
557 | else if (info->control.use_cts_prot) |
558 | rates[i].count = ratetbl->rate[i].count_cts; |
559 | else |
560 | rates[i].count = ratetbl->rate[i].count; |
561 | } else { |
562 | rates[i].idx = -1; |
563 | rates[i].count = 0; |
564 | } |
565 | |
566 | if (rates[i].idx < 0 || !rates[i].count) |
567 | break; |
568 | } |
569 | } |
570 | |
571 | static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, |
572 | struct ieee80211_sta *sta, |
573 | struct ieee80211_supported_band *sband, |
574 | struct ieee80211_tx_info *info, |
575 | struct ieee80211_tx_rate *rates, |
576 | int max_rates) |
577 | { |
578 | enum nl80211_chan_width chan_width; |
579 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; |
580 | bool has_mcs_mask; |
581 | u32 mask; |
582 | u32 rate_flags; |
583 | int i; |
584 | |
585 | /* |
586 | * Try to enforce the rateidx mask the user wanted. skip this if the |
587 | * default mask (allow all rates) is used to save some processing for |
588 | * the common case. |
589 | */ |
590 | mask = sdata->rc_rateidx_mask[info->band]; |
591 | has_mcs_mask = sdata->rc_has_mcs_mask[info->band]; |
592 | rate_flags = |
593 | ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); |
594 | for (i = 0; i < sband->n_bitrates; i++) |
595 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) |
596 | mask &= ~BIT(i); |
597 | |
598 | if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask) |
599 | return; |
600 | |
601 | if (has_mcs_mask) |
602 | memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band], |
603 | sizeof(mcs_mask)); |
604 | else |
605 | memset(mcs_mask, 0xff, sizeof(mcs_mask)); |
606 | |
607 | if (sta) { |
608 | /* Filter out rates that the STA does not support */ |
609 | mask &= sta->supp_rates[info->band]; |
610 | for (i = 0; i < sizeof(mcs_mask); i++) |
611 | mcs_mask[i] &= sta->ht_cap.mcs.rx_mask[i]; |
612 | } |
613 | |
614 | /* |
615 | * Make sure the rate index selected for each TX rate is |
616 | * included in the configured mask and change the rate indexes |
617 | * if needed. |
618 | */ |
619 | chan_width = sdata->vif.bss_conf.chandef.width; |
620 | for (i = 0; i < max_rates; i++) { |
621 | /* Skip invalid rates */ |
622 | if (rates[i].idx < 0) |
623 | break; |
624 | |
625 | rate_idx_match_mask(&rates[i], sband, chan_width, mask, |
626 | mcs_mask); |
627 | } |
628 | } |
629 | |
630 | void ieee80211_get_tx_rates(struct ieee80211_vif *vif, |
631 | struct ieee80211_sta *sta, |
632 | struct sk_buff *skb, |
633 | struct ieee80211_tx_rate *dest, |
634 | int max_rates) |
635 | { |
636 | struct ieee80211_sub_if_data *sdata; |
637 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
638 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
639 | struct ieee80211_supported_band *sband; |
640 | |
641 | rate_control_fill_sta_table(sta, info, dest, max_rates); |
642 | |
643 | if (!vif) |
644 | return; |
645 | |
646 | sdata = vif_to_sdata(vif); |
647 | sband = sdata->local->hw.wiphy->bands[info->band]; |
648 | |
649 | if (ieee80211_is_data(hdr->frame_control)) |
650 | rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates); |
651 | |
652 | if (dest[0].idx < 0) |
653 | __rate_control_send_low(&sdata->local->hw, sband, sta, info, |
654 | sdata->rc_rateidx_mask[info->band]); |
655 | |
656 | if (sta) |
657 | rate_fixup_ratelist(vif, sband, info, dest, max_rates); |
658 | } |
659 | EXPORT_SYMBOL(ieee80211_get_tx_rates); |
660 | |
661 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
662 | struct sta_info *sta, |
663 | struct ieee80211_tx_rate_control *txrc) |
664 | { |
665 | struct rate_control_ref *ref = sdata->local->rate_ctrl; |
666 | void *priv_sta = NULL; |
667 | struct ieee80211_sta *ista = NULL; |
668 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
669 | int i; |
670 | |
671 | if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) { |
672 | ista = &sta->sta; |
673 | priv_sta = sta->rate_ctrl_priv; |
674 | } |
675 | |
676 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
677 | info->control.rates[i].idx = -1; |
678 | info->control.rates[i].flags = 0; |
679 | info->control.rates[i].count = 0; |
680 | } |
681 | |
682 | if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) |
683 | return; |
684 | |
685 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); |
686 | |
687 | if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_RC_TABLE) |
688 | return; |
689 | |
690 | ieee80211_get_tx_rates(&sdata->vif, ista, txrc->skb, |
691 | info->control.rates, |
692 | ARRAY_SIZE(info->control.rates)); |
693 | } |
694 | |
695 | int rate_control_set_rates(struct ieee80211_hw *hw, |
696 | struct ieee80211_sta *pubsta, |
697 | struct ieee80211_sta_rates *rates) |
698 | { |
699 | struct ieee80211_sta_rates *old; |
700 | |
701 | /* |
702 | * mac80211 guarantees that this function will not be called |
703 | * concurrently, so the following RCU access is safe, even without |
704 | * extra locking. This can not be checked easily, so we just set |
705 | * the condition to true. |
706 | */ |
707 | old = rcu_dereference_protected(pubsta->rates, true); |
708 | rcu_assign_pointer(pubsta->rates, rates); |
709 | if (old) |
710 | kfree_rcu(old, rcu_head); |
711 | |
712 | return 0; |
713 | } |
714 | EXPORT_SYMBOL(rate_control_set_rates); |
715 | |
716 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
717 | const char *name) |
718 | { |
719 | struct rate_control_ref *ref; |
720 | |
721 | ASSERT_RTNL(); |
722 | |
723 | if (local->open_count) |
724 | return -EBUSY; |
725 | |
726 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { |
727 | if (WARN_ON(!local->ops->set_rts_threshold)) |
728 | return -EINVAL; |
729 | return 0; |
730 | } |
731 | |
732 | ref = rate_control_alloc(name, local); |
733 | if (!ref) { |
734 | wiphy_warn(local->hw.wiphy, |
735 | "Failed to select rate control algorithm\n"); |
736 | return -ENOENT; |
737 | } |
738 | |
739 | WARN_ON(local->rate_ctrl); |
740 | local->rate_ctrl = ref; |
741 | |
742 | wiphy_debug(local->hw.wiphy, "Selected rate control algorithm '%s'\n", |
743 | ref->ops->name); |
744 | |
745 | return 0; |
746 | } |
747 | |
748 | void rate_control_deinitialize(struct ieee80211_local *local) |
749 | { |
750 | struct rate_control_ref *ref; |
751 | |
752 | ref = local->rate_ctrl; |
753 | |
754 | if (!ref) |
755 | return; |
756 | |
757 | local->rate_ctrl = NULL; |
758 | rate_control_free(ref); |
759 | } |
760 | |
761 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9