diff options
158 files changed, 4630 insertions, 2843 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl new file mode 100644 index 000000000000..b84c9282828f --- /dev/null +++ b/Documentation/DocBook/80211.tmpl | |||
@@ -0,0 +1,496 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!DOCTYPE set PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" | ||
3 | "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> | ||
4 | <set> | ||
5 | <setinfo> | ||
6 | <title>The 802.11 subsystems – for kernel developers</title> | ||
7 | <subtitle> | ||
8 | Explaining wireless 802.11 networking in the Linux kernel | ||
9 | </subtitle> | ||
10 | |||
11 | <copyright> | ||
12 | <year>2007-2009</year> | ||
13 | <holder>Johannes Berg</holder> | ||
14 | </copyright> | ||
15 | |||
16 | <authorgroup> | ||
17 | <author> | ||
18 | <firstname>Johannes</firstname> | ||
19 | <surname>Berg</surname> | ||
20 | <affiliation> | ||
21 | <address><email>johannes@sipsolutions.net</email></address> | ||
22 | </affiliation> | ||
23 | </author> | ||
24 | </authorgroup> | ||
25 | |||
26 | <legalnotice> | ||
27 | <para> | ||
28 | This documentation is free software; you can redistribute | ||
29 | it and/or modify it under the terms of the GNU General Public | ||
30 | License version 2 as published by the Free Software Foundation. | ||
31 | </para> | ||
32 | <para> | ||
33 | This documentation is distributed in the hope that it will be | ||
34 | useful, but WITHOUT ANY WARRANTY; without even the implied | ||
35 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
36 | See the GNU General Public License for more details. | ||
37 | </para> | ||
38 | <para> | ||
39 | You should have received a copy of the GNU General Public | ||
40 | License along with this documentation; if not, write to the Free | ||
41 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
42 | MA 02111-1307 USA | ||
43 | </para> | ||
44 | <para> | ||
45 | For more details see the file COPYING in the source | ||
46 | distribution of Linux. | ||
47 | </para> | ||
48 | </legalnotice> | ||
49 | |||
50 | <abstract> | ||
51 | <para> | ||
52 | These books attempt to give a description of the | ||
53 | various subsystems that play a role in 802.11 wireless | ||
54 | networking in Linux. Since these books are for kernel | ||
55 | developers they attempts to document the structures | ||
56 | and functions used in the kernel as well as giving a | ||
57 | higher-level overview. | ||
58 | </para> | ||
59 | <para> | ||
60 | The reader is expected to be familiar with the 802.11 | ||
61 | standard as published by the IEEE in 802.11-2007 (or | ||
62 | possibly later versions). References to this standard | ||
63 | will be given as "802.11-2007 8.1.5". | ||
64 | </para> | ||
65 | </abstract> | ||
66 | </setinfo> | ||
67 | <book id="cfg80211-developers-guide"> | ||
68 | !Ainclude/net/cfg80211.h | ||
69 | <bookinfo> | ||
70 | <title>The cfg80211 subsystem</title> | ||
71 | |||
72 | <abstract> | ||
73 | !Pinclude/net/cfg80211.h Introduction | ||
74 | </abstract> | ||
75 | </bookinfo> | ||
76 | <chapter> | ||
77 | <title>Device registration</title> | ||
78 | !Pinclude/net/cfg80211.h Device registration | ||
79 | !Finclude/net/cfg80211.h ieee80211_band | ||
80 | !Finclude/net/cfg80211.h ieee80211_channel_flags | ||
81 | !Finclude/net/cfg80211.h ieee80211_channel | ||
82 | !Finclude/net/cfg80211.h ieee80211_rate_flags | ||
83 | !Finclude/net/cfg80211.h ieee80211_rate | ||
84 | !Finclude/net/cfg80211.h ieee80211_sta_ht_cap | ||
85 | !Finclude/net/cfg80211.h ieee80211_supported_band | ||
86 | !Finclude/net/cfg80211.h cfg80211_signal_type | ||
87 | !Finclude/net/cfg80211.h wiphy_params_flags | ||
88 | !Finclude/net/cfg80211.h wiphy_flags | ||
89 | !Finclude/net/cfg80211.h wiphy | ||
90 | !Finclude/net/cfg80211.h wireless_dev | ||
91 | !Finclude/net/cfg80211.h wiphy_new | ||
92 | !Finclude/net/cfg80211.h wiphy_register | ||
93 | !Finclude/net/cfg80211.h wiphy_unregister | ||
94 | !Finclude/net/cfg80211.h wiphy_free | ||
95 | |||
96 | !Finclude/net/cfg80211.h wiphy_name | ||
97 | !Finclude/net/cfg80211.h wiphy_dev | ||
98 | !Finclude/net/cfg80211.h wiphy_priv | ||
99 | !Finclude/net/cfg80211.h priv_to_wiphy | ||
100 | !Finclude/net/cfg80211.h set_wiphy_dev | ||
101 | !Finclude/net/cfg80211.h wdev_priv | ||
102 | </chapter> | ||
103 | <chapter> | ||
104 | <title>Actions and configuration</title> | ||
105 | !Pinclude/net/cfg80211.h Actions and configuration | ||
106 | !Finclude/net/cfg80211.h cfg80211_ops | ||
107 | !Finclude/net/cfg80211.h vif_params | ||
108 | !Finclude/net/cfg80211.h key_params | ||
109 | !Finclude/net/cfg80211.h survey_info_flags | ||
110 | !Finclude/net/cfg80211.h survey_info | ||
111 | !Finclude/net/cfg80211.h beacon_parameters | ||
112 | !Finclude/net/cfg80211.h plink_actions | ||
113 | !Finclude/net/cfg80211.h station_parameters | ||
114 | !Finclude/net/cfg80211.h station_info_flags | ||
115 | !Finclude/net/cfg80211.h rate_info_flags | ||
116 | !Finclude/net/cfg80211.h rate_info | ||
117 | !Finclude/net/cfg80211.h station_info | ||
118 | !Finclude/net/cfg80211.h monitor_flags | ||
119 | !Finclude/net/cfg80211.h mpath_info_flags | ||
120 | !Finclude/net/cfg80211.h mpath_info | ||
121 | !Finclude/net/cfg80211.h bss_parameters | ||
122 | !Finclude/net/cfg80211.h ieee80211_txq_params | ||
123 | !Finclude/net/cfg80211.h cfg80211_crypto_settings | ||
124 | !Finclude/net/cfg80211.h cfg80211_auth_request | ||
125 | !Finclude/net/cfg80211.h cfg80211_assoc_request | ||
126 | !Finclude/net/cfg80211.h cfg80211_deauth_request | ||
127 | !Finclude/net/cfg80211.h cfg80211_disassoc_request | ||
128 | !Finclude/net/cfg80211.h cfg80211_ibss_params | ||
129 | !Finclude/net/cfg80211.h cfg80211_connect_params | ||
130 | !Finclude/net/cfg80211.h cfg80211_pmksa | ||
131 | !Finclude/net/cfg80211.h cfg80211_send_rx_auth | ||
132 | !Finclude/net/cfg80211.h cfg80211_send_auth_timeout | ||
133 | !Finclude/net/cfg80211.h __cfg80211_auth_canceled | ||
134 | !Finclude/net/cfg80211.h cfg80211_send_rx_assoc | ||
135 | !Finclude/net/cfg80211.h cfg80211_send_assoc_timeout | ||
136 | !Finclude/net/cfg80211.h cfg80211_send_deauth | ||
137 | !Finclude/net/cfg80211.h __cfg80211_send_deauth | ||
138 | !Finclude/net/cfg80211.h cfg80211_send_disassoc | ||
139 | !Finclude/net/cfg80211.h __cfg80211_send_disassoc | ||
140 | !Finclude/net/cfg80211.h cfg80211_ibss_joined | ||
141 | !Finclude/net/cfg80211.h cfg80211_connect_result | ||
142 | !Finclude/net/cfg80211.h cfg80211_roamed | ||
143 | !Finclude/net/cfg80211.h cfg80211_disconnected | ||
144 | !Finclude/net/cfg80211.h cfg80211_ready_on_channel | ||
145 | !Finclude/net/cfg80211.h cfg80211_remain_on_channel_expired | ||
146 | !Finclude/net/cfg80211.h cfg80211_new_sta | ||
147 | !Finclude/net/cfg80211.h cfg80211_rx_mgmt | ||
148 | !Finclude/net/cfg80211.h cfg80211_mgmt_tx_status | ||
149 | !Finclude/net/cfg80211.h cfg80211_cqm_rssi_notify | ||
150 | !Finclude/net/cfg80211.h cfg80211_michael_mic_failure | ||
151 | </chapter> | ||
152 | <chapter> | ||
153 | <title>Scanning and BSS list handling</title> | ||
154 | !Pinclude/net/cfg80211.h Scanning and BSS list handling | ||
155 | !Finclude/net/cfg80211.h cfg80211_ssid | ||
156 | !Finclude/net/cfg80211.h cfg80211_scan_request | ||
157 | !Finclude/net/cfg80211.h cfg80211_scan_done | ||
158 | !Finclude/net/cfg80211.h cfg80211_bss | ||
159 | !Finclude/net/cfg80211.h cfg80211_inform_bss_frame | ||
160 | !Finclude/net/cfg80211.h cfg80211_inform_bss | ||
161 | !Finclude/net/cfg80211.h cfg80211_unlink_bss | ||
162 | !Finclude/net/cfg80211.h cfg80211_find_ie | ||
163 | !Finclude/net/cfg80211.h ieee80211_bss_get_ie | ||
164 | </chapter> | ||
165 | <chapter> | ||
166 | <title>Utility functions</title> | ||
167 | !Pinclude/net/cfg80211.h Utility functions | ||
168 | !Finclude/net/cfg80211.h ieee80211_channel_to_frequency | ||
169 | !Finclude/net/cfg80211.h ieee80211_frequency_to_channel | ||
170 | !Finclude/net/cfg80211.h ieee80211_get_channel | ||
171 | !Finclude/net/cfg80211.h ieee80211_get_response_rate | ||
172 | !Finclude/net/cfg80211.h ieee80211_hdrlen | ||
173 | !Finclude/net/cfg80211.h ieee80211_get_hdrlen_from_skb | ||
174 | !Finclude/net/cfg80211.h ieee80211_radiotap_iterator | ||
175 | </chapter> | ||
176 | <chapter> | ||
177 | <title>Data path helpers</title> | ||
178 | !Pinclude/net/cfg80211.h Data path helpers | ||
179 | !Finclude/net/cfg80211.h ieee80211_data_to_8023 | ||
180 | !Finclude/net/cfg80211.h ieee80211_data_from_8023 | ||
181 | !Finclude/net/cfg80211.h ieee80211_amsdu_to_8023s | ||
182 | !Finclude/net/cfg80211.h cfg80211_classify8021d | ||
183 | </chapter> | ||
184 | <chapter> | ||
185 | <title>Regulatory enforcement infrastructure</title> | ||
186 | !Pinclude/net/cfg80211.h Regulatory enforcement infrastructure | ||
187 | !Finclude/net/cfg80211.h regulatory_hint | ||
188 | !Finclude/net/cfg80211.h wiphy_apply_custom_regulatory | ||
189 | !Finclude/net/cfg80211.h freq_reg_info | ||
190 | </chapter> | ||
191 | <chapter> | ||
192 | <title>RFkill integration</title> | ||
193 | !Pinclude/net/cfg80211.h RFkill integration | ||
194 | !Finclude/net/cfg80211.h wiphy_rfkill_set_hw_state | ||
195 | !Finclude/net/cfg80211.h wiphy_rfkill_start_polling | ||
196 | !Finclude/net/cfg80211.h wiphy_rfkill_stop_polling | ||
197 | </chapter> | ||
198 | <chapter> | ||
199 | <title>Test mode</title> | ||
200 | !Pinclude/net/cfg80211.h Test mode | ||
201 | !Finclude/net/cfg80211.h cfg80211_testmode_alloc_reply_skb | ||
202 | !Finclude/net/cfg80211.h cfg80211_testmode_reply | ||
203 | !Finclude/net/cfg80211.h cfg80211_testmode_alloc_event_skb | ||
204 | !Finclude/net/cfg80211.h cfg80211_testmode_event | ||
205 | </chapter> | ||
206 | </book> | ||
207 | <book id="mac80211-developers-guide"> | ||
208 | <bookinfo> | ||
209 | <title>The mac80211 subsystem</title> | ||
210 | <abstract> | ||
211 | !Pinclude/net/mac80211.h Introduction | ||
212 | !Pinclude/net/mac80211.h Warning | ||
213 | </abstract> | ||
214 | </bookinfo> | ||
215 | |||
216 | <toc></toc> | ||
217 | |||
218 | <!-- | ||
219 | Generally, this document shall be ordered by increasing complexity. | ||
220 | It is important to note that readers should be able to read only | ||
221 | the first few sections to get a working driver and only advanced | ||
222 | usage should require reading the full document. | ||
223 | --> | ||
224 | |||
225 | <part> | ||
226 | <title>The basic mac80211 driver interface</title> | ||
227 | <partintro> | ||
228 | <para> | ||
229 | You should read and understand the information contained | ||
230 | within this part of the book while implementing a driver. | ||
231 | In some chapters, advanced usage is noted, that may be | ||
232 | skipped at first. | ||
233 | </para> | ||
234 | <para> | ||
235 | This part of the book only covers station and monitor mode | ||
236 | functionality, additional information required to implement | ||
237 | the other modes is covered in the second part of the book. | ||
238 | </para> | ||
239 | </partintro> | ||
240 | |||
241 | <chapter id="basics"> | ||
242 | <title>Basic hardware handling</title> | ||
243 | <para>TBD</para> | ||
244 | <para> | ||
245 | This chapter shall contain information on getting a hw | ||
246 | struct allocated and registered with mac80211. | ||
247 | </para> | ||
248 | <para> | ||
249 | Since it is required to allocate rates/modes before registering | ||
250 | a hw struct, this chapter shall also contain information on setting | ||
251 | up the rate/mode structs. | ||
252 | </para> | ||
253 | <para> | ||
254 | Additionally, some discussion about the callbacks and | ||
255 | the general programming model should be in here, including | ||
256 | the definition of ieee80211_ops which will be referred to | ||
257 | a lot. | ||
258 | </para> | ||
259 | <para> | ||
260 | Finally, a discussion of hardware capabilities should be done | ||
261 | with references to other parts of the book. | ||
262 | </para> | ||
263 | <!-- intentionally multiple !F lines to get proper order --> | ||
264 | !Finclude/net/mac80211.h ieee80211_hw | ||
265 | !Finclude/net/mac80211.h ieee80211_hw_flags | ||
266 | !Finclude/net/mac80211.h SET_IEEE80211_DEV | ||
267 | !Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR | ||
268 | !Finclude/net/mac80211.h ieee80211_ops | ||
269 | !Finclude/net/mac80211.h ieee80211_alloc_hw | ||
270 | !Finclude/net/mac80211.h ieee80211_register_hw | ||
271 | !Finclude/net/mac80211.h ieee80211_get_tx_led_name | ||
272 | !Finclude/net/mac80211.h ieee80211_get_rx_led_name | ||
273 | !Finclude/net/mac80211.h ieee80211_get_assoc_led_name | ||
274 | !Finclude/net/mac80211.h ieee80211_get_radio_led_name | ||
275 | !Finclude/net/mac80211.h ieee80211_unregister_hw | ||
276 | !Finclude/net/mac80211.h ieee80211_free_hw | ||
277 | </chapter> | ||
278 | |||
279 | <chapter id="phy-handling"> | ||
280 | <title>PHY configuration</title> | ||
281 | <para>TBD</para> | ||
282 | <para> | ||
283 | This chapter should describe PHY handling including | ||
284 | start/stop callbacks and the various structures used. | ||
285 | </para> | ||
286 | !Finclude/net/mac80211.h ieee80211_conf | ||
287 | !Finclude/net/mac80211.h ieee80211_conf_flags | ||
288 | </chapter> | ||
289 | |||
290 | <chapter id="iface-handling"> | ||
291 | <title>Virtual interfaces</title> | ||
292 | <para>TBD</para> | ||
293 | <para> | ||
294 | This chapter should describe virtual interface basics | ||
295 | that are relevant to the driver (VLANs, MGMT etc are not.) | ||
296 | It should explain the use of the add_iface/remove_iface | ||
297 | callbacks as well as the interface configuration callbacks. | ||
298 | </para> | ||
299 | <para>Things related to AP mode should be discussed there.</para> | ||
300 | <para> | ||
301 | Things related to supporting multiple interfaces should be | ||
302 | in the appropriate chapter, a BIG FAT note should be here about | ||
303 | this though and the recommendation to allow only a single | ||
304 | interface in STA mode at first! | ||
305 | </para> | ||
306 | !Finclude/net/mac80211.h ieee80211_vif | ||
307 | </chapter> | ||
308 | |||
309 | <chapter id="rx-tx"> | ||
310 | <title>Receive and transmit processing</title> | ||
311 | <sect1> | ||
312 | <title>what should be here</title> | ||
313 | <para>TBD</para> | ||
314 | <para> | ||
315 | This should describe the receive and transmit | ||
316 | paths in mac80211/the drivers as well as | ||
317 | transmit status handling. | ||
318 | </para> | ||
319 | </sect1> | ||
320 | <sect1> | ||
321 | <title>Frame format</title> | ||
322 | !Pinclude/net/mac80211.h Frame format | ||
323 | </sect1> | ||
324 | <sect1> | ||
325 | <title>Packet alignment</title> | ||
326 | !Pnet/mac80211/rx.c Packet alignment | ||
327 | </sect1> | ||
328 | <sect1> | ||
329 | <title>Calling into mac80211 from interrupts</title> | ||
330 | !Pinclude/net/mac80211.h Calling mac80211 from interrupts | ||
331 | </sect1> | ||
332 | <sect1> | ||
333 | <title>functions/definitions</title> | ||
334 | !Finclude/net/mac80211.h ieee80211_rx_status | ||
335 | !Finclude/net/mac80211.h mac80211_rx_flags | ||
336 | !Finclude/net/mac80211.h ieee80211_tx_info | ||
337 | !Finclude/net/mac80211.h ieee80211_rx | ||
338 | !Finclude/net/mac80211.h ieee80211_rx_irqsafe | ||
339 | !Finclude/net/mac80211.h ieee80211_tx_status | ||
340 | !Finclude/net/mac80211.h ieee80211_tx_status_irqsafe | ||
341 | !Finclude/net/mac80211.h ieee80211_rts_get | ||
342 | !Finclude/net/mac80211.h ieee80211_rts_duration | ||
343 | !Finclude/net/mac80211.h ieee80211_ctstoself_get | ||
344 | !Finclude/net/mac80211.h ieee80211_ctstoself_duration | ||
345 | !Finclude/net/mac80211.h ieee80211_generic_frame_duration | ||
346 | !Finclude/net/mac80211.h ieee80211_wake_queue | ||
347 | !Finclude/net/mac80211.h ieee80211_stop_queue | ||
348 | !Finclude/net/mac80211.h ieee80211_wake_queues | ||
349 | !Finclude/net/mac80211.h ieee80211_stop_queues | ||
350 | </sect1> | ||
351 | </chapter> | ||
352 | |||
353 | <chapter id="filters"> | ||
354 | <title>Frame filtering</title> | ||
355 | !Pinclude/net/mac80211.h Frame filtering | ||
356 | !Finclude/net/mac80211.h ieee80211_filter_flags | ||
357 | </chapter> | ||
358 | </part> | ||
359 | |||
360 | <part id="advanced"> | ||
361 | <title>Advanced driver interface</title> | ||
362 | <partintro> | ||
363 | <para> | ||
364 | Information contained within this part of the book is | ||
365 | of interest only for advanced interaction of mac80211 | ||
366 | with drivers to exploit more hardware capabilities and | ||
367 | improve performance. | ||
368 | </para> | ||
369 | </partintro> | ||
370 | |||
371 | <chapter id="hardware-crypto-offload"> | ||
372 | <title>Hardware crypto acceleration</title> | ||
373 | !Pinclude/net/mac80211.h Hardware crypto acceleration | ||
374 | <!-- intentionally multiple !F lines to get proper order --> | ||
375 | !Finclude/net/mac80211.h set_key_cmd | ||
376 | !Finclude/net/mac80211.h ieee80211_key_conf | ||
377 | !Finclude/net/mac80211.h ieee80211_key_flags | ||
378 | </chapter> | ||
379 | |||
380 | <chapter id="powersave"> | ||
381 | <title>Powersave support</title> | ||
382 | !Pinclude/net/mac80211.h Powersave support | ||
383 | </chapter> | ||
384 | |||
385 | <chapter id="beacon-filter"> | ||
386 | <title>Beacon filter support</title> | ||
387 | !Pinclude/net/mac80211.h Beacon filter support | ||
388 | !Finclude/net/mac80211.h ieee80211_beacon_loss | ||
389 | </chapter> | ||
390 | |||
391 | <chapter id="qos"> | ||
392 | <title>Multiple queues and QoS support</title> | ||
393 | <para>TBD</para> | ||
394 | !Finclude/net/mac80211.h ieee80211_tx_queue_params | ||
395 | </chapter> | ||
396 | |||
397 | <chapter id="AP"> | ||
398 | <title>Access point mode support</title> | ||
399 | <para>TBD</para> | ||
400 | <para>Some parts of the if_conf should be discussed here instead</para> | ||
401 | <para> | ||
402 | Insert notes about VLAN interfaces with hw crypto here or | ||
403 | in the hw crypto chapter. | ||
404 | </para> | ||
405 | !Finclude/net/mac80211.h ieee80211_get_buffered_bc | ||
406 | !Finclude/net/mac80211.h ieee80211_beacon_get | ||
407 | </chapter> | ||
408 | |||
409 | <chapter id="multi-iface"> | ||
410 | <title>Supporting multiple virtual interfaces</title> | ||
411 | <para>TBD</para> | ||
412 | <para> | ||
413 | Note: WDS with identical MAC address should almost always be OK | ||
414 | </para> | ||
415 | <para> | ||
416 | Insert notes about having multiple virtual interfaces with | ||
417 | different MAC addresses here, note which configurations are | ||
418 | supported by mac80211, add notes about supporting hw crypto | ||
419 | with it. | ||
420 | </para> | ||
421 | </chapter> | ||
422 | |||
423 | <chapter id="hardware-scan-offload"> | ||
424 | <title>Hardware scan offload</title> | ||
425 | <para>TBD</para> | ||
426 | !Finclude/net/mac80211.h ieee80211_scan_completed | ||
427 | </chapter> | ||
428 | </part> | ||
429 | |||
430 | <part id="rate-control"> | ||
431 | <title>Rate control interface</title> | ||
432 | <partintro> | ||
433 | <para>TBD</para> | ||
434 | <para> | ||
435 | This part of the book describes the rate control algorithm | ||
436 | interface and how it relates to mac80211 and drivers. | ||
437 | </para> | ||
438 | </partintro> | ||
439 | <chapter id="dummy"> | ||
440 | <title>dummy chapter</title> | ||
441 | <para>TBD</para> | ||
442 | </chapter> | ||
443 | </part> | ||
444 | |||
445 | <part id="internal"> | ||
446 | <title>Internals</title> | ||
447 | <partintro> | ||
448 | <para>TBD</para> | ||
449 | <para> | ||
450 | This part of the book describes mac80211 internals. | ||
451 | </para> | ||
452 | </partintro> | ||
453 | |||
454 | <chapter id="key-handling"> | ||
455 | <title>Key handling</title> | ||
456 | <sect1> | ||
457 | <title>Key handling basics</title> | ||
458 | !Pnet/mac80211/key.c Key handling basics | ||
459 | </sect1> | ||
460 | <sect1> | ||
461 | <title>MORE TBD</title> | ||
462 | <para>TBD</para> | ||
463 | </sect1> | ||
464 | </chapter> | ||
465 | |||
466 | <chapter id="rx-processing"> | ||
467 | <title>Receive processing</title> | ||
468 | <para>TBD</para> | ||
469 | </chapter> | ||
470 | |||
471 | <chapter id="tx-processing"> | ||
472 | <title>Transmit processing</title> | ||
473 | <para>TBD</para> | ||
474 | </chapter> | ||
475 | |||
476 | <chapter id="sta-info"> | ||
477 | <title>Station info handling</title> | ||
478 | <sect1> | ||
479 | <title>Programming information</title> | ||
480 | !Fnet/mac80211/sta_info.h sta_info | ||
481 | !Fnet/mac80211/sta_info.h ieee80211_sta_info_flags | ||
482 | </sect1> | ||
483 | <sect1> | ||
484 | <title>STA information lifetime rules</title> | ||
485 | !Pnet/mac80211/sta_info.c STA information lifetime rules | ||
486 | </sect1> | ||
487 | </chapter> | ||
488 | |||
489 | <chapter id="synchronisation"> | ||
490 | <title>Synchronisation</title> | ||
491 | <para>TBD</para> | ||
492 | <para>Locking, lots of RCU</para> | ||
493 | </chapter> | ||
494 | </part> | ||
495 | </book> | ||
496 | </set> | ||
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 34929f24c284..8b6e00a71034 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile | |||
@@ -12,7 +12,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ | |||
12 | kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ | 12 | kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ |
13 | gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ | 13 | gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ |
14 | genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ | 14 | genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ |
15 | mac80211.xml debugobjects.xml sh.xml regulator.xml \ | 15 | 80211.xml debugobjects.xml sh.xml regulator.xml \ |
16 | alsa-driver-api.xml writing-an-alsa-driver.xml \ | 16 | alsa-driver-api.xml writing-an-alsa-driver.xml \ |
17 | tracepoint.xml media.xml drm.xml | 17 | tracepoint.xml media.xml drm.xml |
18 | 18 | ||
diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl deleted file mode 100644 index affb15a344a1..000000000000 --- a/Documentation/DocBook/mac80211.tmpl +++ /dev/null | |||
@@ -1,337 +0,0 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" | ||
3 | "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> | ||
4 | |||
5 | <book id="mac80211-developers-guide"> | ||
6 | <bookinfo> | ||
7 | <title>The mac80211 subsystem for kernel developers</title> | ||
8 | |||
9 | <authorgroup> | ||
10 | <author> | ||
11 | <firstname>Johannes</firstname> | ||
12 | <surname>Berg</surname> | ||
13 | <affiliation> | ||
14 | <address><email>johannes@sipsolutions.net</email></address> | ||
15 | </affiliation> | ||
16 | </author> | ||
17 | </authorgroup> | ||
18 | |||
19 | <copyright> | ||
20 | <year>2007-2009</year> | ||
21 | <holder>Johannes Berg</holder> | ||
22 | </copyright> | ||
23 | |||
24 | <legalnotice> | ||
25 | <para> | ||
26 | This documentation is free software; you can redistribute | ||
27 | it and/or modify it under the terms of the GNU General Public | ||
28 | License version 2 as published by the Free Software Foundation. | ||
29 | </para> | ||
30 | |||
31 | <para> | ||
32 | This documentation is distributed in the hope that it will be | ||
33 | useful, but WITHOUT ANY WARRANTY; without even the implied | ||
34 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
35 | See the GNU General Public License for more details. | ||
36 | </para> | ||
37 | |||
38 | <para> | ||
39 | You should have received a copy of the GNU General Public | ||
40 | License along with this documentation; if not, write to the Free | ||
41 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
42 | MA 02111-1307 USA | ||
43 | </para> | ||
44 | |||
45 | <para> | ||
46 | For more details see the file COPYING in the source | ||
47 | distribution of Linux. | ||
48 | </para> | ||
49 | </legalnotice> | ||
50 | |||
51 | <abstract> | ||
52 | !Pinclude/net/mac80211.h Introduction | ||
53 | !Pinclude/net/mac80211.h Warning | ||
54 | </abstract> | ||
55 | </bookinfo> | ||
56 | |||
57 | <toc></toc> | ||
58 | |||
59 | <!-- | ||
60 | Generally, this document shall be ordered by increasing complexity. | ||
61 | It is important to note that readers should be able to read only | ||
62 | the first few sections to get a working driver and only advanced | ||
63 | usage should require reading the full document. | ||
64 | --> | ||
65 | |||
66 | <part> | ||
67 | <title>The basic mac80211 driver interface</title> | ||
68 | <partintro> | ||
69 | <para> | ||
70 | You should read and understand the information contained | ||
71 | within this part of the book while implementing a driver. | ||
72 | In some chapters, advanced usage is noted, that may be | ||
73 | skipped at first. | ||
74 | </para> | ||
75 | <para> | ||
76 | This part of the book only covers station and monitor mode | ||
77 | functionality, additional information required to implement | ||
78 | the other modes is covered in the second part of the book. | ||
79 | </para> | ||
80 | </partintro> | ||
81 | |||
82 | <chapter id="basics"> | ||
83 | <title>Basic hardware handling</title> | ||
84 | <para>TBD</para> | ||
85 | <para> | ||
86 | This chapter shall contain information on getting a hw | ||
87 | struct allocated and registered with mac80211. | ||
88 | </para> | ||
89 | <para> | ||
90 | Since it is required to allocate rates/modes before registering | ||
91 | a hw struct, this chapter shall also contain information on setting | ||
92 | up the rate/mode structs. | ||
93 | </para> | ||
94 | <para> | ||
95 | Additionally, some discussion about the callbacks and | ||
96 | the general programming model should be in here, including | ||
97 | the definition of ieee80211_ops which will be referred to | ||
98 | a lot. | ||
99 | </para> | ||
100 | <para> | ||
101 | Finally, a discussion of hardware capabilities should be done | ||
102 | with references to other parts of the book. | ||
103 | </para> | ||
104 | <!-- intentionally multiple !F lines to get proper order --> | ||
105 | !Finclude/net/mac80211.h ieee80211_hw | ||
106 | !Finclude/net/mac80211.h ieee80211_hw_flags | ||
107 | !Finclude/net/mac80211.h SET_IEEE80211_DEV | ||
108 | !Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR | ||
109 | !Finclude/net/mac80211.h ieee80211_ops | ||
110 | !Finclude/net/mac80211.h ieee80211_alloc_hw | ||
111 | !Finclude/net/mac80211.h ieee80211_register_hw | ||
112 | !Finclude/net/mac80211.h ieee80211_get_tx_led_name | ||
113 | !Finclude/net/mac80211.h ieee80211_get_rx_led_name | ||
114 | !Finclude/net/mac80211.h ieee80211_get_assoc_led_name | ||
115 | !Finclude/net/mac80211.h ieee80211_get_radio_led_name | ||
116 | !Finclude/net/mac80211.h ieee80211_unregister_hw | ||
117 | !Finclude/net/mac80211.h ieee80211_free_hw | ||
118 | </chapter> | ||
119 | |||
120 | <chapter id="phy-handling"> | ||
121 | <title>PHY configuration</title> | ||
122 | <para>TBD</para> | ||
123 | <para> | ||
124 | This chapter should describe PHY handling including | ||
125 | start/stop callbacks and the various structures used. | ||
126 | </para> | ||
127 | !Finclude/net/mac80211.h ieee80211_conf | ||
128 | !Finclude/net/mac80211.h ieee80211_conf_flags | ||
129 | </chapter> | ||
130 | |||
131 | <chapter id="iface-handling"> | ||
132 | <title>Virtual interfaces</title> | ||
133 | <para>TBD</para> | ||
134 | <para> | ||
135 | This chapter should describe virtual interface basics | ||
136 | that are relevant to the driver (VLANs, MGMT etc are not.) | ||
137 | It should explain the use of the add_iface/remove_iface | ||
138 | callbacks as well as the interface configuration callbacks. | ||
139 | </para> | ||
140 | <para>Things related to AP mode should be discussed there.</para> | ||
141 | <para> | ||
142 | Things related to supporting multiple interfaces should be | ||
143 | in the appropriate chapter, a BIG FAT note should be here about | ||
144 | this though and the recommendation to allow only a single | ||
145 | interface in STA mode at first! | ||
146 | </para> | ||
147 | !Finclude/net/mac80211.h ieee80211_vif | ||
148 | </chapter> | ||
149 | |||
150 | <chapter id="rx-tx"> | ||
151 | <title>Receive and transmit processing</title> | ||
152 | <sect1> | ||
153 | <title>what should be here</title> | ||
154 | <para>TBD</para> | ||
155 | <para> | ||
156 | This should describe the receive and transmit | ||
157 | paths in mac80211/the drivers as well as | ||
158 | transmit status handling. | ||
159 | </para> | ||
160 | </sect1> | ||
161 | <sect1> | ||
162 | <title>Frame format</title> | ||
163 | !Pinclude/net/mac80211.h Frame format | ||
164 | </sect1> | ||
165 | <sect1> | ||
166 | <title>Packet alignment</title> | ||
167 | !Pnet/mac80211/rx.c Packet alignment | ||
168 | </sect1> | ||
169 | <sect1> | ||
170 | <title>Calling into mac80211 from interrupts</title> | ||
171 | !Pinclude/net/mac80211.h Calling mac80211 from interrupts | ||
172 | </sect1> | ||
173 | <sect1> | ||
174 | <title>functions/definitions</title> | ||
175 | !Finclude/net/mac80211.h ieee80211_rx_status | ||
176 | !Finclude/net/mac80211.h mac80211_rx_flags | ||
177 | !Finclude/net/mac80211.h ieee80211_tx_info | ||
178 | !Finclude/net/mac80211.h ieee80211_rx | ||
179 | !Finclude/net/mac80211.h ieee80211_rx_irqsafe | ||
180 | !Finclude/net/mac80211.h ieee80211_tx_status | ||
181 | !Finclude/net/mac80211.h ieee80211_tx_status_irqsafe | ||
182 | !Finclude/net/mac80211.h ieee80211_rts_get | ||
183 | !Finclude/net/mac80211.h ieee80211_rts_duration | ||
184 | !Finclude/net/mac80211.h ieee80211_ctstoself_get | ||
185 | !Finclude/net/mac80211.h ieee80211_ctstoself_duration | ||
186 | !Finclude/net/mac80211.h ieee80211_generic_frame_duration | ||
187 | !Finclude/net/mac80211.h ieee80211_wake_queue | ||
188 | !Finclude/net/mac80211.h ieee80211_stop_queue | ||
189 | !Finclude/net/mac80211.h ieee80211_wake_queues | ||
190 | !Finclude/net/mac80211.h ieee80211_stop_queues | ||
191 | </sect1> | ||
192 | </chapter> | ||
193 | |||
194 | <chapter id="filters"> | ||
195 | <title>Frame filtering</title> | ||
196 | !Pinclude/net/mac80211.h Frame filtering | ||
197 | !Finclude/net/mac80211.h ieee80211_filter_flags | ||
198 | </chapter> | ||
199 | </part> | ||
200 | |||
201 | <part id="advanced"> | ||
202 | <title>Advanced driver interface</title> | ||
203 | <partintro> | ||
204 | <para> | ||
205 | Information contained within this part of the book is | ||
206 | of interest only for advanced interaction of mac80211 | ||
207 | with drivers to exploit more hardware capabilities and | ||
208 | improve performance. | ||
209 | </para> | ||
210 | </partintro> | ||
211 | |||
212 | <chapter id="hardware-crypto-offload"> | ||
213 | <title>Hardware crypto acceleration</title> | ||
214 | !Pinclude/net/mac80211.h Hardware crypto acceleration | ||
215 | <!-- intentionally multiple !F lines to get proper order --> | ||
216 | !Finclude/net/mac80211.h set_key_cmd | ||
217 | !Finclude/net/mac80211.h ieee80211_key_conf | ||
218 | !Finclude/net/mac80211.h ieee80211_key_alg | ||
219 | !Finclude/net/mac80211.h ieee80211_key_flags | ||
220 | </chapter> | ||
221 | |||
222 | <chapter id="powersave"> | ||
223 | <title>Powersave support</title> | ||
224 | !Pinclude/net/mac80211.h Powersave support | ||
225 | </chapter> | ||
226 | |||
227 | <chapter id="beacon-filter"> | ||
228 | <title>Beacon filter support</title> | ||
229 | !Pinclude/net/mac80211.h Beacon filter support | ||
230 | !Finclude/net/mac80211.h ieee80211_beacon_loss | ||
231 | </chapter> | ||
232 | |||
233 | <chapter id="qos"> | ||
234 | <title>Multiple queues and QoS support</title> | ||
235 | <para>TBD</para> | ||
236 | !Finclude/net/mac80211.h ieee80211_tx_queue_params | ||
237 | </chapter> | ||
238 | |||
239 | <chapter id="AP"> | ||
240 | <title>Access point mode support</title> | ||
241 | <para>TBD</para> | ||
242 | <para>Some parts of the if_conf should be discussed here instead</para> | ||
243 | <para> | ||
244 | Insert notes about VLAN interfaces with hw crypto here or | ||
245 | in the hw crypto chapter. | ||
246 | </para> | ||
247 | !Finclude/net/mac80211.h ieee80211_get_buffered_bc | ||
248 | !Finclude/net/mac80211.h ieee80211_beacon_get | ||
249 | </chapter> | ||
250 | |||
251 | <chapter id="multi-iface"> | ||
252 | <title>Supporting multiple virtual interfaces</title> | ||
253 | <para>TBD</para> | ||
254 | <para> | ||
255 | Note: WDS with identical MAC address should almost always be OK | ||
256 | </para> | ||
257 | <para> | ||
258 | Insert notes about having multiple virtual interfaces with | ||
259 | different MAC addresses here, note which configurations are | ||
260 | supported by mac80211, add notes about supporting hw crypto | ||
261 | with it. | ||
262 | </para> | ||
263 | </chapter> | ||
264 | |||
265 | <chapter id="hardware-scan-offload"> | ||
266 | <title>Hardware scan offload</title> | ||
267 | <para>TBD</para> | ||
268 | !Finclude/net/mac80211.h ieee80211_scan_completed | ||
269 | </chapter> | ||
270 | </part> | ||
271 | |||
272 | <part id="rate-control"> | ||
273 | <title>Rate control interface</title> | ||
274 | <partintro> | ||
275 | <para>TBD</para> | ||
276 | <para> | ||
277 | This part of the book describes the rate control algorithm | ||
278 | interface and how it relates to mac80211 and drivers. | ||
279 | </para> | ||
280 | </partintro> | ||
281 | <chapter id="dummy"> | ||
282 | <title>dummy chapter</title> | ||
283 | <para>TBD</para> | ||
284 | </chapter> | ||
285 | </part> | ||
286 | |||
287 | <part id="internal"> | ||
288 | <title>Internals</title> | ||
289 | <partintro> | ||
290 | <para>TBD</para> | ||
291 | <para> | ||
292 | This part of the book describes mac80211 internals. | ||
293 | </para> | ||
294 | </partintro> | ||
295 | |||
296 | <chapter id="key-handling"> | ||
297 | <title>Key handling</title> | ||
298 | <sect1> | ||
299 | <title>Key handling basics</title> | ||
300 | !Pnet/mac80211/key.c Key handling basics | ||
301 | </sect1> | ||
302 | <sect1> | ||
303 | <title>MORE TBD</title> | ||
304 | <para>TBD</para> | ||
305 | </sect1> | ||
306 | </chapter> | ||
307 | |||
308 | <chapter id="rx-processing"> | ||
309 | <title>Receive processing</title> | ||
310 | <para>TBD</para> | ||
311 | </chapter> | ||
312 | |||
313 | <chapter id="tx-processing"> | ||
314 | <title>Transmit processing</title> | ||
315 | <para>TBD</para> | ||
316 | </chapter> | ||
317 | |||
318 | <chapter id="sta-info"> | ||
319 | <title>Station info handling</title> | ||
320 | <sect1> | ||
321 | <title>Programming information</title> | ||
322 | !Fnet/mac80211/sta_info.h sta_info | ||
323 | !Fnet/mac80211/sta_info.h ieee80211_sta_info_flags | ||
324 | </sect1> | ||
325 | <sect1> | ||
326 | <title>STA information lifetime rules</title> | ||
327 | !Pnet/mac80211/sta_info.c STA information lifetime rules | ||
328 | </sect1> | ||
329 | </chapter> | ||
330 | |||
331 | <chapter id="synchronisation"> | ||
332 | <title>Synchronisation</title> | ||
333 | <para>TBD</para> | ||
334 | <para>Locking, lots of RCU</para> | ||
335 | </chapter> | ||
336 | </part> | ||
337 | </book> | ||
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 1128fa8c9ed5..91c5f73b5ba3 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -2061,11 +2061,12 @@ static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2061 | 2061 | ||
2062 | int i; | 2062 | int i; |
2063 | 2063 | ||
2064 | at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d " | 2064 | at76_dbg(DBG_MAC80211, "%s(): cmd %d key->cipher %d key->keyidx %d " |
2065 | "key->keylen %d", | 2065 | "key->keylen %d", |
2066 | __func__, cmd, key->alg, key->keyidx, key->keylen); | 2066 | __func__, cmd, key->cipher, key->keyidx, key->keylen); |
2067 | 2067 | ||
2068 | if (key->alg != ALG_WEP) | 2068 | if ((key->cipher != WLAN_CIPHER_SUITE_WEP40) && |
2069 | (key->cipher != WLAN_CIPHER_SUITE_WEP104)) | ||
2069 | return -EOPNOTSUPP; | 2070 | return -EOPNOTSUPP; |
2070 | 2071 | ||
2071 | key->hw_key_idx = key->keyidx; | 2072 | key->hw_key_idx = key->keyidx; |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index debfb0fbc7c5..32bf79e6a320 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -1190,14 +1190,13 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1190 | if (info->control.hw_key) { | 1190 | if (info->control.hw_key) { |
1191 | icv = info->control.hw_key->icv_len; | 1191 | icv = info->control.hw_key->icv_len; |
1192 | 1192 | ||
1193 | switch (info->control.hw_key->alg) { | 1193 | switch (info->control.hw_key->cipher) { |
1194 | case ALG_WEP: | 1194 | case WLAN_CIPHER_SUITE_WEP40: |
1195 | case WLAN_CIPHER_SUITE_WEP104: | ||
1196 | case WLAN_CIPHER_SUITE_TKIP: | ||
1195 | keytype = AR9170_TX_MAC_ENCR_RC4; | 1197 | keytype = AR9170_TX_MAC_ENCR_RC4; |
1196 | break; | 1198 | break; |
1197 | case ALG_TKIP: | 1199 | case WLAN_CIPHER_SUITE_CCMP: |
1198 | keytype = AR9170_TX_MAC_ENCR_RC4; | ||
1199 | break; | ||
1200 | case ALG_CCMP: | ||
1201 | keytype = AR9170_TX_MAC_ENCR_AES; | 1200 | keytype = AR9170_TX_MAC_ENCR_AES; |
1202 | break; | 1201 | break; |
1203 | default: | 1202 | default: |
@@ -1778,17 +1777,17 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1778 | if ((!ar->vif) || (ar->disable_offload)) | 1777 | if ((!ar->vif) || (ar->disable_offload)) |
1779 | return -EOPNOTSUPP; | 1778 | return -EOPNOTSUPP; |
1780 | 1779 | ||
1781 | switch (key->alg) { | 1780 | switch (key->cipher) { |
1782 | case ALG_WEP: | 1781 | case WLAN_CIPHER_SUITE_WEP40: |
1783 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 1782 | ktype = AR9170_ENC_ALG_WEP64; |
1784 | ktype = AR9170_ENC_ALG_WEP64; | 1783 | break; |
1785 | else | 1784 | case WLAN_CIPHER_SUITE_WEP104: |
1786 | ktype = AR9170_ENC_ALG_WEP128; | 1785 | ktype = AR9170_ENC_ALG_WEP128; |
1787 | break; | 1786 | break; |
1788 | case ALG_TKIP: | 1787 | case WLAN_CIPHER_SUITE_TKIP: |
1789 | ktype = AR9170_ENC_ALG_TKIP; | 1788 | ktype = AR9170_ENC_ALG_TKIP; |
1790 | break; | 1789 | break; |
1791 | case ALG_CCMP: | 1790 | case WLAN_CIPHER_SUITE_CCMP: |
1792 | ktype = AR9170_ENC_ALG_AESCCMP; | 1791 | ktype = AR9170_ENC_ALG_AESCCMP; |
1793 | break; | 1792 | break; |
1794 | default: | 1793 | default: |
@@ -1827,7 +1826,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1827 | if (err) | 1826 | if (err) |
1828 | goto out; | 1827 | goto out; |
1829 | 1828 | ||
1830 | if (key->alg == ALG_TKIP) { | 1829 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
1831 | err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, | 1830 | err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, |
1832 | ktype, 1, key->key + 16, 16); | 1831 | ktype, 1, key->key + 16, 16); |
1833 | if (err) | 1832 | if (err) |
@@ -1864,7 +1863,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1864 | if (err) | 1863 | if (err) |
1865 | goto out; | 1864 | goto out; |
1866 | 1865 | ||
1867 | if (key->alg == ALG_TKIP) { | 1866 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
1868 | err = ar9170_upload_key(ar, key->hw_key_idx, | 1867 | err = ar9170_upload_key(ar, key->hw_key_idx, |
1869 | NULL, | 1868 | NULL, |
1870 | AR9170_ENC_ALG_NONE, 1, | 1869 | AR9170_ENC_ALG_NONE, 1, |
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 26dbe65fedb0..e4a5f046bba4 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -552,9 +552,9 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah) | |||
552 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) | 552 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) |
553 | return; | 553 | return; |
554 | 554 | ||
555 | /* if one of the errors triggered, we can get a superfluous second | 555 | /* If one of the errors triggered, we can get a superfluous second |
556 | * interrupt, even though we have already reset the register. the | 556 | * interrupt, even though we have already reset the register. The |
557 | * function detects that so we can return early */ | 557 | * function detects that so we can return early. */ |
558 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) | 558 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) |
559 | return; | 559 | return; |
560 | 560 | ||
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ea6362a8988d..f399c4dd8e69 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -175,7 +175,7 @@ | |||
175 | #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 | 175 | #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 |
176 | #define AR5K_TUNE_RADAR_ALERT false | 176 | #define AR5K_TUNE_RADAR_ALERT false |
177 | #define AR5K_TUNE_MIN_TX_FIFO_THRES 1 | 177 | #define AR5K_TUNE_MIN_TX_FIFO_THRES 1 |
178 | #define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1) | 178 | #define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1) |
179 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 | 179 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 |
180 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to | 180 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to |
181 | * be the max value. */ | 181 | * be the max value. */ |
@@ -343,9 +343,6 @@ struct ath5k_srev_name { | |||
343 | #define AR5K_SREV_PHY_5413 0x61 | 343 | #define AR5K_SREV_PHY_5413 0x61 |
344 | #define AR5K_SREV_PHY_2425 0x70 | 344 | #define AR5K_SREV_PHY_2425 0x70 |
345 | 345 | ||
346 | /* IEEE defs */ | ||
347 | #define IEEE80211_MAX_LEN 2500 | ||
348 | |||
349 | /* TODO add support to mac80211 for vendor-specific rates and modes */ | 346 | /* TODO add support to mac80211 for vendor-specific rates and modes */ |
350 | 347 | ||
351 | /* | 348 | /* |
@@ -1190,7 +1187,7 @@ extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); | |||
1190 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | 1187 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); |
1191 | /* BSSID Functions */ | 1188 | /* BSSID Functions */ |
1192 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1189 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1193 | void ath5k_hw_set_associd(struct ath5k_hw *ah); | 1190 | void ath5k_hw_set_bssid(struct ath5k_hw *ah); |
1194 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1191 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1195 | /* Receive start/stop functions */ | 1192 | /* Receive start/stop functions */ |
1196 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | 1193 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index b32e28caeee2..aabad4f13e2a 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -139,12 +139,12 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
139 | else | 139 | else |
140 | ah->ah_version = AR5K_AR5212; | 140 | ah->ah_version = AR5K_AR5212; |
141 | 141 | ||
142 | /*Fill the ath5k_hw struct with the needed functions*/ | 142 | /* Fill the ath5k_hw struct with the needed functions */ |
143 | ret = ath5k_hw_init_desc_functions(ah); | 143 | ret = ath5k_hw_init_desc_functions(ah); |
144 | if (ret) | 144 | if (ret) |
145 | goto err_free; | 145 | goto err_free; |
146 | 146 | ||
147 | /* Bring device out of sleep and reset it's units */ | 147 | /* Bring device out of sleep and reset its units */ |
148 | ret = ath5k_hw_nic_wakeup(ah, 0, true); | 148 | ret = ath5k_hw_nic_wakeup(ah, 0, true); |
149 | if (ret) | 149 | if (ret) |
150 | goto err_free; | 150 | goto err_free; |
@@ -158,7 +158,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
158 | CHANNEL_5GHZ); | 158 | CHANNEL_5GHZ); |
159 | ah->ah_phy = AR5K_PHY(0); | 159 | ah->ah_phy = AR5K_PHY(0); |
160 | 160 | ||
161 | /* Try to identify radio chip based on it's srev */ | 161 | /* Try to identify radio chip based on its srev */ |
162 | switch (ah->ah_radio_5ghz_revision & 0xf0) { | 162 | switch (ah->ah_radio_5ghz_revision & 0xf0) { |
163 | case AR5K_SREV_RAD_5111: | 163 | case AR5K_SREV_RAD_5111: |
164 | ah->ah_radio = AR5K_RF5111; | 164 | ah->ah_radio = AR5K_RF5111; |
@@ -329,7 +329,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
329 | 329 | ||
330 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 330 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
331 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); | 331 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); |
332 | ath5k_hw_set_associd(ah); | 332 | ath5k_hw_set_bssid(ah); |
333 | ath5k_hw_set_opmode(ah, sc->opmode); | 333 | ath5k_hw_set_opmode(ah, sc->opmode); |
334 | 334 | ||
335 | ath5k_hw_rfgain_opt_init(ah); | 335 | ath5k_hw_rfgain_opt_init(ah); |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 373dcfec689c..f2fceb10c9fc 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -612,7 +612,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
612 | goto err_free; | 612 | goto err_free; |
613 | } | 613 | } |
614 | 614 | ||
615 | /*If we passed the test malloc a ath5k_hw struct*/ | 615 | /* If we passed the test, malloc an ath5k_hw struct */ |
616 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | 616 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); |
617 | if (!sc->ah) { | 617 | if (!sc->ah) { |
618 | ret = -ENOMEM; | 618 | ret = -ENOMEM; |
@@ -786,8 +786,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
786 | /* | 786 | /* |
787 | * Check if the MAC has multi-rate retry support. | 787 | * Check if the MAC has multi-rate retry support. |
788 | * We do this by trying to setup a fake extended | 788 | * We do this by trying to setup a fake extended |
789 | * descriptor. MAC's that don't have support will | 789 | * descriptor. MACs that don't have support will |
790 | * return false w/o doing anything. MAC's that do | 790 | * return false w/o doing anything. MACs that do |
791 | * support it will return true w/o doing anything. | 791 | * support it will return true w/o doing anything. |
792 | */ | 792 | */ |
793 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | 793 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); |
@@ -827,7 +827,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
827 | /* | 827 | /* |
828 | * Allocate hardware transmit queues: one queue for | 828 | * Allocate hardware transmit queues: one queue for |
829 | * beacon frames and one data queue for each QoS | 829 | * beacon frames and one data queue for each QoS |
830 | * priority. Note that hw functions handle reseting | 830 | * priority. Note that hw functions handle resetting |
831 | * these queues at the needed time. | 831 | * these queues at the needed time. |
832 | */ | 832 | */ |
833 | ret = ath5k_beaconq_setup(ah); | 833 | ret = ath5k_beaconq_setup(ah); |
@@ -909,7 +909,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
909 | /* | 909 | /* |
910 | * NB: the order of these is important: | 910 | * NB: the order of these is important: |
911 | * o call the 802.11 layer before detaching ath5k_hw to | 911 | * o call the 802.11 layer before detaching ath5k_hw to |
912 | * insure callbacks into the driver to delete global | 912 | * ensure callbacks into the driver to delete global |
913 | * key cache entries can be handled | 913 | * key cache entries can be handled |
914 | * o reclaim the tx queue data structures after calling | 914 | * o reclaim the tx queue data structures after calling |
915 | * the 802.11 layer as we'll get called back to reclaim | 915 | * the 802.11 layer as we'll get called back to reclaim |
@@ -1514,7 +1514,7 @@ ath5k_txq_setup(struct ath5k_softc *sc, | |||
1514 | /* | 1514 | /* |
1515 | * Enable interrupts only for EOL and DESC conditions. | 1515 | * Enable interrupts only for EOL and DESC conditions. |
1516 | * We mark tx descriptors to receive a DESC interrupt | 1516 | * We mark tx descriptors to receive a DESC interrupt |
1517 | * when a tx queue gets deep; otherwise waiting for the | 1517 | * when a tx queue gets deep; otherwise we wait for the |
1518 | * EOL to reap descriptors. Note that this is done to | 1518 | * EOL to reap descriptors. Note that this is done to |
1519 | * reduce interrupt load and this only defers reaping | 1519 | * reduce interrupt load and this only defers reaping |
1520 | * descriptors, never transmitting frames. Aside from | 1520 | * descriptors, never transmitting frames. Aside from |
@@ -1709,7 +1709,7 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1709 | struct ath5k_buf *bf; | 1709 | struct ath5k_buf *bf; |
1710 | int ret; | 1710 | int ret; |
1711 | 1711 | ||
1712 | common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz); | 1712 | common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz); |
1713 | 1713 | ||
1714 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", | 1714 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", |
1715 | common->cachelsz, common->rx_bufsize); | 1715 | common->cachelsz, common->rx_bufsize); |
@@ -1859,7 +1859,7 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) | |||
1859 | } | 1859 | } |
1860 | 1860 | ||
1861 | /* | 1861 | /* |
1862 | * Compute padding position. skb must contains an IEEE 802.11 frame | 1862 | * Compute padding position. skb must contain an IEEE 802.11 frame |
1863 | */ | 1863 | */ |
1864 | static int ath5k_common_padpos(struct sk_buff *skb) | 1864 | static int ath5k_common_padpos(struct sk_buff *skb) |
1865 | { | 1865 | { |
@@ -1878,10 +1878,9 @@ static int ath5k_common_padpos(struct sk_buff *skb) | |||
1878 | } | 1878 | } |
1879 | 1879 | ||
1880 | /* | 1880 | /* |
1881 | * This function expects a 802.11 frame and returns the number of | 1881 | * This function expects an 802.11 frame and returns the number of |
1882 | * bytes added, or -1 if we don't have enought header room. | 1882 | * bytes added, or -1 if we don't have enough header room. |
1883 | */ | 1883 | */ |
1884 | |||
1885 | static int ath5k_add_padding(struct sk_buff *skb) | 1884 | static int ath5k_add_padding(struct sk_buff *skb) |
1886 | { | 1885 | { |
1887 | int padpos = ath5k_common_padpos(skb); | 1886 | int padpos = ath5k_common_padpos(skb); |
@@ -1901,10 +1900,18 @@ static int ath5k_add_padding(struct sk_buff *skb) | |||
1901 | } | 1900 | } |
1902 | 1901 | ||
1903 | /* | 1902 | /* |
1904 | * This function expects a 802.11 frame and returns the number of | 1903 | * The MAC header is padded to have 32-bit boundary if the |
1905 | * bytes removed | 1904 | * packet payload is non-zero. The general calculation for |
1905 | * padsize would take into account odd header lengths: | ||
1906 | * padsize = 4 - (hdrlen & 3); however, since only | ||
1907 | * even-length headers are used, padding can only be 0 or 2 | ||
1908 | * bytes and we can optimize this a bit. We must not try to | ||
1909 | * remove padding from short control frames that do not have a | ||
1910 | * payload. | ||
1911 | * | ||
1912 | * This function expects an 802.11 frame and returns the number of | ||
1913 | * bytes removed. | ||
1906 | */ | 1914 | */ |
1907 | |||
1908 | static int ath5k_remove_padding(struct sk_buff *skb) | 1915 | static int ath5k_remove_padding(struct sk_buff *skb) |
1909 | { | 1916 | { |
1910 | int padpos = ath5k_common_padpos(skb); | 1917 | int padpos = ath5k_common_padpos(skb); |
@@ -1925,14 +1932,6 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1925 | { | 1932 | { |
1926 | struct ieee80211_rx_status *rxs; | 1933 | struct ieee80211_rx_status *rxs; |
1927 | 1934 | ||
1928 | /* The MAC header is padded to have 32-bit boundary if the | ||
1929 | * packet payload is non-zero. The general calculation for | ||
1930 | * padsize would take into account odd header lengths: | ||
1931 | * padsize = (4 - hdrlen % 4) % 4; However, since only | ||
1932 | * even-length headers are used, padding can only be 0 or 2 | ||
1933 | * bytes and we can optimize this a bit. In addition, we must | ||
1934 | * not try to remove padding from short control frames that do | ||
1935 | * not have payload. */ | ||
1936 | ath5k_remove_padding(skb); | 1935 | ath5k_remove_padding(skb); |
1937 | 1936 | ||
1938 | rxs = IEEE80211_SKB_RXCB(skb); | 1937 | rxs = IEEE80211_SKB_RXCB(skb); |
@@ -2036,9 +2035,8 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | |||
2036 | return true; | 2035 | return true; |
2037 | } | 2036 | } |
2038 | 2037 | ||
2039 | /* let crypto-error packets fall through in MNTR */ | 2038 | /* reject any frames with non-crypto errors */ |
2040 | if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | 2039 | if (rs->rs_status & ~(AR5K_RXERR_DECRYPT)) |
2041 | sc->opmode != NL80211_IFTYPE_MONITOR) | ||
2042 | return false; | 2040 | return false; |
2043 | } | 2041 | } |
2044 | 2042 | ||
@@ -2281,10 +2279,11 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2281 | * default antenna which is supposed to be an omni. | 2279 | * default antenna which is supposed to be an omni. |
2282 | * | 2280 | * |
2283 | * Note2: On sectored scenarios it's possible to have | 2281 | * Note2: On sectored scenarios it's possible to have |
2284 | * multiple antennas (1omni -the default- and 14 sectors) | 2282 | * multiple antennas (1 omni -- the default -- and 14 |
2285 | * so if we choose to actually support this mode we need | 2283 | * sectors), so if we choose to actually support this |
2286 | * to allow user to set how many antennas we have and tweak | 2284 | * mode, we need to allow the user to set how many antennas |
2287 | * the code below to send beacons on all of them. | 2285 | * we have and tweak the code below to send beacons |
2286 | * on all of them. | ||
2288 | */ | 2287 | */ |
2289 | if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) | 2288 | if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) |
2290 | antenna = sc->bsent & 4 ? 2 : 1; | 2289 | antenna = sc->bsent & 4 ? 2 : 1; |
@@ -2326,14 +2325,13 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2326 | 2325 | ||
2327 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); | 2326 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); |
2328 | 2327 | ||
2329 | if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || | 2328 | if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION)) { |
2330 | sc->opmode == NL80211_IFTYPE_MONITOR)) { | ||
2331 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); | 2329 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); |
2332 | return; | 2330 | return; |
2333 | } | 2331 | } |
2334 | /* | 2332 | /* |
2335 | * Check if the previous beacon has gone out. If | 2333 | * Check if the previous beacon has gone out. If |
2336 | * not don't don't try to post another, skip this | 2334 | * not, don't don't try to post another: skip this |
2337 | * period and wait for the next. Missed beacons | 2335 | * period and wait for the next. Missed beacons |
2338 | * indicate a problem and should not occur. If we | 2336 | * indicate a problem and should not occur. If we |
2339 | * miss too many consecutive beacons reset the device. | 2337 | * miss too many consecutive beacons reset the device. |
@@ -2901,12 +2899,9 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2901 | 2899 | ||
2902 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 2900 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); |
2903 | 2901 | ||
2904 | if (sc->opmode == NL80211_IFTYPE_MONITOR) | ||
2905 | ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); | ||
2906 | |||
2907 | /* | 2902 | /* |
2908 | * the hardware expects the header padded to 4 byte boundaries | 2903 | * The hardware expects the header padded to 4 byte boundaries. |
2909 | * if this is not the case we add the padding after the header | 2904 | * If this is not the case, we add the padding after the header. |
2910 | */ | 2905 | */ |
2911 | padsize = ath5k_add_padding(skb); | 2906 | padsize = ath5k_add_padding(skb); |
2912 | if (padsize < 0) { | 2907 | if (padsize < 0) { |
@@ -3049,7 +3044,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
3049 | case NL80211_IFTYPE_STATION: | 3044 | case NL80211_IFTYPE_STATION: |
3050 | case NL80211_IFTYPE_ADHOC: | 3045 | case NL80211_IFTYPE_ADHOC: |
3051 | case NL80211_IFTYPE_MESH_POINT: | 3046 | case NL80211_IFTYPE_MESH_POINT: |
3052 | case NL80211_IFTYPE_MONITOR: | ||
3053 | sc->opmode = vif->type; | 3047 | sc->opmode = vif->type; |
3054 | break; | 3048 | break; |
3055 | default: | 3049 | default: |
@@ -3233,9 +3227,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
3233 | rfilt |= AR5K_RX_FILTER_PHYERR; | 3227 | rfilt |= AR5K_RX_FILTER_PHYERR; |
3234 | 3228 | ||
3235 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons | 3229 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons |
3236 | * and probes for any BSSID, this needs testing */ | 3230 | * and probes for any BSSID */ |
3237 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) | 3231 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) |
3238 | rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ; | 3232 | rfilt |= AR5K_RX_FILTER_BEACON; |
3239 | 3233 | ||
3240 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not | 3234 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not |
3241 | * set we should only pass on control frames for this | 3235 | * set we should only pass on control frames for this |
@@ -3251,7 +3245,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
3251 | 3245 | ||
3252 | switch (sc->opmode) { | 3246 | switch (sc->opmode) { |
3253 | case NL80211_IFTYPE_MESH_POINT: | 3247 | case NL80211_IFTYPE_MESH_POINT: |
3254 | case NL80211_IFTYPE_MONITOR: | ||
3255 | rfilt |= AR5K_RX_FILTER_CONTROL | | 3248 | rfilt |= AR5K_RX_FILTER_CONTROL | |
3256 | AR5K_RX_FILTER_BEACON | | 3249 | AR5K_RX_FILTER_BEACON | |
3257 | AR5K_RX_FILTER_PROBEREQ | | 3250 | AR5K_RX_FILTER_PROBEREQ | |
@@ -3274,7 +3267,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
3274 | 3267 | ||
3275 | /* Set multicast bits */ | 3268 | /* Set multicast bits */ |
3276 | ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); | 3269 | ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); |
3277 | /* Set the cached hw filter flags, this will alter actually | 3270 | /* Set the cached hw filter flags, this will later actually |
3278 | * be set in HW */ | 3271 | * be set in HW */ |
3279 | sc->filter_flags = rfilt; | 3272 | sc->filter_flags = rfilt; |
3280 | 3273 | ||
@@ -3297,11 +3290,12 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3297 | if (sc->opmode == NL80211_IFTYPE_AP) | 3290 | if (sc->opmode == NL80211_IFTYPE_AP) |
3298 | return -EOPNOTSUPP; | 3291 | return -EOPNOTSUPP; |
3299 | 3292 | ||
3300 | switch (key->alg) { | 3293 | switch (key->cipher) { |
3301 | case ALG_WEP: | 3294 | case WLAN_CIPHER_SUITE_WEP40: |
3302 | case ALG_TKIP: | 3295 | case WLAN_CIPHER_SUITE_WEP104: |
3296 | case WLAN_CIPHER_SUITE_TKIP: | ||
3303 | break; | 3297 | break; |
3304 | case ALG_CCMP: | 3298 | case WLAN_CIPHER_SUITE_CCMP: |
3305 | if (sc->ah->ah_aes_support) | 3299 | if (sc->ah->ah_aes_support) |
3306 | break; | 3300 | break; |
3307 | 3301 | ||
@@ -3475,7 +3469,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3475 | /* Cache for later use during resets */ | 3469 | /* Cache for later use during resets */ |
3476 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | 3470 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
3477 | common->curaid = 0; | 3471 | common->curaid = 0; |
3478 | ath5k_hw_set_associd(ah); | 3472 | ath5k_hw_set_bssid(ah); |
3479 | mmiowb(); | 3473 | mmiowb(); |
3480 | } | 3474 | } |
3481 | 3475 | ||
@@ -3493,7 +3487,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3493 | "Bss Info ASSOC %d, bssid: %pM\n", | 3487 | "Bss Info ASSOC %d, bssid: %pM\n", |
3494 | bss_conf->aid, common->curbssid); | 3488 | bss_conf->aid, common->curbssid); |
3495 | common->curaid = bss_conf->aid; | 3489 | common->curaid = bss_conf->aid; |
3496 | ath5k_hw_set_associd(ah); | 3490 | ath5k_hw_set_bssid(ah); |
3497 | /* Once ANI is available you would start it here */ | 3491 | /* Once ANI is available you would start it here */ |
3498 | } | 3492 | } |
3499 | } | 3493 | } |
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 484f31870ba8..58bb6c5dda7b 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -377,11 +377,11 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | |||
377 | * | 377 | * |
378 | * This function increases/decreases the tx trigger level for the tx fifo | 378 | * This function increases/decreases the tx trigger level for the tx fifo |
379 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes | 379 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes |
380 | * the buffer and transmits it's data. Lowering this results sending small | 380 | * the buffer and transmits its data. Lowering this results sending small |
381 | * frames more quickly but can lead to tx underruns, raising it a lot can | 381 | * frames more quickly but can lead to tx underruns, raising it a lot can |
382 | * result other problems (i think bmiss is related). Right now we start with | 382 | * result other problems (i think bmiss is related). Right now we start with |
383 | * the lowest possible (64Bytes) and if we get tx underrun we increase it using | 383 | * the lowest possible (64Bytes) and if we get tx underrun we increase it using |
384 | * the increase flag. Returns -EIO if we have have reached maximum/minimum. | 384 | * the increase flag. Returns -EIO if we have reached maximum/minimum. |
385 | * | 385 | * |
386 | * XXX: Link this with tx DMA size ? | 386 | * XXX: Link this with tx DMA size ? |
387 | * XXX: Use it to save interrupts ? | 387 | * XXX: Use it to save interrupts ? |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index ae316fec4a6a..39722dd73e43 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -661,7 +661,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) | |||
661 | * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC | 661 | * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC |
662 | * steps that match with the power values we read from eeprom. On | 662 | * steps that match with the power values we read from eeprom. On |
663 | * older eeprom versions (< 3.2) these steps are equaly spaced at | 663 | * older eeprom versions (< 3.2) these steps are equaly spaced at |
664 | * 10% of the pcdac curve -until the curve reaches it's maximum- | 664 | * 10% of the pcdac curve -until the curve reaches its maximum- |
665 | * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) | 665 | * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) |
666 | * these 11 steps are spaced in a different way. This function returns | 666 | * these 11 steps are spaced in a different way. This function returns |
667 | * the pcdac steps based on eeprom version and curve min/max so that we | 667 | * the pcdac steps based on eeprom version and curve min/max so that we |
@@ -1113,7 +1113,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) | |||
1113 | */ | 1113 | */ |
1114 | 1114 | ||
1115 | /* For RF2413 power calibration data doesn't start on a fixed location and | 1115 | /* For RF2413 power calibration data doesn't start on a fixed location and |
1116 | * if a mode is not supported, it's section is missing -not zeroed-. | 1116 | * if a mode is not supported, its section is missing -not zeroed-. |
1117 | * So we need to calculate the starting offset for each section by using | 1117 | * So we need to calculate the starting offset for each section by using |
1118 | * these two functions */ | 1118 | * these two functions */ |
1119 | 1119 | ||
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 86fdb6ddfaaa..3fef5931ec3a 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -308,27 +308,26 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | |||
308 | } | 308 | } |
309 | 309 | ||
310 | /** | 310 | /** |
311 | * ath5k_hw_set_associd - Set BSSID for association | 311 | * ath5k_hw_set_bssid - Set current BSSID on hw |
312 | * | 312 | * |
313 | * @ah: The &struct ath5k_hw | 313 | * @ah: The &struct ath5k_hw |
314 | * @bssid: BSSID | ||
315 | * @assoc_id: Assoc id | ||
316 | * | 314 | * |
317 | * Sets the BSSID which trigers the "SME Join" operation | 315 | * Sets the current BSSID and BSSID mask we have from the |
316 | * common struct into the hardware | ||
318 | */ | 317 | */ |
319 | void ath5k_hw_set_associd(struct ath5k_hw *ah) | 318 | void ath5k_hw_set_bssid(struct ath5k_hw *ah) |
320 | { | 319 | { |
321 | struct ath_common *common = ath5k_hw_common(ah); | 320 | struct ath_common *common = ath5k_hw_common(ah); |
322 | u16 tim_offset = 0; | 321 | u16 tim_offset = 0; |
323 | 322 | ||
324 | /* | 323 | /* |
325 | * Set simple BSSID mask on 5212 | 324 | * Set BSSID mask on 5212 |
326 | */ | 325 | */ |
327 | if (ah->ah_version == AR5K_AR5212) | 326 | if (ah->ah_version == AR5K_AR5212) |
328 | ath_hw_setbssidmask(common); | 327 | ath_hw_setbssidmask(common); |
329 | 328 | ||
330 | /* | 329 | /* |
331 | * Set BSSID which triggers the "SME Join" operation | 330 | * Set BSSID |
332 | */ | 331 | */ |
333 | ath5k_hw_reg_write(ah, | 332 | ath5k_hw_reg_write(ah, |
334 | get_unaligned_le32(common->curbssid), | 333 | get_unaligned_le32(common->curbssid), |
@@ -695,21 +694,18 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | |||
695 | static | 694 | static |
696 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | 695 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) |
697 | { | 696 | { |
698 | switch (key->alg) { | 697 | switch (key->cipher) { |
699 | case ALG_TKIP: | 698 | case WLAN_CIPHER_SUITE_TKIP: |
700 | return AR5K_KEYTABLE_TYPE_TKIP; | 699 | return AR5K_KEYTABLE_TYPE_TKIP; |
701 | case ALG_CCMP: | 700 | case WLAN_CIPHER_SUITE_CCMP: |
702 | return AR5K_KEYTABLE_TYPE_CCM; | 701 | return AR5K_KEYTABLE_TYPE_CCM; |
703 | case ALG_WEP: | 702 | case WLAN_CIPHER_SUITE_WEP40: |
704 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 703 | return AR5K_KEYTABLE_TYPE_40; |
705 | return AR5K_KEYTABLE_TYPE_40; | 704 | case WLAN_CIPHER_SUITE_WEP104: |
706 | else if (key->keylen == WLAN_KEY_LEN_WEP104) | 705 | return AR5K_KEYTABLE_TYPE_104; |
707 | return AR5K_KEYTABLE_TYPE_104; | ||
708 | return -EINVAL; | ||
709 | default: | 706 | default: |
710 | return -EINVAL; | 707 | return -EINVAL; |
711 | } | 708 | } |
712 | return -EINVAL; | ||
713 | } | 709 | } |
714 | 710 | ||
715 | /* | 711 | /* |
@@ -728,7 +724,7 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | |||
728 | bool is_tkip; | 724 | bool is_tkip; |
729 | const u8 *key_ptr; | 725 | const u8 *key_ptr; |
730 | 726 | ||
731 | is_tkip = (key->alg == ALG_TKIP); | 727 | is_tkip = (key->cipher == WLAN_CIPHER_SUITE_TKIP); |
732 | 728 | ||
733 | /* | 729 | /* |
734 | * key->keylen comes in from mac80211 in bytes. | 730 | * key->keylen comes in from mac80211 in bytes. |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6284c389ba18..c7c446592374 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -115,7 +115,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
115 | \**********************/ | 115 | \**********************/ |
116 | 116 | ||
117 | /* | 117 | /* |
118 | * This code is used to optimize rf gain on different environments | 118 | * This code is used to optimize RF gain on different environments |
119 | * (temperature mostly) based on feedback from a power detector. | 119 | * (temperature mostly) based on feedback from a power detector. |
120 | * | 120 | * |
121 | * It's only used on RF5111 and RF5112, later RF chips seem to have | 121 | * It's only used on RF5111 and RF5112, later RF chips seem to have |
@@ -302,7 +302,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | |||
302 | } | 302 | } |
303 | 303 | ||
304 | /* Perform gain_F adjustment by choosing the right set | 304 | /* Perform gain_F adjustment by choosing the right set |
305 | * of parameters from rf gain optimization ladder */ | 305 | * of parameters from RF gain optimization ladder */ |
306 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) | 306 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) |
307 | { | 307 | { |
308 | const struct ath5k_gain_opt *go; | 308 | const struct ath5k_gain_opt *go; |
@@ -367,7 +367,7 @@ done: | |||
367 | return ret; | 367 | return ret; |
368 | } | 368 | } |
369 | 369 | ||
370 | /* Main callback for thermal rf gain calibration engine | 370 | /* Main callback for thermal RF gain calibration engine |
371 | * Check for a new gain reading and schedule an adjustment | 371 | * Check for a new gain reading and schedule an adjustment |
372 | * if needed. | 372 | * if needed. |
373 | * | 373 | * |
@@ -433,7 +433,7 @@ done: | |||
433 | return ah->ah_gain.g_state; | 433 | return ah->ah_gain.g_state; |
434 | } | 434 | } |
435 | 435 | ||
436 | /* Write initial rf gain table to set the RF sensitivity | 436 | /* Write initial RF gain table to set the RF sensitivity |
437 | * this one works on all RF chips and has nothing to do | 437 | * this one works on all RF chips and has nothing to do |
438 | * with gain_F calibration */ | 438 | * with gain_F calibration */ |
439 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | 439 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) |
@@ -496,7 +496,7 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
496 | 496 | ||
497 | 497 | ||
498 | /* | 498 | /* |
499 | * Setup RF registers by writing rf buffer on hw | 499 | * Setup RF registers by writing RF buffer on hw |
500 | */ | 500 | */ |
501 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 501 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
502 | unsigned int mode) | 502 | unsigned int mode) |
@@ -571,7 +571,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
571 | return -EINVAL; | 571 | return -EINVAL; |
572 | } | 572 | } |
573 | 573 | ||
574 | /* If it's the first time we set rf buffer, allocate | 574 | /* If it's the first time we set RF buffer, allocate |
575 | * ah->ah_rf_banks based on ah->ah_rf_banks_size | 575 | * ah->ah_rf_banks based on ah->ah_rf_banks_size |
576 | * we set above */ | 576 | * we set above */ |
577 | if (ah->ah_rf_banks == NULL) { | 577 | if (ah->ah_rf_banks == NULL) { |
@@ -3035,9 +3035,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3035 | /* Limit max power if we have a CTL available */ | 3035 | /* Limit max power if we have a CTL available */ |
3036 | ath5k_get_max_ctl_power(ah, channel); | 3036 | ath5k_get_max_ctl_power(ah, channel); |
3037 | 3037 | ||
3038 | /* FIXME: Tx power limit for this regdomain | ||
3039 | * XXX: Mac80211/CRDA will do that anyway ? */ | ||
3040 | |||
3041 | /* FIXME: Antenna reduction stuff */ | 3038 | /* FIXME: Antenna reduction stuff */ |
3042 | 3039 | ||
3043 | /* FIXME: Limit power on turbo modes */ | 3040 | /* FIXME: Limit power on turbo modes */ |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 55b4ac6d236f..05ef587ad2b4 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -1911,7 +1911,7 @@ | |||
1911 | #define AR5K_PHY_TURBO 0x9804 /* Register Address */ | 1911 | #define AR5K_PHY_TURBO 0x9804 /* Register Address */ |
1912 | #define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ | 1912 | #define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ |
1913 | #define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ | 1913 | #define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ |
1914 | #define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */ | 1914 | #define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo */ |
1915 | 1915 | ||
1916 | /* | 1916 | /* |
1917 | * PHY agility command register | 1917 | * PHY agility command register |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 498aa28ea9e6..4154959125b6 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -959,7 +959,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
959 | AR5K_QUEUE_DCU_SEQNUM(0)); | 959 | AR5K_QUEUE_DCU_SEQNUM(0)); |
960 | } | 960 | } |
961 | 961 | ||
962 | /* TSF accelerates on AR5211 durring reset | 962 | /* TSF accelerates on AR5211 during reset |
963 | * As a workaround save it here and restore | 963 | * As a workaround save it here and restore |
964 | * it later so that it's back in time after | 964 | * it later so that it's back in time after |
965 | * reset. This way it'll get re-synced on the | 965 | * reset. This way it'll get re-synced on the |
@@ -1080,7 +1080,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1080 | return ret; | 1080 | return ret; |
1081 | 1081 | ||
1082 | /* Spur info is available only from EEPROM versions | 1082 | /* Spur info is available only from EEPROM versions |
1083 | * bigger than 5.3 but but the EEPOM routines will use | 1083 | * greater than 5.3, but the EEPROM routines will use |
1084 | * static values for older versions */ | 1084 | * static values for older versions */ |
1085 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | 1085 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) |
1086 | ath5k_hw_set_spur_mitigation_filter(ah, | 1086 | ath5k_hw_set_spur_mitigation_filter(ah, |
@@ -1160,7 +1160,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1160 | */ | 1160 | */ |
1161 | 1161 | ||
1162 | /* Restore bssid and bssid mask */ | 1162 | /* Restore bssid and bssid mask */ |
1163 | ath5k_hw_set_associd(ah); | 1163 | ath5k_hw_set_bssid(ah); |
1164 | 1164 | ||
1165 | /* Set PCU config */ | 1165 | /* Set PCU config */ |
1166 | ath5k_hw_set_opmode(ah, op_mode); | 1166 | ath5k_hw_set_opmode(ah, op_mode); |
@@ -1173,11 +1173,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1173 | /* Set RSSI/BRSSI thresholds | 1173 | /* Set RSSI/BRSSI thresholds |
1174 | * | 1174 | * |
1175 | * Note: If we decide to set this value | 1175 | * Note: If we decide to set this value |
1176 | * dynamicaly, have in mind that when AR5K_RSSI_THR | 1176 | * dynamically, keep in mind that when AR5K_RSSI_THR |
1177 | * register is read it might return 0x40 if we haven't | 1177 | * register is read, it might return 0x40 if we haven't |
1178 | * wrote anything to it plus BMISS RSSI threshold is zeroed. | 1178 | * written anything to it. Also, BMISS RSSI threshold is zeroed. |
1179 | * So doing a save/restore procedure here isn't the right | 1179 | * So doing a save/restore procedure here isn't the right |
1180 | * choice. Instead store it on ath5k_hw */ | 1180 | * choice. Instead, store it in ath5k_hw */ |
1181 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | | 1181 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | |
1182 | AR5K_TUNE_BMISS_THRES << | 1182 | AR5K_TUNE_BMISS_THRES << |
1183 | AR5K_RSSI_THR_BMISS_S), | 1183 | AR5K_RSSI_THR_BMISS_S), |
@@ -1235,7 +1235,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1235 | 1235 | ||
1236 | /* | 1236 | /* |
1237 | * Perform ADC test to see if baseband is ready | 1237 | * Perform ADC test to see if baseband is ready |
1238 | * Set tx hold and check adc test register | 1238 | * Set TX hold and check ADC test register |
1239 | */ | 1239 | */ |
1240 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | 1240 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); |
1241 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | 1241 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); |
@@ -1254,15 +1254,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1254 | * | 1254 | * |
1255 | * This method is used to calibrate some static offsets | 1255 | * This method is used to calibrate some static offsets |
1256 | * used together with on-the fly I/Q calibration (the | 1256 | * used together with on-the fly I/Q calibration (the |
1257 | * one performed via ath5k_hw_phy_calibrate), that doesn't | 1257 | * one performed via ath5k_hw_phy_calibrate), which doesn't |
1258 | * interrupt rx path. | 1258 | * interrupt rx path. |
1259 | * | 1259 | * |
1260 | * While rx path is re-routed to the power detector we also | 1260 | * While rx path is re-routed to the power detector we also |
1261 | * start a noise floor calibration, to measure the | 1261 | * start a noise floor calibration to measure the |
1262 | * card's noise floor (the noise we measure when we are not | 1262 | * card's noise floor (the noise we measure when we are not |
1263 | * transmiting or receiving anything). | 1263 | * transmitting or receiving anything). |
1264 | * | 1264 | * |
1265 | * If we are in a noisy environment AGC calibration may time | 1265 | * If we are in a noisy environment, AGC calibration may time |
1266 | * out and/or noise floor calibration might timeout. | 1266 | * out and/or noise floor calibration might timeout. |
1267 | */ | 1267 | */ |
1268 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 1268 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, |
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h index e50baff66175..3ac4cff4239d 100644 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h | |||
@@ -25,10 +25,10 @@ | |||
25 | * | 25 | * |
26 | * We don't write on those registers directly but | 26 | * We don't write on those registers directly but |
27 | * we send a data packet on the chip, using a special register, | 27 | * we send a data packet on the chip, using a special register, |
28 | * that holds all the settings we need. After we 've sent the | 28 | * that holds all the settings we need. After we've sent the |
29 | * data packet, we write on another special register to notify hw | 29 | * data packet, we write on another special register to notify hw |
30 | * to apply the settings. This is done so that control registers | 30 | * to apply the settings. This is done so that control registers |
31 | * can be dynamicaly programmed during operation and the settings | 31 | * can be dynamically programmed during operation and the settings |
32 | * are applied faster on the hw. | 32 | * are applied faster on the hw. |
33 | * | 33 | * |
34 | * We call each data packet an "RF Bank" and all the data we write | 34 | * We call each data packet an "RF Bank" and all the data we write |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 973ae4f49f35..4555e9983903 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -46,6 +46,7 @@ ath9k_htc-y += htc_hst.o \ | |||
46 | htc_drv_txrx.o \ | 46 | htc_drv_txrx.o \ |
47 | htc_drv_main.o \ | 47 | htc_drv_main.o \ |
48 | htc_drv_beacon.o \ | 48 | htc_drv_beacon.o \ |
49 | htc_drv_init.o | 49 | htc_drv_init.o \ |
50 | htc_drv_gpio.o | ||
50 | 51 | ||
51 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o | 52 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 5b995bee70ae..a462da23e87e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -185,7 +185,7 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
185 | ath_print(common, ATH_DBG_INTERRUPT, | 185 | ath_print(common, ATH_DBG_INTERRUPT, |
186 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); | 186 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); |
187 | 187 | ||
188 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | 188 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); |
189 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); | 189 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); |
190 | 190 | ||
191 | } | 191 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 07f26ee7a723..f0197a6046ab 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -423,6 +423,7 @@ int ath_beaconq_config(struct ath_softc *sc); | |||
423 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ | 423 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ |
424 | #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ | 424 | #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ |
425 | #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ | 425 | #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ |
426 | #define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ | ||
426 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 427 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
427 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 428 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
428 | 429 | ||
@@ -436,14 +437,6 @@ void ath_ani_calibrate(unsigned long data); | |||
436 | /* BTCOEX */ | 437 | /* BTCOEX */ |
437 | /**********/ | 438 | /**********/ |
438 | 439 | ||
439 | /* Defines the BT AR_BT_COEX_WGHT used */ | ||
440 | enum ath_stomp_type { | ||
441 | ATH_BTCOEX_NO_STOMP, | ||
442 | ATH_BTCOEX_STOMP_ALL, | ||
443 | ATH_BTCOEX_STOMP_LOW, | ||
444 | ATH_BTCOEX_STOMP_NONE | ||
445 | }; | ||
446 | |||
447 | struct ath_btcoex { | 440 | struct ath_btcoex { |
448 | bool hw_timer_enabled; | 441 | bool hw_timer_enabled; |
449 | spinlock_t btcoex_lock; | 442 | spinlock_t btcoex_lock; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 4d4b22d52dfd..081192e78a46 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -359,11 +359,12 @@ void ath_beacon_tasklet(unsigned long data) | |||
359 | sc->beacon.bmisscnt++; | 359 | sc->beacon.bmisscnt++; |
360 | 360 | ||
361 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { | 361 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { |
362 | ath_print(common, ATH_DBG_BEACON, | 362 | ath_print(common, ATH_DBG_BSTUCK, |
363 | "missed %u consecutive beacons\n", | 363 | "missed %u consecutive beacons\n", |
364 | sc->beacon.bmisscnt); | 364 | sc->beacon.bmisscnt); |
365 | ath9k_hw_bstuck_nfcal(ah); | ||
365 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { | 366 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { |
366 | ath_print(common, ATH_DBG_BEACON, | 367 | ath_print(common, ATH_DBG_BSTUCK, |
367 | "beacon is officially stuck\n"); | 368 | "beacon is officially stuck\n"); |
368 | sc->sc_flags |= SC_OP_TSF_RESET; | 369 | sc->sc_flags |= SC_OP_TSF_RESET; |
369 | ath_reset(sc, false); | 370 | ath_reset(sc, false); |
@@ -373,7 +374,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
373 | } | 374 | } |
374 | 375 | ||
375 | if (sc->beacon.bmisscnt != 0) { | 376 | if (sc->beacon.bmisscnt != 0) { |
376 | ath_print(common, ATH_DBG_BEACON, | 377 | ath_print(common, ATH_DBG_BSTUCK, |
377 | "resume beacon xmit after %u misses\n", | 378 | "resume beacon xmit after %u misses\n", |
378 | sc->beacon.bmisscnt); | 379 | sc->beacon.bmisscnt); |
379 | sc->beacon.bmisscnt = 0; | 380 | sc->beacon.bmisscnt = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index fb4ac15f3b93..6a92e57fddf0 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -168,6 +168,7 @@ EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); | |||
168 | static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) | 168 | static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) |
169 | { | 169 | { |
170 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | 170 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
171 | u32 val; | ||
171 | 172 | ||
172 | /* | 173 | /* |
173 | * Program coex mode and weight registers to | 174 | * Program coex mode and weight registers to |
@@ -177,6 +178,12 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) | |||
177 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); | 178 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); |
178 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); | 179 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); |
179 | 180 | ||
181 | if (AR_SREV_9271(ah)) { | ||
182 | val = REG_READ(ah, 0x50040); | ||
183 | val &= 0xFFFFFEFF; | ||
184 | REG_WRITE(ah, 0x50040, val); | ||
185 | } | ||
186 | |||
180 | REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); | 187 | REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); |
181 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); | 188 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); |
182 | 189 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 45208690c0ec..67ee5d735cc1 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -19,8 +19,7 @@ | |||
19 | 19 | ||
20 | /* Common calibration code */ | 20 | /* Common calibration code */ |
21 | 21 | ||
22 | /* We can tune this as we go by monitoring really low values */ | 22 | #define ATH9K_NF_TOO_HIGH -60 |
23 | #define ATH9K_NF_TOO_LOW -60 | ||
24 | 23 | ||
25 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | 24 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) |
26 | { | 25 | { |
@@ -45,11 +44,39 @@ static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | |||
45 | return nfval; | 44 | return nfval; |
46 | } | 45 | } |
47 | 46 | ||
48 | static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | 47 | static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah, |
48 | struct ath9k_channel *chan) | ||
49 | { | ||
50 | struct ath_nf_limits *limit; | ||
51 | |||
52 | if (!chan || IS_CHAN_2GHZ(chan)) | ||
53 | limit = &ah->nf_2g; | ||
54 | else | ||
55 | limit = &ah->nf_5g; | ||
56 | |||
57 | return limit; | ||
58 | } | ||
59 | |||
60 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | ||
61 | struct ath9k_channel *chan) | ||
62 | { | ||
63 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; | ||
64 | } | ||
65 | |||
66 | |||
67 | static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, | ||
68 | struct ath9k_hw_cal_data *cal, | ||
49 | int16_t *nfarray) | 69 | int16_t *nfarray) |
50 | { | 70 | { |
71 | struct ath_common *common = ath9k_hw_common(ah); | ||
72 | struct ath_nf_limits *limit; | ||
73 | struct ath9k_nfcal_hist *h; | ||
74 | bool high_nf_mid = false; | ||
51 | int i; | 75 | int i; |
52 | 76 | ||
77 | h = cal->nfCalHist; | ||
78 | limit = ath9k_hw_get_nf_limits(ah, ah->curchan); | ||
79 | |||
53 | for (i = 0; i < NUM_NF_READINGS; i++) { | 80 | for (i = 0; i < NUM_NF_READINGS; i++) { |
54 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; | 81 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; |
55 | 82 | ||
@@ -63,7 +90,39 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | |||
63 | h[i].privNF = | 90 | h[i].privNF = |
64 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); | 91 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); |
65 | } | 92 | } |
93 | |||
94 | if (!h[i].privNF) | ||
95 | continue; | ||
96 | |||
97 | if (h[i].privNF > limit->max) { | ||
98 | high_nf_mid = true; | ||
99 | |||
100 | ath_print(common, ATH_DBG_CALIBRATE, | ||
101 | "NFmid[%d] (%d) > MAX (%d), %s\n", | ||
102 | i, h[i].privNF, limit->max, | ||
103 | (cal->nfcal_interference ? | ||
104 | "not corrected (due to interference)" : | ||
105 | "correcting to MAX")); | ||
106 | |||
107 | /* | ||
108 | * Normally we limit the average noise floor by the | ||
109 | * hardware specific maximum here. However if we have | ||
110 | * encountered stuck beacons because of interference, | ||
111 | * we bypass this limit here in order to better deal | ||
112 | * with our environment. | ||
113 | */ | ||
114 | if (!cal->nfcal_interference) | ||
115 | h[i].privNF = limit->max; | ||
116 | } | ||
66 | } | 117 | } |
118 | |||
119 | /* | ||
120 | * If the noise floor seems normal for all chains, assume that | ||
121 | * there is no significant interference in the environment anymore. | ||
122 | * Re-enable the enforcement of the NF maximum again. | ||
123 | */ | ||
124 | if (!high_nf_mid) | ||
125 | cal->nfcal_interference = false; | ||
67 | } | 126 | } |
68 | 127 | ||
69 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, | 128 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, |
@@ -104,19 +163,6 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah, | |||
104 | ah->cal_samples = 0; | 163 | ah->cal_samples = 0; |
105 | } | 164 | } |
106 | 165 | ||
107 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | ||
108 | struct ath9k_channel *chan) | ||
109 | { | ||
110 | struct ath_nf_limits *limit; | ||
111 | |||
112 | if (!chan || IS_CHAN_2GHZ(chan)) | ||
113 | limit = &ah->nf_2g; | ||
114 | else | ||
115 | limit = &ah->nf_5g; | ||
116 | |||
117 | return limit->nominal; | ||
118 | } | ||
119 | |||
120 | /* This is done for the currently configured channel */ | 166 | /* This is done for the currently configured channel */ |
121 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 167 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
122 | { | 168 | { |
@@ -277,10 +323,10 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) | |||
277 | "NF calibrated [%s] [chain %d] is %d\n", | 323 | "NF calibrated [%s] [chain %d] is %d\n", |
278 | (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); | 324 | (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); |
279 | 325 | ||
280 | if (nf[i] > limit->max) { | 326 | if (nf[i] > ATH9K_NF_TOO_HIGH) { |
281 | ath_print(common, ATH_DBG_CALIBRATE, | 327 | ath_print(common, ATH_DBG_CALIBRATE, |
282 | "NF[%d] (%d) > MAX (%d), correcting to MAX", | 328 | "NF[%d] (%d) > MAX (%d), correcting to MAX", |
283 | i, nf[i], limit->max); | 329 | i, nf[i], ATH9K_NF_TOO_HIGH); |
284 | nf[i] = limit->max; | 330 | nf[i] = limit->max; |
285 | } else if (nf[i] < limit->min) { | 331 | } else if (nf[i] < limit->min) { |
286 | ath_print(common, ATH_DBG_CALIBRATE, | 332 | ath_print(common, ATH_DBG_CALIBRATE, |
@@ -326,7 +372,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
326 | 372 | ||
327 | h = caldata->nfCalHist; | 373 | h = caldata->nfCalHist; |
328 | caldata->nfcal_pending = false; | 374 | caldata->nfcal_pending = false; |
329 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); | 375 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); |
330 | caldata->rawNoiseFloor = h[0].privNF; | 376 | caldata->rawNoiseFloor = h[0].privNF; |
331 | return true; | 377 | return true; |
332 | } | 378 | } |
@@ -361,3 +407,28 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | |||
361 | return ah->caldata->rawNoiseFloor; | 407 | return ah->caldata->rawNoiseFloor; |
362 | } | 408 | } |
363 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | 409 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); |
410 | |||
411 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) | ||
412 | { | ||
413 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
414 | |||
415 | if (unlikely(!caldata)) | ||
416 | return; | ||
417 | |||
418 | /* | ||
419 | * If beacons are stuck, the most likely cause is interference. | ||
420 | * Triggering a noise floor calibration at this point helps the | ||
421 | * hardware adapt to a noisy environment much faster. | ||
422 | * To ensure that we recover from stuck beacons quickly, let | ||
423 | * the baseband update the internal NF value itself, similar to | ||
424 | * what is being done after a full reset. | ||
425 | */ | ||
426 | if (!caldata->nfcal_pending) | ||
427 | ath9k_hw_start_nfcal(ah, true); | ||
428 | else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)) | ||
429 | ath9k_hw_getnf(ah, ah->curchan); | ||
430 | |||
431 | caldata->nfcal_interference = true; | ||
432 | } | ||
433 | EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal); | ||
434 | |||
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 0a304b3eeeb6..5b053a6260b2 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -113,6 +113,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); | |||
113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); | 113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); |
114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | 114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
115 | struct ath9k_channel *chan); | 115 | struct ath9k_channel *chan); |
116 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); | ||
116 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); | 117 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); |
117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, | 118 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
118 | struct ath9k_cal_list *currCal); | 119 | struct ath9k_cal_list *currCal); |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index c86f7d3593ab..31cfe468e3fc 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -46,12 +46,17 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | |||
46 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 46 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
47 | 47 | ||
48 | if (tx_info->control.hw_key) { | 48 | if (tx_info->control.hw_key) { |
49 | if (tx_info->control.hw_key->alg == ALG_WEP) | 49 | switch (tx_info->control.hw_key->cipher) { |
50 | case WLAN_CIPHER_SUITE_WEP40: | ||
51 | case WLAN_CIPHER_SUITE_WEP104: | ||
50 | return ATH9K_KEY_TYPE_WEP; | 52 | return ATH9K_KEY_TYPE_WEP; |
51 | else if (tx_info->control.hw_key->alg == ALG_TKIP) | 53 | case WLAN_CIPHER_SUITE_TKIP: |
52 | return ATH9K_KEY_TYPE_TKIP; | 54 | return ATH9K_KEY_TYPE_TKIP; |
53 | else if (tx_info->control.hw_key->alg == ALG_CCMP) | 55 | case WLAN_CIPHER_SUITE_CCMP: |
54 | return ATH9K_KEY_TYPE_AES; | 56 | return ATH9K_KEY_TYPE_AES; |
57 | default: | ||
58 | break; | ||
59 | } | ||
55 | } | 60 | } |
56 | 61 | ||
57 | return ATH9K_KEY_TYPE_CLEAR; | 62 | return ATH9K_KEY_TYPE_CLEAR; |
@@ -212,11 +217,11 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | |||
212 | } | 217 | } |
213 | 218 | ||
214 | static int ath_reserve_key_cache_slot(struct ath_common *common, | 219 | static int ath_reserve_key_cache_slot(struct ath_common *common, |
215 | enum ieee80211_key_alg alg) | 220 | u32 cipher) |
216 | { | 221 | { |
217 | int i; | 222 | int i; |
218 | 223 | ||
219 | if (alg == ALG_TKIP) | 224 | if (cipher == WLAN_CIPHER_SUITE_TKIP) |
220 | return ath_reserve_key_cache_slot_tkip(common); | 225 | return ath_reserve_key_cache_slot_tkip(common); |
221 | 226 | ||
222 | /* First, try to find slots that would not be available for TKIP. */ | 227 | /* First, try to find slots that would not be available for TKIP. */ |
@@ -293,14 +298,15 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
293 | 298 | ||
294 | memset(&hk, 0, sizeof(hk)); | 299 | memset(&hk, 0, sizeof(hk)); |
295 | 300 | ||
296 | switch (key->alg) { | 301 | switch (key->cipher) { |
297 | case ALG_WEP: | 302 | case WLAN_CIPHER_SUITE_WEP40: |
303 | case WLAN_CIPHER_SUITE_WEP104: | ||
298 | hk.kv_type = ATH9K_CIPHER_WEP; | 304 | hk.kv_type = ATH9K_CIPHER_WEP; |
299 | break; | 305 | break; |
300 | case ALG_TKIP: | 306 | case WLAN_CIPHER_SUITE_TKIP: |
301 | hk.kv_type = ATH9K_CIPHER_TKIP; | 307 | hk.kv_type = ATH9K_CIPHER_TKIP; |
302 | break; | 308 | break; |
303 | case ALG_CCMP: | 309 | case WLAN_CIPHER_SUITE_CCMP: |
304 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | 310 | hk.kv_type = ATH9K_CIPHER_AES_CCM; |
305 | break; | 311 | break; |
306 | default: | 312 | default: |
@@ -316,7 +322,7 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
316 | memcpy(gmac, vif->addr, ETH_ALEN); | 322 | memcpy(gmac, vif->addr, ETH_ALEN); |
317 | gmac[0] |= 0x01; | 323 | gmac[0] |= 0x01; |
318 | mac = gmac; | 324 | mac = gmac; |
319 | idx = ath_reserve_key_cache_slot(common, key->alg); | 325 | idx = ath_reserve_key_cache_slot(common, key->cipher); |
320 | break; | 326 | break; |
321 | case NL80211_IFTYPE_ADHOC: | 327 | case NL80211_IFTYPE_ADHOC: |
322 | if (!sta) { | 328 | if (!sta) { |
@@ -326,7 +332,7 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
326 | memcpy(gmac, sta->addr, ETH_ALEN); | 332 | memcpy(gmac, sta->addr, ETH_ALEN); |
327 | gmac[0] |= 0x01; | 333 | gmac[0] |= 0x01; |
328 | mac = gmac; | 334 | mac = gmac; |
329 | idx = ath_reserve_key_cache_slot(common, key->alg); | 335 | idx = ath_reserve_key_cache_slot(common, key->cipher); |
330 | break; | 336 | break; |
331 | default: | 337 | default: |
332 | idx = key->keyidx; | 338 | idx = key->keyidx; |
@@ -348,13 +354,13 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
348 | return -EOPNOTSUPP; | 354 | return -EOPNOTSUPP; |
349 | mac = sta->addr; | 355 | mac = sta->addr; |
350 | 356 | ||
351 | idx = ath_reserve_key_cache_slot(common, key->alg); | 357 | idx = ath_reserve_key_cache_slot(common, key->cipher); |
352 | } | 358 | } |
353 | 359 | ||
354 | if (idx < 0) | 360 | if (idx < 0) |
355 | return -ENOSPC; /* no free key cache entries */ | 361 | return -ENOSPC; /* no free key cache entries */ |
356 | 362 | ||
357 | if (key->alg == ALG_TKIP) | 363 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
358 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | 364 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, |
359 | vif->type == NL80211_IFTYPE_AP); | 365 | vif->type == NL80211_IFTYPE_AP); |
360 | else | 366 | else |
@@ -364,7 +370,7 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
364 | return -EIO; | 370 | return -EIO; |
365 | 371 | ||
366 | set_bit(idx, common->keymap); | 372 | set_bit(idx, common->keymap); |
367 | if (key->alg == ALG_TKIP) { | 373 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
368 | set_bit(idx + 64, common->keymap); | 374 | set_bit(idx + 64, common->keymap); |
369 | if (common->splitmic) { | 375 | if (common->splitmic) { |
370 | set_bit(idx + 32, common->keymap); | 376 | set_bit(idx + 32, common->keymap); |
@@ -389,7 +395,7 @@ void ath9k_cmn_key_delete(struct ath_common *common, | |||
389 | return; | 395 | return; |
390 | 396 | ||
391 | clear_bit(key->hw_key_idx, common->keymap); | 397 | clear_bit(key->hw_key_idx, common->keymap); |
392 | if (key->alg != ALG_TKIP) | 398 | if (key->cipher != WLAN_CIPHER_SUITE_TKIP) |
393 | return; | 399 | return; |
394 | 400 | ||
395 | clear_bit(key->hw_key_idx + 64, common->keymap); | 401 | clear_bit(key->hw_key_idx + 64, common->keymap); |
@@ -414,6 +420,37 @@ int ath9k_cmn_count_streams(unsigned int chainmask, int max) | |||
414 | } | 420 | } |
415 | EXPORT_SYMBOL(ath9k_cmn_count_streams); | 421 | EXPORT_SYMBOL(ath9k_cmn_count_streams); |
416 | 422 | ||
423 | /* | ||
424 | * Configures appropriate weight based on stomp type. | ||
425 | */ | ||
426 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | ||
427 | enum ath_stomp_type stomp_type) | ||
428 | { | ||
429 | struct ath_hw *ah = common->ah; | ||
430 | |||
431 | switch (stomp_type) { | ||
432 | case ATH_BTCOEX_STOMP_ALL: | ||
433 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
434 | AR_STOMP_ALL_WLAN_WGHT); | ||
435 | break; | ||
436 | case ATH_BTCOEX_STOMP_LOW: | ||
437 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
438 | AR_STOMP_LOW_WLAN_WGHT); | ||
439 | break; | ||
440 | case ATH_BTCOEX_STOMP_NONE: | ||
441 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
442 | AR_STOMP_NONE_WLAN_WGHT); | ||
443 | break; | ||
444 | default: | ||
445 | ath_print(common, ATH_DBG_BTCOEX, | ||
446 | "Invalid Stomptype\n"); | ||
447 | break; | ||
448 | } | ||
449 | |||
450 | ath9k_hw_btcoex_enable(ah); | ||
451 | } | ||
452 | EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp); | ||
453 | |||
417 | static int __init ath9k_cmn_init(void) | 454 | static int __init ath9k_cmn_init(void) |
418 | { | 455 | { |
419 | return 0; | 456 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 97809d39c73f..4aa4e7dbe4d2 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -52,6 +52,14 @@ | |||
52 | #define ATH_EP_RND(x, mul) \ | 52 | #define ATH_EP_RND(x, mul) \ |
53 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | 53 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) |
54 | 54 | ||
55 | /* Defines the BT AR_BT_COEX_WGHT used */ | ||
56 | enum ath_stomp_type { | ||
57 | ATH_BTCOEX_NO_STOMP, | ||
58 | ATH_BTCOEX_STOMP_ALL, | ||
59 | ATH_BTCOEX_STOMP_LOW, | ||
60 | ATH_BTCOEX_STOMP_NONE | ||
61 | }; | ||
62 | |||
55 | int ath9k_cmn_padpos(__le16 frame_control); | 63 | int ath9k_cmn_padpos(__le16 frame_control); |
56 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 64 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
57 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | 65 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, |
@@ -65,3 +73,5 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
65 | void ath9k_cmn_key_delete(struct ath_common *common, | 73 | void ath9k_cmn_key_delete(struct ath_common *common, |
66 | struct ieee80211_key_conf *key); | 74 | struct ieee80211_key_conf *key); |
67 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 75 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
76 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | ||
77 | enum ath_stomp_type stomp_type); | ||
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 3a8ee999da5d..4a9a68bba324 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -251,36 +251,6 @@ static void ath_detect_bt_priority(struct ath_softc *sc) | |||
251 | } | 251 | } |
252 | } | 252 | } |
253 | 253 | ||
254 | /* | ||
255 | * Configures appropriate weight based on stomp type. | ||
256 | */ | ||
257 | static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, | ||
258 | enum ath_stomp_type stomp_type) | ||
259 | { | ||
260 | struct ath_hw *ah = sc->sc_ah; | ||
261 | |||
262 | switch (stomp_type) { | ||
263 | case ATH_BTCOEX_STOMP_ALL: | ||
264 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
265 | AR_STOMP_ALL_WLAN_WGHT); | ||
266 | break; | ||
267 | case ATH_BTCOEX_STOMP_LOW: | ||
268 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
269 | AR_STOMP_LOW_WLAN_WGHT); | ||
270 | break; | ||
271 | case ATH_BTCOEX_STOMP_NONE: | ||
272 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
273 | AR_STOMP_NONE_WLAN_WGHT); | ||
274 | break; | ||
275 | default: | ||
276 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
277 | "Invalid Stomptype\n"); | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | ath9k_hw_btcoex_enable(ah); | ||
282 | } | ||
283 | |||
284 | static void ath9k_gen_timer_start(struct ath_hw *ah, | 254 | static void ath9k_gen_timer_start(struct ath_hw *ah, |
285 | struct ath_gen_timer *timer, | 255 | struct ath_gen_timer *timer, |
286 | u32 timer_next, | 256 | u32 timer_next, |
@@ -319,6 +289,7 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
319 | struct ath_softc *sc = (struct ath_softc *) data; | 289 | struct ath_softc *sc = (struct ath_softc *) data; |
320 | struct ath_hw *ah = sc->sc_ah; | 290 | struct ath_hw *ah = sc->sc_ah; |
321 | struct ath_btcoex *btcoex = &sc->btcoex; | 291 | struct ath_btcoex *btcoex = &sc->btcoex; |
292 | struct ath_common *common = ath9k_hw_common(ah); | ||
322 | u32 timer_period; | 293 | u32 timer_period; |
323 | bool is_btscan; | 294 | bool is_btscan; |
324 | 295 | ||
@@ -328,7 +299,7 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
328 | 299 | ||
329 | spin_lock_bh(&btcoex->btcoex_lock); | 300 | spin_lock_bh(&btcoex->btcoex_lock); |
330 | 301 | ||
331 | ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL : | 302 | ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : |
332 | btcoex->bt_stomp_type); | 303 | btcoex->bt_stomp_type); |
333 | 304 | ||
334 | spin_unlock_bh(&btcoex->btcoex_lock); | 305 | spin_unlock_bh(&btcoex->btcoex_lock); |
@@ -359,17 +330,18 @@ static void ath_btcoex_no_stomp_timer(void *arg) | |||
359 | struct ath_softc *sc = (struct ath_softc *)arg; | 330 | struct ath_softc *sc = (struct ath_softc *)arg; |
360 | struct ath_hw *ah = sc->sc_ah; | 331 | struct ath_hw *ah = sc->sc_ah; |
361 | struct ath_btcoex *btcoex = &sc->btcoex; | 332 | struct ath_btcoex *btcoex = &sc->btcoex; |
333 | struct ath_common *common = ath9k_hw_common(ah); | ||
362 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | 334 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; |
363 | 335 | ||
364 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | 336 | ath_print(common, ATH_DBG_BTCOEX, |
365 | "no stomp timer running\n"); | 337 | "no stomp timer running\n"); |
366 | 338 | ||
367 | spin_lock_bh(&btcoex->btcoex_lock); | 339 | spin_lock_bh(&btcoex->btcoex_lock); |
368 | 340 | ||
369 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | 341 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) |
370 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); | 342 | ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); |
371 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | 343 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) |
372 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); | 344 | ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); |
373 | 345 | ||
374 | spin_unlock_bh(&btcoex->btcoex_lock); | 346 | spin_unlock_bh(&btcoex->btcoex_lock); |
375 | } | 347 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 17e7a9a367e7..495f18950ac9 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -920,7 +920,8 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, | |||
920 | } | 920 | } |
921 | 921 | ||
922 | ret = ath9k_htc_hw_init(hif_dev->htc_handle, | 922 | ret = ath9k_htc_hw_init(hif_dev->htc_handle, |
923 | &hif_dev->udev->dev, hif_dev->device_id); | 923 | &hif_dev->udev->dev, hif_dev->device_id, |
924 | hif_dev->udev->product); | ||
924 | if (ret) { | 925 | if (ret) { |
925 | ret = -EINVAL; | 926 | ret = -EINVAL; |
926 | goto err_htc_hw_init; | 927 | goto err_htc_hw_init; |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 43b9e21bc562..75ecf6a30d25 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -316,17 +316,32 @@ struct htc_beacon_config { | |||
316 | u8 dtim_count; | 316 | u8 dtim_count; |
317 | }; | 317 | }; |
318 | 318 | ||
319 | #define OP_INVALID BIT(0) | 319 | struct ath_btcoex { |
320 | #define OP_SCANNING BIT(1) | 320 | u32 bt_priority_cnt; |
321 | #define OP_FULL_RESET BIT(2) | 321 | unsigned long bt_priority_time; |
322 | #define OP_LED_ASSOCIATED BIT(3) | 322 | int bt_stomp_type; /* Types of BT stomping */ |
323 | #define OP_LED_ON BIT(4) | 323 | u32 btcoex_no_stomp; |
324 | #define OP_PREAMBLE_SHORT BIT(5) | 324 | u32 btcoex_period; |
325 | #define OP_PROTECT_ENABLE BIT(6) | 325 | u32 btscan_no_stomp; |
326 | #define OP_ASSOCIATED BIT(7) | 326 | }; |
327 | #define OP_ENABLE_BEACON BIT(8) | 327 | |
328 | #define OP_LED_DEINIT BIT(9) | 328 | void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv); |
329 | #define OP_UNPLUGGED BIT(10) | 329 | void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv); |
330 | void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv); | ||
331 | |||
332 | #define OP_INVALID BIT(0) | ||
333 | #define OP_SCANNING BIT(1) | ||
334 | #define OP_FULL_RESET BIT(2) | ||
335 | #define OP_LED_ASSOCIATED BIT(3) | ||
336 | #define OP_LED_ON BIT(4) | ||
337 | #define OP_PREAMBLE_SHORT BIT(5) | ||
338 | #define OP_PROTECT_ENABLE BIT(6) | ||
339 | #define OP_ASSOCIATED BIT(7) | ||
340 | #define OP_ENABLE_BEACON BIT(8) | ||
341 | #define OP_LED_DEINIT BIT(9) | ||
342 | #define OP_UNPLUGGED BIT(10) | ||
343 | #define OP_BT_PRIORITY_DETECTED BIT(11) | ||
344 | #define OP_BT_SCAN BIT(12) | ||
330 | 345 | ||
331 | struct ath9k_htc_priv { | 346 | struct ath9k_htc_priv { |
332 | struct device *dev; | 347 | struct device *dev; |
@@ -391,6 +406,9 @@ struct ath9k_htc_priv { | |||
391 | int cabq; | 406 | int cabq; |
392 | int hwq_map[WME_NUM_AC]; | 407 | int hwq_map[WME_NUM_AC]; |
393 | 408 | ||
409 | struct ath_btcoex btcoex; | ||
410 | struct delayed_work coex_period_work; | ||
411 | struct delayed_work duty_cycle_work; | ||
394 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 412 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
395 | struct ath9k_debug debug; | 413 | struct ath9k_debug debug; |
396 | #endif | 414 | #endif |
@@ -443,7 +461,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv); | |||
443 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); | 461 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); |
444 | 462 | ||
445 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | 463 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, |
446 | u16 devid); | 464 | u16 devid, char *product); |
447 | void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); | 465 | void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); |
448 | #ifdef CONFIG_PM | 466 | #ifdef CONFIG_PM |
449 | int ath9k_htc_resume(struct htc_target *htc_handle); | 467 | int ath9k_htc_resume(struct htc_target *htc_handle); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c new file mode 100644 index 000000000000..50eec9a3b88c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -0,0 +1,134 @@ | |||
1 | #include "htc.h" | ||
2 | |||
3 | /******************/ | ||
4 | /* BTCOEX */ | ||
5 | /******************/ | ||
6 | |||
7 | /* | ||
8 | * Detects if there is any priority bt traffic | ||
9 | */ | ||
10 | static void ath_detect_bt_priority(struct ath9k_htc_priv *priv) | ||
11 | { | ||
12 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
13 | struct ath_hw *ah = priv->ah; | ||
14 | |||
15 | if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio)) | ||
16 | btcoex->bt_priority_cnt++; | ||
17 | |||
18 | if (time_after(jiffies, btcoex->bt_priority_time + | ||
19 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | ||
20 | priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); | ||
21 | /* Detect if colocated bt started scanning */ | ||
22 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { | ||
23 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
24 | "BT scan detected"); | ||
25 | priv->op_flags |= (OP_BT_SCAN | | ||
26 | OP_BT_PRIORITY_DETECTED); | ||
27 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | ||
28 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
29 | "BT priority traffic detected"); | ||
30 | priv->op_flags |= OP_BT_PRIORITY_DETECTED; | ||
31 | } | ||
32 | |||
33 | btcoex->bt_priority_cnt = 0; | ||
34 | btcoex->bt_priority_time = jiffies; | ||
35 | } | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * This is the master bt coex work which runs for every | ||
40 | * 45ms, bt traffic will be given priority during 55% of this | ||
41 | * period while wlan gets remaining 45% | ||
42 | */ | ||
43 | static void ath_btcoex_period_work(struct work_struct *work) | ||
44 | { | ||
45 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
46 | coex_period_work.work); | ||
47 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
48 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
49 | u32 timer_period; | ||
50 | bool is_btscan; | ||
51 | int ret; | ||
52 | u8 cmd_rsp, aggr; | ||
53 | |||
54 | ath_detect_bt_priority(priv); | ||
55 | |||
56 | is_btscan = !!(priv->op_flags & OP_BT_SCAN); | ||
57 | |||
58 | aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED; | ||
59 | |||
60 | WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr); | ||
61 | |||
62 | ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : | ||
63 | btcoex->bt_stomp_type); | ||
64 | |||
65 | timer_period = is_btscan ? btcoex->btscan_no_stomp : | ||
66 | btcoex->btcoex_no_stomp; | ||
67 | ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, | ||
68 | msecs_to_jiffies(timer_period)); | ||
69 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, | ||
70 | msecs_to_jiffies(btcoex->btcoex_period)); | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Work to time slice between wlan and bt traffic and | ||
75 | * configure weight registers | ||
76 | */ | ||
77 | static void ath_btcoex_duty_cycle_work(struct work_struct *work) | ||
78 | { | ||
79 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
80 | duty_cycle_work.work); | ||
81 | struct ath_hw *ah = priv->ah; | ||
82 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
83 | struct ath_common *common = ath9k_hw_common(ah); | ||
84 | bool is_btscan = priv->op_flags & OP_BT_SCAN; | ||
85 | |||
86 | ath_print(common, ATH_DBG_BTCOEX, | ||
87 | "time slice work for bt and wlan\n"); | ||
88 | |||
89 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | ||
90 | ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); | ||
91 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | ||
92 | ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); | ||
93 | } | ||
94 | |||
95 | void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) | ||
96 | { | ||
97 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
98 | |||
99 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD; | ||
100 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | ||
101 | btcoex->btcoex_period / 100; | ||
102 | btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * | ||
103 | btcoex->btcoex_period / 100; | ||
104 | INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work); | ||
105 | INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * (Re)start btcoex work | ||
110 | */ | ||
111 | |||
112 | void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv) | ||
113 | { | ||
114 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
115 | struct ath_hw *ah = priv->ah; | ||
116 | |||
117 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
118 | "Starting btcoex work"); | ||
119 | |||
120 | btcoex->bt_priority_cnt = 0; | ||
121 | btcoex->bt_priority_time = jiffies; | ||
122 | priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); | ||
123 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0); | ||
124 | } | ||
125 | |||
126 | |||
127 | /* | ||
128 | * Cancel btcoex and bt duty cycle work. | ||
129 | */ | ||
130 | void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv) | ||
131 | { | ||
132 | cancel_delayed_work_sync(&priv->coex_period_work); | ||
133 | cancel_delayed_work_sync(&priv->duty_cycle_work); | ||
134 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 2d4279191d7a..695e2b088d10 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | |||
41 | .max_power = 20, \ | 41 | .max_power = 20, \ |
42 | } | 42 | } |
43 | 43 | ||
44 | #define ATH_HTC_BTCOEX_PRODUCT_ID "wb193" | ||
45 | |||
44 | static struct ieee80211_channel ath9k_2ghz_channels[] = { | 46 | static struct ieee80211_channel ath9k_2ghz_channels[] = { |
45 | CHAN2G(2412, 0), /* Channel 1 */ | 47 | CHAN2G(2412, 0), /* Channel 1 */ |
46 | CHAN2G(2417, 1), /* Channel 2 */ | 48 | CHAN2G(2417, 1), /* Channel 2 */ |
@@ -605,7 +607,31 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
605 | priv->ah->opmode = NL80211_IFTYPE_STATION; | 607 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
606 | } | 608 | } |
607 | 609 | ||
608 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | 610 | static void ath9k_init_btcoex(struct ath9k_htc_priv *priv) |
611 | { | ||
612 | int qnum; | ||
613 | |||
614 | switch (priv->ah->btcoex_hw.scheme) { | ||
615 | case ATH_BTCOEX_CFG_NONE: | ||
616 | break; | ||
617 | case ATH_BTCOEX_CFG_3WIRE: | ||
618 | priv->ah->btcoex_hw.btactive_gpio = 7; | ||
619 | priv->ah->btcoex_hw.btpriority_gpio = 6; | ||
620 | priv->ah->btcoex_hw.wlanactive_gpio = 8; | ||
621 | priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
622 | ath9k_hw_btcoex_init_3wire(priv->ah); | ||
623 | ath_htc_init_btcoex_work(priv); | ||
624 | qnum = priv->hwq_map[WME_AC_BE]; | ||
625 | ath9k_hw_init_btcoex_hw(priv->ah, qnum); | ||
626 | break; | ||
627 | default: | ||
628 | WARN_ON(1); | ||
629 | break; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, | ||
634 | u16 devid, char *product) | ||
609 | { | 635 | { |
610 | struct ath_hw *ah = NULL; | 636 | struct ath_hw *ah = NULL; |
611 | struct ath_common *common; | 637 | struct ath_common *common; |
@@ -672,6 +698,11 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | |||
672 | ath9k_init_channels_rates(priv); | 698 | ath9k_init_channels_rates(priv); |
673 | ath9k_init_misc(priv); | 699 | ath9k_init_misc(priv); |
674 | 700 | ||
701 | if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) { | ||
702 | ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE; | ||
703 | ath9k_init_btcoex(priv); | ||
704 | } | ||
705 | |||
675 | return 0; | 706 | return 0; |
676 | 707 | ||
677 | err_queues: | 708 | err_queues: |
@@ -734,7 +765,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
734 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | 765 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
735 | } | 766 | } |
736 | 767 | ||
737 | static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | 768 | static int ath9k_init_device(struct ath9k_htc_priv *priv, |
769 | u16 devid, char *product) | ||
738 | { | 770 | { |
739 | struct ieee80211_hw *hw = priv->hw; | 771 | struct ieee80211_hw *hw = priv->hw; |
740 | struct ath_common *common; | 772 | struct ath_common *common; |
@@ -743,7 +775,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | |||
743 | struct ath_regulatory *reg; | 775 | struct ath_regulatory *reg; |
744 | 776 | ||
745 | /* Bring up device */ | 777 | /* Bring up device */ |
746 | error = ath9k_init_priv(priv, devid); | 778 | error = ath9k_init_priv(priv, devid, product); |
747 | if (error != 0) | 779 | if (error != 0) |
748 | goto err_init; | 780 | goto err_init; |
749 | 781 | ||
@@ -801,7 +833,7 @@ err_init: | |||
801 | } | 833 | } |
802 | 834 | ||
803 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | 835 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, |
804 | u16 devid) | 836 | u16 devid, char *product) |
805 | { | 837 | { |
806 | struct ieee80211_hw *hw; | 838 | struct ieee80211_hw *hw; |
807 | struct ath9k_htc_priv *priv; | 839 | struct ath9k_htc_priv *priv; |
@@ -835,7 +867,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | |||
835 | /* The device may have been unplugged earlier. */ | 867 | /* The device may have been unplugged earlier. */ |
836 | priv->op_flags &= ~OP_UNPLUGGED; | 868 | priv->op_flags &= ~OP_UNPLUGGED; |
837 | 869 | ||
838 | ret = ath9k_init_device(priv, devid); | 870 | ret = ath9k_init_device(priv, devid, product); |
839 | if (ret) | 871 | if (ret) |
840 | goto err_init; | 872 | goto err_init; |
841 | 873 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7d09b4b17bbd..5e318cb662c6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1210,6 +1210,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1210 | 1210 | ||
1211 | ieee80211_wake_queues(hw); | 1211 | ieee80211_wake_queues(hw); |
1212 | 1212 | ||
1213 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { | ||
1214 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
1215 | AR_STOMP_LOW_WLAN_WGHT); | ||
1216 | ath9k_hw_btcoex_enable(ah); | ||
1217 | ath_htc_resume_btcoex_work(priv); | ||
1218 | } | ||
1213 | mutex_unlock(&priv->mutex); | 1219 | mutex_unlock(&priv->mutex); |
1214 | 1220 | ||
1215 | return ret; | 1221 | return ret; |
@@ -1254,6 +1260,12 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1254 | "Monitor interface removed\n"); | 1260 | "Monitor interface removed\n"); |
1255 | } | 1261 | } |
1256 | 1262 | ||
1263 | if (ah->btcoex_hw.enabled) { | ||
1264 | ath9k_hw_btcoex_disable(ah); | ||
1265 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | ||
1266 | ath_htc_cancel_btcoex_work(priv); | ||
1267 | } | ||
1268 | |||
1257 | ath9k_hw_phy_disable(ah); | 1269 | ath9k_hw_phy_disable(ah); |
1258 | ath9k_hw_disable(ah); | 1270 | ath9k_hw_disable(ah); |
1259 | ath9k_hw_configpcipowersave(ah, 1, 1); | 1271 | ath9k_hw_configpcipowersave(ah, 1, 1); |
@@ -1585,9 +1597,10 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1585 | key->hw_key_idx = ret; | 1597 | key->hw_key_idx = ret; |
1586 | /* push IV and Michael MIC generation to stack */ | 1598 | /* push IV and Michael MIC generation to stack */ |
1587 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1599 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1588 | if (key->alg == ALG_TKIP) | 1600 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1589 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1601 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1590 | if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP) | 1602 | if (priv->ah->sw_mgmt_crypto && |
1603 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | ||
1591 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 1604 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; |
1592 | ret = 0; | 1605 | ret = 0; |
1593 | } | 1606 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 705c0f342e1c..861ec9269309 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -462,9 +462,9 @@ void ath9k_htc_hw_free(struct htc_target *htc) | |||
462 | } | 462 | } |
463 | 463 | ||
464 | int ath9k_htc_hw_init(struct htc_target *target, | 464 | int ath9k_htc_hw_init(struct htc_target *target, |
465 | struct device *dev, u16 devid) | 465 | struct device *dev, u16 devid, char *product) |
466 | { | 466 | { |
467 | if (ath9k_htc_probe_device(target, dev, devid)) { | 467 | if (ath9k_htc_probe_device(target, dev, devid, product)) { |
468 | printk(KERN_ERR "Failed to initialize the device\n"); | 468 | printk(KERN_ERR "Failed to initialize the device\n"); |
469 | return -ENODEV; | 469 | return -ENODEV; |
470 | } | 470 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index faba6790328b..07b6509d5896 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h | |||
@@ -239,7 +239,7 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, | |||
239 | struct device *dev); | 239 | struct device *dev); |
240 | void ath9k_htc_hw_free(struct htc_target *htc); | 240 | void ath9k_htc_hw_free(struct htc_target *htc); |
241 | int ath9k_htc_hw_init(struct htc_target *target, | 241 | int ath9k_htc_hw_init(struct htc_target *target, |
242 | struct device *dev, u16 devid); | 242 | struct device *dev, u16 devid, char *product); |
243 | void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); | 243 | void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); |
244 | 244 | ||
245 | #endif /* HTC_HST_H */ | 245 | #endif /* HTC_HST_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 399f7c1283cd..1601dd439890 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -355,6 +355,7 @@ struct ath9k_hw_cal_data { | |||
355 | int16_t rawNoiseFloor; | 355 | int16_t rawNoiseFloor; |
356 | bool paprd_done; | 356 | bool paprd_done; |
357 | bool nfcal_pending; | 357 | bool nfcal_pending; |
358 | bool nfcal_interference; | ||
358 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | 359 | u16 small_signal_gain[AR9300_MAX_CHAINS]; |
359 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | 360 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; |
360 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 361 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3caa32316e7b..1165f909ef04 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -226,9 +226,10 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
226 | caldata = &aphy->caldata; | 226 | caldata = &aphy->caldata; |
227 | 227 | ||
228 | ath_print(common, ATH_DBG_CONFIG, | 228 | ath_print(common, ATH_DBG_CONFIG, |
229 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", | 229 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", |
230 | sc->sc_ah->curchan->channel, | 230 | sc->sc_ah->curchan->channel, |
231 | channel->center_freq, conf_is_ht40(conf)); | 231 | channel->center_freq, conf_is_ht40(conf), |
232 | fastcc); | ||
232 | 233 | ||
233 | spin_lock_bh(&sc->sc_resetlock); | 234 | spin_lock_bh(&sc->sc_resetlock); |
234 | 235 | ||
@@ -395,7 +396,12 @@ void ath_ani_calibrate(unsigned long data) | |||
395 | bool shortcal = false; | 396 | bool shortcal = false; |
396 | bool aniflag = false; | 397 | bool aniflag = false; |
397 | unsigned int timestamp = jiffies_to_msecs(jiffies); | 398 | unsigned int timestamp = jiffies_to_msecs(jiffies); |
398 | u32 cal_interval, short_cal_interval; | 399 | u32 cal_interval, short_cal_interval, long_cal_interval; |
400 | |||
401 | if (ah->caldata && ah->caldata->nfcal_interference) | ||
402 | long_cal_interval = ATH_LONG_CALINTERVAL_INT; | ||
403 | else | ||
404 | long_cal_interval = ATH_LONG_CALINTERVAL; | ||
399 | 405 | ||
400 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? | 406 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? |
401 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | 407 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; |
@@ -407,7 +413,7 @@ void ath_ani_calibrate(unsigned long data) | |||
407 | ath9k_ps_wakeup(sc); | 413 | ath9k_ps_wakeup(sc); |
408 | 414 | ||
409 | /* Long calibration runs independently of short calibration. */ | 415 | /* Long calibration runs independently of short calibration. */ |
410 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { | 416 | if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { |
411 | longcal = true; | 417 | longcal = true; |
412 | ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); | 418 | ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); |
413 | common->ani.longcal_timer = timestamp; | 419 | common->ani.longcal_timer = timestamp; |
@@ -1776,9 +1782,10 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1776 | key->hw_key_idx = ret; | 1782 | key->hw_key_idx = ret; |
1777 | /* push IV and Michael MIC generation to stack */ | 1783 | /* push IV and Michael MIC generation to stack */ |
1778 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1784 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1779 | if (key->alg == ALG_TKIP) | 1785 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1780 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1786 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1781 | if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP) | 1787 | if (sc->sc_ah->sw_mgmt_crypto && |
1788 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | ||
1782 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 1789 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; |
1783 | ret = 0; | 1790 | ret = 0; |
1784 | } | 1791 | } |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 6260faa658a2..45fe9cac7971 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -85,6 +85,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
85 | return "WMI_TGT_DETACH_CMDID"; | 85 | return "WMI_TGT_DETACH_CMDID"; |
86 | case WMI_TGT_TXQ_ENABLE_CMDID: | 86 | case WMI_TGT_TXQ_ENABLE_CMDID: |
87 | return "WMI_TGT_TXQ_ENABLE_CMDID"; | 87 | return "WMI_TGT_TXQ_ENABLE_CMDID"; |
88 | case WMI_AGGR_LIMIT_CMD: | ||
89 | return "WMI_AGGR_LIMIT_CMD"; | ||
88 | } | 90 | } |
89 | 91 | ||
90 | return "Bogus"; | 92 | return "Bogus"; |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 765db5faa2d3..a0bf857625df 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
@@ -71,6 +71,7 @@ enum wmi_cmd_id { | |||
71 | WMI_TX_AGGR_ENABLE_CMDID, | 71 | WMI_TX_AGGR_ENABLE_CMDID, |
72 | WMI_TGT_DETACH_CMDID, | 72 | WMI_TGT_DETACH_CMDID, |
73 | WMI_TGT_TXQ_ENABLE_CMDID, | 73 | WMI_TGT_TXQ_ENABLE_CMDID, |
74 | WMI_AGGR_LIMIT_CMD = 0x0026, | ||
74 | }; | 75 | }; |
75 | 76 | ||
76 | enum wmi_event_id { | 77 | enum wmi_event_id { |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4dda14e36227..457f07692ac7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1407,22 +1407,6 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
1407 | return htype; | 1407 | return htype; |
1408 | } | 1408 | } |
1409 | 1409 | ||
1410 | static int get_hw_crypto_keytype(struct sk_buff *skb) | ||
1411 | { | ||
1412 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1413 | |||
1414 | if (tx_info->control.hw_key) { | ||
1415 | if (tx_info->control.hw_key->alg == ALG_WEP) | ||
1416 | return ATH9K_KEY_TYPE_WEP; | ||
1417 | else if (tx_info->control.hw_key->alg == ALG_TKIP) | ||
1418 | return ATH9K_KEY_TYPE_TKIP; | ||
1419 | else if (tx_info->control.hw_key->alg == ALG_CCMP) | ||
1420 | return ATH9K_KEY_TYPE_AES; | ||
1421 | } | ||
1422 | |||
1423 | return ATH9K_KEY_TYPE_CLEAR; | ||
1424 | } | ||
1425 | |||
1426 | static void assign_aggr_tid_seqno(struct sk_buff *skb, | 1410 | static void assign_aggr_tid_seqno(struct sk_buff *skb, |
1427 | struct ath_buf *bf) | 1411 | struct ath_buf *bf) |
1428 | { | 1412 | { |
@@ -1661,7 +1645,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1661 | bf->bf_state.bfs_paprd_timestamp = jiffies; | 1645 | bf->bf_state.bfs_paprd_timestamp = jiffies; |
1662 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); | 1646 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); |
1663 | 1647 | ||
1664 | bf->bf_keytype = get_hw_crypto_keytype(skb); | 1648 | bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb); |
1665 | if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { | 1649 | if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { |
1666 | bf->bf_frmlen += tx_info->control.hw_key->icv_len; | 1650 | bf->bf_frmlen += tx_info->control.hw_key->icv_len; |
1667 | bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; | 1651 | bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; |
diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index 873bf526e11f..fd3a020682dc 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h | |||
@@ -36,6 +36,7 @@ | |||
36 | * @ATH_DBG_PS: power save processing | 36 | * @ATH_DBG_PS: power save processing |
37 | * @ATH_DBG_HWTIMER: hardware timer handling | 37 | * @ATH_DBG_HWTIMER: hardware timer handling |
38 | * @ATH_DBG_BTCOEX: bluetooth coexistance | 38 | * @ATH_DBG_BTCOEX: bluetooth coexistance |
39 | * @ATH_DBG_BSTUCK: stuck beacons | ||
39 | * @ATH_DBG_ANY: enable all debugging | 40 | * @ATH_DBG_ANY: enable all debugging |
40 | * | 41 | * |
41 | * The debug level is used to control the amount and type of debugging output | 42 | * The debug level is used to control the amount and type of debugging output |
@@ -60,6 +61,7 @@ enum ATH_DEBUG { | |||
60 | ATH_DBG_HWTIMER = 0x00001000, | 61 | ATH_DBG_HWTIMER = 0x00001000, |
61 | ATH_DBG_BTCOEX = 0x00002000, | 62 | ATH_DBG_BTCOEX = 0x00002000, |
62 | ATH_DBG_WMI = 0x00004000, | 63 | ATH_DBG_WMI = 0x00004000, |
64 | ATH_DBG_BSTUCK = 0x00008000, | ||
63 | ATH_DBG_ANY = 0xffffffff | 65 | ATH_DBG_ANY = 0xffffffff |
64 | }; | 66 | }; |
65 | 67 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 20631ae2ddd7..a1186525c70d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2280,6 +2280,7 @@ out: | |||
2280 | 2280 | ||
2281 | static int b43_upload_microcode(struct b43_wldev *dev) | 2281 | static int b43_upload_microcode(struct b43_wldev *dev) |
2282 | { | 2282 | { |
2283 | struct wiphy *wiphy = dev->wl->hw->wiphy; | ||
2283 | const size_t hdr_len = sizeof(struct b43_fw_header); | 2284 | const size_t hdr_len = sizeof(struct b43_fw_header); |
2284 | const __be32 *data; | 2285 | const __be32 *data; |
2285 | unsigned int i, len; | 2286 | unsigned int i, len; |
@@ -2405,6 +2406,10 @@ static int b43_upload_microcode(struct b43_wldev *dev) | |||
2405 | } | 2406 | } |
2406 | } | 2407 | } |
2407 | 2408 | ||
2409 | snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u", | ||
2410 | dev->fw.rev, dev->fw.patch); | ||
2411 | wiphy->hw_version = dev->dev->id.coreid; | ||
2412 | |||
2408 | if (b43_is_old_txhdr_format(dev)) { | 2413 | if (b43_is_old_txhdr_format(dev)) { |
2409 | /* We're over the deadline, but we keep support for old fw | 2414 | /* We're over the deadline, but we keep support for old fw |
2410 | * until it turns out to be in major conflict with something new. */ | 2415 | * until it turns out to be in major conflict with something new. */ |
@@ -3754,17 +3759,17 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3754 | } | 3759 | } |
3755 | 3760 | ||
3756 | err = -EINVAL; | 3761 | err = -EINVAL; |
3757 | switch (key->alg) { | 3762 | switch (key->cipher) { |
3758 | case ALG_WEP: | 3763 | case WLAN_CIPHER_SUITE_WEP40: |
3759 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 3764 | algorithm = B43_SEC_ALGO_WEP40; |
3760 | algorithm = B43_SEC_ALGO_WEP40; | 3765 | break; |
3761 | else | 3766 | case WLAN_CIPHER_SUITE_WEP104: |
3762 | algorithm = B43_SEC_ALGO_WEP104; | 3767 | algorithm = B43_SEC_ALGO_WEP104; |
3763 | break; | 3768 | break; |
3764 | case ALG_TKIP: | 3769 | case WLAN_CIPHER_SUITE_TKIP: |
3765 | algorithm = B43_SEC_ALGO_TKIP; | 3770 | algorithm = B43_SEC_ALGO_TKIP; |
3766 | break; | 3771 | break; |
3767 | case ALG_CCMP: | 3772 | case WLAN_CIPHER_SUITE_CCMP: |
3768 | algorithm = B43_SEC_ALGO_AES; | 3773 | algorithm = B43_SEC_ALGO_AES; |
3769 | break; | 3774 | break; |
3770 | default: | 3775 | default: |
@@ -4250,6 +4255,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
4250 | B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED); | 4255 | B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED); |
4251 | if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) | 4256 | if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) |
4252 | return; | 4257 | return; |
4258 | |||
4259 | /* Unregister HW RNG driver */ | ||
4260 | b43_rng_exit(dev->wl); | ||
4261 | |||
4253 | b43_set_status(dev, B43_STAT_UNINIT); | 4262 | b43_set_status(dev, B43_STAT_UNINIT); |
4254 | 4263 | ||
4255 | /* Stop the microcode PSM. */ | 4264 | /* Stop the microcode PSM. */ |
@@ -4379,6 +4388,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4379 | 4388 | ||
4380 | b43_set_status(dev, B43_STAT_INITIALIZED); | 4389 | b43_set_status(dev, B43_STAT_INITIALIZED); |
4381 | 4390 | ||
4391 | /* Register HW RNG driver */ | ||
4392 | b43_rng_init(dev->wl); | ||
4393 | |||
4382 | out: | 4394 | out: |
4383 | return err; | 4395 | return err; |
4384 | 4396 | ||
@@ -4984,7 +4996,6 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) | |||
4984 | if (err) | 4996 | if (err) |
4985 | goto err_one_core_detach; | 4997 | goto err_one_core_detach; |
4986 | b43_leds_register(wl->current_dev); | 4998 | b43_leds_register(wl->current_dev); |
4987 | b43_rng_init(wl); | ||
4988 | } | 4999 | } |
4989 | 5000 | ||
4990 | out: | 5001 | out: |
@@ -5020,7 +5031,6 @@ static void b43_remove(struct ssb_device *dev) | |||
5020 | b43_one_core_detach(dev); | 5031 | b43_one_core_detach(dev); |
5021 | 5032 | ||
5022 | if (list_empty(&wl->devlist)) { | 5033 | if (list_empty(&wl->devlist)) { |
5023 | b43_rng_exit(wl); | ||
5024 | b43_leds_unregister(wl); | 5034 | b43_leds_unregister(wl); |
5025 | /* Last core on the chip unregistered. | 5035 | /* Last core on the chip unregistered. |
5026 | * We can destroy common struct b43_wl. | 5036 | * We can destroy common struct b43_wl. |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e288c559481d..d116229c3347 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -893,7 +893,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) | |||
893 | } | 893 | } |
894 | 894 | ||
895 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ | 895 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ |
896 | static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) | 896 | static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) |
897 | { | 897 | { |
898 | struct b43_phy_n *nphy = dev->phy.n; | 898 | struct b43_phy_n *nphy = dev->phy.n; |
899 | u8 i, j; | 899 | u8 i, j; |
@@ -1094,11 +1094,12 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) | |||
1094 | b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); | 1094 | b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); |
1095 | b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); | 1095 | b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); |
1096 | 1096 | ||
1097 | b43_nphy_gain_crtl_workarounds(dev); | 1097 | b43_nphy_gain_ctrl_workarounds(dev); |
1098 | 1098 | ||
1099 | if (dev->phy.rev < 2) { | 1099 | if (dev->phy.rev < 2) { |
1100 | if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) | 1100 | if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) |
1101 | ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/ | 1101 | b43_hf_write(dev, b43_hf_read(dev) | |
1102 | B43_HF_MLADVW); | ||
1102 | } else if (dev->phy.rev == 2) { | 1103 | } else if (dev->phy.rev == 2) { |
1103 | b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); | 1104 | b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); |
1104 | b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); | 1105 | b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); |
@@ -3073,6 +3074,55 @@ static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, | |||
3073 | return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); | 3074 | return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); |
3074 | } | 3075 | } |
3075 | 3076 | ||
3077 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ | ||
3078 | static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on) | ||
3079 | { | ||
3080 | u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); | ||
3081 | if (on) | ||
3082 | tmslow |= SSB_TMSLOW_PHYCLK; | ||
3083 | else | ||
3084 | tmslow &= ~SSB_TMSLOW_PHYCLK; | ||
3085 | ssb_write32(dev->dev, SSB_TMSLOW, tmslow); | ||
3086 | } | ||
3087 | |||
3088 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ | ||
3089 | static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) | ||
3090 | { | ||
3091 | struct b43_phy *phy = &dev->phy; | ||
3092 | struct b43_phy_n *nphy = phy->n; | ||
3093 | u16 buf[16]; | ||
3094 | |||
3095 | if (0 /* FIXME clk */) | ||
3096 | return; | ||
3097 | |||
3098 | b43_mac_suspend(dev); | ||
3099 | |||
3100 | if (nphy->hang_avoid) | ||
3101 | b43_nphy_stay_in_carrier_search(dev, true); | ||
3102 | |||
3103 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, | ||
3104 | (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT); | ||
3105 | |||
3106 | if (mask & 0x3 != 0x3) { | ||
3107 | b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1); | ||
3108 | if (dev->phy.rev >= 3) { | ||
3109 | /* TODO */ | ||
3110 | } | ||
3111 | } else { | ||
3112 | b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E); | ||
3113 | if (dev->phy.rev >= 3) { | ||
3114 | /* TODO */ | ||
3115 | } | ||
3116 | } | ||
3117 | |||
3118 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | ||
3119 | |||
3120 | if (nphy->hang_avoid) | ||
3121 | b43_nphy_stay_in_carrier_search(dev, false); | ||
3122 | |||
3123 | b43_mac_enable(dev); | ||
3124 | } | ||
3125 | |||
3076 | /* | 3126 | /* |
3077 | * Init N-PHY | 3127 | * Init N-PHY |
3078 | * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N | 3128 | * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N |
@@ -3173,7 +3223,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3173 | b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); | 3223 | b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); |
3174 | b43_nphy_bmac_clock_fgc(dev, 0); | 3224 | b43_nphy_bmac_clock_fgc(dev, 0); |
3175 | 3225 | ||
3176 | /* TODO N PHY MAC PHY Clock Set with argument 1 */ | 3226 | b43_nphy_mac_phy_clock_set(dev, true); |
3177 | 3227 | ||
3178 | b43_nphy_pa_override(dev, false); | 3228 | b43_nphy_pa_override(dev, false); |
3179 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); | 3229 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); |
@@ -3199,7 +3249,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3199 | } | 3249 | } |
3200 | 3250 | ||
3201 | if (nphy->phyrxchain != 3) | 3251 | if (nphy->phyrxchain != 3) |
3202 | ;/* TODO N PHY RX Core Set State with phyrxchain as argument */ | 3252 | b43_nphy_set_rx_core_state(dev, nphy->phyrxchain); |
3203 | if (nphy->mphase_cal_phase_id > 0) | 3253 | if (nphy->mphase_cal_phase_id > 0) |
3204 | ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ | 3254 | ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ |
3205 | 3255 | ||
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1713f5f7a58b..67f18ecdb3bf 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -1623,6 +1623,7 @@ error: | |||
1623 | 1623 | ||
1624 | static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) | 1624 | static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) |
1625 | { | 1625 | { |
1626 | struct wiphy *wiphy = dev->wl->hw->wiphy; | ||
1626 | const size_t hdr_len = sizeof(struct b43legacy_fw_header); | 1627 | const size_t hdr_len = sizeof(struct b43legacy_fw_header); |
1627 | const __be32 *data; | 1628 | const __be32 *data; |
1628 | unsigned int i; | 1629 | unsigned int i; |
@@ -1732,6 +1733,10 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) | |||
1732 | dev->fw.rev = fwrev; | 1733 | dev->fw.rev = fwrev; |
1733 | dev->fw.patch = fwpatch; | 1734 | dev->fw.patch = fwpatch; |
1734 | 1735 | ||
1736 | snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u", | ||
1737 | dev->fw.rev, dev->fw.patch); | ||
1738 | wiphy->hw_version = dev->dev->id.coreid; | ||
1739 | |||
1735 | return 0; | 1740 | return 0; |
1736 | 1741 | ||
1737 | error: | 1742 | error: |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index a85e43a8d758..6038633ef361 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -1696,7 +1696,7 @@ static int prism2_request_scan(struct net_device *dev) | |||
1696 | hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, | 1696 | hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, |
1697 | HFA384X_ROAMING_FIRMWARE); | 1697 | HFA384X_ROAMING_FIRMWARE); |
1698 | 1698 | ||
1699 | return 0; | 1699 | return ret; |
1700 | } | 1700 | } |
1701 | 1701 | ||
1702 | #else /* !PRISM2_NO_STATION_MODES */ | 1702 | #else /* !PRISM2_NO_STATION_MODES */ |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 2ba57340083c..61915f371416 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -3056,9 +3056,9 @@ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv) | |||
3056 | 3056 | ||
3057 | packet = list_entry(element, struct ipw2100_tx_packet, list); | 3057 | packet = list_entry(element, struct ipw2100_tx_packet, list); |
3058 | 3058 | ||
3059 | IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n", | 3059 | IPW_DEBUG_TX("using TBD at virt=%p, phys=%04X\n", |
3060 | &txq->drv[txq->next], | 3060 | &txq->drv[txq->next], |
3061 | (void *)(txq->nic + txq->next * | 3061 | (u32) (txq->nic + txq->next * |
3062 | sizeof(struct ipw2100_bd))); | 3062 | sizeof(struct ipw2100_bd))); |
3063 | 3063 | ||
3064 | packet->index = txq->next; | 3064 | packet->index = txq->next; |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index a51e4da1bdfc..b82364258dc5 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -3,6 +3,9 @@ config IWLWIFI | |||
3 | depends on PCI && MAC80211 | 3 | depends on PCI && MAC80211 |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | 5 | ||
6 | menu "Debugging Options" | ||
7 | depends on IWLWIFI | ||
8 | |||
6 | config IWLWIFI_DEBUG | 9 | config IWLWIFI_DEBUG |
7 | bool "Enable full debugging output in iwlagn and iwl3945 drivers" | 10 | bool "Enable full debugging output in iwlagn and iwl3945 drivers" |
8 | depends on IWLWIFI | 11 | depends on IWLWIFI |
@@ -36,6 +39,12 @@ config IWLWIFI_DEBUGFS | |||
36 | is a low-impact option that allows getting insight into the | 39 | is a low-impact option that allows getting insight into the |
37 | driver's state at runtime. | 40 | driver's state at runtime. |
38 | 41 | ||
42 | config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | ||
43 | bool "Experimental uCode support" | ||
44 | depends on IWLWIFI && IWLWIFI_DEBUG | ||
45 | ---help--- | ||
46 | Enable use of experimental ucode for testing and debugging. | ||
47 | |||
39 | config IWLWIFI_DEVICE_TRACING | 48 | config IWLWIFI_DEVICE_TRACING |
40 | bool "iwlwifi device access tracing" | 49 | bool "iwlwifi device access tracing" |
41 | depends on IWLWIFI | 50 | depends on IWLWIFI |
@@ -53,6 +62,7 @@ config IWLWIFI_DEVICE_TRACING | |||
53 | 62 | ||
54 | If unsure, say Y so we can help you better when problems | 63 | If unsure, say Y so we can help you better when problems |
55 | occur. | 64 | occur. |
65 | endmenu | ||
56 | 66 | ||
57 | config IWLAGN | 67 | config IWLAGN |
58 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" | 68 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 728bb858ba97..493163925a45 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o | |||
12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o | 12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o |
13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o | 13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o |
14 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o | 14 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o |
15 | iwlagn-objs += iwl-agn-tt.o | ||
15 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o | 16 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o |
16 | 17 | ||
17 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 18 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 0b779a41a142..3bf5a30828be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -229,6 +229,11 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
229 | .check_ack_health = iwl_good_ack_health, | 229 | .check_ack_health = iwl_good_ack_health, |
230 | .txfifo_flush = iwlagn_txfifo_flush, | 230 | .txfifo_flush = iwlagn_txfifo_flush, |
231 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | 231 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, |
232 | .tt_ops = { | ||
233 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
234 | .tt_power_mode = iwl_tt_current_power_mode, | ||
235 | .ct_kill_check = iwl_check_for_ct_kill, | ||
236 | } | ||
232 | }; | 237 | }; |
233 | 238 | ||
234 | static const struct iwl_ops iwl1000_ops = { | 239 | static const struct iwl_ops iwl1000_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d92b72909233..f0a47f42d4b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -1470,7 +1470,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, | |||
1470 | 1470 | ||
1471 | cmd.band = band; | 1471 | cmd.band = band; |
1472 | cmd.expect_beacon = 0; | 1472 | cmd.expect_beacon = 0; |
1473 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); | 1473 | ch = ch_switch->channel->hw_value; |
1474 | cmd.channel = cpu_to_le16(ch); | 1474 | cmd.channel = cpu_to_le16(ch); |
1475 | cmd.rxon_flags = priv->staging_rxon.flags; | 1475 | cmd.rxon_flags = priv->staging_rxon.flags; |
1476 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | 1476 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 48bdcd8d2e94..013f3dae69f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -291,7 +291,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
291 | }; | 291 | }; |
292 | 292 | ||
293 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 293 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
294 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); | 294 | ch = ch_switch->channel->hw_value; |
295 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | 295 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", |
296 | priv->active_rxon.channel, ch); | 296 | priv->active_rxon.channel, ch); |
297 | cmd.channel = cpu_to_le16(ch); | 297 | cmd.channel = cpu_to_le16(ch); |
@@ -405,6 +405,11 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
405 | .check_ack_health = iwl_good_ack_health, | 405 | .check_ack_health = iwl_good_ack_health, |
406 | .txfifo_flush = iwlagn_txfifo_flush, | 406 | .txfifo_flush = iwlagn_txfifo_flush, |
407 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | 407 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, |
408 | .tt_ops = { | ||
409 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
410 | .tt_power_mode = iwl_tt_current_power_mode, | ||
411 | .ct_kill_check = iwl_check_for_ct_kill, | ||
412 | } | ||
408 | }; | 413 | }; |
409 | 414 | ||
410 | static struct iwl_lib_ops iwl5150_lib = { | 415 | static struct iwl_lib_ops iwl5150_lib = { |
@@ -470,6 +475,11 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
470 | .check_ack_health = iwl_good_ack_health, | 475 | .check_ack_health = iwl_good_ack_health, |
471 | .txfifo_flush = iwlagn_txfifo_flush, | 476 | .txfifo_flush = iwlagn_txfifo_flush, |
472 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | 477 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, |
478 | .tt_ops = { | ||
479 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
480 | .tt_power_mode = iwl_tt_current_power_mode, | ||
481 | .ct_kill_check = iwl_check_for_ct_kill, | ||
482 | } | ||
473 | }; | 483 | }; |
474 | 484 | ||
475 | static const struct iwl_ops iwl5000_ops = { | 485 | static const struct iwl_ops iwl5000_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index cee06b968de8..9e390f698641 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -214,7 +214,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
214 | }; | 214 | }; |
215 | 215 | ||
216 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 216 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
217 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); | 217 | ch = ch_switch->channel->hw_value; |
218 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", | 218 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", |
219 | priv->active_rxon.channel, ch); | 219 | priv->active_rxon.channel, ch); |
220 | cmd.channel = cpu_to_le16(ch); | 220 | cmd.channel = cpu_to_le16(ch); |
@@ -330,6 +330,11 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
330 | .check_ack_health = iwl_good_ack_health, | 330 | .check_ack_health = iwl_good_ack_health, |
331 | .txfifo_flush = iwlagn_txfifo_flush, | 331 | .txfifo_flush = iwlagn_txfifo_flush, |
332 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | 332 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, |
333 | .tt_ops = { | ||
334 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
335 | .tt_power_mode = iwl_tt_current_power_mode, | ||
336 | .ct_kill_check = iwl_check_for_ct_kill, | ||
337 | } | ||
333 | }; | 338 | }; |
334 | 339 | ||
335 | static const struct iwl_ops iwl6000_ops = { | 340 | static const struct iwl_ops iwl6000_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 75b901b3eb1e..84939763d178 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -235,13 +235,13 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
235 | /* data from PHY/DSP regarding signal strength, etc., | 235 | /* data from PHY/DSP regarding signal strength, etc., |
236 | * contents are always there, not configurable by host | 236 | * contents are always there, not configurable by host |
237 | */ | 237 | */ |
238 | struct iwl5000_non_cfg_phy *ncphy = | 238 | struct iwlagn_non_cfg_phy *ncphy = |
239 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | 239 | (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf; |
240 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | 240 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; |
241 | u8 agc; | 241 | u8 agc; |
242 | 242 | ||
243 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | 243 | val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]); |
244 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | 244 | agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS; |
245 | 245 | ||
246 | /* Find max rssi among 3 possible receivers. | 246 | /* Find max rssi among 3 possible receivers. |
247 | * These values are measured by the digital signal processor (DSP). | 247 | * These values are measured by the digital signal processor (DSP). |
@@ -249,11 +249,14 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
249 | * if the radio's automatic gain control (AGC) is working right. | 249 | * if the radio's automatic gain control (AGC) is working right. |
250 | * AGC value (see below) will provide the "interesting" info. | 250 | * AGC value (see below) will provide the "interesting" info. |
251 | */ | 251 | */ |
252 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | 252 | val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]); |
253 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | 253 | rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >> |
254 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | 254 | IWLAGN_OFDM_RSSI_A_BIT_POS; |
255 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | 255 | rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >> |
256 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | 256 | IWLAGN_OFDM_RSSI_B_BIT_POS; |
257 | val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]); | ||
258 | rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >> | ||
259 | IWLAGN_OFDM_RSSI_C_BIT_POS; | ||
257 | 260 | ||
258 | max_rssi = max_t(u32, rssi_a, rssi_b); | 261 | max_rssi = max_t(u32, rssi_a, rssi_b); |
259 | max_rssi = max_t(u32, max_rssi, rssi_c); | 262 | max_rssi = max_t(u32, max_rssi, rssi_c); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9dd9e64c2b0b..eedd71f5506b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -1098,7 +1098,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
1098 | if (chan->band != band) | 1098 | if (chan->band != band) |
1099 | continue; | 1099 | continue; |
1100 | 1100 | ||
1101 | channel = ieee80211_frequency_to_channel(chan->center_freq); | 1101 | channel = chan->hw_value; |
1102 | scan_ch->channel = cpu_to_le16(channel); | 1102 | scan_ch->channel = cpu_to_le16(channel); |
1103 | 1103 | ||
1104 | ch_info = iwl_get_channel_info(priv, band, channel); | 1104 | ch_info = iwl_get_channel_info(priv, band, channel); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 23e5c42e7d7e..a4563389bad0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -82,6 +82,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
82 | struct iwl_lq_sta *lq_sta); | 82 | struct iwl_lq_sta *lq_sta); |
83 | static void rs_fill_link_cmd(struct iwl_priv *priv, | 83 | static void rs_fill_link_cmd(struct iwl_priv *priv, |
84 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); | 84 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); |
85 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta); | ||
85 | 86 | ||
86 | 87 | ||
87 | #ifdef CONFIG_MAC80211_DEBUGFS | 88 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -502,6 +503,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
502 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); | 503 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); |
503 | u8 mcs; | 504 | u8 mcs; |
504 | 505 | ||
506 | memset(tbl, 0, sizeof(struct iwl_scale_tbl_info)); | ||
505 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | 507 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); |
506 | 508 | ||
507 | if (*rate_idx == IWL_RATE_INVALID) { | 509 | if (*rate_idx == IWL_RATE_INVALID) { |
@@ -848,7 +850,20 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
848 | other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 850 | other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
849 | } else { | 851 | } else { |
850 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); | 852 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); |
851 | return; | 853 | tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
854 | IWL_DEBUG_RATE(priv, "active- lq:%x, ant:%x, SGI:%d\n", | ||
855 | tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI); | ||
856 | tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); | ||
857 | IWL_DEBUG_RATE(priv, "search- lq:%x, ant:%x, SGI:%d\n", | ||
858 | tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI); | ||
859 | IWL_DEBUG_RATE(priv, "actual- lq:%x, ant:%x, SGI:%d\n", | ||
860 | tbl_type.lq_type, tbl_type.ant_type, tbl_type.is_SGI); | ||
861 | /* | ||
862 | * no matching table found, let's by-pass the data collection | ||
863 | * and continue to perform rate scale to find the rate table | ||
864 | */ | ||
865 | rs_stay_in_table(lq_sta); | ||
866 | goto done; | ||
852 | } | 867 | } |
853 | 868 | ||
854 | /* | 869 | /* |
@@ -909,7 +924,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
909 | } | 924 | } |
910 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ | 925 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ |
911 | lq_sta->last_rate_n_flags = tx_rate; | 926 | lq_sta->last_rate_n_flags = tx_rate; |
912 | 927 | done: | |
913 | /* See if there's a better rate or modulation mode to try. */ | 928 | /* See if there's a better rate or modulation mode to try. */ |
914 | if (sta && sta->supp_rates[sband->band]) | 929 | if (sta && sta->supp_rates[sband->band]) |
915 | rs_rate_scale_perform(priv, skb, sta, lq_sta); | 930 | rs_rate_scale_perform(priv, skb, sta, lq_sta); |
@@ -1265,7 +1280,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1265 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1280 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
1266 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1281 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1267 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1282 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1268 | u8 start_action = tbl->action; | 1283 | u8 start_action; |
1269 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1284 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1270 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1285 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1271 | int ret = 0; | 1286 | int ret = 0; |
@@ -1277,6 +1292,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1277 | else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && | 1292 | else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && |
1278 | tbl->action > IWL_LEGACY_SWITCH_SISO) | 1293 | tbl->action > IWL_LEGACY_SWITCH_SISO) |
1279 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1294 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
1295 | start_action = tbl->action; | ||
1280 | for (; ;) { | 1296 | for (; ;) { |
1281 | lq_sta->action_counter++; | 1297 | lq_sta->action_counter++; |
1282 | switch (tbl->action) { | 1298 | switch (tbl->action) { |
@@ -1403,7 +1419,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1403 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 1419 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
1404 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1420 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1405 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1421 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1406 | u8 start_action = tbl->action; | 1422 | u8 start_action; |
1407 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1423 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1408 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1424 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1409 | u8 update_search_tbl_counter = 0; | 1425 | u8 update_search_tbl_counter = 0; |
@@ -1414,6 +1430,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1414 | /* stay in SISO */ | 1430 | /* stay in SISO */ |
1415 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1431 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1416 | } | 1432 | } |
1433 | start_action = tbl->action; | ||
1417 | for (;;) { | 1434 | for (;;) { |
1418 | lq_sta->action_counter++; | 1435 | lq_sta->action_counter++; |
1419 | switch (tbl->action) { | 1436 | switch (tbl->action) { |
@@ -1541,7 +1558,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1541 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 1558 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
1542 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1559 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1543 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1560 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1544 | u8 start_action = tbl->action; | 1561 | u8 start_action; |
1545 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1562 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1546 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1563 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1547 | u8 update_search_tbl_counter = 0; | 1564 | u8 update_search_tbl_counter = 0; |
@@ -1553,6 +1570,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1553 | /* switch in SISO */ | 1570 | /* switch in SISO */ |
1554 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | 1571 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; |
1555 | } | 1572 | } |
1573 | start_action = tbl->action; | ||
1556 | for (;;) { | 1574 | for (;;) { |
1557 | lq_sta->action_counter++; | 1575 | lq_sta->action_counter++; |
1558 | switch (tbl->action) { | 1576 | switch (tbl->action) { |
@@ -1682,7 +1700,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1682 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 1700 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
1683 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1701 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1684 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1702 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1685 | u8 start_action = tbl->action; | 1703 | u8 start_action; |
1686 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1704 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1687 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1705 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1688 | int ret; | 1706 | int ret; |
@@ -1694,6 +1712,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1694 | /* switch in SISO */ | 1712 | /* switch in SISO */ |
1695 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | 1713 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; |
1696 | } | 1714 | } |
1715 | start_action = tbl->action; | ||
1697 | for (;;) { | 1716 | for (;;) { |
1698 | lq_sta->action_counter++; | 1717 | lq_sta->action_counter++; |
1699 | switch (tbl->action) { | 1718 | switch (tbl->action) { |
@@ -2594,7 +2613,6 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2594 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2613 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); |
2595 | 2614 | ||
2596 | /* Interpret new_rate (rate_n_flags) */ | 2615 | /* Interpret new_rate (rate_n_flags) */ |
2597 | memset(&tbl_type, 0, sizeof(tbl_type)); | ||
2598 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, | 2616 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, |
2599 | &tbl_type, &rate_idx); | 2617 | &tbl_type, &rate_idx); |
2600 | 2618 | ||
@@ -2694,8 +2712,18 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2694 | 2712 | ||
2695 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | 2713 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
2696 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | 2714 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; |
2715 | |||
2697 | lq_cmd->agg_params.agg_time_limit = | 2716 | lq_cmd->agg_params.agg_time_limit = |
2698 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | 2717 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); |
2718 | /* | ||
2719 | * overwrite if needed, pass aggregation time limit | ||
2720 | * to uCode in uSec | ||
2721 | */ | ||
2722 | if (priv && priv->cfg->agg_time_limit && | ||
2723 | priv->cfg->agg_time_limit >= LINK_QUAL_AGG_TIME_LIMIT_MIN && | ||
2724 | priv->cfg->agg_time_limit <= LINK_QUAL_AGG_TIME_LIMIT_MAX) | ||
2725 | lq_cmd->agg_params.agg_time_limit = | ||
2726 | cpu_to_le16(priv->cfg->agg_time_limit); | ||
2699 | } | 2727 | } |
2700 | 2728 | ||
2701 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 2729 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c new file mode 100644 index 000000000000..30298ea56a24 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c | |||
@@ -0,0 +1,696 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | #include <net/mac80211.h> | ||
36 | |||
37 | #include "iwl-eeprom.h" | ||
38 | #include "iwl-dev.h" | ||
39 | #include "iwl-core.h" | ||
40 | #include "iwl-io.h" | ||
41 | #include "iwl-commands.h" | ||
42 | #include "iwl-debug.h" | ||
43 | #include "iwl-agn-tt.h" | ||
44 | |||
45 | /* default Thermal Throttling transaction table | ||
46 | * Current state | Throttling Down | Throttling Up | ||
47 | *============================================================================= | ||
48 | * Condition Nxt State Condition Nxt State Condition Nxt State | ||
49 | *----------------------------------------------------------------------------- | ||
50 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A | ||
51 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 | ||
52 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 | ||
53 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | ||
54 | *============================================================================= | ||
55 | */ | ||
56 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { | ||
57 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, | ||
58 | {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, | ||
59 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
60 | }; | ||
61 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { | ||
62 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, | ||
63 | {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, | ||
64 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
65 | }; | ||
66 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { | ||
67 | {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, | ||
68 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, | ||
69 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
70 | }; | ||
71 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { | ||
72 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, | ||
73 | {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, | ||
74 | {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | ||
75 | }; | ||
76 | |||
77 | /* Advance Thermal Throttling default restriction table */ | ||
78 | static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { | ||
79 | {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, | ||
80 | {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, | ||
81 | {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, | ||
82 | {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } | ||
83 | }; | ||
84 | |||
85 | bool iwl_tt_is_low_power_state(struct iwl_priv *priv) | ||
86 | { | ||
87 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
88 | |||
89 | if (tt->state >= IWL_TI_1) | ||
90 | return true; | ||
91 | return false; | ||
92 | } | ||
93 | |||
94 | u8 iwl_tt_current_power_mode(struct iwl_priv *priv) | ||
95 | { | ||
96 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
97 | |||
98 | return tt->tt_power_mode; | ||
99 | } | ||
100 | |||
101 | bool iwl_ht_enabled(struct iwl_priv *priv) | ||
102 | { | ||
103 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
104 | struct iwl_tt_restriction *restriction; | ||
105 | |||
106 | if (!priv->thermal_throttle.advanced_tt) | ||
107 | return true; | ||
108 | restriction = tt->restriction + tt->state; | ||
109 | return restriction->is_ht; | ||
110 | } | ||
111 | |||
112 | static bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | ||
113 | { | ||
114 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | ||
115 | bool within_margin = false; | ||
116 | |||
117 | if (priv->cfg->temperature_kelvin) | ||
118 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
119 | |||
120 | if (!priv->thermal_throttle.advanced_tt) | ||
121 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
122 | CT_KILL_THRESHOLD_LEGACY) ? true : false; | ||
123 | else | ||
124 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
125 | CT_KILL_THRESHOLD) ? true : false; | ||
126 | return within_margin; | ||
127 | } | ||
128 | |||
129 | bool iwl_check_for_ct_kill(struct iwl_priv *priv) | ||
130 | { | ||
131 | bool is_ct_kill = false; | ||
132 | |||
133 | if (iwl_within_ct_kill_margin(priv)) { | ||
134 | iwl_tt_enter_ct_kill(priv); | ||
135 | is_ct_kill = true; | ||
136 | } | ||
137 | return is_ct_kill; | ||
138 | } | ||
139 | |||
140 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) | ||
141 | { | ||
142 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
143 | struct iwl_tt_restriction *restriction; | ||
144 | |||
145 | if (!priv->thermal_throttle.advanced_tt) | ||
146 | return IWL_ANT_OK_MULTI; | ||
147 | restriction = tt->restriction + tt->state; | ||
148 | return restriction->tx_stream; | ||
149 | } | ||
150 | |||
151 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) | ||
152 | { | ||
153 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
154 | struct iwl_tt_restriction *restriction; | ||
155 | |||
156 | if (!priv->thermal_throttle.advanced_tt) | ||
157 | return IWL_ANT_OK_MULTI; | ||
158 | restriction = tt->restriction + tt->state; | ||
159 | return restriction->rx_stream; | ||
160 | } | ||
161 | |||
162 | #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ | ||
163 | #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ | ||
164 | |||
165 | /* | ||
166 | * toggle the bit to wake up uCode and check the temperature | ||
167 | * if the temperature is below CT, uCode will stay awake and send card | ||
168 | * state notification with CT_KILL bit clear to inform Thermal Throttling | ||
169 | * Management to change state. Otherwise, uCode will go back to sleep | ||
170 | * without doing anything, driver should continue the 5 seconds timer | ||
171 | * to wake up uCode for temperature check until temperature drop below CT | ||
172 | */ | ||
173 | static void iwl_tt_check_exit_ct_kill(unsigned long data) | ||
174 | { | ||
175 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
176 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
177 | unsigned long flags; | ||
178 | |||
179 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
180 | return; | ||
181 | |||
182 | if (tt->state == IWL_TI_CT_KILL) { | ||
183 | if (priv->thermal_throttle.ct_kill_toggle) { | ||
184 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
185 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
186 | priv->thermal_throttle.ct_kill_toggle = false; | ||
187 | } else { | ||
188 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
189 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
190 | priv->thermal_throttle.ct_kill_toggle = true; | ||
191 | } | ||
192 | iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
193 | spin_lock_irqsave(&priv->reg_lock, flags); | ||
194 | if (!iwl_grab_nic_access(priv)) | ||
195 | iwl_release_nic_access(priv); | ||
196 | spin_unlock_irqrestore(&priv->reg_lock, flags); | ||
197 | |||
198 | /* Reschedule the ct_kill timer to occur in | ||
199 | * CT_KILL_EXIT_DURATION seconds to ensure we get a | ||
200 | * thermal update */ | ||
201 | IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); | ||
202 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, | ||
203 | jiffies + CT_KILL_EXIT_DURATION * HZ); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | ||
208 | bool stop) | ||
209 | { | ||
210 | if (stop) { | ||
211 | IWL_DEBUG_POWER(priv, "Stop all queues\n"); | ||
212 | if (priv->mac80211_registered) | ||
213 | ieee80211_stop_queues(priv->hw); | ||
214 | IWL_DEBUG_POWER(priv, | ||
215 | "Schedule 5 seconds CT_KILL Timer\n"); | ||
216 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, | ||
217 | jiffies + CT_KILL_EXIT_DURATION * HZ); | ||
218 | } else { | ||
219 | IWL_DEBUG_POWER(priv, "Wake all queues\n"); | ||
220 | if (priv->mac80211_registered) | ||
221 | ieee80211_wake_queues(priv->hw); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static void iwl_tt_ready_for_ct_kill(unsigned long data) | ||
226 | { | ||
227 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
228 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
229 | |||
230 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
231 | return; | ||
232 | |||
233 | /* temperature timer expired, ready to go into CT_KILL state */ | ||
234 | if (tt->state != IWL_TI_CT_KILL) { | ||
235 | IWL_DEBUG_POWER(priv, "entering CT_KILL state when " | ||
236 | "temperature timer expired\n"); | ||
237 | tt->state = IWL_TI_CT_KILL; | ||
238 | set_bit(STATUS_CT_KILL, &priv->status); | ||
239 | iwl_perform_ct_kill_task(priv, true); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) | ||
244 | { | ||
245 | IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); | ||
246 | /* make request to retrieve statistics information */ | ||
247 | iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
248 | /* Reschedule the ct_kill wait timer */ | ||
249 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, | ||
250 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); | ||
251 | } | ||
252 | |||
253 | #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) | ||
254 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) | ||
255 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) | ||
256 | |||
257 | /* | ||
258 | * Legacy thermal throttling | ||
259 | * 1) Avoid NIC destruction due to high temperatures | ||
260 | * Chip will identify dangerously high temperatures that can | ||
261 | * harm the device and will power down | ||
262 | * 2) Avoid the NIC power down due to high temperature | ||
263 | * Throttle early enough to lower the power consumption before | ||
264 | * drastic steps are needed | ||
265 | */ | ||
266 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | ||
267 | { | ||
268 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
269 | enum iwl_tt_state old_state; | ||
270 | |||
271 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
272 | if ((tt->tt_previous_temp) && | ||
273 | (temp > tt->tt_previous_temp) && | ||
274 | ((temp - tt->tt_previous_temp) > | ||
275 | IWL_TT_INCREASE_MARGIN)) { | ||
276 | IWL_DEBUG_POWER(priv, | ||
277 | "Temperature increase %d degree Celsius\n", | ||
278 | (temp - tt->tt_previous_temp)); | ||
279 | } | ||
280 | #endif | ||
281 | old_state = tt->state; | ||
282 | /* in Celsius */ | ||
283 | if (temp >= IWL_MINIMAL_POWER_THRESHOLD) | ||
284 | tt->state = IWL_TI_CT_KILL; | ||
285 | else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) | ||
286 | tt->state = IWL_TI_2; | ||
287 | else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) | ||
288 | tt->state = IWL_TI_1; | ||
289 | else | ||
290 | tt->state = IWL_TI_0; | ||
291 | |||
292 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
293 | tt->tt_previous_temp = temp; | ||
294 | #endif | ||
295 | /* stop ct_kill_waiting_tm timer */ | ||
296 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
297 | if (tt->state != old_state) { | ||
298 | switch (tt->state) { | ||
299 | case IWL_TI_0: | ||
300 | /* | ||
301 | * When the system is ready to go back to IWL_TI_0 | ||
302 | * we only have to call iwl_power_update_mode() to | ||
303 | * do so. | ||
304 | */ | ||
305 | break; | ||
306 | case IWL_TI_1: | ||
307 | tt->tt_power_mode = IWL_POWER_INDEX_3; | ||
308 | break; | ||
309 | case IWL_TI_2: | ||
310 | tt->tt_power_mode = IWL_POWER_INDEX_4; | ||
311 | break; | ||
312 | default: | ||
313 | tt->tt_power_mode = IWL_POWER_INDEX_5; | ||
314 | break; | ||
315 | } | ||
316 | mutex_lock(&priv->mutex); | ||
317 | if (old_state == IWL_TI_CT_KILL) | ||
318 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
319 | if (tt->state != IWL_TI_CT_KILL && | ||
320 | iwl_power_update_mode(priv, true)) { | ||
321 | /* TT state not updated | ||
322 | * try again during next temperature read | ||
323 | */ | ||
324 | if (old_state == IWL_TI_CT_KILL) | ||
325 | set_bit(STATUS_CT_KILL, &priv->status); | ||
326 | tt->state = old_state; | ||
327 | IWL_ERR(priv, "Cannot update power mode, " | ||
328 | "TT state not updated\n"); | ||
329 | } else { | ||
330 | if (tt->state == IWL_TI_CT_KILL) { | ||
331 | if (force) { | ||
332 | set_bit(STATUS_CT_KILL, &priv->status); | ||
333 | iwl_perform_ct_kill_task(priv, true); | ||
334 | } else { | ||
335 | iwl_prepare_ct_kill_task(priv); | ||
336 | tt->state = old_state; | ||
337 | } | ||
338 | } else if (old_state == IWL_TI_CT_KILL && | ||
339 | tt->state != IWL_TI_CT_KILL) | ||
340 | iwl_perform_ct_kill_task(priv, false); | ||
341 | IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", | ||
342 | tt->state); | ||
343 | IWL_DEBUG_POWER(priv, "Power Index change to %u\n", | ||
344 | tt->tt_power_mode); | ||
345 | } | ||
346 | mutex_unlock(&priv->mutex); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Advance thermal throttling | ||
352 | * 1) Avoid NIC destruction due to high temperatures | ||
353 | * Chip will identify dangerously high temperatures that can | ||
354 | * harm the device and will power down | ||
355 | * 2) Avoid the NIC power down due to high temperature | ||
356 | * Throttle early enough to lower the power consumption before | ||
357 | * drastic steps are needed | ||
358 | * Actions include relaxing the power down sleep thresholds and | ||
359 | * decreasing the number of TX streams | ||
360 | * 3) Avoid throughput performance impact as much as possible | ||
361 | * | ||
362 | *============================================================================= | ||
363 | * Condition Nxt State Condition Nxt State Condition Nxt State | ||
364 | *----------------------------------------------------------------------------- | ||
365 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A | ||
366 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 | ||
367 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 | ||
368 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | ||
369 | *============================================================================= | ||
370 | */ | ||
371 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | ||
372 | { | ||
373 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
374 | int i; | ||
375 | bool changed = false; | ||
376 | enum iwl_tt_state old_state; | ||
377 | struct iwl_tt_trans *transaction; | ||
378 | |||
379 | old_state = tt->state; | ||
380 | for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { | ||
381 | /* based on the current TT state, | ||
382 | * find the curresponding transaction table | ||
383 | * each table has (IWL_TI_STATE_MAX - 1) entries | ||
384 | * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) | ||
385 | * will advance to the correct table. | ||
386 | * then based on the current temperature | ||
387 | * find the next state need to transaction to | ||
388 | * go through all the possible (IWL_TI_STATE_MAX - 1) entries | ||
389 | * in the current table to see if transaction is needed | ||
390 | */ | ||
391 | transaction = tt->transaction + | ||
392 | ((old_state * (IWL_TI_STATE_MAX - 1)) + i); | ||
393 | if (temp >= transaction->tt_low && | ||
394 | temp <= transaction->tt_high) { | ||
395 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
396 | if ((tt->tt_previous_temp) && | ||
397 | (temp > tt->tt_previous_temp) && | ||
398 | ((temp - tt->tt_previous_temp) > | ||
399 | IWL_TT_INCREASE_MARGIN)) { | ||
400 | IWL_DEBUG_POWER(priv, | ||
401 | "Temperature increase %d " | ||
402 | "degree Celsius\n", | ||
403 | (temp - tt->tt_previous_temp)); | ||
404 | } | ||
405 | tt->tt_previous_temp = temp; | ||
406 | #endif | ||
407 | if (old_state != | ||
408 | transaction->next_state) { | ||
409 | changed = true; | ||
410 | tt->state = | ||
411 | transaction->next_state; | ||
412 | } | ||
413 | break; | ||
414 | } | ||
415 | } | ||
416 | /* stop ct_kill_waiting_tm timer */ | ||
417 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
418 | if (changed) { | ||
419 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | ||
420 | |||
421 | if (tt->state >= IWL_TI_1) { | ||
422 | /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ | ||
423 | tt->tt_power_mode = IWL_POWER_INDEX_5; | ||
424 | if (!iwl_ht_enabled(priv)) | ||
425 | /* disable HT */ | ||
426 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
427 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | ||
428 | RXON_FLG_HT40_PROT_MSK | | ||
429 | RXON_FLG_HT_PROT_MSK); | ||
430 | else { | ||
431 | /* check HT capability and set | ||
432 | * according to the system HT capability | ||
433 | * in case get disabled before */ | ||
434 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
435 | } | ||
436 | |||
437 | } else { | ||
438 | /* | ||
439 | * restore system power setting -- it will be | ||
440 | * recalculated automatically. | ||
441 | */ | ||
442 | |||
443 | /* check HT capability and set | ||
444 | * according to the system HT capability | ||
445 | * in case get disabled before */ | ||
446 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
447 | } | ||
448 | mutex_lock(&priv->mutex); | ||
449 | if (old_state == IWL_TI_CT_KILL) | ||
450 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
451 | if (tt->state != IWL_TI_CT_KILL && | ||
452 | iwl_power_update_mode(priv, true)) { | ||
453 | /* TT state not updated | ||
454 | * try again during next temperature read | ||
455 | */ | ||
456 | IWL_ERR(priv, "Cannot update power mode, " | ||
457 | "TT state not updated\n"); | ||
458 | if (old_state == IWL_TI_CT_KILL) | ||
459 | set_bit(STATUS_CT_KILL, &priv->status); | ||
460 | tt->state = old_state; | ||
461 | } else { | ||
462 | IWL_DEBUG_POWER(priv, | ||
463 | "Thermal Throttling to new state: %u\n", | ||
464 | tt->state); | ||
465 | if (old_state != IWL_TI_CT_KILL && | ||
466 | tt->state == IWL_TI_CT_KILL) { | ||
467 | if (force) { | ||
468 | IWL_DEBUG_POWER(priv, | ||
469 | "Enter IWL_TI_CT_KILL\n"); | ||
470 | set_bit(STATUS_CT_KILL, &priv->status); | ||
471 | iwl_perform_ct_kill_task(priv, true); | ||
472 | } else { | ||
473 | iwl_prepare_ct_kill_task(priv); | ||
474 | tt->state = old_state; | ||
475 | } | ||
476 | } else if (old_state == IWL_TI_CT_KILL && | ||
477 | tt->state != IWL_TI_CT_KILL) { | ||
478 | IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); | ||
479 | iwl_perform_ct_kill_task(priv, false); | ||
480 | } | ||
481 | } | ||
482 | mutex_unlock(&priv->mutex); | ||
483 | } | ||
484 | } | ||
485 | |||
486 | /* Card State Notification indicated reach critical temperature | ||
487 | * if PSP not enable, no Thermal Throttling function will be performed | ||
488 | * just set the GP1 bit to acknowledge the event | ||
489 | * otherwise, go into IWL_TI_CT_KILL state | ||
490 | * since Card State Notification will not provide any temperature reading | ||
491 | * for Legacy mode | ||
492 | * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() | ||
493 | * for advance mode | ||
494 | * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state | ||
495 | */ | ||
496 | static void iwl_bg_ct_enter(struct work_struct *work) | ||
497 | { | ||
498 | struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); | ||
499 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
500 | |||
501 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
502 | return; | ||
503 | |||
504 | if (!iwl_is_ready(priv)) | ||
505 | return; | ||
506 | |||
507 | if (tt->state != IWL_TI_CT_KILL) { | ||
508 | IWL_ERR(priv, "Device reached critical temperature " | ||
509 | "- ucode going to sleep!\n"); | ||
510 | if (!priv->thermal_throttle.advanced_tt) | ||
511 | iwl_legacy_tt_handler(priv, | ||
512 | IWL_MINIMAL_POWER_THRESHOLD, | ||
513 | true); | ||
514 | else | ||
515 | iwl_advance_tt_handler(priv, | ||
516 | CT_KILL_THRESHOLD + 1, true); | ||
517 | } | ||
518 | } | ||
519 | |||
520 | /* Card State Notification indicated out of critical temperature | ||
521 | * since Card State Notification will not provide any temperature reading | ||
522 | * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature | ||
523 | * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state | ||
524 | */ | ||
525 | static void iwl_bg_ct_exit(struct work_struct *work) | ||
526 | { | ||
527 | struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); | ||
528 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
529 | |||
530 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
531 | return; | ||
532 | |||
533 | if (!iwl_is_ready(priv)) | ||
534 | return; | ||
535 | |||
536 | /* stop ct_kill_exit_tm timer */ | ||
537 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | ||
538 | |||
539 | if (tt->state == IWL_TI_CT_KILL) { | ||
540 | IWL_ERR(priv, | ||
541 | "Device temperature below critical" | ||
542 | "- ucode awake!\n"); | ||
543 | /* | ||
544 | * exit from CT_KILL state | ||
545 | * reset the current temperature reading | ||
546 | */ | ||
547 | priv->temperature = 0; | ||
548 | if (!priv->thermal_throttle.advanced_tt) | ||
549 | iwl_legacy_tt_handler(priv, | ||
550 | IWL_REDUCED_PERFORMANCE_THRESHOLD_2, | ||
551 | true); | ||
552 | else | ||
553 | iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, | ||
554 | true); | ||
555 | } | ||
556 | } | ||
557 | |||
558 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv) | ||
559 | { | ||
560 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
561 | return; | ||
562 | |||
563 | IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); | ||
564 | queue_work(priv->workqueue, &priv->ct_enter); | ||
565 | } | ||
566 | EXPORT_SYMBOL(iwl_tt_enter_ct_kill); | ||
567 | |||
568 | void iwl_tt_exit_ct_kill(struct iwl_priv *priv) | ||
569 | { | ||
570 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
571 | return; | ||
572 | |||
573 | IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); | ||
574 | queue_work(priv->workqueue, &priv->ct_exit); | ||
575 | } | ||
576 | EXPORT_SYMBOL(iwl_tt_exit_ct_kill); | ||
577 | |||
578 | static void iwl_bg_tt_work(struct work_struct *work) | ||
579 | { | ||
580 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); | ||
581 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | ||
582 | |||
583 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
584 | return; | ||
585 | |||
586 | if (priv->cfg->temperature_kelvin) | ||
587 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
588 | |||
589 | if (!priv->thermal_throttle.advanced_tt) | ||
590 | iwl_legacy_tt_handler(priv, temp, false); | ||
591 | else | ||
592 | iwl_advance_tt_handler(priv, temp, false); | ||
593 | } | ||
594 | |||
595 | void iwl_tt_handler(struct iwl_priv *priv) | ||
596 | { | ||
597 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
598 | return; | ||
599 | |||
600 | IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); | ||
601 | queue_work(priv->workqueue, &priv->tt_work); | ||
602 | } | ||
603 | EXPORT_SYMBOL(iwl_tt_handler); | ||
604 | |||
605 | /* Thermal throttling initialization | ||
606 | * For advance thermal throttling: | ||
607 | * Initialize Thermal Index and temperature threshold table | ||
608 | * Initialize thermal throttling restriction table | ||
609 | */ | ||
610 | void iwl_tt_initialize(struct iwl_priv *priv) | ||
611 | { | ||
612 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
613 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); | ||
614 | struct iwl_tt_trans *transaction; | ||
615 | |||
616 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); | ||
617 | |||
618 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); | ||
619 | |||
620 | tt->state = IWL_TI_0; | ||
621 | init_timer(&priv->thermal_throttle.ct_kill_exit_tm); | ||
622 | priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; | ||
623 | priv->thermal_throttle.ct_kill_exit_tm.function = | ||
624 | iwl_tt_check_exit_ct_kill; | ||
625 | init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
626 | priv->thermal_throttle.ct_kill_waiting_tm.data = | ||
627 | (unsigned long)priv; | ||
628 | priv->thermal_throttle.ct_kill_waiting_tm.function = | ||
629 | iwl_tt_ready_for_ct_kill; | ||
630 | /* setup deferred ct kill work */ | ||
631 | INIT_WORK(&priv->tt_work, iwl_bg_tt_work); | ||
632 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | ||
633 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); | ||
634 | |||
635 | if (priv->cfg->adv_thermal_throttle) { | ||
636 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); | ||
637 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * | ||
638 | IWL_TI_STATE_MAX, GFP_KERNEL); | ||
639 | tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * | ||
640 | IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), | ||
641 | GFP_KERNEL); | ||
642 | if (!tt->restriction || !tt->transaction) { | ||
643 | IWL_ERR(priv, "Fallback to Legacy Throttling\n"); | ||
644 | priv->thermal_throttle.advanced_tt = false; | ||
645 | kfree(tt->restriction); | ||
646 | tt->restriction = NULL; | ||
647 | kfree(tt->transaction); | ||
648 | tt->transaction = NULL; | ||
649 | } else { | ||
650 | transaction = tt->transaction + | ||
651 | (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); | ||
652 | memcpy(transaction, &tt_range_0[0], size); | ||
653 | transaction = tt->transaction + | ||
654 | (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); | ||
655 | memcpy(transaction, &tt_range_1[0], size); | ||
656 | transaction = tt->transaction + | ||
657 | (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); | ||
658 | memcpy(transaction, &tt_range_2[0], size); | ||
659 | transaction = tt->transaction + | ||
660 | (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); | ||
661 | memcpy(transaction, &tt_range_3[0], size); | ||
662 | size = sizeof(struct iwl_tt_restriction) * | ||
663 | IWL_TI_STATE_MAX; | ||
664 | memcpy(tt->restriction, | ||
665 | &restriction_range[0], size); | ||
666 | priv->thermal_throttle.advanced_tt = true; | ||
667 | } | ||
668 | } else { | ||
669 | IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); | ||
670 | priv->thermal_throttle.advanced_tt = false; | ||
671 | } | ||
672 | } | ||
673 | EXPORT_SYMBOL(iwl_tt_initialize); | ||
674 | |||
675 | /* cleanup thermal throttling management related memory and timer */ | ||
676 | void iwl_tt_exit(struct iwl_priv *priv) | ||
677 | { | ||
678 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
679 | |||
680 | /* stop ct_kill_exit_tm timer if activated */ | ||
681 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | ||
682 | /* stop ct_kill_waiting_tm timer if activated */ | ||
683 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
684 | cancel_work_sync(&priv->tt_work); | ||
685 | cancel_work_sync(&priv->ct_enter); | ||
686 | cancel_work_sync(&priv->ct_exit); | ||
687 | |||
688 | if (priv->thermal_throttle.advanced_tt) { | ||
689 | /* free advance thermal throttling memory */ | ||
690 | kfree(tt->restriction); | ||
691 | tt->restriction = NULL; | ||
692 | kfree(tt->transaction); | ||
693 | tt->transaction = NULL; | ||
694 | } | ||
695 | } | ||
696 | EXPORT_SYMBOL(iwl_tt_exit); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h new file mode 100644 index 000000000000..d55060427cac --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | #ifndef __iwl_tt_setting_h__ | ||
29 | #define __iwl_tt_setting_h__ | ||
30 | |||
31 | #include "iwl-commands.h" | ||
32 | |||
33 | #define IWL_ABSOLUTE_ZERO 0 | ||
34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF | ||
35 | #define IWL_TT_INCREASE_MARGIN 5 | ||
36 | #define IWL_TT_CT_KILL_MARGIN 3 | ||
37 | |||
38 | enum iwl_antenna_ok { | ||
39 | IWL_ANT_OK_NONE, | ||
40 | IWL_ANT_OK_SINGLE, | ||
41 | IWL_ANT_OK_MULTI, | ||
42 | }; | ||
43 | |||
44 | /* Thermal Throttling State Machine states */ | ||
45 | enum iwl_tt_state { | ||
46 | IWL_TI_0, /* normal temperature, system power state */ | ||
47 | IWL_TI_1, /* high temperature detect, low power state */ | ||
48 | IWL_TI_2, /* higher temperature detected, lower power state */ | ||
49 | IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ | ||
50 | IWL_TI_STATE_MAX | ||
51 | }; | ||
52 | |||
53 | /** | ||
54 | * struct iwl_tt_restriction - Thermal Throttling restriction table | ||
55 | * @tx_stream: number of tx stream allowed | ||
56 | * @is_ht: ht enable/disable | ||
57 | * @rx_stream: number of rx stream allowed | ||
58 | * | ||
59 | * This table is used by advance thermal throttling management | ||
60 | * based on the current thermal throttling state, and determines | ||
61 | * the number of tx/rx streams and the status of HT operation. | ||
62 | */ | ||
63 | struct iwl_tt_restriction { | ||
64 | enum iwl_antenna_ok tx_stream; | ||
65 | enum iwl_antenna_ok rx_stream; | ||
66 | bool is_ht; | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * struct iwl_tt_trans - Thermal Throttling transaction table | ||
71 | * @next_state: next thermal throttling mode | ||
72 | * @tt_low: low temperature threshold to change state | ||
73 | * @tt_high: high temperature threshold to change state | ||
74 | * | ||
75 | * This is used by the advanced thermal throttling algorithm | ||
76 | * to determine the next thermal state to go based on the | ||
77 | * current temperature. | ||
78 | */ | ||
79 | struct iwl_tt_trans { | ||
80 | enum iwl_tt_state next_state; | ||
81 | u32 tt_low; | ||
82 | u32 tt_high; | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * struct iwl_tt_mgnt - Thermal Throttling Management structure | ||
87 | * @advanced_tt: advanced thermal throttle required | ||
88 | * @state: current Thermal Throttling state | ||
89 | * @tt_power_mode: Thermal Throttling power mode index | ||
90 | * being used to set power level when | ||
91 | * when thermal throttling state != IWL_TI_0 | ||
92 | * the tt_power_mode should set to different | ||
93 | * power mode based on the current tt state | ||
94 | * @tt_previous_temperature: last measured temperature | ||
95 | * @iwl_tt_restriction: ptr to restriction tbl, used by advance | ||
96 | * thermal throttling to determine how many tx/rx streams | ||
97 | * should be used in tt state; and can HT be enabled or not | ||
98 | * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling | ||
99 | * state transaction | ||
100 | * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature | ||
101 | * @ct_kill_exit_tm: timer to exit thermal kill | ||
102 | */ | ||
103 | struct iwl_tt_mgmt { | ||
104 | enum iwl_tt_state state; | ||
105 | bool advanced_tt; | ||
106 | u8 tt_power_mode; | ||
107 | bool ct_kill_toggle; | ||
108 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
109 | s32 tt_previous_temp; | ||
110 | #endif | ||
111 | struct iwl_tt_restriction *restriction; | ||
112 | struct iwl_tt_trans *transaction; | ||
113 | struct timer_list ct_kill_exit_tm; | ||
114 | struct timer_list ct_kill_waiting_tm; | ||
115 | }; | ||
116 | |||
117 | u8 iwl_tt_current_power_mode(struct iwl_priv *priv); | ||
118 | bool iwl_tt_is_low_power_state(struct iwl_priv *priv); | ||
119 | bool iwl_ht_enabled(struct iwl_priv *priv); | ||
120 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); | ||
121 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); | ||
122 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); | ||
123 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); | ||
124 | void iwl_tt_exit_ct_kill(struct iwl_priv *priv); | ||
125 | void iwl_tt_handler(struct iwl_priv *priv); | ||
126 | void iwl_tt_initialize(struct iwl_priv *priv); | ||
127 | void iwl_tt_exit(struct iwl_priv *priv); | ||
128 | |||
129 | #endif /* __iwl_tt_setting_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 69155aa448fb..3fc982e87921 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -470,8 +470,8 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | |||
470 | { | 470 | { |
471 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | 471 | struct ieee80211_key_conf *keyconf = info->control.hw_key; |
472 | 472 | ||
473 | switch (keyconf->alg) { | 473 | switch (keyconf->cipher) { |
474 | case ALG_CCMP: | 474 | case WLAN_CIPHER_SUITE_CCMP: |
475 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | 475 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; |
476 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | 476 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); |
477 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 477 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
@@ -479,20 +479,20 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | |||
479 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | 479 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); |
480 | break; | 480 | break; |
481 | 481 | ||
482 | case ALG_TKIP: | 482 | case WLAN_CIPHER_SUITE_TKIP: |
483 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | 483 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; |
484 | ieee80211_get_tkip_key(keyconf, skb_frag, | 484 | ieee80211_get_tkip_key(keyconf, skb_frag, |
485 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | 485 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); |
486 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | 486 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); |
487 | break; | 487 | break; |
488 | 488 | ||
489 | case ALG_WEP: | 489 | case WLAN_CIPHER_SUITE_WEP104: |
490 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
491 | /* fall through */ | ||
492 | case WLAN_CIPHER_SUITE_WEP40: | ||
490 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | 493 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | |
491 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | 494 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); |
492 | 495 | ||
493 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
494 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
495 | |||
496 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | 496 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); |
497 | 497 | ||
498 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | 498 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " |
@@ -500,7 +500,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | |||
500 | break; | 500 | break; |
501 | 501 | ||
502 | default: | 502 | default: |
503 | IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); | 503 | IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher); |
504 | break; | 504 | break; |
505 | } | 505 | } |
506 | } | 506 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 10d7b9b7f064..3ced9ea9c5fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci-aspm.h> | ||
36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
37 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
38 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
@@ -763,10 +764,10 @@ static void iwl_bg_ucode_trace(unsigned long data) | |||
763 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 764 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, |
764 | struct iwl_rx_mem_buffer *rxb) | 765 | struct iwl_rx_mem_buffer *rxb) |
765 | { | 766 | { |
766 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
767 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 767 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
768 | struct iwl4965_beacon_notif *beacon = | 768 | struct iwl4965_beacon_notif *beacon = |
769 | (struct iwl4965_beacon_notif *)pkt->u.raw; | 769 | (struct iwl4965_beacon_notif *)pkt->u.raw; |
770 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
770 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | 771 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); |
771 | 772 | ||
772 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " | 773 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " |
@@ -778,6 +779,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, | |||
778 | le32_to_cpu(beacon->low_tsf), rate); | 779 | le32_to_cpu(beacon->low_tsf), rate); |
779 | #endif | 780 | #endif |
780 | 781 | ||
782 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
783 | |||
781 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && | 784 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && |
782 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) | 785 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) |
783 | queue_work(priv->workqueue, &priv->beacon_update); | 786 | queue_work(priv->workqueue, &priv->beacon_update); |
@@ -1656,24 +1659,37 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | |||
1656 | static int iwl_mac_setup_register(struct iwl_priv *priv, | 1659 | static int iwl_mac_setup_register(struct iwl_priv *priv, |
1657 | struct iwlagn_ucode_capabilities *capa); | 1660 | struct iwlagn_ucode_capabilities *capa); |
1658 | 1661 | ||
1662 | #define UCODE_EXPERIMENTAL_INDEX 100 | ||
1663 | #define UCODE_EXPERIMENTAL_TAG "exp" | ||
1664 | |||
1659 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | 1665 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) |
1660 | { | 1666 | { |
1661 | const char *name_pre = priv->cfg->fw_name_pre; | 1667 | const char *name_pre = priv->cfg->fw_name_pre; |
1668 | char tag[8]; | ||
1662 | 1669 | ||
1663 | if (first) | 1670 | if (first) { |
1671 | #ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | ||
1672 | priv->fw_index = UCODE_EXPERIMENTAL_INDEX; | ||
1673 | strcpy(tag, UCODE_EXPERIMENTAL_TAG); | ||
1674 | } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) { | ||
1675 | #endif | ||
1664 | priv->fw_index = priv->cfg->ucode_api_max; | 1676 | priv->fw_index = priv->cfg->ucode_api_max; |
1665 | else | 1677 | sprintf(tag, "%d", priv->fw_index); |
1678 | } else { | ||
1666 | priv->fw_index--; | 1679 | priv->fw_index--; |
1680 | sprintf(tag, "%d", priv->fw_index); | ||
1681 | } | ||
1667 | 1682 | ||
1668 | if (priv->fw_index < priv->cfg->ucode_api_min) { | 1683 | if (priv->fw_index < priv->cfg->ucode_api_min) { |
1669 | IWL_ERR(priv, "no suitable firmware found!\n"); | 1684 | IWL_ERR(priv, "no suitable firmware found!\n"); |
1670 | return -ENOENT; | 1685 | return -ENOENT; |
1671 | } | 1686 | } |
1672 | 1687 | ||
1673 | sprintf(priv->firmware_name, "%s%d%s", | 1688 | sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); |
1674 | name_pre, priv->fw_index, ".ucode"); | ||
1675 | 1689 | ||
1676 | IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n", | 1690 | IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n", |
1691 | (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) | ||
1692 | ? "EXPERIMENTAL " : "", | ||
1677 | priv->firmware_name); | 1693 | priv->firmware_name); |
1678 | 1694 | ||
1679 | return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, | 1695 | return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, |
@@ -1968,8 +1984,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1968 | memset(&pieces, 0, sizeof(pieces)); | 1984 | memset(&pieces, 0, sizeof(pieces)); |
1969 | 1985 | ||
1970 | if (!ucode_raw) { | 1986 | if (!ucode_raw) { |
1971 | IWL_ERR(priv, "request for firmware file '%s' failed.\n", | 1987 | if (priv->fw_index <= priv->cfg->ucode_api_max) |
1972 | priv->firmware_name); | 1988 | IWL_ERR(priv, |
1989 | "request for firmware file '%s' failed.\n", | ||
1990 | priv->firmware_name); | ||
1973 | goto try_again; | 1991 | goto try_again; |
1974 | } | 1992 | } |
1975 | 1993 | ||
@@ -2016,7 +2034,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
2016 | api_max, api_ver); | 2034 | api_max, api_ver); |
2017 | 2035 | ||
2018 | if (build) | 2036 | if (build) |
2019 | sprintf(buildstr, " build %u", build); | 2037 | sprintf(buildstr, " build %u%s", build, |
2038 | (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) | ||
2039 | ? " (EXP)" : ""); | ||
2020 | else | 2040 | else |
2021 | buildstr[0] = '\0'; | 2041 | buildstr[0] = '\0'; |
2022 | 2042 | ||
@@ -2589,6 +2609,52 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2589 | return pos; | 2609 | return pos; |
2590 | } | 2610 | } |
2591 | 2611 | ||
2612 | static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | ||
2613 | { | ||
2614 | struct iwl_ct_kill_config cmd; | ||
2615 | struct iwl_ct_kill_throttling_config adv_cmd; | ||
2616 | unsigned long flags; | ||
2617 | int ret = 0; | ||
2618 | |||
2619 | spin_lock_irqsave(&priv->lock, flags); | ||
2620 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
2621 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
2622 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2623 | priv->thermal_throttle.ct_kill_toggle = false; | ||
2624 | |||
2625 | if (priv->cfg->support_ct_kill_exit) { | ||
2626 | adv_cmd.critical_temperature_enter = | ||
2627 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | ||
2628 | adv_cmd.critical_temperature_exit = | ||
2629 | cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); | ||
2630 | |||
2631 | ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, | ||
2632 | sizeof(adv_cmd), &adv_cmd); | ||
2633 | if (ret) | ||
2634 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | ||
2635 | else | ||
2636 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | ||
2637 | "succeeded, " | ||
2638 | "critical temperature enter is %d," | ||
2639 | "exit is %d\n", | ||
2640 | priv->hw_params.ct_kill_threshold, | ||
2641 | priv->hw_params.ct_kill_exit_threshold); | ||
2642 | } else { | ||
2643 | cmd.critical_temperature_R = | ||
2644 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | ||
2645 | |||
2646 | ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, | ||
2647 | sizeof(cmd), &cmd); | ||
2648 | if (ret) | ||
2649 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | ||
2650 | else | ||
2651 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | ||
2652 | "succeeded, " | ||
2653 | "critical temperature is %d\n", | ||
2654 | priv->hw_params.ct_kill_threshold); | ||
2655 | } | ||
2656 | } | ||
2657 | |||
2592 | /** | 2658 | /** |
2593 | * iwl_alive_start - called after REPLY_ALIVE notification received | 2659 | * iwl_alive_start - called after REPLY_ALIVE notification received |
2594 | * from protocol/runtime uCode (initialization uCode's | 2660 | * from protocol/runtime uCode (initialization uCode's |
@@ -3060,9 +3126,7 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3060 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 3126 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
3061 | iwlcore_commit_rxon(priv); | 3127 | iwlcore_commit_rxon(priv); |
3062 | 3128 | ||
3063 | iwl_setup_rxon_timing(priv, vif); | 3129 | ret = iwl_send_rxon_timing(priv, vif); |
3064 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
3065 | sizeof(priv->rxon_timing), &priv->rxon_timing); | ||
3066 | if (ret) | 3130 | if (ret) |
3067 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3131 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3068 | "Attempting to continue.\n"); | 3132 | "Attempting to continue.\n"); |
@@ -3298,9 +3362,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3298 | iwlcore_commit_rxon(priv); | 3362 | iwlcore_commit_rxon(priv); |
3299 | 3363 | ||
3300 | /* RXON Timing */ | 3364 | /* RXON Timing */ |
3301 | iwl_setup_rxon_timing(priv, vif); | 3365 | ret = iwl_send_rxon_timing(priv, vif); |
3302 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
3303 | sizeof(priv->rxon_timing), &priv->rxon_timing); | ||
3304 | if (ret) | 3366 | if (ret) |
3305 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3367 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3306 | "Attempting to continue.\n"); | 3368 | "Attempting to continue.\n"); |
@@ -3386,7 +3448,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3386 | * in 1X mode. | 3448 | * in 1X mode. |
3387 | * In legacy wep mode, we use another host command to the uCode. | 3449 | * In legacy wep mode, we use another host command to the uCode. |
3388 | */ | 3450 | */ |
3389 | if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) { | 3451 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
3452 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && | ||
3453 | !sta) { | ||
3390 | if (cmd == SET_KEY) | 3454 | if (cmd == SET_KEY) |
3391 | is_default_wep_key = !priv->key_mapping_key; | 3455 | is_default_wep_key = !priv->key_mapping_key; |
3392 | else | 3456 | else |
@@ -3581,6 +3645,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3581 | struct iwl_priv *priv = hw->priv; | 3645 | struct iwl_priv *priv = hw->priv; |
3582 | const struct iwl_channel_info *ch_info; | 3646 | const struct iwl_channel_info *ch_info; |
3583 | struct ieee80211_conf *conf = &hw->conf; | 3647 | struct ieee80211_conf *conf = &hw->conf; |
3648 | struct ieee80211_channel *channel = ch_switch->channel; | ||
3584 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 3649 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
3585 | u16 ch; | 3650 | u16 ch; |
3586 | unsigned long flags = 0; | 3651 | unsigned long flags = 0; |
@@ -3604,11 +3669,10 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3604 | mutex_lock(&priv->mutex); | 3669 | mutex_lock(&priv->mutex); |
3605 | if (priv->cfg->ops->lib->set_channel_switch) { | 3670 | if (priv->cfg->ops->lib->set_channel_switch) { |
3606 | 3671 | ||
3607 | ch = ieee80211_frequency_to_channel( | 3672 | ch = channel->hw_value; |
3608 | ch_switch->channel->center_freq); | ||
3609 | if (le16_to_cpu(priv->active_rxon.channel) != ch) { | 3673 | if (le16_to_cpu(priv->active_rxon.channel) != ch) { |
3610 | ch_info = iwl_get_channel_info(priv, | 3674 | ch_info = iwl_get_channel_info(priv, |
3611 | conf->channel->band, | 3675 | channel->band, |
3612 | ch); | 3676 | ch); |
3613 | if (!is_channel_valid(ch_info)) { | 3677 | if (!is_channel_valid(ch_info)) { |
3614 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); | 3678 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); |
@@ -3637,15 +3701,12 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3637 | } else | 3701 | } else |
3638 | ht_conf->is_40mhz = false; | 3702 | ht_conf->is_40mhz = false; |
3639 | 3703 | ||
3640 | /* if we are switching from ht to 2.4 clear flags | 3704 | if (le16_to_cpu(priv->staging_rxon.channel) != ch) |
3641 | * from any ht related info since 2.4 does not | ||
3642 | * support ht */ | ||
3643 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | ||
3644 | priv->staging_rxon.flags = 0; | 3705 | priv->staging_rxon.flags = 0; |
3645 | 3706 | ||
3646 | iwl_set_rxon_channel(priv, conf->channel); | 3707 | iwl_set_rxon_channel(priv, channel); |
3647 | iwl_set_rxon_ht(priv, ht_conf); | 3708 | iwl_set_rxon_ht(priv, ht_conf); |
3648 | iwl_set_flags_for_band(priv, conf->channel->band, | 3709 | iwl_set_flags_for_band(priv, channel->band, |
3649 | priv->vif); | 3710 | priv->vif); |
3650 | spin_unlock_irqrestore(&priv->lock, flags); | 3711 | spin_unlock_irqrestore(&priv->lock, flags); |
3651 | 3712 | ||
@@ -3923,8 +3984,35 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3923 | .sta_remove = iwl_mac_sta_remove, | 3984 | .sta_remove = iwl_mac_sta_remove, |
3924 | .channel_switch = iwl_mac_channel_switch, | 3985 | .channel_switch = iwl_mac_channel_switch, |
3925 | .flush = iwl_mac_flush, | 3986 | .flush = iwl_mac_flush, |
3987 | .tx_last_beacon = iwl_mac_tx_last_beacon, | ||
3926 | }; | 3988 | }; |
3927 | 3989 | ||
3990 | static void iwl_hw_detect(struct iwl_priv *priv) | ||
3991 | { | ||
3992 | priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); | ||
3993 | priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); | ||
3994 | pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); | ||
3995 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); | ||
3996 | } | ||
3997 | |||
3998 | static int iwl_set_hw_params(struct iwl_priv *priv) | ||
3999 | { | ||
4000 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | ||
4001 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
4002 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
4003 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); | ||
4004 | else | ||
4005 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); | ||
4006 | |||
4007 | priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; | ||
4008 | |||
4009 | if (priv->cfg->mod_params->disable_11n) | ||
4010 | priv->cfg->sku &= ~IWL_SKU_N; | ||
4011 | |||
4012 | /* Device-specific setup */ | ||
4013 | return priv->cfg->ops->lib->set_hw_params(priv); | ||
4014 | } | ||
4015 | |||
3928 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 4016 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
3929 | { | 4017 | { |
3930 | int err = 0; | 4018 | int err = 0; |
@@ -3968,6 +4056,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3968 | /************************** | 4056 | /************************** |
3969 | * 2. Initializing PCI bus | 4057 | * 2. Initializing PCI bus |
3970 | **************************/ | 4058 | **************************/ |
4059 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
4060 | PCIE_LINK_STATE_CLKPM); | ||
4061 | |||
3971 | if (pci_enable_device(pdev)) { | 4062 | if (pci_enable_device(pdev)) { |
3972 | err = -ENODEV; | 4063 | err = -ENODEV; |
3973 | goto out_ieee80211_free_hw; | 4064 | goto out_ieee80211_free_hw; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 60725a5c1b69..4083e4430827 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -1367,21 +1367,24 @@ struct iwl4965_rx_non_cfg_phy { | |||
1367 | } __packed; | 1367 | } __packed; |
1368 | 1368 | ||
1369 | 1369 | ||
1370 | #define IWL50_RX_RES_PHY_CNT 8 | 1370 | #define IWLAGN_RX_RES_PHY_CNT 8 |
1371 | #define IWL50_RX_RES_AGC_IDX 1 | 1371 | #define IWLAGN_RX_RES_AGC_IDX 1 |
1372 | #define IWL50_RX_RES_RSSI_AB_IDX 2 | 1372 | #define IWLAGN_RX_RES_RSSI_AB_IDX 2 |
1373 | #define IWL50_RX_RES_RSSI_C_IDX 3 | 1373 | #define IWLAGN_RX_RES_RSSI_C_IDX 3 |
1374 | #define IWL50_OFDM_AGC_MSK 0xfe00 | 1374 | #define IWLAGN_OFDM_AGC_MSK 0xfe00 |
1375 | #define IWL50_OFDM_AGC_BIT_POS 9 | 1375 | #define IWLAGN_OFDM_AGC_BIT_POS 9 |
1376 | #define IWL50_OFDM_RSSI_A_MSK 0x00ff | 1376 | #define IWLAGN_OFDM_RSSI_INBAND_A_BITMSK 0x00ff |
1377 | #define IWL50_OFDM_RSSI_A_BIT_POS 0 | 1377 | #define IWLAGN_OFDM_RSSI_ALLBAND_A_BITMSK 0xff00 |
1378 | #define IWL50_OFDM_RSSI_B_MSK 0xff0000 | 1378 | #define IWLAGN_OFDM_RSSI_A_BIT_POS 0 |
1379 | #define IWL50_OFDM_RSSI_B_BIT_POS 16 | 1379 | #define IWLAGN_OFDM_RSSI_INBAND_B_BITMSK 0xff0000 |
1380 | #define IWL50_OFDM_RSSI_C_MSK 0x00ff | 1380 | #define IWLAGN_OFDM_RSSI_ALLBAND_B_BITMSK 0xff000000 |
1381 | #define IWL50_OFDM_RSSI_C_BIT_POS 0 | 1381 | #define IWLAGN_OFDM_RSSI_B_BIT_POS 16 |
1382 | #define IWLAGN_OFDM_RSSI_INBAND_C_BITMSK 0x00ff | ||
1383 | #define IWLAGN_OFDM_RSSI_ALLBAND_C_BITMSK 0xff00 | ||
1384 | #define IWLAGN_OFDM_RSSI_C_BIT_POS 0 | ||
1382 | 1385 | ||
1383 | struct iwl5000_non_cfg_phy { | 1386 | struct iwlagn_non_cfg_phy { |
1384 | __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* up to 8 phy entries */ | 1387 | __le32 non_cfg_phy[IWLAGN_RX_RES_PHY_CNT]; /* up to 8 phy entries */ |
1385 | } __packed; | 1388 | } __packed; |
1386 | 1389 | ||
1387 | 1390 | ||
@@ -1401,7 +1404,7 @@ struct iwl_rx_phy_res { | |||
1401 | u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */ | 1404 | u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */ |
1402 | __le32 rate_n_flags; /* RATE_MCS_* */ | 1405 | __le32 rate_n_flags; /* RATE_MCS_* */ |
1403 | __le16 byte_count; /* frame's byte-count */ | 1406 | __le16 byte_count; /* frame's byte-count */ |
1404 | __le16 reserved3; | 1407 | __le16 frame_time; /* frame's time on the air */ |
1405 | } __packed; | 1408 | } __packed; |
1406 | 1409 | ||
1407 | struct iwl_rx_mpdu_res_start { | 1410 | struct iwl_rx_mpdu_res_start { |
@@ -2092,8 +2095,8 @@ struct iwl_link_qual_general_params { | |||
2092 | } __packed; | 2095 | } __packed; |
2093 | 2096 | ||
2094 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ | 2097 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ |
2095 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (65535) | 2098 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) |
2096 | #define LINK_QUAL_AGG_TIME_LIMIT_MIN (0) | 2099 | #define LINK_QUAL_AGG_TIME_LIMIT_MIN (100) |
2097 | 2100 | ||
2098 | #define LINK_QUAL_AGG_DISABLE_START_DEF (3) | 2101 | #define LINK_QUAL_AGG_DISABLE_START_DEF (3) |
2099 | #define LINK_QUAL_AGG_DISABLE_START_MAX (255) | 2102 | #define LINK_QUAL_AGG_DISABLE_START_MAX (255) |
@@ -2110,8 +2113,10 @@ struct iwl_link_qual_general_params { | |||
2110 | */ | 2113 | */ |
2111 | struct iwl_link_qual_agg_params { | 2114 | struct iwl_link_qual_agg_params { |
2112 | 2115 | ||
2113 | /* Maximum number of uSec in aggregation. | 2116 | /* |
2114 | * Driver should set this to 4000 (4 milliseconds). */ | 2117 | *Maximum number of uSec in aggregation. |
2118 | * default set to 4000 (4 milliseconds) if not configured in .cfg | ||
2119 | */ | ||
2115 | __le16 agg_time_limit; | 2120 | __le16 agg_time_limit; |
2116 | 2121 | ||
2117 | /* | 2122 | /* |
@@ -2919,6 +2924,11 @@ struct iwl_scancomplete_notification { | |||
2919 | * | 2924 | * |
2920 | *****************************************************************************/ | 2925 | *****************************************************************************/ |
2921 | 2926 | ||
2927 | enum iwl_ibss_manager { | ||
2928 | IWL_NOT_IBSS_MANAGER = 0, | ||
2929 | IWL_IBSS_MANAGER = 1, | ||
2930 | }; | ||
2931 | |||
2922 | /* | 2932 | /* |
2923 | * BEACON_NOTIFICATION = 0x90 (notification only, not a command) | 2933 | * BEACON_NOTIFICATION = 0x90 (notification only, not a command) |
2924 | */ | 2934 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 07dbc2796448..3d9443b9bec1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -183,14 +183,6 @@ out: | |||
183 | } | 183 | } |
184 | EXPORT_SYMBOL(iwl_alloc_all); | 184 | EXPORT_SYMBOL(iwl_alloc_all); |
185 | 185 | ||
186 | void iwl_hw_detect(struct iwl_priv *priv) | ||
187 | { | ||
188 | priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); | ||
189 | priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); | ||
190 | pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); | ||
191 | } | ||
192 | EXPORT_SYMBOL(iwl_hw_detect); | ||
193 | |||
194 | /* | 186 | /* |
195 | * QoS support | 187 | * QoS support |
196 | */ | 188 | */ |
@@ -247,7 +239,11 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
247 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | 239 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; |
248 | 240 | ||
249 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | 241 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; |
242 | if (priv->cfg->ampdu_factor) | ||
243 | ht_info->ampdu_factor = priv->cfg->ampdu_factor; | ||
250 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | 244 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; |
245 | if (priv->cfg->ampdu_density) | ||
246 | ht_info->ampdu_density = priv->cfg->ampdu_density; | ||
251 | 247 | ||
252 | ht_info->mcs.rx_mask[0] = 0xFF; | 248 | ht_info->mcs.rx_mask[0] = 0xFF; |
253 | if (rx_chains_num >= 2) | 249 | if (rx_chains_num >= 2) |
@@ -499,17 +495,19 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | |||
499 | return new_val; | 495 | return new_val; |
500 | } | 496 | } |
501 | 497 | ||
502 | void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) | 498 | int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) |
503 | { | 499 | { |
504 | u64 tsf; | 500 | u64 tsf; |
505 | s32 interval_tm, rem; | 501 | s32 interval_tm, rem; |
506 | unsigned long flags; | ||
507 | struct ieee80211_conf *conf = NULL; | 502 | struct ieee80211_conf *conf = NULL; |
508 | u16 beacon_int; | 503 | u16 beacon_int; |
509 | 504 | ||
510 | conf = ieee80211_get_hw_conf(priv->hw); | 505 | conf = ieee80211_get_hw_conf(priv->hw); |
511 | 506 | ||
512 | spin_lock_irqsave(&priv->lock, flags); | 507 | lockdep_assert_held(&priv->mutex); |
508 | |||
509 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | ||
510 | |||
513 | priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); | 511 | priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); |
514 | priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); | 512 | priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); |
515 | 513 | ||
@@ -532,14 +530,16 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
532 | rem = do_div(tsf, interval_tm); | 530 | rem = do_div(tsf, interval_tm); |
533 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | 531 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); |
534 | 532 | ||
535 | spin_unlock_irqrestore(&priv->lock, flags); | ||
536 | IWL_DEBUG_ASSOC(priv, | 533 | IWL_DEBUG_ASSOC(priv, |
537 | "beacon interval %d beacon timer %d beacon tim %d\n", | 534 | "beacon interval %d beacon timer %d beacon tim %d\n", |
538 | le16_to_cpu(priv->rxon_timing.beacon_interval), | 535 | le16_to_cpu(priv->rxon_timing.beacon_interval), |
539 | le32_to_cpu(priv->rxon_timing.beacon_init_val), | 536 | le32_to_cpu(priv->rxon_timing.beacon_init_val), |
540 | le16_to_cpu(priv->rxon_timing.atim_window)); | 537 | le16_to_cpu(priv->rxon_timing.atim_window)); |
538 | |||
539 | return iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
540 | sizeof(priv->rxon_timing), &priv->rxon_timing); | ||
541 | } | 541 | } |
542 | EXPORT_SYMBOL(iwl_setup_rxon_timing); | 542 | EXPORT_SYMBOL(iwl_send_rxon_timing); |
543 | 543 | ||
544 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) | 544 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) |
545 | { | 545 | { |
@@ -912,25 +912,18 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv, | |||
912 | EXPORT_SYMBOL(iwl_get_single_channel_number); | 912 | EXPORT_SYMBOL(iwl_get_single_channel_number); |
913 | 913 | ||
914 | /** | 914 | /** |
915 | * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON | 915 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON |
916 | * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz | 916 | * @ch: requested channel as a pointer to struct ieee80211_channel |
917 | * @channel: Any channel valid for the requested phymode | ||
918 | 917 | ||
919 | * In addition to setting the staging RXON, priv->phymode is also set. | 918 | * In addition to setting the staging RXON, priv->band is also set. |
920 | * | 919 | * |
921 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields | 920 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields |
922 | * in the staging RXON flag structure based on the phymode | 921 | * in the staging RXON flag structure based on the ch->band |
923 | */ | 922 | */ |
924 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) | 923 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) |
925 | { | 924 | { |
926 | enum ieee80211_band band = ch->band; | 925 | enum ieee80211_band band = ch->band; |
927 | u16 channel = ieee80211_frequency_to_channel(ch->center_freq); | 926 | u16 channel = ch->hw_value; |
928 | |||
929 | if (!iwl_get_channel_info(priv, band, channel)) { | ||
930 | IWL_DEBUG_INFO(priv, "Could not set channel to %d [%d]\n", | ||
931 | channel, band); | ||
932 | return -EINVAL; | ||
933 | } | ||
934 | 927 | ||
935 | if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && | 928 | if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && |
936 | (priv->band == band)) | 929 | (priv->band == band)) |
@@ -1328,25 +1321,6 @@ out: | |||
1328 | EXPORT_SYMBOL(iwl_apm_init); | 1321 | EXPORT_SYMBOL(iwl_apm_init); |
1329 | 1322 | ||
1330 | 1323 | ||
1331 | int iwl_set_hw_params(struct iwl_priv *priv) | ||
1332 | { | ||
1333 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | ||
1334 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
1335 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
1336 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); | ||
1337 | else | ||
1338 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); | ||
1339 | |||
1340 | priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; | ||
1341 | |||
1342 | if (priv->cfg->mod_params->disable_11n) | ||
1343 | priv->cfg->sku &= ~IWL_SKU_N; | ||
1344 | |||
1345 | /* Device-specific setup */ | ||
1346 | return priv->cfg->ops->lib->set_hw_params(priv); | ||
1347 | } | ||
1348 | EXPORT_SYMBOL(iwl_set_hw_params); | ||
1349 | |||
1350 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | 1324 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) |
1351 | { | 1325 | { |
1352 | int ret = 0; | 1326 | int ret = 0; |
@@ -1496,76 +1470,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | |||
1496 | } | 1470 | } |
1497 | EXPORT_SYMBOL(iwl_send_statistics_request); | 1471 | EXPORT_SYMBOL(iwl_send_statistics_request); |
1498 | 1472 | ||
1499 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) | ||
1500 | { | ||
1501 | struct iwl_ct_kill_config cmd; | ||
1502 | struct iwl_ct_kill_throttling_config adv_cmd; | ||
1503 | unsigned long flags; | ||
1504 | int ret = 0; | ||
1505 | |||
1506 | spin_lock_irqsave(&priv->lock, flags); | ||
1507 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
1508 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
1509 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1510 | priv->thermal_throttle.ct_kill_toggle = false; | ||
1511 | |||
1512 | if (priv->cfg->support_ct_kill_exit) { | ||
1513 | adv_cmd.critical_temperature_enter = | ||
1514 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | ||
1515 | adv_cmd.critical_temperature_exit = | ||
1516 | cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); | ||
1517 | |||
1518 | ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, | ||
1519 | sizeof(adv_cmd), &adv_cmd); | ||
1520 | if (ret) | ||
1521 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | ||
1522 | else | ||
1523 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | ||
1524 | "succeeded, " | ||
1525 | "critical temperature enter is %d," | ||
1526 | "exit is %d\n", | ||
1527 | priv->hw_params.ct_kill_threshold, | ||
1528 | priv->hw_params.ct_kill_exit_threshold); | ||
1529 | } else { | ||
1530 | cmd.critical_temperature_R = | ||
1531 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | ||
1532 | |||
1533 | ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, | ||
1534 | sizeof(cmd), &cmd); | ||
1535 | if (ret) | ||
1536 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | ||
1537 | else | ||
1538 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | ||
1539 | "succeeded, " | ||
1540 | "critical temperature is %d\n", | ||
1541 | priv->hw_params.ct_kill_threshold); | ||
1542 | } | ||
1543 | } | ||
1544 | EXPORT_SYMBOL(iwl_rf_kill_ct_config); | ||
1545 | |||
1546 | |||
1547 | /* | ||
1548 | * CARD_STATE_CMD | ||
1549 | * | ||
1550 | * Use: Sets the device's internal card state to enable, disable, or halt | ||
1551 | * | ||
1552 | * When in the 'enable' state the card operates as normal. | ||
1553 | * When in the 'disable' state, the card enters into a low power mode. | ||
1554 | * When in the 'halt' state, the card is shut down and must be fully | ||
1555 | * restarted to come back on. | ||
1556 | */ | ||
1557 | int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) | ||
1558 | { | ||
1559 | struct iwl_host_cmd cmd = { | ||
1560 | .id = REPLY_CARD_STATE_CMD, | ||
1561 | .len = sizeof(u32), | ||
1562 | .data = &flags, | ||
1563 | .flags = meta_flag, | ||
1564 | }; | ||
1565 | |||
1566 | return iwl_send_cmd(priv, &cmd); | ||
1567 | } | ||
1568 | |||
1569 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | 1473 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, |
1570 | struct iwl_rx_mem_buffer *rxb) | 1474 | struct iwl_rx_mem_buffer *rxb) |
1571 | { | 1475 | { |
@@ -1648,6 +1552,14 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1648 | } | 1552 | } |
1649 | EXPORT_SYMBOL(iwl_mac_conf_tx); | 1553 | EXPORT_SYMBOL(iwl_mac_conf_tx); |
1650 | 1554 | ||
1555 | int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw) | ||
1556 | { | ||
1557 | struct iwl_priv *priv = hw->priv; | ||
1558 | |||
1559 | return priv->ibss_manager == IWL_IBSS_MANAGER; | ||
1560 | } | ||
1561 | EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); | ||
1562 | |||
1651 | static void iwl_ht_conf(struct iwl_priv *priv, | 1563 | static void iwl_ht_conf(struct iwl_priv *priv, |
1652 | struct ieee80211_vif *vif) | 1564 | struct ieee80211_vif *vif) |
1653 | { | 1565 | { |
@@ -2014,6 +1926,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2014 | struct iwl_priv *priv = hw->priv; | 1926 | struct iwl_priv *priv = hw->priv; |
2015 | const struct iwl_channel_info *ch_info; | 1927 | const struct iwl_channel_info *ch_info; |
2016 | struct ieee80211_conf *conf = &hw->conf; | 1928 | struct ieee80211_conf *conf = &hw->conf; |
1929 | struct ieee80211_channel *channel = conf->channel; | ||
2017 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 1930 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2018 | unsigned long flags = 0; | 1931 | unsigned long flags = 0; |
2019 | int ret = 0; | 1932 | int ret = 0; |
@@ -2023,7 +1936,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2023 | mutex_lock(&priv->mutex); | 1936 | mutex_lock(&priv->mutex); |
2024 | 1937 | ||
2025 | IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", | 1938 | IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", |
2026 | conf->channel->hw_value, changed); | 1939 | channel->hw_value, changed); |
2027 | 1940 | ||
2028 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && | 1941 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && |
2029 | test_bit(STATUS_SCANNING, &priv->status))) { | 1942 | test_bit(STATUS_SCANNING, &priv->status))) { |
@@ -2054,8 +1967,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2054 | if (scan_active) | 1967 | if (scan_active) |
2055 | goto set_ch_out; | 1968 | goto set_ch_out; |
2056 | 1969 | ||
2057 | ch = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1970 | ch = channel->hw_value; |
2058 | ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); | 1971 | ch_info = iwl_get_channel_info(priv, channel->band, ch); |
2059 | if (!is_channel_valid(ch_info)) { | 1972 | if (!is_channel_valid(ch_info)) { |
2060 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); | 1973 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); |
2061 | ret = -EINVAL; | 1974 | ret = -EINVAL; |
@@ -2086,16 +1999,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2086 | * from BSS config in iwl_ht_conf */ | 1999 | * from BSS config in iwl_ht_conf */ |
2087 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 2000 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
2088 | 2001 | ||
2089 | /* if we are switching from ht to 2.4 clear flags | ||
2090 | * from any ht related info since 2.4 does not | ||
2091 | * support ht */ | ||
2092 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | 2002 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) |
2093 | priv->staging_rxon.flags = 0; | 2003 | priv->staging_rxon.flags = 0; |
2094 | 2004 | ||
2095 | iwl_set_rxon_channel(priv, conf->channel); | 2005 | iwl_set_rxon_channel(priv, channel); |
2096 | iwl_set_rxon_ht(priv, ht_conf); | 2006 | iwl_set_rxon_ht(priv, ht_conf); |
2097 | 2007 | ||
2098 | iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); | 2008 | iwl_set_flags_for_band(priv, channel->band, priv->vif); |
2099 | spin_unlock_irqrestore(&priv->lock, flags); | 2009 | spin_unlock_irqrestore(&priv->lock, flags); |
2100 | 2010 | ||
2101 | if (priv->cfg->ops->lib->update_bcast_station) | 2011 | if (priv->cfg->ops->lib->update_bcast_station) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5e6ee3da6bbf..7b1e832bae56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -136,6 +136,12 @@ struct iwl_temp_ops { | |||
136 | void (*set_calib_version)(struct iwl_priv *priv); | 136 | void (*set_calib_version)(struct iwl_priv *priv); |
137 | }; | 137 | }; |
138 | 138 | ||
139 | struct iwl_tt_ops { | ||
140 | bool (*lower_power_detection)(struct iwl_priv *priv); | ||
141 | u8 (*tt_power_mode)(struct iwl_priv *priv); | ||
142 | bool (*ct_kill_check)(struct iwl_priv *priv); | ||
143 | }; | ||
144 | |||
139 | struct iwl_lib_ops { | 145 | struct iwl_lib_ops { |
140 | /* set hw dependent parameters */ | 146 | /* set hw dependent parameters */ |
141 | int (*set_hw_params)(struct iwl_priv *priv); | 147 | int (*set_hw_params)(struct iwl_priv *priv); |
@@ -212,6 +218,9 @@ struct iwl_lib_ops { | |||
212 | void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); | 218 | void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); |
213 | 219 | ||
214 | struct iwl_debugfs_ops debugfs_ops; | 220 | struct iwl_debugfs_ops debugfs_ops; |
221 | |||
222 | /* thermal throttling */ | ||
223 | struct iwl_tt_ops tt_ops; | ||
215 | }; | 224 | }; |
216 | 225 | ||
217 | struct iwl_led_ops { | 226 | struct iwl_led_ops { |
@@ -269,6 +278,11 @@ struct iwl_mod_params { | |||
269 | * @chain_noise_calib_by_driver: driver has the capability to perform | 278 | * @chain_noise_calib_by_driver: driver has the capability to perform |
270 | * chain noise calibration operation | 279 | * chain noise calibration operation |
271 | * @scan_antennas: available antenna for scan operation | 280 | * @scan_antennas: available antenna for scan operation |
281 | * @need_dc_calib: need to perform init dc calibration | ||
282 | * @bt_statistics: use BT version of statistics notification | ||
283 | * @agg_time_limit: maximum number of uSec in aggregation | ||
284 | * @ampdu_factor: Maximum A-MPDU length factor | ||
285 | * @ampdu_density: Minimum A-MPDU spacing | ||
272 | * | 286 | * |
273 | * We enable the driver to be backward compatible wrt API version. The | 287 | * We enable the driver to be backward compatible wrt API version. The |
274 | * driver specifies which APIs it supports (with @ucode_api_max being the | 288 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -339,6 +353,9 @@ struct iwl_cfg { | |||
339 | u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; | 353 | u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; |
340 | const bool need_dc_calib; | 354 | const bool need_dc_calib; |
341 | const bool bt_statistics; | 355 | const bool bt_statistics; |
356 | u16 agg_time_limit; | ||
357 | u8 ampdu_factor; | ||
358 | u8 ampdu_density; | ||
342 | }; | 359 | }; |
343 | 360 | ||
344 | /*************************** | 361 | /*************************** |
@@ -347,10 +364,10 @@ struct iwl_cfg { | |||
347 | 364 | ||
348 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, | 365 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, |
349 | struct ieee80211_ops *hw_ops); | 366 | struct ieee80211_ops *hw_ops); |
350 | void iwl_hw_detect(struct iwl_priv *priv); | ||
351 | void iwl_activate_qos(struct iwl_priv *priv); | 367 | void iwl_activate_qos(struct iwl_priv *priv); |
352 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 368 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, |
353 | const struct ieee80211_tx_queue_params *params); | 369 | const struct ieee80211_tx_queue_params *params); |
370 | int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); | ||
354 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); | 371 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); |
355 | int iwl_check_rxon_cmd(struct iwl_priv *priv); | 372 | int iwl_check_rxon_cmd(struct iwl_priv *priv); |
356 | int iwl_full_rxon_required(struct iwl_priv *priv); | 373 | int iwl_full_rxon_required(struct iwl_priv *priv); |
@@ -372,7 +389,6 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
372 | u32 decrypt_res, | 389 | u32 decrypt_res, |
373 | struct ieee80211_rx_status *stats); | 390 | struct ieee80211_rx_status *stats); |
374 | void iwl_irq_handle_error(struct iwl_priv *priv); | 391 | void iwl_irq_handle_error(struct iwl_priv *priv); |
375 | int iwl_set_hw_params(struct iwl_priv *priv); | ||
376 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); | 392 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); |
377 | void iwl_bss_info_changed(struct ieee80211_hw *hw, | 393 | void iwl_bss_info_changed(struct ieee80211_hw *hw, |
378 | struct ieee80211_vif *vif, | 394 | struct ieee80211_vif *vif, |
@@ -527,7 +543,6 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | |||
527 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, | 543 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, |
528 | struct ieee80211_vif *vif, | 544 | struct ieee80211_vif *vif, |
529 | struct cfg80211_scan_request *req); | 545 | struct cfg80211_scan_request *req); |
530 | void iwl_bg_start_internal_scan(struct work_struct *work); | ||
531 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | 546 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); |
532 | int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); | 547 | int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); |
533 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 548 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
@@ -539,9 +554,6 @@ u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | |||
539 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 554 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, |
540 | enum ieee80211_band band, | 555 | enum ieee80211_band band, |
541 | struct ieee80211_vif *vif); | 556 | struct ieee80211_vif *vif); |
542 | void iwl_bg_scan_check(struct work_struct *data); | ||
543 | void iwl_bg_abort_scan(struct work_struct *work); | ||
544 | void iwl_bg_scan_completed(struct work_struct *work); | ||
545 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); | 557 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); |
546 | 558 | ||
547 | /* For faster active scanning, scan will move to the next channel if fewer than | 559 | /* For faster active scanning, scan will move to the next channel if fewer than |
@@ -580,8 +592,6 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, | |||
580 | 592 | ||
581 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); | 593 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); |
582 | 594 | ||
583 | int iwl_send_card_state(struct iwl_priv *priv, u32 flags, | ||
584 | u8 meta_flag); | ||
585 | 595 | ||
586 | /***************************************************** | 596 | /***************************************************** |
587 | * PCI * | 597 | * PCI * |
@@ -695,7 +705,6 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) | |||
695 | return iwl_is_ready(priv); | 705 | return iwl_is_ready(priv); |
696 | } | 706 | } |
697 | 707 | ||
698 | extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); | ||
699 | extern void iwl_send_bt_config(struct iwl_priv *priv); | 708 | extern void iwl_send_bt_config(struct iwl_priv *priv); |
700 | extern int iwl_send_statistics_request(struct iwl_priv *priv, | 709 | extern int iwl_send_statistics_request(struct iwl_priv *priv, |
701 | u8 flags, bool clear); | 710 | u8 flags, bool clear); |
@@ -704,7 +713,7 @@ extern int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
704 | void iwl_apm_stop(struct iwl_priv *priv); | 713 | void iwl_apm_stop(struct iwl_priv *priv); |
705 | int iwl_apm_init(struct iwl_priv *priv); | 714 | int iwl_apm_init(struct iwl_priv *priv); |
706 | 715 | ||
707 | void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); | 716 | int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); |
708 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) | 717 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) |
709 | { | 718 | { |
710 | return priv->cfg->ops->hcmd->rxon_assoc(priv); | 719 | return priv->cfg->ops->hcmd->rxon_assoc(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index e96a1bb12783..d3acdae72381 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -467,8 +467,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
467 | for (i = 0; i < supp_band->n_channels; i++) | 467 | for (i = 0; i < supp_band->n_channels; i++) |
468 | pos += scnprintf(buf + pos, bufsz - pos, | 468 | pos += scnprintf(buf + pos, bufsz - pos, |
469 | "%d: %ddBm: BSS%s%s, %s.\n", | 469 | "%d: %ddBm: BSS%s%s, %s.\n", |
470 | ieee80211_frequency_to_channel( | 470 | channels[i].hw_value, |
471 | channels[i].center_freq), | ||
472 | channels[i].max_power, | 471 | channels[i].max_power, |
473 | channels[i].flags & IEEE80211_CHAN_RADAR ? | 472 | channels[i].flags & IEEE80211_CHAN_RADAR ? |
474 | " (IEEE 802.11h required)" : "", | 473 | " (IEEE 802.11h required)" : "", |
@@ -491,8 +490,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
491 | for (i = 0; i < supp_band->n_channels; i++) | 490 | for (i = 0; i < supp_band->n_channels; i++) |
492 | pos += scnprintf(buf + pos, bufsz - pos, | 491 | pos += scnprintf(buf + pos, bufsz - pos, |
493 | "%d: %ddBm: BSS%s%s, %s.\n", | 492 | "%d: %ddBm: BSS%s%s, %s.\n", |
494 | ieee80211_frequency_to_channel( | 493 | channels[i].hw_value, |
495 | channels[i].center_freq), | ||
496 | channels[i].max_power, | 494 | channels[i].max_power, |
497 | channels[i].flags & IEEE80211_CHAN_RADAR ? | 495 | channels[i].flags & IEEE80211_CHAN_RADAR ? |
498 | " (IEEE 802.11h required)" : "", | 496 | " (IEEE 802.11h required)" : "", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2e97cd2fa98a..1ad330342ffc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -47,6 +47,7 @@ | |||
47 | #include "iwl-led.h" | 47 | #include "iwl-led.h" |
48 | #include "iwl-power.h" | 48 | #include "iwl-power.h" |
49 | #include "iwl-agn-rs.h" | 49 | #include "iwl-agn-rs.h" |
50 | #include "iwl-agn-tt.h" | ||
50 | 51 | ||
51 | struct iwl_tx_queue; | 52 | struct iwl_tx_queue; |
52 | 53 | ||
@@ -420,7 +421,7 @@ struct iwl_tid_data { | |||
420 | }; | 421 | }; |
421 | 422 | ||
422 | struct iwl_hw_key { | 423 | struct iwl_hw_key { |
423 | enum ieee80211_key_alg alg; | 424 | u32 cipher; |
424 | int keylen; | 425 | int keylen; |
425 | u8 keyidx; | 426 | u8 keyidx; |
426 | u8 key[32]; | 427 | u8 key[32]; |
@@ -434,7 +435,13 @@ union iwl_ht_rate_supp { | |||
434 | }; | 435 | }; |
435 | }; | 436 | }; |
436 | 437 | ||
437 | #define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3) | 438 | #define CFG_HT_RX_AMPDU_FACTOR_8K (0x0) |
439 | #define CFG_HT_RX_AMPDU_FACTOR_16K (0x1) | ||
440 | #define CFG_HT_RX_AMPDU_FACTOR_32K (0x2) | ||
441 | #define CFG_HT_RX_AMPDU_FACTOR_64K (0x3) | ||
442 | #define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K | ||
443 | #define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K | ||
444 | #define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K | ||
438 | 445 | ||
439 | /* | 446 | /* |
440 | * Maximal MPDU density for TX aggregation | 447 | * Maximal MPDU density for TX aggregation |
@@ -443,8 +450,13 @@ union iwl_ht_rate_supp { | |||
443 | * 6 - 8us density | 450 | * 6 - 8us density |
444 | * 7 - 16us density | 451 | * 7 - 16us density |
445 | */ | 452 | */ |
453 | #define CFG_HT_MPDU_DENSITY_2USEC (0x4) | ||
446 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) | 454 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) |
455 | #define CFG_HT_MPDU_DENSITY_8USEC (0x6) | ||
456 | #define CFG_HT_MPDU_DENSITY_16USEC (0x7) | ||
447 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC | 457 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC |
458 | #define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC | ||
459 | #define CFG_HT_MPDU_DENSITY_MIN (0x1) | ||
448 | 460 | ||
449 | struct iwl_ht_config { | 461 | struct iwl_ht_config { |
450 | /* self configuration data */ | 462 | /* self configuration data */ |
@@ -1052,7 +1064,6 @@ struct iwl_event_log { | |||
1052 | #define IWL_DEF_MONITORING_PERIOD (1000) | 1064 | #define IWL_DEF_MONITORING_PERIOD (1000) |
1053 | #define IWL_LONG_MONITORING_PERIOD (5000) | 1065 | #define IWL_LONG_MONITORING_PERIOD (5000) |
1054 | #define IWL_ONE_HUNDRED_MSECS (100) | 1066 | #define IWL_ONE_HUNDRED_MSECS (100) |
1055 | #define IWL_SIXTY_SECS (60000) | ||
1056 | 1067 | ||
1057 | enum iwl_reset { | 1068 | enum iwl_reset { |
1058 | IWL_RF_RESET = 0, | 1069 | IWL_RF_RESET = 0, |
@@ -1110,6 +1121,9 @@ struct iwl_priv { | |||
1110 | u32 ucode_beacon_time; | 1121 | u32 ucode_beacon_time; |
1111 | int missed_beacon_threshold; | 1122 | int missed_beacon_threshold; |
1112 | 1123 | ||
1124 | /* track IBSS manager (last beacon) status */ | ||
1125 | u32 ibss_manager; | ||
1126 | |||
1113 | /* storing the jiffies when the plcp error rate is received */ | 1127 | /* storing the jiffies when the plcp error rate is received */ |
1114 | unsigned long plcp_jiffies; | 1128 | unsigned long plcp_jiffies; |
1115 | 1129 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index cda6a94d6cc9..63c0ab46261f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -192,47 +192,6 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
192 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); | 192 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); |
193 | } | 193 | } |
194 | 194 | ||
195 | /* default Thermal Throttling transaction table | ||
196 | * Current state | Throttling Down | Throttling Up | ||
197 | *============================================================================= | ||
198 | * Condition Nxt State Condition Nxt State Condition Nxt State | ||
199 | *----------------------------------------------------------------------------- | ||
200 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A | ||
201 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 | ||
202 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 | ||
203 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | ||
204 | *============================================================================= | ||
205 | */ | ||
206 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { | ||
207 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, | ||
208 | {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, | ||
209 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
210 | }; | ||
211 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { | ||
212 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, | ||
213 | {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, | ||
214 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
215 | }; | ||
216 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { | ||
217 | {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, | ||
218 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, | ||
219 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
220 | }; | ||
221 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { | ||
222 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, | ||
223 | {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, | ||
224 | {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | ||
225 | }; | ||
226 | |||
227 | /* Advance Thermal Throttling default restriction table */ | ||
228 | static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { | ||
229 | {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, | ||
230 | {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, | ||
231 | {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, | ||
232 | {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } | ||
233 | }; | ||
234 | |||
235 | |||
236 | static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, | 195 | static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, |
237 | struct iwl_powertable_cmd *cmd) | 196 | struct iwl_powertable_cmd *cmd) |
238 | { | 197 | { |
@@ -308,7 +267,6 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) | |||
308 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) | 267 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) |
309 | { | 268 | { |
310 | int ret = 0; | 269 | int ret = 0; |
311 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
312 | bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; | 270 | bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; |
313 | bool update_chains; | 271 | bool update_chains; |
314 | struct iwl_powertable_cmd cmd; | 272 | struct iwl_powertable_cmd cmd; |
@@ -325,9 +283,13 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
325 | else if (priv->cfg->supports_idle && | 283 | else if (priv->cfg->supports_idle && |
326 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) | 284 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) |
327 | iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); | 285 | iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); |
328 | else if (tt->state >= IWL_TI_1) | 286 | else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && |
329 | iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); | 287 | priv->cfg->ops->lib->tt_ops.tt_power_mode && |
330 | else if (!enabled) | 288 | priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { |
289 | /* in thermal throttling low power state */ | ||
290 | iwl_static_sleep_cmd(priv, &cmd, | ||
291 | priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper); | ||
292 | } else if (!enabled) | ||
331 | iwl_power_sleep_cam_cmd(priv, &cmd); | 293 | iwl_power_sleep_cam_cmd(priv, &cmd); |
332 | else if (priv->power_data.debug_sleep_level_override >= 0) | 294 | else if (priv->power_data.debug_sleep_level_override >= 0) |
333 | iwl_static_sleep_cmd(priv, &cmd, | 295 | iwl_static_sleep_cmd(priv, &cmd, |
@@ -367,592 +329,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
367 | } | 329 | } |
368 | EXPORT_SYMBOL(iwl_power_update_mode); | 330 | EXPORT_SYMBOL(iwl_power_update_mode); |
369 | 331 | ||
370 | bool iwl_ht_enabled(struct iwl_priv *priv) | ||
371 | { | ||
372 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
373 | struct iwl_tt_restriction *restriction; | ||
374 | |||
375 | if (!priv->thermal_throttle.advanced_tt) | ||
376 | return true; | ||
377 | restriction = tt->restriction + tt->state; | ||
378 | return restriction->is_ht; | ||
379 | } | ||
380 | EXPORT_SYMBOL(iwl_ht_enabled); | ||
381 | |||
382 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | ||
383 | { | ||
384 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | ||
385 | bool within_margin = false; | ||
386 | |||
387 | if (priv->cfg->temperature_kelvin) | ||
388 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
389 | |||
390 | if (!priv->thermal_throttle.advanced_tt) | ||
391 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
392 | CT_KILL_THRESHOLD_LEGACY) ? true : false; | ||
393 | else | ||
394 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
395 | CT_KILL_THRESHOLD) ? true : false; | ||
396 | return within_margin; | ||
397 | } | ||
398 | |||
399 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) | ||
400 | { | ||
401 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
402 | struct iwl_tt_restriction *restriction; | ||
403 | |||
404 | if (!priv->thermal_throttle.advanced_tt) | ||
405 | return IWL_ANT_OK_MULTI; | ||
406 | restriction = tt->restriction + tt->state; | ||
407 | return restriction->tx_stream; | ||
408 | } | ||
409 | EXPORT_SYMBOL(iwl_tx_ant_restriction); | ||
410 | |||
411 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) | ||
412 | { | ||
413 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
414 | struct iwl_tt_restriction *restriction; | ||
415 | |||
416 | if (!priv->thermal_throttle.advanced_tt) | ||
417 | return IWL_ANT_OK_MULTI; | ||
418 | restriction = tt->restriction + tt->state; | ||
419 | return restriction->rx_stream; | ||
420 | } | ||
421 | |||
422 | #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ | ||
423 | #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ | ||
424 | |||
425 | /* | ||
426 | * toggle the bit to wake up uCode and check the temperature | ||
427 | * if the temperature is below CT, uCode will stay awake and send card | ||
428 | * state notification with CT_KILL bit clear to inform Thermal Throttling | ||
429 | * Management to change state. Otherwise, uCode will go back to sleep | ||
430 | * without doing anything, driver should continue the 5 seconds timer | ||
431 | * to wake up uCode for temperature check until temperature drop below CT | ||
432 | */ | ||
433 | static void iwl_tt_check_exit_ct_kill(unsigned long data) | ||
434 | { | ||
435 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
436 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
437 | unsigned long flags; | ||
438 | |||
439 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
440 | return; | ||
441 | |||
442 | if (tt->state == IWL_TI_CT_KILL) { | ||
443 | if (priv->thermal_throttle.ct_kill_toggle) { | ||
444 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
445 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
446 | priv->thermal_throttle.ct_kill_toggle = false; | ||
447 | } else { | ||
448 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
449 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
450 | priv->thermal_throttle.ct_kill_toggle = true; | ||
451 | } | ||
452 | iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
453 | spin_lock_irqsave(&priv->reg_lock, flags); | ||
454 | if (!iwl_grab_nic_access(priv)) | ||
455 | iwl_release_nic_access(priv); | ||
456 | spin_unlock_irqrestore(&priv->reg_lock, flags); | ||
457 | |||
458 | /* Reschedule the ct_kill timer to occur in | ||
459 | * CT_KILL_EXIT_DURATION seconds to ensure we get a | ||
460 | * thermal update */ | ||
461 | IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); | ||
462 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + | ||
463 | CT_KILL_EXIT_DURATION * HZ); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | ||
468 | bool stop) | ||
469 | { | ||
470 | if (stop) { | ||
471 | IWL_DEBUG_POWER(priv, "Stop all queues\n"); | ||
472 | if (priv->mac80211_registered) | ||
473 | ieee80211_stop_queues(priv->hw); | ||
474 | IWL_DEBUG_POWER(priv, | ||
475 | "Schedule 5 seconds CT_KILL Timer\n"); | ||
476 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + | ||
477 | CT_KILL_EXIT_DURATION * HZ); | ||
478 | } else { | ||
479 | IWL_DEBUG_POWER(priv, "Wake all queues\n"); | ||
480 | if (priv->mac80211_registered) | ||
481 | ieee80211_wake_queues(priv->hw); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | static void iwl_tt_ready_for_ct_kill(unsigned long data) | ||
486 | { | ||
487 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
488 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
489 | |||
490 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
491 | return; | ||
492 | |||
493 | /* temperature timer expired, ready to go into CT_KILL state */ | ||
494 | if (tt->state != IWL_TI_CT_KILL) { | ||
495 | IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n"); | ||
496 | tt->state = IWL_TI_CT_KILL; | ||
497 | set_bit(STATUS_CT_KILL, &priv->status); | ||
498 | iwl_perform_ct_kill_task(priv, true); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) | ||
503 | { | ||
504 | IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); | ||
505 | /* make request to retrieve statistics information */ | ||
506 | iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
507 | /* Reschedule the ct_kill wait timer */ | ||
508 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, | ||
509 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); | ||
510 | } | ||
511 | |||
512 | #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) | ||
513 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) | ||
514 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) | ||
515 | |||
516 | /* | ||
517 | * Legacy thermal throttling | ||
518 | * 1) Avoid NIC destruction due to high temperatures | ||
519 | * Chip will identify dangerously high temperatures that can | ||
520 | * harm the device and will power down | ||
521 | * 2) Avoid the NIC power down due to high temperature | ||
522 | * Throttle early enough to lower the power consumption before | ||
523 | * drastic steps are needed | ||
524 | */ | ||
525 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | ||
526 | { | ||
527 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
528 | enum iwl_tt_state old_state; | ||
529 | |||
530 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
531 | if ((tt->tt_previous_temp) && | ||
532 | (temp > tt->tt_previous_temp) && | ||
533 | ((temp - tt->tt_previous_temp) > | ||
534 | IWL_TT_INCREASE_MARGIN)) { | ||
535 | IWL_DEBUG_POWER(priv, | ||
536 | "Temperature increase %d degree Celsius\n", | ||
537 | (temp - tt->tt_previous_temp)); | ||
538 | } | ||
539 | #endif | ||
540 | old_state = tt->state; | ||
541 | /* in Celsius */ | ||
542 | if (temp >= IWL_MINIMAL_POWER_THRESHOLD) | ||
543 | tt->state = IWL_TI_CT_KILL; | ||
544 | else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) | ||
545 | tt->state = IWL_TI_2; | ||
546 | else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) | ||
547 | tt->state = IWL_TI_1; | ||
548 | else | ||
549 | tt->state = IWL_TI_0; | ||
550 | |||
551 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
552 | tt->tt_previous_temp = temp; | ||
553 | #endif | ||
554 | /* stop ct_kill_waiting_tm timer */ | ||
555 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
556 | if (tt->state != old_state) { | ||
557 | switch (tt->state) { | ||
558 | case IWL_TI_0: | ||
559 | /* | ||
560 | * When the system is ready to go back to IWL_TI_0 | ||
561 | * we only have to call iwl_power_update_mode() to | ||
562 | * do so. | ||
563 | */ | ||
564 | break; | ||
565 | case IWL_TI_1: | ||
566 | tt->tt_power_mode = IWL_POWER_INDEX_3; | ||
567 | break; | ||
568 | case IWL_TI_2: | ||
569 | tt->tt_power_mode = IWL_POWER_INDEX_4; | ||
570 | break; | ||
571 | default: | ||
572 | tt->tt_power_mode = IWL_POWER_INDEX_5; | ||
573 | break; | ||
574 | } | ||
575 | mutex_lock(&priv->mutex); | ||
576 | if (old_state == IWL_TI_CT_KILL) | ||
577 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
578 | if (tt->state != IWL_TI_CT_KILL && | ||
579 | iwl_power_update_mode(priv, true)) { | ||
580 | /* TT state not updated | ||
581 | * try again during next temperature read | ||
582 | */ | ||
583 | if (old_state == IWL_TI_CT_KILL) | ||
584 | set_bit(STATUS_CT_KILL, &priv->status); | ||
585 | tt->state = old_state; | ||
586 | IWL_ERR(priv, "Cannot update power mode, " | ||
587 | "TT state not updated\n"); | ||
588 | } else { | ||
589 | if (tt->state == IWL_TI_CT_KILL) { | ||
590 | if (force) { | ||
591 | set_bit(STATUS_CT_KILL, &priv->status); | ||
592 | iwl_perform_ct_kill_task(priv, true); | ||
593 | } else { | ||
594 | iwl_prepare_ct_kill_task(priv); | ||
595 | tt->state = old_state; | ||
596 | } | ||
597 | } else if (old_state == IWL_TI_CT_KILL && | ||
598 | tt->state != IWL_TI_CT_KILL) | ||
599 | iwl_perform_ct_kill_task(priv, false); | ||
600 | IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", | ||
601 | tt->state); | ||
602 | IWL_DEBUG_POWER(priv, "Power Index change to %u\n", | ||
603 | tt->tt_power_mode); | ||
604 | } | ||
605 | mutex_unlock(&priv->mutex); | ||
606 | } | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * Advance thermal throttling | ||
611 | * 1) Avoid NIC destruction due to high temperatures | ||
612 | * Chip will identify dangerously high temperatures that can | ||
613 | * harm the device and will power down | ||
614 | * 2) Avoid the NIC power down due to high temperature | ||
615 | * Throttle early enough to lower the power consumption before | ||
616 | * drastic steps are needed | ||
617 | * Actions include relaxing the power down sleep thresholds and | ||
618 | * decreasing the number of TX streams | ||
619 | * 3) Avoid throughput performance impact as much as possible | ||
620 | * | ||
621 | *============================================================================= | ||
622 | * Condition Nxt State Condition Nxt State Condition Nxt State | ||
623 | *----------------------------------------------------------------------------- | ||
624 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A | ||
625 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 | ||
626 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 | ||
627 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | ||
628 | *============================================================================= | ||
629 | */ | ||
630 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | ||
631 | { | ||
632 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
633 | int i; | ||
634 | bool changed = false; | ||
635 | enum iwl_tt_state old_state; | ||
636 | struct iwl_tt_trans *transaction; | ||
637 | |||
638 | old_state = tt->state; | ||
639 | for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { | ||
640 | /* based on the current TT state, | ||
641 | * find the curresponding transaction table | ||
642 | * each table has (IWL_TI_STATE_MAX - 1) entries | ||
643 | * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) | ||
644 | * will advance to the correct table. | ||
645 | * then based on the current temperature | ||
646 | * find the next state need to transaction to | ||
647 | * go through all the possible (IWL_TI_STATE_MAX - 1) entries | ||
648 | * in the current table to see if transaction is needed | ||
649 | */ | ||
650 | transaction = tt->transaction + | ||
651 | ((old_state * (IWL_TI_STATE_MAX - 1)) + i); | ||
652 | if (temp >= transaction->tt_low && | ||
653 | temp <= transaction->tt_high) { | ||
654 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
655 | if ((tt->tt_previous_temp) && | ||
656 | (temp > tt->tt_previous_temp) && | ||
657 | ((temp - tt->tt_previous_temp) > | ||
658 | IWL_TT_INCREASE_MARGIN)) { | ||
659 | IWL_DEBUG_POWER(priv, | ||
660 | "Temperature increase %d " | ||
661 | "degree Celsius\n", | ||
662 | (temp - tt->tt_previous_temp)); | ||
663 | } | ||
664 | tt->tt_previous_temp = temp; | ||
665 | #endif | ||
666 | if (old_state != | ||
667 | transaction->next_state) { | ||
668 | changed = true; | ||
669 | tt->state = | ||
670 | transaction->next_state; | ||
671 | } | ||
672 | break; | ||
673 | } | ||
674 | } | ||
675 | /* stop ct_kill_waiting_tm timer */ | ||
676 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
677 | if (changed) { | ||
678 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | ||
679 | |||
680 | if (tt->state >= IWL_TI_1) { | ||
681 | /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ | ||
682 | tt->tt_power_mode = IWL_POWER_INDEX_5; | ||
683 | if (!iwl_ht_enabled(priv)) | ||
684 | /* disable HT */ | ||
685 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
686 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | ||
687 | RXON_FLG_HT40_PROT_MSK | | ||
688 | RXON_FLG_HT_PROT_MSK); | ||
689 | else { | ||
690 | /* check HT capability and set | ||
691 | * according to the system HT capability | ||
692 | * in case get disabled before */ | ||
693 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
694 | } | ||
695 | |||
696 | } else { | ||
697 | /* | ||
698 | * restore system power setting -- it will be | ||
699 | * recalculated automatically. | ||
700 | */ | ||
701 | |||
702 | /* check HT capability and set | ||
703 | * according to the system HT capability | ||
704 | * in case get disabled before */ | ||
705 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
706 | } | ||
707 | mutex_lock(&priv->mutex); | ||
708 | if (old_state == IWL_TI_CT_KILL) | ||
709 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
710 | if (tt->state != IWL_TI_CT_KILL && | ||
711 | iwl_power_update_mode(priv, true)) { | ||
712 | /* TT state not updated | ||
713 | * try again during next temperature read | ||
714 | */ | ||
715 | IWL_ERR(priv, "Cannot update power mode, " | ||
716 | "TT state not updated\n"); | ||
717 | if (old_state == IWL_TI_CT_KILL) | ||
718 | set_bit(STATUS_CT_KILL, &priv->status); | ||
719 | tt->state = old_state; | ||
720 | } else { | ||
721 | IWL_DEBUG_POWER(priv, | ||
722 | "Thermal Throttling to new state: %u\n", | ||
723 | tt->state); | ||
724 | if (old_state != IWL_TI_CT_KILL && | ||
725 | tt->state == IWL_TI_CT_KILL) { | ||
726 | if (force) { | ||
727 | IWL_DEBUG_POWER(priv, | ||
728 | "Enter IWL_TI_CT_KILL\n"); | ||
729 | set_bit(STATUS_CT_KILL, &priv->status); | ||
730 | iwl_perform_ct_kill_task(priv, true); | ||
731 | } else { | ||
732 | iwl_prepare_ct_kill_task(priv); | ||
733 | tt->state = old_state; | ||
734 | } | ||
735 | } else if (old_state == IWL_TI_CT_KILL && | ||
736 | tt->state != IWL_TI_CT_KILL) { | ||
737 | IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); | ||
738 | iwl_perform_ct_kill_task(priv, false); | ||
739 | } | ||
740 | } | ||
741 | mutex_unlock(&priv->mutex); | ||
742 | } | ||
743 | } | ||
744 | |||
745 | /* Card State Notification indicated reach critical temperature | ||
746 | * if PSP not enable, no Thermal Throttling function will be performed | ||
747 | * just set the GP1 bit to acknowledge the event | ||
748 | * otherwise, go into IWL_TI_CT_KILL state | ||
749 | * since Card State Notification will not provide any temperature reading | ||
750 | * for Legacy mode | ||
751 | * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() | ||
752 | * for advance mode | ||
753 | * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state | ||
754 | */ | ||
755 | static void iwl_bg_ct_enter(struct work_struct *work) | ||
756 | { | ||
757 | struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); | ||
758 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
759 | |||
760 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
761 | return; | ||
762 | |||
763 | if (!iwl_is_ready(priv)) | ||
764 | return; | ||
765 | |||
766 | if (tt->state != IWL_TI_CT_KILL) { | ||
767 | IWL_ERR(priv, "Device reached critical temperature " | ||
768 | "- ucode going to sleep!\n"); | ||
769 | if (!priv->thermal_throttle.advanced_tt) | ||
770 | iwl_legacy_tt_handler(priv, | ||
771 | IWL_MINIMAL_POWER_THRESHOLD, | ||
772 | true); | ||
773 | else | ||
774 | iwl_advance_tt_handler(priv, | ||
775 | CT_KILL_THRESHOLD + 1, true); | ||
776 | } | ||
777 | } | ||
778 | |||
779 | /* Card State Notification indicated out of critical temperature | ||
780 | * since Card State Notification will not provide any temperature reading | ||
781 | * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature | ||
782 | * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state | ||
783 | */ | ||
784 | static void iwl_bg_ct_exit(struct work_struct *work) | ||
785 | { | ||
786 | struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); | ||
787 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
788 | |||
789 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
790 | return; | ||
791 | |||
792 | if (!iwl_is_ready(priv)) | ||
793 | return; | ||
794 | |||
795 | /* stop ct_kill_exit_tm timer */ | ||
796 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | ||
797 | |||
798 | if (tt->state == IWL_TI_CT_KILL) { | ||
799 | IWL_ERR(priv, | ||
800 | "Device temperature below critical" | ||
801 | "- ucode awake!\n"); | ||
802 | /* | ||
803 | * exit from CT_KILL state | ||
804 | * reset the current temperature reading | ||
805 | */ | ||
806 | priv->temperature = 0; | ||
807 | if (!priv->thermal_throttle.advanced_tt) | ||
808 | iwl_legacy_tt_handler(priv, | ||
809 | IWL_REDUCED_PERFORMANCE_THRESHOLD_2, | ||
810 | true); | ||
811 | else | ||
812 | iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, | ||
813 | true); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv) | ||
818 | { | ||
819 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
820 | return; | ||
821 | |||
822 | IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); | ||
823 | queue_work(priv->workqueue, &priv->ct_enter); | ||
824 | } | ||
825 | EXPORT_SYMBOL(iwl_tt_enter_ct_kill); | ||
826 | |||
827 | void iwl_tt_exit_ct_kill(struct iwl_priv *priv) | ||
828 | { | ||
829 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
830 | return; | ||
831 | |||
832 | IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); | ||
833 | queue_work(priv->workqueue, &priv->ct_exit); | ||
834 | } | ||
835 | EXPORT_SYMBOL(iwl_tt_exit_ct_kill); | ||
836 | |||
837 | static void iwl_bg_tt_work(struct work_struct *work) | ||
838 | { | ||
839 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); | ||
840 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | ||
841 | |||
842 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
843 | return; | ||
844 | |||
845 | if (priv->cfg->temperature_kelvin) | ||
846 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
847 | |||
848 | if (!priv->thermal_throttle.advanced_tt) | ||
849 | iwl_legacy_tt_handler(priv, temp, false); | ||
850 | else | ||
851 | iwl_advance_tt_handler(priv, temp, false); | ||
852 | } | ||
853 | |||
854 | void iwl_tt_handler(struct iwl_priv *priv) | ||
855 | { | ||
856 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
857 | return; | ||
858 | |||
859 | IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); | ||
860 | queue_work(priv->workqueue, &priv->tt_work); | ||
861 | } | ||
862 | EXPORT_SYMBOL(iwl_tt_handler); | ||
863 | |||
864 | /* Thermal throttling initialization | ||
865 | * For advance thermal throttling: | ||
866 | * Initialize Thermal Index and temperature threshold table | ||
867 | * Initialize thermal throttling restriction table | ||
868 | */ | ||
869 | void iwl_tt_initialize(struct iwl_priv *priv) | ||
870 | { | ||
871 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
872 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); | ||
873 | struct iwl_tt_trans *transaction; | ||
874 | |||
875 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); | ||
876 | |||
877 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); | ||
878 | |||
879 | tt->state = IWL_TI_0; | ||
880 | init_timer(&priv->thermal_throttle.ct_kill_exit_tm); | ||
881 | priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; | ||
882 | priv->thermal_throttle.ct_kill_exit_tm.function = | ||
883 | iwl_tt_check_exit_ct_kill; | ||
884 | init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
885 | priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv; | ||
886 | priv->thermal_throttle.ct_kill_waiting_tm.function = | ||
887 | iwl_tt_ready_for_ct_kill; | ||
888 | /* setup deferred ct kill work */ | ||
889 | INIT_WORK(&priv->tt_work, iwl_bg_tt_work); | ||
890 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | ||
891 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); | ||
892 | |||
893 | if (priv->cfg->adv_thermal_throttle) { | ||
894 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); | ||
895 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * | ||
896 | IWL_TI_STATE_MAX, GFP_KERNEL); | ||
897 | tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * | ||
898 | IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), | ||
899 | GFP_KERNEL); | ||
900 | if (!tt->restriction || !tt->transaction) { | ||
901 | IWL_ERR(priv, "Fallback to Legacy Throttling\n"); | ||
902 | priv->thermal_throttle.advanced_tt = false; | ||
903 | kfree(tt->restriction); | ||
904 | tt->restriction = NULL; | ||
905 | kfree(tt->transaction); | ||
906 | tt->transaction = NULL; | ||
907 | } else { | ||
908 | transaction = tt->transaction + | ||
909 | (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); | ||
910 | memcpy(transaction, &tt_range_0[0], size); | ||
911 | transaction = tt->transaction + | ||
912 | (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); | ||
913 | memcpy(transaction, &tt_range_1[0], size); | ||
914 | transaction = tt->transaction + | ||
915 | (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); | ||
916 | memcpy(transaction, &tt_range_2[0], size); | ||
917 | transaction = tt->transaction + | ||
918 | (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); | ||
919 | memcpy(transaction, &tt_range_3[0], size); | ||
920 | size = sizeof(struct iwl_tt_restriction) * | ||
921 | IWL_TI_STATE_MAX; | ||
922 | memcpy(tt->restriction, | ||
923 | &restriction_range[0], size); | ||
924 | priv->thermal_throttle.advanced_tt = true; | ||
925 | } | ||
926 | } else { | ||
927 | IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); | ||
928 | priv->thermal_throttle.advanced_tt = false; | ||
929 | } | ||
930 | } | ||
931 | EXPORT_SYMBOL(iwl_tt_initialize); | ||
932 | |||
933 | /* cleanup thermal throttling management related memory and timer */ | ||
934 | void iwl_tt_exit(struct iwl_priv *priv) | ||
935 | { | ||
936 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
937 | |||
938 | /* stop ct_kill_exit_tm timer if activated */ | ||
939 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | ||
940 | /* stop ct_kill_waiting_tm timer if activated */ | ||
941 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
942 | cancel_work_sync(&priv->tt_work); | ||
943 | cancel_work_sync(&priv->ct_enter); | ||
944 | cancel_work_sync(&priv->ct_exit); | ||
945 | |||
946 | if (priv->thermal_throttle.advanced_tt) { | ||
947 | /* free advance thermal throttling memory */ | ||
948 | kfree(tt->restriction); | ||
949 | tt->restriction = NULL; | ||
950 | kfree(tt->transaction); | ||
951 | tt->transaction = NULL; | ||
952 | } | ||
953 | } | ||
954 | EXPORT_SYMBOL(iwl_tt_exit); | ||
955 | |||
956 | /* initialize to default */ | 332 | /* initialize to default */ |
957 | void iwl_power_initialize(struct iwl_priv *priv) | 333 | void iwl_power_initialize(struct iwl_priv *priv) |
958 | { | 334 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 5db91c10dcc8..df81565a7cc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h | |||
@@ -30,90 +30,6 @@ | |||
30 | 30 | ||
31 | #include "iwl-commands.h" | 31 | #include "iwl-commands.h" |
32 | 32 | ||
33 | #define IWL_ABSOLUTE_ZERO 0 | ||
34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF | ||
35 | #define IWL_TT_INCREASE_MARGIN 5 | ||
36 | #define IWL_TT_CT_KILL_MARGIN 3 | ||
37 | |||
38 | enum iwl_antenna_ok { | ||
39 | IWL_ANT_OK_NONE, | ||
40 | IWL_ANT_OK_SINGLE, | ||
41 | IWL_ANT_OK_MULTI, | ||
42 | }; | ||
43 | |||
44 | /* Thermal Throttling State Machine states */ | ||
45 | enum iwl_tt_state { | ||
46 | IWL_TI_0, /* normal temperature, system power state */ | ||
47 | IWL_TI_1, /* high temperature detect, low power state */ | ||
48 | IWL_TI_2, /* higher temperature detected, lower power state */ | ||
49 | IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ | ||
50 | IWL_TI_STATE_MAX | ||
51 | }; | ||
52 | |||
53 | /** | ||
54 | * struct iwl_tt_restriction - Thermal Throttling restriction table | ||
55 | * @tx_stream: number of tx stream allowed | ||
56 | * @is_ht: ht enable/disable | ||
57 | * @rx_stream: number of rx stream allowed | ||
58 | * | ||
59 | * This table is used by advance thermal throttling management | ||
60 | * based on the current thermal throttling state, and determines | ||
61 | * the number of tx/rx streams and the status of HT operation. | ||
62 | */ | ||
63 | struct iwl_tt_restriction { | ||
64 | enum iwl_antenna_ok tx_stream; | ||
65 | enum iwl_antenna_ok rx_stream; | ||
66 | bool is_ht; | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * struct iwl_tt_trans - Thermal Throttling transaction table | ||
71 | * @next_state: next thermal throttling mode | ||
72 | * @tt_low: low temperature threshold to change state | ||
73 | * @tt_high: high temperature threshold to change state | ||
74 | * | ||
75 | * This is used by the advanced thermal throttling algorithm | ||
76 | * to determine the next thermal state to go based on the | ||
77 | * current temperature. | ||
78 | */ | ||
79 | struct iwl_tt_trans { | ||
80 | enum iwl_tt_state next_state; | ||
81 | u32 tt_low; | ||
82 | u32 tt_high; | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * struct iwl_tt_mgnt - Thermal Throttling Management structure | ||
87 | * @advanced_tt: advanced thermal throttle required | ||
88 | * @state: current Thermal Throttling state | ||
89 | * @tt_power_mode: Thermal Throttling power mode index | ||
90 | * being used to set power level when | ||
91 | * when thermal throttling state != IWL_TI_0 | ||
92 | * the tt_power_mode should set to different | ||
93 | * power mode based on the current tt state | ||
94 | * @tt_previous_temperature: last measured temperature | ||
95 | * @iwl_tt_restriction: ptr to restriction tbl, used by advance | ||
96 | * thermal throttling to determine how many tx/rx streams | ||
97 | * should be used in tt state; and can HT be enabled or not | ||
98 | * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling | ||
99 | * state transaction | ||
100 | * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature | ||
101 | * @ct_kill_exit_tm: timer to exit thermal kill | ||
102 | */ | ||
103 | struct iwl_tt_mgmt { | ||
104 | enum iwl_tt_state state; | ||
105 | bool advanced_tt; | ||
106 | u8 tt_power_mode; | ||
107 | bool ct_kill_toggle; | ||
108 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
109 | s32 tt_previous_temp; | ||
110 | #endif | ||
111 | struct iwl_tt_restriction *restriction; | ||
112 | struct iwl_tt_trans *transaction; | ||
113 | struct timer_list ct_kill_exit_tm; | ||
114 | struct timer_list ct_kill_waiting_tm; | ||
115 | }; | ||
116 | |||
117 | enum iwl_power_level { | 33 | enum iwl_power_level { |
118 | IWL_POWER_INDEX_1, | 34 | IWL_POWER_INDEX_1, |
119 | IWL_POWER_INDEX_2, | 35 | IWL_POWER_INDEX_2, |
@@ -130,15 +46,6 @@ struct iwl_power_mgr { | |||
130 | }; | 46 | }; |
131 | 47 | ||
132 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); | 48 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); |
133 | bool iwl_ht_enabled(struct iwl_priv *priv); | ||
134 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv); | ||
135 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); | ||
136 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); | ||
137 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); | ||
138 | void iwl_tt_exit_ct_kill(struct iwl_priv *priv); | ||
139 | void iwl_tt_handler(struct iwl_priv *priv); | ||
140 | void iwl_tt_initialize(struct iwl_priv *priv); | ||
141 | void iwl_tt_exit(struct iwl_priv *priv); | ||
142 | void iwl_power_initialize(struct iwl_priv *priv); | 49 | void iwl_power_initialize(struct iwl_priv *priv); |
143 | 50 | ||
144 | extern bool no_sleep_autoadjust; | 51 | extern bool no_sleep_autoadjust; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a4b3663a262f..8d7fa59364fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -378,7 +378,7 @@ void iwl_internal_short_hw_scan(struct iwl_priv *priv) | |||
378 | queue_work(priv->workqueue, &priv->start_internal_scan); | 378 | queue_work(priv->workqueue, &priv->start_internal_scan); |
379 | } | 379 | } |
380 | 380 | ||
381 | void iwl_bg_start_internal_scan(struct work_struct *work) | 381 | static void iwl_bg_start_internal_scan(struct work_struct *work) |
382 | { | 382 | { |
383 | struct iwl_priv *priv = | 383 | struct iwl_priv *priv = |
384 | container_of(work, struct iwl_priv, start_internal_scan); | 384 | container_of(work, struct iwl_priv, start_internal_scan); |
@@ -418,9 +418,8 @@ void iwl_bg_start_internal_scan(struct work_struct *work) | |||
418 | unlock: | 418 | unlock: |
419 | mutex_unlock(&priv->mutex); | 419 | mutex_unlock(&priv->mutex); |
420 | } | 420 | } |
421 | EXPORT_SYMBOL(iwl_bg_start_internal_scan); | ||
422 | 421 | ||
423 | void iwl_bg_scan_check(struct work_struct *data) | 422 | static void iwl_bg_scan_check(struct work_struct *data) |
424 | { | 423 | { |
425 | struct iwl_priv *priv = | 424 | struct iwl_priv *priv = |
426 | container_of(data, struct iwl_priv, scan_check.work); | 425 | container_of(data, struct iwl_priv, scan_check.work); |
@@ -439,7 +438,6 @@ void iwl_bg_scan_check(struct work_struct *data) | |||
439 | } | 438 | } |
440 | mutex_unlock(&priv->mutex); | 439 | mutex_unlock(&priv->mutex); |
441 | } | 440 | } |
442 | EXPORT_SYMBOL(iwl_bg_scan_check); | ||
443 | 441 | ||
444 | /** | 442 | /** |
445 | * iwl_fill_probe_req - fill in all required fields and IE for probe request | 443 | * iwl_fill_probe_req - fill in all required fields and IE for probe request |
@@ -489,7 +487,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
489 | } | 487 | } |
490 | EXPORT_SYMBOL(iwl_fill_probe_req); | 488 | EXPORT_SYMBOL(iwl_fill_probe_req); |
491 | 489 | ||
492 | void iwl_bg_abort_scan(struct work_struct *work) | 490 | static void iwl_bg_abort_scan(struct work_struct *work) |
493 | { | 491 | { |
494 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); | 492 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); |
495 | 493 | ||
@@ -504,13 +502,13 @@ void iwl_bg_abort_scan(struct work_struct *work) | |||
504 | iwl_send_scan_abort(priv); | 502 | iwl_send_scan_abort(priv); |
505 | mutex_unlock(&priv->mutex); | 503 | mutex_unlock(&priv->mutex); |
506 | } | 504 | } |
507 | EXPORT_SYMBOL(iwl_bg_abort_scan); | ||
508 | 505 | ||
509 | void iwl_bg_scan_completed(struct work_struct *work) | 506 | static void iwl_bg_scan_completed(struct work_struct *work) |
510 | { | 507 | { |
511 | struct iwl_priv *priv = | 508 | struct iwl_priv *priv = |
512 | container_of(work, struct iwl_priv, scan_completed); | 509 | container_of(work, struct iwl_priv, scan_completed); |
513 | bool internal = false; | 510 | bool internal = false; |
511 | bool scan_completed = false; | ||
514 | 512 | ||
515 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); | 513 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); |
516 | 514 | ||
@@ -521,7 +519,8 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
521 | priv->is_internal_short_scan = false; | 519 | priv->is_internal_short_scan = false; |
522 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | 520 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); |
523 | internal = true; | 521 | internal = true; |
524 | } else { | 522 | } else if (priv->scan_request) { |
523 | scan_completed = true; | ||
525 | priv->scan_request = NULL; | 524 | priv->scan_request = NULL; |
526 | priv->scan_vif = NULL; | 525 | priv->scan_vif = NULL; |
527 | } | 526 | } |
@@ -552,10 +551,9 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
552 | * into driver again into functions that will attempt to take | 551 | * into driver again into functions that will attempt to take |
553 | * mutex. | 552 | * mutex. |
554 | */ | 553 | */ |
555 | if (!internal) | 554 | if (scan_completed) |
556 | ieee80211_scan_completed(priv->hw, false); | 555 | ieee80211_scan_completed(priv->hw, false); |
557 | } | 556 | } |
558 | EXPORT_SYMBOL(iwl_bg_scan_completed); | ||
559 | 557 | ||
560 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | 558 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) |
561 | { | 559 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7e0829be5e78..d5e8db37b86e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -818,7 +818,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
818 | 818 | ||
819 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; | 819 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; |
820 | keyconf->hw_key_idx = HW_KEY_DEFAULT; | 820 | keyconf->hw_key_idx = HW_KEY_DEFAULT; |
821 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; | 821 | priv->stations[IWL_AP_ID].keyinfo.cipher = keyconf->cipher; |
822 | 822 | ||
823 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; | 823 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; |
824 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, | 824 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, |
@@ -856,7 +856,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
856 | 856 | ||
857 | spin_lock_irqsave(&priv->sta_lock, flags); | 857 | spin_lock_irqsave(&priv->sta_lock, flags); |
858 | 858 | ||
859 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 859 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; |
860 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | 860 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; |
861 | priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; | 861 | priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; |
862 | 862 | ||
@@ -906,7 +906,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
906 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 906 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
907 | 907 | ||
908 | spin_lock_irqsave(&priv->sta_lock, flags); | 908 | spin_lock_irqsave(&priv->sta_lock, flags); |
909 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 909 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; |
910 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | 910 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; |
911 | 911 | ||
912 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, | 912 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, |
@@ -955,7 +955,7 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
955 | 955 | ||
956 | spin_lock_irqsave(&priv->sta_lock, flags); | 956 | spin_lock_irqsave(&priv->sta_lock, flags); |
957 | 957 | ||
958 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 958 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; |
959 | priv->stations[sta_id].keyinfo.keylen = 16; | 959 | priv->stations[sta_id].keyinfo.keylen = 16; |
960 | 960 | ||
961 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) | 961 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) |
@@ -1090,24 +1090,26 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, | |||
1090 | priv->key_mapping_key++; | 1090 | priv->key_mapping_key++; |
1091 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | 1091 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; |
1092 | 1092 | ||
1093 | switch (keyconf->alg) { | 1093 | switch (keyconf->cipher) { |
1094 | case ALG_CCMP: | 1094 | case WLAN_CIPHER_SUITE_CCMP: |
1095 | ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); | 1095 | ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); |
1096 | break; | 1096 | break; |
1097 | case ALG_TKIP: | 1097 | case WLAN_CIPHER_SUITE_TKIP: |
1098 | ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id); | 1098 | ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id); |
1099 | break; | 1099 | break; |
1100 | case ALG_WEP: | 1100 | case WLAN_CIPHER_SUITE_WEP40: |
1101 | case WLAN_CIPHER_SUITE_WEP104: | ||
1101 | ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); | 1102 | ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); |
1102 | break; | 1103 | break; |
1103 | default: | 1104 | default: |
1104 | IWL_ERR(priv, | 1105 | IWL_ERR(priv, |
1105 | "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); | 1106 | "Unknown alg: %s cipher = %x\n", __func__, |
1107 | keyconf->cipher); | ||
1106 | ret = -EINVAL; | 1108 | ret = -EINVAL; |
1107 | } | 1109 | } |
1108 | 1110 | ||
1109 | IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", | 1111 | IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n", |
1110 | keyconf->alg, keyconf->keylen, keyconf->keyidx, | 1112 | keyconf->cipher, keyconf->keylen, keyconf->keyidx, |
1111 | sta_id, ret); | 1113 | sta_id, ret); |
1112 | 1114 | ||
1113 | return ret; | 1115 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index a81989c06983..c308dab14673 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -422,6 +422,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
422 | int len; | 422 | int len; |
423 | u32 idx; | 423 | u32 idx; |
424 | u16 fix_size; | 424 | u16 fix_size; |
425 | bool is_ct_kill = false; | ||
425 | 426 | ||
426 | cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); | 427 | cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); |
427 | fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); | 428 | fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); |
@@ -443,9 +444,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
443 | 444 | ||
444 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { | 445 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { |
445 | IWL_ERR(priv, "No space in command queue\n"); | 446 | IWL_ERR(priv, "No space in command queue\n"); |
446 | if (iwl_within_ct_kill_margin(priv)) | 447 | if (priv->cfg->ops->lib->tt_ops.ct_kill_check) { |
447 | iwl_tt_enter_ct_kill(priv); | 448 | is_ct_kill = |
448 | else { | 449 | priv->cfg->ops->lib->tt_ops.ct_kill_check(priv); |
450 | } | ||
451 | if (!is_ct_kill) { | ||
449 | IWL_ERR(priv, "Restarting adapter due to queue full\n"); | 452 | IWL_ERR(priv, "Restarting adapter due to queue full\n"); |
450 | queue_work(priv->workqueue, &priv->restart); | 453 | queue_work(priv->workqueue, &priv->restart); |
451 | } | 454 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 59a308b02f95..94d7e6e1323d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci-aspm.h> | ||
36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
37 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
38 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
@@ -151,7 +152,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
151 | key_flags &= ~STA_KEY_FLG_INVALID; | 152 | key_flags &= ~STA_KEY_FLG_INVALID; |
152 | 153 | ||
153 | spin_lock_irqsave(&priv->sta_lock, flags); | 154 | spin_lock_irqsave(&priv->sta_lock, flags); |
154 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 155 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; |
155 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | 156 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; |
156 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, | 157 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, |
157 | keyconf->keylen); | 158 | keyconf->keylen); |
@@ -222,23 +223,25 @@ static int iwl3945_set_dynamic_key(struct iwl_priv *priv, | |||
222 | 223 | ||
223 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | 224 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; |
224 | 225 | ||
225 | switch (keyconf->alg) { | 226 | switch (keyconf->cipher) { |
226 | case ALG_CCMP: | 227 | case WLAN_CIPHER_SUITE_CCMP: |
227 | ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); | 228 | ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); |
228 | break; | 229 | break; |
229 | case ALG_TKIP: | 230 | case WLAN_CIPHER_SUITE_TKIP: |
230 | ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id); | 231 | ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id); |
231 | break; | 232 | break; |
232 | case ALG_WEP: | 233 | case WLAN_CIPHER_SUITE_WEP40: |
234 | case WLAN_CIPHER_SUITE_WEP104: | ||
233 | ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); | 235 | ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); |
234 | break; | 236 | break; |
235 | default: | 237 | default: |
236 | IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); | 238 | IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__, |
239 | keyconf->cipher); | ||
237 | ret = -EINVAL; | 240 | ret = -EINVAL; |
238 | } | 241 | } |
239 | 242 | ||
240 | IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", | 243 | IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n", |
241 | keyconf->alg, keyconf->keylen, keyconf->keyidx, | 244 | keyconf->cipher, keyconf->keylen, keyconf->keyidx, |
242 | sta_id, ret); | 245 | sta_id, ret); |
243 | 246 | ||
244 | return ret; | 247 | return ret; |
@@ -254,10 +257,11 @@ static int iwl3945_remove_static_key(struct iwl_priv *priv) | |||
254 | static int iwl3945_set_static_key(struct iwl_priv *priv, | 257 | static int iwl3945_set_static_key(struct iwl_priv *priv, |
255 | struct ieee80211_key_conf *key) | 258 | struct ieee80211_key_conf *key) |
256 | { | 259 | { |
257 | if (key->alg == ALG_WEP) | 260 | if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
261 | key->cipher == WLAN_CIPHER_SUITE_WEP104) | ||
258 | return -EOPNOTSUPP; | 262 | return -EOPNOTSUPP; |
259 | 263 | ||
260 | IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg); | 264 | IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher); |
261 | return -EINVAL; | 265 | return -EINVAL; |
262 | } | 266 | } |
263 | 267 | ||
@@ -369,23 +373,25 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
369 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 373 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
370 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; | 374 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; |
371 | 375 | ||
372 | switch (keyinfo->alg) { | 376 | tx_cmd->sec_ctl = 0; |
373 | case ALG_CCMP: | 377 | |
378 | switch (keyinfo->cipher) { | ||
379 | case WLAN_CIPHER_SUITE_CCMP: | ||
374 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | 380 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; |
375 | memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); | 381 | memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); |
376 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | 382 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); |
377 | break; | 383 | break; |
378 | 384 | ||
379 | case ALG_TKIP: | 385 | case WLAN_CIPHER_SUITE_TKIP: |
380 | break; | 386 | break; |
381 | 387 | ||
382 | case ALG_WEP: | 388 | case WLAN_CIPHER_SUITE_WEP104: |
383 | tx_cmd->sec_ctl = TX_CMD_SEC_WEP | | 389 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; |
390 | /* fall through */ | ||
391 | case WLAN_CIPHER_SUITE_WEP40: | ||
392 | tx_cmd->sec_ctl |= TX_CMD_SEC_WEP | | ||
384 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; | 393 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; |
385 | 394 | ||
386 | if (keyinfo->keylen == 13) | ||
387 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
388 | |||
389 | memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen); | 395 | memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen); |
390 | 396 | ||
391 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | 397 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " |
@@ -393,7 +399,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
393 | break; | 399 | break; |
394 | 400 | ||
395 | default: | 401 | default: |
396 | IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg); | 402 | IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher); |
397 | break; | 403 | break; |
398 | } | 404 | } |
399 | } | 405 | } |
@@ -813,9 +819,9 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) | |||
813 | static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | 819 | static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, |
814 | struct iwl_rx_mem_buffer *rxb) | 820 | struct iwl_rx_mem_buffer *rxb) |
815 | { | 821 | { |
816 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
817 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 822 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
818 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); | 823 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); |
824 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
819 | u8 rate = beacon->beacon_notify_hdr.rate; | 825 | u8 rate = beacon->beacon_notify_hdr.rate; |
820 | 826 | ||
821 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " | 827 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " |
@@ -827,6 +833,8 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | |||
827 | le32_to_cpu(beacon->low_tsf), rate); | 833 | le32_to_cpu(beacon->low_tsf), rate); |
828 | #endif | 834 | #endif |
829 | 835 | ||
836 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
837 | |||
830 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && | 838 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && |
831 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) | 839 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) |
832 | queue_work(priv->workqueue, &priv->beacon_update); | 840 | queue_work(priv->workqueue, &priv->beacon_update); |
@@ -3086,10 +3094,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3086 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 3094 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
3087 | iwlcore_commit_rxon(priv); | 3095 | iwlcore_commit_rxon(priv); |
3088 | 3096 | ||
3089 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | 3097 | rc = iwl_send_rxon_timing(priv, vif); |
3090 | iwl_setup_rxon_timing(priv, vif); | ||
3091 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
3092 | sizeof(priv->rxon_timing), &priv->rxon_timing); | ||
3093 | if (rc) | 3098 | if (rc) |
3094 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3099 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3095 | "Attempting to continue.\n"); | 3100 | "Attempting to continue.\n"); |
@@ -3263,11 +3268,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3263 | iwlcore_commit_rxon(priv); | 3268 | iwlcore_commit_rxon(priv); |
3264 | 3269 | ||
3265 | /* RXON Timing */ | 3270 | /* RXON Timing */ |
3266 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | 3271 | rc = iwl_send_rxon_timing(priv, vif); |
3267 | iwl_setup_rxon_timing(priv, vif); | ||
3268 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
3269 | sizeof(priv->rxon_timing), | ||
3270 | &priv->rxon_timing); | ||
3271 | if (rc) | 3272 | if (rc) |
3272 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3273 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3273 | "Attempting to continue.\n"); | 3274 | "Attempting to continue.\n"); |
@@ -3785,10 +3786,8 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) | |||
3785 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); | 3786 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); |
3786 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); | 3787 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); |
3787 | INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); | 3788 | INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); |
3788 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); | 3789 | |
3789 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); | 3790 | iwl_setup_scan_deferred_work(priv); |
3790 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); | ||
3791 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | ||
3792 | 3791 | ||
3793 | iwl3945_hw_setup_deferred_work(priv); | 3792 | iwl3945_hw_setup_deferred_work(priv); |
3794 | 3793 | ||
@@ -3853,6 +3852,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
3853 | .hw_scan = iwl_mac_hw_scan, | 3852 | .hw_scan = iwl_mac_hw_scan, |
3854 | .sta_add = iwl3945_mac_sta_add, | 3853 | .sta_add = iwl3945_mac_sta_add, |
3855 | .sta_remove = iwl_mac_sta_remove, | 3854 | .sta_remove = iwl_mac_sta_remove, |
3855 | .tx_last_beacon = iwl_mac_tx_last_beacon, | ||
3856 | }; | 3856 | }; |
3857 | 3857 | ||
3858 | static int iwl3945_init_drv(struct iwl_priv *priv) | 3858 | static int iwl3945_init_drv(struct iwl_priv *priv) |
@@ -4009,6 +4009,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4009 | /*************************** | 4009 | /*************************** |
4010 | * 2. Initializing PCI bus | 4010 | * 2. Initializing PCI bus |
4011 | * *************************/ | 4011 | * *************************/ |
4012 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
4013 | PCIE_LINK_STATE_CLKPM); | ||
4014 | |||
4012 | if (pci_enable_device(pdev)) { | 4015 | if (pci_enable_device(pdev)) { |
4013 | err = -ENODEV; | 4016 | err = -ENODEV; |
4014 | goto out_ieee80211_free_hw; | 4017 | goto out_ieee80211_free_hw; |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index c02fcedea9fa..a944893ae3ca 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -1195,11 +1195,8 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, | |||
1195 | IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " | 1195 | IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " |
1196 | "oid is 0x%x\n", hdr->oid); | 1196 | "oid is 0x%x\n", hdr->oid); |
1197 | 1197 | ||
1198 | if (hdr->oid <= WIFI_IF_NTFY_MAX) { | 1198 | set_bit(hdr->oid, &iwm->wifi_ntfy[0]); |
1199 | set_bit(hdr->oid, &iwm->wifi_ntfy[0]); | 1199 | wake_up_interruptible(&iwm->wifi_ntfy_queue); |
1200 | wake_up_interruptible(&iwm->wifi_ntfy_queue); | ||
1201 | } else | ||
1202 | return -EINVAL; | ||
1203 | 1200 | ||
1204 | switch (hdr->oid) { | 1201 | switch (hdr->oid) { |
1205 | case UMAC_WIFI_IF_CMD_SET_PROFILE: | 1202 | case UMAC_WIFI_IF_CMD_SET_PROFILE: |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 3e82f1627209..317f086ced0a 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/wait.h> | 10 | #include <linux/wait.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/wait.h> | ||
13 | #include <linux/ieee80211.h> | 14 | #include <linux/ieee80211.h> |
14 | #include <net/cfg80211.h> | 15 | #include <net/cfg80211.h> |
15 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
@@ -526,20 +527,31 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
526 | 527 | ||
527 | pos = scanresp->bssdesc_and_tlvbuffer; | 528 | pos = scanresp->bssdesc_and_tlvbuffer; |
528 | 529 | ||
530 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_RSP", scanresp->bssdesc_and_tlvbuffer, | ||
531 | scanresp->bssdescriptsize); | ||
532 | |||
529 | tsfdesc = pos + bsssize; | 533 | tsfdesc = pos + bsssize; |
530 | tsfsize = 4 + 8 * scanresp->nr_sets; | 534 | tsfsize = 4 + 8 * scanresp->nr_sets; |
535 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TSF", (u8 *) tsfdesc, tsfsize); | ||
531 | 536 | ||
532 | /* Validity check: we expect a Marvell-Local TLV */ | 537 | /* Validity check: we expect a Marvell-Local TLV */ |
533 | i = get_unaligned_le16(tsfdesc); | 538 | i = get_unaligned_le16(tsfdesc); |
534 | tsfdesc += 2; | 539 | tsfdesc += 2; |
535 | if (i != TLV_TYPE_TSFTIMESTAMP) | 540 | if (i != TLV_TYPE_TSFTIMESTAMP) { |
541 | lbs_deb_scan("scan response: invalid TSF Timestamp %d\n", i); | ||
536 | goto done; | 542 | goto done; |
543 | } | ||
544 | |||
537 | /* Validity check: the TLV holds TSF values with 8 bytes each, so | 545 | /* Validity check: the TLV holds TSF values with 8 bytes each, so |
538 | * the size in the TLV must match the nr_sets value */ | 546 | * the size in the TLV must match the nr_sets value */ |
539 | i = get_unaligned_le16(tsfdesc); | 547 | i = get_unaligned_le16(tsfdesc); |
540 | tsfdesc += 2; | 548 | tsfdesc += 2; |
541 | if (i / 8 != scanresp->nr_sets) | 549 | if (i / 8 != scanresp->nr_sets) { |
550 | lbs_deb_scan("scan response: invalid number of TSF timestamp " | ||
551 | "sets (expected %d got %d)\n", scanresp->nr_sets, | ||
552 | i / 8); | ||
542 | goto done; | 553 | goto done; |
554 | } | ||
543 | 555 | ||
544 | for (i = 0; i < scanresp->nr_sets; i++) { | 556 | for (i = 0; i < scanresp->nr_sets; i++) { |
545 | const u8 *bssid; | 557 | const u8 *bssid; |
@@ -581,8 +593,11 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
581 | id = *pos++; | 593 | id = *pos++; |
582 | elen = *pos++; | 594 | elen = *pos++; |
583 | left -= 2; | 595 | left -= 2; |
584 | if (elen > left || elen == 0) | 596 | if (elen > left || elen == 0) { |
597 | lbs_deb_scan("scan response: invalid IE fmt\n"); | ||
585 | goto done; | 598 | goto done; |
599 | } | ||
600 | |||
586 | if (id == WLAN_EID_DS_PARAMS) | 601 | if (id == WLAN_EID_DS_PARAMS) |
587 | chan_no = *pos; | 602 | chan_no = *pos; |
588 | if (id == WLAN_EID_SSID) { | 603 | if (id == WLAN_EID_SSID) { |
@@ -613,7 +628,9 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
613 | capa, intvl, ie, ielen, | 628 | capa, intvl, ie, ielen, |
614 | LBS_SCAN_RSSI_TO_MBM(rssi), | 629 | LBS_SCAN_RSSI_TO_MBM(rssi), |
615 | GFP_KERNEL); | 630 | GFP_KERNEL); |
616 | } | 631 | } else |
632 | lbs_deb_scan("scan response: missing BSS channel IE\n"); | ||
633 | |||
617 | tsfdesc += 8; | 634 | tsfdesc += 8; |
618 | } | 635 | } |
619 | ret = 0; | 636 | ret = 0; |
@@ -1103,7 +1120,7 @@ static int lbs_associate(struct lbs_private *priv, | |||
1103 | lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp); | 1120 | lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp); |
1104 | 1121 | ||
1105 | /* add auth type TLV */ | 1122 | /* add auth type TLV */ |
1106 | if (priv->fwrelease >= 0x09000000) | 1123 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) >= 9) |
1107 | pos += lbs_add_auth_type_tlv(pos, sme->auth_type); | 1124 | pos += lbs_add_auth_type_tlv(pos, sme->auth_type); |
1108 | 1125 | ||
1109 | /* add WPA/WPA2 TLV */ | 1126 | /* add WPA/WPA2 TLV */ |
@@ -1114,6 +1131,9 @@ static int lbs_associate(struct lbs_private *priv, | |||
1114 | (u16)(pos - (u8 *) &cmd->iebuf); | 1131 | (u16)(pos - (u8 *) &cmd->iebuf); |
1115 | cmd->hdr.size = cpu_to_le16(len); | 1132 | cmd->hdr.size = cpu_to_le16(len); |
1116 | 1133 | ||
1134 | lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_CMD", (u8 *) cmd, | ||
1135 | le16_to_cpu(cmd->hdr.size)); | ||
1136 | |||
1117 | /* store for later use */ | 1137 | /* store for later use */ |
1118 | memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN); | 1138 | memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN); |
1119 | 1139 | ||
@@ -1121,14 +1141,28 @@ static int lbs_associate(struct lbs_private *priv, | |||
1121 | if (ret) | 1141 | if (ret) |
1122 | goto done; | 1142 | goto done; |
1123 | 1143 | ||
1124 | |||
1125 | /* generate connect message to cfg80211 */ | 1144 | /* generate connect message to cfg80211 */ |
1126 | 1145 | ||
1127 | resp = (void *) cmd; /* recast for easier field access */ | 1146 | resp = (void *) cmd; /* recast for easier field access */ |
1128 | status = le16_to_cpu(resp->statuscode); | 1147 | status = le16_to_cpu(resp->statuscode); |
1129 | 1148 | ||
1130 | /* Convert statis code of old firmware */ | 1149 | /* Older FW versions map the IEEE 802.11 Status Code in the association |
1131 | if (priv->fwrelease < 0x09000000) | 1150 | * response to the following values returned in resp->statuscode: |
1151 | * | ||
1152 | * IEEE Status Code Marvell Status Code | ||
1153 | * 0 -> 0x0000 ASSOC_RESULT_SUCCESS | ||
1154 | * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1155 | * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1156 | * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1157 | * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1158 | * others -> 0x0003 ASSOC_RESULT_REFUSED | ||
1159 | * | ||
1160 | * Other response codes: | ||
1161 | * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) | ||
1162 | * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for | ||
1163 | * association response from the AP) | ||
1164 | */ | ||
1165 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) { | ||
1132 | switch (status) { | 1166 | switch (status) { |
1133 | case 0: | 1167 | case 0: |
1134 | break; | 1168 | break; |
@@ -1150,11 +1184,16 @@ static int lbs_associate(struct lbs_private *priv, | |||
1150 | break; | 1184 | break; |
1151 | default: | 1185 | default: |
1152 | lbs_deb_assoc("association failure %d\n", status); | 1186 | lbs_deb_assoc("association failure %d\n", status); |
1153 | status = WLAN_STATUS_UNSPECIFIED_FAILURE; | 1187 | /* v5 OLPC firmware does return the AP status code if |
1188 | * it's not one of the values above. Let that through. | ||
1189 | */ | ||
1190 | break; | ||
1191 | } | ||
1154 | } | 1192 | } |
1155 | 1193 | ||
1156 | lbs_deb_assoc("status %d, capability 0x%04x\n", status, | 1194 | lbs_deb_assoc("status %d, statuscode 0x%04x, capability 0x%04x, " |
1157 | le16_to_cpu(resp->capability)); | 1195 | "aid 0x%04x\n", status, le16_to_cpu(resp->statuscode), |
1196 | le16_to_cpu(resp->capability), le16_to_cpu(resp->aid)); | ||
1158 | 1197 | ||
1159 | resp_ie_len = le16_to_cpu(resp->hdr.size) | 1198 | resp_ie_len = le16_to_cpu(resp->hdr.size) |
1160 | - sizeof(resp->hdr) | 1199 | - sizeof(resp->hdr) |
@@ -1174,7 +1213,6 @@ static int lbs_associate(struct lbs_private *priv, | |||
1174 | netif_tx_wake_all_queues(priv->dev); | 1213 | netif_tx_wake_all_queues(priv->dev); |
1175 | } | 1214 | } |
1176 | 1215 | ||
1177 | |||
1178 | done: | 1216 | done: |
1179 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | 1217 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); |
1180 | return ret; | 1218 | return ret; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 1d141fefd767..2ae752d10065 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -8,7 +8,14 @@ | |||
8 | #define _LBS_DECL_H_ | 8 | #define _LBS_DECL_H_ |
9 | 9 | ||
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/firmware.h> | ||
11 | 12 | ||
13 | /* Should be terminated by a NULL entry */ | ||
14 | struct lbs_fw_table { | ||
15 | int model; | ||
16 | const char *helper; | ||
17 | const char *fwname; | ||
18 | }; | ||
12 | 19 | ||
13 | struct lbs_private; | 20 | struct lbs_private; |
14 | struct sk_buff; | 21 | struct sk_buff; |
@@ -53,4 +60,10 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | |||
53 | u32 lbs_fw_index_to_data_rate(u8 index); | 60 | u32 lbs_fw_index_to_data_rate(u8 index); |
54 | u8 lbs_data_rate_to_fw_index(u32 rate); | 61 | u8 lbs_data_rate_to_fw_index(u32 rate); |
55 | 62 | ||
63 | int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
64 | const char *user_mainfw, u32 card_model, | ||
65 | const struct lbs_fw_table *fw_table, | ||
66 | const struct firmware **helper, | ||
67 | const struct firmware **mainfw); | ||
68 | |||
56 | #endif | 69 | #endif |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 9c298396be50..e213a5dc049d 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -48,7 +48,6 @@ | |||
48 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); | 48 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); |
49 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); | 49 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); |
50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
51 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
52 | 51 | ||
53 | 52 | ||
54 | 53 | ||
@@ -61,9 +60,34 @@ struct if_cs_card { | |||
61 | struct lbs_private *priv; | 60 | struct lbs_private *priv; |
62 | void __iomem *iobase; | 61 | void __iomem *iobase; |
63 | bool align_regs; | 62 | bool align_regs; |
63 | u32 model; | ||
64 | }; | 64 | }; |
65 | 65 | ||
66 | 66 | ||
67 | enum { | ||
68 | MODEL_UNKNOWN = 0x00, | ||
69 | MODEL_8305 = 0x01, | ||
70 | MODEL_8381 = 0x02, | ||
71 | MODEL_8385 = 0x03 | ||
72 | }; | ||
73 | |||
74 | static const struct lbs_fw_table fw_table[] = { | ||
75 | { MODEL_8305, "libertas/cf8305.bin", NULL }, | ||
76 | { MODEL_8305, "libertas_cs_helper.fw", NULL }, | ||
77 | { MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" }, | ||
78 | { MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" }, | ||
79 | { MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" }, | ||
80 | { MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" }, | ||
81 | { 0, NULL, NULL } | ||
82 | }; | ||
83 | MODULE_FIRMWARE("libertas/cf8305.bin"); | ||
84 | MODULE_FIRMWARE("libertas/cf8381_helper.bin"); | ||
85 | MODULE_FIRMWARE("libertas/cf8381.bin"); | ||
86 | MODULE_FIRMWARE("libertas/cf8385_helper.bin"); | ||
87 | MODULE_FIRMWARE("libertas/cf8385.bin"); | ||
88 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
89 | MODULE_FIRMWARE("libertas_cs.fw"); | ||
90 | |||
67 | 91 | ||
68 | /********************************************************************/ | 92 | /********************************************************************/ |
69 | /* Hardware access */ | 93 | /* Hardware access */ |
@@ -289,22 +313,19 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
289 | #define CF8385_MANFID 0x02df | 313 | #define CF8385_MANFID 0x02df |
290 | #define CF8385_CARDID 0x8103 | 314 | #define CF8385_CARDID 0x8103 |
291 | 315 | ||
292 | static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev) | 316 | /* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when |
293 | { | 317 | * that gets fixed. Currently there's no way to access it from the probe hook. |
294 | return (p_dev->manf_id == CF8305_MANFID && | 318 | */ |
295 | p_dev->card_id == CF8305_CARDID); | 319 | static inline u32 get_model(u16 manf_id, u16 card_id) |
296 | } | ||
297 | |||
298 | static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) | ||
299 | { | ||
300 | return (p_dev->manf_id == CF8381_MANFID && | ||
301 | p_dev->card_id == CF8381_CARDID); | ||
302 | } | ||
303 | |||
304 | static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev) | ||
305 | { | 320 | { |
306 | return (p_dev->manf_id == CF8385_MANFID && | 321 | /* NOTE: keep in sync with if_cs_ids */ |
307 | p_dev->card_id == CF8385_CARDID); | 322 | if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID) |
323 | return MODEL_8305; | ||
324 | else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID) | ||
325 | return MODEL_8381; | ||
326 | else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID) | ||
327 | return MODEL_8385; | ||
328 | return MODEL_UNKNOWN; | ||
308 | } | 329 | } |
309 | 330 | ||
310 | /********************************************************************/ | 331 | /********************************************************************/ |
@@ -558,12 +579,11 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) | |||
558 | * | 579 | * |
559 | * Return 0 on success | 580 | * Return 0 on success |
560 | */ | 581 | */ |
561 | static int if_cs_prog_helper(struct if_cs_card *card) | 582 | static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) |
562 | { | 583 | { |
563 | int ret = 0; | 584 | int ret = 0; |
564 | int sent = 0; | 585 | int sent = 0; |
565 | u8 scratch; | 586 | u8 scratch; |
566 | const struct firmware *fw; | ||
567 | 587 | ||
568 | lbs_deb_enter(LBS_DEB_CS); | 588 | lbs_deb_enter(LBS_DEB_CS); |
569 | 589 | ||
@@ -589,14 +609,6 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
589 | goto done; | 609 | goto done; |
590 | } | 610 | } |
591 | 611 | ||
592 | /* TODO: make firmware file configurable */ | ||
593 | ret = request_firmware(&fw, "libertas_cs_helper.fw", | ||
594 | &card->p_dev->dev); | ||
595 | if (ret) { | ||
596 | lbs_pr_err("can't load helper firmware\n"); | ||
597 | ret = -ENODEV; | ||
598 | goto done; | ||
599 | } | ||
600 | lbs_deb_cs("helper size %td\n", fw->size); | 612 | lbs_deb_cs("helper size %td\n", fw->size); |
601 | 613 | ||
602 | /* "Set the 5 bytes of the helper image to 0" */ | 614 | /* "Set the 5 bytes of the helper image to 0" */ |
@@ -635,7 +647,7 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
635 | if (ret < 0) { | 647 | if (ret < 0) { |
636 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", | 648 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", |
637 | sent, ret); | 649 | sent, ret); |
638 | goto err_release; | 650 | goto done; |
639 | } | 651 | } |
640 | 652 | ||
641 | if (count == 0) | 653 | if (count == 0) |
@@ -644,17 +656,14 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
644 | sent += count; | 656 | sent += count; |
645 | } | 657 | } |
646 | 658 | ||
647 | err_release: | ||
648 | release_firmware(fw); | ||
649 | done: | 659 | done: |
650 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 660 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
651 | return ret; | 661 | return ret; |
652 | } | 662 | } |
653 | 663 | ||
654 | 664 | ||
655 | static int if_cs_prog_real(struct if_cs_card *card) | 665 | static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) |
656 | { | 666 | { |
657 | const struct firmware *fw; | ||
658 | int ret = 0; | 667 | int ret = 0; |
659 | int retry = 0; | 668 | int retry = 0; |
660 | int len = 0; | 669 | int len = 0; |
@@ -662,21 +671,13 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
662 | 671 | ||
663 | lbs_deb_enter(LBS_DEB_CS); | 672 | lbs_deb_enter(LBS_DEB_CS); |
664 | 673 | ||
665 | /* TODO: make firmware file configurable */ | ||
666 | ret = request_firmware(&fw, "libertas_cs.fw", | ||
667 | &card->p_dev->dev); | ||
668 | if (ret) { | ||
669 | lbs_pr_err("can't load firmware\n"); | ||
670 | ret = -ENODEV; | ||
671 | goto done; | ||
672 | } | ||
673 | lbs_deb_cs("fw size %td\n", fw->size); | 674 | lbs_deb_cs("fw size %td\n", fw->size); |
674 | 675 | ||
675 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, | 676 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, |
676 | IF_CS_SQ_HELPER_OK); | 677 | IF_CS_SQ_HELPER_OK); |
677 | if (ret < 0) { | 678 | if (ret < 0) { |
678 | lbs_pr_err("helper firmware doesn't answer\n"); | 679 | lbs_pr_err("helper firmware doesn't answer\n"); |
679 | goto err_release; | 680 | goto done; |
680 | } | 681 | } |
681 | 682 | ||
682 | for (sent = 0; sent < fw->size; sent += len) { | 683 | for (sent = 0; sent < fw->size; sent += len) { |
@@ -691,7 +692,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
691 | if (retry > 20) { | 692 | if (retry > 20) { |
692 | lbs_pr_err("could not download firmware\n"); | 693 | lbs_pr_err("could not download firmware\n"); |
693 | ret = -ENODEV; | 694 | ret = -ENODEV; |
694 | goto err_release; | 695 | goto done; |
695 | } | 696 | } |
696 | if (retry) { | 697 | if (retry) { |
697 | sent -= len; | 698 | sent -= len; |
@@ -710,7 +711,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
710 | IF_CS_BIT_COMMAND); | 711 | IF_CS_BIT_COMMAND); |
711 | if (ret < 0) { | 712 | if (ret < 0) { |
712 | lbs_pr_err("can't download firmware at 0x%x\n", sent); | 713 | lbs_pr_err("can't download firmware at 0x%x\n", sent); |
713 | goto err_release; | 714 | goto done; |
714 | } | 715 | } |
715 | } | 716 | } |
716 | 717 | ||
@@ -718,9 +719,6 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
718 | if (ret < 0) | 719 | if (ret < 0) |
719 | lbs_pr_err("firmware download failed\n"); | 720 | lbs_pr_err("firmware download failed\n"); |
720 | 721 | ||
721 | err_release: | ||
722 | release_firmware(fw); | ||
723 | |||
724 | done: | 722 | done: |
725 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 723 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
726 | return ret; | 724 | return ret; |
@@ -824,6 +822,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
824 | unsigned int prod_id; | 822 | unsigned int prod_id; |
825 | struct lbs_private *priv; | 823 | struct lbs_private *priv; |
826 | struct if_cs_card *card; | 824 | struct if_cs_card *card; |
825 | const struct firmware *helper = NULL; | ||
826 | const struct firmware *mainfw = NULL; | ||
827 | 827 | ||
828 | lbs_deb_enter(LBS_DEB_CS); | 828 | lbs_deb_enter(LBS_DEB_CS); |
829 | 829 | ||
@@ -843,7 +843,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
843 | goto out1; | 843 | goto out1; |
844 | } | 844 | } |
845 | 845 | ||
846 | |||
847 | /* | 846 | /* |
848 | * Allocate an interrupt line. Note that this does not assign | 847 | * Allocate an interrupt line. Note that this does not assign |
849 | * a handler to the interrupt, unless the 'Handler' member of | 848 | * a handler to the interrupt, unless the 'Handler' member of |
@@ -881,34 +880,47 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
881 | */ | 880 | */ |
882 | card->align_regs = 0; | 881 | card->align_regs = 0; |
883 | 882 | ||
883 | card->model = get_model(p_dev->manf_id, p_dev->card_id); | ||
884 | if (card->model == MODEL_UNKNOWN) { | ||
885 | lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", | ||
886 | p_dev->manf_id, p_dev->card_id); | ||
887 | goto out2; | ||
888 | } | ||
889 | |||
884 | /* Check if we have a current silicon */ | 890 | /* Check if we have a current silicon */ |
885 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); | 891 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); |
886 | if (if_cs_hw_is_cf8305(p_dev)) { | 892 | if (card->model == MODEL_8305) { |
887 | card->align_regs = 1; | 893 | card->align_regs = 1; |
888 | if (prod_id < IF_CS_CF8305_B1_REV) { | 894 | if (prod_id < IF_CS_CF8305_B1_REV) { |
889 | lbs_pr_err("old chips like 8305 rev B3 " | 895 | lbs_pr_err("8305 rev B0 and older are not supported\n"); |
890 | "aren't supported\n"); | ||
891 | ret = -ENODEV; | 896 | ret = -ENODEV; |
892 | goto out2; | 897 | goto out2; |
893 | } | 898 | } |
894 | } | 899 | } |
895 | 900 | ||
896 | if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { | 901 | if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) { |
897 | lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); | 902 | lbs_pr_err("8381 rev B2 and older are not supported\n"); |
898 | ret = -ENODEV; | 903 | ret = -ENODEV; |
899 | goto out2; | 904 | goto out2; |
900 | } | 905 | } |
901 | 906 | ||
902 | if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) { | 907 | if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) { |
903 | lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); | 908 | lbs_pr_err("8385 rev B0 and older are not supported\n"); |
904 | ret = -ENODEV; | 909 | ret = -ENODEV; |
905 | goto out2; | 910 | goto out2; |
906 | } | 911 | } |
907 | 912 | ||
913 | ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, | ||
914 | &fw_table[0], &helper, &mainfw); | ||
915 | if (ret) { | ||
916 | lbs_pr_err("failed to find firmware (%d)\n", ret); | ||
917 | goto out2; | ||
918 | } | ||
919 | |||
908 | /* Load the firmware early, before calling into libertas.ko */ | 920 | /* Load the firmware early, before calling into libertas.ko */ |
909 | ret = if_cs_prog_helper(card); | 921 | ret = if_cs_prog_helper(card, helper); |
910 | if (ret == 0 && !if_cs_hw_is_cf8305(p_dev)) | 922 | if (ret == 0 && (card->model != MODEL_8305)) |
911 | ret = if_cs_prog_real(card); | 923 | ret = if_cs_prog_real(card, mainfw); |
912 | if (ret) | 924 | if (ret) |
913 | goto out2; | 925 | goto out2; |
914 | 926 | ||
@@ -957,6 +969,11 @@ out2: | |||
957 | out1: | 969 | out1: |
958 | pcmcia_disable_device(p_dev); | 970 | pcmcia_disable_device(p_dev); |
959 | out: | 971 | out: |
972 | if (helper) | ||
973 | release_firmware(helper); | ||
974 | if (mainfw) | ||
975 | release_firmware(mainfw); | ||
976 | |||
960 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 977 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
961 | return ret; | 978 | return ret; |
962 | } | 979 | } |
@@ -993,6 +1010,7 @@ static struct pcmcia_device_id if_cs_ids[] = { | |||
993 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), | 1010 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), |
994 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), | 1011 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), |
995 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), | 1012 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), |
1013 | /* NOTE: keep in sync with get_model() */ | ||
996 | PCMCIA_DEVICE_NULL, | 1014 | PCMCIA_DEVICE_NULL, |
997 | }; | 1015 | }; |
998 | MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); | 1016 | MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index ba854c70ab94..1bbaaa44d981 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -76,36 +76,32 @@ static const struct sdio_device_id if_sdio_ids[] = { | |||
76 | 76 | ||
77 | MODULE_DEVICE_TABLE(sdio, if_sdio_ids); | 77 | MODULE_DEVICE_TABLE(sdio, if_sdio_ids); |
78 | 78 | ||
79 | struct if_sdio_model { | 79 | #define MODEL_8385 0x04 |
80 | int model; | 80 | #define MODEL_8686 0x0b |
81 | const char *helper; | 81 | #define MODEL_8688 0x10 |
82 | const char *firmware; | 82 | |
83 | }; | 83 | static const struct lbs_fw_table fw_table[] = { |
84 | 84 | { MODEL_8385, "libertas/sd8385_helper.bin", "libertas/sd8385.bin" }, | |
85 | static struct if_sdio_model if_sdio_models[] = { | 85 | { MODEL_8385, "sd8385_helper.bin", "sd8385.bin" }, |
86 | { | 86 | { MODEL_8686, "libertas/sd8686_v9_helper.bin", "libertas/sd8686_v9.bin" }, |
87 | /* 8385 */ | 87 | { MODEL_8686, "libertas/sd8686_v8_helper.bin", "libertas/sd8686_v8.bin" }, |
88 | .model = IF_SDIO_MODEL_8385, | 88 | { MODEL_8686, "sd8686_helper.bin", "sd8686.bin" }, |
89 | .helper = "sd8385_helper.bin", | 89 | { MODEL_8688, "libertas/sd8688_helper.bin", "libertas/sd8688.bin" }, |
90 | .firmware = "sd8385.bin", | 90 | { MODEL_8688, "sd8688_helper.bin", "sd8688.bin" }, |
91 | }, | 91 | { 0, NULL, NULL } |
92 | { | ||
93 | /* 8686 */ | ||
94 | .model = IF_SDIO_MODEL_8686, | ||
95 | .helper = "sd8686_helper.bin", | ||
96 | .firmware = "sd8686.bin", | ||
97 | }, | ||
98 | { | ||
99 | /* 8688 */ | ||
100 | .model = IF_SDIO_MODEL_8688, | ||
101 | .helper = "sd8688_helper.bin", | ||
102 | .firmware = "sd8688.bin", | ||
103 | }, | ||
104 | }; | 92 | }; |
93 | MODULE_FIRMWARE("libertas/sd8385_helper.bin"); | ||
94 | MODULE_FIRMWARE("libertas/sd8385.bin"); | ||
105 | MODULE_FIRMWARE("sd8385_helper.bin"); | 95 | MODULE_FIRMWARE("sd8385_helper.bin"); |
106 | MODULE_FIRMWARE("sd8385.bin"); | 96 | MODULE_FIRMWARE("sd8385.bin"); |
97 | MODULE_FIRMWARE("libertas/sd8686_v9_helper.bin"); | ||
98 | MODULE_FIRMWARE("libertas/sd8686_v9.bin"); | ||
99 | MODULE_FIRMWARE("libertas/sd8686_v8_helper.bin"); | ||
100 | MODULE_FIRMWARE("libertas/sd8686_v8.bin"); | ||
107 | MODULE_FIRMWARE("sd8686_helper.bin"); | 101 | MODULE_FIRMWARE("sd8686_helper.bin"); |
108 | MODULE_FIRMWARE("sd8686.bin"); | 102 | MODULE_FIRMWARE("sd8686.bin"); |
103 | MODULE_FIRMWARE("libertas/sd8688_helper.bin"); | ||
104 | MODULE_FIRMWARE("libertas/sd8688.bin"); | ||
109 | MODULE_FIRMWARE("sd8688_helper.bin"); | 105 | MODULE_FIRMWARE("sd8688_helper.bin"); |
110 | MODULE_FIRMWARE("sd8688.bin"); | 106 | MODULE_FIRMWARE("sd8688.bin"); |
111 | 107 | ||
@@ -187,11 +183,11 @@ static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err) | |||
187 | u16 rx_len; | 183 | u16 rx_len; |
188 | 184 | ||
189 | switch (card->model) { | 185 | switch (card->model) { |
190 | case IF_SDIO_MODEL_8385: | 186 | case MODEL_8385: |
191 | case IF_SDIO_MODEL_8686: | 187 | case MODEL_8686: |
192 | rx_len = if_sdio_read_scratch(card, &ret); | 188 | rx_len = if_sdio_read_scratch(card, &ret); |
193 | break; | 189 | break; |
194 | case IF_SDIO_MODEL_8688: | 190 | case MODEL_8688: |
195 | default: /* for newer chipsets */ | 191 | default: /* for newer chipsets */ |
196 | rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); | 192 | rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); |
197 | if (!ret) | 193 | if (!ret) |
@@ -288,7 +284,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card, | |||
288 | 284 | ||
289 | lbs_deb_enter(LBS_DEB_SDIO); | 285 | lbs_deb_enter(LBS_DEB_SDIO); |
290 | 286 | ||
291 | if (card->model == IF_SDIO_MODEL_8385) { | 287 | if (card->model == MODEL_8385) { |
292 | event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); | 288 | event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); |
293 | if (ret) | 289 | if (ret) |
294 | goto out; | 290 | goto out; |
@@ -466,10 +462,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) | |||
466 | 462 | ||
467 | #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) | 463 | #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) |
468 | 464 | ||
469 | static int if_sdio_prog_helper(struct if_sdio_card *card) | 465 | static int if_sdio_prog_helper(struct if_sdio_card *card, |
466 | const struct firmware *fw) | ||
470 | { | 467 | { |
471 | int ret; | 468 | int ret; |
472 | const struct firmware *fw; | ||
473 | unsigned long timeout; | 469 | unsigned long timeout; |
474 | u8 *chunk_buffer; | 470 | u8 *chunk_buffer; |
475 | u32 chunk_size; | 471 | u32 chunk_size; |
@@ -478,16 +474,10 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
478 | 474 | ||
479 | lbs_deb_enter(LBS_DEB_SDIO); | 475 | lbs_deb_enter(LBS_DEB_SDIO); |
480 | 476 | ||
481 | ret = request_firmware(&fw, card->helper, &card->func->dev); | ||
482 | if (ret) { | ||
483 | lbs_pr_err("can't load helper firmware\n"); | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | chunk_buffer = kzalloc(64, GFP_KERNEL); | 477 | chunk_buffer = kzalloc(64, GFP_KERNEL); |
488 | if (!chunk_buffer) { | 478 | if (!chunk_buffer) { |
489 | ret = -ENOMEM; | 479 | ret = -ENOMEM; |
490 | goto release_fw; | 480 | goto out; |
491 | } | 481 | } |
492 | 482 | ||
493 | sdio_claim_host(card->func); | 483 | sdio_claim_host(card->func); |
@@ -562,22 +552,19 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
562 | release: | 552 | release: |
563 | sdio_release_host(card->func); | 553 | sdio_release_host(card->func); |
564 | kfree(chunk_buffer); | 554 | kfree(chunk_buffer); |
565 | release_fw: | ||
566 | release_firmware(fw); | ||
567 | 555 | ||
568 | out: | 556 | out: |
569 | if (ret) | 557 | if (ret) |
570 | lbs_pr_err("failed to load helper firmware\n"); | 558 | lbs_pr_err("failed to load helper firmware\n"); |
571 | 559 | ||
572 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 560 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
573 | |||
574 | return ret; | 561 | return ret; |
575 | } | 562 | } |
576 | 563 | ||
577 | static int if_sdio_prog_real(struct if_sdio_card *card) | 564 | static int if_sdio_prog_real(struct if_sdio_card *card, |
565 | const struct firmware *fw) | ||
578 | { | 566 | { |
579 | int ret; | 567 | int ret; |
580 | const struct firmware *fw; | ||
581 | unsigned long timeout; | 568 | unsigned long timeout; |
582 | u8 *chunk_buffer; | 569 | u8 *chunk_buffer; |
583 | u32 chunk_size; | 570 | u32 chunk_size; |
@@ -586,16 +573,10 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
586 | 573 | ||
587 | lbs_deb_enter(LBS_DEB_SDIO); | 574 | lbs_deb_enter(LBS_DEB_SDIO); |
588 | 575 | ||
589 | ret = request_firmware(&fw, card->firmware, &card->func->dev); | ||
590 | if (ret) { | ||
591 | lbs_pr_err("can't load firmware\n"); | ||
592 | goto out; | ||
593 | } | ||
594 | |||
595 | chunk_buffer = kzalloc(512, GFP_KERNEL); | 576 | chunk_buffer = kzalloc(512, GFP_KERNEL); |
596 | if (!chunk_buffer) { | 577 | if (!chunk_buffer) { |
597 | ret = -ENOMEM; | 578 | ret = -ENOMEM; |
598 | goto release_fw; | 579 | goto out; |
599 | } | 580 | } |
600 | 581 | ||
601 | sdio_claim_host(card->func); | 582 | sdio_claim_host(card->func); |
@@ -685,15 +666,12 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
685 | release: | 666 | release: |
686 | sdio_release_host(card->func); | 667 | sdio_release_host(card->func); |
687 | kfree(chunk_buffer); | 668 | kfree(chunk_buffer); |
688 | release_fw: | ||
689 | release_firmware(fw); | ||
690 | 669 | ||
691 | out: | 670 | out: |
692 | if (ret) | 671 | if (ret) |
693 | lbs_pr_err("failed to load firmware\n"); | 672 | lbs_pr_err("failed to load firmware\n"); |
694 | 673 | ||
695 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 674 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
696 | |||
697 | return ret; | 675 | return ret; |
698 | } | 676 | } |
699 | 677 | ||
@@ -701,6 +679,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
701 | { | 679 | { |
702 | int ret; | 680 | int ret; |
703 | u16 scratch; | 681 | u16 scratch; |
682 | const struct firmware *helper = NULL; | ||
683 | const struct firmware *mainfw = NULL; | ||
704 | 684 | ||
705 | lbs_deb_enter(LBS_DEB_SDIO); | 685 | lbs_deb_enter(LBS_DEB_SDIO); |
706 | 686 | ||
@@ -718,11 +698,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
718 | goto success; | 698 | goto success; |
719 | } | 699 | } |
720 | 700 | ||
721 | ret = if_sdio_prog_helper(card); | 701 | ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, |
702 | card->model, &fw_table[0], &helper, &mainfw); | ||
703 | if (ret) { | ||
704 | lbs_pr_err("failed to find firmware (%d)\n", ret); | ||
705 | goto out; | ||
706 | } | ||
707 | |||
708 | ret = if_sdio_prog_helper(card, helper); | ||
722 | if (ret) | 709 | if (ret) |
723 | goto out; | 710 | goto out; |
724 | 711 | ||
725 | ret = if_sdio_prog_real(card); | 712 | ret = if_sdio_prog_real(card, mainfw); |
726 | if (ret) | 713 | if (ret) |
727 | goto out; | 714 | goto out; |
728 | 715 | ||
@@ -733,8 +720,12 @@ success: | |||
733 | ret = 0; | 720 | ret = 0; |
734 | 721 | ||
735 | out: | 722 | out: |
736 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 723 | if (helper) |
724 | release_firmware(helper); | ||
725 | if (mainfw) | ||
726 | release_firmware(mainfw); | ||
737 | 727 | ||
728 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
738 | return ret; | 729 | return ret; |
739 | } | 730 | } |
740 | 731 | ||
@@ -938,7 +929,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
938 | "ID: %x", &model) == 1) | 929 | "ID: %x", &model) == 1) |
939 | break; | 930 | break; |
940 | if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { | 931 | if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { |
941 | model = IF_SDIO_MODEL_8385; | 932 | model = MODEL_8385; |
942 | break; | 933 | break; |
943 | } | 934 | } |
944 | } | 935 | } |
@@ -956,13 +947,13 @@ static int if_sdio_probe(struct sdio_func *func, | |||
956 | card->model = model; | 947 | card->model = model; |
957 | 948 | ||
958 | switch (card->model) { | 949 | switch (card->model) { |
959 | case IF_SDIO_MODEL_8385: | 950 | case MODEL_8385: |
960 | card->scratch_reg = IF_SDIO_SCRATCH_OLD; | 951 | card->scratch_reg = IF_SDIO_SCRATCH_OLD; |
961 | break; | 952 | break; |
962 | case IF_SDIO_MODEL_8686: | 953 | case MODEL_8686: |
963 | card->scratch_reg = IF_SDIO_SCRATCH; | 954 | card->scratch_reg = IF_SDIO_SCRATCH; |
964 | break; | 955 | break; |
965 | case IF_SDIO_MODEL_8688: | 956 | case MODEL_8688: |
966 | default: /* for newer chipsets */ | 957 | default: /* for newer chipsets */ |
967 | card->scratch_reg = IF_SDIO_FW_STATUS; | 958 | card->scratch_reg = IF_SDIO_FW_STATUS; |
968 | break; | 959 | break; |
@@ -972,49 +963,17 @@ static int if_sdio_probe(struct sdio_func *func, | |||
972 | card->workqueue = create_workqueue("libertas_sdio"); | 963 | card->workqueue = create_workqueue("libertas_sdio"); |
973 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); | 964 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); |
974 | 965 | ||
975 | for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) { | 966 | /* Check if we support this card */ |
976 | if (card->model == if_sdio_models[i].model) | 967 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
968 | if (card->model == fw_table[i].model) | ||
977 | break; | 969 | break; |
978 | } | 970 | } |
979 | 971 | if (i == ARRAY_SIZE(fw_table)) { | |
980 | if (i == ARRAY_SIZE(if_sdio_models)) { | ||
981 | lbs_pr_err("unknown card model 0x%x\n", card->model); | 972 | lbs_pr_err("unknown card model 0x%x\n", card->model); |
982 | ret = -ENODEV; | 973 | ret = -ENODEV; |
983 | goto free; | 974 | goto free; |
984 | } | 975 | } |
985 | 976 | ||
986 | card->helper = if_sdio_models[i].helper; | ||
987 | card->firmware = if_sdio_models[i].firmware; | ||
988 | |||
989 | kparam_block_sysfs_write(helper_name); | ||
990 | if (lbs_helper_name) { | ||
991 | char *helper = kstrdup(lbs_helper_name, GFP_KERNEL); | ||
992 | if (!helper) { | ||
993 | kparam_unblock_sysfs_write(helper_name); | ||
994 | ret = -ENOMEM; | ||
995 | goto free; | ||
996 | } | ||
997 | lbs_deb_sdio("overriding helper firmware: %s\n", | ||
998 | lbs_helper_name); | ||
999 | card->helper = helper; | ||
1000 | card->helper_allocated = true; | ||
1001 | } | ||
1002 | kparam_unblock_sysfs_write(helper_name); | ||
1003 | |||
1004 | kparam_block_sysfs_write(fw_name); | ||
1005 | if (lbs_fw_name) { | ||
1006 | char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL); | ||
1007 | if (!fw_name) { | ||
1008 | kparam_unblock_sysfs_write(fw_name); | ||
1009 | ret = -ENOMEM; | ||
1010 | goto free; | ||
1011 | } | ||
1012 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); | ||
1013 | card->firmware = fw_name; | ||
1014 | card->firmware_allocated = true; | ||
1015 | } | ||
1016 | kparam_unblock_sysfs_write(fw_name); | ||
1017 | |||
1018 | sdio_claim_host(func); | 977 | sdio_claim_host(func); |
1019 | 978 | ||
1020 | ret = sdio_enable_func(func); | 979 | ret = sdio_enable_func(func); |
@@ -1028,7 +987,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1028 | /* For 1-bit transfers to the 8686 model, we need to enable the | 987 | /* For 1-bit transfers to the 8686 model, we need to enable the |
1029 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | 988 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 |
1030 | * bit to allow access to non-vendor registers. */ | 989 | * bit to allow access to non-vendor registers. */ |
1031 | if ((card->model == IF_SDIO_MODEL_8686) && | 990 | if ((card->model == MODEL_8686) && |
1032 | (host->caps & MMC_CAP_SDIO_IRQ) && | 991 | (host->caps & MMC_CAP_SDIO_IRQ) && |
1033 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | 992 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { |
1034 | u8 reg; | 993 | u8 reg; |
@@ -1091,8 +1050,8 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1091 | * Get rx_unit if the chip is SD8688 or newer. | 1050 | * Get rx_unit if the chip is SD8688 or newer. |
1092 | * SD8385 & SD8686 do not have rx_unit. | 1051 | * SD8385 & SD8686 do not have rx_unit. |
1093 | */ | 1052 | */ |
1094 | if ((card->model != IF_SDIO_MODEL_8385) | 1053 | if ((card->model != MODEL_8385) |
1095 | && (card->model != IF_SDIO_MODEL_8686)) | 1054 | && (card->model != MODEL_8686)) |
1096 | card->rx_unit = if_sdio_read_rx_unit(card); | 1055 | card->rx_unit = if_sdio_read_rx_unit(card); |
1097 | else | 1056 | else |
1098 | card->rx_unit = 0; | 1057 | card->rx_unit = 0; |
@@ -1108,7 +1067,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1108 | /* | 1067 | /* |
1109 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions | 1068 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions |
1110 | */ | 1069 | */ |
1111 | if (card->model == IF_SDIO_MODEL_8688) { | 1070 | if (card->model == MODEL_8688) { |
1112 | struct cmd_header cmd; | 1071 | struct cmd_header cmd; |
1113 | 1072 | ||
1114 | memset(&cmd, 0, sizeof(cmd)); | 1073 | memset(&cmd, 0, sizeof(cmd)); |
@@ -1165,7 +1124,7 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1165 | 1124 | ||
1166 | card = sdio_get_drvdata(func); | 1125 | card = sdio_get_drvdata(func); |
1167 | 1126 | ||
1168 | if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) { | 1127 | if (user_rmmod && (card->model == MODEL_8688)) { |
1169 | /* | 1128 | /* |
1170 | * FUNC_SHUTDOWN is required for SD8688 WLAN/BT | 1129 | * FUNC_SHUTDOWN is required for SD8688 WLAN/BT |
1171 | * multiple functions | 1130 | * multiple functions |
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 12179c1dc9c9..62fda3592f67 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h | |||
@@ -12,10 +12,6 @@ | |||
12 | #ifndef _LBS_IF_SDIO_H | 12 | #ifndef _LBS_IF_SDIO_H |
13 | #define _LBS_IF_SDIO_H | 13 | #define _LBS_IF_SDIO_H |
14 | 14 | ||
15 | #define IF_SDIO_MODEL_8385 0x04 | ||
16 | #define IF_SDIO_MODEL_8686 0x0b | ||
17 | #define IF_SDIO_MODEL_8688 0x10 | ||
18 | |||
19 | #define IF_SDIO_IOPORT 0x00 | 15 | #define IF_SDIO_IOPORT 0x00 |
20 | 16 | ||
21 | #define IF_SDIO_H_INT_MASK 0x04 | 17 | #define IF_SDIO_H_INT_MASK 0x04 |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index fe3f08028eb3..79bcb4e5d2ca 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -39,9 +39,6 @@ struct if_spi_card { | |||
39 | struct lbs_private *priv; | 39 | struct lbs_private *priv; |
40 | struct libertas_spi_platform_data *pdata; | 40 | struct libertas_spi_platform_data *pdata; |
41 | 41 | ||
42 | char helper_fw_name[IF_SPI_FW_NAME_MAX]; | ||
43 | char main_fw_name[IF_SPI_FW_NAME_MAX]; | ||
44 | |||
45 | /* The card ID and card revision, as reported by the hardware. */ | 42 | /* The card ID and card revision, as reported by the hardware. */ |
46 | u16 card_id; | 43 | u16 card_id; |
47 | u8 card_rev; | 44 | u8 card_rev; |
@@ -70,10 +67,28 @@ static void free_if_spi_card(struct if_spi_card *card) | |||
70 | kfree(card); | 67 | kfree(card); |
71 | } | 68 | } |
72 | 69 | ||
73 | static struct chip_ident chip_id_to_device_name[] = { | 70 | #define MODEL_8385 0x04 |
74 | { .chip_id = 0x04, .name = 8385 }, | 71 | #define MODEL_8686 0x0b |
75 | { .chip_id = 0x0b, .name = 8686 }, | 72 | #define MODEL_8688 0x10 |
73 | |||
74 | static const struct lbs_fw_table fw_table[] = { | ||
75 | { MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" }, | ||
76 | { MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" }, | ||
77 | { MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" }, | ||
78 | { MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" }, | ||
79 | { MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" }, | ||
80 | { 0, NULL, NULL } | ||
76 | }; | 81 | }; |
82 | MODULE_FIRMWARE("libertas/gspi8385_helper.bin"); | ||
83 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
84 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
85 | MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin"); | ||
86 | MODULE_FIRMWARE("libertas/gspi8686_v9.bin"); | ||
87 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
88 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
89 | MODULE_FIRMWARE("libertas/gspi8688_helper.bin"); | ||
90 | MODULE_FIRMWARE("libertas/gspi8688.bin"); | ||
91 | |||
77 | 92 | ||
78 | /* | 93 | /* |
79 | * SPI Interface Unit Routines | 94 | * SPI Interface Unit Routines |
@@ -399,26 +414,20 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes) | |||
399 | * Firmware Loading | 414 | * Firmware Loading |
400 | */ | 415 | */ |
401 | 416 | ||
402 | static int if_spi_prog_helper_firmware(struct if_spi_card *card) | 417 | static int if_spi_prog_helper_firmware(struct if_spi_card *card, |
418 | const struct firmware *firmware) | ||
403 | { | 419 | { |
404 | int err = 0; | 420 | int err = 0; |
405 | const struct firmware *firmware = NULL; | ||
406 | int bytes_remaining; | 421 | int bytes_remaining; |
407 | const u8 *fw; | 422 | const u8 *fw; |
408 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; | 423 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; |
409 | struct spi_device *spi = card->spi; | ||
410 | 424 | ||
411 | lbs_deb_enter(LBS_DEB_SPI); | 425 | lbs_deb_enter(LBS_DEB_SPI); |
412 | 426 | ||
413 | err = spu_set_interrupt_mode(card, 1, 0); | 427 | err = spu_set_interrupt_mode(card, 1, 0); |
414 | if (err) | 428 | if (err) |
415 | goto out; | 429 | goto out; |
416 | /* Get helper firmware image */ | 430 | |
417 | err = request_firmware(&firmware, card->helper_fw_name, &spi->dev); | ||
418 | if (err) { | ||
419 | lbs_pr_err("request_firmware failed with err = %d\n", err); | ||
420 | goto out; | ||
421 | } | ||
422 | bytes_remaining = firmware->size; | 431 | bytes_remaining = firmware->size; |
423 | fw = firmware->data; | 432 | fw = firmware->data; |
424 | 433 | ||
@@ -429,13 +438,13 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
429 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, | 438 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, |
430 | HELPER_FW_LOAD_CHUNK_SZ); | 439 | HELPER_FW_LOAD_CHUNK_SZ); |
431 | if (err) | 440 | if (err) |
432 | goto release_firmware; | 441 | goto out; |
433 | 442 | ||
434 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, | 443 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, |
435 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, | 444 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, |
436 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); | 445 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); |
437 | if (err) | 446 | if (err) |
438 | goto release_firmware; | 447 | goto out; |
439 | 448 | ||
440 | /* Feed the data into the command read/write port reg | 449 | /* Feed the data into the command read/write port reg |
441 | * in chunks of 64 bytes */ | 450 | * in chunks of 64 bytes */ |
@@ -446,16 +455,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
446 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | 455 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, |
447 | temp, HELPER_FW_LOAD_CHUNK_SZ); | 456 | temp, HELPER_FW_LOAD_CHUNK_SZ); |
448 | if (err) | 457 | if (err) |
449 | goto release_firmware; | 458 | goto out; |
450 | 459 | ||
451 | /* Interrupt the boot code */ | 460 | /* Interrupt the boot code */ |
452 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 461 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
453 | if (err) | 462 | if (err) |
454 | goto release_firmware; | 463 | goto out; |
455 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | 464 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, |
456 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 465 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
457 | if (err) | 466 | if (err) |
458 | goto release_firmware; | 467 | goto out; |
459 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; | 468 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; |
460 | fw += HELPER_FW_LOAD_CHUNK_SZ; | 469 | fw += HELPER_FW_LOAD_CHUNK_SZ; |
461 | } | 470 | } |
@@ -465,18 +474,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
465 | * bootloader. This completes the helper download. */ | 474 | * bootloader. This completes the helper download. */ |
466 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); | 475 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); |
467 | if (err) | 476 | if (err) |
468 | goto release_firmware; | 477 | goto out; |
469 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 478 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
470 | if (err) | 479 | if (err) |
471 | goto release_firmware; | 480 | goto out; |
472 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | 481 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, |
473 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 482 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
474 | goto release_firmware; | 483 | goto out; |
475 | 484 | ||
476 | lbs_deb_spi("waiting for helper to boot...\n"); | 485 | lbs_deb_spi("waiting for helper to boot...\n"); |
477 | 486 | ||
478 | release_firmware: | ||
479 | release_firmware(firmware); | ||
480 | out: | 487 | out: |
481 | if (err) | 488 | if (err) |
482 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); | 489 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); |
@@ -523,13 +530,12 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, | |||
523 | return len; | 530 | return len; |
524 | } | 531 | } |
525 | 532 | ||
526 | static int if_spi_prog_main_firmware(struct if_spi_card *card) | 533 | static int if_spi_prog_main_firmware(struct if_spi_card *card, |
534 | const struct firmware *firmware) | ||
527 | { | 535 | { |
528 | int len, prev_len; | 536 | int len, prev_len; |
529 | int bytes, crc_err = 0, err = 0; | 537 | int bytes, crc_err = 0, err = 0; |
530 | const struct firmware *firmware = NULL; | ||
531 | const u8 *fw; | 538 | const u8 *fw; |
532 | struct spi_device *spi = card->spi; | ||
533 | u16 num_crc_errs; | 539 | u16 num_crc_errs; |
534 | 540 | ||
535 | lbs_deb_enter(LBS_DEB_SPI); | 541 | lbs_deb_enter(LBS_DEB_SPI); |
@@ -538,19 +544,11 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
538 | if (err) | 544 | if (err) |
539 | goto out; | 545 | goto out; |
540 | 546 | ||
541 | /* Get firmware image */ | ||
542 | err = request_firmware(&firmware, card->main_fw_name, &spi->dev); | ||
543 | if (err) { | ||
544 | lbs_pr_err("%s: can't get firmware '%s' from kernel. " | ||
545 | "err = %d\n", __func__, card->main_fw_name, err); | ||
546 | goto out; | ||
547 | } | ||
548 | |||
549 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); | 547 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); |
550 | if (err) { | 548 | if (err) { |
551 | lbs_pr_err("%s: timed out waiting for initial " | 549 | lbs_pr_err("%s: timed out waiting for initial " |
552 | "scratch reg = 0\n", __func__); | 550 | "scratch reg = 0\n", __func__); |
553 | goto release_firmware; | 551 | goto out; |
554 | } | 552 | } |
555 | 553 | ||
556 | num_crc_errs = 0; | 554 | num_crc_errs = 0; |
@@ -560,7 +558,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
560 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { | 558 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { |
561 | if (len < 0) { | 559 | if (len < 0) { |
562 | err = len; | 560 | err = len; |
563 | goto release_firmware; | 561 | goto out; |
564 | } | 562 | } |
565 | if (bytes < 0) { | 563 | if (bytes < 0) { |
566 | /* If there are no more bytes left, we would normally | 564 | /* If there are no more bytes left, we would normally |
@@ -575,7 +573,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
575 | lbs_pr_err("Too many CRC errors encountered " | 573 | lbs_pr_err("Too many CRC errors encountered " |
576 | "in firmware load.\n"); | 574 | "in firmware load.\n"); |
577 | err = -EIO; | 575 | err = -EIO; |
578 | goto release_firmware; | 576 | goto out; |
579 | } | 577 | } |
580 | } else { | 578 | } else { |
581 | /* Previous transfer succeeded. Advance counters. */ | 579 | /* Previous transfer succeeded. Advance counters. */ |
@@ -590,15 +588,15 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
590 | 588 | ||
591 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 589 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
592 | if (err) | 590 | if (err) |
593 | goto release_firmware; | 591 | goto out; |
594 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | 592 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, |
595 | card->cmd_buffer, len); | 593 | card->cmd_buffer, len); |
596 | if (err) | 594 | if (err) |
597 | goto release_firmware; | 595 | goto out; |
598 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , | 596 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , |
599 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 597 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
600 | if (err) | 598 | if (err) |
601 | goto release_firmware; | 599 | goto out; |
602 | prev_len = len; | 600 | prev_len = len; |
603 | } | 601 | } |
604 | if (bytes > prev_len) { | 602 | if (bytes > prev_len) { |
@@ -611,12 +609,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
611 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); | 609 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); |
612 | if (err) { | 610 | if (err) { |
613 | lbs_pr_err("failed to confirm the firmware download\n"); | 611 | lbs_pr_err("failed to confirm the firmware download\n"); |
614 | goto release_firmware; | 612 | goto out; |
615 | } | 613 | } |
616 | 614 | ||
617 | release_firmware: | ||
618 | release_firmware(firmware); | ||
619 | |||
620 | out: | 615 | out: |
621 | if (err) | 616 | if (err) |
622 | lbs_pr_err("failed to load firmware (err=%d)\n", err); | 617 | lbs_pr_err("failed to load firmware (err=%d)\n", err); |
@@ -800,14 +795,16 @@ static int lbs_spi_thread(void *data) | |||
800 | goto err; | 795 | goto err; |
801 | } | 796 | } |
802 | 797 | ||
803 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) | 798 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) { |
804 | err = if_spi_c2h_cmd(card); | 799 | err = if_spi_c2h_cmd(card); |
805 | if (err) | 800 | if (err) |
806 | goto err; | 801 | goto err; |
807 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) | 802 | } |
803 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) { | ||
808 | err = if_spi_c2h_data(card); | 804 | err = if_spi_c2h_data(card); |
809 | if (err) | 805 | if (err) |
810 | goto err; | 806 | goto err; |
807 | } | ||
811 | 808 | ||
812 | /* workaround: in PS mode, the card does not set the Command | 809 | /* workaround: in PS mode, the card does not set the Command |
813 | * Download Ready bit, but it sets TX Download Ready. */ | 810 | * Download Ready bit, but it sets TX Download Ready. */ |
@@ -886,37 +883,16 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) | |||
886 | * SPI callbacks | 883 | * SPI callbacks |
887 | */ | 884 | */ |
888 | 885 | ||
889 | static int if_spi_calculate_fw_names(u16 card_id, | ||
890 | char *helper_fw, char *main_fw) | ||
891 | { | ||
892 | int i; | ||
893 | for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { | ||
894 | if (card_id == chip_id_to_device_name[i].chip_id) | ||
895 | break; | ||
896 | } | ||
897 | if (i == ARRAY_SIZE(chip_id_to_device_name)) { | ||
898 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); | ||
899 | return -EAFNOSUPPORT; | ||
900 | } | ||
901 | snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin", | ||
902 | chip_id_to_device_name[i].name); | ||
903 | snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin", | ||
904 | chip_id_to_device_name[i].name); | ||
905 | return 0; | ||
906 | } | ||
907 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
908 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
909 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
910 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
911 | |||
912 | static int __devinit if_spi_probe(struct spi_device *spi) | 886 | static int __devinit if_spi_probe(struct spi_device *spi) |
913 | { | 887 | { |
914 | struct if_spi_card *card; | 888 | struct if_spi_card *card; |
915 | struct lbs_private *priv = NULL; | 889 | struct lbs_private *priv = NULL; |
916 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | 890 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; |
917 | int err = 0; | 891 | int err = 0, i; |
918 | u32 scratch; | 892 | u32 scratch; |
919 | struct sched_param param = { .sched_priority = 1 }; | 893 | struct sched_param param = { .sched_priority = 1 }; |
894 | const struct firmware *helper = NULL; | ||
895 | const struct firmware *mainfw = NULL; | ||
920 | 896 | ||
921 | lbs_deb_enter(LBS_DEB_SPI); | 897 | lbs_deb_enter(LBS_DEB_SPI); |
922 | 898 | ||
@@ -961,10 +937,25 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
961 | lbs_deb_spi("Firmware is already loaded for " | 937 | lbs_deb_spi("Firmware is already loaded for " |
962 | "Marvell WLAN 802.11 adapter\n"); | 938 | "Marvell WLAN 802.11 adapter\n"); |
963 | else { | 939 | else { |
964 | err = if_spi_calculate_fw_names(card->card_id, | 940 | /* Check if we support this card */ |
965 | card->helper_fw_name, card->main_fw_name); | 941 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
966 | if (err) | 942 | if (card->card_id == fw_table[i].model) |
943 | break; | ||
944 | } | ||
945 | if (i == ARRAY_SIZE(fw_table)) { | ||
946 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", | ||
947 | card->card_id); | ||
948 | err = -ENODEV; | ||
967 | goto free_card; | 949 | goto free_card; |
950 | } | ||
951 | |||
952 | err = lbs_get_firmware(&card->spi->dev, NULL, NULL, | ||
953 | card->card_id, &fw_table[0], &helper, | ||
954 | &mainfw); | ||
955 | if (err) { | ||
956 | lbs_pr_err("failed to find firmware (%d)\n", err); | ||
957 | goto free_card; | ||
958 | } | ||
968 | 959 | ||
969 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " | 960 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " |
970 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " | 961 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " |
@@ -973,10 +964,10 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
973 | card->card_id, card->card_rev, | 964 | card->card_id, card->card_rev, |
974 | spi->master->bus_num, spi->chip_select, | 965 | spi->master->bus_num, spi->chip_select, |
975 | spi->max_speed_hz); | 966 | spi->max_speed_hz); |
976 | err = if_spi_prog_helper_firmware(card); | 967 | err = if_spi_prog_helper_firmware(card, helper); |
977 | if (err) | 968 | if (err) |
978 | goto free_card; | 969 | goto free_card; |
979 | err = if_spi_prog_main_firmware(card); | 970 | err = if_spi_prog_main_firmware(card, mainfw); |
980 | if (err) | 971 | if (err) |
981 | goto free_card; | 972 | goto free_card; |
982 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); | 973 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); |
@@ -1044,6 +1035,11 @@ remove_card: | |||
1044 | free_card: | 1035 | free_card: |
1045 | free_if_spi_card(card); | 1036 | free_if_spi_card(card); |
1046 | out: | 1037 | out: |
1038 | if (helper) | ||
1039 | release_firmware(helper); | ||
1040 | if (mainfw) | ||
1041 | release_firmware(mainfw); | ||
1042 | |||
1047 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1043 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
1048 | return err; | 1044 | return err; |
1049 | } | 1045 | } |
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h index f87eec410848..8b1417d3b71b 100644 --- a/drivers/net/wireless/libertas/if_spi.h +++ b/drivers/net/wireless/libertas/if_spi.h | |||
@@ -25,11 +25,6 @@ | |||
25 | 25 | ||
26 | #define IF_SPI_FW_NAME_MAX 30 | 26 | #define IF_SPI_FW_NAME_MAX 30 |
27 | 27 | ||
28 | struct chip_ident { | ||
29 | u16 chip_id; | ||
30 | u16 name; | ||
31 | }; | ||
32 | |||
33 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 | 28 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 |
34 | 29 | ||
35 | /* Chunk size when loading the helper firmware */ | 30 | /* Chunk size when loading the helper firmware */ |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 3ff61063671a..e906616232a2 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -26,15 +26,25 @@ | |||
26 | 26 | ||
27 | #define MESSAGE_HEADER_LEN 4 | 27 | #define MESSAGE_HEADER_LEN 4 |
28 | 28 | ||
29 | static char *lbs_fw_name = "usb8388.bin"; | 29 | static char *lbs_fw_name = NULL; |
30 | module_param_named(fw_name, lbs_fw_name, charp, 0644); | 30 | module_param_named(fw_name, lbs_fw_name, charp, 0644); |
31 | 31 | ||
32 | MODULE_FIRMWARE("libertas/usb8388_v9.bin"); | ||
33 | MODULE_FIRMWARE("libertas/usb8388_v5.bin"); | ||
34 | MODULE_FIRMWARE("libertas/usb8388.bin"); | ||
35 | MODULE_FIRMWARE("libertas/usb8682.bin"); | ||
32 | MODULE_FIRMWARE("usb8388.bin"); | 36 | MODULE_FIRMWARE("usb8388.bin"); |
33 | 37 | ||
38 | enum { | ||
39 | MODEL_UNKNOWN = 0x0, | ||
40 | MODEL_8388 = 0x1, | ||
41 | MODEL_8682 = 0x2 | ||
42 | }; | ||
43 | |||
34 | static struct usb_device_id if_usb_table[] = { | 44 | static struct usb_device_id if_usb_table[] = { |
35 | /* Enter the device signature inside */ | 45 | /* Enter the device signature inside */ |
36 | { USB_DEVICE(0x1286, 0x2001) }, | 46 | { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, |
37 | { USB_DEVICE(0x05a3, 0x8388) }, | 47 | { USB_DEVICE(0x05a3, 0x8388), .driver_info = MODEL_8388 }, |
38 | {} /* Terminating entry */ | 48 | {} /* Terminating entry */ |
39 | }; | 49 | }; |
40 | 50 | ||
@@ -66,6 +76,8 @@ static ssize_t if_usb_firmware_set(struct device *dev, | |||
66 | struct if_usb_card *cardp = priv->card; | 76 | struct if_usb_card *cardp = priv->card; |
67 | int ret; | 77 | int ret; |
68 | 78 | ||
79 | BUG_ON(buf == NULL); | ||
80 | |||
69 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); | 81 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); |
70 | if (ret == 0) | 82 | if (ret == 0) |
71 | return count; | 83 | return count; |
@@ -91,6 +103,8 @@ static ssize_t if_usb_boot2_set(struct device *dev, | |||
91 | struct if_usb_card *cardp = priv->card; | 103 | struct if_usb_card *cardp = priv->card; |
92 | int ret; | 104 | int ret; |
93 | 105 | ||
106 | BUG_ON(buf == NULL); | ||
107 | |||
94 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); | 108 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); |
95 | if (ret == 0) | 109 | if (ret == 0) |
96 | return count; | 110 | return count; |
@@ -244,6 +258,7 @@ static int if_usb_probe(struct usb_interface *intf, | |||
244 | init_waitqueue_head(&cardp->fw_wq); | 258 | init_waitqueue_head(&cardp->fw_wq); |
245 | 259 | ||
246 | cardp->udev = udev; | 260 | cardp->udev = udev; |
261 | cardp->model = (uint32_t) id->driver_info; | ||
247 | iface_desc = intf->cur_altsetting; | 262 | iface_desc = intf->cur_altsetting; |
248 | 263 | ||
249 | lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" | 264 | lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" |
@@ -924,6 +939,38 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp, | |||
924 | return ret; | 939 | return ret; |
925 | } | 940 | } |
926 | 941 | ||
942 | /* table of firmware file names */ | ||
943 | static const struct { | ||
944 | u32 model; | ||
945 | const char *fwname; | ||
946 | } fw_table[] = { | ||
947 | { MODEL_8388, "libertas/usb8388_v9.bin" }, | ||
948 | { MODEL_8388, "libertas/usb8388_v5.bin" }, | ||
949 | { MODEL_8388, "libertas/usb8388.bin" }, | ||
950 | { MODEL_8388, "usb8388.bin" }, | ||
951 | { MODEL_8682, "libertas/usb8682.bin" } | ||
952 | }; | ||
953 | |||
954 | static int get_fw(struct if_usb_card *cardp, const char *fwname) | ||
955 | { | ||
956 | int i; | ||
957 | |||
958 | /* Try user-specified firmware first */ | ||
959 | if (fwname) | ||
960 | return request_firmware(&cardp->fw, fwname, &cardp->udev->dev); | ||
961 | |||
962 | /* Otherwise search for firmware to use */ | ||
963 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { | ||
964 | if (fw_table[i].model != cardp->model) | ||
965 | continue; | ||
966 | if (request_firmware(&cardp->fw, fw_table[i].fwname, | ||
967 | &cardp->udev->dev) == 0) | ||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | return -ENOENT; | ||
972 | } | ||
973 | |||
927 | static int __if_usb_prog_firmware(struct if_usb_card *cardp, | 974 | static int __if_usb_prog_firmware(struct if_usb_card *cardp, |
928 | const char *fwname, int cmd) | 975 | const char *fwname, int cmd) |
929 | { | 976 | { |
@@ -933,10 +980,9 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp, | |||
933 | 980 | ||
934 | lbs_deb_enter(LBS_DEB_USB); | 981 | lbs_deb_enter(LBS_DEB_USB); |
935 | 982 | ||
936 | ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev); | 983 | ret = get_fw(cardp, fwname); |
937 | if (ret < 0) { | 984 | if (ret) { |
938 | lbs_pr_err("request_firmware() failed with %#x\n", ret); | 985 | lbs_pr_err("failed to find firmware (%d)\n", ret); |
939 | lbs_pr_err("firmware %s not found\n", fwname); | ||
940 | goto done; | 986 | goto done; |
941 | } | 987 | } |
942 | 988 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index 5ba0aee0eb2f..d819e7e3c9aa 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h | |||
@@ -43,6 +43,7 @@ struct bootcmdresp | |||
43 | /** USB card description structure*/ | 43 | /** USB card description structure*/ |
44 | struct if_usb_card { | 44 | struct if_usb_card { |
45 | struct usb_device *udev; | 45 | struct usb_device *udev; |
46 | uint32_t model; /* MODEL_* */ | ||
46 | struct urb *rx_urb, *tx_urb; | 47 | struct urb *rx_urb, *tx_urb; |
47 | struct lbs_private *priv; | 48 | struct lbs_private *priv; |
48 | 49 | ||
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 24958a86747b..47ce5a6ba120 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -1047,6 +1047,111 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) | |||
1047 | } | 1047 | } |
1048 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); | 1048 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); |
1049 | 1049 | ||
1050 | /** | ||
1051 | * @brief Retrieves two-stage firmware | ||
1052 | * | ||
1053 | * @param dev A pointer to device structure | ||
1054 | * @param user_helper User-defined helper firmware file | ||
1055 | * @param user_mainfw User-defined main firmware file | ||
1056 | * @param card_model Bus-specific card model ID used to filter firmware table | ||
1057 | * elements | ||
1058 | * @param fw_table Table of firmware file names and device model numbers | ||
1059 | * terminated by an entry with a NULL helper name | ||
1060 | * @param helper On success, the helper firmware; caller must free | ||
1061 | * @param mainfw On success, the main firmware; caller must free | ||
1062 | * | ||
1063 | * @return 0 on success, non-zero on failure | ||
1064 | */ | ||
1065 | int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
1066 | const char *user_mainfw, u32 card_model, | ||
1067 | const struct lbs_fw_table *fw_table, | ||
1068 | const struct firmware **helper, | ||
1069 | const struct firmware **mainfw) | ||
1070 | { | ||
1071 | const struct lbs_fw_table *iter; | ||
1072 | int ret; | ||
1073 | |||
1074 | BUG_ON(helper == NULL); | ||
1075 | BUG_ON(mainfw == NULL); | ||
1076 | |||
1077 | /* Try user-specified firmware first */ | ||
1078 | if (user_helper) { | ||
1079 | ret = request_firmware(helper, user_helper, dev); | ||
1080 | if (ret) { | ||
1081 | lbs_pr_err("couldn't find helper firmware %s", | ||
1082 | user_helper); | ||
1083 | goto fail; | ||
1084 | } | ||
1085 | } | ||
1086 | if (user_mainfw) { | ||
1087 | ret = request_firmware(mainfw, user_mainfw, dev); | ||
1088 | if (ret) { | ||
1089 | lbs_pr_err("couldn't find main firmware %s", | ||
1090 | user_mainfw); | ||
1091 | goto fail; | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | if (*helper && *mainfw) | ||
1096 | return 0; | ||
1097 | |||
1098 | /* Otherwise search for firmware to use. If neither the helper or | ||
1099 | * the main firmware were specified by the user, then we need to | ||
1100 | * make sure that found helper & main are from the same entry in | ||
1101 | * fw_table. | ||
1102 | */ | ||
1103 | iter = fw_table; | ||
1104 | while (iter && iter->helper) { | ||
1105 | if (iter->model != card_model) | ||
1106 | goto next; | ||
1107 | |||
1108 | if (*helper == NULL) { | ||
1109 | ret = request_firmware(helper, iter->helper, dev); | ||
1110 | if (ret) | ||
1111 | goto next; | ||
1112 | |||
1113 | /* If the device has one-stage firmware (ie cf8305) and | ||
1114 | * we've got it then we don't need to bother with the | ||
1115 | * main firmware. | ||
1116 | */ | ||
1117 | if (iter->fwname == NULL) | ||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | if (*mainfw == NULL) { | ||
1122 | ret = request_firmware(mainfw, iter->fwname, dev); | ||
1123 | if (ret && !user_helper) { | ||
1124 | /* Clear the helper if it wasn't user-specified | ||
1125 | * and the main firmware load failed, to ensure | ||
1126 | * we don't have mismatched firmware pairs. | ||
1127 | */ | ||
1128 | release_firmware(*helper); | ||
1129 | *helper = NULL; | ||
1130 | } | ||
1131 | } | ||
1132 | |||
1133 | if (*helper && *mainfw) | ||
1134 | return 0; | ||
1135 | |||
1136 | next: | ||
1137 | iter++; | ||
1138 | } | ||
1139 | |||
1140 | fail: | ||
1141 | /* Failed */ | ||
1142 | if (*helper) { | ||
1143 | release_firmware(*helper); | ||
1144 | *helper = NULL; | ||
1145 | } | ||
1146 | if (*mainfw) { | ||
1147 | release_firmware(*mainfw); | ||
1148 | *mainfw = NULL; | ||
1149 | } | ||
1150 | |||
1151 | return -ENOENT; | ||
1152 | } | ||
1153 | EXPORT_SYMBOL_GPL(lbs_get_firmware); | ||
1154 | |||
1050 | static int __init lbs_init_module(void) | 1155 | static int __init lbs_init_module(void) |
1051 | { | 1156 | { |
1052 | lbs_deb_enter(LBS_DEB_MAIN); | 1157 | lbs_deb_enter(LBS_DEB_MAIN); |
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 41a4f214ade1..ba7d96584cb6 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c | |||
@@ -54,7 +54,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); | |||
54 | /** | 54 | /** |
55 | * if_usb_wrike_bulk_callback - call back to handle URB status | 55 | * if_usb_wrike_bulk_callback - call back to handle URB status |
56 | * | 56 | * |
57 | * @param urb pointer to urb structure | 57 | * @param urb pointer to urb structure |
58 | */ | 58 | */ |
59 | static void if_usb_write_bulk_callback(struct urb *urb) | 59 | static void if_usb_write_bulk_callback(struct urb *urb) |
60 | { | 60 | { |
@@ -178,16 +178,19 @@ static int if_usb_probe(struct usb_interface *intf, | |||
178 | le16_to_cpu(endpoint->wMaxPacketSize); | 178 | le16_to_cpu(endpoint->wMaxPacketSize); |
179 | cardp->ep_in = usb_endpoint_num(endpoint); | 179 | cardp->ep_in = usb_endpoint_num(endpoint); |
180 | 180 | ||
181 | lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); | 181 | lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", |
182 | lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size); | 182 | cardp->ep_in); |
183 | lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", | ||
184 | cardp->ep_in_size); | ||
183 | } else if (usb_endpoint_is_bulk_out(endpoint)) { | 185 | } else if (usb_endpoint_is_bulk_out(endpoint)) { |
184 | cardp->ep_out_size = | 186 | cardp->ep_out_size = |
185 | le16_to_cpu(endpoint->wMaxPacketSize); | 187 | le16_to_cpu(endpoint->wMaxPacketSize); |
186 | cardp->ep_out = usb_endpoint_num(endpoint); | 188 | cardp->ep_out = usb_endpoint_num(endpoint); |
187 | 189 | ||
188 | lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); | 190 | lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", |
191 | cardp->ep_out); | ||
189 | lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", | 192 | lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", |
190 | cardp->ep_out_size); | 193 | cardp->ep_out_size); |
191 | } | 194 | } |
192 | } | 195 | } |
193 | if (!cardp->ep_out_size || !cardp->ep_in_size) { | 196 | if (!cardp->ep_out_size || !cardp->ep_in_size) { |
@@ -318,10 +321,12 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) | |||
318 | 321 | ||
319 | if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { | 322 | if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { |
320 | lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); | 323 | lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); |
321 | lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n", | 324 | lbtf_deb_usb2(&cardp->udev->dev, |
322 | cardp->fwseqnum, cardp->totalbytes); | 325 | "seqnum = %d totalbytes = %d\n", |
326 | cardp->fwseqnum, cardp->totalbytes); | ||
323 | } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { | 327 | } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { |
324 | lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n"); | 328 | lbtf_deb_usb2(&cardp->udev->dev, |
329 | "Host has finished FW downloading\n"); | ||
325 | lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); | 330 | lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); |
326 | 331 | ||
327 | /* Host has finished FW downloading | 332 | /* Host has finished FW downloading |
@@ -367,7 +372,7 @@ EXPORT_SYMBOL_GPL(if_usb_reset_device); | |||
367 | /** | 372 | /** |
368 | * usb_tx_block - transfer data to the device | 373 | * usb_tx_block - transfer data to the device |
369 | * | 374 | * |
370 | * @priv pointer to struct lbtf_private | 375 | * @priv pointer to struct lbtf_private |
371 | * @payload pointer to payload data | 376 | * @payload pointer to payload data |
372 | * @nb data length | 377 | * @nb data length |
373 | * @data non-zero for data, zero for commands | 378 | * @data non-zero for data, zero for commands |
@@ -400,7 +405,8 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, | |||
400 | urb->transfer_flags |= URB_ZERO_PACKET; | 405 | urb->transfer_flags |= URB_ZERO_PACKET; |
401 | 406 | ||
402 | if (usb_submit_urb(urb, GFP_ATOMIC)) { | 407 | if (usb_submit_urb(urb, GFP_ATOMIC)) { |
403 | lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret); | 408 | lbtf_deb_usbd(&cardp->udev->dev, |
409 | "usb_submit_urb failed: %d\n", ret); | ||
404 | goto tx_ret; | 410 | goto tx_ret; |
405 | } | 411 | } |
406 | 412 | ||
@@ -438,10 +444,12 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, | |||
438 | 444 | ||
439 | cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; | 445 | cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; |
440 | 446 | ||
441 | lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); | 447 | lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", |
448 | cardp->rx_urb); | ||
442 | ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC); | 449 | ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC); |
443 | if (ret) { | 450 | if (ret) { |
444 | lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret); | 451 | lbtf_deb_usbd(&cardp->udev->dev, |
452 | "Submit Rx URB failed: %d\n", ret); | ||
445 | kfree_skb(skb); | 453 | kfree_skb(skb); |
446 | cardp->rx_skb = NULL; | 454 | cardp->rx_skb = NULL; |
447 | lbtf_deb_leave(LBTF_DEB_USB); | 455 | lbtf_deb_leave(LBTF_DEB_USB); |
@@ -522,14 +530,14 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
522 | } | 530 | } |
523 | } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) { | 531 | } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) { |
524 | pr_info("boot cmd response cmd_tag error (%d)\n", | 532 | pr_info("boot cmd response cmd_tag error (%d)\n", |
525 | bcmdresp.cmd); | 533 | bcmdresp.cmd); |
526 | } else if (bcmdresp.result != BOOT_CMD_RESP_OK) { | 534 | } else if (bcmdresp.result != BOOT_CMD_RESP_OK) { |
527 | pr_info("boot cmd response result error (%d)\n", | 535 | pr_info("boot cmd response result error (%d)\n", |
528 | bcmdresp.result); | 536 | bcmdresp.result); |
529 | } else { | 537 | } else { |
530 | cardp->bootcmdresp = 1; | 538 | cardp->bootcmdresp = 1; |
531 | lbtf_deb_usbd(&cardp->udev->dev, | 539 | lbtf_deb_usbd(&cardp->udev->dev, |
532 | "Received valid boot command response\n"); | 540 | "Received valid boot command response\n"); |
533 | } | 541 | } |
534 | 542 | ||
535 | kfree_skb(skb); | 543 | kfree_skb(skb); |
@@ -541,19 +549,23 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
541 | syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader), | 549 | syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader), |
542 | GFP_ATOMIC); | 550 | GFP_ATOMIC); |
543 | if (!syncfwheader) { | 551 | if (!syncfwheader) { |
544 | lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); | 552 | lbtf_deb_usbd(&cardp->udev->dev, |
553 | "Failure to allocate syncfwheader\n"); | ||
545 | kfree_skb(skb); | 554 | kfree_skb(skb); |
546 | lbtf_deb_leave(LBTF_DEB_USB); | 555 | lbtf_deb_leave(LBTF_DEB_USB); |
547 | return; | 556 | return; |
548 | } | 557 | } |
549 | 558 | ||
550 | if (!syncfwheader->cmd) { | 559 | if (!syncfwheader->cmd) { |
551 | lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); | 560 | lbtf_deb_usb2(&cardp->udev->dev, |
552 | lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", | 561 | "FW received Blk with correct CRC\n"); |
553 | le32_to_cpu(syncfwheader->seqnum)); | 562 | lbtf_deb_usb2(&cardp->udev->dev, |
563 | "FW received Blk seqnum = %d\n", | ||
564 | le32_to_cpu(syncfwheader->seqnum)); | ||
554 | cardp->CRC_OK = 1; | 565 | cardp->CRC_OK = 1; |
555 | } else { | 566 | } else { |
556 | lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n"); | 567 | lbtf_deb_usbd(&cardp->udev->dev, |
568 | "FW received Blk with CRC error\n"); | ||
557 | cardp->CRC_OK = 0; | 569 | cardp->CRC_OK = 0; |
558 | } | 570 | } |
559 | 571 | ||
@@ -666,7 +678,8 @@ static void if_usb_receive(struct urb *urb) | |||
666 | { | 678 | { |
667 | /* Event cause handling */ | 679 | /* Event cause handling */ |
668 | u32 event_cause = le32_to_cpu(pkt[1]); | 680 | u32 event_cause = le32_to_cpu(pkt[1]); |
669 | lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause); | 681 | lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", |
682 | event_cause); | ||
670 | 683 | ||
671 | /* Icky undocumented magic special case */ | 684 | /* Icky undocumented magic special case */ |
672 | if (event_cause & 0xffff0000) { | 685 | if (event_cause & 0xffff0000) { |
@@ -689,7 +702,7 @@ static void if_usb_receive(struct urb *urb) | |||
689 | } | 702 | } |
690 | default: | 703 | default: |
691 | lbtf_deb_usbd(&cardp->udev->dev, | 704 | lbtf_deb_usbd(&cardp->udev->dev, |
692 | "libertastf: unknown command type 0x%X\n", recvtype); | 705 | "libertastf: unknown command type 0x%X\n", recvtype); |
693 | kfree_skb(skb); | 706 | kfree_skb(skb); |
694 | break; | 707 | break; |
695 | } | 708 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 86fa8abdd66f..298ba79fc51b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -9,7 +9,8 @@ | |||
9 | 9 | ||
10 | /* | 10 | /* |
11 | * TODO: | 11 | * TODO: |
12 | * - IBSS mode simulation (Beacon transmission with competition for "air time") | 12 | * - Add TSF sync and fix IBSS beacon transmission by adding |
13 | * competition for "air time" at TBTT | ||
13 | * - RX filtering based on filter configuration (data->rx_filter) | 14 | * - RX filtering based on filter configuration (data->rx_filter) |
14 | */ | 15 | */ |
15 | 16 | ||
@@ -620,7 +621,8 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
620 | hwsim_check_magic(vif); | 621 | hwsim_check_magic(vif); |
621 | 622 | ||
622 | if (vif->type != NL80211_IFTYPE_AP && | 623 | if (vif->type != NL80211_IFTYPE_AP && |
623 | vif->type != NL80211_IFTYPE_MESH_POINT) | 624 | vif->type != NL80211_IFTYPE_MESH_POINT && |
625 | vif->type != NL80211_IFTYPE_ADHOC) | ||
624 | return; | 626 | return; |
625 | 627 | ||
626 | skb = ieee80211_beacon_get(hw, vif); | 628 | skb = ieee80211_beacon_get(hw, vif); |
@@ -1295,6 +1297,7 @@ static int __init init_mac80211_hwsim(void) | |||
1295 | hw->wiphy->interface_modes = | 1297 | hw->wiphy->interface_modes = |
1296 | BIT(NL80211_IFTYPE_STATION) | | 1298 | BIT(NL80211_IFTYPE_STATION) | |
1297 | BIT(NL80211_IFTYPE_AP) | | 1299 | BIT(NL80211_IFTYPE_AP) | |
1300 | BIT(NL80211_IFTYPE_ADHOC) | | ||
1298 | BIT(NL80211_IFTYPE_MESH_POINT); | 1301 | BIT(NL80211_IFTYPE_MESH_POINT); |
1299 | 1302 | ||
1300 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 1303 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig index b0342a520bf1..60a930e45a8b 100644 --- a/drivers/net/wireless/p54/Kconfig +++ b/drivers/net/wireless/p54/Kconfig | |||
@@ -2,6 +2,7 @@ config P54_COMMON | |||
2 | tristate "Softmac Prism54 support" | 2 | tristate "Softmac Prism54 support" |
3 | depends on MAC80211 && EXPERIMENTAL | 3 | depends on MAC80211 && EXPERIMENTAL |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | select CRC_CCITT | ||
5 | ---help--- | 6 | ---help--- |
6 | This is common code for isl38xx/stlc45xx based modules. | 7 | This is common code for isl38xx/stlc45xx based modules. |
7 | This module does nothing by itself - the USB/PCI/SPI front-ends | 8 | This module does nothing by itself - the USB/PCI/SPI front-ends |
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 78347041ec40..8c05266d37f4 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | 24 | ||
25 | #include <net/mac80211.h> | 25 | #include <net/mac80211.h> |
26 | #include <linux/crc-ccitt.h> | ||
26 | 27 | ||
27 | #include "p54.h" | 28 | #include "p54.h" |
28 | #include "eeprom.h" | 29 | #include "eeprom.h" |
@@ -540,6 +541,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
540 | int err; | 541 | int err; |
541 | u8 *end = (u8 *)eeprom + len; | 542 | u8 *end = (u8 *)eeprom + len; |
542 | u16 synth = 0; | 543 | u16 synth = 0; |
544 | u16 crc16 = ~0; | ||
543 | 545 | ||
544 | wrap = (struct eeprom_pda_wrap *) eeprom; | 546 | wrap = (struct eeprom_pda_wrap *) eeprom; |
545 | entry = (void *)wrap->data + le16_to_cpu(wrap->len); | 547 | entry = (void *)wrap->data + le16_to_cpu(wrap->len); |
@@ -655,16 +657,29 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
655 | } | 657 | } |
656 | break; | 658 | break; |
657 | case PDR_END: | 659 | case PDR_END: |
658 | /* make it overrun */ | 660 | crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry)); |
659 | entry_len = len; | 661 | if (crc16 != le16_to_cpup((__le16 *)entry->data)) { |
662 | wiphy_err(dev->wiphy, "eeprom failed checksum " | ||
663 | "test!\n"); | ||
664 | err = -ENOMSG; | ||
665 | goto err; | ||
666 | } else { | ||
667 | goto good_eeprom; | ||
668 | } | ||
660 | break; | 669 | break; |
661 | default: | 670 | default: |
662 | break; | 671 | break; |
663 | } | 672 | } |
664 | 673 | ||
665 | entry = (void *)entry + (entry_len + 1)*2; | 674 | crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2); |
675 | entry = (void *)entry + (entry_len + 1) * 2; | ||
666 | } | 676 | } |
667 | 677 | ||
678 | wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n"); | ||
679 | err = -ENODATA; | ||
680 | goto err; | ||
681 | |||
682 | good_eeprom: | ||
668 | if (!synth || !priv->iq_autocal || !priv->output_limit || | 683 | if (!synth || !priv->iq_autocal || !priv->output_limit || |
669 | !priv->curve_data) { | 684 | !priv->curve_data) { |
670 | wiphy_err(dev->wiphy, | 685 | wiphy_err(dev->wiphy, |
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 15b20c29a604..92b9b1f05fd5 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c | |||
@@ -123,10 +123,14 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) | |||
123 | bootrec = (struct bootrec *)&bootrec->data[len]; | 123 | bootrec = (struct bootrec *)&bootrec->data[len]; |
124 | } | 124 | } |
125 | 125 | ||
126 | if (fw_version) | 126 | if (fw_version) { |
127 | wiphy_info(priv->hw->wiphy, | 127 | wiphy_info(priv->hw->wiphy, |
128 | "FW rev %s - Softmac protocol %x.%x\n", | 128 | "FW rev %s - Softmac protocol %x.%x\n", |
129 | fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); | 129 | fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); |
130 | snprintf(dev->wiphy->fw_version, sizeof(dev->wiphy->fw_version), | ||
131 | "%s - %x.%x", fw_version, | ||
132 | priv->fw_var >> 8, priv->fw_var & 0xff); | ||
133 | } | ||
130 | 134 | ||
131 | if (priv->fw_var < 0x500) | 135 | if (priv->fw_var < 0x500) |
132 | wiphy_info(priv->hw->wiphy, | 136 | wiphy_info(priv->hw->wiphy, |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 47db439b63bf..622d27b6d8f2 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -429,8 +429,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
429 | 429 | ||
430 | mutex_lock(&priv->conf_mutex); | 430 | mutex_lock(&priv->conf_mutex); |
431 | if (cmd == SET_KEY) { | 431 | if (cmd == SET_KEY) { |
432 | switch (key->alg) { | 432 | switch (key->cipher) { |
433 | case ALG_TKIP: | 433 | case WLAN_CIPHER_SUITE_TKIP: |
434 | if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL | | 434 | if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL | |
435 | BR_DESC_PRIV_CAP_TKIP))) { | 435 | BR_DESC_PRIV_CAP_TKIP))) { |
436 | ret = -EOPNOTSUPP; | 436 | ret = -EOPNOTSUPP; |
@@ -439,7 +439,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
439 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 439 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
440 | algo = P54_CRYPTO_TKIPMICHAEL; | 440 | algo = P54_CRYPTO_TKIPMICHAEL; |
441 | break; | 441 | break; |
442 | case ALG_WEP: | 442 | case WLAN_CIPHER_SUITE_WEP40: |
443 | case WLAN_CIPHER_SUITE_WEP104: | ||
443 | if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) { | 444 | if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) { |
444 | ret = -EOPNOTSUPP; | 445 | ret = -EOPNOTSUPP; |
445 | goto out_unlock; | 446 | goto out_unlock; |
@@ -447,7 +448,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
447 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 448 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
448 | algo = P54_CRYPTO_WEP; | 449 | algo = P54_CRYPTO_WEP; |
449 | break; | 450 | break; |
450 | case ALG_CCMP: | 451 | case WLAN_CIPHER_SUITE_CCMP: |
451 | if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) { | 452 | if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) { |
452 | ret = -EOPNOTSUPP; | 453 | ret = -EOPNOTSUPP; |
453 | goto out_unlock; | 454 | goto out_unlock; |
diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h index 1ea1050911d9..d592cbd34d78 100644 --- a/drivers/net/wireless/p54/p54spi_eeprom.h +++ b/drivers/net/wireless/p54/p54spi_eeprom.h | |||
@@ -671,7 +671,7 @@ static unsigned char p54spi_eeprom[] = { | |||
671 | 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, | 671 | 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, |
672 | 672 | ||
673 | 0x02, 0x00, 0x00, 0x00, /* PDR_END */ | 673 | 0x02, 0x00, 0x00, 0x00, /* PDR_END */ |
674 | 0xa8, 0xf5 /* bogus data */ | 674 | 0x67, 0x99, |
675 | }; | 675 | }; |
676 | 676 | ||
677 | #endif /* P54SPI_EEPROM_H */ | 677 | #endif /* P54SPI_EEPROM_H */ |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 173aec3d6e7e..34447d1ad80d 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -683,14 +683,15 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, | |||
683 | } | 683 | } |
684 | } | 684 | } |
685 | 685 | ||
686 | static u8 p54_convert_algo(enum ieee80211_key_alg alg) | 686 | static u8 p54_convert_algo(u32 cipher) |
687 | { | 687 | { |
688 | switch (alg) { | 688 | switch (cipher) { |
689 | case ALG_WEP: | 689 | case WLAN_CIPHER_SUITE_WEP40: |
690 | case WLAN_CIPHER_SUITE_WEP104: | ||
690 | return P54_CRYPTO_WEP; | 691 | return P54_CRYPTO_WEP; |
691 | case ALG_TKIP: | 692 | case WLAN_CIPHER_SUITE_TKIP: |
692 | return P54_CRYPTO_TKIPMICHAEL; | 693 | return P54_CRYPTO_TKIPMICHAEL; |
693 | case ALG_CCMP: | 694 | case WLAN_CIPHER_SUITE_CCMP: |
694 | return P54_CRYPTO_AESCCMP; | 695 | return P54_CRYPTO_AESCCMP; |
695 | default: | 696 | default: |
696 | return 0; | 697 | return 0; |
@@ -731,7 +732,7 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
731 | 732 | ||
732 | if (info->control.hw_key) { | 733 | if (info->control.hw_key) { |
733 | crypt_offset = ieee80211_get_hdrlen_from_skb(skb); | 734 | crypt_offset = ieee80211_get_hdrlen_from_skb(skb); |
734 | if (info->control.hw_key->alg == ALG_TKIP) { | 735 | if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
735 | u8 *iv = (u8 *)(skb->data + crypt_offset); | 736 | u8 *iv = (u8 *)(skb->data + crypt_offset); |
736 | /* | 737 | /* |
737 | * The firmware excepts that the IV has to have | 738 | * The firmware excepts that the IV has to have |
@@ -827,10 +828,10 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
827 | hdr->tries = ridx; | 828 | hdr->tries = ridx; |
828 | txhdr->rts_rate_idx = 0; | 829 | txhdr->rts_rate_idx = 0; |
829 | if (info->control.hw_key) { | 830 | if (info->control.hw_key) { |
830 | txhdr->key_type = p54_convert_algo(info->control.hw_key->alg); | 831 | txhdr->key_type = p54_convert_algo(info->control.hw_key->cipher); |
831 | txhdr->key_len = min((u8)16, info->control.hw_key->keylen); | 832 | txhdr->key_len = min((u8)16, info->control.hw_key->keylen); |
832 | memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); | 833 | memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); |
833 | if (info->control.hw_key->alg == ALG_TKIP) { | 834 | if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
834 | /* reserve space for the MIC key */ | 835 | /* reserve space for the MIC key */ |
835 | len += 8; | 836 | len += 8; |
836 | memcpy(skb_put(skb, 8), &(info->control.hw_key->key | 837 | memcpy(skb_put(skb, 8), &(info->control.hw_key->key |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 77cd65db8500..d97a2caf582b 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
@@ -3234,7 +3234,7 @@ prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) | |||
3234 | switch (cmd) { | 3234 | switch (cmd) { |
3235 | case PRISM54_HOSTAPD: | 3235 | case PRISM54_HOSTAPD: |
3236 | if (!capable(CAP_NET_ADMIN)) | 3236 | if (!capable(CAP_NET_ADMIN)) |
3237 | return -EPERM; | 3237 | return -EPERM; |
3238 | ret = prism54_hostapd(ndev, &wrq->u.data); | 3238 | ret = prism54_hostapd(ndev, &wrq->u.data); |
3239 | return ret; | 3239 | return ret; |
3240 | } | 3240 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8ddaae44d7fb..baadf03a800e 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -355,7 +355,9 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, | |||
355 | * it is known that not work at least on some hardware. | 355 | * it is known that not work at least on some hardware. |
356 | * SW crypto will be used in that case. | 356 | * SW crypto will be used in that case. |
357 | */ | 357 | */ |
358 | if (key->alg == ALG_WEP && key->keyidx != 0) | 358 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
359 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && | ||
360 | key->keyidx != 0) | ||
359 | return -EOPNOTSUPP; | 361 | return -EOPNOTSUPP; |
360 | 362 | ||
361 | /* | 363 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index ed4ebcdde7c9..cf1f16bfcd5e 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -1318,7 +1318,25 @@ | |||
1318 | #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) | 1318 | #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) |
1319 | 1319 | ||
1320 | /* | 1320 | /* |
1321 | * TX_STA_FIFO: TX Result for specific PID status fifo register | 1321 | * TX_STA_FIFO: TX Result for specific PID status fifo register. |
1322 | * | ||
1323 | * This register is implemented as FIFO with 16 entries in the HW. Each | ||
1324 | * register read fetches the next tx result. If the FIFO is full because | ||
1325 | * it wasn't read fast enough after the according interrupt (TX_FIFO_STATUS) | ||
1326 | * triggered, the hw seems to simply drop further tx results. | ||
1327 | * | ||
1328 | * VALID: 1: this tx result is valid | ||
1329 | * 0: no valid tx result -> driver should stop reading | ||
1330 | * PID_TYPE: The PID latched from the PID field in the TXWI, can be used | ||
1331 | * to match a frame with its tx result (even though the PID is | ||
1332 | * only 4 bits wide). | ||
1333 | * TX_SUCCESS: Indicates tx success (1) or failure (0) | ||
1334 | * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0) | ||
1335 | * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0) | ||
1336 | * WCID: The wireless client ID. | ||
1337 | * MCS: The tx rate used during the last transmission of this frame, be it | ||
1338 | * successful or not. | ||
1339 | * PHYMODE: The phymode used for the transmission. | ||
1322 | */ | 1340 | */ |
1323 | #define TX_STA_FIFO 0x1718 | 1341 | #define TX_STA_FIFO 0x1718 |
1324 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) | 1342 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) |
@@ -1945,6 +1963,13 @@ struct mac_iveiv_entry { | |||
1945 | 1963 | ||
1946 | /* | 1964 | /* |
1947 | * Word1 | 1965 | * Word1 |
1966 | * ACK: 0: No Ack needed, 1: Ack needed | ||
1967 | * NSEQ: 0: Don't assign hw sequence number, 1: Assign hw sequence number | ||
1968 | * BW_WIN_SIZE: BA windows size of the recipient | ||
1969 | * WIRELESS_CLI_ID: Client ID for WCID table access | ||
1970 | * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame | ||
1971 | * PACKETID: Will be latched into the TX_STA_FIFO register once the according | ||
1972 | * frame was processed. 0: Don't report tx status for this frame. | ||
1948 | */ | 1973 | */ |
1949 | #define TXWI_W1_ACK FIELD32(0x00000001) | 1974 | #define TXWI_W1_ACK FIELD32(0x00000001) |
1950 | #define TXWI_W1_NSEQ FIELD32(0x00000002) | 1975 | #define TXWI_W1_NSEQ FIELD32(0x00000002) |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 8c00fbda8664..6a0cb2d924d8 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> | ||
2 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> | 3 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 4 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> |
4 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 5 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
@@ -427,8 +428,10 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
427 | } | 428 | } |
428 | EXPORT_SYMBOL_GPL(rt2800_load_firmware); | 429 | EXPORT_SYMBOL_GPL(rt2800_load_firmware); |
429 | 430 | ||
430 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | 431 | void rt2800_write_tx_data(struct queue_entry *entry, |
432 | struct txentry_desc *txdesc) | ||
431 | { | 433 | { |
434 | __le32 *txwi = rt2800_drv_get_txwi(entry); | ||
432 | u32 word; | 435 | u32 word; |
433 | 436 | ||
434 | /* | 437 | /* |
@@ -437,7 +440,8 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | |||
437 | rt2x00_desc_read(txwi, 0, &word); | 440 | rt2x00_desc_read(txwi, 0, &word); |
438 | rt2x00_set_field32(&word, TXWI_W0_FRAG, | 441 | rt2x00_set_field32(&word, TXWI_W0_FRAG, |
439 | test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | 442 | test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); |
440 | rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); | 443 | rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, |
444 | test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags)); | ||
441 | rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); | 445 | rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); |
442 | rt2x00_set_field32(&word, TXWI_W0_TS, | 446 | rt2x00_set_field32(&word, TXWI_W0_TS, |
443 | test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); | 447 | test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); |
@@ -478,7 +482,7 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | |||
478 | _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); | 482 | _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); |
479 | _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); | 483 | _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); |
480 | } | 484 | } |
481 | EXPORT_SYMBOL_GPL(rt2800_write_txwi); | 485 | EXPORT_SYMBOL_GPL(rt2800_write_tx_data); |
482 | 486 | ||
483 | static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) | 487 | static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) |
484 | { | 488 | { |
@@ -490,7 +494,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) | |||
490 | u8 offset1; | 494 | u8 offset1; |
491 | u8 offset2; | 495 | u8 offset2; |
492 | 496 | ||
493 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) { | 497 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
494 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); | 498 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); |
495 | offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); | 499 | offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); |
496 | offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); | 500 | offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); |
@@ -569,6 +573,122 @@ void rt2800_process_rxwi(struct queue_entry *entry, | |||
569 | } | 573 | } |
570 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); | 574 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); |
571 | 575 | ||
576 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev) | ||
577 | { | ||
578 | struct data_queue *queue; | ||
579 | struct queue_entry *entry; | ||
580 | __le32 *txwi; | ||
581 | struct txdone_entry_desc txdesc; | ||
582 | u32 word; | ||
583 | u32 reg; | ||
584 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; | ||
585 | u16 mcs, real_mcs; | ||
586 | int i; | ||
587 | |||
588 | /* | ||
589 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO | ||
590 | * at most X times and also stop processing once the TX_STA_FIFO_VALID | ||
591 | * flag is not set anymore. | ||
592 | * | ||
593 | * The legacy drivers use X=TX_RING_SIZE but state in a comment | ||
594 | * that the TX_STA_FIFO stack has a size of 16. We stick to our | ||
595 | * tx ring size for now. | ||
596 | */ | ||
597 | for (i = 0; i < TX_ENTRIES; i++) { | ||
598 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); | ||
599 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | ||
600 | break; | ||
601 | |||
602 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | ||
603 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | ||
604 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | ||
605 | |||
606 | /* | ||
607 | * Skip this entry when it contains an invalid | ||
608 | * queue identication number. | ||
609 | */ | ||
610 | if (pid <= 0 || pid > QID_RX) | ||
611 | continue; | ||
612 | |||
613 | queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); | ||
614 | if (unlikely(!queue)) | ||
615 | continue; | ||
616 | |||
617 | /* | ||
618 | * Inside each queue, we process each entry in a chronological | ||
619 | * order. We first check that the queue is not empty. | ||
620 | */ | ||
621 | entry = NULL; | ||
622 | while (!rt2x00queue_empty(queue)) { | ||
623 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
624 | if (!test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
625 | break; | ||
626 | |||
627 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
628 | } | ||
629 | |||
630 | if (!entry || rt2x00queue_empty(queue)) | ||
631 | break; | ||
632 | |||
633 | /* | ||
634 | * Check if we got a match by looking at WCID/ACK/PID | ||
635 | * fields | ||
636 | */ | ||
637 | txwi = rt2800_drv_get_txwi(entry); | ||
638 | |||
639 | rt2x00_desc_read(txwi, 1, &word); | ||
640 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
641 | tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); | ||
642 | tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); | ||
643 | |||
644 | if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) | ||
645 | WARNING(rt2x00dev, "invalid TX_STA_FIFO content"); | ||
646 | |||
647 | /* | ||
648 | * Obtain the status about this packet. | ||
649 | */ | ||
650 | txdesc.flags = 0; | ||
651 | rt2x00_desc_read(txwi, 0, &word); | ||
652 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
653 | mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
654 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
655 | |||
656 | /* | ||
657 | * Ralink has a retry mechanism using a global fallback | ||
658 | * table. We setup this fallback table to try the immediate | ||
659 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field | ||
660 | * always contains the MCS used for the last transmission, be | ||
661 | * it successful or not. | ||
662 | */ | ||
663 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { | ||
664 | /* | ||
665 | * Transmission succeeded. The number of retries is | ||
666 | * mcs - real_mcs | ||
667 | */ | ||
668 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
669 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
670 | } else { | ||
671 | /* | ||
672 | * Transmission failed. The number of retries is | ||
673 | * always 7 in this case (for a total number of 8 | ||
674 | * frames sent). | ||
675 | */ | ||
676 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
677 | txdesc.retry = rt2x00dev->long_retry; | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * the frame was retried at least once | ||
682 | * -> hw used fallback rates | ||
683 | */ | ||
684 | if (txdesc.retry) | ||
685 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
686 | |||
687 | rt2x00lib_txdone(entry, &txdesc); | ||
688 | } | ||
689 | } | ||
690 | EXPORT_SYMBOL_GPL(rt2800_txdone); | ||
691 | |||
572 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | 692 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) |
573 | { | 693 | { |
574 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 694 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
@@ -600,7 +720,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | |||
600 | /* | 720 | /* |
601 | * Add the TXWI for the beacon to the skb. | 721 | * Add the TXWI for the beacon to the skb. |
602 | */ | 722 | */ |
603 | rt2800_write_txwi((__le32 *)entry->skb->data, txdesc); | 723 | rt2800_write_tx_data(entry, txdesc); |
604 | 724 | ||
605 | /* | 725 | /* |
606 | * Dump beacon to userspace through debugfs. | 726 | * Dump beacon to userspace through debugfs. |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 091641e3c5e2..3b572c63382d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> | ||
3 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
2 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz | 4 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz |
3 | 5 | ||
4 | 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 |
@@ -44,6 +46,7 @@ struct rt2800_ops { | |||
44 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, | 46 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, |
45 | const u8 *data, const size_t len); | 47 | const u8 *data, const size_t len); |
46 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); | 48 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); |
49 | __le32 *(*drv_get_txwi)(struct queue_entry *entry); | ||
47 | }; | 50 | }; |
48 | 51 | ||
49 | static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, | 52 | static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, |
@@ -126,6 +129,13 @@ static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) | |||
126 | return rt2800ops->drv_init_registers(rt2x00dev); | 129 | return rt2800ops->drv_init_registers(rt2x00dev); |
127 | } | 130 | } |
128 | 131 | ||
132 | static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry) | ||
133 | { | ||
134 | const struct rt2800_ops *rt2800ops = entry->queue->rt2x00dev->ops->drv; | ||
135 | |||
136 | return rt2800ops->drv_get_txwi(entry); | ||
137 | } | ||
138 | |||
129 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | 139 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, |
130 | const u8 command, const u8 token, | 140 | const u8 command, const u8 token, |
131 | const u8 arg0, const u8 arg1); | 141 | const u8 arg0, const u8 arg1); |
@@ -135,9 +145,12 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, | |||
135 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | 145 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, |
136 | const u8 *data, const size_t len); | 146 | const u8 *data, const size_t len); |
137 | 147 | ||
138 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); | 148 | void rt2800_write_tx_data(struct queue_entry *entry, |
149 | struct txentry_desc *txdesc); | ||
139 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); | 150 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); |
140 | 151 | ||
152 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev); | ||
153 | |||
141 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); | 154 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); |
142 | 155 | ||
143 | extern const struct rt2x00debug rt2800_rt2x00debug; | 156 | extern const struct rt2x00debug rt2800_rt2x00debug; |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 39b3846fa340..4390f2b74b2e 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | 3 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> |
4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
5 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | 5 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> |
@@ -566,15 +566,11 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
566 | /* | 566 | /* |
567 | * TX descriptor initialization | 567 | * TX descriptor initialization |
568 | */ | 568 | */ |
569 | static void rt2800pci_write_tx_data(struct queue_entry* entry, | 569 | static __le32 *rt2800pci_get_txwi(struct queue_entry *entry) |
570 | struct txentry_desc *txdesc) | ||
571 | { | 570 | { |
572 | __le32 *txwi = (__le32 *) entry->skb->data; | 571 | return (__le32 *) entry->skb->data; |
573 | |||
574 | rt2800_write_txwi(txwi, txdesc); | ||
575 | } | 572 | } |
576 | 573 | ||
577 | |||
578 | static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 574 | static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
579 | struct sk_buff *skb, | 575 | struct sk_buff *skb, |
580 | struct txentry_desc *txdesc) | 576 | struct txentry_desc *txdesc) |
@@ -728,110 +724,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
728 | /* | 724 | /* |
729 | * Interrupt functions. | 725 | * Interrupt functions. |
730 | */ | 726 | */ |
731 | static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | ||
732 | { | ||
733 | struct data_queue *queue; | ||
734 | struct queue_entry *entry; | ||
735 | __le32 *txwi; | ||
736 | struct txdone_entry_desc txdesc; | ||
737 | u32 word; | ||
738 | u32 reg; | ||
739 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; | ||
740 | u16 mcs, real_mcs; | ||
741 | int i; | ||
742 | |||
743 | /* | ||
744 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO | ||
745 | * at most X times and also stop processing once the TX_STA_FIFO_VALID | ||
746 | * flag is not set anymore. | ||
747 | * | ||
748 | * The legacy drivers use X=TX_RING_SIZE but state in a comment | ||
749 | * that the TX_STA_FIFO stack has a size of 16. We stick to our | ||
750 | * tx ring size for now. | ||
751 | */ | ||
752 | for (i = 0; i < TX_ENTRIES; i++) { | ||
753 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); | ||
754 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | ||
755 | break; | ||
756 | |||
757 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | ||
758 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | ||
759 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | ||
760 | |||
761 | /* | ||
762 | * Skip this entry when it contains an invalid | ||
763 | * queue identication number. | ||
764 | */ | ||
765 | if (pid <= 0 || pid > QID_RX) | ||
766 | continue; | ||
767 | |||
768 | queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); | ||
769 | if (unlikely(!queue)) | ||
770 | continue; | ||
771 | |||
772 | /* | ||
773 | * Inside each queue, we process each entry in a chronological | ||
774 | * order. We first check that the queue is not empty. | ||
775 | */ | ||
776 | if (rt2x00queue_empty(queue)) | ||
777 | continue; | ||
778 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
779 | |||
780 | /* Check if we got a match by looking at WCID/ACK/PID | ||
781 | * fields */ | ||
782 | txwi = (__le32 *) entry->skb->data; | ||
783 | |||
784 | rt2x00_desc_read(txwi, 1, &word); | ||
785 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
786 | tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); | ||
787 | tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); | ||
788 | |||
789 | if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) | ||
790 | WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n"); | ||
791 | |||
792 | /* | ||
793 | * Obtain the status about this packet. | ||
794 | */ | ||
795 | txdesc.flags = 0; | ||
796 | rt2x00_desc_read(txwi, 0, &word); | ||
797 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
798 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
799 | |||
800 | /* | ||
801 | * Ralink has a retry mechanism using a global fallback | ||
802 | * table. We setup this fallback table to try the immediate | ||
803 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field | ||
804 | * always contains the MCS used for the last transmission, be | ||
805 | * it successful or not. | ||
806 | */ | ||
807 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { | ||
808 | /* | ||
809 | * Transmission succeeded. The number of retries is | ||
810 | * mcs - real_mcs | ||
811 | */ | ||
812 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
813 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
814 | } else { | ||
815 | /* | ||
816 | * Transmission failed. The number of retries is | ||
817 | * always 7 in this case (for a total number of 8 | ||
818 | * frames sent). | ||
819 | */ | ||
820 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
821 | txdesc.retry = 7; | ||
822 | } | ||
823 | |||
824 | /* | ||
825 | * the frame was retried at least once | ||
826 | * -> hw used fallback rates | ||
827 | */ | ||
828 | if (txdesc.retry) | ||
829 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
830 | |||
831 | rt2x00lib_txdone(entry, &txdesc); | ||
832 | } | ||
833 | } | ||
834 | |||
835 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | 727 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) |
836 | { | 728 | { |
837 | struct ieee80211_conf conf = { .flags = 0 }; | 729 | struct ieee80211_conf conf = { .flags = 0 }; |
@@ -867,7 +759,7 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) | |||
867 | * 4 - Tx done interrupt. | 759 | * 4 - Tx done interrupt. |
868 | */ | 760 | */ |
869 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | 761 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) |
870 | rt2800pci_txdone(rt2x00dev); | 762 | rt2800_txdone(rt2x00dev); |
871 | 763 | ||
872 | /* | 764 | /* |
873 | * 5 - Auto wakeup interrupt. | 765 | * 5 - Auto wakeup interrupt. |
@@ -1011,6 +903,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
1011 | .regbusy_read = rt2x00pci_regbusy_read, | 903 | .regbusy_read = rt2x00pci_regbusy_read, |
1012 | .drv_write_firmware = rt2800pci_write_firmware, | 904 | .drv_write_firmware = rt2800pci_write_firmware, |
1013 | .drv_init_registers = rt2800pci_init_registers, | 905 | .drv_init_registers = rt2800pci_init_registers, |
906 | .drv_get_txwi = rt2800pci_get_txwi, | ||
1014 | }; | 907 | }; |
1015 | 908 | ||
1016 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 909 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
@@ -1030,7 +923,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
1030 | .reset_tuner = rt2800_reset_tuner, | 923 | .reset_tuner = rt2800_reset_tuner, |
1031 | .link_tuner = rt2800_link_tuner, | 924 | .link_tuner = rt2800_link_tuner, |
1032 | .write_tx_desc = rt2800pci_write_tx_desc, | 925 | .write_tx_desc = rt2800pci_write_tx_desc, |
1033 | .write_tx_data = rt2800pci_write_tx_data, | 926 | .write_tx_data = rt2800_write_tx_data, |
1034 | .write_beacon = rt2800_write_beacon, | 927 | .write_beacon = rt2800_write_beacon, |
1035 | .kick_tx_queue = rt2800pci_kick_tx_queue, | 928 | .kick_tx_queue = rt2800pci_kick_tx_queue, |
1036 | .kill_tx_queue = rt2800pci_kill_tx_queue, | 929 | .kill_tx_queue = rt2800pci_kill_tx_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5a2dfe87c6b6..9ad28be294eb 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | 4 | Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> |
4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 5 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
5 | Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | 6 | Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> |
@@ -320,15 +321,14 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
320 | /* | 321 | /* |
321 | * TX descriptor initialization | 322 | * TX descriptor initialization |
322 | */ | 323 | */ |
323 | static void rt2800usb_write_tx_data(struct queue_entry* entry, | 324 | static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) |
324 | struct txentry_desc *txdesc) | ||
325 | { | 325 | { |
326 | __le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); | 326 | if (entry->queue->qid == QID_BEACON) |
327 | 327 | return (__le32 *) (entry->skb->data); | |
328 | rt2800_write_txwi(txwi, txdesc); | 328 | else |
329 | return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); | ||
329 | } | 330 | } |
330 | 331 | ||
331 | |||
332 | static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 332 | static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
333 | struct sk_buff *skb, | 333 | struct sk_buff *skb, |
334 | struct txentry_desc *txdesc) | 334 | struct txentry_desc *txdesc) |
@@ -379,6 +379,38 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry) | |||
379 | } | 379 | } |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * TX control handlers | ||
383 | */ | ||
384 | static void rt2800usb_work_txdone(struct work_struct *work) | ||
385 | { | ||
386 | struct rt2x00_dev *rt2x00dev = | ||
387 | container_of(work, struct rt2x00_dev, txdone_work); | ||
388 | struct data_queue *queue; | ||
389 | struct queue_entry *entry; | ||
390 | |||
391 | rt2800_txdone(rt2x00dev); | ||
392 | |||
393 | /* | ||
394 | * Process any trailing TX status reports for IO failures, | ||
395 | * we loop until we find the first non-IO error entry. This | ||
396 | * can either be a frame which is free, is being uploaded, | ||
397 | * or has completed the upload but didn't have an entry | ||
398 | * in the TX_STAT_FIFO register yet. | ||
399 | */ | ||
400 | tx_queue_for_each(rt2x00dev, queue) { | ||
401 | while (!rt2x00queue_empty(queue)) { | ||
402 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
403 | |||
404 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || | ||
405 | !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
406 | break; | ||
407 | |||
408 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | |||
413 | /* | ||
382 | * RX control handlers | 414 | * RX control handlers |
383 | */ | 415 | */ |
384 | static void rt2800usb_fill_rxdone(struct queue_entry *entry, | 416 | static void rt2800usb_fill_rxdone(struct queue_entry *entry, |
@@ -514,6 +546,11 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
514 | */ | 546 | */ |
515 | rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; | 547 | rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; |
516 | 548 | ||
549 | /* | ||
550 | * Overwrite TX done handler | ||
551 | */ | ||
552 | PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone); | ||
553 | |||
517 | return 0; | 554 | return 0; |
518 | } | 555 | } |
519 | 556 | ||
@@ -549,6 +586,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = { | |||
549 | .regbusy_read = rt2x00usb_regbusy_read, | 586 | .regbusy_read = rt2x00usb_regbusy_read, |
550 | .drv_write_firmware = rt2800usb_write_firmware, | 587 | .drv_write_firmware = rt2800usb_write_firmware, |
551 | .drv_init_registers = rt2800usb_init_registers, | 588 | .drv_init_registers = rt2800usb_init_registers, |
589 | .drv_get_txwi = rt2800usb_get_txwi, | ||
552 | }; | 590 | }; |
553 | 591 | ||
554 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | 592 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { |
@@ -566,7 +604,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
566 | .link_tuner = rt2800_link_tuner, | 604 | .link_tuner = rt2800_link_tuner, |
567 | .watchdog = rt2x00usb_watchdog, | 605 | .watchdog = rt2x00usb_watchdog, |
568 | .write_tx_desc = rt2800usb_write_tx_desc, | 606 | .write_tx_desc = rt2800usb_write_tx_desc, |
569 | .write_tx_data = rt2800usb_write_tx_data, | 607 | .write_tx_data = rt2800_write_tx_data, |
570 | .write_beacon = rt2800_write_beacon, | 608 | .write_beacon = rt2800_write_beacon, |
571 | .get_tx_data_len = rt2800usb_get_tx_data_len, | 609 | .get_tx_data_len = rt2800usb_get_tx_data_len, |
572 | .kick_tx_queue = rt2x00usb_kick_tx_queue, | 610 | .kick_tx_queue = rt2x00usb_kick_tx_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c21af38cc5af..8c65244a847a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 4 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
4 | <http://rt2x00.serialmonkey.com> | 5 | <http://rt2x00.serialmonkey.com> |
5 | 6 | ||
@@ -698,6 +699,7 @@ struct rt2x00_dev { | |||
698 | struct ieee80211_hw *hw; | 699 | struct ieee80211_hw *hw; |
699 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 700 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
700 | enum ieee80211_band curr_band; | 701 | enum ieee80211_band curr_band; |
702 | int curr_freq; | ||
701 | 703 | ||
702 | /* | 704 | /* |
703 | * If enabled, the debugfs interface structures | 705 | * If enabled, the debugfs interface structures |
@@ -850,11 +852,6 @@ struct rt2x00_dev { | |||
850 | struct ieee80211_low_level_stats low_level_stats; | 852 | struct ieee80211_low_level_stats low_level_stats; |
851 | 853 | ||
852 | /* | 854 | /* |
853 | * RX configuration information. | ||
854 | */ | ||
855 | struct ieee80211_rx_status rx_status; | ||
856 | |||
857 | /* | ||
858 | * Scheduled work. | 855 | * Scheduled work. |
859 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() | 856 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() |
860 | * which means it cannot be placed on the hw->workqueue | 857 | * which means it cannot be placed on the hw->workqueue |
@@ -862,6 +859,12 @@ struct rt2x00_dev { | |||
862 | */ | 859 | */ |
863 | struct work_struct intf_work; | 860 | struct work_struct intf_work; |
864 | 861 | ||
862 | /** | ||
863 | * Scheduled work for TX/RX done handling (USB devices) | ||
864 | */ | ||
865 | struct work_struct rxdone_work; | ||
866 | struct work_struct txdone_work; | ||
867 | |||
865 | /* | 868 | /* |
866 | * Data queue arrays for RX, TX and Beacon. | 869 | * Data queue arrays for RX, TX and Beacon. |
867 | * The Beacon array also contains the Atim queue | 870 | * The Beacon array also contains the Atim queue |
@@ -1071,6 +1074,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | |||
1071 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); | 1074 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); |
1072 | void rt2x00lib_txdone(struct queue_entry *entry, | 1075 | void rt2x00lib_txdone(struct queue_entry *entry, |
1073 | struct txdone_entry_desc *txdesc); | 1076 | struct txdone_entry_desc *txdesc); |
1077 | void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); | ||
1074 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | 1078 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, |
1075 | struct queue_entry *entry); | 1079 | struct queue_entry *entry); |
1076 | 1080 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 953dc4f2c6af..34f34fa7f53a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -126,11 +126,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
126 | * ANTENNA_SW_DIVERSITY state to the driver. | 126 | * ANTENNA_SW_DIVERSITY state to the driver. |
127 | * If that happens, fallback to hardware defaults, | 127 | * If that happens, fallback to hardware defaults, |
128 | * or our own default. | 128 | * or our own default. |
129 | * If diversity handling is active for a particular antenna, | ||
130 | * we shouldn't overwrite that antenna. | ||
131 | * The calls to rt2x00lib_config_antenna_check() | ||
132 | * might have caused that we restore back to the already | ||
133 | * active setting. If that has happened we can quit. | ||
134 | */ | 129 | */ |
135 | if (!(ant->flags & ANTENNA_RX_DIVERSITY)) | 130 | if (!(ant->flags & ANTENNA_RX_DIVERSITY)) |
136 | config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); | 131 | config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); |
@@ -142,9 +137,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
142 | else | 137 | else |
143 | config.tx = active->tx; | 138 | config.tx = active->tx; |
144 | 139 | ||
145 | if (config.rx == active->rx && config.tx == active->tx) | ||
146 | return; | ||
147 | |||
148 | /* | 140 | /* |
149 | * Antenna setup changes require the RX to be disabled, | 141 | * Antenna setup changes require the RX to be disabled, |
150 | * else the changes will be ignored by the device. | 142 | * else the changes will be ignored by the device. |
@@ -209,10 +201,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | |||
209 | rt2x00link_reset_tuner(rt2x00dev, false); | 201 | rt2x00link_reset_tuner(rt2x00dev, false); |
210 | 202 | ||
211 | rt2x00dev->curr_band = conf->channel->band; | 203 | rt2x00dev->curr_band = conf->channel->band; |
204 | rt2x00dev->curr_freq = conf->channel->center_freq; | ||
212 | rt2x00dev->tx_power = conf->power_level; | 205 | rt2x00dev->tx_power = conf->power_level; |
213 | rt2x00dev->short_retry = conf->short_frame_max_tx_count; | 206 | rt2x00dev->short_retry = conf->short_frame_max_tx_count; |
214 | rt2x00dev->long_retry = conf->long_frame_max_tx_count; | 207 | rt2x00dev->long_retry = conf->long_frame_max_tx_count; |
215 | |||
216 | rt2x00dev->rx_status.band = conf->channel->band; | ||
217 | rt2x00dev->rx_status.freq = conf->channel->center_freq; | ||
218 | } | 208 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 583dacd8d241..5e9074bf2b8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c | |||
@@ -31,15 +31,14 @@ | |||
31 | 31 | ||
32 | enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) | 32 | enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) |
33 | { | 33 | { |
34 | switch (key->alg) { | 34 | switch (key->cipher) { |
35 | case ALG_WEP: | 35 | case WLAN_CIPHER_SUITE_WEP40: |
36 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 36 | return CIPHER_WEP64; |
37 | return CIPHER_WEP64; | 37 | case WLAN_CIPHER_SUITE_WEP104: |
38 | else | 38 | return CIPHER_WEP128; |
39 | return CIPHER_WEP128; | 39 | case WLAN_CIPHER_SUITE_TKIP: |
40 | case ALG_TKIP: | ||
41 | return CIPHER_TKIP; | 40 | return CIPHER_TKIP; |
42 | case ALG_CCMP: | 41 | case WLAN_CIPHER_SUITE_CCMP: |
43 | return CIPHER_AES; | 42 | return CIPHER_AES; |
44 | default: | 43 | default: |
45 | return CIPHER_NONE; | 44 | return CIPHER_NONE; |
@@ -95,7 +94,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, | |||
95 | overhead += key->iv_len; | 94 | overhead += key->iv_len; |
96 | 95 | ||
97 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { | 96 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
98 | if (key->alg == ALG_TKIP) | 97 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
99 | overhead += 8; | 98 | overhead += 8; |
100 | } | 99 | } |
101 | 100 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 585e8166f22a..e692608bee8b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | 4 | <http://rt2x00.serialmonkey.com> |
4 | 5 | ||
5 | 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 |
@@ -383,15 +384,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
383 | * send the status report back. | 384 | * send the status report back. |
384 | */ | 385 | */ |
385 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) | 386 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) |
386 | /* | 387 | ieee80211_tx_status(rt2x00dev->hw, entry->skb); |
387 | * Only PCI and SOC devices process the tx status in process | ||
388 | * context. Hence use ieee80211_tx_status for PCI and SOC | ||
389 | * devices and stick to ieee80211_tx_status_irqsafe for USB. | ||
390 | */ | ||
391 | if (rt2x00_is_usb(rt2x00dev)) | ||
392 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | ||
393 | else | ||
394 | ieee80211_tx_status(rt2x00dev->hw, entry->skb); | ||
395 | else | 388 | else |
396 | dev_kfree_skb_any(entry->skb); | 389 | dev_kfree_skb_any(entry->skb); |
397 | 390 | ||
@@ -403,7 +396,6 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
403 | 396 | ||
404 | rt2x00dev->ops->lib->clear_entry(entry); | 397 | rt2x00dev->ops->lib->clear_entry(entry); |
405 | 398 | ||
406 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | ||
407 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | 399 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); |
408 | 400 | ||
409 | /* | 401 | /* |
@@ -416,6 +408,18 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
416 | } | 408 | } |
417 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); | 409 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); |
418 | 410 | ||
411 | void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status) | ||
412 | { | ||
413 | struct txdone_entry_desc txdesc; | ||
414 | |||
415 | txdesc.flags = 0; | ||
416 | __set_bit(status, &txdesc.flags); | ||
417 | txdesc.retry = 0; | ||
418 | |||
419 | rt2x00lib_txdone(entry, &txdesc); | ||
420 | } | ||
421 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo); | ||
422 | |||
419 | static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, | 423 | static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, |
420 | struct rxdone_entry_desc *rxdesc) | 424 | struct rxdone_entry_desc *rxdesc) |
421 | { | 425 | { |
@@ -460,9 +464,13 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
460 | { | 464 | { |
461 | struct rxdone_entry_desc rxdesc; | 465 | struct rxdone_entry_desc rxdesc; |
462 | struct sk_buff *skb; | 466 | struct sk_buff *skb; |
463 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; | 467 | struct ieee80211_rx_status *rx_status; |
464 | unsigned int header_length; | 468 | unsigned int header_length; |
465 | int rate_idx; | 469 | int rate_idx; |
470 | |||
471 | if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
472 | goto submit_entry; | ||
473 | |||
466 | /* | 474 | /* |
467 | * Allocate a new sk_buffer. If no new buffer available, drop the | 475 | * Allocate a new sk_buffer. If no new buffer available, drop the |
468 | * received frame and reuse the existing buffer. | 476 | * received frame and reuse the existing buffer. |
@@ -527,39 +535,32 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
527 | */ | 535 | */ |
528 | rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); | 536 | rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); |
529 | rt2x00debug_update_crypto(rt2x00dev, &rxdesc); | 537 | rt2x00debug_update_crypto(rt2x00dev, &rxdesc); |
538 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | ||
530 | 539 | ||
540 | /* | ||
541 | * Initialize RX status information, and send frame | ||
542 | * to mac80211. | ||
543 | */ | ||
544 | rx_status = IEEE80211_SKB_RXCB(entry->skb); | ||
531 | rx_status->mactime = rxdesc.timestamp; | 545 | rx_status->mactime = rxdesc.timestamp; |
546 | rx_status->band = rt2x00dev->curr_band; | ||
547 | rx_status->freq = rt2x00dev->curr_freq; | ||
532 | rx_status->rate_idx = rate_idx; | 548 | rx_status->rate_idx = rate_idx; |
533 | rx_status->signal = rxdesc.rssi; | 549 | rx_status->signal = rxdesc.rssi; |
534 | rx_status->flag = rxdesc.flags; | 550 | rx_status->flag = rxdesc.flags; |
535 | rx_status->antenna = rt2x00dev->link.ant.active.rx; | 551 | rx_status->antenna = rt2x00dev->link.ant.active.rx; |
536 | 552 | ||
537 | /* | 553 | ieee80211_rx_ni(rt2x00dev->hw, entry->skb); |
538 | * Send frame to mac80211 & debugfs. | ||
539 | * mac80211 will clean up the skb structure. | ||
540 | */ | ||
541 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | ||
542 | memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); | ||
543 | |||
544 | /* | ||
545 | * Currently only PCI and SOC devices handle rx interrupts in process | ||
546 | * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni | ||
547 | * for PCI and SOC devices. | ||
548 | */ | ||
549 | if (rt2x00_is_usb(rt2x00dev)) | ||
550 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); | ||
551 | else | ||
552 | ieee80211_rx_ni(rt2x00dev->hw, entry->skb); | ||
553 | 554 | ||
554 | /* | 555 | /* |
555 | * Replace the skb with the freshly allocated one. | 556 | * Replace the skb with the freshly allocated one. |
556 | */ | 557 | */ |
557 | entry->skb = skb; | 558 | entry->skb = skb; |
558 | entry->flags = 0; | ||
559 | 559 | ||
560 | submit_entry: | ||
560 | rt2x00dev->ops->lib->clear_entry(entry); | 561 | rt2x00dev->ops->lib->clear_entry(entry); |
561 | |||
562 | rt2x00queue_index_inc(entry->queue, Q_INDEX); | 562 | rt2x00queue_index_inc(entry->queue, Q_INDEX); |
563 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | ||
563 | } | 564 | } |
564 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); | 565 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); |
565 | 566 | ||
@@ -1017,6 +1018,8 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1017 | * Stop all work. | 1018 | * Stop all work. |
1018 | */ | 1019 | */ |
1019 | cancel_work_sync(&rt2x00dev->intf_work); | 1020 | cancel_work_sync(&rt2x00dev->intf_work); |
1021 | cancel_work_sync(&rt2x00dev->rxdone_work); | ||
1022 | cancel_work_sync(&rt2x00dev->txdone_work); | ||
1020 | 1023 | ||
1021 | /* | 1024 | /* |
1022 | * Uninitialize device. | 1025 | * Uninitialize device. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index b818a43c4672..f0e1eb72befc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c | |||
@@ -63,6 +63,9 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) | |||
63 | 63 | ||
64 | INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", | 64 | INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", |
65 | fw->data[fw->size - 4], fw->data[fw->size - 3]); | 65 | fw->data[fw->size - 4], fw->data[fw->size - 3]); |
66 | snprintf(rt2x00dev->hw->wiphy->fw_version, | ||
67 | sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d", | ||
68 | fw->data[fw->size - 4], fw->data[fw->size - 3]); | ||
66 | 69 | ||
67 | retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); | 70 | retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); |
68 | switch (retval) { | 71 | switch (retval) { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index c004cd3a8847..ad3c7ff4837b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c | |||
@@ -54,6 +54,16 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | |||
54 | */ | 54 | */ |
55 | if (txrate->flags & IEEE80211_TX_RC_MCS) { | 55 | if (txrate->flags & IEEE80211_TX_RC_MCS) { |
56 | txdesc->mcs = txrate->idx; | 56 | txdesc->mcs = txrate->idx; |
57 | |||
58 | /* | ||
59 | * MIMO PS should be set to 1 for STA's using dynamic SM PS | ||
60 | * when using more then one tx stream (>MCS7). | ||
61 | */ | ||
62 | if (tx_info->control.sta && txdesc->mcs > 7 && | ||
63 | (tx_info->control.sta->ht_cap.cap & | ||
64 | (WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
65 | IEEE80211_HT_CAP_SM_PS_SHIFT))) | ||
66 | __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); | ||
57 | } else { | 67 | } else { |
58 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); | 68 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); |
59 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | 69 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9c609be95083..480d33a3ce42 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 4 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
4 | <http://rt2x00.serialmonkey.com> | 5 | <http://rt2x00.serialmonkey.com> |
5 | 6 | ||
@@ -730,9 +731,9 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) | |||
730 | rt2x00queue_reset(queue); | 731 | rt2x00queue_reset(queue); |
731 | 732 | ||
732 | for (i = 0; i < queue->limit; i++) { | 733 | for (i = 0; i < queue->limit; i++) { |
733 | queue->entries[i].flags = 0; | ||
734 | |||
735 | rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); | 734 | rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); |
735 | if (queue->qid == QID_RX) | ||
736 | rt2x00queue_index_inc(queue, Q_INDEX); | ||
736 | } | 737 | } |
737 | } | 738 | } |
738 | } | 739 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 191e7775a9c0..2d3bf843735f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | <http://rt2x00.serialmonkey.com> | 3 | <http://rt2x00.serialmonkey.com> |
4 | 4 | ||
5 | This program is free software; you can redistribute it and/or modify | 5 | This program is free software; you can redistribute it and/or modify |
@@ -268,6 +268,7 @@ struct txdone_entry_desc { | |||
268 | * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. | 268 | * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. |
269 | * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. | 269 | * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. |
270 | * @ENTRY_TXD_HT_SHORT_GI: Use short GI. | 270 | * @ENTRY_TXD_HT_SHORT_GI: Use short GI. |
271 | * @ENTRY_TXD_HT_MIMO_PS: The receiving STA is in dynamic SM PS mode. | ||
271 | */ | 272 | */ |
272 | enum txentry_desc_flags { | 273 | enum txentry_desc_flags { |
273 | ENTRY_TXD_RTS_FRAME, | 274 | ENTRY_TXD_RTS_FRAME, |
@@ -286,6 +287,7 @@ enum txentry_desc_flags { | |||
286 | ENTRY_TXD_HT_AMPDU, | 287 | ENTRY_TXD_HT_AMPDU, |
287 | ENTRY_TXD_HT_BW_40, | 288 | ENTRY_TXD_HT_BW_40, |
288 | ENTRY_TXD_HT_SHORT_GI, | 289 | ENTRY_TXD_HT_SHORT_GI, |
290 | ENTRY_TXD_HT_MIMO_PS, | ||
289 | }; | 291 | }; |
290 | 292 | ||
291 | /** | 293 | /** |
@@ -363,12 +365,16 @@ struct txentry_desc { | |||
363 | * the device has signaled it is done with it. | 365 | * the device has signaled it is done with it. |
364 | * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting | 366 | * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting |
365 | * for the signal to start sending. | 367 | * for the signal to start sending. |
368 | * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured | ||
369 | * while transfering the data to the hardware. No TX status report will | ||
370 | * be expected from the hardware. | ||
366 | */ | 371 | */ |
367 | enum queue_entry_flags { | 372 | enum queue_entry_flags { |
368 | ENTRY_BCN_ASSIGNED, | 373 | ENTRY_BCN_ASSIGNED, |
369 | ENTRY_OWNER_DEVICE_DATA, | 374 | ENTRY_OWNER_DEVICE_DATA, |
370 | ENTRY_OWNER_DEVICE_CRYPTO, | 375 | ENTRY_OWNER_DEVICE_CRYPTO, |
371 | ENTRY_DATA_PENDING, | 376 | ENTRY_DATA_PENDING, |
377 | ENTRY_DATA_IO_FAILED | ||
372 | }; | 378 | }; |
373 | 379 | ||
374 | /** | 380 | /** |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index ff3a36622d1b..f76014f732ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | 4 | <http://rt2x00.serialmonkey.com> |
4 | 5 | ||
5 | 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 |
@@ -167,33 +168,61 @@ EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); | |||
167 | /* | 168 | /* |
168 | * TX data handlers. | 169 | * TX data handlers. |
169 | */ | 170 | */ |
171 | static void rt2x00usb_work_txdone_entry(struct queue_entry *entry) | ||
172 | { | ||
173 | /* | ||
174 | * If the transfer to hardware succeeded, it does not mean the | ||
175 | * frame was send out correctly. It only means the frame | ||
176 | * was succesfully pushed to the hardware, we have no | ||
177 | * way to determine the transmission status right now. | ||
178 | * (Only indirectly by looking at the failed TX counters | ||
179 | * in the register). | ||
180 | */ | ||
181 | if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
182 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
183 | else | ||
184 | rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); | ||
185 | } | ||
186 | |||
187 | static void rt2x00usb_work_txdone(struct work_struct *work) | ||
188 | { | ||
189 | struct rt2x00_dev *rt2x00dev = | ||
190 | container_of(work, struct rt2x00_dev, txdone_work); | ||
191 | struct data_queue *queue; | ||
192 | struct queue_entry *entry; | ||
193 | |||
194 | tx_queue_for_each(rt2x00dev, queue) { | ||
195 | while (!rt2x00queue_empty(queue)) { | ||
196 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
197 | |||
198 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
199 | break; | ||
200 | |||
201 | rt2x00usb_work_txdone_entry(entry); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
170 | static void rt2x00usb_interrupt_txdone(struct urb *urb) | 206 | static void rt2x00usb_interrupt_txdone(struct urb *urb) |
171 | { | 207 | { |
172 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 208 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
173 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 209 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
174 | struct txdone_entry_desc txdesc; | ||
175 | 210 | ||
176 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || | 211 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
177 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 212 | !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
178 | return; | 213 | return; |
179 | 214 | ||
180 | /* | 215 | /* |
181 | * Obtain the status about this packet. | 216 | * Check if the frame was correctly uploaded |
182 | * Note that when the status is 0 it does not mean the | ||
183 | * frame was send out correctly. It only means the frame | ||
184 | * was succesfully pushed to the hardware, we have no | ||
185 | * way to determine the transmission status right now. | ||
186 | * (Only indirectly by looking at the failed TX counters | ||
187 | * in the register). | ||
188 | */ | 217 | */ |
189 | txdesc.flags = 0; | 218 | if (urb->status) |
190 | if (!urb->status) | 219 | __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
191 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | ||
192 | else | ||
193 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
194 | txdesc.retry = 0; | ||
195 | 220 | ||
196 | rt2x00lib_txdone(entry, &txdesc); | 221 | /* |
222 | * Schedule the delayed work for reading the TX status | ||
223 | * from the device. | ||
224 | */ | ||
225 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); | ||
197 | } | 226 | } |
198 | 227 | ||
199 | static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 228 | static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) |
@@ -294,6 +323,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); | |||
294 | 323 | ||
295 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | 324 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) |
296 | { | 325 | { |
326 | struct queue_entry *entry; | ||
297 | struct queue_entry_priv_usb *entry_priv; | 327 | struct queue_entry_priv_usb *entry_priv; |
298 | unsigned short threshold = queue->threshold; | 328 | unsigned short threshold = queue->threshold; |
299 | 329 | ||
@@ -313,14 +343,22 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | |||
313 | * Reset all currently uploaded TX frames. | 343 | * Reset all currently uploaded TX frames. |
314 | */ | 344 | */ |
315 | while (!rt2x00queue_empty(queue)) { | 345 | while (!rt2x00queue_empty(queue)) { |
316 | entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data; | 346 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
347 | entry_priv = entry->priv_data; | ||
317 | usb_kill_urb(entry_priv->urb); | 348 | usb_kill_urb(entry_priv->urb); |
318 | 349 | ||
319 | /* | 350 | /* |
320 | * We need a short delay here to wait for | 351 | * We need a short delay here to wait for |
321 | * the URB to be canceled and invoked the tx_done handler. | 352 | * the URB to be canceled |
353 | */ | ||
354 | do { | ||
355 | udelay(100); | ||
356 | } while (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)); | ||
357 | |||
358 | /* | ||
359 | * Invoke the TX done handler | ||
322 | */ | 360 | */ |
323 | udelay(200); | 361 | rt2x00usb_work_txdone_entry(entry); |
324 | } | 362 | } |
325 | 363 | ||
326 | /* | 364 | /* |
@@ -345,15 +383,41 @@ EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); | |||
345 | /* | 383 | /* |
346 | * RX data handlers. | 384 | * RX data handlers. |
347 | */ | 385 | */ |
386 | static void rt2x00usb_work_rxdone(struct work_struct *work) | ||
387 | { | ||
388 | struct rt2x00_dev *rt2x00dev = | ||
389 | container_of(work, struct rt2x00_dev, rxdone_work); | ||
390 | struct queue_entry *entry; | ||
391 | struct skb_frame_desc *skbdesc; | ||
392 | u8 rxd[32]; | ||
393 | |||
394 | while (!rt2x00queue_empty(rt2x00dev->rx)) { | ||
395 | entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); | ||
396 | |||
397 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
398 | break; | ||
399 | |||
400 | /* | ||
401 | * Fill in desc fields of the skb descriptor | ||
402 | */ | ||
403 | skbdesc = get_skb_frame_desc(entry->skb); | ||
404 | skbdesc->desc = rxd; | ||
405 | skbdesc->desc_len = entry->queue->desc_size; | ||
406 | |||
407 | /* | ||
408 | * Send the frame to rt2x00lib for further processing. | ||
409 | */ | ||
410 | rt2x00lib_rxdone(rt2x00dev, entry); | ||
411 | } | ||
412 | } | ||
413 | |||
348 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) | 414 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) |
349 | { | 415 | { |
350 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 416 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
351 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 417 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
352 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
353 | u8 rxd[32]; | ||
354 | 418 | ||
355 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || | 419 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
356 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 420 | !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
357 | return; | 421 | return; |
358 | 422 | ||
359 | /* | 423 | /* |
@@ -361,22 +425,14 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
361 | * to be actually valid, or if the urb is signaling | 425 | * to be actually valid, or if the urb is signaling |
362 | * a problem. | 426 | * a problem. |
363 | */ | 427 | */ |
364 | if (urb->actual_length < entry->queue->desc_size || urb->status) { | 428 | if (urb->actual_length < entry->queue->desc_size || urb->status) |
365 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 429 | __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
366 | usb_submit_urb(urb, GFP_ATOMIC); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * Fill in desc fields of the skb descriptor | ||
372 | */ | ||
373 | skbdesc->desc = rxd; | ||
374 | skbdesc->desc_len = entry->queue->desc_size; | ||
375 | 430 | ||
376 | /* | 431 | /* |
377 | * Send the frame to rt2x00lib for further processing. | 432 | * Schedule the delayed work for reading the RX status |
433 | * from the device. | ||
378 | */ | 434 | */ |
379 | rt2x00lib_rxdone(rt2x00dev, entry); | 435 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); |
380 | } | 436 | } |
381 | 437 | ||
382 | /* | 438 | /* |
@@ -405,6 +461,8 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
405 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 461 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
406 | int pipe; | 462 | int pipe; |
407 | 463 | ||
464 | entry->flags = 0; | ||
465 | |||
408 | if (entry->queue->qid == QID_RX) { | 466 | if (entry->queue->qid == QID_RX) { |
409 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); | 467 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); |
410 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, | 468 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, |
@@ -413,8 +471,6 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
413 | 471 | ||
414 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 472 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
415 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | 473 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); |
416 | } else { | ||
417 | entry->flags = 0; | ||
418 | } | 474 | } |
419 | } | 475 | } |
420 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 476 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
@@ -659,6 +715,9 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, | |||
659 | 715 | ||
660 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); | 716 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); |
661 | 717 | ||
718 | INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone); | ||
719 | INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); | ||
720 | |||
662 | retval = rt2x00usb_alloc_reg(rt2x00dev); | 721 | retval = rt2x00usb_alloc_reg(rt2x00dev); |
663 | if (retval) | 722 | if (retval) |
664 | goto exit_free_device; | 723 | goto exit_free_device; |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f226582dbc87..3f8d10b76fee 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1050,7 +1050,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
1050 | /* | 1050 | /* |
1051 | * Determine r17 bounds. | 1051 | * Determine r17 bounds. |
1052 | */ | 1052 | */ |
1053 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1053 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1054 | low_bound = 0x28; | 1054 | low_bound = 0x28; |
1055 | up_bound = 0x48; | 1055 | up_bound = 0x48; |
1056 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { | 1056 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { |
@@ -1972,7 +1972,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1972 | return 0; | 1972 | return 0; |
1973 | } | 1973 | } |
1974 | 1974 | ||
1975 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1975 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1976 | if (lna == 3 || lna == 2) | 1976 | if (lna == 3 || lna == 2) |
1977 | offset += 10; | 1977 | offset += 10; |
1978 | } | 1978 | } |
@@ -2107,11 +2107,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2107 | "TX status report missed for entry %d\n", | 2107 | "TX status report missed for entry %d\n", |
2108 | entry_done->entry_idx); | 2108 | entry_done->entry_idx); |
2109 | 2109 | ||
2110 | txdesc.flags = 0; | 2110 | rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); |
2111 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | ||
2112 | txdesc.retry = 0; | ||
2113 | |||
2114 | rt2x00lib_txdone(entry_done, &txdesc); | ||
2115 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 2111 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
2116 | } | 2112 | } |
2117 | 2113 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 99985a218653..8ca19f70aea7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -929,7 +929,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
929 | /* | 929 | /* |
930 | * Determine r17 bounds. | 930 | * Determine r17 bounds. |
931 | */ | 931 | */ |
932 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 932 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
933 | low_bound = 0x28; | 933 | low_bound = 0x28; |
934 | up_bound = 0x48; | 934 | up_bound = 0x48; |
935 | 935 | ||
@@ -1597,7 +1597,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1597 | return 0; | 1597 | return 0; |
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1600 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1601 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { | 1601 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { |
1602 | if (lna == 3 || lna == 2) | 1602 | if (lna == 3 || lna == 2) |
1603 | offset += 10; | 1603 | offset += 10; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 30107ce78dfb..05c6badbe201 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -99,19 +99,66 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | |||
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | static void rtl8180_handle_rx(struct ieee80211_hw *dev) | 102 | static void rtl8180_handle_tx(struct ieee80211_hw *dev) |
103 | { | 103 | { |
104 | struct rtl8180_priv *priv = dev->priv; | 104 | struct rtl8180_priv *priv = dev->priv; |
105 | unsigned int count = 32; | 105 | struct rtl8180_tx_ring *ring; |
106 | int prio; | ||
107 | |||
108 | spin_lock(&priv->lock); | ||
109 | |||
110 | for (prio = 3; prio >= 0; prio--) { | ||
111 | ring = &priv->tx_ring[prio]; | ||
112 | |||
113 | while (skb_queue_len(&ring->queue)) { | ||
114 | struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; | ||
115 | struct sk_buff *skb; | ||
116 | struct ieee80211_tx_info *info; | ||
117 | u32 flags = le32_to_cpu(entry->flags); | ||
118 | |||
119 | if (flags & RTL818X_TX_DESC_FLAG_OWN) | ||
120 | break; | ||
121 | |||
122 | ring->idx = (ring->idx + 1) % ring->entries; | ||
123 | skb = __skb_dequeue(&ring->queue); | ||
124 | pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), | ||
125 | skb->len, PCI_DMA_TODEVICE); | ||
126 | |||
127 | info = IEEE80211_SKB_CB(skb); | ||
128 | ieee80211_tx_info_clear_status(info); | ||
129 | |||
130 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
131 | (flags & RTL818X_TX_DESC_FLAG_TX_OK)) | ||
132 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
133 | |||
134 | info->status.rates[0].count = (flags & 0xFF) + 1; | ||
135 | info->status.rates[1].idx = -1; | ||
136 | |||
137 | ieee80211_tx_status(dev, skb); | ||
138 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | ||
139 | ieee80211_wake_queue(dev, prio); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | spin_unlock(&priv->lock); | ||
144 | } | ||
145 | |||
146 | static int rtl8180_poll(struct ieee80211_hw *dev, int budget) | ||
147 | { | ||
148 | struct rtl8180_priv *priv = dev->priv; | ||
149 | unsigned int count = 0; | ||
106 | u8 signal, agc, sq; | 150 | u8 signal, agc, sq; |
107 | 151 | ||
108 | while (count--) { | 152 | /* handle pending Tx queue cleanup */ |
153 | rtl8180_handle_tx(dev); | ||
154 | |||
155 | while (count++ < budget) { | ||
109 | struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; | 156 | struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; |
110 | struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; | 157 | struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; |
111 | u32 flags = le32_to_cpu(entry->flags); | 158 | u32 flags = le32_to_cpu(entry->flags); |
112 | 159 | ||
113 | if (flags & RTL818X_RX_DESC_FLAG_OWN) | 160 | if (flags & RTL818X_RX_DESC_FLAG_OWN) |
114 | return; | 161 | break; |
115 | 162 | ||
116 | if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | | 163 | if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | |
117 | RTL818X_RX_DESC_FLAG_FOF | | 164 | RTL818X_RX_DESC_FLAG_FOF | |
@@ -151,7 +198,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
151 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | 198 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
152 | 199 | ||
153 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 200 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
154 | ieee80211_rx_irqsafe(dev, skb); | 201 | ieee80211_rx(dev, skb); |
155 | 202 | ||
156 | skb = new_skb; | 203 | skb = new_skb; |
157 | priv->rx_buf[priv->rx_idx] = skb; | 204 | priv->rx_buf[priv->rx_idx] = skb; |
@@ -168,41 +215,16 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
168 | entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); | 215 | entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); |
169 | priv->rx_idx = (priv->rx_idx + 1) % 32; | 216 | priv->rx_idx = (priv->rx_idx + 1) % 32; |
170 | } | 217 | } |
171 | } | ||
172 | 218 | ||
173 | static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) | 219 | if (count < budget) { |
174 | { | 220 | /* disable polling */ |
175 | struct rtl8180_priv *priv = dev->priv; | 221 | ieee80211_napi_complete(dev); |
176 | struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; | ||
177 | 222 | ||
178 | while (skb_queue_len(&ring->queue)) { | 223 | /* enable interrupts */ |
179 | struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; | 224 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); |
180 | struct sk_buff *skb; | ||
181 | struct ieee80211_tx_info *info; | ||
182 | u32 flags = le32_to_cpu(entry->flags); | ||
183 | |||
184 | if (flags & RTL818X_TX_DESC_FLAG_OWN) | ||
185 | return; | ||
186 | |||
187 | ring->idx = (ring->idx + 1) % ring->entries; | ||
188 | skb = __skb_dequeue(&ring->queue); | ||
189 | pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), | ||
190 | skb->len, PCI_DMA_TODEVICE); | ||
191 | |||
192 | info = IEEE80211_SKB_CB(skb); | ||
193 | ieee80211_tx_info_clear_status(info); | ||
194 | |||
195 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
196 | (flags & RTL818X_TX_DESC_FLAG_TX_OK)) | ||
197 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
198 | |||
199 | info->status.rates[0].count = (flags & 0xFF) + 1; | ||
200 | info->status.rates[1].idx = -1; | ||
201 | |||
202 | ieee80211_tx_status_irqsafe(dev, skb); | ||
203 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | ||
204 | ieee80211_wake_queue(dev, prio); | ||
205 | } | 225 | } |
226 | |||
227 | return count; | ||
206 | } | 228 | } |
207 | 229 | ||
208 | static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | 230 | static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) |
@@ -211,31 +233,17 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | |||
211 | struct rtl8180_priv *priv = dev->priv; | 233 | struct rtl8180_priv *priv = dev->priv; |
212 | u16 reg; | 234 | u16 reg; |
213 | 235 | ||
214 | spin_lock(&priv->lock); | ||
215 | reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); | 236 | reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); |
216 | if (unlikely(reg == 0xFFFF)) { | 237 | if (unlikely(reg == 0xFFFF)) |
217 | spin_unlock(&priv->lock); | ||
218 | return IRQ_HANDLED; | 238 | return IRQ_HANDLED; |
219 | } | ||
220 | 239 | ||
221 | rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); | 240 | rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); |
222 | 241 | ||
223 | if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) | 242 | /* disable interrupts */ |
224 | rtl8180_handle_tx(dev, 3); | 243 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); |
225 | |||
226 | if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR)) | ||
227 | rtl8180_handle_tx(dev, 2); | ||
228 | |||
229 | if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR)) | ||
230 | rtl8180_handle_tx(dev, 1); | ||
231 | |||
232 | if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) | ||
233 | rtl8180_handle_tx(dev, 0); | ||
234 | |||
235 | if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) | ||
236 | rtl8180_handle_rx(dev); | ||
237 | 244 | ||
238 | spin_unlock(&priv->lock); | 245 | /* enable polling */ |
246 | ieee80211_napi_schedule(dev); | ||
239 | 247 | ||
240 | return IRQ_HANDLED; | 248 | return IRQ_HANDLED; |
241 | } | 249 | } |
@@ -247,7 +255,6 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
247 | struct rtl8180_priv *priv = dev->priv; | 255 | struct rtl8180_priv *priv = dev->priv; |
248 | struct rtl8180_tx_ring *ring; | 256 | struct rtl8180_tx_ring *ring; |
249 | struct rtl8180_tx_desc *entry; | 257 | struct rtl8180_tx_desc *entry; |
250 | unsigned long flags; | ||
251 | unsigned int idx, prio; | 258 | unsigned int idx, prio; |
252 | dma_addr_t mapping; | 259 | dma_addr_t mapping; |
253 | u32 tx_flags; | 260 | u32 tx_flags; |
@@ -294,7 +301,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
294 | plcp_len |= 1 << 15; | 301 | plcp_len |= 1 << 15; |
295 | } | 302 | } |
296 | 303 | ||
297 | spin_lock_irqsave(&priv->lock, flags); | 304 | spin_lock(&priv->lock); |
298 | 305 | ||
299 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 306 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
300 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 307 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
@@ -318,7 +325,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
318 | if (ring->entries - skb_queue_len(&ring->queue) < 2) | 325 | if (ring->entries - skb_queue_len(&ring->queue) < 2) |
319 | ieee80211_stop_queue(dev, prio); | 326 | ieee80211_stop_queue(dev, prio); |
320 | 327 | ||
321 | spin_unlock_irqrestore(&priv->lock, flags); | 328 | spin_unlock(&priv->lock); |
322 | 329 | ||
323 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); | 330 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); |
324 | 331 | ||
@@ -783,6 +790,7 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
783 | struct rtl8180_priv *priv = dev->priv; | 790 | struct rtl8180_priv *priv = dev->priv; |
784 | struct rtl8180_vif *vif_priv; | 791 | struct rtl8180_vif *vif_priv; |
785 | int i; | 792 | int i; |
793 | u8 reg; | ||
786 | 794 | ||
787 | vif_priv = (struct rtl8180_vif *)&vif->drv_priv; | 795 | vif_priv = (struct rtl8180_vif *)&vif->drv_priv; |
788 | 796 | ||
@@ -791,12 +799,14 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
791 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], | 799 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], |
792 | info->bssid[i]); | 800 | info->bssid[i]); |
793 | 801 | ||
794 | if (is_valid_ether_addr(info->bssid)) | 802 | if (is_valid_ether_addr(info->bssid)) { |
795 | rtl818x_iowrite8(priv, &priv->map->MSR, | 803 | if (vif->type == NL80211_IFTYPE_ADHOC) |
796 | RTL818X_MSR_INFRA); | 804 | reg = RTL818X_MSR_ADHOC; |
797 | else | 805 | else |
798 | rtl818x_iowrite8(priv, &priv->map->MSR, | 806 | reg = RTL818X_MSR_INFRA; |
799 | RTL818X_MSR_NO_LINK); | 807 | } else |
808 | reg = RTL818X_MSR_NO_LINK; | ||
809 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | ||
800 | } | 810 | } |
801 | 811 | ||
802 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) | 812 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) |
@@ -861,6 +871,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
861 | .prepare_multicast = rtl8180_prepare_multicast, | 871 | .prepare_multicast = rtl8180_prepare_multicast, |
862 | .configure_filter = rtl8180_configure_filter, | 872 | .configure_filter = rtl8180_configure_filter, |
863 | .get_tsf = rtl8180_get_tsf, | 873 | .get_tsf = rtl8180_get_tsf, |
874 | .napi_poll = rtl8180_poll, | ||
864 | }; | 875 | }; |
865 | 876 | ||
866 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 877 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
@@ -992,6 +1003,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
992 | dev->queues = 1; | 1003 | dev->queues = 1; |
993 | dev->max_signal = 65; | 1004 | dev->max_signal = 65; |
994 | 1005 | ||
1006 | dev->napi_weight = 64; | ||
1007 | |||
995 | reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); | 1008 | reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); |
996 | reg &= RTL818X_TX_CONF_HWVER_MASK; | 1009 | reg &= RTL818X_TX_CONF_HWVER_MASK; |
997 | switch (reg) { | 1010 | switch (reg) { |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 98e0351c1dd6..38fa8244cc96 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -1176,13 +1176,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, | |||
1176 | else | 1176 | else |
1177 | reg = 0; | 1177 | reg = 0; |
1178 | 1178 | ||
1179 | if (is_valid_ether_addr(info->bssid)) { | 1179 | if (is_valid_ether_addr(info->bssid)) |
1180 | reg |= RTL818X_MSR_INFRA; | 1180 | reg |= RTL818X_MSR_INFRA; |
1181 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | 1181 | else |
1182 | } else { | ||
1183 | reg |= RTL818X_MSR_NO_LINK; | 1182 | reg |= RTL818X_MSR_NO_LINK; |
1184 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | 1183 | |
1185 | } | 1184 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); |
1186 | 1185 | ||
1187 | mutex_unlock(&priv->conf_mutex); | 1186 | mutex_unlock(&priv->conf_mutex); |
1188 | } | 1187 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index 91891f928070..2f8a2ba744dc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c | |||
@@ -380,7 +380,7 @@ int wl1251_acx_pd_threshold(struct wl1251 *wl) | |||
380 | 380 | ||
381 | out: | 381 | out: |
382 | kfree(pd); | 382 | kfree(pd); |
383 | return 0; | 383 | return ret; |
384 | } | 384 | } |
385 | 385 | ||
386 | int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) | 386 | int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) |
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 842df310d92a..a8845b8f2451 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h | |||
@@ -37,7 +37,7 @@ struct acx_header { | |||
37 | 37 | ||
38 | /* payload length (not including headers */ | 38 | /* payload length (not including headers */ |
39 | u16 len; | 39 | u16 len; |
40 | }; | 40 | } __packed; |
41 | 41 | ||
42 | struct acx_error_counter { | 42 | struct acx_error_counter { |
43 | struct acx_header header; | 43 | struct acx_header header; |
@@ -459,8 +459,8 @@ struct acx_beacon_filter_ie_table { | |||
459 | struct acx_header header; | 459 | struct acx_header header; |
460 | 460 | ||
461 | u8 num_ie; | 461 | u8 num_ie; |
462 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
463 | u8 pad[3]; | 462 | u8 pad[3]; |
463 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
464 | } __packed; | 464 | } __packed; |
465 | 465 | ||
466 | #define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */ | 466 | #define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */ |
@@ -471,7 +471,7 @@ struct acx_conn_monit_params { | |||
471 | 471 | ||
472 | u32 synch_fail_thold; /* number of beacons missed */ | 472 | u32 synch_fail_thold; /* number of beacons missed */ |
473 | u32 bss_lose_timeout; /* number of TU's from synch fail */ | 473 | u32 bss_lose_timeout; /* number of TU's from synch fail */ |
474 | }; | 474 | } __packed; |
475 | 475 | ||
476 | enum { | 476 | enum { |
477 | SG_ENABLE = 0, | 477 | SG_ENABLE = 0, |
@@ -1056,7 +1056,7 @@ struct acx_rate_class { | |||
1056 | u8 long_retry_limit; | 1056 | u8 long_retry_limit; |
1057 | u8 aflags; | 1057 | u8 aflags; |
1058 | u8 reserved; | 1058 | u8 reserved; |
1059 | }; | 1059 | } __packed; |
1060 | 1060 | ||
1061 | struct acx_rate_policy { | 1061 | struct acx_rate_policy { |
1062 | struct acx_header header; | 1062 | struct acx_header header; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 65e0416be5b6..5e65f47fda8a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -302,7 +302,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
302 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | | 302 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | |
303 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | | 303 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | |
304 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | | 304 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | |
305 | BT_PTA_PREDICTION_EVENT_ID; | 305 | BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID; |
306 | 306 | ||
307 | ret = wl1251_event_unmask(wl); | 307 | ret = wl1251_event_unmask(wl); |
308 | if (ret < 0) { | 308 | if (ret < 0) { |
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index ce3722f4c3e3..15fb68c6b542 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c | |||
@@ -200,7 +200,7 @@ int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, | |||
200 | 200 | ||
201 | out: | 201 | out: |
202 | kfree(vbm); | 202 | kfree(vbm); |
203 | return 0; | 203 | return ret; |
204 | } | 204 | } |
205 | 205 | ||
206 | int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) | 206 | int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) |
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index a9e4991369be..60d7e522486c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h | |||
@@ -111,7 +111,7 @@ struct wl1251_cmd_header { | |||
111 | struct wl1251_command { | 111 | struct wl1251_command { |
112 | struct wl1251_cmd_header header; | 112 | struct wl1251_cmd_header header; |
113 | u8 parameters[MAX_CMD_PARAMS]; | 113 | u8 parameters[MAX_CMD_PARAMS]; |
114 | }; | 114 | } __packed; |
115 | 115 | ||
116 | enum { | 116 | enum { |
117 | CMD_MAILBOX_IDLE = 0, | 117 | CMD_MAILBOX_IDLE = 0, |
@@ -164,7 +164,7 @@ struct cmd_read_write_memory { | |||
164 | of this field is the Host in WRITE command or the Wilink in READ | 164 | of this field is the Host in WRITE command or the Wilink in READ |
165 | command. */ | 165 | command. */ |
166 | u8 value[MAX_READ_SIZE]; | 166 | u8 value[MAX_READ_SIZE]; |
167 | }; | 167 | } __packed; |
168 | 168 | ||
169 | #define CMDMBOX_HEADER_LEN 4 | 169 | #define CMDMBOX_HEADER_LEN 4 |
170 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | 170 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 |
@@ -339,7 +339,7 @@ struct wl1251_cmd_trigger_scan_to { | |||
339 | struct wl1251_cmd_header header; | 339 | struct wl1251_cmd_header header; |
340 | 340 | ||
341 | u32 timeout; | 341 | u32 timeout; |
342 | }; | 342 | } __packed; |
343 | 343 | ||
344 | /* HW encryption keys */ | 344 | /* HW encryption keys */ |
345 | #define NUM_ACCESS_CATEGORIES_COPY 4 | 345 | #define NUM_ACCESS_CATEGORIES_COPY 4 |
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c index 020d764f9c13..e093a1c5a205 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ b/drivers/net/wireless/wl12xx/wl1251_event.c | |||
@@ -97,6 +97,35 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) | |||
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | 99 | ||
100 | /* | ||
101 | * Poll the mailbox event field until any of the bits in the mask is set or a | ||
102 | * timeout occurs (WL1251_EVENT_TIMEOUT in msecs) | ||
103 | */ | ||
104 | int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms) | ||
105 | { | ||
106 | u32 events_vector, event; | ||
107 | unsigned long timeout; | ||
108 | |||
109 | timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
110 | |||
111 | do { | ||
112 | if (time_after(jiffies, timeout)) | ||
113 | return -ETIMEDOUT; | ||
114 | |||
115 | msleep(1); | ||
116 | |||
117 | /* read from both event fields */ | ||
118 | wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector, | ||
119 | sizeof(events_vector)); | ||
120 | event = events_vector & mask; | ||
121 | wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector, | ||
122 | sizeof(events_vector)); | ||
123 | event |= events_vector & mask; | ||
124 | } while (!event); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
100 | int wl1251_event_unmask(struct wl1251 *wl) | 129 | int wl1251_event_unmask(struct wl1251 *wl) |
101 | { | 130 | { |
102 | int ret; | 131 | int ret; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h index f48a2b66bc5a..ec456474a842 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.h +++ b/drivers/net/wireless/wl12xx/wl1251_event.h | |||
@@ -117,5 +117,6 @@ struct event_mailbox { | |||
117 | int wl1251_event_unmask(struct wl1251 *wl); | 117 | int wl1251_event_unmask(struct wl1251 *wl); |
118 | void wl1251_event_mbox_config(struct wl1251 *wl); | 118 | void wl1251_event_mbox_config(struct wl1251 *wl); |
119 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox); | 119 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox); |
120 | int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms); | ||
120 | 121 | ||
121 | #endif | 122 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 861a5f33761e..c81e95b45c14 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -293,14 +293,14 @@ static void wl1251_irq_work(struct work_struct *work) | |||
293 | wl1251_tx_complete(wl); | 293 | wl1251_tx_complete(wl); |
294 | } | 294 | } |
295 | 295 | ||
296 | if (intr & (WL1251_ACX_INTR_EVENT_A | | 296 | if (intr & WL1251_ACX_INTR_EVENT_A) { |
297 | WL1251_ACX_INTR_EVENT_B)) { | 297 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_A"); |
298 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", | 298 | wl1251_event_handle(wl, 0); |
299 | intr); | 299 | } |
300 | if (intr & WL1251_ACX_INTR_EVENT_A) | 300 | |
301 | wl1251_event_handle(wl, 0); | 301 | if (intr & WL1251_ACX_INTR_EVENT_B) { |
302 | else | 302 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_B"); |
303 | wl1251_event_handle(wl, 1); | 303 | wl1251_event_handle(wl, 1); |
304 | } | 304 | } |
305 | 305 | ||
306 | if (intr & WL1251_ACX_INTR_INIT_COMPLETE) | 306 | if (intr & WL1251_ACX_INTR_INIT_COMPLETE) |
@@ -339,11 +339,9 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, | |||
339 | if (ret < 0) | 339 | if (ret < 0) |
340 | goto out; | 340 | goto out; |
341 | 341 | ||
342 | /* | 342 | ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100); |
343 | * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify | 343 | if (ret < 0) |
344 | * locking we just sleep instead, for now | 344 | wl1251_warning("join timeout"); |
345 | */ | ||
346 | msleep(10); | ||
347 | 345 | ||
348 | out: | 346 | out: |
349 | return ret; | 347 | return ret; |
@@ -725,8 +723,9 @@ static int wl1251_set_key_type(struct wl1251 *wl, | |||
725 | struct ieee80211_key_conf *mac80211_key, | 723 | struct ieee80211_key_conf *mac80211_key, |
726 | const u8 *addr) | 724 | const u8 *addr) |
727 | { | 725 | { |
728 | switch (mac80211_key->alg) { | 726 | switch (mac80211_key->cipher) { |
729 | case ALG_WEP: | 727 | case WLAN_CIPHER_SUITE_WEP40: |
728 | case WLAN_CIPHER_SUITE_WEP104: | ||
730 | if (is_broadcast_ether_addr(addr)) | 729 | if (is_broadcast_ether_addr(addr)) |
731 | key->key_type = KEY_WEP_DEFAULT; | 730 | key->key_type = KEY_WEP_DEFAULT; |
732 | else | 731 | else |
@@ -734,7 +733,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, | |||
734 | 733 | ||
735 | mac80211_key->hw_key_idx = mac80211_key->keyidx; | 734 | mac80211_key->hw_key_idx = mac80211_key->keyidx; |
736 | break; | 735 | break; |
737 | case ALG_TKIP: | 736 | case WLAN_CIPHER_SUITE_TKIP: |
738 | if (is_broadcast_ether_addr(addr)) | 737 | if (is_broadcast_ether_addr(addr)) |
739 | key->key_type = KEY_TKIP_MIC_GROUP; | 738 | key->key_type = KEY_TKIP_MIC_GROUP; |
740 | else | 739 | else |
@@ -742,7 +741,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, | |||
742 | 741 | ||
743 | mac80211_key->hw_key_idx = mac80211_key->keyidx; | 742 | mac80211_key->hw_key_idx = mac80211_key->keyidx; |
744 | break; | 743 | break; |
745 | case ALG_CCMP: | 744 | case WLAN_CIPHER_SUITE_CCMP: |
746 | if (is_broadcast_ether_addr(addr)) | 745 | if (is_broadcast_ether_addr(addr)) |
747 | key->key_type = KEY_AES_GROUP; | 746 | key->key_type = KEY_AES_GROUP; |
748 | else | 747 | else |
@@ -750,7 +749,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, | |||
750 | mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 749 | mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
751 | break; | 750 | break; |
752 | default: | 751 | default: |
753 | wl1251_error("Unknown key algo 0x%x", mac80211_key->alg); | 752 | wl1251_error("Unknown key cipher 0x%x", mac80211_key->cipher); |
754 | return -EOPNOTSUPP; | 753 | return -EOPNOTSUPP; |
755 | } | 754 | } |
756 | 755 | ||
@@ -783,7 +782,7 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
783 | wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); | 782 | wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); |
784 | wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); | 783 | wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); |
785 | wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", | 784 | wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", |
786 | key->alg, key->keyidx, key->keylen, key->flags); | 785 | key->cipher, key->keyidx, key->keylen, key->flags); |
787 | wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); | 786 | wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); |
788 | 787 | ||
789 | if (is_zero_ether_addr(addr)) { | 788 | if (is_zero_ether_addr(addr)) { |
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index a38ec199187a..6634b3e27cfc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c | |||
@@ -189,7 +189,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
189 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; | 189 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; |
190 | 190 | ||
191 | if (control->control.hw_key && | 191 | if (control->control.hw_key && |
192 | control->control.hw_key->alg == ALG_TKIP) { | 192 | control->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
193 | int hdrlen; | 193 | int hdrlen; |
194 | __le16 fc; | 194 | __le16 fc; |
195 | u16 length; | 195 | u16 length; |
@@ -399,7 +399,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl, | |||
399 | */ | 399 | */ |
400 | frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); | 400 | frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); |
401 | if (info->control.hw_key && | 401 | if (info->control.hw_key && |
402 | info->control.hw_key->alg == ALG_TKIP) { | 402 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
403 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 403 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
404 | memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen); | 404 | memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen); |
405 | skb_pull(skb, WL1251_TKIP_IV_SPACE); | 405 | skb_pull(skb, WL1251_TKIP_IV_SPACE); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index bb245f05af49..f03ad088db8b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -269,7 +269,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl) | |||
269 | 269 | ||
270 | out: | 270 | out: |
271 | kfree(pd); | 271 | kfree(pd); |
272 | return 0; | 272 | return ret; |
273 | } | 273 | } |
274 | 274 | ||
275 | int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) | 275 | int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 9d68f0012f05..30194c0f36a9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -1439,7 +1439,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1439 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); | 1439 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); |
1440 | wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); | 1440 | wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); |
1441 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", | 1441 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", |
1442 | key_conf->alg, key_conf->keyidx, | 1442 | key_conf->cipher, key_conf->keyidx, |
1443 | key_conf->keylen, key_conf->flags); | 1443 | key_conf->keylen, key_conf->flags); |
1444 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); | 1444 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); |
1445 | 1445 | ||
@@ -1455,20 +1455,21 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1455 | if (ret < 0) | 1455 | if (ret < 0) |
1456 | goto out_unlock; | 1456 | goto out_unlock; |
1457 | 1457 | ||
1458 | switch (key_conf->alg) { | 1458 | switch (key_conf->cipher) { |
1459 | case ALG_WEP: | 1459 | case WLAN_CIPHER_SUITE_WEP40: |
1460 | case WLAN_CIPHER_SUITE_WEP104: | ||
1460 | key_type = KEY_WEP; | 1461 | key_type = KEY_WEP; |
1461 | 1462 | ||
1462 | key_conf->hw_key_idx = key_conf->keyidx; | 1463 | key_conf->hw_key_idx = key_conf->keyidx; |
1463 | break; | 1464 | break; |
1464 | case ALG_TKIP: | 1465 | case WLAN_CIPHER_SUITE_TKIP: |
1465 | key_type = KEY_TKIP; | 1466 | key_type = KEY_TKIP; |
1466 | 1467 | ||
1467 | key_conf->hw_key_idx = key_conf->keyidx; | 1468 | key_conf->hw_key_idx = key_conf->keyidx; |
1468 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 1469 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1469 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 1470 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1470 | break; | 1471 | break; |
1471 | case ALG_CCMP: | 1472 | case WLAN_CIPHER_SUITE_CCMP: |
1472 | key_type = KEY_AES; | 1473 | key_type = KEY_AES; |
1473 | 1474 | ||
1474 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1475 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
@@ -1476,7 +1477,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1476 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 1477 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1477 | break; | 1478 | break; |
1478 | default: | 1479 | default: |
1479 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1480 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); |
1480 | 1481 | ||
1481 | ret = -EOPNOTSUPP; | 1482 | ret = -EOPNOTSUPP; |
1482 | goto out_sleep; | 1483 | goto out_sleep; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index c592cc2e9fe8..dc0b46c93c4b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -193,7 +193,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
193 | info = IEEE80211_SKB_CB(skb); | 193 | info = IEEE80211_SKB_CB(skb); |
194 | 194 | ||
195 | if (info->control.hw_key && | 195 | if (info->control.hw_key && |
196 | info->control.hw_key->alg == ALG_TKIP) | 196 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) |
197 | extra = WL1271_TKIP_IV_SPACE; | 197 | extra = WL1271_TKIP_IV_SPACE; |
198 | 198 | ||
199 | if (info->control.hw_key) { | 199 | if (info->control.hw_key) { |
@@ -347,7 +347,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
347 | 347 | ||
348 | /* remove TKIP header space if present */ | 348 | /* remove TKIP header space if present */ |
349 | if (info->control.hw_key && | 349 | if (info->control.hw_key && |
350 | info->control.hw_key->alg == ALG_TKIP) { | 350 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
351 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 351 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
352 | memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); | 352 | memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); |
353 | skb_pull(skb, WL1271_TKIP_IV_SPACE); | 353 | skb_pull(skb, WL1271_TKIP_IV_SPACE); |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index b2af3c549bb3..87a95bcfee57 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -973,6 +973,7 @@ static void dump_fw_registers(struct zd_chip *chip) | |||
973 | 973 | ||
974 | static int print_fw_version(struct zd_chip *chip) | 974 | static int print_fw_version(struct zd_chip *chip) |
975 | { | 975 | { |
976 | struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy; | ||
976 | int r; | 977 | int r; |
977 | u16 version; | 978 | u16 version; |
978 | 979 | ||
@@ -982,6 +983,10 @@ static int print_fw_version(struct zd_chip *chip) | |||
982 | return r; | 983 | return r; |
983 | 984 | ||
984 | dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); | 985 | dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); |
986 | |||
987 | snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), | ||
988 | "%04hx", version); | ||
989 | |||
985 | return 0; | 990 | return 0; |
986 | } | 991 | } |
987 | 992 | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 59962dbc2758..0cf9448a32c4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -2171,6 +2171,8 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); | |||
2171 | extern int netdev_class_create_file(struct class_attribute *class_attr); | 2171 | extern int netdev_class_create_file(struct class_attribute *class_attr); |
2172 | extern void netdev_class_remove_file(struct class_attribute *class_attr); | 2172 | extern void netdev_class_remove_file(struct class_attribute *class_attr); |
2173 | 2173 | ||
2174 | extern struct kobj_ns_type_operations net_ns_type_operations; | ||
2175 | |||
2174 | extern char *netdev_drivername(const struct net_device *dev, char *buffer, int len); | 2176 | extern char *netdev_drivername(const struct net_device *dev, char *buffer, int len); |
2175 | 2177 | ||
2176 | extern void linkwatch_run_queue(void); | 2178 | extern void linkwatch_run_queue(void); |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2c8701687336..ec1690da7845 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -40,6 +40,43 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * DOC: Frame transmission/registration support | ||
44 | * | ||
45 | * Frame transmission and registration support exists to allow userspace | ||
46 | * management entities such as wpa_supplicant react to management frames | ||
47 | * that are not being handled by the kernel. This includes, for example, | ||
48 | * certain classes of action frames that cannot be handled in the kernel | ||
49 | * for various reasons. | ||
50 | * | ||
51 | * Frame registration is done on a per-interface basis and registrations | ||
52 | * cannot be removed other than by closing the socket. It is possible to | ||
53 | * specify a registration filter to register, for example, only for a | ||
54 | * certain type of action frame. In particular with action frames, those | ||
55 | * that userspace registers for will not be returned as unhandled by the | ||
56 | * driver, so that the registered application has to take responsibility | ||
57 | * for doing that. | ||
58 | * | ||
59 | * The type of frame that can be registered for is also dependent on the | ||
60 | * driver and interface type. The frame types are advertised in wiphy | ||
61 | * attributes so applications know what to expect. | ||
62 | * | ||
63 | * NOTE: When an interface changes type while registrations are active, | ||
64 | * these registrations are ignored until the interface type is | ||
65 | * changed again. This means that changing the interface type can | ||
66 | * lead to a situation that couldn't otherwise be produced, but | ||
67 | * any such registrations will be dormant in the sense that they | ||
68 | * will not be serviced, i.e. they will not receive any frames. | ||
69 | * | ||
70 | * Frame transmission allows userspace to send for example the required | ||
71 | * responses to action frames. It is subject to some sanity checking, | ||
72 | * but many frames can be transmitted. When a frame was transmitted, its | ||
73 | * status is indicated to the sending socket. | ||
74 | * | ||
75 | * For more technical details, see the corresponding command descriptions | ||
76 | * below. | ||
77 | */ | ||
78 | |||
79 | /** | ||
43 | * enum nl80211_commands - supported nl80211 commands | 80 | * enum nl80211_commands - supported nl80211 commands |
44 | * | 81 | * |
45 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors | 82 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors |
@@ -301,16 +338,20 @@ | |||
301 | * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface | 338 | * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface |
302 | * and @NL80211_ATTR_TX_RATES the set of allowed rates. | 339 | * and @NL80211_ATTR_TX_RATES the set of allowed rates. |
303 | * | 340 | * |
304 | * @NL80211_CMD_REGISTER_ACTION: Register for receiving certain action frames | 341 | * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames |
305 | * (via @NL80211_CMD_ACTION) for processing in userspace. This command | 342 | * (via @NL80211_CMD_FRAME) for processing in userspace. This command |
306 | * requires an interface index and a match attribute containing the first | 343 | * requires an interface index, a frame type attribute (optional for |
307 | * few bytes of the frame that should match, e.g. a single byte for only | 344 | * backward compatibility reasons, if not given assumes action frames) |
308 | * a category match or four bytes for vendor frames including the OUI. | 345 | * and a match attribute containing the first few bytes of the frame |
309 | * The registration cannot be dropped, but is removed automatically | 346 | * that should match, e.g. a single byte for only a category match or |
310 | * when the netlink socket is closed. Multiple registrations can be made. | 347 | * four bytes for vendor frames including the OUI. The registration |
311 | * @NL80211_CMD_ACTION: Action frame TX request and RX notification. This | 348 | * cannot be dropped, but is removed automatically when the netlink |
312 | * command is used both as a request to transmit an Action frame and as an | 349 | * socket is closed. Multiple registrations can be made. |
313 | * event indicating reception of an Action frame that was not processed in | 350 | * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for |
351 | * backward compatibility | ||
352 | * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This | ||
353 | * command is used both as a request to transmit a management frame and | ||
354 | * as an event indicating reception of a frame that was not processed in | ||
314 | * kernel code, but is for us (i.e., which may need to be processed in a | 355 | * kernel code, but is for us (i.e., which may need to be processed in a |
315 | * user space application). %NL80211_ATTR_FRAME is used to specify the | 356 | * user space application). %NL80211_ATTR_FRAME is used to specify the |
316 | * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and | 357 | * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and |
@@ -320,11 +361,14 @@ | |||
320 | * operational channel). When called, this operation returns a cookie | 361 | * operational channel). When called, this operation returns a cookie |
321 | * (%NL80211_ATTR_COOKIE) that will be included with the TX status event | 362 | * (%NL80211_ATTR_COOKIE) that will be included with the TX status event |
322 | * pertaining to the TX request. | 363 | * pertaining to the TX request. |
323 | * @NL80211_CMD_ACTION_TX_STATUS: Report TX status of an Action frame | 364 | * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. |
324 | * transmitted with %NL80211_CMD_ACTION. %NL80211_ATTR_COOKIE identifies | 365 | * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame |
366 | * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies | ||
325 | * the TX command and %NL80211_ATTR_FRAME includes the contents of the | 367 | * the TX command and %NL80211_ATTR_FRAME includes the contents of the |
326 | * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged | 368 | * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged |
327 | * the frame. | 369 | * the frame. |
370 | * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for | ||
371 | * backward compatibility. | ||
328 | * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command | 372 | * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command |
329 | * is used to configure connection quality monitoring notification trigger | 373 | * is used to configure connection quality monitoring notification trigger |
330 | * levels. | 374 | * levels. |
@@ -429,9 +473,12 @@ enum nl80211_commands { | |||
429 | 473 | ||
430 | NL80211_CMD_SET_TX_BITRATE_MASK, | 474 | NL80211_CMD_SET_TX_BITRATE_MASK, |
431 | 475 | ||
432 | NL80211_CMD_REGISTER_ACTION, | 476 | NL80211_CMD_REGISTER_FRAME, |
433 | NL80211_CMD_ACTION, | 477 | NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME, |
434 | NL80211_CMD_ACTION_TX_STATUS, | 478 | NL80211_CMD_FRAME, |
479 | NL80211_CMD_ACTION = NL80211_CMD_FRAME, | ||
480 | NL80211_CMD_FRAME_TX_STATUS, | ||
481 | NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS, | ||
435 | 482 | ||
436 | NL80211_CMD_SET_POWER_SAVE, | 483 | NL80211_CMD_SET_POWER_SAVE, |
437 | NL80211_CMD_GET_POWER_SAVE, | 484 | NL80211_CMD_GET_POWER_SAVE, |
@@ -708,7 +755,16 @@ enum nl80211_commands { | |||
708 | * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. | 755 | * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. |
709 | * | 756 | * |
710 | * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain | 757 | * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain |
711 | * at least one byte, currently used with @NL80211_CMD_REGISTER_ACTION. | 758 | * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. |
759 | * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the | ||
760 | * @NL80211_CMD_REGISTER_FRAME command. | ||
761 | * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a | ||
762 | * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing | ||
763 | * information about which frame types can be transmitted with | ||
764 | * %NL80211_CMD_FRAME. | ||
765 | * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a | ||
766 | * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing | ||
767 | * information about which frame types can be registered for RX. | ||
712 | * | 768 | * |
713 | * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was | 769 | * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was |
714 | * acknowledged by the recipient. | 770 | * acknowledged by the recipient. |
@@ -891,6 +947,10 @@ enum nl80211_attrs { | |||
891 | NL80211_ATTR_WIPHY_TX_POWER_SETTING, | 947 | NL80211_ATTR_WIPHY_TX_POWER_SETTING, |
892 | NL80211_ATTR_WIPHY_TX_POWER_LEVEL, | 948 | NL80211_ATTR_WIPHY_TX_POWER_LEVEL, |
893 | 949 | ||
950 | NL80211_ATTR_TX_FRAME_TYPES, | ||
951 | NL80211_ATTR_RX_FRAME_TYPES, | ||
952 | NL80211_ATTR_FRAME_TYPE, | ||
953 | |||
894 | /* add attributes here, update the policy in nl80211.c */ | 954 | /* add attributes here, update the policy in nl80211.c */ |
895 | 955 | ||
896 | __NL80211_ATTR_AFTER_LAST, | 956 | __NL80211_ATTR_AFTER_LAST, |
@@ -947,7 +1007,7 @@ enum nl80211_attrs { | |||
947 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames | 1007 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames |
948 | * @NL80211_IFTYPE_MESH_POINT: mesh point | 1008 | * @NL80211_IFTYPE_MESH_POINT: mesh point |
949 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined | 1009 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined |
950 | * @__NL80211_IFTYPE_AFTER_LAST: internal use | 1010 | * @NUM_NL80211_IFTYPES: number of defined interface types |
951 | * | 1011 | * |
952 | * These values are used with the %NL80211_ATTR_IFTYPE | 1012 | * These values are used with the %NL80211_ATTR_IFTYPE |
953 | * to set the type of an interface. | 1013 | * to set the type of an interface. |
@@ -964,8 +1024,8 @@ enum nl80211_iftype { | |||
964 | NL80211_IFTYPE_MESH_POINT, | 1024 | NL80211_IFTYPE_MESH_POINT, |
965 | 1025 | ||
966 | /* keep last */ | 1026 | /* keep last */ |
967 | __NL80211_IFTYPE_AFTER_LAST, | 1027 | NUM_NL80211_IFTYPES, |
968 | NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 | 1028 | NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1 |
969 | }; | 1029 | }; |
970 | 1030 | ||
971 | /** | 1031 | /** |
@@ -974,11 +1034,14 @@ enum nl80211_iftype { | |||
974 | * Station flags. When a station is added to an AP interface, it is | 1034 | * Station flags. When a station is added to an AP interface, it is |
975 | * assumed to be already associated (and hence authenticated.) | 1035 | * assumed to be already associated (and hence authenticated.) |
976 | * | 1036 | * |
1037 | * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved | ||
977 | * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) | 1038 | * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) |
978 | * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames | 1039 | * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames |
979 | * with short barker preamble | 1040 | * with short barker preamble |
980 | * @NL80211_STA_FLAG_WME: station is WME/QoS capable | 1041 | * @NL80211_STA_FLAG_WME: station is WME/QoS capable |
981 | * @NL80211_STA_FLAG_MFP: station uses management frame protection | 1042 | * @NL80211_STA_FLAG_MFP: station uses management frame protection |
1043 | * @NL80211_STA_FLAG_MAX: highest station flag number currently defined | ||
1044 | * @__NL80211_STA_FLAG_AFTER_LAST: internal use | ||
982 | */ | 1045 | */ |
983 | enum nl80211_sta_flags { | 1046 | enum nl80211_sta_flags { |
984 | __NL80211_STA_FLAG_INVALID, | 1047 | __NL80211_STA_FLAG_INVALID, |
@@ -1091,14 +1154,17 @@ enum nl80211_mpath_flags { | |||
1091 | * information about a mesh path. | 1154 | * information about a mesh path. |
1092 | * | 1155 | * |
1093 | * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved | 1156 | * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved |
1094 | * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination | 1157 | * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination |
1095 | * @NL80211_ATTR_MPATH_SN: destination sequence number | 1158 | * @NL80211_MPATH_INFO_SN: destination sequence number |
1096 | * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path | 1159 | * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path |
1097 | * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now | 1160 | * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now |
1098 | * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in | 1161 | * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in |
1099 | * &enum nl80211_mpath_flags; | 1162 | * &enum nl80211_mpath_flags; |
1100 | * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec | 1163 | * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec |
1101 | * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries | 1164 | * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries |
1165 | * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number | ||
1166 | * currently defind | ||
1167 | * @__NL80211_MPATH_INFO_AFTER_LAST: internal use | ||
1102 | */ | 1168 | */ |
1103 | enum nl80211_mpath_info { | 1169 | enum nl80211_mpath_info { |
1104 | __NL80211_MPATH_INFO_INVALID, | 1170 | __NL80211_MPATH_INFO_INVALID, |
@@ -1127,6 +1193,8 @@ enum nl80211_mpath_info { | |||
1127 | * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE | 1193 | * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE |
1128 | * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n | 1194 | * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n |
1129 | * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n | 1195 | * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n |
1196 | * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined | ||
1197 | * @__NL80211_BAND_ATTR_AFTER_LAST: internal use | ||
1130 | */ | 1198 | */ |
1131 | enum nl80211_band_attr { | 1199 | enum nl80211_band_attr { |
1132 | __NL80211_BAND_ATTR_INVALID, | 1200 | __NL80211_BAND_ATTR_INVALID, |
@@ -1147,6 +1215,7 @@ enum nl80211_band_attr { | |||
1147 | 1215 | ||
1148 | /** | 1216 | /** |
1149 | * enum nl80211_frequency_attr - frequency attributes | 1217 | * enum nl80211_frequency_attr - frequency attributes |
1218 | * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved | ||
1150 | * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz | 1219 | * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz |
1151 | * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current | 1220 | * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current |
1152 | * regulatory domain. | 1221 | * regulatory domain. |
@@ -1158,6 +1227,9 @@ enum nl80211_band_attr { | |||
1158 | * on this channel in current regulatory domain. | 1227 | * on this channel in current regulatory domain. |
1159 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm | 1228 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm |
1160 | * (100 * dBm). | 1229 | * (100 * dBm). |
1230 | * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number | ||
1231 | * currently defined | ||
1232 | * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use | ||
1161 | */ | 1233 | */ |
1162 | enum nl80211_frequency_attr { | 1234 | enum nl80211_frequency_attr { |
1163 | __NL80211_FREQUENCY_ATTR_INVALID, | 1235 | __NL80211_FREQUENCY_ATTR_INVALID, |
@@ -1177,9 +1249,13 @@ enum nl80211_frequency_attr { | |||
1177 | 1249 | ||
1178 | /** | 1250 | /** |
1179 | * enum nl80211_bitrate_attr - bitrate attributes | 1251 | * enum nl80211_bitrate_attr - bitrate attributes |
1252 | * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved | ||
1180 | * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps | 1253 | * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps |
1181 | * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported | 1254 | * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported |
1182 | * in 2.4 GHz band. | 1255 | * in 2.4 GHz band. |
1256 | * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number | ||
1257 | * currently defined | ||
1258 | * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use | ||
1183 | */ | 1259 | */ |
1184 | enum nl80211_bitrate_attr { | 1260 | enum nl80211_bitrate_attr { |
1185 | __NL80211_BITRATE_ATTR_INVALID, | 1261 | __NL80211_BITRATE_ATTR_INVALID, |
@@ -1235,6 +1311,7 @@ enum nl80211_reg_type { | |||
1235 | 1311 | ||
1236 | /** | 1312 | /** |
1237 | * enum nl80211_reg_rule_attr - regulatory rule attributes | 1313 | * enum nl80211_reg_rule_attr - regulatory rule attributes |
1314 | * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved | ||
1238 | * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional | 1315 | * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional |
1239 | * considerations for a given frequency range. These are the | 1316 | * considerations for a given frequency range. These are the |
1240 | * &enum nl80211_reg_rule_flags. | 1317 | * &enum nl80211_reg_rule_flags. |
@@ -1251,6 +1328,9 @@ enum nl80211_reg_type { | |||
1251 | * If you don't have one then don't send this. | 1328 | * If you don't have one then don't send this. |
1252 | * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for | 1329 | * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for |
1253 | * a given frequency range. The value is in mBm (100 * dBm). | 1330 | * a given frequency range. The value is in mBm (100 * dBm). |
1331 | * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number | ||
1332 | * currently defined | ||
1333 | * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use | ||
1254 | */ | 1334 | */ |
1255 | enum nl80211_reg_rule_attr { | 1335 | enum nl80211_reg_rule_attr { |
1256 | __NL80211_REG_RULE_ATTR_INVALID, | 1336 | __NL80211_REG_RULE_ATTR_INVALID, |
@@ -1302,6 +1382,9 @@ enum nl80211_reg_rule_flags { | |||
1302 | * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved | 1382 | * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved |
1303 | * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel | 1383 | * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel |
1304 | * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) | 1384 | * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) |
1385 | * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number | ||
1386 | * currently defined | ||
1387 | * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use | ||
1305 | */ | 1388 | */ |
1306 | enum nl80211_survey_info { | 1389 | enum nl80211_survey_info { |
1307 | __NL80211_SURVEY_INFO_INVALID, | 1390 | __NL80211_SURVEY_INFO_INVALID, |
@@ -1466,6 +1549,7 @@ enum nl80211_channel_type { | |||
1466 | * enum nl80211_bss - netlink attributes for a BSS | 1549 | * enum nl80211_bss - netlink attributes for a BSS |
1467 | * | 1550 | * |
1468 | * @__NL80211_BSS_INVALID: invalid | 1551 | * @__NL80211_BSS_INVALID: invalid |
1552 | * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets) | ||
1469 | * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) | 1553 | * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) |
1470 | * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) | 1554 | * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) |
1471 | * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) | 1555 | * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) |
@@ -1509,6 +1593,12 @@ enum nl80211_bss { | |||
1509 | 1593 | ||
1510 | /** | 1594 | /** |
1511 | * enum nl80211_bss_status - BSS "status" | 1595 | * enum nl80211_bss_status - BSS "status" |
1596 | * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS. | ||
1597 | * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS. | ||
1598 | * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS. | ||
1599 | * | ||
1600 | * The BSS status is a BSS attribute in scan dumps, which | ||
1601 | * indicates the status the interface has wrt. this BSS. | ||
1512 | */ | 1602 | */ |
1513 | enum nl80211_bss_status { | 1603 | enum nl80211_bss_status { |
1514 | NL80211_BSS_STATUS_AUTHENTICATED, | 1604 | NL80211_BSS_STATUS_AUTHENTICATED, |
@@ -1619,8 +1709,8 @@ enum nl80211_tx_rate_attributes { | |||
1619 | 1709 | ||
1620 | /** | 1710 | /** |
1621 | * enum nl80211_band - Frequency band | 1711 | * enum nl80211_band - Frequency band |
1622 | * @NL80211_BAND_2GHZ - 2.4 GHz ISM band | 1712 | * @NL80211_BAND_2GHZ: 2.4 GHz ISM band |
1623 | * @NL80211_BAND_5GHZ - around 5 GHz band (4.9 - 5.7 GHz) | 1713 | * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) |
1624 | */ | 1714 | */ |
1625 | enum nl80211_band { | 1715 | enum nl80211_band { |
1626 | NL80211_BAND_2GHZ, | 1716 | NL80211_BAND_2GHZ, |
@@ -1658,9 +1748,9 @@ enum nl80211_attr_cqm { | |||
1658 | 1748 | ||
1659 | /** | 1749 | /** |
1660 | * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event | 1750 | * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event |
1661 | * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW - The RSSI level is lower than the | 1751 | * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the |
1662 | * configured threshold | 1752 | * configured threshold |
1663 | * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH - The RSSI is higher than the | 1753 | * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the |
1664 | * configured threshold | 1754 | * configured threshold |
1665 | */ | 1755 | */ |
1666 | enum nl80211_cqm_rssi_threshold_event { | 1756 | enum nl80211_cqm_rssi_threshold_event { |
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index a6d5225b9275..11daf9c140e7 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h | |||
@@ -97,6 +97,7 @@ | |||
97 | #define SSB_TMSLOW_RESET 0x00000001 /* Reset */ | 97 | #define SSB_TMSLOW_RESET 0x00000001 /* Reset */ |
98 | #define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */ | 98 | #define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */ |
99 | #define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */ | 99 | #define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */ |
100 | #define SSB_TMSLOW_PHYCLK 0x00000010 /* MAC PHY Clock Control Enable */ | ||
100 | #define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */ | 101 | #define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */ |
101 | #define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */ | 102 | #define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */ |
102 | #define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */ | 103 | #define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2fd06c60ffbb..f2740537b5d6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -25,6 +25,43 @@ | |||
25 | #include <linux/wireless.h> | 25 | #include <linux/wireless.h> |
26 | 26 | ||
27 | 27 | ||
28 | /** | ||
29 | * DOC: Introduction | ||
30 | * | ||
31 | * cfg80211 is the configuration API for 802.11 devices in Linux. It bridges | ||
32 | * userspace and drivers, and offers some utility functionality associated | ||
33 | * with 802.11. cfg80211 must, directly or indirectly via mac80211, be used | ||
34 | * by all modern wireless drivers in Linux, so that they offer a consistent | ||
35 | * API through nl80211. For backward compatibility, cfg80211 also offers | ||
36 | * wireless extensions to userspace, but hides them from drivers completely. | ||
37 | * | ||
38 | * Additionally, cfg80211 contains code to help enforce regulatory spectrum | ||
39 | * use restrictions. | ||
40 | */ | ||
41 | |||
42 | |||
43 | /** | ||
44 | * DOC: Device registration | ||
45 | * | ||
46 | * In order for a driver to use cfg80211, it must register the hardware device | ||
47 | * with cfg80211. This happens through a number of hardware capability structs | ||
48 | * described below. | ||
49 | * | ||
50 | * The fundamental structure for each device is the 'wiphy', of which each | ||
51 | * instance describes a physical wireless device connected to the system. Each | ||
52 | * such wiphy can have zero, one, or many virtual interfaces associated with | ||
53 | * it, which need to be identified as such by pointing the network interface's | ||
54 | * @ieee80211_ptr pointer to a &struct wireless_dev which further describes | ||
55 | * the wireless part of the interface, normally this struct is embedded in the | ||
56 | * network interface's private data area. Drivers can optionally allow creating | ||
57 | * or destroying virtual interfaces on the fly, but without at least one or the | ||
58 | * ability to create some the wireless device isn't useful. | ||
59 | * | ||
60 | * Each wiphy structure contains device capability information, and also has | ||
61 | * a pointer to the various operations the driver offers. The definitions and | ||
62 | * structures here describe these capabilities in detail. | ||
63 | */ | ||
64 | |||
28 | /* | 65 | /* |
29 | * wireless hardware capability structures | 66 | * wireless hardware capability structures |
30 | */ | 67 | */ |
@@ -205,6 +242,21 @@ struct ieee80211_supported_band { | |||
205 | */ | 242 | */ |
206 | 243 | ||
207 | /** | 244 | /** |
245 | * DOC: Actions and configuration | ||
246 | * | ||
247 | * Each wireless device and each virtual interface offer a set of configuration | ||
248 | * operations and other actions that are invoked by userspace. Each of these | ||
249 | * actions is described in the operations structure, and the parameters these | ||
250 | * operations use are described separately. | ||
251 | * | ||
252 | * Additionally, some operations are asynchronous and expect to get status | ||
253 | * information via some functions that drivers need to call. | ||
254 | * | ||
255 | * Scanning and BSS list handling with its associated functionality is described | ||
256 | * in a separate chapter. | ||
257 | */ | ||
258 | |||
259 | /** | ||
208 | * struct vif_params - describes virtual interface parameters | 260 | * struct vif_params - describes virtual interface parameters |
209 | * @mesh_id: mesh ID to use | 261 | * @mesh_id: mesh ID to use |
210 | * @mesh_id_len: length of the mesh ID | 262 | * @mesh_id_len: length of the mesh ID |
@@ -570,8 +622,28 @@ struct ieee80211_txq_params { | |||
570 | /* from net/wireless.h */ | 622 | /* from net/wireless.h */ |
571 | struct wiphy; | 623 | struct wiphy; |
572 | 624 | ||
573 | /* from net/ieee80211.h */ | 625 | /** |
574 | struct ieee80211_channel; | 626 | * DOC: Scanning and BSS list handling |
627 | * | ||
628 | * The scanning process itself is fairly simple, but cfg80211 offers quite | ||
629 | * a bit of helper functionality. To start a scan, the scan operation will | ||
630 | * be invoked with a scan definition. This scan definition contains the | ||
631 | * channels to scan, and the SSIDs to send probe requests for (including the | ||
632 | * wildcard, if desired). A passive scan is indicated by having no SSIDs to | ||
633 | * probe. Additionally, a scan request may contain extra information elements | ||
634 | * that should be added to the probe request. The IEs are guaranteed to be | ||
635 | * well-formed, and will not exceed the maximum length the driver advertised | ||
636 | * in the wiphy structure. | ||
637 | * | ||
638 | * When scanning finds a BSS, cfg80211 needs to be notified of that, because | ||
639 | * it is responsible for maintaining the BSS list; the driver should not | ||
640 | * maintain a list itself. For this notification, various functions exist. | ||
641 | * | ||
642 | * Since drivers do not maintain a BSS list, there are also a number of | ||
643 | * functions to search for a BSS and obtain information about it from the | ||
644 | * BSS structure cfg80211 maintains. The BSS list is also made available | ||
645 | * to userspace. | ||
646 | */ | ||
575 | 647 | ||
576 | /** | 648 | /** |
577 | * struct cfg80211_ssid - SSID description | 649 | * struct cfg80211_ssid - SSID description |
@@ -1020,7 +1092,7 @@ struct cfg80211_pmksa { | |||
1020 | * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. | 1092 | * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. |
1021 | * This allows the operation to be terminated prior to timeout based on | 1093 | * This allows the operation to be terminated prior to timeout based on |
1022 | * the duration value. | 1094 | * the duration value. |
1023 | * @action: Transmit an action frame | 1095 | * @mgmt_tx: Transmit a management frame |
1024 | * | 1096 | * |
1025 | * @testmode_cmd: run a test mode command | 1097 | * @testmode_cmd: run a test mode command |
1026 | * | 1098 | * |
@@ -1172,7 +1244,7 @@ struct cfg80211_ops { | |||
1172 | struct net_device *dev, | 1244 | struct net_device *dev, |
1173 | u64 cookie); | 1245 | u64 cookie); |
1174 | 1246 | ||
1175 | int (*action)(struct wiphy *wiphy, struct net_device *dev, | 1247 | int (*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev, |
1176 | struct ieee80211_channel *chan, | 1248 | struct ieee80211_channel *chan, |
1177 | enum nl80211_channel_type channel_type, | 1249 | enum nl80211_channel_type channel_type, |
1178 | bool channel_type_valid, | 1250 | bool channel_type_valid, |
@@ -1236,6 +1308,10 @@ struct mac_address { | |||
1236 | u8 addr[ETH_ALEN]; | 1308 | u8 addr[ETH_ALEN]; |
1237 | }; | 1309 | }; |
1238 | 1310 | ||
1311 | struct ieee80211_txrx_stypes { | ||
1312 | u16 tx, rx; | ||
1313 | }; | ||
1314 | |||
1239 | /** | 1315 | /** |
1240 | * struct wiphy - wireless hardware description | 1316 | * struct wiphy - wireless hardware description |
1241 | * @reg_notifier: the driver's regulatory notification callback | 1317 | * @reg_notifier: the driver's regulatory notification callback |
@@ -1286,6 +1362,10 @@ struct mac_address { | |||
1286 | * @privid: a pointer that drivers can use to identify if an arbitrary | 1362 | * @privid: a pointer that drivers can use to identify if an arbitrary |
1287 | * wiphy is theirs, e.g. in global notifiers | 1363 | * wiphy is theirs, e.g. in global notifiers |
1288 | * @bands: information about bands/channels supported by this device | 1364 | * @bands: information about bands/channels supported by this device |
1365 | * | ||
1366 | * @mgmt_stypes: bitmasks of frame subtypes that can be subscribed to or | ||
1367 | * transmitted through nl80211, points to an array indexed by interface | ||
1368 | * type | ||
1289 | */ | 1369 | */ |
1290 | struct wiphy { | 1370 | struct wiphy { |
1291 | /* assign these fields before you register the wiphy */ | 1371 | /* assign these fields before you register the wiphy */ |
@@ -1294,9 +1374,12 @@ struct wiphy { | |||
1294 | u8 perm_addr[ETH_ALEN]; | 1374 | u8 perm_addr[ETH_ALEN]; |
1295 | u8 addr_mask[ETH_ALEN]; | 1375 | u8 addr_mask[ETH_ALEN]; |
1296 | 1376 | ||
1297 | u16 n_addresses; | ||
1298 | struct mac_address *addresses; | 1377 | struct mac_address *addresses; |
1299 | 1378 | ||
1379 | const struct ieee80211_txrx_stypes *mgmt_stypes; | ||
1380 | |||
1381 | u16 n_addresses; | ||
1382 | |||
1300 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ | 1383 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ |
1301 | u16 interface_modes; | 1384 | u16 interface_modes; |
1302 | 1385 | ||
@@ -1492,8 +1575,8 @@ struct cfg80211_cached_keys; | |||
1492 | * set by driver (if supported) on add_interface BEFORE registering the | 1575 | * set by driver (if supported) on add_interface BEFORE registering the |
1493 | * netdev and may otherwise be used by driver read-only, will be update | 1576 | * netdev and may otherwise be used by driver read-only, will be update |
1494 | * by cfg80211 on change_interface | 1577 | * by cfg80211 on change_interface |
1495 | * @action_registrations: list of registrations for action frames | 1578 | * @mgmt_registrations: list of registrations for management frames |
1496 | * @action_registrations_lock: lock for the list | 1579 | * @mgmt_registrations_lock: lock for the list |
1497 | * @mtx: mutex used to lock data in this struct | 1580 | * @mtx: mutex used to lock data in this struct |
1498 | * @cleanup_work: work struct used for cleanup that can't be done directly | 1581 | * @cleanup_work: work struct used for cleanup that can't be done directly |
1499 | */ | 1582 | */ |
@@ -1505,8 +1588,8 @@ struct wireless_dev { | |||
1505 | struct list_head list; | 1588 | struct list_head list; |
1506 | struct net_device *netdev; | 1589 | struct net_device *netdev; |
1507 | 1590 | ||
1508 | struct list_head action_registrations; | 1591 | struct list_head mgmt_registrations; |
1509 | spinlock_t action_registrations_lock; | 1592 | spinlock_t mgmt_registrations_lock; |
1510 | 1593 | ||
1511 | struct mutex mtx; | 1594 | struct mutex mtx; |
1512 | 1595 | ||
@@ -1563,8 +1646,10 @@ static inline void *wdev_priv(struct wireless_dev *wdev) | |||
1563 | return wiphy_priv(wdev->wiphy); | 1646 | return wiphy_priv(wdev->wiphy); |
1564 | } | 1647 | } |
1565 | 1648 | ||
1566 | /* | 1649 | /** |
1567 | * Utility functions | 1650 | * DOC: Utility functions |
1651 | * | ||
1652 | * cfg80211 offers a number of utility functions that can be useful. | ||
1568 | */ | 1653 | */ |
1569 | 1654 | ||
1570 | /** | 1655 | /** |
@@ -1715,7 +1800,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); | |||
1715 | * ieee80211_hdrlen - get header length in bytes from frame control | 1800 | * ieee80211_hdrlen - get header length in bytes from frame control |
1716 | * @fc: frame control field in little-endian format | 1801 | * @fc: frame control field in little-endian format |
1717 | */ | 1802 | */ |
1718 | unsigned int ieee80211_hdrlen(__le16 fc); | 1803 | unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); |
1804 | |||
1805 | /** | ||
1806 | * DOC: Data path helpers | ||
1807 | * | ||
1808 | * In addition to generic utilities, cfg80211 also offers | ||
1809 | * functions that help implement the data path for devices | ||
1810 | * that do not do the 802.11/802.3 conversion on the device. | ||
1811 | */ | ||
1719 | 1812 | ||
1720 | /** | 1813 | /** |
1721 | * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 | 1814 | * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 |
@@ -1777,8 +1870,10 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb); | |||
1777 | */ | 1870 | */ |
1778 | const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); | 1871 | const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); |
1779 | 1872 | ||
1780 | /* | 1873 | /** |
1781 | * Regulatory helper functions for wiphys | 1874 | * DOC: Regulatory enforcement infrastructure |
1875 | * | ||
1876 | * TODO | ||
1782 | */ | 1877 | */ |
1783 | 1878 | ||
1784 | /** | 1879 | /** |
@@ -2181,6 +2276,20 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, | |||
2181 | void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); | 2276 | void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); |
2182 | 2277 | ||
2183 | /** | 2278 | /** |
2279 | * DOC: RFkill integration | ||
2280 | * | ||
2281 | * RFkill integration in cfg80211 is almost invisible to drivers, | ||
2282 | * as cfg80211 automatically registers an rfkill instance for each | ||
2283 | * wireless device it knows about. Soft kill is also translated | ||
2284 | * into disconnecting and turning all interfaces off, drivers are | ||
2285 | * expected to turn off the device when all interfaces are down. | ||
2286 | * | ||
2287 | * However, devices may have a hard RFkill line, in which case they | ||
2288 | * also need to interact with the rfkill subsystem, via cfg80211. | ||
2289 | * They can do this with a few helper functions documented here. | ||
2290 | */ | ||
2291 | |||
2292 | /** | ||
2184 | * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state | 2293 | * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state |
2185 | * @wiphy: the wiphy | 2294 | * @wiphy: the wiphy |
2186 | * @blocked: block status | 2295 | * @blocked: block status |
@@ -2201,6 +2310,17 @@ void wiphy_rfkill_stop_polling(struct wiphy *wiphy); | |||
2201 | 2310 | ||
2202 | #ifdef CONFIG_NL80211_TESTMODE | 2311 | #ifdef CONFIG_NL80211_TESTMODE |
2203 | /** | 2312 | /** |
2313 | * DOC: Test mode | ||
2314 | * | ||
2315 | * Test mode is a set of utility functions to allow drivers to | ||
2316 | * interact with driver-specific tools to aid, for instance, | ||
2317 | * factory programming. | ||
2318 | * | ||
2319 | * This chapter describes how drivers interact with it, for more | ||
2320 | * information see the nl80211 book's chapter on it. | ||
2321 | */ | ||
2322 | |||
2323 | /** | ||
2204 | * cfg80211_testmode_alloc_reply_skb - allocate testmode reply | 2324 | * cfg80211_testmode_alloc_reply_skb - allocate testmode reply |
2205 | * @wiphy: the wiphy | 2325 | * @wiphy: the wiphy |
2206 | * @approxlen: an upper bound of the length of the data that will | 2326 | * @approxlen: an upper bound of the length of the data that will |
@@ -2373,38 +2493,39 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
2373 | struct station_info *sinfo, gfp_t gfp); | 2493 | struct station_info *sinfo, gfp_t gfp); |
2374 | 2494 | ||
2375 | /** | 2495 | /** |
2376 | * cfg80211_rx_action - notification of received, unprocessed Action frame | 2496 | * cfg80211_rx_mgmt - notification of received, unprocessed management frame |
2377 | * @dev: network device | 2497 | * @dev: network device |
2378 | * @freq: Frequency on which the frame was received in MHz | 2498 | * @freq: Frequency on which the frame was received in MHz |
2379 | * @buf: Action frame (header + body) | 2499 | * @buf: Management frame (header + body) |
2380 | * @len: length of the frame data | 2500 | * @len: length of the frame data |
2381 | * @gfp: context flags | 2501 | * @gfp: context flags |
2382 | * Returns %true if a user space application is responsible for rejecting the | 2502 | * |
2383 | * unrecognized Action frame; %false if no such application is registered | 2503 | * Returns %true if a user space application has registered for this frame. |
2384 | * (i.e., the driver is responsible for rejecting the unrecognized Action | 2504 | * For action frames, that makes it responsible for rejecting unrecognized |
2385 | * frame) | 2505 | * action frames; %false otherwise, in which case for action frames the |
2506 | * driver is responsible for rejecting the frame. | ||
2386 | * | 2507 | * |
2387 | * This function is called whenever an Action frame is received for a station | 2508 | * This function is called whenever an Action frame is received for a station |
2388 | * mode interface, but is not processed in kernel. | 2509 | * mode interface, but is not processed in kernel. |
2389 | */ | 2510 | */ |
2390 | bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, | 2511 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, |
2391 | size_t len, gfp_t gfp); | 2512 | size_t len, gfp_t gfp); |
2392 | 2513 | ||
2393 | /** | 2514 | /** |
2394 | * cfg80211_action_tx_status - notification of TX status for Action frame | 2515 | * cfg80211_mgmt_tx_status - notification of TX status for management frame |
2395 | * @dev: network device | 2516 | * @dev: network device |
2396 | * @cookie: Cookie returned by cfg80211_ops::action() | 2517 | * @cookie: Cookie returned by cfg80211_ops::mgmt_tx() |
2397 | * @buf: Action frame (header + body) | 2518 | * @buf: Management frame (header + body) |
2398 | * @len: length of the frame data | 2519 | * @len: length of the frame data |
2399 | * @ack: Whether frame was acknowledged | 2520 | * @ack: Whether frame was acknowledged |
2400 | * @gfp: context flags | 2521 | * @gfp: context flags |
2401 | * | 2522 | * |
2402 | * This function is called whenever an Action frame was requested to be | 2523 | * This function is called whenever a management frame was requested to be |
2403 | * transmitted with cfg80211_ops::action() to report the TX status of the | 2524 | * transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the |
2404 | * transmission attempt. | 2525 | * transmission attempt. |
2405 | */ | 2526 | */ |
2406 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | 2527 | void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie, |
2407 | const u8 *buf, size_t len, bool ack, gfp_t gfp); | 2528 | const u8 *buf, size_t len, bool ack, gfp_t gfp); |
2408 | 2529 | ||
2409 | 2530 | ||
2410 | /** | 2531 | /** |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b0787a1dea90..2a1811366076 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -149,6 +149,7 @@ struct ieee80211_low_level_stats { | |||
149 | * @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed. | 149 | * @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed. |
150 | * @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note | 150 | * @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note |
151 | * that it is only ever disabled for station mode. | 151 | * that it is only ever disabled for station mode. |
152 | * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface. | ||
152 | */ | 153 | */ |
153 | enum ieee80211_bss_change { | 154 | enum ieee80211_bss_change { |
154 | BSS_CHANGED_ASSOC = 1<<0, | 155 | BSS_CHANGED_ASSOC = 1<<0, |
@@ -165,6 +166,7 @@ enum ieee80211_bss_change { | |||
165 | BSS_CHANGED_IBSS = 1<<11, | 166 | BSS_CHANGED_IBSS = 1<<11, |
166 | BSS_CHANGED_ARP_FILTER = 1<<12, | 167 | BSS_CHANGED_ARP_FILTER = 1<<12, |
167 | BSS_CHANGED_QOS = 1<<13, | 168 | BSS_CHANGED_QOS = 1<<13, |
169 | BSS_CHANGED_IDLE = 1<<14, | ||
168 | 170 | ||
169 | /* when adding here, make sure to change ieee80211_reconfig */ | 171 | /* when adding here, make sure to change ieee80211_reconfig */ |
170 | }; | 172 | }; |
@@ -223,6 +225,9 @@ enum ieee80211_bss_change { | |||
223 | * hardware must not perform any ARP filtering. Note, that the filter will | 225 | * hardware must not perform any ARP filtering. Note, that the filter will |
224 | * be enabled also in promiscuous mode. | 226 | * be enabled also in promiscuous mode. |
225 | * @qos: This is a QoS-enabled BSS. | 227 | * @qos: This is a QoS-enabled BSS. |
228 | * @idle: This interface is idle. There's also a global idle flag in the | ||
229 | * hardware config which may be more appropriate depending on what | ||
230 | * your driver/device needs to do. | ||
226 | */ | 231 | */ |
227 | struct ieee80211_bss_conf { | 232 | struct ieee80211_bss_conf { |
228 | const u8 *bssid; | 233 | const u8 *bssid; |
@@ -247,6 +252,7 @@ struct ieee80211_bss_conf { | |||
247 | u8 arp_addr_cnt; | 252 | u8 arp_addr_cnt; |
248 | bool arp_filter_enabled; | 253 | bool arp_filter_enabled; |
249 | bool qos; | 254 | bool qos; |
255 | bool idle; | ||
250 | }; | 256 | }; |
251 | 257 | ||
252 | /** | 258 | /** |
@@ -783,20 +789,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | |||
783 | } | 789 | } |
784 | 790 | ||
785 | /** | 791 | /** |
786 | * enum ieee80211_key_alg - key algorithm | ||
787 | * @ALG_WEP: WEP40 or WEP104 | ||
788 | * @ALG_TKIP: TKIP | ||
789 | * @ALG_CCMP: CCMP (AES) | ||
790 | * @ALG_AES_CMAC: AES-128-CMAC | ||
791 | */ | ||
792 | enum ieee80211_key_alg { | ||
793 | ALG_WEP, | ||
794 | ALG_TKIP, | ||
795 | ALG_CCMP, | ||
796 | ALG_AES_CMAC, | ||
797 | }; | ||
798 | |||
799 | /** | ||
800 | * enum ieee80211_key_flags - key flags | 792 | * enum ieee80211_key_flags - key flags |
801 | * | 793 | * |
802 | * These flags are used for communication about keys between the driver | 794 | * These flags are used for communication about keys between the driver |
@@ -833,7 +825,7 @@ enum ieee80211_key_flags { | |||
833 | * @hw_key_idx: To be set by the driver, this is the key index the driver | 825 | * @hw_key_idx: To be set by the driver, this is the key index the driver |
834 | * wants to be given when a frame is transmitted and needs to be | 826 | * wants to be given when a frame is transmitted and needs to be |
835 | * encrypted in hardware. | 827 | * encrypted in hardware. |
836 | * @alg: The key algorithm. | 828 | * @cipher: The key's cipher suite selector. |
837 | * @flags: key flags, see &enum ieee80211_key_flags. | 829 | * @flags: key flags, see &enum ieee80211_key_flags. |
838 | * @keyidx: the key index (0-3) | 830 | * @keyidx: the key index (0-3) |
839 | * @keylen: key material length | 831 | * @keylen: key material length |
@@ -846,7 +838,7 @@ enum ieee80211_key_flags { | |||
846 | * @iv_len: The IV length for this key type | 838 | * @iv_len: The IV length for this key type |
847 | */ | 839 | */ |
848 | struct ieee80211_key_conf { | 840 | struct ieee80211_key_conf { |
849 | enum ieee80211_key_alg alg; | 841 | u32 cipher; |
850 | u8 icv_len; | 842 | u8 icv_len; |
851 | u8 iv_len; | 843 | u8 iv_len; |
852 | u8 hw_key_idx; | 844 | u8 hw_key_idx; |
@@ -1102,6 +1094,10 @@ enum ieee80211_hw_flags { | |||
1102 | * | 1094 | * |
1103 | * @max_rates: maximum number of alternate rate retry stages | 1095 | * @max_rates: maximum number of alternate rate retry stages |
1104 | * @max_rate_tries: maximum number of tries for each stage | 1096 | * @max_rate_tries: maximum number of tries for each stage |
1097 | * | ||
1098 | * @napi_weight: weight used for NAPI polling. You must specify an | ||
1099 | * appropriate value here if a napi_poll operation is provided | ||
1100 | * by your driver. | ||
1105 | */ | 1101 | */ |
1106 | struct ieee80211_hw { | 1102 | struct ieee80211_hw { |
1107 | struct ieee80211_conf conf; | 1103 | struct ieee80211_conf conf; |
@@ -1113,6 +1109,7 @@ struct ieee80211_hw { | |||
1113 | int channel_change_time; | 1109 | int channel_change_time; |
1114 | int vif_data_size; | 1110 | int vif_data_size; |
1115 | int sta_data_size; | 1111 | int sta_data_size; |
1112 | int napi_weight; | ||
1116 | u16 queues; | 1113 | u16 queues; |
1117 | u16 max_listen_interval; | 1114 | u16 max_listen_interval; |
1118 | s8 max_signal; | 1115 | s8 max_signal; |
@@ -1687,6 +1684,8 @@ enum ieee80211_ampdu_mlme_action { | |||
1687 | * switch operation for CSAs received from the AP may implement this | 1684 | * switch operation for CSAs received from the AP may implement this |
1688 | * callback. They must then call ieee80211_chswitch_done() to indicate | 1685 | * callback. They must then call ieee80211_chswitch_done() to indicate |
1689 | * completion of the channel switch. | 1686 | * completion of the channel switch. |
1687 | * | ||
1688 | * @napi_poll: Poll Rx queue for incoming data frames. | ||
1690 | */ | 1689 | */ |
1691 | struct ieee80211_ops { | 1690 | struct ieee80211_ops { |
1692 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); | 1691 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); |
@@ -1752,6 +1751,7 @@ struct ieee80211_ops { | |||
1752 | void (*flush)(struct ieee80211_hw *hw, bool drop); | 1751 | void (*flush)(struct ieee80211_hw *hw, bool drop); |
1753 | void (*channel_switch)(struct ieee80211_hw *hw, | 1752 | void (*channel_switch)(struct ieee80211_hw *hw, |
1754 | struct ieee80211_channel_switch *ch_switch); | 1753 | struct ieee80211_channel_switch *ch_switch); |
1754 | int (*napi_poll)(struct ieee80211_hw *hw, int budget); | ||
1755 | }; | 1755 | }; |
1756 | 1756 | ||
1757 | /** | 1757 | /** |
@@ -1897,6 +1897,22 @@ void ieee80211_free_hw(struct ieee80211_hw *hw); | |||
1897 | */ | 1897 | */ |
1898 | void ieee80211_restart_hw(struct ieee80211_hw *hw); | 1898 | void ieee80211_restart_hw(struct ieee80211_hw *hw); |
1899 | 1899 | ||
1900 | /** ieee80211_napi_schedule - schedule NAPI poll | ||
1901 | * | ||
1902 | * Use this function to schedule NAPI polling on a device. | ||
1903 | * | ||
1904 | * @hw: the hardware to start polling | ||
1905 | */ | ||
1906 | void ieee80211_napi_schedule(struct ieee80211_hw *hw); | ||
1907 | |||
1908 | /** ieee80211_napi_complete - complete NAPI polling | ||
1909 | * | ||
1910 | * Use this function to finish NAPI polling on a device. | ||
1911 | * | ||
1912 | * @hw: the hardware to stop polling | ||
1913 | */ | ||
1914 | void ieee80211_napi_complete(struct ieee80211_hw *hw); | ||
1915 | |||
1900 | /** | 1916 | /** |
1901 | * ieee80211_rx - receive frame | 1917 | * ieee80211_rx - receive frame |
1902 | * | 1918 | * |
@@ -2518,6 +2534,18 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | |||
2518 | */ | 2534 | */ |
2519 | void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success); | 2535 | void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success); |
2520 | 2536 | ||
2537 | /** | ||
2538 | * ieee80211_request_smps - request SM PS transition | ||
2539 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
2540 | * @smps_mode: new SM PS mode | ||
2541 | * | ||
2542 | * This allows the driver to request an SM PS transition in managed | ||
2543 | * mode. This is useful when the driver has more information than | ||
2544 | * the stack about possible interference, for example by bluetooth. | ||
2545 | */ | ||
2546 | void ieee80211_request_smps(struct ieee80211_vif *vif, | ||
2547 | enum ieee80211_smps_mode smps_mode); | ||
2548 | |||
2521 | /* Rate control API */ | 2549 | /* Rate control API */ |
2522 | 2550 | ||
2523 | /** | 2551 | /** |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index af4dfbadf2a0..7d748542d97e 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -789,12 +789,13 @@ static const void *net_netlink_ns(struct sock *sk) | |||
789 | return sock_net(sk); | 789 | return sock_net(sk); |
790 | } | 790 | } |
791 | 791 | ||
792 | static struct kobj_ns_type_operations net_ns_type_operations = { | 792 | struct kobj_ns_type_operations net_ns_type_operations = { |
793 | .type = KOBJ_NS_TYPE_NET, | 793 | .type = KOBJ_NS_TYPE_NET, |
794 | .current_ns = net_current_ns, | 794 | .current_ns = net_current_ns, |
795 | .netlink_ns = net_netlink_ns, | 795 | .netlink_ns = net_netlink_ns, |
796 | .initial_ns = net_initial_ns, | 796 | .initial_ns = net_initial_ns, |
797 | }; | 797 | }; |
798 | EXPORT_SYMBOL_GPL(net_ns_type_operations); | ||
798 | 799 | ||
799 | static void net_kobj_ns_exit(struct net *net) | 800 | static void net_kobj_ns_exit(struct net *net) |
800 | { | 801 | { |
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index a87cb3ba2df6..d2b03e0851ef 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -138,10 +138,8 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) | |||
138 | struct crypto_cipher *tfm; | 138 | struct crypto_cipher *tfm; |
139 | 139 | ||
140 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 140 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); |
141 | if (IS_ERR(tfm)) | 141 | if (!IS_ERR(tfm)) |
142 | return NULL; | 142 | crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); |
143 | |||
144 | crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); | ||
145 | 143 | ||
146 | return tfm; | 144 | return tfm; |
147 | } | 145 | } |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 3d097b3d7b62..b4d66cca76d6 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -119,10 +119,8 @@ struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) | |||
119 | struct crypto_cipher *tfm; | 119 | struct crypto_cipher *tfm; |
120 | 120 | ||
121 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 121 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); |
122 | if (IS_ERR(tfm)) | 122 | if (!IS_ERR(tfm)) |
123 | return NULL; | 123 | crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); |
124 | |||
125 | crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); | ||
126 | 124 | ||
127 | return tfm; | 125 | return tfm; |
128 | } | 126 | } |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 965b272499fd..58eab9e8e4ee 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -86,6 +86,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
86 | tid, 0, reason); | 86 | tid, 0, reason); |
87 | 87 | ||
88 | del_timer_sync(&tid_rx->session_timer); | 88 | del_timer_sync(&tid_rx->session_timer); |
89 | del_timer_sync(&tid_rx->reorder_timer); | ||
89 | 90 | ||
90 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); | 91 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); |
91 | } | 92 | } |
@@ -120,6 +121,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
120 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); | 121 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); |
121 | } | 122 | } |
122 | 123 | ||
124 | static void sta_rx_agg_reorder_timer_expired(unsigned long data) | ||
125 | { | ||
126 | u8 *ptid = (u8 *)data; | ||
127 | u8 *timer_to_id = ptid - *ptid; | ||
128 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
129 | timer_to_tid[0]); | ||
130 | |||
131 | rcu_read_lock(); | ||
132 | spin_lock(&sta->lock); | ||
133 | ieee80211_release_reorder_timeout(sta, *ptid); | ||
134 | spin_unlock(&sta->lock); | ||
135 | rcu_read_unlock(); | ||
136 | } | ||
137 | |||
123 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 138 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |
124 | u8 dialog_token, u16 status, u16 policy, | 139 | u8 dialog_token, u16 status, u16 policy, |
125 | u16 buf_size, u16 timeout) | 140 | u16 buf_size, u16 timeout) |
@@ -251,11 +266,18 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
251 | goto end; | 266 | goto end; |
252 | } | 267 | } |
253 | 268 | ||
269 | spin_lock_init(&tid_agg_rx->reorder_lock); | ||
270 | |||
254 | /* rx timer */ | 271 | /* rx timer */ |
255 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; | 272 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; |
256 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 273 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
257 | init_timer(&tid_agg_rx->session_timer); | 274 | init_timer(&tid_agg_rx->session_timer); |
258 | 275 | ||
276 | /* rx reorder timer */ | ||
277 | tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; | ||
278 | tid_agg_rx->reorder_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | ||
279 | init_timer(&tid_agg_rx->reorder_timer); | ||
280 | |||
259 | /* prepare reordering buffer */ | 281 | /* prepare reordering buffer */ |
260 | tid_agg_rx->reorder_buf = | 282 | tid_agg_rx->reorder_buf = |
261 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); | 283 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 29ac8e1a509e..94787d21282c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -116,7 +116,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
116 | { | 116 | { |
117 | struct ieee80211_sub_if_data *sdata; | 117 | struct ieee80211_sub_if_data *sdata; |
118 | struct sta_info *sta = NULL; | 118 | struct sta_info *sta = NULL; |
119 | enum ieee80211_key_alg alg; | ||
120 | struct ieee80211_key *key; | 119 | struct ieee80211_key *key; |
121 | int err; | 120 | int err; |
122 | 121 | ||
@@ -125,33 +124,22 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
125 | 124 | ||
126 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 125 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
127 | 126 | ||
127 | /* reject WEP and TKIP keys if WEP failed to initialize */ | ||
128 | switch (params->cipher) { | 128 | switch (params->cipher) { |
129 | case WLAN_CIPHER_SUITE_WEP40: | 129 | case WLAN_CIPHER_SUITE_WEP40: |
130 | case WLAN_CIPHER_SUITE_WEP104: | ||
131 | alg = ALG_WEP; | ||
132 | break; | ||
133 | case WLAN_CIPHER_SUITE_TKIP: | 130 | case WLAN_CIPHER_SUITE_TKIP: |
134 | alg = ALG_TKIP; | 131 | case WLAN_CIPHER_SUITE_WEP104: |
135 | break; | 132 | if (IS_ERR(sdata->local->wep_tx_tfm)) |
136 | case WLAN_CIPHER_SUITE_CCMP: | 133 | return -EINVAL; |
137 | alg = ALG_CCMP; | ||
138 | break; | ||
139 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
140 | alg = ALG_AES_CMAC; | ||
141 | break; | 134 | break; |
142 | default: | 135 | default: |
143 | return -EINVAL; | 136 | break; |
144 | } | 137 | } |
145 | 138 | ||
146 | /* reject WEP and TKIP keys if WEP failed to initialize */ | 139 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, |
147 | if ((alg == ALG_WEP || alg == ALG_TKIP) && | 140 | params->key, params->seq_len, params->seq); |
148 | IS_ERR(sdata->local->wep_tx_tfm)) | 141 | if (IS_ERR(key)) |
149 | return -EINVAL; | 142 | return PTR_ERR(key); |
150 | |||
151 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, | ||
152 | params->seq_len, params->seq); | ||
153 | if (!key) | ||
154 | return -ENOMEM; | ||
155 | 143 | ||
156 | mutex_lock(&sdata->local->sta_mtx); | 144 | mutex_lock(&sdata->local->sta_mtx); |
157 | 145 | ||
@@ -247,10 +235,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
247 | 235 | ||
248 | memset(¶ms, 0, sizeof(params)); | 236 | memset(¶ms, 0, sizeof(params)); |
249 | 237 | ||
250 | switch (key->conf.alg) { | 238 | params.cipher = key->conf.cipher; |
251 | case ALG_TKIP: | ||
252 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | ||
253 | 239 | ||
240 | switch (key->conf.cipher) { | ||
241 | case WLAN_CIPHER_SUITE_TKIP: | ||
254 | iv32 = key->u.tkip.tx.iv32; | 242 | iv32 = key->u.tkip.tx.iv32; |
255 | iv16 = key->u.tkip.tx.iv16; | 243 | iv16 = key->u.tkip.tx.iv16; |
256 | 244 | ||
@@ -268,8 +256,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
268 | params.seq = seq; | 256 | params.seq = seq; |
269 | params.seq_len = 6; | 257 | params.seq_len = 6; |
270 | break; | 258 | break; |
271 | case ALG_CCMP: | 259 | case WLAN_CIPHER_SUITE_CCMP: |
272 | params.cipher = WLAN_CIPHER_SUITE_CCMP; | ||
273 | seq[0] = key->u.ccmp.tx_pn[5]; | 260 | seq[0] = key->u.ccmp.tx_pn[5]; |
274 | seq[1] = key->u.ccmp.tx_pn[4]; | 261 | seq[1] = key->u.ccmp.tx_pn[4]; |
275 | seq[2] = key->u.ccmp.tx_pn[3]; | 262 | seq[2] = key->u.ccmp.tx_pn[3]; |
@@ -279,14 +266,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
279 | params.seq = seq; | 266 | params.seq = seq; |
280 | params.seq_len = 6; | 267 | params.seq_len = 6; |
281 | break; | 268 | break; |
282 | case ALG_WEP: | 269 | case WLAN_CIPHER_SUITE_AES_CMAC: |
283 | if (key->conf.keylen == 5) | ||
284 | params.cipher = WLAN_CIPHER_SUITE_WEP40; | ||
285 | else | ||
286 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | ||
287 | break; | ||
288 | case ALG_AES_CMAC: | ||
289 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | ||
290 | seq[0] = key->u.aes_cmac.tx_pn[5]; | 270 | seq[0] = key->u.aes_cmac.tx_pn[5]; |
291 | seq[1] = key->u.aes_cmac.tx_pn[4]; | 271 | seq[1] = key->u.aes_cmac.tx_pn[4]; |
292 | seq[2] = key->u.aes_cmac.tx_pn[3]; | 272 | seq[2] = key->u.aes_cmac.tx_pn[3]; |
@@ -1541,11 +1521,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
1541 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | 1521 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); |
1542 | } | 1522 | } |
1543 | 1523 | ||
1544 | static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | 1524 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
1545 | struct ieee80211_channel *chan, | 1525 | struct ieee80211_channel *chan, |
1546 | enum nl80211_channel_type channel_type, | 1526 | enum nl80211_channel_type channel_type, |
1547 | bool channel_type_valid, | 1527 | bool channel_type_valid, |
1548 | const u8 *buf, size_t len, u64 *cookie) | 1528 | const u8 *buf, size_t len, u64 *cookie) |
1549 | { | 1529 | { |
1550 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1530 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1551 | struct ieee80211_local *local = sdata->local; | 1531 | struct ieee80211_local *local = sdata->local; |
@@ -1575,8 +1555,6 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | |||
1575 | return -ENOLINK; | 1555 | return -ENOLINK; |
1576 | break; | 1556 | break; |
1577 | case NL80211_IFTYPE_STATION: | 1557 | case NL80211_IFTYPE_STATION: |
1578 | if (!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) | ||
1579 | flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1580 | break; | 1558 | break; |
1581 | default: | 1559 | default: |
1582 | return -EOPNOTSUPP; | 1560 | return -EOPNOTSUPP; |
@@ -1647,6 +1625,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1647 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1625 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1648 | .remain_on_channel = ieee80211_remain_on_channel, | 1626 | .remain_on_channel = ieee80211_remain_on_channel, |
1649 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1627 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1650 | .action = ieee80211_action, | 1628 | .mgmt_tx = ieee80211_mgmt_tx, |
1651 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | 1629 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
1652 | }; | 1630 | }; |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index fa5e76e658ef..1647f8dc5cda 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -64,26 +64,13 @@ static ssize_t key_algorithm_read(struct file *file, | |||
64 | char __user *userbuf, | 64 | char __user *userbuf, |
65 | size_t count, loff_t *ppos) | 65 | size_t count, loff_t *ppos) |
66 | { | 66 | { |
67 | char *alg; | 67 | char buf[15]; |
68 | struct ieee80211_key *key = file->private_data; | 68 | struct ieee80211_key *key = file->private_data; |
69 | u32 c = key->conf.cipher; | ||
69 | 70 | ||
70 | switch (key->conf.alg) { | 71 | sprintf(buf, "%.2x-%.2x-%.2x:%d\n", |
71 | case ALG_WEP: | 72 | c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); |
72 | alg = "WEP\n"; | 73 | return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); |
73 | break; | ||
74 | case ALG_TKIP: | ||
75 | alg = "TKIP\n"; | ||
76 | break; | ||
77 | case ALG_CCMP: | ||
78 | alg = "CCMP\n"; | ||
79 | break; | ||
80 | case ALG_AES_CMAC: | ||
81 | alg = "AES-128-CMAC\n"; | ||
82 | break; | ||
83 | default: | ||
84 | return 0; | ||
85 | } | ||
86 | return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg)); | ||
87 | } | 74 | } |
88 | KEY_OPS(algorithm); | 75 | KEY_OPS(algorithm); |
89 | 76 | ||
@@ -95,21 +82,22 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | |||
95 | int len; | 82 | int len; |
96 | struct ieee80211_key *key = file->private_data; | 83 | struct ieee80211_key *key = file->private_data; |
97 | 84 | ||
98 | switch (key->conf.alg) { | 85 | switch (key->conf.cipher) { |
99 | case ALG_WEP: | 86 | case WLAN_CIPHER_SUITE_WEP40: |
87 | case WLAN_CIPHER_SUITE_WEP104: | ||
100 | len = scnprintf(buf, sizeof(buf), "\n"); | 88 | len = scnprintf(buf, sizeof(buf), "\n"); |
101 | break; | 89 | break; |
102 | case ALG_TKIP: | 90 | case WLAN_CIPHER_SUITE_TKIP: |
103 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", | 91 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", |
104 | key->u.tkip.tx.iv32, | 92 | key->u.tkip.tx.iv32, |
105 | key->u.tkip.tx.iv16); | 93 | key->u.tkip.tx.iv16); |
106 | break; | 94 | break; |
107 | case ALG_CCMP: | 95 | case WLAN_CIPHER_SUITE_CCMP: |
108 | tpn = key->u.ccmp.tx_pn; | 96 | tpn = key->u.ccmp.tx_pn; |
109 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 97 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
110 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); | 98 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); |
111 | break; | 99 | break; |
112 | case ALG_AES_CMAC: | 100 | case WLAN_CIPHER_SUITE_AES_CMAC: |
113 | tpn = key->u.aes_cmac.tx_pn; | 101 | tpn = key->u.aes_cmac.tx_pn; |
114 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 102 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
115 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], | 103 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], |
@@ -130,11 +118,12 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
130 | int i, len; | 118 | int i, len; |
131 | const u8 *rpn; | 119 | const u8 *rpn; |
132 | 120 | ||
133 | switch (key->conf.alg) { | 121 | switch (key->conf.cipher) { |
134 | case ALG_WEP: | 122 | case WLAN_CIPHER_SUITE_WEP40: |
123 | case WLAN_CIPHER_SUITE_WEP104: | ||
135 | len = scnprintf(buf, sizeof(buf), "\n"); | 124 | len = scnprintf(buf, sizeof(buf), "\n"); |
136 | break; | 125 | break; |
137 | case ALG_TKIP: | 126 | case WLAN_CIPHER_SUITE_TKIP: |
138 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 127 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) |
139 | p += scnprintf(p, sizeof(buf)+buf-p, | 128 | p += scnprintf(p, sizeof(buf)+buf-p, |
140 | "%08x %04x\n", | 129 | "%08x %04x\n", |
@@ -142,7 +131,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
142 | key->u.tkip.rx[i].iv16); | 131 | key->u.tkip.rx[i].iv16); |
143 | len = p - buf; | 132 | len = p - buf; |
144 | break; | 133 | break; |
145 | case ALG_CCMP: | 134 | case WLAN_CIPHER_SUITE_CCMP: |
146 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { | 135 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { |
147 | rpn = key->u.ccmp.rx_pn[i]; | 136 | rpn = key->u.ccmp.rx_pn[i]; |
148 | p += scnprintf(p, sizeof(buf)+buf-p, | 137 | p += scnprintf(p, sizeof(buf)+buf-p, |
@@ -152,7 +141,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
152 | } | 141 | } |
153 | len = p - buf; | 142 | len = p - buf; |
154 | break; | 143 | break; |
155 | case ALG_AES_CMAC: | 144 | case WLAN_CIPHER_SUITE_AES_CMAC: |
156 | rpn = key->u.aes_cmac.rx_pn; | 145 | rpn = key->u.aes_cmac.rx_pn; |
157 | p += scnprintf(p, sizeof(buf)+buf-p, | 146 | p += scnprintf(p, sizeof(buf)+buf-p, |
158 | "%02x%02x%02x%02x%02x%02x\n", | 147 | "%02x%02x%02x%02x%02x%02x\n", |
@@ -174,11 +163,11 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf, | |||
174 | char buf[20]; | 163 | char buf[20]; |
175 | int len; | 164 | int len; |
176 | 165 | ||
177 | switch (key->conf.alg) { | 166 | switch (key->conf.cipher) { |
178 | case ALG_CCMP: | 167 | case WLAN_CIPHER_SUITE_CCMP: |
179 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); | 168 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); |
180 | break; | 169 | break; |
181 | case ALG_AES_CMAC: | 170 | case WLAN_CIPHER_SUITE_AES_CMAC: |
182 | len = scnprintf(buf, sizeof(buf), "%u\n", | 171 | len = scnprintf(buf, sizeof(buf), "%u\n", |
183 | key->u.aes_cmac.replays); | 172 | key->u.aes_cmac.replays); |
184 | break; | 173 | break; |
@@ -196,8 +185,8 @@ static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, | |||
196 | char buf[20]; | 185 | char buf[20]; |
197 | int len; | 186 | int len; |
198 | 187 | ||
199 | switch (key->conf.alg) { | 188 | switch (key->conf.cipher) { |
200 | case ALG_AES_CMAC: | 189 | case WLAN_CIPHER_SUITE_AES_CMAC: |
201 | len = scnprintf(buf, sizeof(buf), "%u\n", | 190 | len = scnprintf(buf, sizeof(buf), "%u\n", |
202 | key->u.aes_cmac.icverrors); | 191 | key->u.aes_cmac.icverrors); |
203 | break; | 192 | break; |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 5d5d2a974668..b5a95582d816 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -336,7 +336,7 @@ TRACE_EVENT(drv_set_key, | |||
336 | LOCAL_ENTRY | 336 | LOCAL_ENTRY |
337 | VIF_ENTRY | 337 | VIF_ENTRY |
338 | STA_ENTRY | 338 | STA_ENTRY |
339 | __field(enum ieee80211_key_alg, alg) | 339 | __field(u32, cipher) |
340 | __field(u8, hw_key_idx) | 340 | __field(u8, hw_key_idx) |
341 | __field(u8, flags) | 341 | __field(u8, flags) |
342 | __field(s8, keyidx) | 342 | __field(s8, keyidx) |
@@ -346,7 +346,7 @@ TRACE_EVENT(drv_set_key, | |||
346 | LOCAL_ASSIGN; | 346 | LOCAL_ASSIGN; |
347 | VIF_ASSIGN; | 347 | VIF_ASSIGN; |
348 | STA_ASSIGN; | 348 | STA_ASSIGN; |
349 | __entry->alg = key->alg; | 349 | __entry->cipher = key->cipher; |
350 | __entry->flags = key->flags; | 350 | __entry->flags = key->flags; |
351 | __entry->keyidx = key->keyidx; | 351 | __entry->keyidx = key->keyidx; |
352 | __entry->hw_key_idx = key->hw_key_idx; | 352 | __entry->hw_key_idx = key->hw_key_idx; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 9d101fb33861..11f74f5f7b2f 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -265,3 +265,31 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
265 | 265 | ||
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | |||
269 | void ieee80211_request_smps_work(struct work_struct *work) | ||
270 | { | ||
271 | struct ieee80211_sub_if_data *sdata = | ||
272 | container_of(work, struct ieee80211_sub_if_data, | ||
273 | u.mgd.request_smps_work); | ||
274 | |||
275 | mutex_lock(&sdata->u.mgd.mtx); | ||
276 | __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode); | ||
277 | mutex_unlock(&sdata->u.mgd.mtx); | ||
278 | } | ||
279 | |||
280 | void ieee80211_request_smps(struct ieee80211_vif *vif, | ||
281 | enum ieee80211_smps_mode smps_mode) | ||
282 | { | ||
283 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
284 | |||
285 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
286 | return; | ||
287 | |||
288 | if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF)) | ||
289 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
290 | |||
291 | ieee80211_queue_work(&sdata->local->hw, | ||
292 | &sdata->u.mgd.request_smps_work); | ||
293 | } | ||
294 | /* this might change ... don't want non-open drivers using it */ | ||
295 | EXPORT_SYMBOL_GPL(ieee80211_request_smps); | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c691780725a7..32af97108425 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -920,12 +920,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
920 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | 920 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); |
921 | sdata->u.ibss.ssid_len = params->ssid_len; | 921 | sdata->u.ibss.ssid_len = params->ssid_len; |
922 | 922 | ||
923 | mutex_unlock(&sdata->u.ibss.mtx); | ||
924 | |||
925 | mutex_lock(&sdata->local->mtx); | ||
923 | ieee80211_recalc_idle(sdata->local); | 926 | ieee80211_recalc_idle(sdata->local); |
927 | mutex_unlock(&sdata->local->mtx); | ||
924 | 928 | ||
925 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 929 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
926 | 930 | ||
927 | mutex_unlock(&sdata->u.ibss.mtx); | ||
928 | |||
929 | return 0; | 931 | return 0; |
930 | } | 932 | } |
931 | 933 | ||
@@ -980,7 +982,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
980 | 982 | ||
981 | mutex_unlock(&sdata->u.ibss.mtx); | 983 | mutex_unlock(&sdata->u.ibss.mtx); |
982 | 984 | ||
985 | mutex_lock(&local->mtx); | ||
983 | ieee80211_recalc_idle(sdata->local); | 986 | ieee80211_recalc_idle(sdata->local); |
987 | mutex_unlock(&local->mtx); | ||
984 | 988 | ||
985 | return 0; | 989 | return 0; |
986 | } | 990 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 65e0ed6c2975..e73ae51dc036 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -170,6 +170,7 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
170 | #define IEEE80211_RX_RA_MATCH BIT(1) | 170 | #define IEEE80211_RX_RA_MATCH BIT(1) |
171 | #define IEEE80211_RX_AMSDU BIT(2) | 171 | #define IEEE80211_RX_AMSDU BIT(2) |
172 | #define IEEE80211_RX_FRAGMENTED BIT(3) | 172 | #define IEEE80211_RX_FRAGMENTED BIT(3) |
173 | #define IEEE80211_MALFORMED_ACTION_FRM BIT(4) | ||
173 | /* only add flags here that do not change with subframes of an aMPDU */ | 174 | /* only add flags here that do not change with subframes of an aMPDU */ |
174 | 175 | ||
175 | struct ieee80211_rx_data { | 176 | struct ieee80211_rx_data { |
@@ -343,7 +344,10 @@ struct ieee80211_if_managed { | |||
343 | unsigned long timers_running; /* used for quiesce/restart */ | 344 | unsigned long timers_running; /* used for quiesce/restart */ |
344 | bool powersave; /* powersave requested for this iface */ | 345 | bool powersave; /* powersave requested for this iface */ |
345 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | 346 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ |
346 | ap_smps; /* smps mode AP thinks we're in */ | 347 | ap_smps, /* smps mode AP thinks we're in */ |
348 | driver_smps_mode; /* smps mode request */ | ||
349 | |||
350 | struct work_struct request_smps_work; | ||
347 | 351 | ||
348 | unsigned int flags; | 352 | unsigned int flags; |
349 | 353 | ||
@@ -497,6 +501,9 @@ struct ieee80211_sub_if_data { | |||
497 | */ | 501 | */ |
498 | bool ht_opmode_valid; | 502 | bool ht_opmode_valid; |
499 | 503 | ||
504 | /* to detect idle changes */ | ||
505 | bool old_idle; | ||
506 | |||
500 | /* Fragment table for host-based reassembly */ | 507 | /* Fragment table for host-based reassembly */ |
501 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 508 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
502 | unsigned int fragment_next; | 509 | unsigned int fragment_next; |
@@ -634,7 +641,6 @@ struct ieee80211_local { | |||
634 | /* | 641 | /* |
635 | * work stuff, potentially off-channel (in the future) | 642 | * work stuff, potentially off-channel (in the future) |
636 | */ | 643 | */ |
637 | struct mutex work_mtx; | ||
638 | struct list_head work_list; | 644 | struct list_head work_list; |
639 | struct timer_list work_timer; | 645 | struct timer_list work_timer; |
640 | struct work_struct work_work; | 646 | struct work_struct work_work; |
@@ -746,9 +752,10 @@ struct ieee80211_local { | |||
746 | */ | 752 | */ |
747 | struct mutex key_mtx; | 753 | struct mutex key_mtx; |
748 | 754 | ||
755 | /* mutex for scan and work locking */ | ||
756 | struct mutex mtx; | ||
749 | 757 | ||
750 | /* Scanning and BSS list */ | 758 | /* Scanning and BSS list */ |
751 | struct mutex scan_mtx; | ||
752 | unsigned long scanning; | 759 | unsigned long scanning; |
753 | struct cfg80211_ssid scan_ssid; | 760 | struct cfg80211_ssid scan_ssid; |
754 | struct cfg80211_scan_request *int_scan_req; | 761 | struct cfg80211_scan_request *int_scan_req; |
@@ -870,6 +877,11 @@ struct ieee80211_local { | |||
870 | struct dentry *keys; | 877 | struct dentry *keys; |
871 | } debugfs; | 878 | } debugfs; |
872 | #endif | 879 | #endif |
880 | |||
881 | /* dummy netdev for use w/ NAPI */ | ||
882 | struct net_device napi_dev; | ||
883 | |||
884 | struct napi_struct napi; | ||
873 | }; | 885 | }; |
874 | 886 | ||
875 | static inline struct ieee80211_sub_if_data * | 887 | static inline struct ieee80211_sub_if_data * |
@@ -1105,6 +1117,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
1105 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 1117 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
1106 | enum ieee80211_smps_mode smps, const u8 *da, | 1118 | enum ieee80211_smps_mode smps, const u8 *da, |
1107 | const u8 *bssid); | 1119 | const u8 *bssid); |
1120 | void ieee80211_request_smps_work(struct work_struct *work); | ||
1108 | 1121 | ||
1109 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1122 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1110 | u16 initiator, u16 reason); | 1123 | u16 initiator, u16 reason); |
@@ -1131,6 +1144,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | |||
1131 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | 1144 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); |
1132 | void ieee80211_ba_session_work(struct work_struct *work); | 1145 | void ieee80211_ba_session_work(struct work_struct *work); |
1133 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); | 1146 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); |
1147 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid); | ||
1134 | 1148 | ||
1135 | /* Spectrum management */ | 1149 | /* Spectrum management */ |
1136 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1150 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ebbe264e2b0b..86f434f234ae 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -177,7 +177,7 @@ static int ieee80211_open(struct net_device *dev) | |||
177 | /* no special treatment */ | 177 | /* no special treatment */ |
178 | break; | 178 | break; |
179 | case NL80211_IFTYPE_UNSPECIFIED: | 179 | case NL80211_IFTYPE_UNSPECIFIED: |
180 | case __NL80211_IFTYPE_AFTER_LAST: | 180 | case NUM_NL80211_IFTYPES: |
181 | /* cannot happen */ | 181 | /* cannot happen */ |
182 | WARN_ON(1); | 182 | WARN_ON(1); |
183 | break; | 183 | break; |
@@ -187,6 +187,8 @@ static int ieee80211_open(struct net_device *dev) | |||
187 | res = drv_start(local); | 187 | res = drv_start(local); |
188 | if (res) | 188 | if (res) |
189 | goto err_del_bss; | 189 | goto err_del_bss; |
190 | if (local->ops->napi_poll) | ||
191 | napi_enable(&local->napi); | ||
190 | /* we're brought up, everything changes */ | 192 | /* we're brought up, everything changes */ |
191 | hw_reconf_flags = ~0; | 193 | hw_reconf_flags = ~0; |
192 | ieee80211_led_radio(local, true); | 194 | ieee80211_led_radio(local, true); |
@@ -307,7 +309,9 @@ static int ieee80211_open(struct net_device *dev) | |||
307 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 309 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
308 | atomic_inc(&local->iff_promiscs); | 310 | atomic_inc(&local->iff_promiscs); |
309 | 311 | ||
312 | mutex_lock(&local->mtx); | ||
310 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | 313 | hw_reconf_flags |= __ieee80211_recalc_idle(local); |
314 | mutex_unlock(&local->mtx); | ||
311 | 315 | ||
312 | local->open_count++; | 316 | local->open_count++; |
313 | if (hw_reconf_flags) { | 317 | if (hw_reconf_flags) { |
@@ -514,11 +518,15 @@ static int ieee80211_stop(struct net_device *dev) | |||
514 | 518 | ||
515 | sdata->bss = NULL; | 519 | sdata->bss = NULL; |
516 | 520 | ||
521 | mutex_lock(&local->mtx); | ||
517 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | 522 | hw_reconf_flags |= __ieee80211_recalc_idle(local); |
523 | mutex_unlock(&local->mtx); | ||
518 | 524 | ||
519 | ieee80211_recalc_ps(local, -1); | 525 | ieee80211_recalc_ps(local, -1); |
520 | 526 | ||
521 | if (local->open_count == 0) { | 527 | if (local->open_count == 0) { |
528 | if (local->ops->napi_poll) | ||
529 | napi_disable(&local->napi); | ||
522 | ieee80211_clear_tx_pending(local); | 530 | ieee80211_clear_tx_pending(local); |
523 | ieee80211_stop_device(local); | 531 | ieee80211_stop_device(local); |
524 | 532 | ||
@@ -626,7 +634,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
626 | case NL80211_IFTYPE_MONITOR: | 634 | case NL80211_IFTYPE_MONITOR: |
627 | break; | 635 | break; |
628 | case NL80211_IFTYPE_UNSPECIFIED: | 636 | case NL80211_IFTYPE_UNSPECIFIED: |
629 | case __NL80211_IFTYPE_AFTER_LAST: | 637 | case NUM_NL80211_IFTYPES: |
630 | BUG(); | 638 | BUG(); |
631 | break; | 639 | break; |
632 | } | 640 | } |
@@ -878,7 +886,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
878 | case NL80211_IFTYPE_AP_VLAN: | 886 | case NL80211_IFTYPE_AP_VLAN: |
879 | break; | 887 | break; |
880 | case NL80211_IFTYPE_UNSPECIFIED: | 888 | case NL80211_IFTYPE_UNSPECIFIED: |
881 | case __NL80211_IFTYPE_AFTER_LAST: | 889 | case NUM_NL80211_IFTYPES: |
882 | BUG(); | 890 | BUG(); |
883 | break; | 891 | break; |
884 | } | 892 | } |
@@ -1195,28 +1203,61 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1195 | { | 1203 | { |
1196 | struct ieee80211_sub_if_data *sdata; | 1204 | struct ieee80211_sub_if_data *sdata; |
1197 | int count = 0; | 1205 | int count = 0; |
1206 | bool working = false, scanning = false; | ||
1207 | struct ieee80211_work *wk; | ||
1198 | 1208 | ||
1199 | if (!list_empty(&local->work_list)) | 1209 | #ifdef CONFIG_PROVE_LOCKING |
1200 | return ieee80211_idle_off(local, "working"); | 1210 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && |
1201 | 1211 | !lockdep_is_held(&local->iflist_mtx)); | |
1202 | if (local->scanning) | 1212 | #endif |
1203 | return ieee80211_idle_off(local, "scanning"); | 1213 | lockdep_assert_held(&local->mtx); |
1204 | 1214 | ||
1205 | list_for_each_entry(sdata, &local->interfaces, list) { | 1215 | list_for_each_entry(sdata, &local->interfaces, list) { |
1206 | if (!ieee80211_sdata_running(sdata)) | 1216 | if (!ieee80211_sdata_running(sdata)) { |
1217 | sdata->vif.bss_conf.idle = true; | ||
1207 | continue; | 1218 | continue; |
1219 | } | ||
1220 | |||
1221 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
1222 | |||
1208 | /* do not count disabled managed interfaces */ | 1223 | /* do not count disabled managed interfaces */ |
1209 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1224 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1210 | !sdata->u.mgd.associated) | 1225 | !sdata->u.mgd.associated) { |
1226 | sdata->vif.bss_conf.idle = true; | ||
1211 | continue; | 1227 | continue; |
1228 | } | ||
1212 | /* do not count unused IBSS interfaces */ | 1229 | /* do not count unused IBSS interfaces */ |
1213 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 1230 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
1214 | !sdata->u.ibss.ssid_len) | 1231 | !sdata->u.ibss.ssid_len) { |
1232 | sdata->vif.bss_conf.idle = true; | ||
1215 | continue; | 1233 | continue; |
1234 | } | ||
1216 | /* count everything else */ | 1235 | /* count everything else */ |
1217 | count++; | 1236 | count++; |
1218 | } | 1237 | } |
1219 | 1238 | ||
1239 | list_for_each_entry(wk, &local->work_list, list) { | ||
1240 | working = true; | ||
1241 | wk->sdata->vif.bss_conf.idle = false; | ||
1242 | } | ||
1243 | |||
1244 | if (local->scan_sdata) { | ||
1245 | scanning = true; | ||
1246 | local->scan_sdata->vif.bss_conf.idle = false; | ||
1247 | } | ||
1248 | |||
1249 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1250 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
1251 | continue; | ||
1252 | if (!ieee80211_sdata_running(sdata)) | ||
1253 | continue; | ||
1254 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
1255 | } | ||
1256 | |||
1257 | if (working) | ||
1258 | return ieee80211_idle_off(local, "working"); | ||
1259 | if (scanning) | ||
1260 | return ieee80211_idle_off(local, "scanning"); | ||
1220 | if (!count) | 1261 | if (!count) |
1221 | return ieee80211_idle_on(local); | 1262 | return ieee80211_idle_on(local); |
1222 | else | 1263 | else |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 1b9d87ed143a..9c27c53cfae5 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -227,20 +227,18 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
227 | } | 227 | } |
228 | } | 228 | } |
229 | 229 | ||
230 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 230 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
231 | int idx, | ||
232 | size_t key_len, | ||
233 | const u8 *key_data, | 231 | const u8 *key_data, |
234 | size_t seq_len, const u8 *seq) | 232 | size_t seq_len, const u8 *seq) |
235 | { | 233 | { |
236 | struct ieee80211_key *key; | 234 | struct ieee80211_key *key; |
237 | int i, j; | 235 | int i, j, err; |
238 | 236 | ||
239 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); | 237 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); |
240 | 238 | ||
241 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); | 239 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); |
242 | if (!key) | 240 | if (!key) |
243 | return NULL; | 241 | return ERR_PTR(-ENOMEM); |
244 | 242 | ||
245 | /* | 243 | /* |
246 | * Default to software encryption; we'll later upload the | 244 | * Default to software encryption; we'll later upload the |
@@ -249,15 +247,16 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
249 | key->conf.flags = 0; | 247 | key->conf.flags = 0; |
250 | key->flags = 0; | 248 | key->flags = 0; |
251 | 249 | ||
252 | key->conf.alg = alg; | 250 | key->conf.cipher = cipher; |
253 | key->conf.keyidx = idx; | 251 | key->conf.keyidx = idx; |
254 | key->conf.keylen = key_len; | 252 | key->conf.keylen = key_len; |
255 | switch (alg) { | 253 | switch (cipher) { |
256 | case ALG_WEP: | 254 | case WLAN_CIPHER_SUITE_WEP40: |
255 | case WLAN_CIPHER_SUITE_WEP104: | ||
257 | key->conf.iv_len = WEP_IV_LEN; | 256 | key->conf.iv_len = WEP_IV_LEN; |
258 | key->conf.icv_len = WEP_ICV_LEN; | 257 | key->conf.icv_len = WEP_ICV_LEN; |
259 | break; | 258 | break; |
260 | case ALG_TKIP: | 259 | case WLAN_CIPHER_SUITE_TKIP: |
261 | key->conf.iv_len = TKIP_IV_LEN; | 260 | key->conf.iv_len = TKIP_IV_LEN; |
262 | key->conf.icv_len = TKIP_ICV_LEN; | 261 | key->conf.icv_len = TKIP_ICV_LEN; |
263 | if (seq) { | 262 | if (seq) { |
@@ -269,7 +268,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
269 | } | 268 | } |
270 | } | 269 | } |
271 | break; | 270 | break; |
272 | case ALG_CCMP: | 271 | case WLAN_CIPHER_SUITE_CCMP: |
273 | key->conf.iv_len = CCMP_HDR_LEN; | 272 | key->conf.iv_len = CCMP_HDR_LEN; |
274 | key->conf.icv_len = CCMP_MIC_LEN; | 273 | key->conf.icv_len = CCMP_MIC_LEN; |
275 | if (seq) { | 274 | if (seq) { |
@@ -278,42 +277,38 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
278 | key->u.ccmp.rx_pn[i][j] = | 277 | key->u.ccmp.rx_pn[i][j] = |
279 | seq[CCMP_PN_LEN - j - 1]; | 278 | seq[CCMP_PN_LEN - j - 1]; |
280 | } | 279 | } |
281 | break; | ||
282 | case ALG_AES_CMAC: | ||
283 | key->conf.iv_len = 0; | ||
284 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | ||
285 | if (seq) | ||
286 | for (j = 0; j < 6; j++) | ||
287 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | ||
288 | break; | ||
289 | } | ||
290 | memcpy(key->conf.key, key_data, key_len); | ||
291 | INIT_LIST_HEAD(&key->list); | ||
292 | |||
293 | if (alg == ALG_CCMP) { | ||
294 | /* | 280 | /* |
295 | * Initialize AES key state here as an optimization so that | 281 | * Initialize AES key state here as an optimization so that |
296 | * it does not need to be initialized for every packet. | 282 | * it does not need to be initialized for every packet. |
297 | */ | 283 | */ |
298 | key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); | 284 | key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); |
299 | if (!key->u.ccmp.tfm) { | 285 | if (IS_ERR(key->u.ccmp.tfm)) { |
286 | err = PTR_ERR(key->u.ccmp.tfm); | ||
300 | kfree(key); | 287 | kfree(key); |
301 | return NULL; | 288 | key = ERR_PTR(err); |
302 | } | 289 | } |
303 | } | 290 | break; |
304 | 291 | case WLAN_CIPHER_SUITE_AES_CMAC: | |
305 | if (alg == ALG_AES_CMAC) { | 292 | key->conf.iv_len = 0; |
293 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | ||
294 | if (seq) | ||
295 | for (j = 0; j < 6; j++) | ||
296 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | ||
306 | /* | 297 | /* |
307 | * Initialize AES key state here as an optimization so that | 298 | * Initialize AES key state here as an optimization so that |
308 | * it does not need to be initialized for every packet. | 299 | * it does not need to be initialized for every packet. |
309 | */ | 300 | */ |
310 | key->u.aes_cmac.tfm = | 301 | key->u.aes_cmac.tfm = |
311 | ieee80211_aes_cmac_key_setup(key_data); | 302 | ieee80211_aes_cmac_key_setup(key_data); |
312 | if (!key->u.aes_cmac.tfm) { | 303 | if (IS_ERR(key->u.aes_cmac.tfm)) { |
304 | err = PTR_ERR(key->u.aes_cmac.tfm); | ||
313 | kfree(key); | 305 | kfree(key); |
314 | return NULL; | 306 | key = ERR_PTR(err); |
315 | } | 307 | } |
308 | break; | ||
316 | } | 309 | } |
310 | memcpy(key->conf.key, key_data, key_len); | ||
311 | INIT_LIST_HEAD(&key->list); | ||
317 | 312 | ||
318 | return key; | 313 | return key; |
319 | } | 314 | } |
@@ -326,9 +321,9 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
326 | if (key->local) | 321 | if (key->local) |
327 | ieee80211_key_disable_hw_accel(key); | 322 | ieee80211_key_disable_hw_accel(key); |
328 | 323 | ||
329 | if (key->conf.alg == ALG_CCMP) | 324 | if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) |
330 | ieee80211_aes_key_free(key->u.ccmp.tfm); | 325 | ieee80211_aes_key_free(key->u.ccmp.tfm); |
331 | if (key->conf.alg == ALG_AES_CMAC) | 326 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
332 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | 327 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); |
333 | if (key->local) | 328 | if (key->local) |
334 | ieee80211_debugfs_key_remove(key); | 329 | ieee80211_debugfs_key_remove(key); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index b665bbb7a471..53b5ce12536f 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -123,9 +123,7 @@ struct ieee80211_key { | |||
123 | struct ieee80211_key_conf conf; | 123 | struct ieee80211_key_conf conf; |
124 | }; | 124 | }; |
125 | 125 | ||
126 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 126 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
127 | int idx, | ||
128 | size_t key_len, | ||
129 | const u8 *key_data, | 127 | const u8 *key_data, |
130 | size_t seq_len, const u8 *seq); | 128 | size_t seq_len, const u8 *seq); |
131 | /* | 129 | /* |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 798a91b100cc..a53feac4618c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -99,11 +99,13 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
99 | int ret = 0; | 99 | int ret = 0; |
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | 101 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | ||
102 | 103 | ||
103 | might_sleep(); | 104 | might_sleep(); |
104 | 105 | ||
105 | scan_chan = local->scan_channel; | 106 | scan_chan = local->scan_channel; |
106 | 107 | ||
108 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
107 | if (scan_chan) { | 109 | if (scan_chan) { |
108 | chan = scan_chan; | 110 | chan = scan_chan; |
109 | channel_type = NL80211_CHAN_NO_HT; | 111 | channel_type = NL80211_CHAN_NO_HT; |
@@ -117,8 +119,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
117 | channel_type = local->_oper_channel_type; | 119 | channel_type = local->_oper_channel_type; |
118 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | 120 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; |
119 | } | 121 | } |
122 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
120 | 123 | ||
121 | if (chan != local->hw.conf.channel || | 124 | if (offchannel_flag || chan != local->hw.conf.channel || |
122 | channel_type != local->hw.conf.channel_type) { | 125 | channel_type != local->hw.conf.channel_type) { |
123 | local->hw.conf.channel = chan; | 126 | local->hw.conf.channel = chan; |
124 | local->hw.conf.channel_type = channel_type; | 127 | local->hw.conf.channel_type = channel_type; |
@@ -390,6 +393,65 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
390 | } | 393 | } |
391 | #endif | 394 | #endif |
392 | 395 | ||
396 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | ||
397 | { | ||
398 | struct ieee80211_local *local = | ||
399 | container_of(napi, struct ieee80211_local, napi); | ||
400 | |||
401 | return local->ops->napi_poll(&local->hw, budget); | ||
402 | } | ||
403 | |||
404 | void ieee80211_napi_schedule(struct ieee80211_hw *hw) | ||
405 | { | ||
406 | struct ieee80211_local *local = hw_to_local(hw); | ||
407 | |||
408 | napi_schedule(&local->napi); | ||
409 | } | ||
410 | EXPORT_SYMBOL(ieee80211_napi_schedule); | ||
411 | |||
412 | void ieee80211_napi_complete(struct ieee80211_hw *hw) | ||
413 | { | ||
414 | struct ieee80211_local *local = hw_to_local(hw); | ||
415 | |||
416 | napi_complete(&local->napi); | ||
417 | } | ||
418 | EXPORT_SYMBOL(ieee80211_napi_complete); | ||
419 | |||
420 | /* There isn't a lot of sense in it, but you can transmit anything you like */ | ||
421 | static const struct ieee80211_txrx_stypes | ||
422 | ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | ||
423 | [NL80211_IFTYPE_ADHOC] = { | ||
424 | .tx = 0xffff, | ||
425 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4), | ||
426 | }, | ||
427 | [NL80211_IFTYPE_STATION] = { | ||
428 | .tx = 0xffff, | ||
429 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
430 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
431 | }, | ||
432 | [NL80211_IFTYPE_AP] = { | ||
433 | .tx = 0xffff, | ||
434 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
435 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
436 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
437 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
438 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
439 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
440 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
441 | }, | ||
442 | [NL80211_IFTYPE_AP_VLAN] = { | ||
443 | /* copy AP */ | ||
444 | .tx = 0xffff, | ||
445 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
446 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
447 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
448 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
449 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
450 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
451 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
452 | }, | ||
453 | }; | ||
454 | |||
393 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 455 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
394 | const struct ieee80211_ops *ops) | 456 | const struct ieee80211_ops *ops) |
395 | { | 457 | { |
@@ -419,6 +481,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
419 | if (!wiphy) | 481 | if (!wiphy) |
420 | return NULL; | 482 | return NULL; |
421 | 483 | ||
484 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; | ||
485 | |||
422 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 486 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
423 | WIPHY_FLAG_4ADDR_AP | | 487 | WIPHY_FLAG_4ADDR_AP | |
424 | WIPHY_FLAG_4ADDR_STATION; | 488 | WIPHY_FLAG_4ADDR_STATION; |
@@ -455,7 +519,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
455 | __hw_addr_init(&local->mc_list); | 519 | __hw_addr_init(&local->mc_list); |
456 | 520 | ||
457 | mutex_init(&local->iflist_mtx); | 521 | mutex_init(&local->iflist_mtx); |
458 | mutex_init(&local->scan_mtx); | 522 | mutex_init(&local->mtx); |
459 | 523 | ||
460 | mutex_init(&local->key_mtx); | 524 | mutex_init(&local->key_mtx); |
461 | spin_lock_init(&local->filter_lock); | 525 | spin_lock_init(&local->filter_lock); |
@@ -494,6 +558,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
494 | skb_queue_head_init(&local->skb_queue); | 558 | skb_queue_head_init(&local->skb_queue); |
495 | skb_queue_head_init(&local->skb_queue_unreliable); | 559 | skb_queue_head_init(&local->skb_queue_unreliable); |
496 | 560 | ||
561 | /* init dummy netdev for use w/ NAPI */ | ||
562 | init_dummy_netdev(&local->napi_dev); | ||
563 | |||
497 | return local_to_hw(local); | 564 | return local_to_hw(local); |
498 | } | 565 | } |
499 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 566 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
@@ -506,6 +573,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
506 | int channels, max_bitrates; | 573 | int channels, max_bitrates; |
507 | bool supp_ht; | 574 | bool supp_ht; |
508 | static const u32 cipher_suites[] = { | 575 | static const u32 cipher_suites[] = { |
576 | /* keep WEP first, it may be removed below */ | ||
509 | WLAN_CIPHER_SUITE_WEP40, | 577 | WLAN_CIPHER_SUITE_WEP40, |
510 | WLAN_CIPHER_SUITE_WEP104, | 578 | WLAN_CIPHER_SUITE_WEP104, |
511 | WLAN_CIPHER_SUITE_TKIP, | 579 | WLAN_CIPHER_SUITE_TKIP, |
@@ -593,6 +661,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
593 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 661 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
594 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) | 662 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) |
595 | local->hw.wiphy->n_cipher_suites--; | 663 | local->hw.wiphy->n_cipher_suites--; |
664 | if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { | ||
665 | local->hw.wiphy->cipher_suites += 2; | ||
666 | local->hw.wiphy->n_cipher_suites -= 2; | ||
667 | } | ||
596 | 668 | ||
597 | result = wiphy_register(local->hw.wiphy); | 669 | result = wiphy_register(local->hw.wiphy); |
598 | if (result < 0) | 670 | if (result < 0) |
@@ -683,6 +755,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
683 | goto fail_ifa; | 755 | goto fail_ifa; |
684 | #endif | 756 | #endif |
685 | 757 | ||
758 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, | ||
759 | local->hw.napi_weight); | ||
760 | |||
686 | return 0; | 761 | return 0; |
687 | 762 | ||
688 | #ifdef CONFIG_INET | 763 | #ifdef CONFIG_INET |
@@ -758,7 +833,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
758 | struct ieee80211_local *local = hw_to_local(hw); | 833 | struct ieee80211_local *local = hw_to_local(hw); |
759 | 834 | ||
760 | mutex_destroy(&local->iflist_mtx); | 835 | mutex_destroy(&local->iflist_mtx); |
761 | mutex_destroy(&local->scan_mtx); | 836 | mutex_destroy(&local->mtx); |
762 | 837 | ||
763 | wiphy_free(local->hw.wiphy); | 838 | wiphy_free(local->hw.wiphy); |
764 | } | 839 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b6c163ac22da..38996a44aa8e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1103,8 +1103,11 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1103 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | 1103 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); |
1104 | 1104 | ||
1105 | ieee80211_set_disassoc(sdata, true); | 1105 | ieee80211_set_disassoc(sdata, true); |
1106 | ieee80211_recalc_idle(local); | ||
1107 | mutex_unlock(&ifmgd->mtx); | 1106 | mutex_unlock(&ifmgd->mtx); |
1107 | |||
1108 | mutex_lock(&local->mtx); | ||
1109 | ieee80211_recalc_idle(local); | ||
1110 | mutex_unlock(&local->mtx); | ||
1108 | /* | 1111 | /* |
1109 | * must be outside lock due to cfg80211, | 1112 | * must be outside lock due to cfg80211, |
1110 | * but that's not a problem. | 1113 | * but that's not a problem. |
@@ -1173,7 +1176,9 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1173 | sdata->name, bssid, reason_code); | 1176 | sdata->name, bssid, reason_code); |
1174 | 1177 | ||
1175 | ieee80211_set_disassoc(sdata, true); | 1178 | ieee80211_set_disassoc(sdata, true); |
1179 | mutex_lock(&sdata->local->mtx); | ||
1176 | ieee80211_recalc_idle(sdata->local); | 1180 | ieee80211_recalc_idle(sdata->local); |
1181 | mutex_unlock(&sdata->local->mtx); | ||
1177 | 1182 | ||
1178 | return RX_MGMT_CFG80211_DEAUTH; | 1183 | return RX_MGMT_CFG80211_DEAUTH; |
1179 | } | 1184 | } |
@@ -1203,7 +1208,9 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1203 | sdata->name, mgmt->sa, reason_code); | 1208 | sdata->name, mgmt->sa, reason_code); |
1204 | 1209 | ||
1205 | ieee80211_set_disassoc(sdata, true); | 1210 | ieee80211_set_disassoc(sdata, true); |
1211 | mutex_lock(&sdata->local->mtx); | ||
1206 | ieee80211_recalc_idle(sdata->local); | 1212 | ieee80211_recalc_idle(sdata->local); |
1213 | mutex_unlock(&sdata->local->mtx); | ||
1207 | return RX_MGMT_CFG80211_DISASSOC; | 1214 | return RX_MGMT_CFG80211_DISASSOC; |
1208 | } | 1215 | } |
1209 | 1216 | ||
@@ -1751,7 +1758,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1751 | struct ieee80211_local *local = sdata->local; | 1758 | struct ieee80211_local *local = sdata->local; |
1752 | struct ieee80211_work *wk; | 1759 | struct ieee80211_work *wk; |
1753 | 1760 | ||
1754 | mutex_lock(&local->work_mtx); | 1761 | mutex_lock(&local->mtx); |
1755 | list_for_each_entry(wk, &local->work_list, list) { | 1762 | list_for_each_entry(wk, &local->work_list, list) { |
1756 | if (wk->sdata != sdata) | 1763 | if (wk->sdata != sdata) |
1757 | continue; | 1764 | continue; |
@@ -1783,7 +1790,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1783 | free_work(wk); | 1790 | free_work(wk); |
1784 | break; | 1791 | break; |
1785 | } | 1792 | } |
1786 | mutex_unlock(&local->work_mtx); | 1793 | mutex_unlock(&local->mtx); |
1787 | 1794 | ||
1788 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 1795 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
1789 | } | 1796 | } |
@@ -1840,8 +1847,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1840 | " after %dms, disconnecting.\n", | 1847 | " after %dms, disconnecting.\n", |
1841 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1848 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1842 | ieee80211_set_disassoc(sdata, true); | 1849 | ieee80211_set_disassoc(sdata, true); |
1843 | ieee80211_recalc_idle(local); | ||
1844 | mutex_unlock(&ifmgd->mtx); | 1850 | mutex_unlock(&ifmgd->mtx); |
1851 | mutex_lock(&local->mtx); | ||
1852 | ieee80211_recalc_idle(local); | ||
1853 | mutex_unlock(&local->mtx); | ||
1845 | /* | 1854 | /* |
1846 | * must be outside lock due to cfg80211, | 1855 | * must be outside lock due to cfg80211, |
1847 | * but that's not a problem. | 1856 | * but that's not a problem. |
@@ -1917,6 +1926,8 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
1917 | * time -- the code here is properly synchronised. | 1926 | * time -- the code here is properly synchronised. |
1918 | */ | 1927 | */ |
1919 | 1928 | ||
1929 | cancel_work_sync(&ifmgd->request_smps_work); | ||
1930 | |||
1920 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | 1931 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
1921 | if (del_timer_sync(&ifmgd->timer)) | 1932 | if (del_timer_sync(&ifmgd->timer)) |
1922 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 1933 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
@@ -1952,6 +1963,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
1952 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 1963 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
1953 | INIT_WORK(&ifmgd->beacon_connection_loss_work, | 1964 | INIT_WORK(&ifmgd->beacon_connection_loss_work, |
1954 | ieee80211_beacon_connection_loss_work); | 1965 | ieee80211_beacon_connection_loss_work); |
1966 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); | ||
1955 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 1967 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
1956 | (unsigned long) sdata); | 1968 | (unsigned long) sdata); |
1957 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 1969 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
@@ -2275,7 +2287,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2275 | 2287 | ||
2276 | mutex_unlock(&ifmgd->mtx); | 2288 | mutex_unlock(&ifmgd->mtx); |
2277 | 2289 | ||
2278 | mutex_lock(&local->work_mtx); | 2290 | mutex_lock(&local->mtx); |
2279 | list_for_each_entry(wk, &local->work_list, list) { | 2291 | list_for_each_entry(wk, &local->work_list, list) { |
2280 | if (wk->sdata != sdata) | 2292 | if (wk->sdata != sdata) |
2281 | continue; | 2293 | continue; |
@@ -2294,7 +2306,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2294 | free_work(wk); | 2306 | free_work(wk); |
2295 | break; | 2307 | break; |
2296 | } | 2308 | } |
2297 | mutex_unlock(&local->work_mtx); | 2309 | mutex_unlock(&local->mtx); |
2298 | 2310 | ||
2299 | /* | 2311 | /* |
2300 | * If somebody requests authentication and we haven't | 2312 | * If somebody requests authentication and we haven't |
@@ -2319,7 +2331,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2319 | if (assoc_bss) | 2331 | if (assoc_bss) |
2320 | sta_info_destroy_addr(sdata, bssid); | 2332 | sta_info_destroy_addr(sdata, bssid); |
2321 | 2333 | ||
2334 | mutex_lock(&sdata->local->mtx); | ||
2322 | ieee80211_recalc_idle(sdata->local); | 2335 | ieee80211_recalc_idle(sdata->local); |
2336 | mutex_unlock(&sdata->local->mtx); | ||
2323 | 2337 | ||
2324 | return 0; | 2338 | return 0; |
2325 | } | 2339 | } |
@@ -2357,7 +2371,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2357 | cookie, !req->local_state_change); | 2371 | cookie, !req->local_state_change); |
2358 | sta_info_destroy_addr(sdata, bssid); | 2372 | sta_info_destroy_addr(sdata, bssid); |
2359 | 2373 | ||
2374 | mutex_lock(&sdata->local->mtx); | ||
2360 | ieee80211_recalc_idle(sdata->local); | 2375 | ieee80211_recalc_idle(sdata->local); |
2376 | mutex_unlock(&sdata->local->mtx); | ||
2361 | 2377 | ||
2362 | return 0; | 2378 | return 0; |
2363 | } | 2379 | } |
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index 47438b4a9af5..135f36fd4d5d 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c | |||
@@ -162,7 +162,7 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, | |||
162 | file_info->next_entry = (file_info->next_entry + 1) % | 162 | file_info->next_entry = (file_info->next_entry + 1) % |
163 | RC_PID_EVENT_RING_SIZE; | 163 | RC_PID_EVENT_RING_SIZE; |
164 | 164 | ||
165 | /* Print information about the event. Note that userpace needs to | 165 | /* Print information about the event. Note that userspace needs to |
166 | * provide large enough buffers. */ | 166 | * provide large enough buffers. */ |
167 | length = length < RC_PID_PRINT_BUF_SIZE ? | 167 | length = length < RC_PID_PRINT_BUF_SIZE ? |
168 | length : RC_PID_PRINT_BUF_SIZE; | 168 | length : RC_PID_PRINT_BUF_SIZE; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fa0f37e4afe4..aa41e382bbb3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -538,20 +538,12 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
538 | int index, | 538 | int index, |
539 | struct sk_buff_head *frames) | 539 | struct sk_buff_head *frames) |
540 | { | 540 | { |
541 | struct ieee80211_supported_band *sband; | ||
542 | struct ieee80211_rate *rate = NULL; | ||
543 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 541 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
544 | struct ieee80211_rx_status *status; | ||
545 | 542 | ||
546 | if (!skb) | 543 | if (!skb) |
547 | goto no_frame; | 544 | goto no_frame; |
548 | 545 | ||
549 | status = IEEE80211_SKB_RXCB(skb); | 546 | /* release the frame from the reorder ring buffer */ |
550 | |||
551 | /* release the reordered frames to stack */ | ||
552 | sband = hw->wiphy->bands[status->band]; | ||
553 | if (!(status->flag & RX_FLAG_HT)) | ||
554 | rate = &sband->bitrates[status->rate_idx]; | ||
555 | tid_agg_rx->stored_mpdu_num--; | 547 | tid_agg_rx->stored_mpdu_num--; |
556 | tid_agg_rx->reorder_buf[index] = NULL; | 548 | tid_agg_rx->reorder_buf[index] = NULL; |
557 | __skb_queue_tail(frames, skb); | 549 | __skb_queue_tail(frames, skb); |
@@ -580,9 +572,80 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |||
580 | * frames that have not yet been received are assumed to be lost and the skb | 572 | * frames that have not yet been received are assumed to be lost and the skb |
581 | * can be released for processing. This may also release other skb's from the | 573 | * can be released for processing. This may also release other skb's from the |
582 | * reorder buffer if there are no additional gaps between the frames. | 574 | * reorder buffer if there are no additional gaps between the frames. |
575 | * | ||
576 | * Callers must hold tid_agg_rx->reorder_lock. | ||
583 | */ | 577 | */ |
584 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | 578 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) |
585 | 579 | ||
580 | static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | ||
581 | struct tid_ampdu_rx *tid_agg_rx, | ||
582 | struct sk_buff_head *frames) | ||
583 | { | ||
584 | int index, j; | ||
585 | |||
586 | /* release the buffer until next missing frame */ | ||
587 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
588 | tid_agg_rx->buf_size; | ||
589 | if (!tid_agg_rx->reorder_buf[index] && | ||
590 | tid_agg_rx->stored_mpdu_num > 1) { | ||
591 | /* | ||
592 | * No buffers ready to be released, but check whether any | ||
593 | * frames in the reorder buffer have timed out. | ||
594 | */ | ||
595 | int skipped = 1; | ||
596 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | ||
597 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
598 | if (!tid_agg_rx->reorder_buf[j]) { | ||
599 | skipped++; | ||
600 | continue; | ||
601 | } | ||
602 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
603 | HT_RX_REORDER_BUF_TIMEOUT)) | ||
604 | goto set_release_timer; | ||
605 | |||
606 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
607 | if (net_ratelimit()) | ||
608 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
609 | "frame due to timeout on earlier " | ||
610 | "frames\n", | ||
611 | wiphy_name(hw->wiphy)); | ||
612 | #endif | ||
613 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | ||
614 | j, frames); | ||
615 | |||
616 | /* | ||
617 | * Increment the head seq# also for the skipped slots. | ||
618 | */ | ||
619 | tid_agg_rx->head_seq_num = | ||
620 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | ||
621 | skipped = 0; | ||
622 | } | ||
623 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
624 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | ||
625 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
626 | tid_agg_rx->buf_size; | ||
627 | } | ||
628 | |||
629 | if (tid_agg_rx->stored_mpdu_num) { | ||
630 | j = index = seq_sub(tid_agg_rx->head_seq_num, | ||
631 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | ||
632 | |||
633 | for (; j != (index - 1) % tid_agg_rx->buf_size; | ||
634 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
635 | if (tid_agg_rx->reorder_buf[j]) | ||
636 | break; | ||
637 | } | ||
638 | |||
639 | set_release_timer: | ||
640 | |||
641 | mod_timer(&tid_agg_rx->reorder_timer, | ||
642 | tid_agg_rx->reorder_time[j] + | ||
643 | HT_RX_REORDER_BUF_TIMEOUT); | ||
644 | } else { | ||
645 | del_timer(&tid_agg_rx->reorder_timer); | ||
646 | } | ||
647 | } | ||
648 | |||
586 | /* | 649 | /* |
587 | * As this function belongs to the RX path it must be under | 650 | * As this function belongs to the RX path it must be under |
588 | * rcu_read_lock protection. It returns false if the frame | 651 | * rcu_read_lock protection. It returns false if the frame |
@@ -598,14 +661,16 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
598 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | 661 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; |
599 | u16 head_seq_num, buf_size; | 662 | u16 head_seq_num, buf_size; |
600 | int index; | 663 | int index; |
664 | bool ret = true; | ||
601 | 665 | ||
602 | buf_size = tid_agg_rx->buf_size; | 666 | buf_size = tid_agg_rx->buf_size; |
603 | head_seq_num = tid_agg_rx->head_seq_num; | 667 | head_seq_num = tid_agg_rx->head_seq_num; |
604 | 668 | ||
669 | spin_lock(&tid_agg_rx->reorder_lock); | ||
605 | /* frame with out of date sequence number */ | 670 | /* frame with out of date sequence number */ |
606 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 671 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
607 | dev_kfree_skb(skb); | 672 | dev_kfree_skb(skb); |
608 | return true; | 673 | goto out; |
609 | } | 674 | } |
610 | 675 | ||
611 | /* | 676 | /* |
@@ -626,7 +691,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
626 | /* check if we already stored this frame */ | 691 | /* check if we already stored this frame */ |
627 | if (tid_agg_rx->reorder_buf[index]) { | 692 | if (tid_agg_rx->reorder_buf[index]) { |
628 | dev_kfree_skb(skb); | 693 | dev_kfree_skb(skb); |
629 | return true; | 694 | goto out; |
630 | } | 695 | } |
631 | 696 | ||
632 | /* | 697 | /* |
@@ -636,58 +701,19 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
636 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 701 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
637 | tid_agg_rx->stored_mpdu_num == 0) { | 702 | tid_agg_rx->stored_mpdu_num == 0) { |
638 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 703 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
639 | return false; | 704 | ret = false; |
705 | goto out; | ||
640 | } | 706 | } |
641 | 707 | ||
642 | /* put the frame in the reordering buffer */ | 708 | /* put the frame in the reordering buffer */ |
643 | tid_agg_rx->reorder_buf[index] = skb; | 709 | tid_agg_rx->reorder_buf[index] = skb; |
644 | tid_agg_rx->reorder_time[index] = jiffies; | 710 | tid_agg_rx->reorder_time[index] = jiffies; |
645 | tid_agg_rx->stored_mpdu_num++; | 711 | tid_agg_rx->stored_mpdu_num++; |
646 | /* release the buffer until next missing frame */ | 712 | ieee80211_sta_reorder_release(hw, tid_agg_rx, frames); |
647 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
648 | tid_agg_rx->buf_size; | ||
649 | if (!tid_agg_rx->reorder_buf[index] && | ||
650 | tid_agg_rx->stored_mpdu_num > 1) { | ||
651 | /* | ||
652 | * No buffers ready to be released, but check whether any | ||
653 | * frames in the reorder buffer have timed out. | ||
654 | */ | ||
655 | int j; | ||
656 | int skipped = 1; | ||
657 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | ||
658 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
659 | if (!tid_agg_rx->reorder_buf[j]) { | ||
660 | skipped++; | ||
661 | continue; | ||
662 | } | ||
663 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
664 | HT_RX_REORDER_BUF_TIMEOUT)) | ||
665 | break; | ||
666 | |||
667 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
668 | if (net_ratelimit()) | ||
669 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
670 | "frame due to timeout on earlier " | ||
671 | "frames\n", | ||
672 | wiphy_name(hw->wiphy)); | ||
673 | #endif | ||
674 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | ||
675 | j, frames); | ||
676 | 713 | ||
677 | /* | 714 | out: |
678 | * Increment the head seq# also for the skipped slots. | 715 | spin_unlock(&tid_agg_rx->reorder_lock); |
679 | */ | 716 | return ret; |
680 | tid_agg_rx->head_seq_num = | ||
681 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | ||
682 | skipped = 0; | ||
683 | } | ||
684 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
685 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | ||
686 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
687 | tid_agg_rx->buf_size; | ||
688 | } | ||
689 | |||
690 | return true; | ||
691 | } | 717 | } |
692 | 718 | ||
693 | /* | 719 | /* |
@@ -873,6 +899,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
873 | 899 | ||
874 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 900 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
875 | rx->key = stakey; | 901 | rx->key = stakey; |
902 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
903 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
904 | return RX_CONTINUE; | ||
876 | /* Skip decryption if the frame is not protected. */ | 905 | /* Skip decryption if the frame is not protected. */ |
877 | if (!ieee80211_has_protected(fc)) | 906 | if (!ieee80211_has_protected(fc)) |
878 | return RX_CONTINUE; | 907 | return RX_CONTINUE; |
@@ -935,7 +964,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
935 | * pairwise or station-to-station keys, but for WEP we allow | 964 | * pairwise or station-to-station keys, but for WEP we allow |
936 | * using a key index as well. | 965 | * using a key index as well. |
937 | */ | 966 | */ |
938 | if (rx->key && rx->key->conf.alg != ALG_WEP && | 967 | if (rx->key && rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && |
968 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | ||
939 | !is_multicast_ether_addr(hdr->addr1)) | 969 | !is_multicast_ether_addr(hdr->addr1)) |
940 | rx->key = NULL; | 970 | rx->key = NULL; |
941 | } | 971 | } |
@@ -951,8 +981,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
951 | return RX_DROP_UNUSABLE; | 981 | return RX_DROP_UNUSABLE; |
952 | /* the hdr variable is invalid now! */ | 982 | /* the hdr variable is invalid now! */ |
953 | 983 | ||
954 | switch (rx->key->conf.alg) { | 984 | switch (rx->key->conf.cipher) { |
955 | case ALG_WEP: | 985 | case WLAN_CIPHER_SUITE_WEP40: |
986 | case WLAN_CIPHER_SUITE_WEP104: | ||
956 | /* Check for weak IVs if possible */ | 987 | /* Check for weak IVs if possible */ |
957 | if (rx->sta && ieee80211_is_data(fc) && | 988 | if (rx->sta && ieee80211_is_data(fc) && |
958 | (!(status->flag & RX_FLAG_IV_STRIPPED) || | 989 | (!(status->flag & RX_FLAG_IV_STRIPPED) || |
@@ -962,13 +993,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
962 | 993 | ||
963 | result = ieee80211_crypto_wep_decrypt(rx); | 994 | result = ieee80211_crypto_wep_decrypt(rx); |
964 | break; | 995 | break; |
965 | case ALG_TKIP: | 996 | case WLAN_CIPHER_SUITE_TKIP: |
966 | result = ieee80211_crypto_tkip_decrypt(rx); | 997 | result = ieee80211_crypto_tkip_decrypt(rx); |
967 | break; | 998 | break; |
968 | case ALG_CCMP: | 999 | case WLAN_CIPHER_SUITE_CCMP: |
969 | result = ieee80211_crypto_ccmp_decrypt(rx); | 1000 | result = ieee80211_crypto_ccmp_decrypt(rx); |
970 | break; | 1001 | break; |
971 | case ALG_AES_CMAC: | 1002 | case WLAN_CIPHER_SUITE_AES_CMAC: |
972 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | 1003 | result = ieee80211_crypto_aes_cmac_decrypt(rx); |
973 | break; | 1004 | break; |
974 | } | 1005 | } |
@@ -1265,7 +1296,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1265 | /* This is the first fragment of a new frame. */ | 1296 | /* This is the first fragment of a new frame. */ |
1266 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 1297 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
1267 | rx->queue, &(rx->skb)); | 1298 | rx->queue, &(rx->skb)); |
1268 | if (rx->key && rx->key->conf.alg == ALG_CCMP && | 1299 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && |
1269 | ieee80211_has_protected(fc)) { | 1300 | ieee80211_has_protected(fc)) { |
1270 | int queue = ieee80211_is_mgmt(fc) ? | 1301 | int queue = ieee80211_is_mgmt(fc) ? |
1271 | NUM_RX_DATA_QUEUES : rx->queue; | 1302 | NUM_RX_DATA_QUEUES : rx->queue; |
@@ -1294,7 +1325,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1294 | int i; | 1325 | int i; |
1295 | u8 pn[CCMP_PN_LEN], *rpn; | 1326 | u8 pn[CCMP_PN_LEN], *rpn; |
1296 | int queue; | 1327 | int queue; |
1297 | if (!rx->key || rx->key->conf.alg != ALG_CCMP) | 1328 | if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) |
1298 | return RX_DROP_UNUSABLE; | 1329 | return RX_DROP_UNUSABLE; |
1299 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); | 1330 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); |
1300 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { | 1331 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { |
@@ -1909,13 +1940,36 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | |||
1909 | } | 1940 | } |
1910 | 1941 | ||
1911 | static ieee80211_rx_result debug_noinline | 1942 | static ieee80211_rx_result debug_noinline |
1943 | ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | ||
1944 | { | ||
1945 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1946 | |||
1947 | /* | ||
1948 | * From here on, look only at management frames. | ||
1949 | * Data and control frames are already handled, | ||
1950 | * and unknown (reserved) frames are useless. | ||
1951 | */ | ||
1952 | if (rx->skb->len < 24) | ||
1953 | return RX_DROP_MONITOR; | ||
1954 | |||
1955 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | ||
1956 | return RX_DROP_MONITOR; | ||
1957 | |||
1958 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
1959 | return RX_DROP_MONITOR; | ||
1960 | |||
1961 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
1962 | return RX_DROP_UNUSABLE; | ||
1963 | |||
1964 | return RX_CONTINUE; | ||
1965 | } | ||
1966 | |||
1967 | static ieee80211_rx_result debug_noinline | ||
1912 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1968 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1913 | { | 1969 | { |
1914 | struct ieee80211_local *local = rx->local; | 1970 | struct ieee80211_local *local = rx->local; |
1915 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1971 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1916 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1972 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1917 | struct sk_buff *nskb; | ||
1918 | struct ieee80211_rx_status *status; | ||
1919 | int len = rx->skb->len; | 1973 | int len = rx->skb->len; |
1920 | 1974 | ||
1921 | if (!ieee80211_is_action(mgmt->frame_control)) | 1975 | if (!ieee80211_is_action(mgmt->frame_control)) |
@@ -1931,9 +1985,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1931 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1985 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1932 | return RX_DROP_UNUSABLE; | 1986 | return RX_DROP_UNUSABLE; |
1933 | 1987 | ||
1934 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
1935 | return RX_DROP_UNUSABLE; | ||
1936 | |||
1937 | switch (mgmt->u.action.category) { | 1988 | switch (mgmt->u.action.category) { |
1938 | case WLAN_CATEGORY_BACK: | 1989 | case WLAN_CATEGORY_BACK: |
1939 | /* | 1990 | /* |
@@ -2024,17 +2075,36 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2024 | goto queue; | 2075 | goto queue; |
2025 | } | 2076 | } |
2026 | 2077 | ||
2078 | return RX_CONTINUE; | ||
2079 | |||
2027 | invalid: | 2080 | invalid: |
2028 | /* | 2081 | rx->flags |= IEEE80211_MALFORMED_ACTION_FRM; |
2029 | * For AP mode, hostapd is responsible for handling any action | 2082 | /* will return in the next handlers */ |
2030 | * frames that we didn't handle, including returning unknown | 2083 | return RX_CONTINUE; |
2031 | * ones. For all other modes we will return them to the sender, | 2084 | |
2032 | * setting the 0x80 bit in the action category, as required by | 2085 | handled: |
2033 | * 802.11-2007 7.3.1.11. | 2086 | if (rx->sta) |
2034 | */ | 2087 | rx->sta->rx_packets++; |
2035 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 2088 | dev_kfree_skb(rx->skb); |
2036 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 2089 | return RX_QUEUED; |
2037 | return RX_DROP_MONITOR; | 2090 | |
2091 | queue: | ||
2092 | rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; | ||
2093 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
2094 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
2095 | if (rx->sta) | ||
2096 | rx->sta->rx_packets++; | ||
2097 | return RX_QUEUED; | ||
2098 | } | ||
2099 | |||
2100 | static ieee80211_rx_result debug_noinline | ||
2101 | ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | ||
2102 | { | ||
2103 | struct ieee80211_rx_status *status; | ||
2104 | |||
2105 | /* skip known-bad action frames and return them in the next handler */ | ||
2106 | if (rx->flags & IEEE80211_MALFORMED_ACTION_FRM) | ||
2107 | return RX_CONTINUE; | ||
2038 | 2108 | ||
2039 | /* | 2109 | /* |
2040 | * Getting here means the kernel doesn't know how to handle | 2110 | * Getting here means the kernel doesn't know how to handle |
@@ -2044,10 +2114,44 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2044 | */ | 2114 | */ |
2045 | status = IEEE80211_SKB_RXCB(rx->skb); | 2115 | status = IEEE80211_SKB_RXCB(rx->skb); |
2046 | 2116 | ||
2047 | if (cfg80211_rx_action(rx->sdata->dev, status->freq, | 2117 | if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, |
2048 | rx->skb->data, rx->skb->len, | 2118 | rx->skb->data, rx->skb->len, |
2049 | GFP_ATOMIC)) | 2119 | GFP_ATOMIC)) { |
2050 | goto handled; | 2120 | if (rx->sta) |
2121 | rx->sta->rx_packets++; | ||
2122 | dev_kfree_skb(rx->skb); | ||
2123 | return RX_QUEUED; | ||
2124 | } | ||
2125 | |||
2126 | |||
2127 | return RX_CONTINUE; | ||
2128 | } | ||
2129 | |||
2130 | static ieee80211_rx_result debug_noinline | ||
2131 | ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) | ||
2132 | { | ||
2133 | struct ieee80211_local *local = rx->local; | ||
2134 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
2135 | struct sk_buff *nskb; | ||
2136 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
2137 | |||
2138 | if (!ieee80211_is_action(mgmt->frame_control)) | ||
2139 | return RX_CONTINUE; | ||
2140 | |||
2141 | /* | ||
2142 | * For AP mode, hostapd is responsible for handling any action | ||
2143 | * frames that we didn't handle, including returning unknown | ||
2144 | * ones. For all other modes we will return them to the sender, | ||
2145 | * setting the 0x80 bit in the action category, as required by | ||
2146 | * 802.11-2007 7.3.1.11. | ||
2147 | * Newer versions of hostapd shall also use the management frame | ||
2148 | * registration mechanisms, but older ones still use cooked | ||
2149 | * monitor interfaces so push all frames there. | ||
2150 | */ | ||
2151 | if (!(rx->flags & IEEE80211_MALFORMED_ACTION_FRM) && | ||
2152 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
2153 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | ||
2154 | return RX_DROP_MONITOR; | ||
2051 | 2155 | ||
2052 | /* do not return rejected action frames */ | 2156 | /* do not return rejected action frames */ |
2053 | if (mgmt->u.action.category & 0x80) | 2157 | if (mgmt->u.action.category & 0x80) |
@@ -2066,20 +2170,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2066 | 2170 | ||
2067 | ieee80211_tx_skb(rx->sdata, nskb); | 2171 | ieee80211_tx_skb(rx->sdata, nskb); |
2068 | } | 2172 | } |
2069 | |||
2070 | handled: | ||
2071 | if (rx->sta) | ||
2072 | rx->sta->rx_packets++; | ||
2073 | dev_kfree_skb(rx->skb); | 2173 | dev_kfree_skb(rx->skb); |
2074 | return RX_QUEUED; | 2174 | return RX_QUEUED; |
2075 | |||
2076 | queue: | ||
2077 | rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; | ||
2078 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
2079 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
2080 | if (rx->sta) | ||
2081 | rx->sta->rx_packets++; | ||
2082 | return RX_QUEUED; | ||
2083 | } | 2175 | } |
2084 | 2176 | ||
2085 | static ieee80211_rx_result debug_noinline | 2177 | static ieee80211_rx_result debug_noinline |
@@ -2090,15 +2182,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2090 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; | 2182 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; |
2091 | __le16 stype; | 2183 | __le16 stype; |
2092 | 2184 | ||
2093 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
2094 | return RX_DROP_MONITOR; | ||
2095 | |||
2096 | if (rx->skb->len < 24) | ||
2097 | return RX_DROP_MONITOR; | ||
2098 | |||
2099 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
2100 | return RX_DROP_UNUSABLE; | ||
2101 | |||
2102 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); | 2185 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); |
2103 | if (rxs != RX_CONTINUE) | 2186 | if (rxs != RX_CONTINUE) |
2104 | return rxs; | 2187 | return rxs; |
@@ -2267,19 +2350,46 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2267 | dev_kfree_skb(skb); | 2350 | dev_kfree_skb(skb); |
2268 | } | 2351 | } |
2269 | 2352 | ||
2353 | static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | ||
2354 | ieee80211_rx_result res) | ||
2355 | { | ||
2356 | switch (res) { | ||
2357 | case RX_DROP_MONITOR: | ||
2358 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); | ||
2359 | if (rx->sta) | ||
2360 | rx->sta->rx_dropped++; | ||
2361 | /* fall through */ | ||
2362 | case RX_CONTINUE: { | ||
2363 | struct ieee80211_rate *rate = NULL; | ||
2364 | struct ieee80211_supported_band *sband; | ||
2365 | struct ieee80211_rx_status *status; | ||
2366 | |||
2367 | status = IEEE80211_SKB_RXCB((rx->skb)); | ||
2368 | |||
2369 | sband = rx->local->hw.wiphy->bands[status->band]; | ||
2370 | if (!(status->flag & RX_FLAG_HT)) | ||
2371 | rate = &sband->bitrates[status->rate_idx]; | ||
2372 | |||
2373 | ieee80211_rx_cooked_monitor(rx, rate); | ||
2374 | break; | ||
2375 | } | ||
2376 | case RX_DROP_UNUSABLE: | ||
2377 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); | ||
2378 | if (rx->sta) | ||
2379 | rx->sta->rx_dropped++; | ||
2380 | dev_kfree_skb(rx->skb); | ||
2381 | break; | ||
2382 | case RX_QUEUED: | ||
2383 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued); | ||
2384 | break; | ||
2385 | } | ||
2386 | } | ||
2270 | 2387 | ||
2271 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | 2388 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, |
2272 | struct ieee80211_rx_data *rx, | 2389 | struct sk_buff_head *frames) |
2273 | struct sk_buff *skb, | ||
2274 | struct ieee80211_rate *rate) | ||
2275 | { | 2390 | { |
2276 | struct sk_buff_head reorder_release; | ||
2277 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2391 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2278 | 2392 | struct sk_buff *skb; | |
2279 | __skb_queue_head_init(&reorder_release); | ||
2280 | |||
2281 | rx->skb = skb; | ||
2282 | rx->sdata = sdata; | ||
2283 | 2393 | ||
2284 | #define CALL_RXH(rxh) \ | 2394 | #define CALL_RXH(rxh) \ |
2285 | do { \ | 2395 | do { \ |
@@ -2288,17 +2398,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
2288 | goto rxh_next; \ | 2398 | goto rxh_next; \ |
2289 | } while (0); | 2399 | } while (0); |
2290 | 2400 | ||
2291 | /* | 2401 | while ((skb = __skb_dequeue(frames))) { |
2292 | * NB: the rxh_next label works even if we jump | ||
2293 | * to it from here because then the list will | ||
2294 | * be empty, which is a trivial check | ||
2295 | */ | ||
2296 | CALL_RXH(ieee80211_rx_h_passive_scan) | ||
2297 | CALL_RXH(ieee80211_rx_h_check) | ||
2298 | |||
2299 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); | ||
2300 | |||
2301 | while ((skb = __skb_dequeue(&reorder_release))) { | ||
2302 | /* | 2402 | /* |
2303 | * all the other fields are valid across frames | 2403 | * all the other fields are valid across frames |
2304 | * that belong to an aMPDU since they are on the | 2404 | * that belong to an aMPDU since they are on the |
@@ -2316,42 +2416,91 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
2316 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | 2416 | CALL_RXH(ieee80211_rx_h_remove_qos_control) |
2317 | CALL_RXH(ieee80211_rx_h_amsdu) | 2417 | CALL_RXH(ieee80211_rx_h_amsdu) |
2318 | #ifdef CONFIG_MAC80211_MESH | 2418 | #ifdef CONFIG_MAC80211_MESH |
2319 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2419 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) |
2320 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 2420 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
2321 | #endif | 2421 | #endif |
2322 | CALL_RXH(ieee80211_rx_h_data) | 2422 | CALL_RXH(ieee80211_rx_h_data) |
2323 | 2423 | ||
2324 | /* special treatment -- needs the queue */ | 2424 | /* special treatment -- needs the queue */ |
2325 | res = ieee80211_rx_h_ctrl(rx, &reorder_release); | 2425 | res = ieee80211_rx_h_ctrl(rx, frames); |
2326 | if (res != RX_CONTINUE) | 2426 | if (res != RX_CONTINUE) |
2327 | goto rxh_next; | 2427 | goto rxh_next; |
2328 | 2428 | ||
2429 | CALL_RXH(ieee80211_rx_h_mgmt_check) | ||
2329 | CALL_RXH(ieee80211_rx_h_action) | 2430 | CALL_RXH(ieee80211_rx_h_action) |
2431 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) | ||
2432 | CALL_RXH(ieee80211_rx_h_action_return) | ||
2330 | CALL_RXH(ieee80211_rx_h_mgmt) | 2433 | CALL_RXH(ieee80211_rx_h_mgmt) |
2331 | 2434 | ||
2435 | rxh_next: | ||
2436 | ieee80211_rx_handlers_result(rx, res); | ||
2437 | |||
2332 | #undef CALL_RXH | 2438 | #undef CALL_RXH |
2439 | } | ||
2440 | } | ||
2441 | |||
2442 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | ||
2443 | struct ieee80211_rx_data *rx, | ||
2444 | struct sk_buff *skb) | ||
2445 | { | ||
2446 | struct sk_buff_head reorder_release; | ||
2447 | ieee80211_rx_result res = RX_DROP_MONITOR; | ||
2448 | |||
2449 | __skb_queue_head_init(&reorder_release); | ||
2450 | |||
2451 | rx->skb = skb; | ||
2452 | rx->sdata = sdata; | ||
2453 | |||
2454 | #define CALL_RXH(rxh) \ | ||
2455 | do { \ | ||
2456 | res = rxh(rx); \ | ||
2457 | if (res != RX_CONTINUE) \ | ||
2458 | goto rxh_next; \ | ||
2459 | } while (0); | ||
2460 | |||
2461 | CALL_RXH(ieee80211_rx_h_passive_scan) | ||
2462 | CALL_RXH(ieee80211_rx_h_check) | ||
2463 | |||
2464 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); | ||
2465 | |||
2466 | ieee80211_rx_handlers(rx, &reorder_release); | ||
2467 | return; | ||
2333 | 2468 | ||
2334 | rxh_next: | 2469 | rxh_next: |
2335 | switch (res) { | 2470 | ieee80211_rx_handlers_result(rx, res); |
2336 | case RX_DROP_MONITOR: | 2471 | |
2337 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 2472 | #undef CALL_RXH |
2338 | if (rx->sta) | 2473 | } |
2339 | rx->sta->rx_dropped++; | 2474 | |
2340 | /* fall through */ | 2475 | /* |
2341 | case RX_CONTINUE: | 2476 | * This function makes calls into the RX path. Therefore the |
2342 | ieee80211_rx_cooked_monitor(rx, rate); | 2477 | * caller must hold the sta_info->lock and everything has to |
2343 | break; | 2478 | * be under rcu_read_lock protection as well. |
2344 | case RX_DROP_UNUSABLE: | 2479 | */ |
2345 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 2480 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2346 | if (rx->sta) | 2481 | { |
2347 | rx->sta->rx_dropped++; | 2482 | struct sk_buff_head frames; |
2348 | dev_kfree_skb(rx->skb); | 2483 | struct ieee80211_rx_data rx = { }; |
2349 | break; | 2484 | |
2350 | case RX_QUEUED: | 2485 | __skb_queue_head_init(&frames); |
2351 | I802_DEBUG_INC(sdata->local->rx_handlers_queued); | 2486 | |
2352 | break; | 2487 | /* construct rx struct */ |
2353 | } | 2488 | rx.sta = sta; |
2354 | } | 2489 | rx.sdata = sta->sdata; |
2490 | rx.local = sta->local; | ||
2491 | rx.queue = tid; | ||
2492 | rx.flags |= IEEE80211_RX_RA_MATCH; | ||
2493 | |||
2494 | if (unlikely(test_bit(SCAN_HW_SCANNING, &sta->local->scanning) || | ||
2495 | test_bit(SCAN_OFF_CHANNEL, &sta->local->scanning))) | ||
2496 | rx.flags |= IEEE80211_RX_IN_SCAN; | ||
2497 | |||
2498 | spin_lock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock); | ||
2499 | ieee80211_sta_reorder_release(&sta->local->hw, | ||
2500 | sta->ampdu_mlme.tid_rx[tid], &frames); | ||
2501 | spin_unlock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock); | ||
2502 | |||
2503 | ieee80211_rx_handlers(&rx, &frames); | ||
2355 | } | 2504 | } |
2356 | 2505 | ||
2357 | /* main receive path */ | 2506 | /* main receive path */ |
@@ -2433,7 +2582,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2433 | break; | 2582 | break; |
2434 | case NL80211_IFTYPE_MONITOR: | 2583 | case NL80211_IFTYPE_MONITOR: |
2435 | case NL80211_IFTYPE_UNSPECIFIED: | 2584 | case NL80211_IFTYPE_UNSPECIFIED: |
2436 | case __NL80211_IFTYPE_AFTER_LAST: | 2585 | case NUM_NL80211_IFTYPES: |
2437 | /* should never get here */ | 2586 | /* should never get here */ |
2438 | WARN_ON(1); | 2587 | WARN_ON(1); |
2439 | break; | 2588 | break; |
@@ -2447,8 +2596,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2447 | * be called with rcu_read_lock protection. | 2596 | * be called with rcu_read_lock protection. |
2448 | */ | 2597 | */ |
2449 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | 2598 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
2450 | struct sk_buff *skb, | 2599 | struct sk_buff *skb) |
2451 | struct ieee80211_rate *rate) | ||
2452 | { | 2600 | { |
2453 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 2601 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
2454 | struct ieee80211_local *local = hw_to_local(hw); | 2602 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -2556,7 +2704,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2556 | prev->name); | 2704 | prev->name); |
2557 | goto next; | 2705 | goto next; |
2558 | } | 2706 | } |
2559 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | 2707 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); |
2560 | next: | 2708 | next: |
2561 | prev = sdata; | 2709 | prev = sdata; |
2562 | } | 2710 | } |
@@ -2572,7 +2720,7 @@ next: | |||
2572 | } | 2720 | } |
2573 | } | 2721 | } |
2574 | if (prev) | 2722 | if (prev) |
2575 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); | 2723 | ieee80211_invoke_rx_handlers(prev, &rx, skb); |
2576 | else | 2724 | else |
2577 | dev_kfree_skb(skb); | 2725 | dev_kfree_skb(skb); |
2578 | } | 2726 | } |
@@ -2615,28 +2763,37 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2615 | if (WARN_ON(!local->started)) | 2763 | if (WARN_ON(!local->started)) |
2616 | goto drop; | 2764 | goto drop; |
2617 | 2765 | ||
2618 | if (status->flag & RX_FLAG_HT) { | 2766 | if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { |
2619 | /* | 2767 | /* |
2620 | * rate_idx is MCS index, which can be [0-76] as documented on: | 2768 | * Validate the rate, unless a PLCP error means that |
2621 | * | 2769 | * we probably can't have a valid rate here anyway. |
2622 | * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n | ||
2623 | * | ||
2624 | * Anything else would be some sort of driver or hardware error. | ||
2625 | * The driver should catch hardware errors. | ||
2626 | */ | 2770 | */ |
2627 | if (WARN((status->rate_idx < 0 || | 2771 | |
2628 | status->rate_idx > 76), | 2772 | if (status->flag & RX_FLAG_HT) { |
2629 | "Rate marked as an HT rate but passed " | 2773 | /* |
2630 | "status->rate_idx is not " | 2774 | * rate_idx is MCS index, which can be [0-76] |
2631 | "an MCS index [0-76]: %d (0x%02x)\n", | 2775 | * as documented on: |
2632 | status->rate_idx, | 2776 | * |
2633 | status->rate_idx)) | 2777 | * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n |
2634 | goto drop; | 2778 | * |
2635 | } else { | 2779 | * Anything else would be some sort of driver or |
2636 | if (WARN_ON(status->rate_idx < 0 || | 2780 | * hardware error. The driver should catch hardware |
2637 | status->rate_idx >= sband->n_bitrates)) | 2781 | * errors. |
2638 | goto drop; | 2782 | */ |
2639 | rate = &sband->bitrates[status->rate_idx]; | 2783 | if (WARN((status->rate_idx < 0 || |
2784 | status->rate_idx > 76), | ||
2785 | "Rate marked as an HT rate but passed " | ||
2786 | "status->rate_idx is not " | ||
2787 | "an MCS index [0-76]: %d (0x%02x)\n", | ||
2788 | status->rate_idx, | ||
2789 | status->rate_idx)) | ||
2790 | goto drop; | ||
2791 | } else { | ||
2792 | if (WARN_ON(status->rate_idx < 0 || | ||
2793 | status->rate_idx >= sband->n_bitrates)) | ||
2794 | goto drop; | ||
2795 | rate = &sband->bitrates[status->rate_idx]; | ||
2796 | } | ||
2640 | } | 2797 | } |
2641 | 2798 | ||
2642 | /* | 2799 | /* |
@@ -2658,7 +2815,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2658 | return; | 2815 | return; |
2659 | } | 2816 | } |
2660 | 2817 | ||
2661 | __ieee80211_rx_handle_packet(hw, skb, rate); | 2818 | __ieee80211_rx_handle_packet(hw, skb); |
2662 | 2819 | ||
2663 | rcu_read_unlock(); | 2820 | rcu_read_unlock(); |
2664 | 2821 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 872d7b6ef6b3..31f233f7f51a 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -255,7 +255,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
255 | 255 | ||
256 | trace_api_scan_completed(local, aborted); | 256 | trace_api_scan_completed(local, aborted); |
257 | 257 | ||
258 | mutex_lock(&local->scan_mtx); | 258 | mutex_lock(&local->mtx); |
259 | 259 | ||
260 | /* | 260 | /* |
261 | * It's ok to abort a not-yet-running scan (that | 261 | * It's ok to abort a not-yet-running scan (that |
@@ -267,7 +267,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
267 | aborted = true; | 267 | aborted = true; |
268 | 268 | ||
269 | if (WARN_ON(!local->scan_req)) { | 269 | if (WARN_ON(!local->scan_req)) { |
270 | mutex_unlock(&local->scan_mtx); | 270 | mutex_unlock(&local->mtx); |
271 | return; | 271 | return; |
272 | } | 272 | } |
273 | 273 | ||
@@ -275,7 +275,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
275 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 275 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { |
276 | ieee80211_queue_delayed_work(&local->hw, | 276 | ieee80211_queue_delayed_work(&local->hw, |
277 | &local->scan_work, 0); | 277 | &local->scan_work, 0); |
278 | mutex_unlock(&local->scan_mtx); | 278 | mutex_unlock(&local->mtx); |
279 | return; | 279 | return; |
280 | } | 280 | } |
281 | 281 | ||
@@ -291,7 +291,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
291 | local->scan_channel = NULL; | 291 | local->scan_channel = NULL; |
292 | 292 | ||
293 | /* we only have to protect scan_req and hw/sw scan */ | 293 | /* we only have to protect scan_req and hw/sw scan */ |
294 | mutex_unlock(&local->scan_mtx); | 294 | mutex_unlock(&local->mtx); |
295 | 295 | ||
296 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 296 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
297 | if (was_hw_scan) | 297 | if (was_hw_scan) |
@@ -304,7 +304,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
304 | ieee80211_offchannel_return(local, true); | 304 | ieee80211_offchannel_return(local, true); |
305 | 305 | ||
306 | done: | 306 | done: |
307 | mutex_lock(&local->mtx); | ||
307 | ieee80211_recalc_idle(local); | 308 | ieee80211_recalc_idle(local); |
309 | mutex_unlock(&local->mtx); | ||
308 | ieee80211_mlme_notify_scan_completed(local); | 310 | ieee80211_mlme_notify_scan_completed(local); |
309 | ieee80211_ibss_notify_scan_completed(local); | 311 | ieee80211_ibss_notify_scan_completed(local); |
310 | ieee80211_mesh_notify_scan_completed(local); | 312 | ieee80211_mesh_notify_scan_completed(local); |
@@ -639,15 +641,15 @@ void ieee80211_scan_work(struct work_struct *work) | |||
639 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 641 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
640 | unsigned long next_delay = 0; | 642 | unsigned long next_delay = 0; |
641 | 643 | ||
642 | mutex_lock(&local->scan_mtx); | 644 | mutex_lock(&local->mtx); |
643 | if (!sdata || !local->scan_req) { | 645 | if (!sdata || !local->scan_req) { |
644 | mutex_unlock(&local->scan_mtx); | 646 | mutex_unlock(&local->mtx); |
645 | return; | 647 | return; |
646 | } | 648 | } |
647 | 649 | ||
648 | if (local->hw_scan_req) { | 650 | if (local->hw_scan_req) { |
649 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); | 651 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); |
650 | mutex_unlock(&local->scan_mtx); | 652 | mutex_unlock(&local->mtx); |
651 | if (rc) | 653 | if (rc) |
652 | ieee80211_scan_completed(&local->hw, true); | 654 | ieee80211_scan_completed(&local->hw, true); |
653 | return; | 655 | return; |
@@ -661,14 +663,14 @@ void ieee80211_scan_work(struct work_struct *work) | |||
661 | local->scan_sdata = NULL; | 663 | local->scan_sdata = NULL; |
662 | 664 | ||
663 | rc = __ieee80211_start_scan(sdata, req); | 665 | rc = __ieee80211_start_scan(sdata, req); |
664 | mutex_unlock(&local->scan_mtx); | 666 | mutex_unlock(&local->mtx); |
665 | 667 | ||
666 | if (rc) | 668 | if (rc) |
667 | ieee80211_scan_completed(&local->hw, true); | 669 | ieee80211_scan_completed(&local->hw, true); |
668 | return; | 670 | return; |
669 | } | 671 | } |
670 | 672 | ||
671 | mutex_unlock(&local->scan_mtx); | 673 | mutex_unlock(&local->mtx); |
672 | 674 | ||
673 | /* | 675 | /* |
674 | * Avoid re-scheduling when the sdata is going away. | 676 | * Avoid re-scheduling when the sdata is going away. |
@@ -711,9 +713,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
711 | { | 713 | { |
712 | int res; | 714 | int res; |
713 | 715 | ||
714 | mutex_lock(&sdata->local->scan_mtx); | 716 | mutex_lock(&sdata->local->mtx); |
715 | res = __ieee80211_start_scan(sdata, req); | 717 | res = __ieee80211_start_scan(sdata, req); |
716 | mutex_unlock(&sdata->local->scan_mtx); | 718 | mutex_unlock(&sdata->local->mtx); |
717 | 719 | ||
718 | return res; | 720 | return res; |
719 | } | 721 | } |
@@ -726,7 +728,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
726 | int ret = -EBUSY; | 728 | int ret = -EBUSY; |
727 | enum ieee80211_band band; | 729 | enum ieee80211_band band; |
728 | 730 | ||
729 | mutex_lock(&local->scan_mtx); | 731 | mutex_lock(&local->mtx); |
730 | 732 | ||
731 | /* busy scanning */ | 733 | /* busy scanning */ |
732 | if (local->scan_req) | 734 | if (local->scan_req) |
@@ -761,7 +763,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
761 | 763 | ||
762 | ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); | 764 | ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); |
763 | unlock: | 765 | unlock: |
764 | mutex_unlock(&local->scan_mtx); | 766 | mutex_unlock(&local->mtx); |
765 | return ret; | 767 | return ret; |
766 | } | 768 | } |
767 | 769 | ||
@@ -775,10 +777,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
775 | * Only call this function when a scan can't be | 777 | * Only call this function when a scan can't be |
776 | * queued -- mostly at suspend under RTNL. | 778 | * queued -- mostly at suspend under RTNL. |
777 | */ | 779 | */ |
778 | mutex_lock(&local->scan_mtx); | 780 | mutex_lock(&local->mtx); |
779 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || | 781 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || |
780 | (!local->scanning && local->scan_req); | 782 | (!local->scanning && local->scan_req); |
781 | mutex_unlock(&local->scan_mtx); | 783 | mutex_unlock(&local->mtx); |
782 | 784 | ||
783 | if (abortscan) | 785 | if (abortscan) |
784 | ieee80211_scan_completed(&local->hw, true); | 786 | ieee80211_scan_completed(&local->hw, true); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 54262e72376d..810c5ce98316 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -103,6 +103,7 @@ struct tid_ampdu_tx { | |||
103 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs | 103 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs |
104 | * @reorder_time: jiffies when skb was added | 104 | * @reorder_time: jiffies when skb was added |
105 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | 105 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) |
106 | * @reorder_timer: releases expired frames from the reorder buffer. | ||
106 | * @head_seq_num: head sequence number in reordering buffer. | 107 | * @head_seq_num: head sequence number in reordering buffer. |
107 | * @stored_mpdu_num: number of MPDUs in reordering buffer | 108 | * @stored_mpdu_num: number of MPDUs in reordering buffer |
108 | * @ssn: Starting Sequence Number expected to be aggregated. | 109 | * @ssn: Starting Sequence Number expected to be aggregated. |
@@ -110,20 +111,25 @@ struct tid_ampdu_tx { | |||
110 | * @timeout: reset timer value (in TUs). | 111 | * @timeout: reset timer value (in TUs). |
111 | * @dialog_token: dialog token for aggregation session | 112 | * @dialog_token: dialog token for aggregation session |
112 | * @rcu_head: RCU head used for freeing this struct | 113 | * @rcu_head: RCU head used for freeing this struct |
114 | * @reorder_lock: serializes access to reorder buffer, see below. | ||
113 | * | 115 | * |
114 | * This structure is protected by RCU and the per-station | 116 | * This structure is protected by RCU and the per-station |
115 | * spinlock. Assignments to the array holding it must hold | 117 | * spinlock. Assignments to the array holding it must hold |
116 | * the spinlock, only the RX path can access it under RCU | 118 | * the spinlock. |
117 | * lock-free. The RX path, since it is single-threaded, | 119 | * |
118 | * can even modify the structure without locking since the | 120 | * The @reorder_lock is used to protect the variables and |
119 | * only other modifications to it are done when the struct | 121 | * arrays such as @reorder_buf, @reorder_time, @head_seq_num, |
120 | * can not yet or no longer be found by the RX path. | 122 | * @stored_mpdu_num and @reorder_time from being corrupted by |
123 | * concurrent access of the RX path and the expired frame | ||
124 | * release timer. | ||
121 | */ | 125 | */ |
122 | struct tid_ampdu_rx { | 126 | struct tid_ampdu_rx { |
123 | struct rcu_head rcu_head; | 127 | struct rcu_head rcu_head; |
128 | spinlock_t reorder_lock; | ||
124 | struct sk_buff **reorder_buf; | 129 | struct sk_buff **reorder_buf; |
125 | unsigned long *reorder_time; | 130 | unsigned long *reorder_time; |
126 | struct timer_list session_timer; | 131 | struct timer_list session_timer; |
132 | struct timer_list reorder_timer; | ||
127 | u16 head_seq_num; | 133 | u16 head_seq_num; |
128 | u16 stored_mpdu_num; | 134 | u16 stored_mpdu_num; |
129 | u16 ssn; | 135 | u16 ssn; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 10caec5ea8fa..67a35841bef0 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -296,7 +296,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
296 | } | 296 | } |
297 | 297 | ||
298 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) | 298 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) |
299 | cfg80211_action_tx_status( | 299 | cfg80211_mgmt_tx_status( |
300 | skb->dev, (unsigned long) skb, skb->data, skb->len, | 300 | skb->dev, (unsigned long) skb, skb->data, skb->len, |
301 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | 301 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); |
302 | 302 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c54db966926b..bc4fefc91663 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -543,15 +543,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
543 | tx->key->tx_rx_count++; | 543 | tx->key->tx_rx_count++; |
544 | /* TODO: add threshold stuff again */ | 544 | /* TODO: add threshold stuff again */ |
545 | 545 | ||
546 | switch (tx->key->conf.alg) { | 546 | switch (tx->key->conf.cipher) { |
547 | case ALG_WEP: | 547 | case WLAN_CIPHER_SUITE_WEP40: |
548 | case WLAN_CIPHER_SUITE_WEP104: | ||
548 | if (ieee80211_is_auth(hdr->frame_control)) | 549 | if (ieee80211_is_auth(hdr->frame_control)) |
549 | break; | 550 | break; |
550 | case ALG_TKIP: | 551 | case WLAN_CIPHER_SUITE_TKIP: |
551 | if (!ieee80211_is_data_present(hdr->frame_control)) | 552 | if (!ieee80211_is_data_present(hdr->frame_control)) |
552 | tx->key = NULL; | 553 | tx->key = NULL; |
553 | break; | 554 | break; |
554 | case ALG_CCMP: | 555 | case WLAN_CIPHER_SUITE_CCMP: |
555 | if (!ieee80211_is_data_present(hdr->frame_control) && | 556 | if (!ieee80211_is_data_present(hdr->frame_control) && |
556 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, | 557 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, |
557 | tx->skb)) | 558 | tx->skb)) |
@@ -561,7 +562,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
561 | IEEE80211_KEY_FLAG_SW_MGMT) && | 562 | IEEE80211_KEY_FLAG_SW_MGMT) && |
562 | ieee80211_is_mgmt(hdr->frame_control); | 563 | ieee80211_is_mgmt(hdr->frame_control); |
563 | break; | 564 | break; |
564 | case ALG_AES_CMAC: | 565 | case WLAN_CIPHER_SUITE_AES_CMAC: |
565 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 566 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
566 | tx->key = NULL; | 567 | tx->key = NULL; |
567 | break; | 568 | break; |
@@ -949,14 +950,15 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | |||
949 | if (!tx->key) | 950 | if (!tx->key) |
950 | return TX_CONTINUE; | 951 | return TX_CONTINUE; |
951 | 952 | ||
952 | switch (tx->key->conf.alg) { | 953 | switch (tx->key->conf.cipher) { |
953 | case ALG_WEP: | 954 | case WLAN_CIPHER_SUITE_WEP40: |
955 | case WLAN_CIPHER_SUITE_WEP104: | ||
954 | return ieee80211_crypto_wep_encrypt(tx); | 956 | return ieee80211_crypto_wep_encrypt(tx); |
955 | case ALG_TKIP: | 957 | case WLAN_CIPHER_SUITE_TKIP: |
956 | return ieee80211_crypto_tkip_encrypt(tx); | 958 | return ieee80211_crypto_tkip_encrypt(tx); |
957 | case ALG_CCMP: | 959 | case WLAN_CIPHER_SUITE_CCMP: |
958 | return ieee80211_crypto_ccmp_encrypt(tx); | 960 | return ieee80211_crypto_ccmp_encrypt(tx); |
959 | case ALG_AES_CMAC: | 961 | case WLAN_CIPHER_SUITE_AES_CMAC: |
960 | return ieee80211_crypto_aes_cmac_encrypt(tx); | 962 | return ieee80211_crypto_aes_cmac_encrypt(tx); |
961 | } | 963 | } |
962 | 964 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 748387d45bc0..cd2b485fed4f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -471,7 +471,7 @@ void ieee80211_iterate_active_interfaces( | |||
471 | 471 | ||
472 | list_for_each_entry(sdata, &local->interfaces, list) { | 472 | list_for_each_entry(sdata, &local->interfaces, list) { |
473 | switch (sdata->vif.type) { | 473 | switch (sdata->vif.type) { |
474 | case __NL80211_IFTYPE_AFTER_LAST: | 474 | case NUM_NL80211_IFTYPES: |
475 | case NL80211_IFTYPE_UNSPECIFIED: | 475 | case NL80211_IFTYPE_UNSPECIFIED: |
476 | case NL80211_IFTYPE_MONITOR: | 476 | case NL80211_IFTYPE_MONITOR: |
477 | case NL80211_IFTYPE_AP_VLAN: | 477 | case NL80211_IFTYPE_AP_VLAN: |
@@ -505,7 +505,7 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
505 | 505 | ||
506 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 506 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
507 | switch (sdata->vif.type) { | 507 | switch (sdata->vif.type) { |
508 | case __NL80211_IFTYPE_AFTER_LAST: | 508 | case NUM_NL80211_IFTYPES: |
509 | case NL80211_IFTYPE_UNSPECIFIED: | 509 | case NL80211_IFTYPE_UNSPECIFIED: |
510 | case NL80211_IFTYPE_MONITOR: | 510 | case NL80211_IFTYPE_MONITOR: |
511 | case NL80211_IFTYPE_AP_VLAN: | 511 | case NL80211_IFTYPE_AP_VLAN: |
@@ -1189,7 +1189,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1189 | /* ignore virtual */ | 1189 | /* ignore virtual */ |
1190 | break; | 1190 | break; |
1191 | case NL80211_IFTYPE_UNSPECIFIED: | 1191 | case NL80211_IFTYPE_UNSPECIFIED: |
1192 | case __NL80211_IFTYPE_AFTER_LAST: | 1192 | case NUM_NL80211_IFTYPES: |
1193 | WARN_ON(1); | 1193 | WARN_ON(1); |
1194 | break; | 1194 | break; |
1195 | } | 1195 | } |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 9ebc8d8a1f5b..f27484c22b9f 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -240,7 +240,7 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, | |||
240 | 240 | ||
241 | keyidx = skb->data[hdrlen + 3] >> 6; | 241 | keyidx = skb->data[hdrlen + 3] >> 6; |
242 | 242 | ||
243 | if (!key || keyidx != key->conf.keyidx || key->conf.alg != ALG_WEP) | 243 | if (!key || keyidx != key->conf.keyidx) |
244 | return -1; | 244 | return -1; |
245 | 245 | ||
246 | klen = 3 + key->conf.keylen; | 246 | klen = 3 + key->conf.keylen; |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 81d4ad64184a..ae344d1ba056 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -43,7 +43,7 @@ enum work_action { | |||
43 | /* utils */ | 43 | /* utils */ |
44 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) | 44 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) |
45 | { | 45 | { |
46 | WARN_ON(!mutex_is_locked(&local->work_mtx)); | 46 | lockdep_assert_held(&local->mtx); |
47 | } | 47 | } |
48 | 48 | ||
49 | /* | 49 | /* |
@@ -757,7 +757,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
757 | mgmt = (struct ieee80211_mgmt *) skb->data; | 757 | mgmt = (struct ieee80211_mgmt *) skb->data; |
758 | fc = le16_to_cpu(mgmt->frame_control); | 758 | fc = le16_to_cpu(mgmt->frame_control); |
759 | 759 | ||
760 | mutex_lock(&local->work_mtx); | 760 | mutex_lock(&local->mtx); |
761 | 761 | ||
762 | list_for_each_entry(wk, &local->work_list, list) { | 762 | list_for_each_entry(wk, &local->work_list, list) { |
763 | const u8 *bssid = NULL; | 763 | const u8 *bssid = NULL; |
@@ -833,7 +833,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
833 | WARN(1, "unexpected: %d", rma); | 833 | WARN(1, "unexpected: %d", rma); |
834 | } | 834 | } |
835 | 835 | ||
836 | mutex_unlock(&local->work_mtx); | 836 | mutex_unlock(&local->mtx); |
837 | 837 | ||
838 | if (rma != WORK_ACT_DONE) | 838 | if (rma != WORK_ACT_DONE) |
839 | goto out; | 839 | goto out; |
@@ -845,9 +845,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
845 | case WORK_DONE_REQUEUE: | 845 | case WORK_DONE_REQUEUE: |
846 | synchronize_rcu(); | 846 | synchronize_rcu(); |
847 | wk->started = false; /* restart */ | 847 | wk->started = false; /* restart */ |
848 | mutex_lock(&local->work_mtx); | 848 | mutex_lock(&local->mtx); |
849 | list_add_tail(&wk->list, &local->work_list); | 849 | list_add_tail(&wk->list, &local->work_list); |
850 | mutex_unlock(&local->work_mtx); | 850 | mutex_unlock(&local->mtx); |
851 | } | 851 | } |
852 | 852 | ||
853 | out: | 853 | out: |
@@ -888,9 +888,9 @@ static void ieee80211_work_work(struct work_struct *work) | |||
888 | while ((skb = skb_dequeue(&local->work_skb_queue))) | 888 | while ((skb = skb_dequeue(&local->work_skb_queue))) |
889 | ieee80211_work_rx_queued_mgmt(local, skb); | 889 | ieee80211_work_rx_queued_mgmt(local, skb); |
890 | 890 | ||
891 | ieee80211_recalc_idle(local); | 891 | mutex_lock(&local->mtx); |
892 | 892 | ||
893 | mutex_lock(&local->work_mtx); | 893 | ieee80211_recalc_idle(local); |
894 | 894 | ||
895 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | 895 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { |
896 | bool started = wk->started; | 896 | bool started = wk->started; |
@@ -995,20 +995,16 @@ static void ieee80211_work_work(struct work_struct *work) | |||
995 | run_again(local, jiffies + HZ/2); | 995 | run_again(local, jiffies + HZ/2); |
996 | } | 996 | } |
997 | 997 | ||
998 | mutex_lock(&local->scan_mtx); | ||
999 | |||
1000 | if (list_empty(&local->work_list) && local->scan_req && | 998 | if (list_empty(&local->work_list) && local->scan_req && |
1001 | !local->scanning) | 999 | !local->scanning) |
1002 | ieee80211_queue_delayed_work(&local->hw, | 1000 | ieee80211_queue_delayed_work(&local->hw, |
1003 | &local->scan_work, | 1001 | &local->scan_work, |
1004 | round_jiffies_relative(0)); | 1002 | round_jiffies_relative(0)); |
1005 | 1003 | ||
1006 | mutex_unlock(&local->scan_mtx); | ||
1007 | |||
1008 | mutex_unlock(&local->work_mtx); | ||
1009 | |||
1010 | ieee80211_recalc_idle(local); | 1004 | ieee80211_recalc_idle(local); |
1011 | 1005 | ||
1006 | mutex_unlock(&local->mtx); | ||
1007 | |||
1012 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | 1008 | list_for_each_entry_safe(wk, tmp, &free_work, list) { |
1013 | wk->done(wk, NULL); | 1009 | wk->done(wk, NULL); |
1014 | list_del(&wk->list); | 1010 | list_del(&wk->list); |
@@ -1035,16 +1031,15 @@ void ieee80211_add_work(struct ieee80211_work *wk) | |||
1035 | wk->started = false; | 1031 | wk->started = false; |
1036 | 1032 | ||
1037 | local = wk->sdata->local; | 1033 | local = wk->sdata->local; |
1038 | mutex_lock(&local->work_mtx); | 1034 | mutex_lock(&local->mtx); |
1039 | list_add_tail(&wk->list, &local->work_list); | 1035 | list_add_tail(&wk->list, &local->work_list); |
1040 | mutex_unlock(&local->work_mtx); | 1036 | mutex_unlock(&local->mtx); |
1041 | 1037 | ||
1042 | ieee80211_queue_work(&local->hw, &local->work_work); | 1038 | ieee80211_queue_work(&local->hw, &local->work_work); |
1043 | } | 1039 | } |
1044 | 1040 | ||
1045 | void ieee80211_work_init(struct ieee80211_local *local) | 1041 | void ieee80211_work_init(struct ieee80211_local *local) |
1046 | { | 1042 | { |
1047 | mutex_init(&local->work_mtx); | ||
1048 | INIT_LIST_HEAD(&local->work_list); | 1043 | INIT_LIST_HEAD(&local->work_list); |
1049 | setup_timer(&local->work_timer, ieee80211_work_timer, | 1044 | setup_timer(&local->work_timer, ieee80211_work_timer, |
1050 | (unsigned long)local); | 1045 | (unsigned long)local); |
@@ -1057,7 +1052,7 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1057 | struct ieee80211_local *local = sdata->local; | 1052 | struct ieee80211_local *local = sdata->local; |
1058 | struct ieee80211_work *wk; | 1053 | struct ieee80211_work *wk; |
1059 | 1054 | ||
1060 | mutex_lock(&local->work_mtx); | 1055 | mutex_lock(&local->mtx); |
1061 | list_for_each_entry(wk, &local->work_list, list) { | 1056 | list_for_each_entry(wk, &local->work_list, list) { |
1062 | if (wk->sdata != sdata) | 1057 | if (wk->sdata != sdata) |
1063 | continue; | 1058 | continue; |
@@ -1065,19 +1060,19 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1065 | wk->started = true; | 1060 | wk->started = true; |
1066 | wk->timeout = jiffies; | 1061 | wk->timeout = jiffies; |
1067 | } | 1062 | } |
1068 | mutex_unlock(&local->work_mtx); | 1063 | mutex_unlock(&local->mtx); |
1069 | 1064 | ||
1070 | /* run cleanups etc. */ | 1065 | /* run cleanups etc. */ |
1071 | ieee80211_work_work(&local->work_work); | 1066 | ieee80211_work_work(&local->work_work); |
1072 | 1067 | ||
1073 | mutex_lock(&local->work_mtx); | 1068 | mutex_lock(&local->mtx); |
1074 | list_for_each_entry(wk, &local->work_list, list) { | 1069 | list_for_each_entry(wk, &local->work_list, list) { |
1075 | if (wk->sdata != sdata) | 1070 | if (wk->sdata != sdata) |
1076 | continue; | 1071 | continue; |
1077 | WARN_ON(1); | 1072 | WARN_ON(1); |
1078 | break; | 1073 | break; |
1079 | } | 1074 | } |
1080 | mutex_unlock(&local->work_mtx); | 1075 | mutex_unlock(&local->mtx); |
1081 | } | 1076 | } |
1082 | 1077 | ||
1083 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | 1078 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, |
@@ -1163,7 +1158,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | |||
1163 | struct ieee80211_work *wk, *tmp; | 1158 | struct ieee80211_work *wk, *tmp; |
1164 | bool found = false; | 1159 | bool found = false; |
1165 | 1160 | ||
1166 | mutex_lock(&local->work_mtx); | 1161 | mutex_lock(&local->mtx); |
1167 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | 1162 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { |
1168 | if ((unsigned long) wk == cookie) { | 1163 | if ((unsigned long) wk == cookie) { |
1169 | wk->timeout = jiffies; | 1164 | wk->timeout = jiffies; |
@@ -1171,7 +1166,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | |||
1171 | break; | 1166 | break; |
1172 | } | 1167 | } |
1173 | } | 1168 | } |
1174 | mutex_unlock(&local->work_mtx); | 1169 | mutex_unlock(&local->mtx); |
1175 | 1170 | ||
1176 | if (!found) | 1171 | if (!found) |
1177 | return -ENOENT; | 1172 | return -ENOENT; |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 8d59d27d887e..43882b36da55 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -36,8 +36,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
36 | int tail; | 36 | int tail; |
37 | 37 | ||
38 | hdr = (struct ieee80211_hdr *)skb->data; | 38 | hdr = (struct ieee80211_hdr *)skb->data; |
39 | if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 || | 39 | if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || |
40 | !ieee80211_is_data_present(hdr->frame_control)) | 40 | skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control)) |
41 | return TX_CONTINUE; | 41 | return TX_CONTINUE; |
42 | 42 | ||
43 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 43 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -94,7 +94,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
94 | if (status->flag & RX_FLAG_MMIC_STRIPPED) | 94 | if (status->flag & RX_FLAG_MMIC_STRIPPED) |
95 | return RX_CONTINUE; | 95 | return RX_CONTINUE; |
96 | 96 | ||
97 | if (!rx->key || rx->key->conf.alg != ALG_TKIP || | 97 | if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || |
98 | !ieee80211_has_protected(hdr->frame_control) || | 98 | !ieee80211_has_protected(hdr->frame_control) || |
99 | !ieee80211_is_data_present(hdr->frame_control)) | 99 | !ieee80211_is_data_present(hdr->frame_control)) |
100 | return RX_CONTINUE; | 100 | return RX_CONTINUE; |
@@ -221,19 +221,13 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
221 | if (!rx->sta || skb->len - hdrlen < 12) | 221 | if (!rx->sta || skb->len - hdrlen < 12) |
222 | return RX_DROP_UNUSABLE; | 222 | return RX_DROP_UNUSABLE; |
223 | 223 | ||
224 | if (status->flag & RX_FLAG_DECRYPTED) { | 224 | /* |
225 | if (status->flag & RX_FLAG_IV_STRIPPED) { | 225 | * Let TKIP code verify IV, but skip decryption. |
226 | /* | 226 | * In the case where hardware checks the IV as well, |
227 | * Hardware took care of all processing, including | 227 | * we don't even get here, see ieee80211_rx_h_decrypt() |
228 | * replay protection, and stripped the ICV/IV so | 228 | */ |
229 | * we cannot do any checks here. | 229 | if (status->flag & RX_FLAG_DECRYPTED) |
230 | */ | ||
231 | return RX_CONTINUE; | ||
232 | } | ||
233 | |||
234 | /* let TKIP code verify IV, but skip decryption */ | ||
235 | hwaccel = 1; | 230 | hwaccel = 1; |
236 | } | ||
237 | 231 | ||
238 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 232 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
239 | key, skb->data + hdrlen, | 233 | key, skb->data + hdrlen, |
@@ -447,10 +441,6 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
447 | if (!rx->sta || data_len < 0) | 441 | if (!rx->sta || data_len < 0) |
448 | return RX_DROP_UNUSABLE; | 442 | return RX_DROP_UNUSABLE; |
449 | 443 | ||
450 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
451 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
452 | return RX_CONTINUE; | ||
453 | |||
454 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 444 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
455 | 445 | ||
456 | queue = ieee80211_is_mgmt(hdr->frame_control) ? | 446 | queue = ieee80211_is_mgmt(hdr->frame_control) ? |
@@ -564,10 +554,6 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
564 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 554 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
565 | return RX_CONTINUE; | 555 | return RX_CONTINUE; |
566 | 556 | ||
567 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
568 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
569 | return RX_CONTINUE; | ||
570 | |||
571 | if (skb->len < 24 + sizeof(*mmie)) | 557 | if (skb->len < 24 + sizeof(*mmie)) |
572 | return RX_DROP_UNUSABLE; | 558 | return RX_DROP_UNUSABLE; |
573 | 559 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 541e2fff5e9c..d52630bbab04 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -253,11 +253,16 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | |||
253 | WARN_ON(err); | 253 | WARN_ON(err); |
254 | wdev->netdev->features |= NETIF_F_NETNS_LOCAL; | 254 | wdev->netdev->features |= NETIF_F_NETNS_LOCAL; |
255 | } | 255 | } |
256 | |||
257 | return err; | ||
256 | } | 258 | } |
257 | 259 | ||
258 | wiphy_net_set(&rdev->wiphy, net); | 260 | wiphy_net_set(&rdev->wiphy, net); |
259 | 261 | ||
260 | return err; | 262 | err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev)); |
263 | WARN_ON(err); | ||
264 | |||
265 | return 0; | ||
261 | } | 266 | } |
262 | 267 | ||
263 | static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) | 268 | static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) |
@@ -428,7 +433,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
428 | 433 | ||
429 | /* sanity check ifmodes */ | 434 | /* sanity check ifmodes */ |
430 | WARN_ON(!ifmodes); | 435 | WARN_ON(!ifmodes); |
431 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; | 436 | ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1; |
432 | if (WARN_ON(ifmodes != wiphy->interface_modes)) | 437 | if (WARN_ON(ifmodes != wiphy->interface_modes)) |
433 | wiphy->interface_modes = ifmodes; | 438 | wiphy->interface_modes = ifmodes; |
434 | 439 | ||
@@ -680,8 +685,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
680 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); | 685 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); |
681 | INIT_LIST_HEAD(&wdev->event_list); | 686 | INIT_LIST_HEAD(&wdev->event_list); |
682 | spin_lock_init(&wdev->event_lock); | 687 | spin_lock_init(&wdev->event_lock); |
683 | INIT_LIST_HEAD(&wdev->action_registrations); | 688 | INIT_LIST_HEAD(&wdev->mgmt_registrations); |
684 | spin_lock_init(&wdev->action_registrations_lock); | 689 | spin_lock_init(&wdev->mgmt_registrations_lock); |
685 | 690 | ||
686 | mutex_lock(&rdev->devlist_mtx); | 691 | mutex_lock(&rdev->devlist_mtx); |
687 | list_add_rcu(&wdev->list, &rdev->netdev_list); | 692 | list_add_rcu(&wdev->list, &rdev->netdev_list); |
@@ -801,7 +806,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
801 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); | 806 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); |
802 | list_del_rcu(&wdev->list); | 807 | list_del_rcu(&wdev->list); |
803 | rdev->devlist_generation++; | 808 | rdev->devlist_generation++; |
804 | cfg80211_mlme_purge_actions(wdev); | 809 | cfg80211_mlme_purge_registrations(wdev); |
805 | #ifdef CONFIG_CFG80211_WEXT | 810 | #ifdef CONFIG_CFG80211_WEXT |
806 | kfree(wdev->wext.keys); | 811 | kfree(wdev->wext.keys); |
807 | #endif | 812 | #endif |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 63d57ae399c3..58ab2c791d28 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -331,16 +331,17 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
331 | const u8 *resp_ie, size_t resp_ie_len, | 331 | const u8 *resp_ie, size_t resp_ie_len, |
332 | u16 status, bool wextev, | 332 | u16 status, bool wextev, |
333 | struct cfg80211_bss *bss); | 333 | struct cfg80211_bss *bss); |
334 | int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | 334 | int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, |
335 | const u8 *match_data, int match_len); | 335 | u16 frame_type, const u8 *match_data, |
336 | void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid); | 336 | int match_len); |
337 | void cfg80211_mlme_purge_actions(struct wireless_dev *wdev); | 337 | void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); |
338 | int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | 338 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); |
339 | struct net_device *dev, | 339 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
340 | struct ieee80211_channel *chan, | 340 | struct net_device *dev, |
341 | enum nl80211_channel_type channel_type, | 341 | struct ieee80211_channel *chan, |
342 | bool channel_type_valid, | 342 | enum nl80211_channel_type channel_type, |
343 | const u8 *buf, size_t len, u64 *cookie); | 343 | bool channel_type_valid, |
344 | const u8 *buf, size_t len, u64 *cookie); | ||
344 | 345 | ||
345 | /* SME */ | 346 | /* SME */ |
346 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 347 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index d1a3fb99fdf2..8515b1e5c578 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -149,7 +149,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
149 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 149 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
150 | const u8 *bssid = mgmt->bssid; | 150 | const u8 *bssid = mgmt->bssid; |
151 | int i; | 151 | int i; |
152 | bool found = false; | 152 | bool found = false, was_current = false; |
153 | 153 | ||
154 | ASSERT_WDEV_LOCK(wdev); | 154 | ASSERT_WDEV_LOCK(wdev); |
155 | 155 | ||
@@ -159,6 +159,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
159 | cfg80211_put_bss(&wdev->current_bss->pub); | 159 | cfg80211_put_bss(&wdev->current_bss->pub); |
160 | wdev->current_bss = NULL; | 160 | wdev->current_bss = NULL; |
161 | found = true; | 161 | found = true; |
162 | was_current = true; | ||
162 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { | 163 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { |
163 | if (wdev->auth_bsses[i] && | 164 | if (wdev->auth_bsses[i] && |
164 | memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { | 165 | memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { |
@@ -183,7 +184,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
183 | 184 | ||
184 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); | 185 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); |
185 | 186 | ||
186 | if (wdev->sme_state == CFG80211_SME_CONNECTED) { | 187 | if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { |
187 | u16 reason_code; | 188 | u16 reason_code; |
188 | bool from_ap; | 189 | bool from_ap; |
189 | 190 | ||
@@ -747,31 +748,51 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
747 | } | 748 | } |
748 | EXPORT_SYMBOL(cfg80211_new_sta); | 749 | EXPORT_SYMBOL(cfg80211_new_sta); |
749 | 750 | ||
750 | struct cfg80211_action_registration { | 751 | struct cfg80211_mgmt_registration { |
751 | struct list_head list; | 752 | struct list_head list; |
752 | 753 | ||
753 | u32 nlpid; | 754 | u32 nlpid; |
754 | 755 | ||
755 | int match_len; | 756 | int match_len; |
756 | 757 | ||
758 | __le16 frame_type; | ||
759 | |||
757 | u8 match[]; | 760 | u8 match[]; |
758 | }; | 761 | }; |
759 | 762 | ||
760 | int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | 763 | int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, |
761 | const u8 *match_data, int match_len) | 764 | u16 frame_type, const u8 *match_data, |
765 | int match_len) | ||
762 | { | 766 | { |
763 | struct cfg80211_action_registration *reg, *nreg; | 767 | struct cfg80211_mgmt_registration *reg, *nreg; |
764 | int err = 0; | 768 | int err = 0; |
769 | u16 mgmt_type; | ||
770 | |||
771 | if (!wdev->wiphy->mgmt_stypes) | ||
772 | return -EOPNOTSUPP; | ||
773 | |||
774 | if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) | ||
775 | return -EINVAL; | ||
776 | |||
777 | if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) | ||
778 | return -EINVAL; | ||
779 | |||
780 | mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; | ||
781 | if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) | ||
782 | return -EINVAL; | ||
765 | 783 | ||
766 | nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); | 784 | nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); |
767 | if (!nreg) | 785 | if (!nreg) |
768 | return -ENOMEM; | 786 | return -ENOMEM; |
769 | 787 | ||
770 | spin_lock_bh(&wdev->action_registrations_lock); | 788 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
771 | 789 | ||
772 | list_for_each_entry(reg, &wdev->action_registrations, list) { | 790 | list_for_each_entry(reg, &wdev->mgmt_registrations, list) { |
773 | int mlen = min(match_len, reg->match_len); | 791 | int mlen = min(match_len, reg->match_len); |
774 | 792 | ||
793 | if (frame_type != le16_to_cpu(reg->frame_type)) | ||
794 | continue; | ||
795 | |||
775 | if (memcmp(reg->match, match_data, mlen) == 0) { | 796 | if (memcmp(reg->match, match_data, mlen) == 0) { |
776 | err = -EALREADY; | 797 | err = -EALREADY; |
777 | break; | 798 | break; |
@@ -786,62 +807,75 @@ int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | |||
786 | memcpy(nreg->match, match_data, match_len); | 807 | memcpy(nreg->match, match_data, match_len); |
787 | nreg->match_len = match_len; | 808 | nreg->match_len = match_len; |
788 | nreg->nlpid = snd_pid; | 809 | nreg->nlpid = snd_pid; |
789 | list_add(&nreg->list, &wdev->action_registrations); | 810 | nreg->frame_type = cpu_to_le16(frame_type); |
811 | list_add(&nreg->list, &wdev->mgmt_registrations); | ||
790 | 812 | ||
791 | out: | 813 | out: |
792 | spin_unlock_bh(&wdev->action_registrations_lock); | 814 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
793 | return err; | 815 | return err; |
794 | } | 816 | } |
795 | 817 | ||
796 | void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid) | 818 | void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid) |
797 | { | 819 | { |
798 | struct cfg80211_action_registration *reg, *tmp; | 820 | struct cfg80211_mgmt_registration *reg, *tmp; |
799 | 821 | ||
800 | spin_lock_bh(&wdev->action_registrations_lock); | 822 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
801 | 823 | ||
802 | list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { | 824 | list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { |
803 | if (reg->nlpid == nlpid) { | 825 | if (reg->nlpid == nlpid) { |
804 | list_del(®->list); | 826 | list_del(®->list); |
805 | kfree(reg); | 827 | kfree(reg); |
806 | } | 828 | } |
807 | } | 829 | } |
808 | 830 | ||
809 | spin_unlock_bh(&wdev->action_registrations_lock); | 831 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
810 | } | 832 | } |
811 | 833 | ||
812 | void cfg80211_mlme_purge_actions(struct wireless_dev *wdev) | 834 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) |
813 | { | 835 | { |
814 | struct cfg80211_action_registration *reg, *tmp; | 836 | struct cfg80211_mgmt_registration *reg, *tmp; |
815 | 837 | ||
816 | spin_lock_bh(&wdev->action_registrations_lock); | 838 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
817 | 839 | ||
818 | list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { | 840 | list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { |
819 | list_del(®->list); | 841 | list_del(®->list); |
820 | kfree(reg); | 842 | kfree(reg); |
821 | } | 843 | } |
822 | 844 | ||
823 | spin_unlock_bh(&wdev->action_registrations_lock); | 845 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
824 | } | 846 | } |
825 | 847 | ||
826 | int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | 848 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
827 | struct net_device *dev, | 849 | struct net_device *dev, |
828 | struct ieee80211_channel *chan, | 850 | struct ieee80211_channel *chan, |
829 | enum nl80211_channel_type channel_type, | 851 | enum nl80211_channel_type channel_type, |
830 | bool channel_type_valid, | 852 | bool channel_type_valid, |
831 | const u8 *buf, size_t len, u64 *cookie) | 853 | const u8 *buf, size_t len, u64 *cookie) |
832 | { | 854 | { |
833 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 855 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
834 | const struct ieee80211_mgmt *mgmt; | 856 | const struct ieee80211_mgmt *mgmt; |
857 | u16 stype; | ||
858 | |||
859 | if (!wdev->wiphy->mgmt_stypes) | ||
860 | return -EOPNOTSUPP; | ||
835 | 861 | ||
836 | if (rdev->ops->action == NULL) | 862 | if (!rdev->ops->mgmt_tx) |
837 | return -EOPNOTSUPP; | 863 | return -EOPNOTSUPP; |
864 | |||
838 | if (len < 24 + 1) | 865 | if (len < 24 + 1) |
839 | return -EINVAL; | 866 | return -EINVAL; |
840 | 867 | ||
841 | mgmt = (const struct ieee80211_mgmt *) buf; | 868 | mgmt = (const struct ieee80211_mgmt *) buf; |
842 | if (!ieee80211_is_action(mgmt->frame_control)) | 869 | |
870 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | ||
843 | return -EINVAL; | 871 | return -EINVAL; |
844 | if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { | 872 | |
873 | stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; | ||
874 | if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4))) | ||
875 | return -EINVAL; | ||
876 | |||
877 | if (ieee80211_is_action(mgmt->frame_control) && | ||
878 | mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { | ||
845 | /* Verify that we are associated with the destination AP */ | 879 | /* Verify that we are associated with the destination AP */ |
846 | wdev_lock(wdev); | 880 | wdev_lock(wdev); |
847 | 881 | ||
@@ -862,64 +896,75 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | |||
862 | return -EINVAL; | 896 | return -EINVAL; |
863 | 897 | ||
864 | /* Transmit the Action frame as requested by user space */ | 898 | /* Transmit the Action frame as requested by user space */ |
865 | return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type, | 899 | return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, channel_type, |
866 | channel_type_valid, buf, len, cookie); | 900 | channel_type_valid, buf, len, cookie); |
867 | } | 901 | } |
868 | 902 | ||
869 | bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, | 903 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, |
870 | size_t len, gfp_t gfp) | 904 | size_t len, gfp_t gfp) |
871 | { | 905 | { |
872 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 906 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
873 | struct wiphy *wiphy = wdev->wiphy; | 907 | struct wiphy *wiphy = wdev->wiphy; |
874 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 908 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
875 | struct cfg80211_action_registration *reg; | 909 | struct cfg80211_mgmt_registration *reg; |
876 | const u8 *action_data; | 910 | const struct ieee80211_txrx_stypes *stypes = |
877 | int action_data_len; | 911 | &wiphy->mgmt_stypes[wdev->iftype]; |
912 | struct ieee80211_mgmt *mgmt = (void *)buf; | ||
913 | const u8 *data; | ||
914 | int data_len; | ||
878 | bool result = false; | 915 | bool result = false; |
916 | __le16 ftype = mgmt->frame_control & | ||
917 | cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE); | ||
918 | u16 stype; | ||
879 | 919 | ||
880 | /* frame length - min size excluding category */ | 920 | stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4; |
881 | action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1); | ||
882 | 921 | ||
883 | /* action data starts with category */ | 922 | if (!(stypes->rx & BIT(stype))) |
884 | action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1; | 923 | return false; |
885 | 924 | ||
886 | spin_lock_bh(&wdev->action_registrations_lock); | 925 | data = buf + ieee80211_hdrlen(mgmt->frame_control); |
926 | data_len = len - ieee80211_hdrlen(mgmt->frame_control); | ||
927 | |||
928 | spin_lock_bh(&wdev->mgmt_registrations_lock); | ||
929 | |||
930 | list_for_each_entry(reg, &wdev->mgmt_registrations, list) { | ||
931 | if (reg->frame_type != ftype) | ||
932 | continue; | ||
887 | 933 | ||
888 | list_for_each_entry(reg, &wdev->action_registrations, list) { | 934 | if (reg->match_len > data_len) |
889 | if (reg->match_len > action_data_len) | ||
890 | continue; | 935 | continue; |
891 | 936 | ||
892 | if (memcmp(reg->match, action_data, reg->match_len)) | 937 | if (memcmp(reg->match, data, reg->match_len)) |
893 | continue; | 938 | continue; |
894 | 939 | ||
895 | /* found match! */ | 940 | /* found match! */ |
896 | 941 | ||
897 | /* Indicate the received Action frame to user space */ | 942 | /* Indicate the received Action frame to user space */ |
898 | if (nl80211_send_action(rdev, dev, reg->nlpid, freq, | 943 | if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq, |
899 | buf, len, gfp)) | 944 | buf, len, gfp)) |
900 | continue; | 945 | continue; |
901 | 946 | ||
902 | result = true; | 947 | result = true; |
903 | break; | 948 | break; |
904 | } | 949 | } |
905 | 950 | ||
906 | spin_unlock_bh(&wdev->action_registrations_lock); | 951 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
907 | 952 | ||
908 | return result; | 953 | return result; |
909 | } | 954 | } |
910 | EXPORT_SYMBOL(cfg80211_rx_action); | 955 | EXPORT_SYMBOL(cfg80211_rx_mgmt); |
911 | 956 | ||
912 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | 957 | void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie, |
913 | const u8 *buf, size_t len, bool ack, gfp_t gfp) | 958 | const u8 *buf, size_t len, bool ack, gfp_t gfp) |
914 | { | 959 | { |
915 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 960 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
916 | struct wiphy *wiphy = wdev->wiphy; | 961 | struct wiphy *wiphy = wdev->wiphy; |
917 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 962 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
918 | 963 | ||
919 | /* Indicate TX status of the Action frame to user space */ | 964 | /* Indicate TX status of the Action frame to user space */ |
920 | nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); | 965 | nl80211_send_mgmt_tx_status(rdev, dev, cookie, buf, len, ack, gfp); |
921 | } | 966 | } |
922 | EXPORT_SYMBOL(cfg80211_action_tx_status); | 967 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); |
923 | 968 | ||
924 | void cfg80211_cqm_rssi_notify(struct net_device *dev, | 969 | void cfg80211_cqm_rssi_notify(struct net_device *dev, |
925 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 970 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 37902a54e9c1..927ffbd2aebc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -156,6 +156,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
156 | 156 | ||
157 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, | 157 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, |
158 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, | 158 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, |
159 | [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, | ||
159 | }; | 160 | }; |
160 | 161 | ||
161 | /* policy for the attributes */ | 162 | /* policy for the attributes */ |
@@ -437,6 +438,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
437 | struct ieee80211_rate *rate; | 438 | struct ieee80211_rate *rate; |
438 | int i; | 439 | int i; |
439 | u16 ifmodes = dev->wiphy.interface_modes; | 440 | u16 ifmodes = dev->wiphy.interface_modes; |
441 | const struct ieee80211_txrx_stypes *mgmt_stypes = | ||
442 | dev->wiphy.mgmt_stypes; | ||
440 | 443 | ||
441 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); | 444 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); |
442 | if (!hdr) | 445 | if (!hdr) |
@@ -587,7 +590,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
587 | CMD(flush_pmksa, FLUSH_PMKSA); | 590 | CMD(flush_pmksa, FLUSH_PMKSA); |
588 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | 591 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); |
589 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | 592 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); |
590 | CMD(action, ACTION); | 593 | CMD(mgmt_tx, FRAME); |
591 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | 594 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
592 | i++; | 595 | i++; |
593 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 596 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
@@ -608,6 +611,53 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
608 | 611 | ||
609 | nla_nest_end(msg, nl_cmds); | 612 | nla_nest_end(msg, nl_cmds); |
610 | 613 | ||
614 | if (mgmt_stypes) { | ||
615 | u16 stypes; | ||
616 | struct nlattr *nl_ftypes, *nl_ifs; | ||
617 | enum nl80211_iftype ift; | ||
618 | |||
619 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); | ||
620 | if (!nl_ifs) | ||
621 | goto nla_put_failure; | ||
622 | |||
623 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
624 | nl_ftypes = nla_nest_start(msg, ift); | ||
625 | if (!nl_ftypes) | ||
626 | goto nla_put_failure; | ||
627 | i = 0; | ||
628 | stypes = mgmt_stypes[ift].tx; | ||
629 | while (stypes) { | ||
630 | if (stypes & 1) | ||
631 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, | ||
632 | (i << 4) | IEEE80211_FTYPE_MGMT); | ||
633 | stypes >>= 1; | ||
634 | i++; | ||
635 | } | ||
636 | nla_nest_end(msg, nl_ftypes); | ||
637 | } | ||
638 | |||
639 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); | ||
640 | if (!nl_ifs) | ||
641 | goto nla_put_failure; | ||
642 | |||
643 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
644 | nl_ftypes = nla_nest_start(msg, ift); | ||
645 | if (!nl_ftypes) | ||
646 | goto nla_put_failure; | ||
647 | i = 0; | ||
648 | stypes = mgmt_stypes[ift].rx; | ||
649 | while (stypes) { | ||
650 | if (stypes & 1) | ||
651 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, | ||
652 | (i << 4) | IEEE80211_FTYPE_MGMT); | ||
653 | stypes >>= 1; | ||
654 | i++; | ||
655 | } | ||
656 | nla_nest_end(msg, nl_ftypes); | ||
657 | } | ||
658 | nla_nest_end(msg, nl_ifs); | ||
659 | } | ||
660 | |||
611 | return genlmsg_end(msg, hdr); | 661 | return genlmsg_end(msg, hdr); |
612 | 662 | ||
613 | nla_put_failure: | 663 | nla_put_failure: |
@@ -3572,6 +3622,21 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3572 | if (err) | 3622 | if (err) |
3573 | goto unlock_rtnl; | 3623 | goto unlock_rtnl; |
3574 | 3624 | ||
3625 | if (key.idx >= 0) { | ||
3626 | int i; | ||
3627 | bool ok = false; | ||
3628 | for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) { | ||
3629 | if (key.p.cipher == rdev->wiphy.cipher_suites[i]) { | ||
3630 | ok = true; | ||
3631 | break; | ||
3632 | } | ||
3633 | } | ||
3634 | if (!ok) { | ||
3635 | err = -EINVAL; | ||
3636 | goto out; | ||
3637 | } | ||
3638 | } | ||
3639 | |||
3575 | if (!rdev->ops->auth) { | 3640 | if (!rdev->ops->auth) { |
3576 | err = -EOPNOTSUPP; | 3641 | err = -EOPNOTSUPP; |
3577 | goto out; | 3642 | goto out; |
@@ -4717,17 +4782,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
4717 | return err; | 4782 | return err; |
4718 | } | 4783 | } |
4719 | 4784 | ||
4720 | static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | 4785 | static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) |
4721 | { | 4786 | { |
4722 | struct cfg80211_registered_device *rdev; | 4787 | struct cfg80211_registered_device *rdev; |
4723 | struct net_device *dev; | 4788 | struct net_device *dev; |
4789 | u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; | ||
4724 | int err; | 4790 | int err; |
4725 | 4791 | ||
4726 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) | 4792 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) |
4727 | return -EINVAL; | 4793 | return -EINVAL; |
4728 | 4794 | ||
4729 | if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1) | 4795 | if (info->attrs[NL80211_ATTR_FRAME_TYPE]) |
4730 | return -EINVAL; | 4796 | frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); |
4731 | 4797 | ||
4732 | rtnl_lock(); | 4798 | rtnl_lock(); |
4733 | 4799 | ||
@@ -4742,12 +4808,13 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4742 | } | 4808 | } |
4743 | 4809 | ||
4744 | /* not much point in registering if we can't reply */ | 4810 | /* not much point in registering if we can't reply */ |
4745 | if (!rdev->ops->action) { | 4811 | if (!rdev->ops->mgmt_tx) { |
4746 | err = -EOPNOTSUPP; | 4812 | err = -EOPNOTSUPP; |
4747 | goto out; | 4813 | goto out; |
4748 | } | 4814 | } |
4749 | 4815 | ||
4750 | err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid, | 4816 | err = cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, |
4817 | frame_type, | ||
4751 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), | 4818 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), |
4752 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); | 4819 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); |
4753 | out: | 4820 | out: |
@@ -4758,7 +4825,7 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4758 | return err; | 4825 | return err; |
4759 | } | 4826 | } |
4760 | 4827 | ||
4761 | static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | 4828 | static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) |
4762 | { | 4829 | { |
4763 | struct cfg80211_registered_device *rdev; | 4830 | struct cfg80211_registered_device *rdev; |
4764 | struct net_device *dev; | 4831 | struct net_device *dev; |
@@ -4781,7 +4848,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4781 | if (err) | 4848 | if (err) |
4782 | goto unlock_rtnl; | 4849 | goto unlock_rtnl; |
4783 | 4850 | ||
4784 | if (!rdev->ops->action) { | 4851 | if (!rdev->ops->mgmt_tx) { |
4785 | err = -EOPNOTSUPP; | 4852 | err = -EOPNOTSUPP; |
4786 | goto out; | 4853 | goto out; |
4787 | } | 4854 | } |
@@ -4824,17 +4891,17 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4824 | } | 4891 | } |
4825 | 4892 | ||
4826 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 4893 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
4827 | NL80211_CMD_ACTION); | 4894 | NL80211_CMD_FRAME); |
4828 | 4895 | ||
4829 | if (IS_ERR(hdr)) { | 4896 | if (IS_ERR(hdr)) { |
4830 | err = PTR_ERR(hdr); | 4897 | err = PTR_ERR(hdr); |
4831 | goto free_msg; | 4898 | goto free_msg; |
4832 | } | 4899 | } |
4833 | err = cfg80211_mlme_action(rdev, dev, chan, channel_type, | 4900 | err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, channel_type, |
4834 | channel_type_valid, | 4901 | channel_type_valid, |
4835 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 4902 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
4836 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 4903 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
4837 | &cookie); | 4904 | &cookie); |
4838 | if (err) | 4905 | if (err) |
4839 | goto free_msg; | 4906 | goto free_msg; |
4840 | 4907 | ||
@@ -5333,14 +5400,14 @@ static struct genl_ops nl80211_ops[] = { | |||
5333 | .flags = GENL_ADMIN_PERM, | 5400 | .flags = GENL_ADMIN_PERM, |
5334 | }, | 5401 | }, |
5335 | { | 5402 | { |
5336 | .cmd = NL80211_CMD_REGISTER_ACTION, | 5403 | .cmd = NL80211_CMD_REGISTER_FRAME, |
5337 | .doit = nl80211_register_action, | 5404 | .doit = nl80211_register_mgmt, |
5338 | .policy = nl80211_policy, | 5405 | .policy = nl80211_policy, |
5339 | .flags = GENL_ADMIN_PERM, | 5406 | .flags = GENL_ADMIN_PERM, |
5340 | }, | 5407 | }, |
5341 | { | 5408 | { |
5342 | .cmd = NL80211_CMD_ACTION, | 5409 | .cmd = NL80211_CMD_FRAME, |
5343 | .doit = nl80211_action, | 5410 | .doit = nl80211_tx_mgmt, |
5344 | .policy = nl80211_policy, | 5411 | .policy = nl80211_policy, |
5345 | .flags = GENL_ADMIN_PERM, | 5412 | .flags = GENL_ADMIN_PERM, |
5346 | }, | 5413 | }, |
@@ -6040,9 +6107,9 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
6040 | nl80211_mlme_mcgrp.id, gfp); | 6107 | nl80211_mlme_mcgrp.id, gfp); |
6041 | } | 6108 | } |
6042 | 6109 | ||
6043 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | 6110 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
6044 | struct net_device *netdev, u32 nlpid, | 6111 | struct net_device *netdev, u32 nlpid, |
6045 | int freq, const u8 *buf, size_t len, gfp_t gfp) | 6112 | int freq, const u8 *buf, size_t len, gfp_t gfp) |
6046 | { | 6113 | { |
6047 | struct sk_buff *msg; | 6114 | struct sk_buff *msg; |
6048 | void *hdr; | 6115 | void *hdr; |
@@ -6052,7 +6119,7 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, | |||
6052 | if (!msg) | 6119 | if (!msg) |
6053 | return -ENOMEM; | 6120 | return -ENOMEM; |
6054 | 6121 | ||
6055 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION); | 6122 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); |
6056 | if (!hdr) { | 6123 | if (!hdr) { |
6057 | nlmsg_free(msg); | 6124 | nlmsg_free(msg); |
6058 | return -ENOMEM; | 6125 | return -ENOMEM; |
@@ -6080,10 +6147,10 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, | |||
6080 | return -ENOBUFS; | 6147 | return -ENOBUFS; |
6081 | } | 6148 | } |
6082 | 6149 | ||
6083 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | 6150 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
6084 | struct net_device *netdev, u64 cookie, | 6151 | struct net_device *netdev, u64 cookie, |
6085 | const u8 *buf, size_t len, bool ack, | 6152 | const u8 *buf, size_t len, bool ack, |
6086 | gfp_t gfp) | 6153 | gfp_t gfp) |
6087 | { | 6154 | { |
6088 | struct sk_buff *msg; | 6155 | struct sk_buff *msg; |
6089 | void *hdr; | 6156 | void *hdr; |
@@ -6092,7 +6159,7 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | |||
6092 | if (!msg) | 6159 | if (!msg) |
6093 | return; | 6160 | return; |
6094 | 6161 | ||
6095 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS); | 6162 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS); |
6096 | if (!hdr) { | 6163 | if (!hdr) { |
6097 | nlmsg_free(msg); | 6164 | nlmsg_free(msg); |
6098 | return; | 6165 | return; |
@@ -6179,7 +6246,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
6179 | 6246 | ||
6180 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) | 6247 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) |
6181 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) | 6248 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) |
6182 | cfg80211_mlme_unregister_actions(wdev, notify->pid); | 6249 | cfg80211_mlme_unregister_socket(wdev, notify->pid); |
6183 | 6250 | ||
6184 | rcu_read_unlock(); | 6251 | rcu_read_unlock(); |
6185 | 6252 | ||
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 2ad7fbc7d9f1..30d2f939150d 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -74,13 +74,13 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
74 | struct net_device *dev, const u8 *mac_addr, | 74 | struct net_device *dev, const u8 *mac_addr, |
75 | struct station_info *sinfo, gfp_t gfp); | 75 | struct station_info *sinfo, gfp_t gfp); |
76 | 76 | ||
77 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | 77 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
78 | struct net_device *netdev, u32 nlpid, int freq, | 78 | struct net_device *netdev, u32 nlpid, int freq, |
79 | const u8 *buf, size_t len, gfp_t gfp); | 79 | const u8 *buf, size_t len, gfp_t gfp); |
80 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | 80 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
81 | struct net_device *netdev, u64 cookie, | 81 | struct net_device *netdev, u64 cookie, |
82 | const u8 *buf, size_t len, bool ack, | 82 | const u8 *buf, size_t len, bool ack, |
83 | gfp_t gfp); | 83 | gfp_t gfp); |
84 | 84 | ||
85 | void | 85 | void |
86 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | 86 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f180db0de66c..b0d9a08447c9 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/list.h> | 37 | #include <linux/list.h> |
38 | #include <linux/random.h> | 38 | #include <linux/random.h> |
39 | #include <linux/ctype.h> | ||
39 | #include <linux/nl80211.h> | 40 | #include <linux/nl80211.h> |
40 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
41 | #include <net/cfg80211.h> | 42 | #include <net/cfg80211.h> |
@@ -181,14 +182,6 @@ static bool is_alpha2_set(const char *alpha2) | |||
181 | return false; | 182 | return false; |
182 | } | 183 | } |
183 | 184 | ||
184 | static bool is_alpha_upper(char letter) | ||
185 | { | ||
186 | /* ASCII A - Z */ | ||
187 | if (letter >= 65 && letter <= 90) | ||
188 | return true; | ||
189 | return false; | ||
190 | } | ||
191 | |||
192 | static bool is_unknown_alpha2(const char *alpha2) | 185 | static bool is_unknown_alpha2(const char *alpha2) |
193 | { | 186 | { |
194 | if (!alpha2) | 187 | if (!alpha2) |
@@ -220,7 +213,7 @@ static bool is_an_alpha2(const char *alpha2) | |||
220 | { | 213 | { |
221 | if (!alpha2) | 214 | if (!alpha2) |
222 | return false; | 215 | return false; |
223 | if (is_alpha_upper(alpha2[0]) && is_alpha_upper(alpha2[1])) | 216 | if (isalpha(alpha2[0]) && isalpha(alpha2[1])) |
224 | return true; | 217 | return true; |
225 | return false; | 218 | return false; |
226 | } | 219 | } |
@@ -1399,6 +1392,11 @@ static DECLARE_WORK(reg_work, reg_todo); | |||
1399 | 1392 | ||
1400 | static void queue_regulatory_request(struct regulatory_request *request) | 1393 | static void queue_regulatory_request(struct regulatory_request *request) |
1401 | { | 1394 | { |
1395 | if (isalpha(request->alpha2[0])) | ||
1396 | request->alpha2[0] = toupper(request->alpha2[0]); | ||
1397 | if (isalpha(request->alpha2[1])) | ||
1398 | request->alpha2[1] = toupper(request->alpha2[1]); | ||
1399 | |||
1402 | spin_lock(®_requests_lock); | 1400 | spin_lock(®_requests_lock); |
1403 | list_add_tail(&request->list, ®_requests_list); | 1401 | list_add_tail(&request->list, ®_requests_list); |
1404 | spin_unlock(®_requests_lock); | 1402 | spin_unlock(®_requests_lock); |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 9f2cef3e0ca0..74a9e3cce452 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -110,6 +110,13 @@ static int wiphy_resume(struct device *dev) | |||
110 | return ret; | 110 | return ret; |
111 | } | 111 | } |
112 | 112 | ||
113 | static const void *wiphy_namespace(struct device *d) | ||
114 | { | ||
115 | struct wiphy *wiphy = container_of(d, struct wiphy, dev); | ||
116 | |||
117 | return wiphy_net(wiphy); | ||
118 | } | ||
119 | |||
113 | struct class ieee80211_class = { | 120 | struct class ieee80211_class = { |
114 | .name = "ieee80211", | 121 | .name = "ieee80211", |
115 | .owner = THIS_MODULE, | 122 | .owner = THIS_MODULE, |
@@ -120,6 +127,8 @@ struct class ieee80211_class = { | |||
120 | #endif | 127 | #endif |
121 | .suspend = wiphy_suspend, | 128 | .suspend = wiphy_suspend, |
122 | .resume = wiphy_resume, | 129 | .resume = wiphy_resume, |
130 | .ns_type = &net_ns_type_operations, | ||
131 | .namespace = wiphy_namespace, | ||
123 | }; | 132 | }; |
124 | 133 | ||
125 | int wiphy_sysfs_init(void) | 134 | int wiphy_sysfs_init(void) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 0c8a1e8b7690..8d961cc4ae98 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -221,7 +221,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) = | |||
221 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | 221 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; |
222 | EXPORT_SYMBOL(bridge_tunnel_header); | 222 | EXPORT_SYMBOL(bridge_tunnel_header); |
223 | 223 | ||
224 | unsigned int ieee80211_hdrlen(__le16 fc) | 224 | unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc) |
225 | { | 225 | { |
226 | unsigned int hdrlen = 24; | 226 | unsigned int hdrlen = 24; |
227 | 227 | ||
@@ -823,7 +823,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
823 | /* monitor can't bridge anyway */ | 823 | /* monitor can't bridge anyway */ |
824 | break; | 824 | break; |
825 | case NL80211_IFTYPE_UNSPECIFIED: | 825 | case NL80211_IFTYPE_UNSPECIFIED: |
826 | case __NL80211_IFTYPE_AFTER_LAST: | 826 | case NUM_NL80211_IFTYPES: |
827 | /* not happening */ | 827 | /* not happening */ |
828 | break; | 828 | break; |
829 | } | 829 | } |