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