diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 172 |
1 files changed, 47 insertions, 125 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5e631ce98d7e..cc9f715c7bfc 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -25,7 +25,8 @@ | |||
25 | #include <net/rtnetlink.h> | 25 | #include <net/rtnetlink.h> |
26 | 26 | ||
27 | #include "ieee80211_i.h" | 27 | #include "ieee80211_i.h" |
28 | #include "ieee80211_rate.h" | 28 | #include "rate.h" |
29 | #include "mesh.h" | ||
29 | #include "wme.h" | 30 | #include "wme.h" |
30 | 31 | ||
31 | /* privid for wiphys to determine whether they belong to us or not */ | 32 | /* privid for wiphys to determine whether they belong to us or not */ |
@@ -41,92 +42,6 @@ const unsigned char bridge_tunnel_header[] = | |||
41 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | 42 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; |
42 | 43 | ||
43 | 44 | ||
44 | static int rate_list_match(const int *rate_list, int rate) | ||
45 | { | ||
46 | int i; | ||
47 | |||
48 | if (!rate_list) | ||
49 | return 0; | ||
50 | |||
51 | for (i = 0; rate_list[i] >= 0; i++) | ||
52 | if (rate_list[i] == rate) | ||
53 | return 1; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | void ieee80211_prepare_rates(struct ieee80211_local *local, | ||
59 | struct ieee80211_hw_mode *mode) | ||
60 | { | ||
61 | int i; | ||
62 | |||
63 | for (i = 0; i < mode->num_rates; i++) { | ||
64 | struct ieee80211_rate *rate = &mode->rates[i]; | ||
65 | |||
66 | rate->flags &= ~(IEEE80211_RATE_SUPPORTED | | ||
67 | IEEE80211_RATE_BASIC); | ||
68 | |||
69 | if (local->supp_rates[mode->mode]) { | ||
70 | if (!rate_list_match(local->supp_rates[mode->mode], | ||
71 | rate->rate)) | ||
72 | continue; | ||
73 | } | ||
74 | |||
75 | rate->flags |= IEEE80211_RATE_SUPPORTED; | ||
76 | |||
77 | /* Use configured basic rate set if it is available. If not, | ||
78 | * use defaults that are sane for most cases. */ | ||
79 | if (local->basic_rates[mode->mode]) { | ||
80 | if (rate_list_match(local->basic_rates[mode->mode], | ||
81 | rate->rate)) | ||
82 | rate->flags |= IEEE80211_RATE_BASIC; | ||
83 | } else switch (mode->mode) { | ||
84 | case MODE_IEEE80211A: | ||
85 | if (rate->rate == 60 || rate->rate == 120 || | ||
86 | rate->rate == 240) | ||
87 | rate->flags |= IEEE80211_RATE_BASIC; | ||
88 | break; | ||
89 | case MODE_IEEE80211B: | ||
90 | if (rate->rate == 10 || rate->rate == 20) | ||
91 | rate->flags |= IEEE80211_RATE_BASIC; | ||
92 | break; | ||
93 | case MODE_IEEE80211G: | ||
94 | if (rate->rate == 10 || rate->rate == 20 || | ||
95 | rate->rate == 55 || rate->rate == 110) | ||
96 | rate->flags |= IEEE80211_RATE_BASIC; | ||
97 | break; | ||
98 | case NUM_IEEE80211_MODES: | ||
99 | /* not useful */ | ||
100 | break; | ||
101 | } | ||
102 | |||
103 | /* Set ERP and MANDATORY flags based on phymode */ | ||
104 | switch (mode->mode) { | ||
105 | case MODE_IEEE80211A: | ||
106 | if (rate->rate == 60 || rate->rate == 120 || | ||
107 | rate->rate == 240) | ||
108 | rate->flags |= IEEE80211_RATE_MANDATORY; | ||
109 | break; | ||
110 | case MODE_IEEE80211B: | ||
111 | if (rate->rate == 10) | ||
112 | rate->flags |= IEEE80211_RATE_MANDATORY; | ||
113 | break; | ||
114 | case MODE_IEEE80211G: | ||
115 | if (rate->rate == 10 || rate->rate == 20 || | ||
116 | rate->rate == 55 || rate->rate == 110 || | ||
117 | rate->rate == 60 || rate->rate == 120 || | ||
118 | rate->rate == 240) | ||
119 | rate->flags |= IEEE80211_RATE_MANDATORY; | ||
120 | break; | ||
121 | case NUM_IEEE80211_MODES: | ||
122 | /* not useful */ | ||
123 | break; | ||
124 | } | ||
125 | if (ieee80211_is_erp_rate(mode->mode, rate->rate)) | ||
126 | rate->flags |= IEEE80211_RATE_ERP; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
131 | enum ieee80211_if_types type) | 46 | enum ieee80211_if_types type) |
132 | { | 47 | { |
@@ -232,17 +147,35 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) | |||
232 | } | 147 | } |
233 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); | 148 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); |
234 | 149 | ||
235 | void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx) | 150 | int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) |
151 | { | ||
152 | int ae = meshhdr->flags & IEEE80211S_FLAGS_AE; | ||
153 | /* 7.1.3.5a.2 */ | ||
154 | switch (ae) { | ||
155 | case 0: | ||
156 | return 5; | ||
157 | case 1: | ||
158 | return 11; | ||
159 | case 2: | ||
160 | return 17; | ||
161 | case 3: | ||
162 | return 23; | ||
163 | default: | ||
164 | return 5; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) | ||
236 | { | 169 | { |
237 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | 170 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; |
238 | 171 | ||
239 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 172 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
240 | if (tx->u.tx.extra_frag) { | 173 | if (tx->extra_frag) { |
241 | struct ieee80211_hdr *fhdr; | 174 | struct ieee80211_hdr *fhdr; |
242 | int i; | 175 | int i; |
243 | for (i = 0; i < tx->u.tx.num_extra_frag; i++) { | 176 | for (i = 0; i < tx->num_extra_frag; i++) { |
244 | fhdr = (struct ieee80211_hdr *) | 177 | fhdr = (struct ieee80211_hdr *) |
245 | tx->u.tx.extra_frag[i]->data; | 178 | tx->extra_frag[i]->data; |
246 | fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 179 | fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
247 | } | 180 | } |
248 | } | 181 | } |
@@ -262,7 +195,7 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | |||
262 | * DIV_ROUND_UP() operations. | 195 | * DIV_ROUND_UP() operations. |
263 | */ | 196 | */ |
264 | 197 | ||
265 | if (local->hw.conf.phymode == MODE_IEEE80211A || erp) { | 198 | if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) { |
266 | /* | 199 | /* |
267 | * OFDM: | 200 | * OFDM: |
268 | * | 201 | * |
@@ -304,15 +237,19 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | |||
304 | /* Exported duration function for driver use */ | 237 | /* Exported duration function for driver use */ |
305 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | 238 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, |
306 | struct ieee80211_vif *vif, | 239 | struct ieee80211_vif *vif, |
307 | size_t frame_len, int rate) | 240 | size_t frame_len, |
241 | struct ieee80211_rate *rate) | ||
308 | { | 242 | { |
309 | struct ieee80211_local *local = hw_to_local(hw); | 243 | struct ieee80211_local *local = hw_to_local(hw); |
310 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 244 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
311 | u16 dur; | 245 | u16 dur; |
312 | int erp; | 246 | int erp; |
313 | 247 | ||
314 | erp = ieee80211_is_erp_rate(hw->conf.phymode, rate); | 248 | erp = 0; |
315 | dur = ieee80211_frame_duration(local, frame_len, rate, erp, | 249 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
250 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
251 | |||
252 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, | ||
316 | sdata->bss_conf.use_short_preamble); | 253 | sdata->bss_conf.use_short_preamble); |
317 | 254 | ||
318 | return cpu_to_le16(dur); | 255 | return cpu_to_le16(dur); |
@@ -332,17 +269,20 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
332 | 269 | ||
333 | short_preamble = sdata->bss_conf.use_short_preamble; | 270 | short_preamble = sdata->bss_conf.use_short_preamble; |
334 | 271 | ||
335 | rate = frame_txctl->rts_rate; | 272 | rate = frame_txctl->rts_cts_rate; |
336 | erp = !!(rate->flags & IEEE80211_RATE_ERP); | 273 | |
274 | erp = 0; | ||
275 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
276 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
337 | 277 | ||
338 | /* CTS duration */ | 278 | /* CTS duration */ |
339 | dur = ieee80211_frame_duration(local, 10, rate->rate, | 279 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, |
340 | erp, short_preamble); | 280 | erp, short_preamble); |
341 | /* Data frame duration */ | 281 | /* Data frame duration */ |
342 | dur += ieee80211_frame_duration(local, frame_len, rate->rate, | 282 | dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, |
343 | erp, short_preamble); | 283 | erp, short_preamble); |
344 | /* ACK duration */ | 284 | /* ACK duration */ |
345 | dur += ieee80211_frame_duration(local, 10, rate->rate, | 285 | dur += ieee80211_frame_duration(local, 10, rate->bitrate, |
346 | erp, short_preamble); | 286 | erp, short_preamble); |
347 | 287 | ||
348 | return cpu_to_le16(dur); | 288 | return cpu_to_le16(dur); |
@@ -363,15 +303,17 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
363 | 303 | ||
364 | short_preamble = sdata->bss_conf.use_short_preamble; | 304 | short_preamble = sdata->bss_conf.use_short_preamble; |
365 | 305 | ||
366 | rate = frame_txctl->rts_rate; | 306 | rate = frame_txctl->rts_cts_rate; |
367 | erp = !!(rate->flags & IEEE80211_RATE_ERP); | 307 | erp = 0; |
308 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
309 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
368 | 310 | ||
369 | /* Data frame duration */ | 311 | /* Data frame duration */ |
370 | dur = ieee80211_frame_duration(local, frame_len, rate->rate, | 312 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, |
371 | erp, short_preamble); | 313 | erp, short_preamble); |
372 | if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) { | 314 | if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) { |
373 | /* ACK duration */ | 315 | /* ACK duration */ |
374 | dur += ieee80211_frame_duration(local, 10, rate->rate, | 316 | dur += ieee80211_frame_duration(local, 10, rate->bitrate, |
375 | erp, short_preamble); | 317 | erp, short_preamble); |
376 | } | 318 | } |
377 | 319 | ||
@@ -379,27 +321,6 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
379 | } | 321 | } |
380 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); | 322 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); |
381 | 323 | ||
382 | struct ieee80211_rate * | ||
383 | ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate) | ||
384 | { | ||
385 | struct ieee80211_hw_mode *mode; | ||
386 | int r; | ||
387 | |||
388 | list_for_each_entry(mode, &local->modes_list, list) { | ||
389 | if (mode->mode != phymode) | ||
390 | continue; | ||
391 | for (r = 0; r < mode->num_rates; r++) { | ||
392 | struct ieee80211_rate *rate = &mode->rates[r]; | ||
393 | if (rate->val == hw_rate || | ||
394 | (rate->flags & IEEE80211_RATE_PREAMBLE2 && | ||
395 | rate->val2 == hw_rate)) | ||
396 | return rate; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | return NULL; | ||
401 | } | ||
402 | |||
403 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | 324 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) |
404 | { | 325 | { |
405 | struct ieee80211_local *local = hw_to_local(hw); | 326 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -480,6 +401,7 @@ void ieee80211_iterate_active_interfaces( | |||
480 | case IEEE80211_IF_TYPE_STA: | 401 | case IEEE80211_IF_TYPE_STA: |
481 | case IEEE80211_IF_TYPE_IBSS: | 402 | case IEEE80211_IF_TYPE_IBSS: |
482 | case IEEE80211_IF_TYPE_WDS: | 403 | case IEEE80211_IF_TYPE_WDS: |
404 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
483 | break; | 405 | break; |
484 | } | 406 | } |
485 | if (sdata->dev == local->mdev) | 407 | if (sdata->dev == local->mdev) |