diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-29 01:57:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-29 01:57:58 -0400 |
commit | 28f49d8fec19833672a6a813bfde0068fee50bc9 (patch) | |
tree | 6905c5cabc063e44b891ae0af5b5d7cce69e6e71 | |
parent | 332e4af80d1214fbf0e263e1408fc7c5b64ecdd6 (diff) | |
parent | ff28bd94e307c67abb1bccda5d3a9018bd798e08 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
84 files changed, 3384 insertions, 4607 deletions
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index a83ff23cd68c..0843ed0163a5 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt | |||
@@ -1,89 +1,528 @@ | |||
1 | rfkill - RF switch subsystem support | 1 | rfkill - RF switch subsystem support |
2 | ==================================== | 2 | ==================================== |
3 | 3 | ||
4 | 1 Implementation details | 4 | 1 Introduction |
5 | 2 Driver support | 5 | 2 Implementation details |
6 | 3 Userspace support | 6 | 3 Kernel driver guidelines |
7 | 3.1 wireless device drivers | ||
8 | 3.2 platform/switch drivers | ||
9 | 3.3 input device drivers | ||
10 | 4 Kernel API | ||
11 | 5 Userspace support | ||
7 | 12 | ||
8 | =============================================================================== | ||
9 | 1: Implementation details | ||
10 | 13 | ||
11 | The rfkill switch subsystem offers support for keys often found on laptops | 14 | 1. Introduction: |
12 | to enable wireless devices like WiFi and Bluetooth. | 15 | |
16 | The rfkill switch subsystem exists to add a generic interface to circuitry that | ||
17 | can enable or disable the signal output of a wireless *transmitter* of any | ||
18 | type. By far, the most common use is to disable radio-frequency transmitters. | ||
13 | 19 | ||
14 | This is done by providing the user 3 possibilities: | 20 | Note that disabling the signal output means that the the transmitter is to be |
15 | 1 - The rfkill system handles all events; userspace is not aware of events. | 21 | made to not emit any energy when "blocked". rfkill is not about blocking data |
16 | 2 - The rfkill system handles all events; userspace is informed about the events. | 22 | transmissions, it is about blocking energy emission. |
17 | 3 - The rfkill system does not handle events; userspace handles all events. | ||
18 | 23 | ||
19 | The buttons to enable and disable the wireless radios are important in | 24 | The rfkill subsystem offers support for keys and switches often found on |
25 | laptops to enable wireless devices like WiFi and Bluetooth, so that these keys | ||
26 | and switches actually perform an action in all wireless devices of a given type | ||
27 | attached to the system. | ||
28 | |||
29 | The buttons to enable and disable the wireless transmitters are important in | ||
20 | situations where the user is for example using his laptop on a location where | 30 | situations where the user is for example using his laptop on a location where |
21 | wireless radios _must_ be disabled (e.g. airplanes). | 31 | radio-frequency transmitters _must_ be disabled (e.g. airplanes). |
22 | Because of this requirement, userspace support for the keys should not be | 32 | |
23 | made mandatory. Because userspace might want to perform some additional smarter | 33 | Because of this requirement, userspace support for the keys should not be made |
24 | tasks when the key is pressed, rfkill still provides userspace the possibility | 34 | mandatory. Because userspace might want to perform some additional smarter |
25 | to take over the task to handle the key events. | 35 | tasks when the key is pressed, rfkill provides userspace the possibility to |
36 | take over the task to handle the key events. | ||
37 | |||
38 | =============================================================================== | ||
39 | 2: Implementation details | ||
40 | |||
41 | The rfkill subsystem is composed of various components: the rfkill class, the | ||
42 | rfkill-input module (an input layer handler), and some specific input layer | ||
43 | events. | ||
44 | |||
45 | The rfkill class provides kernel drivers with an interface that allows them to | ||
46 | know when they should enable or disable a wireless network device transmitter. | ||
47 | This is enabled by the CONFIG_RFKILL Kconfig option. | ||
48 | |||
49 | The rfkill class support makes sure userspace will be notified of all state | ||
50 | changes on rfkill devices through uevents. It provides a notification chain | ||
51 | for interested parties in the kernel to also get notified of rfkill state | ||
52 | changes in other drivers. It creates several sysfs entries which can be used | ||
53 | by userspace. See section "Userspace support". | ||
54 | |||
55 | The rfkill-input module provides the kernel with the ability to implement a | ||
56 | basic response when the user presses a key or button (or toggles a switch) | ||
57 | related to rfkill functionality. It is an in-kernel implementation of default | ||
58 | policy of reacting to rfkill-related input events and neither mandatory nor | ||
59 | required for wireless drivers to operate. It is enabled by the | ||
60 | CONFIG_RFKILL_INPUT Kconfig option. | ||
61 | |||
62 | rfkill-input is a rfkill-related events input layer handler. This handler will | ||
63 | listen to all rfkill key events and will change the rfkill state of the | ||
64 | wireless devices accordingly. With this option enabled userspace could either | ||
65 | do nothing or simply perform monitoring tasks. | ||
66 | |||
67 | The rfkill-input module also provides EPO (emergency power-off) functionality | ||
68 | for all wireless transmitters. This function cannot be overridden, and it is | ||
69 | always active. rfkill EPO is related to *_RFKILL_ALL input layer events. | ||
70 | |||
71 | |||
72 | Important terms for the rfkill subsystem: | ||
73 | |||
74 | In order to avoid confusion, we avoid the term "switch" in rfkill when it is | ||
75 | referring to an electronic control circuit that enables or disables a | ||
76 | transmitter. We reserve it for the physical device a human manipulates | ||
77 | (which is an input device, by the way): | ||
78 | |||
79 | rfkill switch: | ||
80 | |||
81 | A physical device a human manipulates. Its state can be perceived by | ||
82 | the kernel either directly (through a GPIO pin, ACPI GPE) or by its | ||
83 | effect on a rfkill line of a wireless device. | ||
84 | |||
85 | rfkill controller: | ||
86 | |||
87 | A hardware circuit that controls the state of a rfkill line, which a | ||
88 | kernel driver can interact with *to modify* that state (i.e. it has | ||
89 | either write-only or read/write access). | ||
90 | |||
91 | rfkill line: | ||
92 | |||
93 | An input channel (hardware or software) of a wireless device, which | ||
94 | causes a wireless transmitter to stop emitting energy (BLOCK) when it | ||
95 | is active. Point of view is extremely important here: rfkill lines are | ||
96 | always seen from the PoV of a wireless device (and its driver). | ||
97 | |||
98 | soft rfkill line/software rfkill line: | ||
99 | |||
100 | A rfkill line the wireless device driver can directly change the state | ||
101 | of. Related to rfkill_state RFKILL_STATE_SOFT_BLOCKED. | ||
102 | |||
103 | hard rfkill line/hardware rfkill line: | ||
104 | |||
105 | A rfkill line that works fully in hardware or firmware, and that cannot | ||
106 | be overridden by the kernel driver. The hardware device or the | ||
107 | firmware just exports its status to the driver, but it is read-only. | ||
108 | Related to rfkill_state RFKILL_STATE_HARD_BLOCKED. | ||
109 | |||
110 | The enum rfkill_state describes the rfkill state of a transmitter: | ||
111 | |||
112 | When a rfkill line or rfkill controller is in the RFKILL_STATE_UNBLOCKED state, | ||
113 | the wireless transmitter (radio TX circuit for example) is *enabled*. When the | ||
114 | it is in the RFKILL_STATE_SOFT_BLOCKED or RFKILL_STATE_HARD_BLOCKED, the | ||
115 | wireless transmitter is to be *blocked* from operating. | ||
116 | |||
117 | RFKILL_STATE_SOFT_BLOCKED indicates that a call to toggle_radio() can change | ||
118 | that state. RFKILL_STATE_HARD_BLOCKED indicates that a call to toggle_radio() | ||
119 | will not be able to change the state and will return with a suitable error if | ||
120 | attempts are made to set the state to RFKILL_STATE_UNBLOCKED. | ||
121 | |||
122 | RFKILL_STATE_HARD_BLOCKED is used by drivers to signal that the device is | ||
123 | locked in the BLOCKED state by a hardwire rfkill line (typically an input pin | ||
124 | that, when active, forces the transmitter to be disabled) which the driver | ||
125 | CANNOT override. | ||
126 | |||
127 | Full rfkill functionality requires two different subsystems to cooperate: the | ||
128 | input layer and the rfkill class. The input layer issues *commands* to the | ||
129 | entire system requesting that devices registered to the rfkill class change | ||
130 | state. The way this interaction happens is not complex, but it is not obvious | ||
131 | either: | ||
132 | |||
133 | Kernel Input layer: | ||
134 | |||
135 | * Generates KEY_WWAN, KEY_WLAN, KEY_BLUETOOTH, SW_RFKILL_ALL, and | ||
136 | other such events when the user presses certain keys, buttons, or | ||
137 | toggles certain physical switches. | ||
138 | |||
139 | THE INPUT LAYER IS NEVER USED TO PROPAGATE STATUS, NOTIFICATIONS OR THE | ||
140 | KIND OF STUFF AN ON-SCREEN-DISPLAY APPLICATION WOULD REPORT. It is | ||
141 | used to issue *commands* for the system to change behaviour, and these | ||
142 | commands may or may not be carried out by some kernel driver or | ||
143 | userspace application. It follows that doing user feedback based only | ||
144 | on input events is broken, as there is no guarantee that an input event | ||
145 | will be acted upon. | ||
146 | |||
147 | Most wireless communication device drivers implementing rfkill | ||
148 | functionality MUST NOT generate these events, and have no reason to | ||
149 | register themselves with the input layer. Doing otherwise is a common | ||
150 | misconception. There is an API to propagate rfkill status change | ||
151 | information, and it is NOT the input layer. | ||
152 | |||
153 | rfkill class: | ||
154 | |||
155 | * Calls a hook in a driver to effectively change the wireless | ||
156 | transmitter state; | ||
157 | * Keeps track of the wireless transmitter state (with help from | ||
158 | the driver); | ||
159 | * Generates userspace notifications (uevents) and a call to a | ||
160 | notification chain (kernel) when there is a wireless transmitter | ||
161 | state change; | ||
162 | * Connects a wireless communications driver with the common rfkill | ||
163 | control system, which, for example, allows actions such as | ||
164 | "switch all bluetooth devices offline" to be carried out by | ||
165 | userspace or by rfkill-input. | ||
166 | |||
167 | THE RFKILL CLASS NEVER ISSUES INPUT EVENTS. THE RFKILL CLASS DOES | ||
168 | NOT LISTEN TO INPUT EVENTS. NO DRIVER USING THE RFKILL CLASS SHALL | ||
169 | EVER LISTEN TO, OR ACT ON RFKILL INPUT EVENTS. Doing otherwise is | ||
170 | a layering violation. | ||
171 | |||
172 | Most wireless data communication drivers in the kernel have just to | ||
173 | implement the rfkill class API to work properly. Interfacing to the | ||
174 | input layer is not often required (and is very often a *bug*) on | ||
175 | wireless drivers. | ||
176 | |||
177 | Platform drivers often have to attach to the input layer to *issue* | ||
178 | (but never to listen to) rfkill events for rfkill switches, and also to | ||
179 | the rfkill class to export a control interface for the platform rfkill | ||
180 | controllers to the rfkill subsystem. This does NOT mean the rfkill | ||
181 | switch is attached to a rfkill class (doing so is almost always wrong). | ||
182 | It just means the same kernel module is the driver for different | ||
183 | devices (rfkill switches and rfkill controllers). | ||
184 | |||
185 | |||
186 | Userspace input handlers (uevents) or kernel input handlers (rfkill-input): | ||
187 | |||
188 | * Implements the policy of what should happen when one of the input | ||
189 | layer events related to rfkill operation is received. | ||
190 | * Uses the sysfs interface (userspace) or private rfkill API calls | ||
191 | to tell the devices registered with the rfkill class to change | ||
192 | their state (i.e. translates the input layer event into real | ||
193 | action). | ||
194 | * rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0 | ||
195 | (power off all transmitters) in a special way: it ignores any | ||
196 | overrides and local state cache and forces all transmitters to the | ||
197 | RFKILL_STATE_SOFT_BLOCKED state (including those which are already | ||
198 | supposed to be BLOCKED). Note that the opposite event (power on all | ||
199 | transmitters) is handled normally. | ||
200 | |||
201 | Userspace uevent handler or kernel platform-specific drivers hooked to the | ||
202 | rfkill notifier chain: | ||
203 | |||
204 | * Taps into the rfkill notifier chain or to KOBJ_CHANGE uevents, | ||
205 | in order to know when a device that is registered with the rfkill | ||
206 | class changes state; | ||
207 | * Issues feedback notifications to the user; | ||
208 | * In the rare platforms where this is required, synthesizes an input | ||
209 | event to command all *OTHER* rfkill devices to also change their | ||
210 | statues when a specific rfkill device changes state. | ||
211 | |||
212 | |||
213 | =============================================================================== | ||
214 | 3: Kernel driver guidelines | ||
215 | |||
216 | Remember: point-of-view is everything for a driver that connects to the rfkill | ||
217 | subsystem. All the details below must be measured/perceived from the point of | ||
218 | view of the specific driver being modified. | ||
219 | |||
220 | The first thing one needs to know is whether his driver should be talking to | ||
221 | the rfkill class or to the input layer. In rare cases (platform drivers), it | ||
222 | could happen that you need to do both, as platform drivers often handle a | ||
223 | variety of devices in the same driver. | ||
224 | |||
225 | Do not mistake input devices for rfkill controllers. The only type of "rfkill | ||
226 | switch" device that is to be registered with the rfkill class are those | ||
227 | directly controlling the circuits that cause a wireless transmitter to stop | ||
228 | working (or the software equivalent of them), i.e. what we call a rfkill | ||
229 | controller. Every other kind of "rfkill switch" is just an input device and | ||
230 | MUST NOT be registered with the rfkill class. | ||
231 | |||
232 | A driver should register a device with the rfkill class when ALL of the | ||
233 | following conditions are met (they define a rfkill controller): | ||
234 | |||
235 | 1. The device is/controls a data communications wireless transmitter; | ||
236 | |||
237 | 2. The kernel can interact with the hardware/firmware to CHANGE the wireless | ||
238 | transmitter state (block/unblock TX operation); | ||
239 | |||
240 | 3. The transmitter can be made to not emit any energy when "blocked": | ||
241 | rfkill is not about blocking data transmissions, it is about blocking | ||
242 | energy emission; | ||
243 | |||
244 | A driver should register a device with the input subsystem to issue | ||
245 | rfkill-related events (KEY_WLAN, KEY_BLUETOOTH, KEY_WWAN, KEY_WIMAX, | ||
246 | SW_RFKILL_ALL, etc) when ALL of the folowing conditions are met: | ||
247 | |||
248 | 1. It is directly related to some physical device the user interacts with, to | ||
249 | command the O.S./firmware/hardware to enable/disable a data communications | ||
250 | wireless transmitter. | ||
251 | |||
252 | Examples of the physical device are: buttons, keys and switches the user | ||
253 | will press/touch/slide/switch to enable or disable the wireless | ||
254 | communication device. | ||
255 | |||
256 | 2. It is NOT slaved to another device, i.e. there is no other device that | ||
257 | issues rfkill-related input events in preference to this one. | ||
26 | 258 | ||
27 | The system inside the kernel has been split into 2 separate sections: | 259 | Please refer to the corner cases and examples section for more details. |
28 | 1 - RFKILL | ||
29 | 2 - RFKILL_INPUT | ||
30 | 260 | ||
31 | The first option enables rfkill support and will make sure userspace will | 261 | When in doubt, do not issue input events. For drivers that should generate |
32 | be notified of any events through the input device. It also creates several | 262 | input events in some platforms, but not in others (e.g. b43), the best solution |
33 | sysfs entries which can be used by userspace. See section "Userspace support". | 263 | is to NEVER generate input events in the first place. That work should be |
264 | deferred to a platform-specific kernel module (which will know when to generate | ||
265 | events through the rfkill notifier chain) or to userspace. This avoids the | ||
266 | usual maintenance problems with DMI whitelisting. | ||
34 | 267 | ||
35 | The second option provides an rfkill input handler. This handler will | ||
36 | listen to all rfkill key events and will toggle the radio accordingly. | ||
37 | With this option enabled userspace could either do nothing or simply | ||
38 | perform monitoring tasks. | ||
39 | 268 | ||
269 | Corner cases and examples: | ||
40 | ==================================== | 270 | ==================================== |
41 | 2: Driver support | ||
42 | 271 | ||
43 | To build a driver with rfkill subsystem support, the driver should | 272 | 1. If the device is an input device that, because of hardware or firmware, |
44 | depend on the Kconfig symbol RFKILL; it should _not_ depend on | 273 | causes wireless transmitters to be blocked regardless of the kernel's will, it |
45 | RKFILL_INPUT. | 274 | is still just an input device, and NOT to be registered with the rfkill class. |
46 | 275 | ||
47 | Unless key events trigger an interrupt to which the driver listens, polling | 276 | 2. If the wireless transmitter switch control is read-only, it is an input |
48 | will be required to determine the key state changes. For this the input | 277 | device and not to be registered with the rfkill class (and maybe not to be made |
49 | layer providers the input-polldev handler. | 278 | an input layer event source either, see below). |
50 | 279 | ||
51 | A driver should implement a few steps to correctly make use of the | 280 | 3. If there is some other device driver *closer* to the actual hardware the |
52 | rfkill subsystem. First for non-polling drivers: | 281 | user interacted with (the button/switch/key) to issue an input event, THAT is |
282 | the device driver that should be issuing input events. | ||
53 | 283 | ||
54 | - rfkill_allocate() | 284 | E.g: |
55 | - input_allocate_device() | 285 | [RFKILL slider switch] -- [GPIO hardware] -- [WLAN card rf-kill input] |
56 | - rfkill_register() | 286 | (platform driver) (wireless card driver) |
57 | - input_register_device() | 287 | |
288 | The user is closer to the RFKILL slide switch plaform driver, so the driver | ||
289 | which must issue input events is the platform driver looking at the GPIO | ||
290 | hardware, and NEVER the wireless card driver (which is just a slave). It is | ||
291 | very likely that there are other leaves than just the WLAN card rf-kill input | ||
292 | (e.g. a bluetooth card, etc)... | ||
293 | |||
294 | On the other hand, some embedded devices do this: | ||
295 | |||
296 | [RFKILL slider switch] -- [WLAN card rf-kill input] | ||
297 | (wireless card driver) | ||
298 | |||
299 | In this situation, the wireless card driver *could* register itself as an input | ||
300 | device and issue rf-kill related input events... but in order to AVOID the need | ||
301 | for DMI whitelisting, the wireless card driver does NOT do it. Userspace (HAL) | ||
302 | or a platform driver (that exists only on these embedded devices) will do the | ||
303 | dirty job of issuing the input events. | ||
304 | |||
305 | |||
306 | COMMON MISTAKES in kernel drivers, related to rfkill: | ||
307 | ==================================== | ||
308 | |||
309 | 1. NEVER confuse input device keys and buttons with input device switches. | ||
310 | |||
311 | 1a. Switches are always set or reset. They report the current state | ||
312 | (on position or off position). | ||
313 | |||
314 | 1b. Keys and buttons are either in the pressed or not-pressed state, and | ||
315 | that's it. A "button" that latches down when you press it, and | ||
316 | unlatches when you press it again is in fact a switch as far as input | ||
317 | devices go. | ||
318 | |||
319 | Add the SW_* events you need for switches, do NOT try to emulate a button using | ||
320 | KEY_* events just because there is no such SW_* event yet. Do NOT try to use, | ||
321 | for example, KEY_BLUETOOTH when you should be using SW_BLUETOOTH instead. | ||
322 | |||
323 | 2. Input device switches (sources of EV_SW events) DO store their current state | ||
324 | (so you *must* initialize it by issuing a gratuitous input layer event on | ||
325 | driver start-up and also when resuming from sleep), and that state CAN be | ||
326 | queried from userspace through IOCTLs. There is no sysfs interface for this, | ||
327 | but that doesn't mean you should break things trying to hook it to the rfkill | ||
328 | class to get a sysfs interface :-) | ||
329 | |||
330 | 3. Do not issue *_RFKILL_ALL events by default, unless you are sure it is the | ||
331 | correct event for your switch/button. These events are emergency power-off | ||
332 | events when they are trying to turn the transmitters off. An example of an | ||
333 | input device which SHOULD generate *_RFKILL_ALL events is the wireless-kill | ||
334 | switch in a laptop which is NOT a hotkey, but a real switch that kills radios | ||
335 | in hardware, even if the O.S. has gone to lunch. An example of an input device | ||
336 | which SHOULD NOT generate *_RFKILL_ALL events by default, is any sort of hot | ||
337 | key that does nothing by itself, as well as any hot key that is type-specific | ||
338 | (e.g. the one for WLAN). | ||
339 | |||
340 | |||
341 | 3.1 Guidelines for wireless device drivers | ||
342 | ------------------------------------------ | ||
343 | |||
344 | 1. Each independent transmitter in a wireless device (usually there is only one | ||
345 | transmitter per device) should have a SINGLE rfkill class attached to it. | ||
346 | |||
347 | 2. If the device does not have any sort of hardware assistance to allow the | ||
348 | driver to rfkill the device, the driver should emulate it by taking all actions | ||
349 | required to silence the transmitter. | ||
350 | |||
351 | 3. If it is impossible to silence the transmitter (i.e. it still emits energy, | ||
352 | even if it is just in brief pulses, when there is no data to transmit and there | ||
353 | is no hardware support to turn it off) do NOT lie to the users. Do not attach | ||
354 | it to a rfkill class. The rfkill subsystem does not deal with data | ||
355 | transmission, it deals with energy emission. If the transmitter is emitting | ||
356 | energy, it is not blocked in rfkill terms. | ||
357 | |||
358 | 4. It doesn't matter if the device has multiple rfkill input lines affecting | ||
359 | the same transmitter, their combined state is to be exported as a single state | ||
360 | per transmitter (see rule 1). | ||
361 | |||
362 | This rule exists because users of the rfkill subsystem expect to get (and set, | ||
363 | when possible) the overall transmitter rfkill state, not of a particular rfkill | ||
364 | line. | ||
365 | |||
366 | Example of a WLAN wireless driver connected to the rfkill subsystem: | ||
367 | -------------------------------------------------------------------- | ||
368 | |||
369 | A certain WLAN card has one input pin that causes it to block the transmitter | ||
370 | and makes the status of that input pin available (only for reading!) to the | ||
371 | kernel driver. This is a hard rfkill input line (it cannot be overridden by | ||
372 | the kernel driver). | ||
373 | |||
374 | The card also has one PCI register that, if manipulated by the driver, causes | ||
375 | it to block the transmitter. This is a soft rfkill input line. | ||
376 | |||
377 | It has also a thermal protection circuitry that shuts down its transmitter if | ||
378 | the card overheats, and makes the status of that protection available (only for | ||
379 | reading!) to the kernel driver. This is also a hard rfkill input line. | ||
380 | |||
381 | If either one of these rfkill lines are active, the transmitter is blocked by | ||
382 | the hardware and forced offline. | ||
383 | |||
384 | The driver should allocate and attach to its struct device *ONE* instance of | ||
385 | the rfkill class (there is only one transmitter). | ||
386 | |||
387 | It can implement the get_state() hook, and return RFKILL_STATE_HARD_BLOCKED if | ||
388 | either one of its two hard rfkill input lines are active. If the two hard | ||
389 | rfkill lines are inactive, it must return RFKILL_STATE_SOFT_BLOCKED if its soft | ||
390 | rfkill input line is active. Only if none of the rfkill input lines are | ||
391 | active, will it return RFKILL_STATE_UNBLOCKED. | ||
58 | 392 | ||
59 | For polling drivers: | 393 | If it doesn't implement the get_state() hook, it must make sure that its calls |
394 | to rfkill_force_state() are enough to keep the status always up-to-date, and it | ||
395 | must do a rfkill_force_state() on resume from sleep. | ||
60 | 396 | ||
397 | Every time the driver gets a notification from the card that one of its rfkill | ||
398 | lines changed state (polling might be needed on badly designed cards that don't | ||
399 | generate interrupts for such events), it recomputes the rfkill state as per | ||
400 | above, and calls rfkill_force_state() to update it. | ||
401 | |||
402 | The driver should implement the toggle_radio() hook, that: | ||
403 | |||
404 | 1. Returns an error if one of the hardware rfkill lines are active, and the | ||
405 | caller asked for RFKILL_STATE_UNBLOCKED. | ||
406 | |||
407 | 2. Activates the soft rfkill line if the caller asked for state | ||
408 | RFKILL_STATE_SOFT_BLOCKED. It should do this even if one of the hard rfkill | ||
409 | lines are active, effectively double-blocking the transmitter. | ||
410 | |||
411 | 3. Deactivates the soft rfkill line if none of the hardware rfkill lines are | ||
412 | active and the caller asked for RFKILL_STATE_UNBLOCKED. | ||
413 | |||
414 | =============================================================================== | ||
415 | 4: Kernel API | ||
416 | |||
417 | To build a driver with rfkill subsystem support, the driver should depend on | ||
418 | (or select) the Kconfig symbol RFKILL; it should _not_ depend on RKFILL_INPUT. | ||
419 | |||
420 | The hardware the driver talks to may be write-only (where the current state | ||
421 | of the hardware is unknown), or read-write (where the hardware can be queried | ||
422 | about its current state). | ||
423 | |||
424 | The rfkill class will call the get_state hook of a device every time it needs | ||
425 | to know the *real* current state of the hardware. This can happen often. | ||
426 | |||
427 | Some hardware provides events when its status changes. In these cases, it is | ||
428 | best for the driver to not provide a get_state hook, and instead register the | ||
429 | rfkill class *already* with the correct status, and keep it updated using | ||
430 | rfkill_force_state() when it gets an event from the hardware. | ||
431 | |||
432 | There is no provision for a statically-allocated rfkill struct. You must | ||
433 | use rfkill_allocate() to allocate one. | ||
434 | |||
435 | You should: | ||
61 | - rfkill_allocate() | 436 | - rfkill_allocate() |
62 | - input_allocate_polled_device() | 437 | - modify rfkill fields (flags, name) |
438 | - modify state to the current hardware state (THIS IS THE ONLY TIME | ||
439 | YOU CAN ACCESS state DIRECTLY) | ||
63 | - rfkill_register() | 440 | - rfkill_register() |
64 | - input_register_polled_device() | ||
65 | 441 | ||
66 | When a key event has been detected, the correct event should be | 442 | The only way to set a device to the RFKILL_STATE_HARD_BLOCKED state is through |
67 | sent over the input device which has been registered by the driver. | 443 | a suitable return of get_state() or through rfkill_force_state(). |
68 | 444 | ||
69 | ==================================== | 445 | When a device is in the RFKILL_STATE_HARD_BLOCKED state, the only way to switch |
70 | 3: Userspace support | 446 | it to a different state is through a suitable return of get_state() or through |
447 | rfkill_force_state(). | ||
448 | |||
449 | If toggle_radio() is called to set a device to state RFKILL_STATE_SOFT_BLOCKED | ||
450 | when that device is already at the RFKILL_STATE_HARD_BLOCKED state, it should | ||
451 | not return an error. Instead, it should try to double-block the transmitter, | ||
452 | so that its state will change from RFKILL_STATE_HARD_BLOCKED to | ||
453 | RFKILL_STATE_SOFT_BLOCKED should the hardware blocking cease. | ||
71 | 454 | ||
72 | For each key an input device will be created which will send out the correct | 455 | Please refer to the source for more documentation. |
73 | key event when the rfkill key has been pressed. | 456 | |
457 | =============================================================================== | ||
458 | 5: Userspace support | ||
459 | |||
460 | rfkill devices issue uevents (with an action of "change"), with the following | ||
461 | environment variables set: | ||
462 | |||
463 | RFKILL_NAME | ||
464 | RFKILL_STATE | ||
465 | RFKILL_TYPE | ||
466 | |||
467 | The ABI for these variables is defined by the sysfs attributes. It is best | ||
468 | to take a quick look at the source to make sure of the possible values. | ||
469 | |||
470 | It is expected that HAL will trap those, and bridge them to DBUS, etc. These | ||
471 | events CAN and SHOULD be used to give feedback to the user about the rfkill | ||
472 | status of the system. | ||
473 | |||
474 | Input devices may issue events that are related to rfkill. These are the | ||
475 | various KEY_* events and SW_* events supported by rfkill-input.c. | ||
476 | |||
477 | ******IMPORTANT****** | ||
478 | When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL | ||
479 | SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it | ||
480 | has set to true the user_claim attribute for that particular switch. This rule | ||
481 | is *absolute*; do NOT violate it. | ||
482 | ******IMPORTANT****** | ||
483 | |||
484 | Userspace must not assume it is the only source of control for rfkill switches. | ||
485 | Their state CAN and WILL change due to firmware actions, direct user actions, | ||
486 | and the rfkill-input EPO override for *_RFKILL_ALL. | ||
487 | |||
488 | When rfkill-input is not active, userspace must initiate a rfkill status | ||
489 | change by writing to the "state" attribute in order for anything to happen. | ||
490 | |||
491 | Take particular care to implement EV_SW SW_RFKILL_ALL properly. When that | ||
492 | switch is set to OFF, *every* rfkill device *MUST* be immediately put into the | ||
493 | RFKILL_STATE_SOFT_BLOCKED state, no questions asked. | ||
74 | 494 | ||
75 | The following sysfs entries will be created: | 495 | The following sysfs entries will be created: |
76 | 496 | ||
77 | name: Name assigned by driver to this key (interface or driver name). | 497 | name: Name assigned by driver to this key (interface or driver name). |
78 | type: Name of the key type ("wlan", "bluetooth", etc). | 498 | type: Name of the key type ("wlan", "bluetooth", etc). |
79 | state: Current state of the key. 1: On, 0: Off. | 499 | state: Current state of the transmitter |
500 | 0: RFKILL_STATE_SOFT_BLOCKED | ||
501 | transmitter is forced off, but one can override it | ||
502 | by a write to the state attribute; | ||
503 | 1: RFKILL_STATE_UNBLOCKED | ||
504 | transmiter is NOT forced off, and may operate if | ||
505 | all other conditions for such operation are met | ||
506 | (such as interface is up and configured, etc); | ||
507 | 2: RFKILL_STATE_HARD_BLOCKED | ||
508 | transmitter is forced off by something outside of | ||
509 | the driver's control. One cannot set a device to | ||
510 | this state through writes to the state attribute; | ||
80 | claim: 1: Userspace handles events, 0: Kernel handles events | 511 | claim: 1: Userspace handles events, 0: Kernel handles events |
81 | 512 | ||
82 | Both the "state" and "claim" entries are also writable. For the "state" entry | 513 | Both the "state" and "claim" entries are also writable. For the "state" entry |
83 | this means that when 1 or 0 is written all radios, not yet in the requested | 514 | this means that when 1 or 0 is written, the device rfkill state (if not yet in |
84 | state, will be will be toggled accordingly. | 515 | the requested state), will be will be toggled accordingly. |
516 | |||
85 | For the "claim" entry writing 1 to it means that the kernel no longer handles | 517 | For the "claim" entry writing 1 to it means that the kernel no longer handles |
86 | key events even though RFKILL_INPUT input was enabled. When "claim" has been | 518 | key events even though RFKILL_INPUT input was enabled. When "claim" has been |
87 | set to 0, userspace should make sure that it listens for the input events or | 519 | set to 0, userspace should make sure that it listens for the input events or |
88 | check the sysfs "state" entry regularly to correctly perform the required | 520 | check the sysfs "state" entry regularly to correctly perform the required tasks |
89 | tasks when the rkfill key is pressed. | 521 | when the rkfill key is pressed. |
522 | |||
523 | A note about input devices and EV_SW events: | ||
524 | |||
525 | In order to know the current state of an input device switch (like | ||
526 | SW_RFKILL_ALL), you will need to use an IOCTL. That information is not | ||
527 | available through sysfs in a generic way at this time, and it is not available | ||
528 | through the rfkill class AT ALL. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index d0ea6ec2552f..5ae19d502e0b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3854,10 +3854,6 @@ P: Ion Badulescu | |||
3854 | M: ionut@cs.columbia.edu | 3854 | M: ionut@cs.columbia.edu |
3855 | S: Maintained | 3855 | S: Maintained |
3856 | 3856 | ||
3857 | STARMODE RADIO IP (STRIP) PROTOCOL DRIVER | ||
3858 | W: http://mosquitonet.Stanford.EDU/strip.html | ||
3859 | S: Unsupported ? | ||
3860 | |||
3861 | STRADIS MPEG-2 DECODER DRIVER | 3857 | STRADIS MPEG-2 DECODER DRIVER |
3862 | P: Nathan Laredo | 3858 | P: Nathan Laredo |
3863 | M: laredo@gnu.org | 3859 | M: laredo@gnu.org |
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 59dce6aa0865..c3bda5ce67c4 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -148,9 +148,9 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev, | |||
148 | unsigned long offset, | 148 | unsigned long offset, |
149 | enum dma_data_direction dir) | 149 | enum dma_data_direction dir) |
150 | { | 150 | { |
151 | dma_sync_single_range_for_device(sdev->dma_dev, dma_base, | 151 | ssb_dma_sync_single_range_for_device(sdev, dma_base, |
152 | offset & dma_desc_align_mask, | 152 | offset & dma_desc_align_mask, |
153 | dma_desc_sync_size, dir); | 153 | dma_desc_sync_size, dir); |
154 | } | 154 | } |
155 | 155 | ||
156 | static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, | 156 | static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, |
@@ -158,9 +158,9 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, | |||
158 | unsigned long offset, | 158 | unsigned long offset, |
159 | enum dma_data_direction dir) | 159 | enum dma_data_direction dir) |
160 | { | 160 | { |
161 | dma_sync_single_range_for_cpu(sdev->dma_dev, dma_base, | 161 | ssb_dma_sync_single_range_for_cpu(sdev, dma_base, |
162 | offset & dma_desc_align_mask, | 162 | offset & dma_desc_align_mask, |
163 | dma_desc_sync_size, dir); | 163 | dma_desc_sync_size, dir); |
164 | } | 164 | } |
165 | 165 | ||
166 | static inline unsigned long br32(const struct b44 *bp, unsigned long reg) | 166 | static inline unsigned long br32(const struct b44 *bp, unsigned long reg) |
@@ -613,10 +613,10 @@ static void b44_tx(struct b44 *bp) | |||
613 | 613 | ||
614 | BUG_ON(skb == NULL); | 614 | BUG_ON(skb == NULL); |
615 | 615 | ||
616 | dma_unmap_single(bp->sdev->dma_dev, | 616 | ssb_dma_unmap_single(bp->sdev, |
617 | rp->mapping, | 617 | rp->mapping, |
618 | skb->len, | 618 | skb->len, |
619 | DMA_TO_DEVICE); | 619 | DMA_TO_DEVICE); |
620 | rp->skb = NULL; | 620 | rp->skb = NULL; |
621 | dev_kfree_skb_irq(skb); | 621 | dev_kfree_skb_irq(skb); |
622 | } | 622 | } |
@@ -653,29 +653,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) | |||
653 | if (skb == NULL) | 653 | if (skb == NULL) |
654 | return -ENOMEM; | 654 | return -ENOMEM; |
655 | 655 | ||
656 | mapping = dma_map_single(bp->sdev->dma_dev, skb->data, | 656 | mapping = ssb_dma_map_single(bp->sdev, skb->data, |
657 | RX_PKT_BUF_SZ, | 657 | RX_PKT_BUF_SZ, |
658 | DMA_FROM_DEVICE); | 658 | DMA_FROM_DEVICE); |
659 | 659 | ||
660 | /* Hardware bug work-around, the chip is unable to do PCI DMA | 660 | /* Hardware bug work-around, the chip is unable to do PCI DMA |
661 | to/from anything above 1GB :-( */ | 661 | to/from anything above 1GB :-( */ |
662 | if (dma_mapping_error(mapping) || | 662 | if (ssb_dma_mapping_error(bp->sdev, mapping) || |
663 | mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) { | 663 | mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) { |
664 | /* Sigh... */ | 664 | /* Sigh... */ |
665 | if (!dma_mapping_error(mapping)) | 665 | if (!ssb_dma_mapping_error(bp->sdev, mapping)) |
666 | dma_unmap_single(bp->sdev->dma_dev, mapping, | 666 | ssb_dma_unmap_single(bp->sdev, mapping, |
667 | RX_PKT_BUF_SZ, DMA_FROM_DEVICE); | 667 | RX_PKT_BUF_SZ, DMA_FROM_DEVICE); |
668 | dev_kfree_skb_any(skb); | 668 | dev_kfree_skb_any(skb); |
669 | skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); | 669 | skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); |
670 | if (skb == NULL) | 670 | if (skb == NULL) |
671 | return -ENOMEM; | 671 | return -ENOMEM; |
672 | mapping = dma_map_single(bp->sdev->dma_dev, skb->data, | 672 | mapping = ssb_dma_map_single(bp->sdev, skb->data, |
673 | RX_PKT_BUF_SZ, | 673 | RX_PKT_BUF_SZ, |
674 | DMA_FROM_DEVICE); | 674 | DMA_FROM_DEVICE); |
675 | if (dma_mapping_error(mapping) || | 675 | if (ssb_dma_mapping_error(bp->sdev, mapping) || |
676 | mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) { | 676 | mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) { |
677 | if (!dma_mapping_error(mapping)) | 677 | if (!ssb_dma_mapping_error(bp->sdev, mapping)) |
678 | dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); | 678 | ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); |
679 | dev_kfree_skb_any(skb); | 679 | dev_kfree_skb_any(skb); |
680 | return -ENOMEM; | 680 | return -ENOMEM; |
681 | } | 681 | } |
@@ -750,9 +750,9 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) | |||
750 | dest_idx * sizeof(dest_desc), | 750 | dest_idx * sizeof(dest_desc), |
751 | DMA_BIDIRECTIONAL); | 751 | DMA_BIDIRECTIONAL); |
752 | 752 | ||
753 | dma_sync_single_for_device(bp->sdev->dma_dev, le32_to_cpu(src_desc->addr), | 753 | ssb_dma_sync_single_for_device(bp->sdev, le32_to_cpu(src_desc->addr), |
754 | RX_PKT_BUF_SZ, | 754 | RX_PKT_BUF_SZ, |
755 | DMA_FROM_DEVICE); | 755 | DMA_FROM_DEVICE); |
756 | } | 756 | } |
757 | 757 | ||
758 | static int b44_rx(struct b44 *bp, int budget) | 758 | static int b44_rx(struct b44 *bp, int budget) |
@@ -772,7 +772,7 @@ static int b44_rx(struct b44 *bp, int budget) | |||
772 | struct rx_header *rh; | 772 | struct rx_header *rh; |
773 | u16 len; | 773 | u16 len; |
774 | 774 | ||
775 | dma_sync_single_for_cpu(bp->sdev->dma_dev, map, | 775 | ssb_dma_sync_single_for_cpu(bp->sdev, map, |
776 | RX_PKT_BUF_SZ, | 776 | RX_PKT_BUF_SZ, |
777 | DMA_FROM_DEVICE); | 777 | DMA_FROM_DEVICE); |
778 | rh = (struct rx_header *) skb->data; | 778 | rh = (struct rx_header *) skb->data; |
@@ -806,8 +806,8 @@ static int b44_rx(struct b44 *bp, int budget) | |||
806 | skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); | 806 | skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); |
807 | if (skb_size < 0) | 807 | if (skb_size < 0) |
808 | goto drop_it; | 808 | goto drop_it; |
809 | dma_unmap_single(bp->sdev->dma_dev, map, | 809 | ssb_dma_unmap_single(bp->sdev, map, |
810 | skb_size, DMA_FROM_DEVICE); | 810 | skb_size, DMA_FROM_DEVICE); |
811 | /* Leave out rx_header */ | 811 | /* Leave out rx_header */ |
812 | skb_put(skb, len + RX_PKT_OFFSET); | 812 | skb_put(skb, len + RX_PKT_OFFSET); |
813 | skb_pull(skb, RX_PKT_OFFSET); | 813 | skb_pull(skb, RX_PKT_OFFSET); |
@@ -966,25 +966,25 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
966 | goto err_out; | 966 | goto err_out; |
967 | } | 967 | } |
968 | 968 | ||
969 | mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE); | 969 | mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE); |
970 | if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { | 970 | if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_30BIT_MASK) { |
971 | struct sk_buff *bounce_skb; | 971 | struct sk_buff *bounce_skb; |
972 | 972 | ||
973 | /* Chip can't handle DMA to/from >1GB, use bounce buffer */ | 973 | /* Chip can't handle DMA to/from >1GB, use bounce buffer */ |
974 | if (!dma_mapping_error(mapping)) | 974 | if (!ssb_dma_mapping_error(bp->sdev, mapping)) |
975 | dma_unmap_single(bp->sdev->dma_dev, mapping, len, | 975 | ssb_dma_unmap_single(bp->sdev, mapping, len, |
976 | DMA_TO_DEVICE); | 976 | DMA_TO_DEVICE); |
977 | 977 | ||
978 | bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA); | 978 | bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA); |
979 | if (!bounce_skb) | 979 | if (!bounce_skb) |
980 | goto err_out; | 980 | goto err_out; |
981 | 981 | ||
982 | mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data, | 982 | mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data, |
983 | len, DMA_TO_DEVICE); | 983 | len, DMA_TO_DEVICE); |
984 | if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { | 984 | if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_30BIT_MASK) { |
985 | if (!dma_mapping_error(mapping)) | 985 | if (!ssb_dma_mapping_error(bp->sdev, mapping)) |
986 | dma_unmap_single(bp->sdev->dma_dev, mapping, | 986 | ssb_dma_unmap_single(bp->sdev, mapping, |
987 | len, DMA_TO_DEVICE); | 987 | len, DMA_TO_DEVICE); |
988 | dev_kfree_skb_any(bounce_skb); | 988 | dev_kfree_skb_any(bounce_skb); |
989 | goto err_out; | 989 | goto err_out; |
990 | } | 990 | } |
@@ -1082,8 +1082,8 @@ static void b44_free_rings(struct b44 *bp) | |||
1082 | 1082 | ||
1083 | if (rp->skb == NULL) | 1083 | if (rp->skb == NULL) |
1084 | continue; | 1084 | continue; |
1085 | dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ, | 1085 | ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ, |
1086 | DMA_FROM_DEVICE); | 1086 | DMA_FROM_DEVICE); |
1087 | dev_kfree_skb_any(rp->skb); | 1087 | dev_kfree_skb_any(rp->skb); |
1088 | rp->skb = NULL; | 1088 | rp->skb = NULL; |
1089 | } | 1089 | } |
@@ -1094,8 +1094,8 @@ static void b44_free_rings(struct b44 *bp) | |||
1094 | 1094 | ||
1095 | if (rp->skb == NULL) | 1095 | if (rp->skb == NULL) |
1096 | continue; | 1096 | continue; |
1097 | dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len, | 1097 | ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len, |
1098 | DMA_TO_DEVICE); | 1098 | DMA_TO_DEVICE); |
1099 | dev_kfree_skb_any(rp->skb); | 1099 | dev_kfree_skb_any(rp->skb); |
1100 | rp->skb = NULL; | 1100 | rp->skb = NULL; |
1101 | } | 1101 | } |
@@ -1117,14 +1117,14 @@ static void b44_init_rings(struct b44 *bp) | |||
1117 | memset(bp->tx_ring, 0, B44_TX_RING_BYTES); | 1117 | memset(bp->tx_ring, 0, B44_TX_RING_BYTES); |
1118 | 1118 | ||
1119 | if (bp->flags & B44_FLAG_RX_RING_HACK) | 1119 | if (bp->flags & B44_FLAG_RX_RING_HACK) |
1120 | dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma, | 1120 | ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma, |
1121 | DMA_TABLE_BYTES, | 1121 | DMA_TABLE_BYTES, |
1122 | DMA_BIDIRECTIONAL); | 1122 | DMA_BIDIRECTIONAL); |
1123 | 1123 | ||
1124 | if (bp->flags & B44_FLAG_TX_RING_HACK) | 1124 | if (bp->flags & B44_FLAG_TX_RING_HACK) |
1125 | dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma, | 1125 | ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma, |
1126 | DMA_TABLE_BYTES, | 1126 | DMA_TABLE_BYTES, |
1127 | DMA_TO_DEVICE); | 1127 | DMA_TO_DEVICE); |
1128 | 1128 | ||
1129 | for (i = 0; i < bp->rx_pending; i++) { | 1129 | for (i = 0; i < bp->rx_pending; i++) { |
1130 | if (b44_alloc_rx_skb(bp, -1, i) < 0) | 1130 | if (b44_alloc_rx_skb(bp, -1, i) < 0) |
@@ -1144,25 +1144,27 @@ static void b44_free_consistent(struct b44 *bp) | |||
1144 | bp->tx_buffers = NULL; | 1144 | bp->tx_buffers = NULL; |
1145 | if (bp->rx_ring) { | 1145 | if (bp->rx_ring) { |
1146 | if (bp->flags & B44_FLAG_RX_RING_HACK) { | 1146 | if (bp->flags & B44_FLAG_RX_RING_HACK) { |
1147 | dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma, | 1147 | ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma, |
1148 | DMA_TABLE_BYTES, | 1148 | DMA_TABLE_BYTES, |
1149 | DMA_BIDIRECTIONAL); | 1149 | DMA_BIDIRECTIONAL); |
1150 | kfree(bp->rx_ring); | 1150 | kfree(bp->rx_ring); |
1151 | } else | 1151 | } else |
1152 | dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES, | 1152 | ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES, |
1153 | bp->rx_ring, bp->rx_ring_dma); | 1153 | bp->rx_ring, bp->rx_ring_dma, |
1154 | GFP_KERNEL); | ||
1154 | bp->rx_ring = NULL; | 1155 | bp->rx_ring = NULL; |
1155 | bp->flags &= ~B44_FLAG_RX_RING_HACK; | 1156 | bp->flags &= ~B44_FLAG_RX_RING_HACK; |
1156 | } | 1157 | } |
1157 | if (bp->tx_ring) { | 1158 | if (bp->tx_ring) { |
1158 | if (bp->flags & B44_FLAG_TX_RING_HACK) { | 1159 | if (bp->flags & B44_FLAG_TX_RING_HACK) { |
1159 | dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma, | 1160 | ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma, |
1160 | DMA_TABLE_BYTES, | 1161 | DMA_TABLE_BYTES, |
1161 | DMA_TO_DEVICE); | 1162 | DMA_TO_DEVICE); |
1162 | kfree(bp->tx_ring); | 1163 | kfree(bp->tx_ring); |
1163 | } else | 1164 | } else |
1164 | dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES, | 1165 | ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES, |
1165 | bp->tx_ring, bp->tx_ring_dma); | 1166 | bp->tx_ring, bp->tx_ring_dma, |
1167 | GFP_KERNEL); | ||
1166 | bp->tx_ring = NULL; | 1168 | bp->tx_ring = NULL; |
1167 | bp->flags &= ~B44_FLAG_TX_RING_HACK; | 1169 | bp->flags &= ~B44_FLAG_TX_RING_HACK; |
1168 | } | 1170 | } |
@@ -1187,7 +1189,7 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) | |||
1187 | goto out_err; | 1189 | goto out_err; |
1188 | 1190 | ||
1189 | size = DMA_TABLE_BYTES; | 1191 | size = DMA_TABLE_BYTES; |
1190 | bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, &bp->rx_ring_dma, gfp); | 1192 | bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp); |
1191 | if (!bp->rx_ring) { | 1193 | if (!bp->rx_ring) { |
1192 | /* Allocation may have failed due to pci_alloc_consistent | 1194 | /* Allocation may have failed due to pci_alloc_consistent |
1193 | insisting on use of GFP_DMA, which is more restrictive | 1195 | insisting on use of GFP_DMA, which is more restrictive |
@@ -1199,11 +1201,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) | |||
1199 | if (!rx_ring) | 1201 | if (!rx_ring) |
1200 | goto out_err; | 1202 | goto out_err; |
1201 | 1203 | ||
1202 | rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring, | 1204 | rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring, |
1203 | DMA_TABLE_BYTES, | 1205 | DMA_TABLE_BYTES, |
1204 | DMA_BIDIRECTIONAL); | 1206 | DMA_BIDIRECTIONAL); |
1205 | 1207 | ||
1206 | if (dma_mapping_error(rx_ring_dma) || | 1208 | if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) || |
1207 | rx_ring_dma + size > DMA_30BIT_MASK) { | 1209 | rx_ring_dma + size > DMA_30BIT_MASK) { |
1208 | kfree(rx_ring); | 1210 | kfree(rx_ring); |
1209 | goto out_err; | 1211 | goto out_err; |
@@ -1214,9 +1216,9 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) | |||
1214 | bp->flags |= B44_FLAG_RX_RING_HACK; | 1216 | bp->flags |= B44_FLAG_RX_RING_HACK; |
1215 | } | 1217 | } |
1216 | 1218 | ||
1217 | bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, &bp->tx_ring_dma, gfp); | 1219 | bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp); |
1218 | if (!bp->tx_ring) { | 1220 | if (!bp->tx_ring) { |
1219 | /* Allocation may have failed due to dma_alloc_coherent | 1221 | /* Allocation may have failed due to ssb_dma_alloc_consistent |
1220 | insisting on use of GFP_DMA, which is more restrictive | 1222 | insisting on use of GFP_DMA, which is more restrictive |
1221 | than necessary... */ | 1223 | than necessary... */ |
1222 | struct dma_desc *tx_ring; | 1224 | struct dma_desc *tx_ring; |
@@ -1226,11 +1228,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) | |||
1226 | if (!tx_ring) | 1228 | if (!tx_ring) |
1227 | goto out_err; | 1229 | goto out_err; |
1228 | 1230 | ||
1229 | tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring, | 1231 | tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring, |
1230 | DMA_TABLE_BYTES, | 1232 | DMA_TABLE_BYTES, |
1231 | DMA_TO_DEVICE); | 1233 | DMA_TO_DEVICE); |
1232 | 1234 | ||
1233 | if (dma_mapping_error(tx_ring_dma) || | 1235 | if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) || |
1234 | tx_ring_dma + size > DMA_30BIT_MASK) { | 1236 | tx_ring_dma + size > DMA_30BIT_MASK) { |
1235 | kfree(tx_ring); | 1237 | kfree(tx_ring); |
1236 | goto out_err; | 1238 | goto out_err; |
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index aa963ac1e37b..6b2dee0cf3a9 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c | |||
@@ -571,6 +571,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len, | |||
571 | * independent format | 571 | * independent format |
572 | */ | 572 | */ |
573 | static char *gelic_wl_translate_scan(struct net_device *netdev, | 573 | static char *gelic_wl_translate_scan(struct net_device *netdev, |
574 | struct iw_request_info *info, | ||
574 | char *ev, | 575 | char *ev, |
575 | char *stop, | 576 | char *stop, |
576 | struct gelic_wl_scan_info *network) | 577 | struct gelic_wl_scan_info *network) |
@@ -588,26 +589,26 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, | |||
588 | iwe.cmd = SIOCGIWAP; | 589 | iwe.cmd = SIOCGIWAP; |
589 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 590 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
590 | memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN); | 591 | memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN); |
591 | ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_ADDR_LEN); | 592 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_ADDR_LEN); |
592 | 593 | ||
593 | /* ESSID */ | 594 | /* ESSID */ |
594 | iwe.cmd = SIOCGIWESSID; | 595 | iwe.cmd = SIOCGIWESSID; |
595 | iwe.u.data.flags = 1; | 596 | iwe.u.data.flags = 1; |
596 | iwe.u.data.length = strnlen(scan->essid, 32); | 597 | iwe.u.data.length = strnlen(scan->essid, 32); |
597 | ev = iwe_stream_add_point(ev, stop, &iwe, scan->essid); | 598 | ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); |
598 | 599 | ||
599 | /* FREQUENCY */ | 600 | /* FREQUENCY */ |
600 | iwe.cmd = SIOCGIWFREQ; | 601 | iwe.cmd = SIOCGIWFREQ; |
601 | iwe.u.freq.m = be16_to_cpu(scan->channel); | 602 | iwe.u.freq.m = be16_to_cpu(scan->channel); |
602 | iwe.u.freq.e = 0; /* table value in MHz */ | 603 | iwe.u.freq.e = 0; /* table value in MHz */ |
603 | iwe.u.freq.i = 0; | 604 | iwe.u.freq.i = 0; |
604 | ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_FREQ_LEN); | 605 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_FREQ_LEN); |
605 | 606 | ||
606 | /* RATES */ | 607 | /* RATES */ |
607 | iwe.cmd = SIOCGIWRATE; | 608 | iwe.cmd = SIOCGIWRATE; |
608 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | 609 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; |
609 | /* to stuff multiple values in one event */ | 610 | /* to stuff multiple values in one event */ |
610 | tmp = ev + IW_EV_LCP_LEN; | 611 | tmp = ev + iwe_stream_lcp_len(info); |
611 | /* put them in ascendant order (older is first) */ | 612 | /* put them in ascendant order (older is first) */ |
612 | i = 0; | 613 | i = 0; |
613 | j = 0; | 614 | j = 0; |
@@ -620,16 +621,16 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, | |||
620 | else | 621 | else |
621 | rate = scan->rate[i++] & 0x7f; | 622 | rate = scan->rate[i++] & 0x7f; |
622 | iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */ | 623 | iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */ |
623 | tmp = iwe_stream_add_value(ev, tmp, stop, &iwe, | 624 | tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, |
624 | IW_EV_PARAM_LEN); | 625 | IW_EV_PARAM_LEN); |
625 | } | 626 | } |
626 | while (j < network->rate_ext_len) { | 627 | while (j < network->rate_ext_len) { |
627 | iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000; | 628 | iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000; |
628 | tmp = iwe_stream_add_value(ev, tmp, stop, &iwe, | 629 | tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, |
629 | IW_EV_PARAM_LEN); | 630 | IW_EV_PARAM_LEN); |
630 | } | 631 | } |
631 | /* Check if we added any rate */ | 632 | /* Check if we added any rate */ |
632 | if (IW_EV_LCP_LEN < (tmp - ev)) | 633 | if (iwe_stream_lcp_len(info) < (tmp - ev)) |
633 | ev = tmp; | 634 | ev = tmp; |
634 | 635 | ||
635 | /* ENCODE */ | 636 | /* ENCODE */ |
@@ -639,7 +640,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, | |||
639 | else | 640 | else |
640 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 641 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
641 | iwe.u.data.length = 0; | 642 | iwe.u.data.length = 0; |
642 | ev = iwe_stream_add_point(ev, stop, &iwe, scan->essid); | 643 | ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); |
643 | 644 | ||
644 | /* MODE */ | 645 | /* MODE */ |
645 | iwe.cmd = SIOCGIWMODE; | 646 | iwe.cmd = SIOCGIWMODE; |
@@ -649,7 +650,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, | |||
649 | iwe.u.mode = IW_MODE_MASTER; | 650 | iwe.u.mode = IW_MODE_MASTER; |
650 | else | 651 | else |
651 | iwe.u.mode = IW_MODE_ADHOC; | 652 | iwe.u.mode = IW_MODE_ADHOC; |
652 | ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_UINT_LEN); | 653 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_UINT_LEN); |
653 | } | 654 | } |
654 | 655 | ||
655 | /* QUAL */ | 656 | /* QUAL */ |
@@ -659,7 +660,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, | |||
659 | iwe.u.qual.level = be16_to_cpu(scan->rssi); | 660 | iwe.u.qual.level = be16_to_cpu(scan->rssi); |
660 | iwe.u.qual.qual = be16_to_cpu(scan->rssi); | 661 | iwe.u.qual.qual = be16_to_cpu(scan->rssi); |
661 | iwe.u.qual.noise = 0; | 662 | iwe.u.qual.noise = 0; |
662 | ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_QUAL_LEN); | 663 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_QUAL_LEN); |
663 | 664 | ||
664 | /* RSN */ | 665 | /* RSN */ |
665 | memset(&iwe, 0, sizeof(iwe)); | 666 | memset(&iwe, 0, sizeof(iwe)); |
@@ -669,7 +670,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, | |||
669 | if (len) { | 670 | if (len) { |
670 | iwe.cmd = IWEVGENIE; | 671 | iwe.cmd = IWEVGENIE; |
671 | iwe.u.data.length = len; | 672 | iwe.u.data.length = len; |
672 | ev = iwe_stream_add_point(ev, stop, &iwe, buf); | 673 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); |
673 | } | 674 | } |
674 | } else { | 675 | } else { |
675 | /* this scan info has IE data */ | 676 | /* this scan info has IE data */ |
@@ -684,7 +685,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, | |||
684 | memcpy(buf, ie_info.wpa.data, ie_info.wpa.len); | 685 | memcpy(buf, ie_info.wpa.data, ie_info.wpa.len); |
685 | iwe.cmd = IWEVGENIE; | 686 | iwe.cmd = IWEVGENIE; |
686 | iwe.u.data.length = ie_info.wpa.len; | 687 | iwe.u.data.length = ie_info.wpa.len; |
687 | ev = iwe_stream_add_point(ev, stop, &iwe, buf); | 688 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); |
688 | } | 689 | } |
689 | 690 | ||
690 | if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) { | 691 | if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) { |
@@ -692,7 +693,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, | |||
692 | memcpy(buf, ie_info.rsn.data, ie_info.rsn.len); | 693 | memcpy(buf, ie_info.rsn.data, ie_info.rsn.len); |
693 | iwe.cmd = IWEVGENIE; | 694 | iwe.cmd = IWEVGENIE; |
694 | iwe.u.data.length = ie_info.rsn.len; | 695 | iwe.u.data.length = ie_info.rsn.len; |
695 | ev = iwe_stream_add_point(ev, stop, &iwe, buf); | 696 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); |
696 | } | 697 | } |
697 | } | 698 | } |
698 | 699 | ||
@@ -737,7 +738,8 @@ static int gelic_wl_get_scan(struct net_device *netdev, | |||
737 | if (wl->scan_age == 0 || | 738 | if (wl->scan_age == 0 || |
738 | time_after(scan_info->last_scanned + wl->scan_age, | 739 | time_after(scan_info->last_scanned + wl->scan_age, |
739 | this_time)) | 740 | this_time)) |
740 | ev = gelic_wl_translate_scan(netdev, ev, stop, | 741 | ev = gelic_wl_translate_scan(netdev, info, |
742 | ev, stop, | ||
741 | scan_info); | 743 | scan_info); |
742 | else | 744 | else |
743 | pr_debug("%s:entry too old\n", __func__); | 745 | pr_debug("%s:entry too old\n", __func__); |
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 22e1e9a1fb73..865f2980c273 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -14,30 +14,6 @@ config WLAN_PRE80211 | |||
14 | This option does not affect the kernel build, it only | 14 | This option does not affect the kernel build, it only |
15 | lets you choose drivers. | 15 | lets you choose drivers. |
16 | 16 | ||
17 | config STRIP | ||
18 | tristate "STRIP (Metricom starmode radio IP)" | ||
19 | depends on INET && WLAN_PRE80211 | ||
20 | select WIRELESS_EXT | ||
21 | ---help--- | ||
22 | Say Y if you have a Metricom radio and intend to use Starmode Radio | ||
23 | IP. STRIP is a radio protocol developed for the MosquitoNet project | ||
24 | (on the WWW at <http://mosquitonet.stanford.edu/>) to send Internet | ||
25 | traffic using Metricom radios. Metricom radios are small, battery | ||
26 | powered, 100kbit/sec packet radio transceivers, about the size and | ||
27 | weight of a cellular telephone. (You may also have heard them called | ||
28 | "Metricom modems" but we avoid the term "modem" because it misleads | ||
29 | many people into thinking that you can plug a Metricom modem into a | ||
30 | phone line and use it as a modem.) | ||
31 | |||
32 | You can use STRIP on any Linux machine with a serial port, although | ||
33 | it is obviously most useful for people with laptop computers. If you | ||
34 | think you might get a Metricom radio in the future, there is no harm | ||
35 | in saying Y to STRIP now, except that it makes the kernel a bit | ||
36 | bigger. | ||
37 | |||
38 | To compile this as a module, choose M here: the module will be | ||
39 | called strip. | ||
40 | |||
41 | config ARLAN | 17 | config ARLAN |
42 | tristate "Aironet Arlan 655 & IC2200 DS support" | 18 | tristate "Aironet Arlan 655 & IC2200 DS support" |
43 | depends on ISA && !64BIT && WLAN_PRE80211 | 19 | depends on ISA && !64BIT && WLAN_PRE80211 |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 54a4f6f1db67..2668934abbff 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -6,7 +6,6 @@ obj-$(CONFIG_IPW2100) += ipw2100.o | |||
6 | 6 | ||
7 | obj-$(CONFIG_IPW2200) += ipw2200.o | 7 | obj-$(CONFIG_IPW2200) += ipw2200.o |
8 | 8 | ||
9 | obj-$(CONFIG_STRIP) += strip.o | ||
10 | obj-$(CONFIG_ARLAN) += arlan.o | 9 | obj-$(CONFIG_ARLAN) += arlan.o |
11 | 10 | ||
12 | arlan-objs := arlan-main.o arlan-proc.o | 11 | arlan-objs := arlan-main.o arlan-proc.o |
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 0ba55ba93958..3333d4596b8d 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1685,7 +1685,6 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
1685 | static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | 1685 | static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) |
1686 | { | 1686 | { |
1687 | struct adm8211_tx_hdr *txhdr; | 1687 | struct adm8211_tx_hdr *txhdr; |
1688 | u16 fc; | ||
1689 | size_t payload_len, hdrlen; | 1688 | size_t payload_len, hdrlen; |
1690 | int plcp, dur, len, plcp_signal, short_preamble; | 1689 | int plcp, dur, len, plcp_signal, short_preamble; |
1691 | struct ieee80211_hdr *hdr; | 1690 | struct ieee80211_hdr *hdr; |
@@ -1696,8 +1695,7 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1696 | plcp_signal = txrate->bitrate; | 1695 | plcp_signal = txrate->bitrate; |
1697 | 1696 | ||
1698 | hdr = (struct ieee80211_hdr *)skb->data; | 1697 | hdr = (struct ieee80211_hdr *)skb->data; |
1699 | fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED; | 1698 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1700 | hdrlen = ieee80211_get_hdrlen(fc); | ||
1701 | memcpy(skb->cb, skb->data, hdrlen); | 1699 | memcpy(skb->cb, skb->data, hdrlen); |
1702 | hdr = (struct ieee80211_hdr *)skb->cb; | 1700 | hdr = (struct ieee80211_hdr *)skb->cb; |
1703 | skb_pull(skb, hdrlen); | 1701 | skb_pull(skb, hdrlen); |
@@ -1711,8 +1709,6 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1711 | txhdr->frame_control = hdr->frame_control; | 1709 | txhdr->frame_control = hdr->frame_control; |
1712 | 1710 | ||
1713 | len = hdrlen + payload_len + FCS_LEN; | 1711 | len = hdrlen + payload_len + FCS_LEN; |
1714 | if (fc & IEEE80211_FCTL_PROTECTED) | ||
1715 | len += 8; | ||
1716 | 1712 | ||
1717 | txhdr->frag = cpu_to_le16(0x0FFF); | 1713 | txhdr->frag = cpu_to_le16(0x0FFF); |
1718 | adm8211_calc_durations(&dur, &plcp, payload_len, | 1714 | adm8211_calc_durations(&dur, &plcp, payload_len, |
@@ -1730,9 +1726,6 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1730 | if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) | 1726 | if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) |
1731 | txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS); | 1727 | txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS); |
1732 | 1728 | ||
1733 | if (fc & IEEE80211_FCTL_PROTECTED) | ||
1734 | txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_WEP_ENGINE); | ||
1735 | |||
1736 | txhdr->retry_limit = info->control.retry_limit; | 1729 | txhdr->retry_limit = info->control.retry_limit; |
1737 | 1730 | ||
1738 | adm8211_tx_raw(dev, skb, plcp_signal, hdrlen); | 1731 | adm8211_tx_raw(dev, skb, plcp_signal, hdrlen); |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index e30f8b79ea89..b5cd850a4a59 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -85,10 +85,10 @@ static struct pci_driver airo_driver = { | |||
85 | 85 | ||
86 | /* Include Wireless Extension definition and check version - Jean II */ | 86 | /* Include Wireless Extension definition and check version - Jean II */ |
87 | #include <linux/wireless.h> | 87 | #include <linux/wireless.h> |
88 | #define WIRELESS_SPY // enable iwspy support | 88 | #define WIRELESS_SPY /* enable iwspy support */ |
89 | #include <net/iw_handler.h> // New driver API | 89 | #include <net/iw_handler.h> /* New driver API */ |
90 | 90 | ||
91 | #define CISCO_EXT // enable Cisco extensions | 91 | #define CISCO_EXT /* enable Cisco extensions */ |
92 | #ifdef CISCO_EXT | 92 | #ifdef CISCO_EXT |
93 | #include <linux/delay.h> | 93 | #include <linux/delay.h> |
94 | #endif | 94 | #endif |
@@ -281,7 +281,7 @@ MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc"); | |||
281 | /* This is a kind of sloppy hack to get this information to OUT4500 and | 281 | /* This is a kind of sloppy hack to get this information to OUT4500 and |
282 | IN4500. I would be extremely interested in the situation where this | 282 | IN4500. I would be extremely interested in the situation where this |
283 | doesn't work though!!! */ | 283 | doesn't work though!!! */ |
284 | static int do8bitIO = 0; | 284 | static int do8bitIO /* = 0 */; |
285 | 285 | ||
286 | /* Return codes */ | 286 | /* Return codes */ |
287 | #define SUCCESS 0 | 287 | #define SUCCESS 0 |
@@ -398,8 +398,8 @@ static int do8bitIO = 0; | |||
398 | #define MAXTXQ 64 | 398 | #define MAXTXQ 64 |
399 | 399 | ||
400 | /* BAP selectors */ | 400 | /* BAP selectors */ |
401 | #define BAP0 0 // Used for receiving packets | 401 | #define BAP0 0 /* Used for receiving packets */ |
402 | #define BAP1 2 // Used for xmiting packets and working with RIDS | 402 | #define BAP1 2 /* Used for xmiting packets and working with RIDS */ |
403 | 403 | ||
404 | /* Flags */ | 404 | /* Flags */ |
405 | #define COMMAND_BUSY 0x8000 | 405 | #define COMMAND_BUSY 0x8000 |
@@ -5522,11 +5522,13 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5522 | Cmd cmd; | 5522 | Cmd cmd; |
5523 | Resp rsp; | 5523 | Resp rsp; |
5524 | 5524 | ||
5525 | if ((ai->APList == NULL) && | 5525 | if (!ai->APList) |
5526 | (ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL) | 5526 | ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL); |
5527 | if (!ai->APList) | ||
5527 | return -ENOMEM; | 5528 | return -ENOMEM; |
5528 | if ((ai->SSID == NULL) && | 5529 | if (!ai->SSID) |
5529 | (ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL)) == NULL) | 5530 | ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL); |
5531 | if (!ai->SSID) | ||
5530 | return -ENOMEM; | 5532 | return -ENOMEM; |
5531 | readAPListRid(ai, ai->APList); | 5533 | readAPListRid(ai, ai->APList); |
5532 | readSsidRid(ai, ai->SSID); | 5534 | readSsidRid(ai, ai->SSID); |
@@ -5537,7 +5539,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5537 | disable_MAC(ai, 0); | 5539 | disable_MAC(ai, 0); |
5538 | netif_device_detach(dev); | 5540 | netif_device_detach(dev); |
5539 | ai->power = state; | 5541 | ai->power = state; |
5540 | cmd.cmd=HOSTSLEEP; | 5542 | cmd.cmd = HOSTSLEEP; |
5541 | issuecommand(ai, &cmd, &rsp); | 5543 | issuecommand(ai, &cmd, &rsp); |
5542 | 5544 | ||
5543 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); | 5545 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); |
@@ -5567,7 +5569,7 @@ static int airo_pci_resume(struct pci_dev *pdev) | |||
5567 | msleep(100); | 5569 | msleep(100); |
5568 | } | 5570 | } |
5569 | 5571 | ||
5570 | set_bit (FLAG_COMMIT, &ai->flags); | 5572 | set_bit(FLAG_COMMIT, &ai->flags); |
5571 | disable_MAC(ai, 0); | 5573 | disable_MAC(ai, 0); |
5572 | msleep(200); | 5574 | msleep(200); |
5573 | if (ai->SSID) { | 5575 | if (ai->SSID) { |
@@ -5594,9 +5596,6 @@ static int airo_pci_resume(struct pci_dev *pdev) | |||
5594 | static int __init airo_init_module( void ) | 5596 | static int __init airo_init_module( void ) |
5595 | { | 5597 | { |
5596 | int i; | 5598 | int i; |
5597 | #if 0 | ||
5598 | int have_isa_dev = 0; | ||
5599 | #endif | ||
5600 | 5599 | ||
5601 | airo_entry = create_proc_entry("driver/aironet", | 5600 | airo_entry = create_proc_entry("driver/aironet", |
5602 | S_IFDIR | airo_perm, | 5601 | S_IFDIR | airo_perm, |
@@ -5607,15 +5606,11 @@ static int __init airo_init_module( void ) | |||
5607 | airo_entry->gid = proc_gid; | 5606 | airo_entry->gid = proc_gid; |
5608 | } | 5607 | } |
5609 | 5608 | ||
5610 | for( i = 0; i < 4 && io[i] && irq[i]; i++ ) { | 5609 | for (i = 0; i < 4 && io[i] && irq[i]; i++) { |
5611 | airo_print_info("", "Trying to configure ISA adapter at irq=%d " | 5610 | airo_print_info("", "Trying to configure ISA adapter at irq=%d " |
5612 | "io=0x%x", irq[i], io[i] ); | 5611 | "io=0x%x", irq[i], io[i] ); |
5613 | if (init_airo_card( irq[i], io[i], 0, NULL )) | 5612 | if (init_airo_card( irq[i], io[i], 0, NULL )) |
5614 | #if 0 | ||
5615 | have_isa_dev = 1; | ||
5616 | #else | ||
5617 | /* do nothing */ ; | 5613 | /* do nothing */ ; |
5618 | #endif | ||
5619 | } | 5614 | } |
5620 | 5615 | ||
5621 | #ifdef CONFIG_PCI | 5616 | #ifdef CONFIG_PCI |
@@ -5661,7 +5656,7 @@ static void __exit airo_cleanup_module( void ) | |||
5661 | 5656 | ||
5662 | static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi) | 5657 | static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi) |
5663 | { | 5658 | { |
5664 | if( !rssi_rid ) | 5659 | if (!rssi_rid) |
5665 | return 0; | 5660 | return 0; |
5666 | 5661 | ||
5667 | return (0x100 - rssi_rid[rssi].rssidBm); | 5662 | return (0x100 - rssi_rid[rssi].rssidBm); |
@@ -5671,10 +5666,10 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm) | |||
5671 | { | 5666 | { |
5672 | int i; | 5667 | int i; |
5673 | 5668 | ||
5674 | if( !rssi_rid ) | 5669 | if (!rssi_rid) |
5675 | return 0; | 5670 | return 0; |
5676 | 5671 | ||
5677 | for( i = 0; i < 256; i++ ) | 5672 | for (i = 0; i < 256; i++) |
5678 | if (rssi_rid[i].rssidBm == dbm) | 5673 | if (rssi_rid[i].rssidBm == dbm) |
5679 | return rssi_rid[i].rssipct; | 5674 | return rssi_rid[i].rssipct; |
5680 | 5675 | ||
@@ -7156,6 +7151,7 @@ out: | |||
7156 | * format that the Wireless Tools will understand - Jean II | 7151 | * format that the Wireless Tools will understand - Jean II |
7157 | */ | 7152 | */ |
7158 | static inline char *airo_translate_scan(struct net_device *dev, | 7153 | static inline char *airo_translate_scan(struct net_device *dev, |
7154 | struct iw_request_info *info, | ||
7159 | char *current_ev, | 7155 | char *current_ev, |
7160 | char *end_buf, | 7156 | char *end_buf, |
7161 | BSSListRid *bss) | 7157 | BSSListRid *bss) |
@@ -7172,7 +7168,8 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7172 | iwe.cmd = SIOCGIWAP; | 7168 | iwe.cmd = SIOCGIWAP; |
7173 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 7169 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
7174 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 7170 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
7175 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); | 7171 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
7172 | &iwe, IW_EV_ADDR_LEN); | ||
7176 | 7173 | ||
7177 | /* Other entries will be displayed in the order we give them */ | 7174 | /* Other entries will be displayed in the order we give them */ |
7178 | 7175 | ||
@@ -7182,7 +7179,8 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7182 | iwe.u.data.length = 32; | 7179 | iwe.u.data.length = 32; |
7183 | iwe.cmd = SIOCGIWESSID; | 7180 | iwe.cmd = SIOCGIWESSID; |
7184 | iwe.u.data.flags = 1; | 7181 | iwe.u.data.flags = 1; |
7185 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); | 7182 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
7183 | &iwe, bss->ssid); | ||
7186 | 7184 | ||
7187 | /* Add mode */ | 7185 | /* Add mode */ |
7188 | iwe.cmd = SIOCGIWMODE; | 7186 | iwe.cmd = SIOCGIWMODE; |
@@ -7192,7 +7190,8 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7192 | iwe.u.mode = IW_MODE_MASTER; | 7190 | iwe.u.mode = IW_MODE_MASTER; |
7193 | else | 7191 | else |
7194 | iwe.u.mode = IW_MODE_ADHOC; | 7192 | iwe.u.mode = IW_MODE_ADHOC; |
7195 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); | 7193 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
7194 | &iwe, IW_EV_UINT_LEN); | ||
7196 | } | 7195 | } |
7197 | 7196 | ||
7198 | /* Add frequency */ | 7197 | /* Add frequency */ |
@@ -7203,7 +7202,8 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7203 | */ | 7202 | */ |
7204 | iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; | 7203 | iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; |
7205 | iwe.u.freq.e = 1; | 7204 | iwe.u.freq.e = 1; |
7206 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); | 7205 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
7206 | &iwe, IW_EV_FREQ_LEN); | ||
7207 | 7207 | ||
7208 | dBm = le16_to_cpu(bss->dBm); | 7208 | dBm = le16_to_cpu(bss->dBm); |
7209 | 7209 | ||
@@ -7223,7 +7223,8 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7223 | | IW_QUAL_DBM; | 7223 | | IW_QUAL_DBM; |
7224 | } | 7224 | } |
7225 | iwe.u.qual.noise = ai->wstats.qual.noise; | 7225 | iwe.u.qual.noise = ai->wstats.qual.noise; |
7226 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); | 7226 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
7227 | &iwe, IW_EV_QUAL_LEN); | ||
7227 | 7228 | ||
7228 | /* Add encryption capability */ | 7229 | /* Add encryption capability */ |
7229 | iwe.cmd = SIOCGIWENCODE; | 7230 | iwe.cmd = SIOCGIWENCODE; |
@@ -7232,11 +7233,12 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7232 | else | 7233 | else |
7233 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 7234 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
7234 | iwe.u.data.length = 0; | 7235 | iwe.u.data.length = 0; |
7235 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); | 7236 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
7237 | &iwe, bss->ssid); | ||
7236 | 7238 | ||
7237 | /* Rate : stuffing multiple values in a single event require a bit | 7239 | /* Rate : stuffing multiple values in a single event require a bit |
7238 | * more of magic - Jean II */ | 7240 | * more of magic - Jean II */ |
7239 | current_val = current_ev + IW_EV_LCP_LEN; | 7241 | current_val = current_ev + iwe_stream_lcp_len(info); |
7240 | 7242 | ||
7241 | iwe.cmd = SIOCGIWRATE; | 7243 | iwe.cmd = SIOCGIWRATE; |
7242 | /* Those two flags are ignored... */ | 7244 | /* Those two flags are ignored... */ |
@@ -7249,10 +7251,12 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7249 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | 7251 | /* Bit rate given in 500 kb/s units (+ 0x80) */ |
7250 | iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000); | 7252 | iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000); |
7251 | /* Add new value to event */ | 7253 | /* Add new value to event */ |
7252 | current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); | 7254 | current_val = iwe_stream_add_value(info, current_ev, |
7255 | current_val, end_buf, | ||
7256 | &iwe, IW_EV_PARAM_LEN); | ||
7253 | } | 7257 | } |
7254 | /* Check if we added any event */ | 7258 | /* Check if we added any event */ |
7255 | if((current_val - current_ev) > IW_EV_LCP_LEN) | 7259 | if ((current_val - current_ev) > iwe_stream_lcp_len(info)) |
7256 | current_ev = current_val; | 7260 | current_ev = current_val; |
7257 | 7261 | ||
7258 | /* Beacon interval */ | 7262 | /* Beacon interval */ |
@@ -7261,7 +7265,8 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7261 | iwe.cmd = IWEVCUSTOM; | 7265 | iwe.cmd = IWEVCUSTOM; |
7262 | sprintf(buf, "bcn_int=%d", bss->beaconInterval); | 7266 | sprintf(buf, "bcn_int=%d", bss->beaconInterval); |
7263 | iwe.u.data.length = strlen(buf); | 7267 | iwe.u.data.length = strlen(buf); |
7264 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); | 7268 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
7269 | &iwe, buf); | ||
7265 | kfree(buf); | 7270 | kfree(buf); |
7266 | } | 7271 | } |
7267 | 7272 | ||
@@ -7295,8 +7300,10 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7295 | iwe.cmd = IWEVGENIE; | 7300 | iwe.cmd = IWEVGENIE; |
7296 | iwe.u.data.length = min(info_element->len + 2, | 7301 | iwe.u.data.length = min(info_element->len + 2, |
7297 | MAX_WPA_IE_LEN); | 7302 | MAX_WPA_IE_LEN); |
7298 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 7303 | current_ev = iwe_stream_add_point( |
7299 | &iwe, (char *) info_element); | 7304 | info, current_ev, |
7305 | end_buf, &iwe, | ||
7306 | (char *) info_element); | ||
7300 | } | 7307 | } |
7301 | break; | 7308 | break; |
7302 | 7309 | ||
@@ -7304,8 +7311,9 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
7304 | iwe.cmd = IWEVGENIE; | 7311 | iwe.cmd = IWEVGENIE; |
7305 | iwe.u.data.length = min(info_element->len + 2, | 7312 | iwe.u.data.length = min(info_element->len + 2, |
7306 | MAX_WPA_IE_LEN); | 7313 | MAX_WPA_IE_LEN); |
7307 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 7314 | current_ev = iwe_stream_add_point( |
7308 | &iwe, (char *) info_element); | 7315 | info, current_ev, end_buf, |
7316 | &iwe, (char *) info_element); | ||
7309 | break; | 7317 | break; |
7310 | 7318 | ||
7311 | default: | 7319 | default: |
@@ -7344,7 +7352,7 @@ static int airo_get_scan(struct net_device *dev, | |||
7344 | 7352 | ||
7345 | list_for_each_entry (net, &ai->network_list, list) { | 7353 | list_for_each_entry (net, &ai->network_list, list) { |
7346 | /* Translate to WE format this entry */ | 7354 | /* Translate to WE format this entry */ |
7347 | current_ev = airo_translate_scan(dev, current_ev, | 7355 | current_ev = airo_translate_scan(dev, info, current_ev, |
7348 | extra + dwrq->length, | 7356 | extra + dwrq->length, |
7349 | &net->bss); | 7357 | &net->bss); |
7350 | 7358 | ||
diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath5k/Kconfig index f1f2aea2eab4..75383a5df992 100644 --- a/drivers/net/wireless/ath5k/Kconfig +++ b/drivers/net/wireless/ath5k/Kconfig | |||
@@ -1,6 +1,9 @@ | |||
1 | config ATH5K | 1 | config ATH5K |
2 | tristate "Atheros 5xxx wireless cards support" | 2 | tristate "Atheros 5xxx wireless cards support" |
3 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL | 3 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL |
4 | select MAC80211_LEDS | ||
5 | select LEDS_CLASS | ||
6 | select NEW_LEDS | ||
4 | ---help--- | 7 | ---help--- |
5 | This module adds support for wireless adapters based on | 8 | This module adds support for wireless adapters based on |
6 | Atheros 5xxx chipset. | 9 | Atheros 5xxx chipset. |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 85045afc1ba7..a43e9b25169b 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -58,11 +58,6 @@ | |||
58 | #include "reg.h" | 58 | #include "reg.h" |
59 | #include "debug.h" | 59 | #include "debug.h" |
60 | 60 | ||
61 | enum { | ||
62 | ATH_LED_TX, | ||
63 | ATH_LED_RX, | ||
64 | }; | ||
65 | |||
66 | static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ | 61 | static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ |
67 | 62 | ||
68 | 63 | ||
@@ -309,13 +304,10 @@ static void ath5k_tasklet_reset(unsigned long data); | |||
309 | 304 | ||
310 | static void ath5k_calibrate(unsigned long data); | 305 | static void ath5k_calibrate(unsigned long data); |
311 | /* LED functions */ | 306 | /* LED functions */ |
312 | static void ath5k_led_off(unsigned long data); | 307 | static int ath5k_init_leds(struct ath5k_softc *sc); |
313 | static void ath5k_led_blink(struct ath5k_softc *sc, | 308 | static void ath5k_led_enable(struct ath5k_softc *sc); |
314 | unsigned int on, | 309 | static void ath5k_led_off(struct ath5k_softc *sc); |
315 | unsigned int off); | 310 | static void ath5k_unregister_leds(struct ath5k_softc *sc); |
316 | static void ath5k_led_event(struct ath5k_softc *sc, | ||
317 | int event); | ||
318 | |||
319 | 311 | ||
320 | /* | 312 | /* |
321 | * Module init/exit functions | 313 | * Module init/exit functions |
@@ -596,8 +588,7 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
596 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 588 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
597 | struct ath5k_softc *sc = hw->priv; | 589 | struct ath5k_softc *sc = hw->priv; |
598 | 590 | ||
599 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) | 591 | ath5k_led_off(sc); |
600 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, 1); | ||
601 | 592 | ||
602 | ath5k_stop_hw(sc); | 593 | ath5k_stop_hw(sc); |
603 | pci_save_state(pdev); | 594 | pci_save_state(pdev); |
@@ -632,10 +623,7 @@ ath5k_pci_resume(struct pci_dev *pdev) | |||
632 | pci_write_config_byte(pdev, 0x41, 0); | 623 | pci_write_config_byte(pdev, 0x41, 0); |
633 | 624 | ||
634 | ath5k_init(sc); | 625 | ath5k_init(sc); |
635 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { | 626 | ath5k_led_enable(sc); |
636 | ath5k_hw_set_gpio_output(ah, sc->led_pin); | ||
637 | ath5k_hw_set_gpio(ah, sc->led_pin, 0); | ||
638 | } | ||
639 | 627 | ||
640 | /* | 628 | /* |
641 | * Reset the key cache since some parts do not | 629 | * Reset the key cache since some parts do not |
@@ -742,27 +730,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
742 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); | 730 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); |
743 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | 731 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); |
744 | setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); | 732 | setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); |
745 | setup_timer(&sc->led_tim, ath5k_led_off, (unsigned long)sc); | ||
746 | |||
747 | sc->led_on = 0; /* low true */ | ||
748 | /* | ||
749 | * Auto-enable soft led processing for IBM cards and for | ||
750 | * 5211 minipci cards. | ||
751 | */ | ||
752 | if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || | ||
753 | pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { | ||
754 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
755 | sc->led_pin = 0; | ||
756 | } | ||
757 | /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ | ||
758 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { | ||
759 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
760 | sc->led_pin = 0; | ||
761 | } | ||
762 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { | ||
763 | ath5k_hw_set_gpio_output(ah, sc->led_pin); | ||
764 | ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on); | ||
765 | } | ||
766 | 733 | ||
767 | ath5k_hw_get_lladdr(ah, mac); | 734 | ath5k_hw_get_lladdr(ah, mac); |
768 | SET_IEEE80211_PERM_ADDR(hw, mac); | 735 | SET_IEEE80211_PERM_ADDR(hw, mac); |
@@ -776,6 +743,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
776 | goto err_queues; | 743 | goto err_queues; |
777 | } | 744 | } |
778 | 745 | ||
746 | ath5k_init_leds(sc); | ||
747 | |||
779 | return 0; | 748 | return 0; |
780 | err_queues: | 749 | err_queues: |
781 | ath5k_txq_release(sc); | 750 | ath5k_txq_release(sc); |
@@ -809,6 +778,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
809 | ath5k_desc_free(sc, pdev); | 778 | ath5k_desc_free(sc, pdev); |
810 | ath5k_txq_release(sc); | 779 | ath5k_txq_release(sc); |
811 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); | 780 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); |
781 | ath5k_unregister_leds(sc); | ||
812 | 782 | ||
813 | /* | 783 | /* |
814 | * NB: can't reclaim these until after ieee80211_ifdetach | 784 | * NB: can't reclaim these until after ieee80211_ifdetach |
@@ -1060,65 +1030,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
1060 | return 0; | 1030 | return 0; |
1061 | } | 1031 | } |
1062 | 1032 | ||
1063 | /* | ||
1064 | * TODO: CLEAN THIS !!! | ||
1065 | */ | ||
1066 | static void | 1033 | static void |
1067 | ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) | 1034 | ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) |
1068 | { | 1035 | { |
1069 | if (unlikely(test_bit(ATH_STAT_LEDSOFT, sc->status))) { | ||
1070 | /* from Atheros NDIS driver, w/ permission */ | ||
1071 | static const struct { | ||
1072 | u16 rate; /* tx/rx 802.11 rate */ | ||
1073 | u16 timeOn; /* LED on time (ms) */ | ||
1074 | u16 timeOff; /* LED off time (ms) */ | ||
1075 | } blinkrates[] = { | ||
1076 | { 108, 40, 10 }, | ||
1077 | { 96, 44, 11 }, | ||
1078 | { 72, 50, 13 }, | ||
1079 | { 48, 57, 14 }, | ||
1080 | { 36, 67, 16 }, | ||
1081 | { 24, 80, 20 }, | ||
1082 | { 22, 100, 25 }, | ||
1083 | { 18, 133, 34 }, | ||
1084 | { 12, 160, 40 }, | ||
1085 | { 10, 200, 50 }, | ||
1086 | { 6, 240, 58 }, | ||
1087 | { 4, 267, 66 }, | ||
1088 | { 2, 400, 100 }, | ||
1089 | { 0, 500, 130 } | ||
1090 | }; | ||
1091 | const struct ath5k_rate_table *rt = | ||
1092 | ath5k_hw_get_rate_table(sc->ah, mode); | ||
1093 | unsigned int i, j; | ||
1094 | |||
1095 | BUG_ON(rt == NULL); | ||
1096 | |||
1097 | memset(sc->hwmap, 0, sizeof(sc->hwmap)); | ||
1098 | for (i = 0; i < 32; i++) { | ||
1099 | u8 ix = rt->rate_code_to_index[i]; | ||
1100 | if (ix == 0xff) { | ||
1101 | sc->hwmap[i].ledon = msecs_to_jiffies(500); | ||
1102 | sc->hwmap[i].ledoff = msecs_to_jiffies(130); | ||
1103 | continue; | ||
1104 | } | ||
1105 | sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD; | ||
1106 | /* receive frames include FCS */ | ||
1107 | sc->hwmap[i].rxflags = sc->hwmap[i].txflags | | ||
1108 | IEEE80211_RADIOTAP_F_FCS; | ||
1109 | /* setup blink rate table to avoid per-packet lookup */ | ||
1110 | for (j = 0; j < ARRAY_SIZE(blinkrates) - 1; j++) | ||
1111 | if (blinkrates[j].rate == /* XXX why 7f? */ | ||
1112 | (rt->rates[ix].dot11_rate&0x7f)) | ||
1113 | break; | ||
1114 | |||
1115 | sc->hwmap[i].ledon = msecs_to_jiffies(blinkrates[j]. | ||
1116 | timeOn); | ||
1117 | sc->hwmap[i].ledoff = msecs_to_jiffies(blinkrates[j]. | ||
1118 | timeOff); | ||
1119 | } | ||
1120 | } | ||
1121 | |||
1122 | sc->curmode = mode; | 1036 | sc->curmode = mode; |
1123 | 1037 | ||
1124 | if (mode == AR5K_MODE_11A) { | 1038 | if (mode == AR5K_MODE_11A) { |
@@ -1691,9 +1605,9 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | |||
1691 | /* Apparently when a default key is used to decrypt the packet | 1605 | /* Apparently when a default key is used to decrypt the packet |
1692 | the hw does not set the index used to decrypt. In such cases | 1606 | the hw does not set the index used to decrypt. In such cases |
1693 | get the index from the packet. */ | 1607 | get the index from the packet. */ |
1694 | if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) && | 1608 | if (ieee80211_has_protected(hdr->frame_control) && |
1695 | !(rs->rs_status & AR5K_RXERR_DECRYPT) && | 1609 | !(rs->rs_status & AR5K_RXERR_DECRYPT) && |
1696 | skb->len >= hlen + 4) { | 1610 | skb->len >= hlen + 4) { |
1697 | keyix = skb->data[hlen + 3] >> 6; | 1611 | keyix = skb->data[hlen + 3] >> 6; |
1698 | 1612 | ||
1699 | if (test_bit(keyix, sc->keymap)) | 1613 | if (test_bit(keyix, sc->keymap)) |
@@ -1712,10 +1626,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1712 | u32 hw_tu; | 1626 | u32 hw_tu; |
1713 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | 1627 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; |
1714 | 1628 | ||
1715 | if ((le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_FTYPE) == | 1629 | if (ieee80211_is_beacon(mgmt->frame_control) && |
1716 | IEEE80211_FTYPE_MGMT && | ||
1717 | (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) == | ||
1718 | IEEE80211_STYPE_BEACON && | ||
1719 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && | 1630 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && |
1720 | memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { | 1631 | memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { |
1721 | /* | 1632 | /* |
@@ -1903,8 +1814,6 @@ accept: | |||
1903 | ath5k_check_ibss_tsf(sc, skb, &rxs); | 1814 | ath5k_check_ibss_tsf(sc, skb, &rxs); |
1904 | 1815 | ||
1905 | __ieee80211_rx(sc->hw, skb, &rxs); | 1816 | __ieee80211_rx(sc->hw, skb, &rxs); |
1906 | sc->led_rxrate = rs.rs_rate; | ||
1907 | ath5k_led_event(sc, ATH_LED_RX); | ||
1908 | next: | 1817 | next: |
1909 | list_move_tail(&bf->list, &sc->rxbuf); | 1818 | list_move_tail(&bf->list, &sc->rxbuf); |
1910 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | 1819 | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
@@ -1985,13 +1894,9 @@ ath5k_tasklet_tx(unsigned long data) | |||
1985 | struct ath5k_softc *sc = (void *)data; | 1894 | struct ath5k_softc *sc = (void *)data; |
1986 | 1895 | ||
1987 | ath5k_tx_processq(sc, sc->txq); | 1896 | ath5k_tx_processq(sc, sc->txq); |
1988 | |||
1989 | ath5k_led_event(sc, ATH_LED_TX); | ||
1990 | } | 1897 | } |
1991 | 1898 | ||
1992 | 1899 | ||
1993 | |||
1994 | |||
1995 | /*****************\ | 1900 | /*****************\ |
1996 | * Beacon handling * | 1901 | * Beacon handling * |
1997 | \*****************/ | 1902 | \*****************/ |
@@ -2366,11 +2271,7 @@ ath5k_stop_locked(struct ath5k_softc *sc) | |||
2366 | ieee80211_stop_queues(sc->hw); | 2271 | ieee80211_stop_queues(sc->hw); |
2367 | 2272 | ||
2368 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | 2273 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { |
2369 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { | 2274 | ath5k_led_off(sc); |
2370 | del_timer_sync(&sc->led_tim); | ||
2371 | ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on); | ||
2372 | __clear_bit(ATH_STAT_LEDBLINKING, sc->status); | ||
2373 | } | ||
2374 | ath5k_hw_set_intr(ah, 0); | 2275 | ath5k_hw_set_intr(ah, 0); |
2375 | } | 2276 | } |
2376 | ath5k_txq_cleanup(sc); | 2277 | ath5k_txq_cleanup(sc); |
@@ -2566,55 +2467,124 @@ ath5k_calibrate(unsigned long data) | |||
2566 | \***************/ | 2467 | \***************/ |
2567 | 2468 | ||
2568 | static void | 2469 | static void |
2569 | ath5k_led_off(unsigned long data) | 2470 | ath5k_led_enable(struct ath5k_softc *sc) |
2570 | { | 2471 | { |
2571 | struct ath5k_softc *sc = (void *)data; | 2472 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { |
2572 | 2473 | ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); | |
2573 | if (test_bit(ATH_STAT_LEDENDBLINK, sc->status)) | 2474 | ath5k_led_off(sc); |
2574 | __clear_bit(ATH_STAT_LEDBLINKING, sc->status); | ||
2575 | else { | ||
2576 | __set_bit(ATH_STAT_LEDENDBLINK, sc->status); | ||
2577 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); | ||
2578 | mod_timer(&sc->led_tim, jiffies + sc->led_off); | ||
2579 | } | 2475 | } |
2580 | } | 2476 | } |
2581 | 2477 | ||
2582 | /* | ||
2583 | * Blink the LED according to the specified on/off times. | ||
2584 | */ | ||
2585 | static void | 2478 | static void |
2586 | ath5k_led_blink(struct ath5k_softc *sc, unsigned int on, | 2479 | ath5k_led_on(struct ath5k_softc *sc) |
2587 | unsigned int off) | ||
2588 | { | 2480 | { |
2589 | ATH5K_DBG(sc, ATH5K_DEBUG_LED, "on %u off %u\n", on, off); | 2481 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) |
2482 | return; | ||
2590 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); | 2483 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); |
2591 | __set_bit(ATH_STAT_LEDBLINKING, sc->status); | ||
2592 | __clear_bit(ATH_STAT_LEDENDBLINK, sc->status); | ||
2593 | sc->led_off = off; | ||
2594 | mod_timer(&sc->led_tim, jiffies + on); | ||
2595 | } | 2484 | } |
2596 | 2485 | ||
2597 | static void | 2486 | static void |
2598 | ath5k_led_event(struct ath5k_softc *sc, int event) | 2487 | ath5k_led_off(struct ath5k_softc *sc) |
2599 | { | 2488 | { |
2600 | if (likely(!test_bit(ATH_STAT_LEDSOFT, sc->status))) | 2489 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) |
2601 | return; | 2490 | return; |
2602 | if (unlikely(test_bit(ATH_STAT_LEDBLINKING, sc->status))) | 2491 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); |
2603 | return; /* don't interrupt active blink */ | 2492 | } |
2604 | switch (event) { | 2493 | |
2605 | case ATH_LED_TX: | 2494 | static void |
2606 | ath5k_led_blink(sc, sc->hwmap[sc->led_txrate].ledon, | 2495 | ath5k_led_brightness_set(struct led_classdev *led_dev, |
2607 | sc->hwmap[sc->led_txrate].ledoff); | 2496 | enum led_brightness brightness) |
2608 | break; | 2497 | { |
2609 | case ATH_LED_RX: | 2498 | struct ath5k_led *led = container_of(led_dev, struct ath5k_led, |
2610 | ath5k_led_blink(sc, sc->hwmap[sc->led_rxrate].ledon, | 2499 | led_dev); |
2611 | sc->hwmap[sc->led_rxrate].ledoff); | 2500 | |
2612 | break; | 2501 | if (brightness == LED_OFF) |
2502 | ath5k_led_off(led->sc); | ||
2503 | else | ||
2504 | ath5k_led_on(led->sc); | ||
2505 | } | ||
2506 | |||
2507 | static int | ||
2508 | ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, | ||
2509 | const char *name, char *trigger) | ||
2510 | { | ||
2511 | int err; | ||
2512 | |||
2513 | led->sc = sc; | ||
2514 | strncpy(led->name, name, sizeof(led->name)); | ||
2515 | led->led_dev.name = led->name; | ||
2516 | led->led_dev.default_trigger = trigger; | ||
2517 | led->led_dev.brightness_set = ath5k_led_brightness_set; | ||
2518 | |||
2519 | err = led_classdev_register(&sc->pdev->dev, &led->led_dev); | ||
2520 | if (err) | ||
2521 | { | ||
2522 | ATH5K_WARN(sc, "could not register LED %s\n", name); | ||
2523 | led->sc = NULL; | ||
2613 | } | 2524 | } |
2525 | return err; | ||
2526 | } | ||
2527 | |||
2528 | static void | ||
2529 | ath5k_unregister_led(struct ath5k_led *led) | ||
2530 | { | ||
2531 | if (!led->sc) | ||
2532 | return; | ||
2533 | led_classdev_unregister(&led->led_dev); | ||
2534 | ath5k_led_off(led->sc); | ||
2535 | led->sc = NULL; | ||
2614 | } | 2536 | } |
2615 | 2537 | ||
2538 | static void | ||
2539 | ath5k_unregister_leds(struct ath5k_softc *sc) | ||
2540 | { | ||
2541 | ath5k_unregister_led(&sc->rx_led); | ||
2542 | ath5k_unregister_led(&sc->tx_led); | ||
2543 | } | ||
2616 | 2544 | ||
2617 | 2545 | ||
2546 | static int | ||
2547 | ath5k_init_leds(struct ath5k_softc *sc) | ||
2548 | { | ||
2549 | int ret = 0; | ||
2550 | struct ieee80211_hw *hw = sc->hw; | ||
2551 | struct pci_dev *pdev = sc->pdev; | ||
2552 | char name[ATH5K_LED_MAX_NAME_LEN + 1]; | ||
2553 | |||
2554 | sc->led_on = 0; /* active low */ | ||
2555 | |||
2556 | /* | ||
2557 | * Auto-enable soft led processing for IBM cards and for | ||
2558 | * 5211 minipci cards. | ||
2559 | */ | ||
2560 | if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || | ||
2561 | pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { | ||
2562 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
2563 | sc->led_pin = 0; | ||
2564 | } | ||
2565 | /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ | ||
2566 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { | ||
2567 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
2568 | sc->led_pin = 1; | ||
2569 | } | ||
2570 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | ||
2571 | goto out; | ||
2572 | |||
2573 | ath5k_led_enable(sc); | ||
2574 | |||
2575 | snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); | ||
2576 | ret = ath5k_register_led(sc, &sc->rx_led, name, | ||
2577 | ieee80211_get_rx_led_name(hw)); | ||
2578 | if (ret) | ||
2579 | goto out; | ||
2580 | |||
2581 | snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); | ||
2582 | ret = ath5k_register_led(sc, &sc->tx_led, name, | ||
2583 | ieee80211_get_tx_led_name(hw)); | ||
2584 | out: | ||
2585 | return ret; | ||
2586 | } | ||
2587 | |||
2618 | 2588 | ||
2619 | /********************\ | 2589 | /********************\ |
2620 | * Mac80211 functions * | 2590 | * Mac80211 functions * |
@@ -2625,7 +2595,6 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2625 | { | 2595 | { |
2626 | struct ath5k_softc *sc = hw->priv; | 2596 | struct ath5k_softc *sc = hw->priv; |
2627 | struct ath5k_buf *bf; | 2597 | struct ath5k_buf *bf; |
2628 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2629 | unsigned long flags; | 2598 | unsigned long flags; |
2630 | int hdrlen; | 2599 | int hdrlen; |
2631 | int pad; | 2600 | int pad; |
@@ -2651,8 +2620,6 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2651 | memmove(skb->data, skb->data+pad, hdrlen); | 2620 | memmove(skb->data, skb->data+pad, hdrlen); |
2652 | } | 2621 | } |
2653 | 2622 | ||
2654 | sc->led_txrate = ieee80211_get_tx_rate(hw, info)->hw_value; | ||
2655 | |||
2656 | spin_lock_irqsave(&sc->txbuflock, flags); | 2623 | spin_lock_irqsave(&sc->txbuflock, flags); |
2657 | if (list_empty(&sc->txbuf)) { | 2624 | if (list_empty(&sc->txbuf)) { |
2658 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); | 2625 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); |
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index bb4b26d523ab..47f414b09e67 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/list.h> | 45 | #include <linux/list.h> |
46 | #include <linux/wireless.h> | 46 | #include <linux/wireless.h> |
47 | #include <linux/if_ether.h> | 47 | #include <linux/if_ether.h> |
48 | #include <linux/leds.h> | ||
48 | 49 | ||
49 | #include "ath5k.h" | 50 | #include "ath5k.h" |
50 | #include "debug.h" | 51 | #include "debug.h" |
@@ -79,6 +80,19 @@ struct ath5k_txq { | |||
79 | bool setup; | 80 | bool setup; |
80 | }; | 81 | }; |
81 | 82 | ||
83 | #define ATH5K_LED_MAX_NAME_LEN 31 | ||
84 | |||
85 | /* | ||
86 | * State for LED triggers | ||
87 | */ | ||
88 | struct ath5k_led | ||
89 | { | ||
90 | char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */ | ||
91 | struct ath5k_softc *sc; /* driver state */ | ||
92 | struct led_classdev led_dev; /* led classdev */ | ||
93 | }; | ||
94 | |||
95 | |||
82 | #if CHAN_DEBUG | 96 | #if CHAN_DEBUG |
83 | #define ATH_CHAN_MAX (26+26+26+200+200) | 97 | #define ATH_CHAN_MAX (26+26+26+200+200) |
84 | #else | 98 | #else |
@@ -118,13 +132,11 @@ struct ath5k_softc { | |||
118 | size_t desc_len; /* size of TX/RX descriptors */ | 132 | size_t desc_len; /* size of TX/RX descriptors */ |
119 | u16 cachelsz; /* cache line size */ | 133 | u16 cachelsz; /* cache line size */ |
120 | 134 | ||
121 | DECLARE_BITMAP(status, 6); | 135 | DECLARE_BITMAP(status, 4); |
122 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ | 136 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ |
123 | #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ | 137 | #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ |
124 | #define ATH_STAT_PROMISC 2 | 138 | #define ATH_STAT_PROMISC 2 |
125 | #define ATH_STAT_LEDBLINKING 3 /* LED blink operation active */ | 139 | #define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ |
126 | #define ATH_STAT_LEDENDBLINK 4 /* finish LED blink operation */ | ||
127 | #define ATH_STAT_LEDSOFT 5 /* enable LED gpio status */ | ||
128 | 140 | ||
129 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ | 141 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ |
130 | unsigned int curmode; /* current phy mode */ | 142 | unsigned int curmode; /* current phy mode */ |
@@ -132,13 +144,6 @@ struct ath5k_softc { | |||
132 | 144 | ||
133 | struct ieee80211_vif *vif; | 145 | struct ieee80211_vif *vif; |
134 | 146 | ||
135 | struct { | ||
136 | u8 rxflags; /* radiotap rx flags */ | ||
137 | u8 txflags; /* radiotap tx flags */ | ||
138 | u16 ledon; /* softled on time */ | ||
139 | u16 ledoff; /* softled off time */ | ||
140 | } hwmap[32]; /* h/w rate ix mappings */ | ||
141 | |||
142 | enum ath5k_int imask; /* interrupt mask copy */ | 147 | enum ath5k_int imask; /* interrupt mask copy */ |
143 | 148 | ||
144 | DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ | 149 | DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ |
@@ -148,9 +153,6 @@ struct ath5k_softc { | |||
148 | unsigned int led_pin, /* GPIO pin for driving LED */ | 153 | unsigned int led_pin, /* GPIO pin for driving LED */ |
149 | led_on, /* pin setting for LED on */ | 154 | led_on, /* pin setting for LED on */ |
150 | led_off; /* off time for current blink */ | 155 | led_off; /* off time for current blink */ |
151 | struct timer_list led_tim; /* led off timer */ | ||
152 | u8 led_rxrate; /* current rx rate for LED */ | ||
153 | u8 led_txrate; /* current tx rate for LED */ | ||
154 | 156 | ||
155 | struct tasklet_struct restq; /* reset tasklet */ | 157 | struct tasklet_struct restq; /* reset tasklet */ |
156 | 158 | ||
@@ -159,6 +161,7 @@ struct ath5k_softc { | |||
159 | spinlock_t rxbuflock; | 161 | spinlock_t rxbuflock; |
160 | u32 *rxlink; /* link ptr in last RX desc */ | 162 | u32 *rxlink; /* link ptr in last RX desc */ |
161 | struct tasklet_struct rxtq; /* rx intr tasklet */ | 163 | struct tasklet_struct rxtq; /* rx intr tasklet */ |
164 | struct ath5k_led rx_led; /* rx led */ | ||
162 | 165 | ||
163 | struct list_head txbuf; /* transmit buffer */ | 166 | struct list_head txbuf; /* transmit buffer */ |
164 | spinlock_t txbuflock; | 167 | spinlock_t txbuflock; |
@@ -167,6 +170,7 @@ struct ath5k_softc { | |||
167 | 170 | ||
168 | struct ath5k_txq *txq; /* beacon and tx*/ | 171 | struct ath5k_txq *txq; /* beacon and tx*/ |
169 | struct tasklet_struct txtq; /* tx intr tasklet */ | 172 | struct tasklet_struct txtq; /* tx intr tasklet */ |
173 | struct ath5k_led tx_led; /* tx led */ | ||
170 | 174 | ||
171 | struct ath5k_buf *bbuf; /* beacon buffer */ | 175 | struct ath5k_buf *bbuf; /* beacon buffer */ |
172 | unsigned int bhalq, /* SW q for outgoing beacons */ | 176 | unsigned int bhalq, /* SW q for outgoing beacons */ |
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 77990b56860b..c6d12c53bda4 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c | |||
@@ -31,14 +31,14 @@ | |||
31 | #include "base.h" | 31 | #include "base.h" |
32 | #include "debug.h" | 32 | #include "debug.h" |
33 | 33 | ||
34 | /*Rate tables*/ | 34 | /* Rate tables */ |
35 | static const struct ath5k_rate_table ath5k_rt_11a = AR5K_RATES_11A; | 35 | static const struct ath5k_rate_table ath5k_rt_11a = AR5K_RATES_11A; |
36 | static const struct ath5k_rate_table ath5k_rt_11b = AR5K_RATES_11B; | 36 | static const struct ath5k_rate_table ath5k_rt_11b = AR5K_RATES_11B; |
37 | static const struct ath5k_rate_table ath5k_rt_11g = AR5K_RATES_11G; | 37 | static const struct ath5k_rate_table ath5k_rt_11g = AR5K_RATES_11G; |
38 | static const struct ath5k_rate_table ath5k_rt_turbo = AR5K_RATES_TURBO; | 38 | static const struct ath5k_rate_table ath5k_rt_turbo = AR5K_RATES_TURBO; |
39 | static const struct ath5k_rate_table ath5k_rt_xr = AR5K_RATES_XR; | 39 | static const struct ath5k_rate_table ath5k_rt_xr = AR5K_RATES_XR; |
40 | 40 | ||
41 | /*Prototypes*/ | 41 | /* Prototypes */ |
42 | static int ath5k_hw_nic_reset(struct ath5k_hw *, u32); | 42 | static int ath5k_hw_nic_reset(struct ath5k_hw *, u32); |
43 | static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool); | 43 | static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool); |
44 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | 44 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 7bb2646ae0ef..28b6ff3eaa37 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
@@ -2310,30 +2310,40 @@ static int atmel_get_scan(struct net_device *dev, | |||
2310 | iwe.cmd = SIOCGIWAP; | 2310 | iwe.cmd = SIOCGIWAP; |
2311 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 2311 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
2312 | memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6); | 2312 | memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6); |
2313 | current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN); | 2313 | current_ev = iwe_stream_add_event(info, current_ev, |
2314 | extra + IW_SCAN_MAX_DATA, | ||
2315 | &iwe, IW_EV_ADDR_LEN); | ||
2314 | 2316 | ||
2315 | iwe.u.data.length = priv->BSSinfo[i].SSIDsize; | 2317 | iwe.u.data.length = priv->BSSinfo[i].SSIDsize; |
2316 | if (iwe.u.data.length > 32) | 2318 | if (iwe.u.data.length > 32) |
2317 | iwe.u.data.length = 32; | 2319 | iwe.u.data.length = 32; |
2318 | iwe.cmd = SIOCGIWESSID; | 2320 | iwe.cmd = SIOCGIWESSID; |
2319 | iwe.u.data.flags = 1; | 2321 | iwe.u.data.flags = 1; |
2320 | current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID); | 2322 | current_ev = iwe_stream_add_point(info, current_ev, |
2323 | extra + IW_SCAN_MAX_DATA, | ||
2324 | &iwe, priv->BSSinfo[i].SSID); | ||
2321 | 2325 | ||
2322 | iwe.cmd = SIOCGIWMODE; | 2326 | iwe.cmd = SIOCGIWMODE; |
2323 | iwe.u.mode = priv->BSSinfo[i].BSStype; | 2327 | iwe.u.mode = priv->BSSinfo[i].BSStype; |
2324 | current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN); | 2328 | current_ev = iwe_stream_add_event(info, current_ev, |
2329 | extra + IW_SCAN_MAX_DATA, | ||
2330 | &iwe, IW_EV_UINT_LEN); | ||
2325 | 2331 | ||
2326 | iwe.cmd = SIOCGIWFREQ; | 2332 | iwe.cmd = SIOCGIWFREQ; |
2327 | iwe.u.freq.m = priv->BSSinfo[i].channel; | 2333 | iwe.u.freq.m = priv->BSSinfo[i].channel; |
2328 | iwe.u.freq.e = 0; | 2334 | iwe.u.freq.e = 0; |
2329 | current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN); | 2335 | current_ev = iwe_stream_add_event(info, current_ev, |
2336 | extra + IW_SCAN_MAX_DATA, | ||
2337 | &iwe, IW_EV_FREQ_LEN); | ||
2330 | 2338 | ||
2331 | /* Add quality statistics */ | 2339 | /* Add quality statistics */ |
2332 | iwe.cmd = IWEVQUAL; | 2340 | iwe.cmd = IWEVQUAL; |
2333 | iwe.u.qual.level = priv->BSSinfo[i].RSSI; | 2341 | iwe.u.qual.level = priv->BSSinfo[i].RSSI; |
2334 | iwe.u.qual.qual = iwe.u.qual.level; | 2342 | iwe.u.qual.qual = iwe.u.qual.level; |
2335 | /* iwe.u.qual.noise = SOMETHING */ | 2343 | /* iwe.u.qual.noise = SOMETHING */ |
2336 | current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA , &iwe, IW_EV_QUAL_LEN); | 2344 | current_ev = iwe_stream_add_event(info, current_ev, |
2345 | extra + IW_SCAN_MAX_DATA, | ||
2346 | &iwe, IW_EV_QUAL_LEN); | ||
2337 | 2347 | ||
2338 | 2348 | ||
2339 | iwe.cmd = SIOCGIWENCODE; | 2349 | iwe.cmd = SIOCGIWENCODE; |
@@ -2342,7 +2352,9 @@ static int atmel_get_scan(struct net_device *dev, | |||
2342 | else | 2352 | else |
2343 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 2353 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
2344 | iwe.u.data.length = 0; | 2354 | iwe.u.data.length = 0; |
2345 | current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL); | 2355 | current_ev = iwe_stream_add_point(info, current_ev, |
2356 | extra + IW_SCAN_MAX_DATA, | ||
2357 | &iwe, NULL); | ||
2346 | } | 2358 | } |
2347 | 2359 | ||
2348 | /* Length of data */ | 2360 | /* Length of data */ |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 532365f5ecef..edcdfa366452 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -441,6 +441,8 @@ enum { | |||
441 | #define B43_FWPANIC_DIE 0 /* Firmware died. Don't auto-restart it. */ | 441 | #define B43_FWPANIC_DIE 0 /* Firmware died. Don't auto-restart it. */ |
442 | #define B43_FWPANIC_RESTART 1 /* Firmware died. Schedule a controller reset. */ | 442 | #define B43_FWPANIC_RESTART 1 /* Firmware died. Schedule a controller reset. */ |
443 | 443 | ||
444 | /* The firmware register that contains the watchdog counter. */ | ||
445 | #define B43_WATCHDOG_REG 1 | ||
444 | 446 | ||
445 | /* Device specific rate values. | 447 | /* Device specific rate values. |
446 | * The actual values defined here are (rate_in_mbps * 2). | 448 | * The actual values defined here are (rate_in_mbps * 2). |
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 210e2789c1c3..29851bc1101f 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c | |||
@@ -74,70 +74,327 @@ struct b43_dfs_file * fops_to_dfs_file(struct b43_wldev *dev, | |||
74 | } while (0) | 74 | } while (0) |
75 | 75 | ||
76 | 76 | ||
77 | /* wl->irq_lock is locked */ | 77 | /* The biggest address values for SHM access from the debugfs files. */ |
78 | static ssize_t tsf_read_file(struct b43_wldev *dev, | 78 | #define B43_MAX_SHM_ROUTING 4 |
79 | char *buf, size_t bufsize) | 79 | #define B43_MAX_SHM_ADDR 0xFFFF |
80 | |||
81 | static ssize_t shm16read__read_file(struct b43_wldev *dev, | ||
82 | char *buf, size_t bufsize) | ||
80 | { | 83 | { |
81 | ssize_t count = 0; | 84 | ssize_t count = 0; |
82 | u64 tsf; | 85 | unsigned int routing, addr; |
86 | u16 val; | ||
83 | 87 | ||
84 | b43_tsf_read(dev, &tsf); | 88 | routing = dev->dfsentry->shm16read_routing_next; |
85 | fappend("0x%08x%08x\n", | 89 | addr = dev->dfsentry->shm16read_addr_next; |
86 | (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), | 90 | if ((routing > B43_MAX_SHM_ROUTING) || |
87 | (unsigned int)(tsf & 0xFFFFFFFFULL)); | 91 | (addr > B43_MAX_SHM_ADDR)) |
92 | return -EDESTADDRREQ; | ||
93 | |||
94 | val = b43_shm_read16(dev, routing, addr); | ||
95 | fappend("0x%04X\n", val); | ||
88 | 96 | ||
89 | return count; | 97 | return count; |
90 | } | 98 | } |
91 | 99 | ||
92 | /* wl->irq_lock is locked */ | 100 | static int shm16read__write_file(struct b43_wldev *dev, |
93 | static int tsf_write_file(struct b43_wldev *dev, | 101 | const char *buf, size_t count) |
94 | const char *buf, size_t count) | ||
95 | { | 102 | { |
96 | u64 tsf; | 103 | unsigned int routing, addr; |
104 | int res; | ||
97 | 105 | ||
98 | if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1) | 106 | res = sscanf(buf, "0x%X 0x%X", &routing, &addr); |
107 | if (res != 2) | ||
99 | return -EINVAL; | 108 | return -EINVAL; |
100 | b43_tsf_write(dev, tsf); | 109 | if (routing > B43_MAX_SHM_ROUTING) |
110 | return -EADDRNOTAVAIL; | ||
111 | if (addr > B43_MAX_SHM_ADDR) | ||
112 | return -EADDRNOTAVAIL; | ||
113 | if (routing == B43_SHM_SHARED) { | ||
114 | if ((addr % 2) != 0) | ||
115 | return -EADDRNOTAVAIL; | ||
116 | } | ||
117 | |||
118 | dev->dfsentry->shm16read_routing_next = routing; | ||
119 | dev->dfsentry->shm16read_addr_next = addr; | ||
101 | 120 | ||
102 | return 0; | 121 | return 0; |
103 | } | 122 | } |
104 | 123 | ||
105 | /* wl->irq_lock is locked */ | 124 | static int shm16write__write_file(struct b43_wldev *dev, |
106 | static ssize_t ucode_regs_read_file(struct b43_wldev *dev, | 125 | const char *buf, size_t count) |
126 | { | ||
127 | unsigned int routing, addr, mask, set; | ||
128 | u16 val; | ||
129 | int res; | ||
130 | unsigned long flags; | ||
131 | |||
132 | res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", | ||
133 | &routing, &addr, &mask, &set); | ||
134 | if (res != 4) | ||
135 | return -EINVAL; | ||
136 | if (routing > B43_MAX_SHM_ROUTING) | ||
137 | return -EADDRNOTAVAIL; | ||
138 | if (addr > B43_MAX_SHM_ADDR) | ||
139 | return -EADDRNOTAVAIL; | ||
140 | if (routing == B43_SHM_SHARED) { | ||
141 | if ((addr % 2) != 0) | ||
142 | return -EADDRNOTAVAIL; | ||
143 | } | ||
144 | if ((mask > 0xFFFF) || (set > 0xFFFF)) | ||
145 | return -E2BIG; | ||
146 | |||
147 | spin_lock_irqsave(&dev->wl->shm_lock, flags); | ||
148 | if (mask == 0) | ||
149 | val = 0; | ||
150 | else | ||
151 | val = __b43_shm_read16(dev, routing, addr); | ||
152 | val &= mask; | ||
153 | val |= set; | ||
154 | __b43_shm_write16(dev, routing, addr, val); | ||
155 | spin_unlock_irqrestore(&dev->wl->shm_lock, flags); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static ssize_t shm32read__read_file(struct b43_wldev *dev, | ||
107 | char *buf, size_t bufsize) | 161 | char *buf, size_t bufsize) |
108 | { | 162 | { |
109 | ssize_t count = 0; | 163 | ssize_t count = 0; |
110 | int i; | 164 | unsigned int routing, addr; |
165 | u32 val; | ||
166 | |||
167 | routing = dev->dfsentry->shm32read_routing_next; | ||
168 | addr = dev->dfsentry->shm32read_addr_next; | ||
169 | if ((routing > B43_MAX_SHM_ROUTING) || | ||
170 | (addr > B43_MAX_SHM_ADDR)) | ||
171 | return -EDESTADDRREQ; | ||
111 | 172 | ||
112 | for (i = 0; i < 64; i++) { | 173 | val = b43_shm_read32(dev, routing, addr); |
113 | fappend("r%d = 0x%04x\n", i, | 174 | fappend("0x%08X\n", val); |
114 | b43_shm_read16(dev, B43_SHM_SCRATCH, i)); | 175 | |
176 | return count; | ||
177 | } | ||
178 | |||
179 | static int shm32read__write_file(struct b43_wldev *dev, | ||
180 | const char *buf, size_t count) | ||
181 | { | ||
182 | unsigned int routing, addr; | ||
183 | int res; | ||
184 | |||
185 | res = sscanf(buf, "0x%X 0x%X", &routing, &addr); | ||
186 | if (res != 2) | ||
187 | return -EINVAL; | ||
188 | if (routing > B43_MAX_SHM_ROUTING) | ||
189 | return -EADDRNOTAVAIL; | ||
190 | if (addr > B43_MAX_SHM_ADDR) | ||
191 | return -EADDRNOTAVAIL; | ||
192 | if (routing == B43_SHM_SHARED) { | ||
193 | if ((addr % 2) != 0) | ||
194 | return -EADDRNOTAVAIL; | ||
195 | } | ||
196 | |||
197 | dev->dfsentry->shm32read_routing_next = routing; | ||
198 | dev->dfsentry->shm32read_addr_next = addr; | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int shm32write__write_file(struct b43_wldev *dev, | ||
204 | const char *buf, size_t count) | ||
205 | { | ||
206 | unsigned int routing, addr, mask, set; | ||
207 | u32 val; | ||
208 | int res; | ||
209 | unsigned long flags; | ||
210 | |||
211 | res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", | ||
212 | &routing, &addr, &mask, &set); | ||
213 | if (res != 4) | ||
214 | return -EINVAL; | ||
215 | if (routing > B43_MAX_SHM_ROUTING) | ||
216 | return -EADDRNOTAVAIL; | ||
217 | if (addr > B43_MAX_SHM_ADDR) | ||
218 | return -EADDRNOTAVAIL; | ||
219 | if (routing == B43_SHM_SHARED) { | ||
220 | if ((addr % 2) != 0) | ||
221 | return -EADDRNOTAVAIL; | ||
115 | } | 222 | } |
223 | if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) | ||
224 | return -E2BIG; | ||
225 | |||
226 | spin_lock_irqsave(&dev->wl->shm_lock, flags); | ||
227 | if (mask == 0) | ||
228 | val = 0; | ||
229 | else | ||
230 | val = __b43_shm_read32(dev, routing, addr); | ||
231 | val &= mask; | ||
232 | val |= set; | ||
233 | __b43_shm_write32(dev, routing, addr, val); | ||
234 | spin_unlock_irqrestore(&dev->wl->shm_lock, flags); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | /* The biggest MMIO address that we allow access to from the debugfs files. */ | ||
240 | #define B43_MAX_MMIO_ACCESS (0xF00 - 1) | ||
241 | |||
242 | static ssize_t mmio16read__read_file(struct b43_wldev *dev, | ||
243 | char *buf, size_t bufsize) | ||
244 | { | ||
245 | ssize_t count = 0; | ||
246 | unsigned int addr; | ||
247 | u16 val; | ||
248 | |||
249 | addr = dev->dfsentry->mmio16read_next; | ||
250 | if (addr > B43_MAX_MMIO_ACCESS) | ||
251 | return -EDESTADDRREQ; | ||
252 | |||
253 | val = b43_read16(dev, addr); | ||
254 | fappend("0x%04X\n", val); | ||
255 | |||
256 | return count; | ||
257 | } | ||
258 | |||
259 | static int mmio16read__write_file(struct b43_wldev *dev, | ||
260 | const char *buf, size_t count) | ||
261 | { | ||
262 | unsigned int addr; | ||
263 | int res; | ||
264 | |||
265 | res = sscanf(buf, "0x%X", &addr); | ||
266 | if (res != 1) | ||
267 | return -EINVAL; | ||
268 | if (addr > B43_MAX_MMIO_ACCESS) | ||
269 | return -EADDRNOTAVAIL; | ||
270 | if ((addr % 2) != 0) | ||
271 | return -EINVAL; | ||
272 | |||
273 | dev->dfsentry->mmio16read_next = addr; | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int mmio16write__write_file(struct b43_wldev *dev, | ||
279 | const char *buf, size_t count) | ||
280 | { | ||
281 | unsigned int addr, mask, set; | ||
282 | int res; | ||
283 | u16 val; | ||
284 | |||
285 | res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set); | ||
286 | if (res != 3) | ||
287 | return -EINVAL; | ||
288 | if (addr > B43_MAX_MMIO_ACCESS) | ||
289 | return -EADDRNOTAVAIL; | ||
290 | if ((mask > 0xFFFF) || (set > 0xFFFF)) | ||
291 | return -E2BIG; | ||
292 | if ((addr % 2) != 0) | ||
293 | return -EINVAL; | ||
294 | |||
295 | if (mask == 0) | ||
296 | val = 0; | ||
297 | else | ||
298 | val = b43_read16(dev, addr); | ||
299 | val &= mask; | ||
300 | val |= set; | ||
301 | b43_write16(dev, addr, val); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static ssize_t mmio32read__read_file(struct b43_wldev *dev, | ||
307 | char *buf, size_t bufsize) | ||
308 | { | ||
309 | ssize_t count = 0; | ||
310 | unsigned int addr; | ||
311 | u32 val; | ||
312 | |||
313 | addr = dev->dfsentry->mmio32read_next; | ||
314 | if (addr > B43_MAX_MMIO_ACCESS) | ||
315 | return -EDESTADDRREQ; | ||
316 | |||
317 | val = b43_read32(dev, addr); | ||
318 | fappend("0x%08X\n", val); | ||
116 | 319 | ||
117 | return count; | 320 | return count; |
118 | } | 321 | } |
119 | 322 | ||
323 | static int mmio32read__write_file(struct b43_wldev *dev, | ||
324 | const char *buf, size_t count) | ||
325 | { | ||
326 | unsigned int addr; | ||
327 | int res; | ||
328 | |||
329 | res = sscanf(buf, "0x%X", &addr); | ||
330 | if (res != 1) | ||
331 | return -EINVAL; | ||
332 | if (addr > B43_MAX_MMIO_ACCESS) | ||
333 | return -EADDRNOTAVAIL; | ||
334 | if ((addr % 4) != 0) | ||
335 | return -EINVAL; | ||
336 | |||
337 | dev->dfsentry->mmio32read_next = addr; | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int mmio32write__write_file(struct b43_wldev *dev, | ||
343 | const char *buf, size_t count) | ||
344 | { | ||
345 | unsigned int addr, mask, set; | ||
346 | int res; | ||
347 | u32 val; | ||
348 | |||
349 | res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set); | ||
350 | if (res != 3) | ||
351 | return -EINVAL; | ||
352 | if (addr > B43_MAX_MMIO_ACCESS) | ||
353 | return -EADDRNOTAVAIL; | ||
354 | if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) | ||
355 | return -E2BIG; | ||
356 | if ((addr % 4) != 0) | ||
357 | return -EINVAL; | ||
358 | |||
359 | if (mask == 0) | ||
360 | val = 0; | ||
361 | else | ||
362 | val = b43_read32(dev, addr); | ||
363 | val &= mask; | ||
364 | val |= set; | ||
365 | b43_write32(dev, addr, val); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
120 | /* wl->irq_lock is locked */ | 370 | /* wl->irq_lock is locked */ |
121 | static ssize_t shm_read_file(struct b43_wldev *dev, | 371 | static ssize_t tsf_read_file(struct b43_wldev *dev, |
122 | char *buf, size_t bufsize) | 372 | char *buf, size_t bufsize) |
123 | { | 373 | { |
124 | ssize_t count = 0; | 374 | ssize_t count = 0; |
125 | int i; | 375 | u64 tsf; |
126 | u16 tmp; | ||
127 | __le16 *le16buf = (__le16 *)buf; | ||
128 | 376 | ||
129 | for (i = 0; i < 0x1000; i++) { | 377 | b43_tsf_read(dev, &tsf); |
130 | if (bufsize < sizeof(tmp)) | 378 | fappend("0x%08x%08x\n", |
131 | break; | 379 | (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), |
132 | tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i); | 380 | (unsigned int)(tsf & 0xFFFFFFFFULL)); |
133 | le16buf[i] = cpu_to_le16(tmp); | ||
134 | count += sizeof(tmp); | ||
135 | bufsize -= sizeof(tmp); | ||
136 | } | ||
137 | 381 | ||
138 | return count; | 382 | return count; |
139 | } | 383 | } |
140 | 384 | ||
385 | /* wl->irq_lock is locked */ | ||
386 | static int tsf_write_file(struct b43_wldev *dev, | ||
387 | const char *buf, size_t count) | ||
388 | { | ||
389 | u64 tsf; | ||
390 | |||
391 | if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1) | ||
392 | return -EINVAL; | ||
393 | b43_tsf_write(dev, tsf); | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
141 | static ssize_t txstat_read_file(struct b43_wldev *dev, | 398 | static ssize_t txstat_read_file(struct b43_wldev *dev, |
142 | char *buf, size_t bufsize) | 399 | char *buf, size_t bufsize) |
143 | { | 400 | { |
@@ -496,9 +753,15 @@ out_unlock: | |||
496 | .take_irqlock = _take_irqlock, \ | 753 | .take_irqlock = _take_irqlock, \ |
497 | } | 754 | } |
498 | 755 | ||
756 | B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file, 1); | ||
757 | B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file, 1); | ||
758 | B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file, 1); | ||
759 | B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file, 1); | ||
760 | B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); | ||
761 | B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); | ||
762 | B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); | ||
763 | B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); | ||
499 | B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); | 764 | B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); |
500 | B43_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1); | ||
501 | B43_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1); | ||
502 | B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); | 765 | B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); |
503 | B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0); | 766 | B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0); |
504 | B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); | 767 | B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); |
@@ -538,6 +801,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) | |||
538 | add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); | 801 | add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); |
539 | add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); | 802 | add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); |
540 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); | 803 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); |
804 | add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); | ||
541 | 805 | ||
542 | #undef add_dyn_dbg | 806 | #undef add_dyn_dbg |
543 | } | 807 | } |
@@ -584,6 +848,13 @@ void b43_debugfs_add_device(struct b43_wldev *dev) | |||
584 | return; | 848 | return; |
585 | } | 849 | } |
586 | 850 | ||
851 | e->mmio16read_next = 0xFFFF; /* invalid address */ | ||
852 | e->mmio32read_next = 0xFFFF; /* invalid address */ | ||
853 | e->shm16read_routing_next = 0xFFFFFFFF; /* invalid routing */ | ||
854 | e->shm16read_addr_next = 0xFFFFFFFF; /* invalid address */ | ||
855 | e->shm32read_routing_next = 0xFFFFFFFF; /* invalid routing */ | ||
856 | e->shm32read_addr_next = 0xFFFFFFFF; /* invalid address */ | ||
857 | |||
587 | #define ADD_FILE(name, mode) \ | 858 | #define ADD_FILE(name, mode) \ |
588 | do { \ | 859 | do { \ |
589 | struct dentry *d; \ | 860 | struct dentry *d; \ |
@@ -596,9 +867,15 @@ void b43_debugfs_add_device(struct b43_wldev *dev) | |||
596 | } while (0) | 867 | } while (0) |
597 | 868 | ||
598 | 869 | ||
870 | ADD_FILE(shm16read, 0600); | ||
871 | ADD_FILE(shm16write, 0200); | ||
872 | ADD_FILE(shm32read, 0600); | ||
873 | ADD_FILE(shm32write, 0200); | ||
874 | ADD_FILE(mmio16read, 0600); | ||
875 | ADD_FILE(mmio16write, 0200); | ||
876 | ADD_FILE(mmio32read, 0600); | ||
877 | ADD_FILE(mmio32write, 0200); | ||
599 | ADD_FILE(tsf, 0600); | 878 | ADD_FILE(tsf, 0600); |
600 | ADD_FILE(ucode_regs, 0400); | ||
601 | ADD_FILE(shm, 0400); | ||
602 | ADD_FILE(txstat, 0400); | 879 | ADD_FILE(txstat, 0400); |
603 | ADD_FILE(txpower_g, 0600); | 880 | ADD_FILE(txpower_g, 0600); |
604 | ADD_FILE(restart, 0200); | 881 | ADD_FILE(restart, 0200); |
@@ -620,9 +897,15 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) | |||
620 | return; | 897 | return; |
621 | b43_remove_dynamic_debug(dev); | 898 | b43_remove_dynamic_debug(dev); |
622 | 899 | ||
900 | debugfs_remove(e->file_shm16read.dentry); | ||
901 | debugfs_remove(e->file_shm16write.dentry); | ||
902 | debugfs_remove(e->file_shm32read.dentry); | ||
903 | debugfs_remove(e->file_shm32write.dentry); | ||
904 | debugfs_remove(e->file_mmio16read.dentry); | ||
905 | debugfs_remove(e->file_mmio16write.dentry); | ||
906 | debugfs_remove(e->file_mmio32read.dentry); | ||
907 | debugfs_remove(e->file_mmio32write.dentry); | ||
623 | debugfs_remove(e->file_tsf.dentry); | 908 | debugfs_remove(e->file_tsf.dentry); |
624 | debugfs_remove(e->file_ucode_regs.dentry); | ||
625 | debugfs_remove(e->file_shm.dentry); | ||
626 | debugfs_remove(e->file_txstat.dentry); | 909 | debugfs_remove(e->file_txstat.dentry); |
627 | debugfs_remove(e->file_txpower_g.dentry); | 910 | debugfs_remove(e->file_txpower_g.dentry); |
628 | debugfs_remove(e->file_restart.dentry); | 911 | debugfs_remove(e->file_restart.dentry); |
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index c75cff4151d9..22ffd02ba554 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h | |||
@@ -11,6 +11,7 @@ enum b43_dyndbg { /* Dynamic debugging features */ | |||
11 | B43_DBG_PWORK_FAST, | 11 | B43_DBG_PWORK_FAST, |
12 | B43_DBG_PWORK_STOP, | 12 | B43_DBG_PWORK_STOP, |
13 | B43_DBG_LO, | 13 | B43_DBG_LO, |
14 | B43_DBG_FIRMWARE, | ||
14 | __B43_NR_DYNDBG, | 15 | __B43_NR_DYNDBG, |
15 | }; | 16 | }; |
16 | 17 | ||
@@ -36,9 +37,15 @@ struct b43_dfsentry { | |||
36 | struct b43_wldev *dev; | 37 | struct b43_wldev *dev; |
37 | struct dentry *subdir; | 38 | struct dentry *subdir; |
38 | 39 | ||
40 | struct b43_dfs_file file_shm16read; | ||
41 | struct b43_dfs_file file_shm16write; | ||
42 | struct b43_dfs_file file_shm32read; | ||
43 | struct b43_dfs_file file_shm32write; | ||
44 | struct b43_dfs_file file_mmio16read; | ||
45 | struct b43_dfs_file file_mmio16write; | ||
46 | struct b43_dfs_file file_mmio32read; | ||
47 | struct b43_dfs_file file_mmio32write; | ||
39 | struct b43_dfs_file file_tsf; | 48 | struct b43_dfs_file file_tsf; |
40 | struct b43_dfs_file file_ucode_regs; | ||
41 | struct b43_dfs_file file_shm; | ||
42 | struct b43_dfs_file file_txstat; | 49 | struct b43_dfs_file file_txstat; |
43 | struct b43_dfs_file file_txpower_g; | 50 | struct b43_dfs_file file_txpower_g; |
44 | struct b43_dfs_file file_restart; | 51 | struct b43_dfs_file file_restart; |
@@ -46,6 +53,18 @@ struct b43_dfsentry { | |||
46 | 53 | ||
47 | struct b43_txstatus_log txstatlog; | 54 | struct b43_txstatus_log txstatlog; |
48 | 55 | ||
56 | /* The cached address for the next mmio16read file read */ | ||
57 | u16 mmio16read_next; | ||
58 | /* The cached address for the next mmio32read file read */ | ||
59 | u16 mmio32read_next; | ||
60 | |||
61 | /* The cached address for the next shm16read file read */ | ||
62 | u32 shm16read_routing_next; | ||
63 | u32 shm16read_addr_next; | ||
64 | /* The cached address for the next shm32read file read */ | ||
65 | u32 shm32read_routing_next; | ||
66 | u32 shm32read_addr_next; | ||
67 | |||
49 | /* Enabled/Disabled list for the dynamic debugging features. */ | 68 | /* Enabled/Disabled list for the dynamic debugging features. */ |
50 | u32 dyn_debug[__B43_NR_DYNDBG]; | 69 | u32 dyn_debug[__B43_NR_DYNDBG]; |
51 | /* Dentries for the dynamic debugging entries. */ | 70 | /* Dentries for the dynamic debugging entries. */ |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 8a09a1db08db..098f886976f6 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -328,11 +328,11 @@ static inline | |||
328 | dma_addr_t dmaaddr; | 328 | dma_addr_t dmaaddr; |
329 | 329 | ||
330 | if (tx) { | 330 | if (tx) { |
331 | dmaaddr = dma_map_single(ring->dev->dev->dma_dev, | 331 | dmaaddr = ssb_dma_map_single(ring->dev->dev, |
332 | buf, len, DMA_TO_DEVICE); | 332 | buf, len, DMA_TO_DEVICE); |
333 | } else { | 333 | } else { |
334 | dmaaddr = dma_map_single(ring->dev->dev->dma_dev, | 334 | dmaaddr = ssb_dma_map_single(ring->dev->dev, |
335 | buf, len, DMA_FROM_DEVICE); | 335 | buf, len, DMA_FROM_DEVICE); |
336 | } | 336 | } |
337 | 337 | ||
338 | return dmaaddr; | 338 | return dmaaddr; |
@@ -343,11 +343,11 @@ static inline | |||
343 | dma_addr_t addr, size_t len, int tx) | 343 | dma_addr_t addr, size_t len, int tx) |
344 | { | 344 | { |
345 | if (tx) { | 345 | if (tx) { |
346 | dma_unmap_single(ring->dev->dev->dma_dev, | 346 | ssb_dma_unmap_single(ring->dev->dev, |
347 | addr, len, DMA_TO_DEVICE); | 347 | addr, len, DMA_TO_DEVICE); |
348 | } else { | 348 | } else { |
349 | dma_unmap_single(ring->dev->dev->dma_dev, | 349 | ssb_dma_unmap_single(ring->dev->dev, |
350 | addr, len, DMA_FROM_DEVICE); | 350 | addr, len, DMA_FROM_DEVICE); |
351 | } | 351 | } |
352 | } | 352 | } |
353 | 353 | ||
@@ -356,8 +356,8 @@ static inline | |||
356 | dma_addr_t addr, size_t len) | 356 | dma_addr_t addr, size_t len) |
357 | { | 357 | { |
358 | B43_WARN_ON(ring->tx); | 358 | B43_WARN_ON(ring->tx); |
359 | dma_sync_single_for_cpu(ring->dev->dev->dma_dev, | 359 | ssb_dma_sync_single_for_cpu(ring->dev->dev, |
360 | addr, len, DMA_FROM_DEVICE); | 360 | addr, len, DMA_FROM_DEVICE); |
361 | } | 361 | } |
362 | 362 | ||
363 | static inline | 363 | static inline |
@@ -365,8 +365,8 @@ static inline | |||
365 | dma_addr_t addr, size_t len) | 365 | dma_addr_t addr, size_t len) |
366 | { | 366 | { |
367 | B43_WARN_ON(ring->tx); | 367 | B43_WARN_ON(ring->tx); |
368 | dma_sync_single_for_device(ring->dev->dev->dma_dev, | 368 | ssb_dma_sync_single_for_device(ring->dev->dev, |
369 | addr, len, DMA_FROM_DEVICE); | 369 | addr, len, DMA_FROM_DEVICE); |
370 | } | 370 | } |
371 | 371 | ||
372 | static inline | 372 | static inline |
@@ -381,7 +381,6 @@ static inline | |||
381 | 381 | ||
382 | static int alloc_ringmemory(struct b43_dmaring *ring) | 382 | static int alloc_ringmemory(struct b43_dmaring *ring) |
383 | { | 383 | { |
384 | struct device *dma_dev = ring->dev->dev->dma_dev; | ||
385 | gfp_t flags = GFP_KERNEL; | 384 | gfp_t flags = GFP_KERNEL; |
386 | 385 | ||
387 | /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K | 386 | /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K |
@@ -392,11 +391,14 @@ static int alloc_ringmemory(struct b43_dmaring *ring) | |||
392 | * For unknown reasons - possibly a hardware error - the BCM4311 rev | 391 | * For unknown reasons - possibly a hardware error - the BCM4311 rev |
393 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, | 392 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, |
394 | * which accounts for the GFP_DMA flag below. | 393 | * which accounts for the GFP_DMA flag below. |
394 | * | ||
395 | * The flags here must match the flags in free_ringmemory below! | ||
395 | */ | 396 | */ |
396 | if (ring->type == B43_DMA_64BIT) | 397 | if (ring->type == B43_DMA_64BIT) |
397 | flags |= GFP_DMA; | 398 | flags |= GFP_DMA; |
398 | ring->descbase = dma_alloc_coherent(dma_dev, B43_DMA_RINGMEMSIZE, | 399 | ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, |
399 | &(ring->dmabase), flags); | 400 | B43_DMA_RINGMEMSIZE, |
401 | &(ring->dmabase), flags); | ||
400 | if (!ring->descbase) { | 402 | if (!ring->descbase) { |
401 | b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); | 403 | b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); |
402 | return -ENOMEM; | 404 | return -ENOMEM; |
@@ -408,10 +410,13 @@ static int alloc_ringmemory(struct b43_dmaring *ring) | |||
408 | 410 | ||
409 | static void free_ringmemory(struct b43_dmaring *ring) | 411 | static void free_ringmemory(struct b43_dmaring *ring) |
410 | { | 412 | { |
411 | struct device *dma_dev = ring->dev->dev->dma_dev; | 413 | gfp_t flags = GFP_KERNEL; |
414 | |||
415 | if (ring->type == B43_DMA_64BIT) | ||
416 | flags |= GFP_DMA; | ||
412 | 417 | ||
413 | dma_free_coherent(dma_dev, B43_DMA_RINGMEMSIZE, | 418 | ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, |
414 | ring->descbase, ring->dmabase); | 419 | ring->descbase, ring->dmabase, flags); |
415 | } | 420 | } |
416 | 421 | ||
417 | /* Reset the RX DMA channel */ | 422 | /* Reset the RX DMA channel */ |
@@ -518,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, | |||
518 | dma_addr_t addr, | 523 | dma_addr_t addr, |
519 | size_t buffersize, bool dma_to_device) | 524 | size_t buffersize, bool dma_to_device) |
520 | { | 525 | { |
521 | if (unlikely(dma_mapping_error(addr))) | 526 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) |
522 | return 1; | 527 | return 1; |
523 | 528 | ||
524 | switch (ring->type) { | 529 | switch (ring->type) { |
@@ -844,10 +849,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
844 | goto err_kfree_meta; | 849 | goto err_kfree_meta; |
845 | 850 | ||
846 | /* test for ability to dma to txhdr_cache */ | 851 | /* test for ability to dma to txhdr_cache */ |
847 | dma_test = dma_map_single(dev->dev->dma_dev, | 852 | dma_test = ssb_dma_map_single(dev->dev, |
848 | ring->txhdr_cache, | 853 | ring->txhdr_cache, |
849 | b43_txhdr_size(dev), | 854 | b43_txhdr_size(dev), |
850 | DMA_TO_DEVICE); | 855 | DMA_TO_DEVICE); |
851 | 856 | ||
852 | if (b43_dma_mapping_error(ring, dma_test, | 857 | if (b43_dma_mapping_error(ring, dma_test, |
853 | b43_txhdr_size(dev), 1)) { | 858 | b43_txhdr_size(dev), 1)) { |
@@ -859,10 +864,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
859 | if (!ring->txhdr_cache) | 864 | if (!ring->txhdr_cache) |
860 | goto err_kfree_meta; | 865 | goto err_kfree_meta; |
861 | 866 | ||
862 | dma_test = dma_map_single(dev->dev->dma_dev, | 867 | dma_test = ssb_dma_map_single(dev->dev, |
863 | ring->txhdr_cache, | 868 | ring->txhdr_cache, |
864 | b43_txhdr_size(dev), | 869 | b43_txhdr_size(dev), |
865 | DMA_TO_DEVICE); | 870 | DMA_TO_DEVICE); |
866 | 871 | ||
867 | if (b43_dma_mapping_error(ring, dma_test, | 872 | if (b43_dma_mapping_error(ring, dma_test, |
868 | b43_txhdr_size(dev), 1)) { | 873 | b43_txhdr_size(dev), 1)) { |
@@ -873,9 +878,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
873 | } | 878 | } |
874 | } | 879 | } |
875 | 880 | ||
876 | dma_unmap_single(dev->dev->dma_dev, | 881 | ssb_dma_unmap_single(dev->dev, |
877 | dma_test, b43_txhdr_size(dev), | 882 | dma_test, b43_txhdr_size(dev), |
878 | DMA_TO_DEVICE); | 883 | DMA_TO_DEVICE); |
879 | } | 884 | } |
880 | 885 | ||
881 | err = alloc_ringmemory(ring); | 886 | err = alloc_ringmemory(ring); |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 704dd3551fff..9d2eb273b726 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -373,13 +373,10 @@ static inline void b43_shm_control_word(struct b43_wldev *dev, | |||
373 | b43_write32(dev, B43_MMIO_SHM_CONTROL, control); | 373 | b43_write32(dev, B43_MMIO_SHM_CONTROL, control); |
374 | } | 374 | } |
375 | 375 | ||
376 | u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) | 376 | u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) |
377 | { | 377 | { |
378 | struct b43_wl *wl = dev->wl; | ||
379 | unsigned long flags; | ||
380 | u32 ret; | 378 | u32 ret; |
381 | 379 | ||
382 | spin_lock_irqsave(&wl->shm_lock, flags); | ||
383 | if (routing == B43_SHM_SHARED) { | 380 | if (routing == B43_SHM_SHARED) { |
384 | B43_WARN_ON(offset & 0x0001); | 381 | B43_WARN_ON(offset & 0x0001); |
385 | if (offset & 0x0003) { | 382 | if (offset & 0x0003) { |
@@ -397,18 +394,26 @@ u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) | |||
397 | b43_shm_control_word(dev, routing, offset); | 394 | b43_shm_control_word(dev, routing, offset); |
398 | ret = b43_read32(dev, B43_MMIO_SHM_DATA); | 395 | ret = b43_read32(dev, B43_MMIO_SHM_DATA); |
399 | out: | 396 | out: |
400 | spin_unlock_irqrestore(&wl->shm_lock, flags); | ||
401 | |||
402 | return ret; | 397 | return ret; |
403 | } | 398 | } |
404 | 399 | ||
405 | u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset) | 400 | u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) |
406 | { | 401 | { |
407 | struct b43_wl *wl = dev->wl; | 402 | struct b43_wl *wl = dev->wl; |
408 | unsigned long flags; | 403 | unsigned long flags; |
409 | u16 ret; | 404 | u32 ret; |
410 | 405 | ||
411 | spin_lock_irqsave(&wl->shm_lock, flags); | 406 | spin_lock_irqsave(&wl->shm_lock, flags); |
407 | ret = __b43_shm_read32(dev, routing, offset); | ||
408 | spin_unlock_irqrestore(&wl->shm_lock, flags); | ||
409 | |||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) | ||
414 | { | ||
415 | u16 ret; | ||
416 | |||
412 | if (routing == B43_SHM_SHARED) { | 417 | if (routing == B43_SHM_SHARED) { |
413 | B43_WARN_ON(offset & 0x0001); | 418 | B43_WARN_ON(offset & 0x0001); |
414 | if (offset & 0x0003) { | 419 | if (offset & 0x0003) { |
@@ -423,17 +428,24 @@ u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset) | |||
423 | b43_shm_control_word(dev, routing, offset); | 428 | b43_shm_control_word(dev, routing, offset); |
424 | ret = b43_read16(dev, B43_MMIO_SHM_DATA); | 429 | ret = b43_read16(dev, B43_MMIO_SHM_DATA); |
425 | out: | 430 | out: |
426 | spin_unlock_irqrestore(&wl->shm_lock, flags); | ||
427 | |||
428 | return ret; | 431 | return ret; |
429 | } | 432 | } |
430 | 433 | ||
431 | void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) | 434 | u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) |
432 | { | 435 | { |
433 | struct b43_wl *wl = dev->wl; | 436 | struct b43_wl *wl = dev->wl; |
434 | unsigned long flags; | 437 | unsigned long flags; |
438 | u16 ret; | ||
435 | 439 | ||
436 | spin_lock_irqsave(&wl->shm_lock, flags); | 440 | spin_lock_irqsave(&wl->shm_lock, flags); |
441 | ret = __b43_shm_read16(dev, routing, offset); | ||
442 | spin_unlock_irqrestore(&wl->shm_lock, flags); | ||
443 | |||
444 | return ret; | ||
445 | } | ||
446 | |||
447 | void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) | ||
448 | { | ||
437 | if (routing == B43_SHM_SHARED) { | 449 | if (routing == B43_SHM_SHARED) { |
438 | B43_WARN_ON(offset & 0x0001); | 450 | B43_WARN_ON(offset & 0x0001); |
439 | if (offset & 0x0003) { | 451 | if (offset & 0x0003) { |
@@ -443,35 +455,47 @@ void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) | |||
443 | (value >> 16) & 0xffff); | 455 | (value >> 16) & 0xffff); |
444 | b43_shm_control_word(dev, routing, (offset >> 2) + 1); | 456 | b43_shm_control_word(dev, routing, (offset >> 2) + 1); |
445 | b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff); | 457 | b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff); |
446 | goto out; | 458 | return; |
447 | } | 459 | } |
448 | offset >>= 2; | 460 | offset >>= 2; |
449 | } | 461 | } |
450 | b43_shm_control_word(dev, routing, offset); | 462 | b43_shm_control_word(dev, routing, offset); |
451 | b43_write32(dev, B43_MMIO_SHM_DATA, value); | 463 | b43_write32(dev, B43_MMIO_SHM_DATA, value); |
452 | out: | ||
453 | spin_unlock_irqrestore(&wl->shm_lock, flags); | ||
454 | } | 464 | } |
455 | 465 | ||
456 | void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) | 466 | void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) |
457 | { | 467 | { |
458 | struct b43_wl *wl = dev->wl; | 468 | struct b43_wl *wl = dev->wl; |
459 | unsigned long flags; | 469 | unsigned long flags; |
460 | 470 | ||
461 | spin_lock_irqsave(&wl->shm_lock, flags); | 471 | spin_lock_irqsave(&wl->shm_lock, flags); |
472 | __b43_shm_write32(dev, routing, offset, value); | ||
473 | spin_unlock_irqrestore(&wl->shm_lock, flags); | ||
474 | } | ||
475 | |||
476 | void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) | ||
477 | { | ||
462 | if (routing == B43_SHM_SHARED) { | 478 | if (routing == B43_SHM_SHARED) { |
463 | B43_WARN_ON(offset & 0x0001); | 479 | B43_WARN_ON(offset & 0x0001); |
464 | if (offset & 0x0003) { | 480 | if (offset & 0x0003) { |
465 | /* Unaligned access */ | 481 | /* Unaligned access */ |
466 | b43_shm_control_word(dev, routing, offset >> 2); | 482 | b43_shm_control_word(dev, routing, offset >> 2); |
467 | b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value); | 483 | b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value); |
468 | goto out; | 484 | return; |
469 | } | 485 | } |
470 | offset >>= 2; | 486 | offset >>= 2; |
471 | } | 487 | } |
472 | b43_shm_control_word(dev, routing, offset); | 488 | b43_shm_control_word(dev, routing, offset); |
473 | b43_write16(dev, B43_MMIO_SHM_DATA, value); | 489 | b43_write16(dev, B43_MMIO_SHM_DATA, value); |
474 | out: | 490 | } |
491 | |||
492 | void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) | ||
493 | { | ||
494 | struct b43_wl *wl = dev->wl; | ||
495 | unsigned long flags; | ||
496 | |||
497 | spin_lock_irqsave(&wl->shm_lock, flags); | ||
498 | __b43_shm_write16(dev, routing, offset, value); | ||
475 | spin_unlock_irqrestore(&wl->shm_lock, flags); | 499 | spin_unlock_irqrestore(&wl->shm_lock, flags); |
476 | } | 500 | } |
477 | 501 | ||
@@ -2463,6 +2487,19 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) | |||
2463 | /* http://bcm-specs.sipsolutions.net/EnableMac */ | 2487 | /* http://bcm-specs.sipsolutions.net/EnableMac */ |
2464 | void b43_mac_enable(struct b43_wldev *dev) | 2488 | void b43_mac_enable(struct b43_wldev *dev) |
2465 | { | 2489 | { |
2490 | if (b43_debug(dev, B43_DBG_FIRMWARE)) { | ||
2491 | u16 fwstate; | ||
2492 | |||
2493 | fwstate = b43_shm_read16(dev, B43_SHM_SHARED, | ||
2494 | B43_SHM_SH_UCODESTAT); | ||
2495 | if ((fwstate != B43_SHM_SH_UCODESTAT_SUSP) && | ||
2496 | (fwstate != B43_SHM_SH_UCODESTAT_SLEEP)) { | ||
2497 | b43err(dev->wl, "b43_mac_enable(): The firmware " | ||
2498 | "should be suspended, but current state is %u\n", | ||
2499 | fwstate); | ||
2500 | } | ||
2501 | } | ||
2502 | |||
2466 | dev->mac_suspended--; | 2503 | dev->mac_suspended--; |
2467 | B43_WARN_ON(dev->mac_suspended < 0); | 2504 | B43_WARN_ON(dev->mac_suspended < 0); |
2468 | if (dev->mac_suspended == 0) { | 2505 | if (dev->mac_suspended == 0) { |
@@ -2783,6 +2820,21 @@ static void b43_periodic_every30sec(struct b43_wldev *dev) | |||
2783 | static void b43_periodic_every15sec(struct b43_wldev *dev) | 2820 | static void b43_periodic_every15sec(struct b43_wldev *dev) |
2784 | { | 2821 | { |
2785 | struct b43_phy *phy = &dev->phy; | 2822 | struct b43_phy *phy = &dev->phy; |
2823 | u16 wdr; | ||
2824 | |||
2825 | if (dev->fw.opensource) { | ||
2826 | /* Check if the firmware is still alive. | ||
2827 | * It will reset the watchdog counter to 0 in its idle loop. */ | ||
2828 | wdr = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_WATCHDOG_REG); | ||
2829 | if (unlikely(wdr)) { | ||
2830 | b43err(dev->wl, "Firmware watchdog: The firmware died!\n"); | ||
2831 | b43_controller_restart(dev, "Firmware watchdog"); | ||
2832 | return; | ||
2833 | } else { | ||
2834 | b43_shm_write16(dev, B43_SHM_SCRATCH, | ||
2835 | B43_WATCHDOG_REG, 1); | ||
2836 | } | ||
2837 | } | ||
2786 | 2838 | ||
2787 | if (phy->type == B43_PHYTYPE_G) { | 2839 | if (phy->type == B43_PHYTYPE_G) { |
2788 | //TODO: update_aci_moving_average | 2840 | //TODO: update_aci_moving_average |
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index dad23c42b422..f871a252cb55 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -95,9 +95,13 @@ void b43_tsf_read(struct b43_wldev *dev, u64 * tsf); | |||
95 | void b43_tsf_write(struct b43_wldev *dev, u64 tsf); | 95 | void b43_tsf_write(struct b43_wldev *dev, u64 tsf); |
96 | 96 | ||
97 | u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); | 97 | u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); |
98 | u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); | ||
98 | u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); | 99 | u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); |
100 | u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); | ||
99 | void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); | 101 | void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); |
102 | void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); | ||
100 | void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); | 103 | void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); |
104 | void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); | ||
101 | 105 | ||
102 | u64 b43_hf_read(struct b43_wldev *dev); | 106 | u64 b43_hf_read(struct b43_wldev *dev); |
103 | void b43_hf_write(struct b43_wldev *dev, u64 value); | 107 | void b43_hf_write(struct b43_wldev *dev, u64 value); |
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 8b1555d95f1c..401591267592 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c | |||
@@ -586,7 +586,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, | |||
586 | 586 | ||
587 | spin_lock(&q->lock); /* IRQs are already disabled. */ | 587 | spin_lock(&q->lock); /* IRQs are already disabled. */ |
588 | 588 | ||
589 | info = (void *)pack->skb; | 589 | info = IEEE80211_SKB_CB(pack->skb); |
590 | memset(&info->status, 0, sizeof(info->status)); | 590 | memset(&info->status, 0, sizeof(info->status)); |
591 | 591 | ||
592 | b43_fill_txstatus_report(info, status); | 592 | b43_fill_txstatus_report(info, status); |
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 11f53cb1139e..4cca203992e8 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c | |||
@@ -88,7 +88,7 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) | |||
88 | goto out_unlock; | 88 | goto out_unlock; |
89 | err = 0; | 89 | err = 0; |
90 | switch (state) { | 90 | switch (state) { |
91 | case RFKILL_STATE_ON: | 91 | case RFKILL_STATE_UNBLOCKED: |
92 | if (!dev->radio_hw_enable) { | 92 | if (!dev->radio_hw_enable) { |
93 | /* No luck. We can't toggle the hardware RF-kill | 93 | /* No luck. We can't toggle the hardware RF-kill |
94 | * button from software. */ | 94 | * button from software. */ |
@@ -98,10 +98,13 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) | |||
98 | if (!dev->phy.radio_on) | 98 | if (!dev->phy.radio_on) |
99 | b43_radio_turn_on(dev); | 99 | b43_radio_turn_on(dev); |
100 | break; | 100 | break; |
101 | case RFKILL_STATE_OFF: | 101 | case RFKILL_STATE_SOFT_BLOCKED: |
102 | if (dev->phy.radio_on) | 102 | if (dev->phy.radio_on) |
103 | b43_radio_turn_off(dev, 0); | 103 | b43_radio_turn_off(dev, 0); |
104 | break; | 104 | break; |
105 | default: | ||
106 | b43warn(wl, "Received unexpected rfkill state %d.\n", state); | ||
107 | break; | ||
105 | } | 108 | } |
106 | out_unlock: | 109 | out_unlock: |
107 | mutex_unlock(&wl->mutex); | 110 | mutex_unlock(&wl->mutex); |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index f9e1cff2aecb..bf6f6c1ed4cf 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -193,7 +193,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
193 | const struct ieee80211_hdr *wlhdr = | 193 | const struct ieee80211_hdr *wlhdr = |
194 | (const struct ieee80211_hdr *)fragment_data; | 194 | (const struct ieee80211_hdr *)fragment_data; |
195 | int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)); | 195 | int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)); |
196 | u16 fctl = le16_to_cpu(wlhdr->frame_control); | 196 | __le16 fctl = wlhdr->frame_control; |
197 | struct ieee80211_rate *fbrate; | 197 | struct ieee80211_rate *fbrate; |
198 | u8 rate, rate_fb; | 198 | u8 rate, rate_fb; |
199 | int rate_ofdm, rate_fb_ofdm; | 199 | int rate_ofdm, rate_fb_ofdm; |
@@ -259,7 +259,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
259 | B43_TXH_MAC_KEYIDX; | 259 | B43_TXH_MAC_KEYIDX; |
260 | mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & | 260 | mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & |
261 | B43_TXH_MAC_KEYALG; | 261 | B43_TXH_MAC_KEYALG; |
262 | wlhdr_len = ieee80211_get_hdrlen(fctl); | 262 | wlhdr_len = ieee80211_hdrlen(fctl); |
263 | iv_len = min((size_t) info->control.iv_len, | 263 | iv_len = min((size_t) info->control.iv_len, |
264 | ARRAY_SIZE(txhdr->iv)); | 264 | ARRAY_SIZE(txhdr->iv)); |
265 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); | 265 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); |
@@ -317,8 +317,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
317 | /* MAC control */ | 317 | /* MAC control */ |
318 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 318 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
319 | mac_ctl |= B43_TXH_MAC_ACK; | 319 | mac_ctl |= B43_TXH_MAC_ACK; |
320 | if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && | 320 | if (!ieee80211_is_pspoll(fctl)) |
321 | ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) | ||
322 | mac_ctl |= B43_TXH_MAC_HWSEQ; | 321 | mac_ctl |= B43_TXH_MAC_HWSEQ; |
323 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 322 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
324 | mac_ctl |= B43_TXH_MAC_STMSDU; | 323 | mac_ctl |= B43_TXH_MAC_STMSDU; |
@@ -509,7 +508,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
509 | struct b43_plcp_hdr6 *plcp; | 508 | struct b43_plcp_hdr6 *plcp; |
510 | struct ieee80211_hdr *wlhdr; | 509 | struct ieee80211_hdr *wlhdr; |
511 | const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; | 510 | const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; |
512 | u16 fctl; | 511 | __le16 fctl; |
513 | u16 phystat0, phystat3, chanstat, mactime; | 512 | u16 phystat0, phystat3, chanstat, mactime; |
514 | u32 macstat; | 513 | u32 macstat; |
515 | u16 chanid; | 514 | u16 chanid; |
@@ -549,7 +548,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
549 | goto drop; | 548 | goto drop; |
550 | } | 549 | } |
551 | wlhdr = (struct ieee80211_hdr *)(skb->data); | 550 | wlhdr = (struct ieee80211_hdr *)(skb->data); |
552 | fctl = le16_to_cpu(wlhdr->frame_control); | 551 | fctl = wlhdr->frame_control; |
553 | 552 | ||
554 | if (macstat & B43_RX_MAC_DEC) { | 553 | if (macstat & B43_RX_MAC_DEC) { |
555 | unsigned int keyidx; | 554 | unsigned int keyidx; |
@@ -564,7 +563,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
564 | B43_WARN_ON(keyidx >= dev->max_nr_keys); | 563 | B43_WARN_ON(keyidx >= dev->max_nr_keys); |
565 | 564 | ||
566 | if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { | 565 | if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { |
567 | wlhdr_len = ieee80211_get_hdrlen(fctl); | 566 | wlhdr_len = ieee80211_hdrlen(fctl); |
568 | if (unlikely(skb->len < (wlhdr_len + 3))) { | 567 | if (unlikely(skb->len < (wlhdr_len + 3))) { |
569 | b43dbg(dev->wl, | 568 | b43dbg(dev->wl, |
570 | "RX: Packet size underrun (3)\n"); | 569 | "RX: Packet size underrun (3)\n"); |
@@ -604,9 +603,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
604 | * of timestamp, i.e. about 65 milliseconds after the PHY received | 603 | * of timestamp, i.e. about 65 milliseconds after the PHY received |
605 | * the first symbol. | 604 | * the first symbol. |
606 | */ | 605 | */ |
607 | if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) | 606 | if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { |
608 | == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) || | ||
609 | dev->wl->radiotap_enabled) { | ||
610 | u16 low_mactime_now; | 607 | u16 low_mactime_now; |
611 | 608 | ||
612 | b43_tsf_read(dev, &status.mactime); | 609 | b43_tsf_read(dev, &status.mactime); |
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 203b0f42ac58..eb0243a22691 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -393,13 +393,13 @@ dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring, | |||
393 | dma_addr_t dmaaddr; | 393 | dma_addr_t dmaaddr; |
394 | 394 | ||
395 | if (tx) | 395 | if (tx) |
396 | dmaaddr = dma_map_single(ring->dev->dev->dma_dev, | 396 | dmaaddr = ssb_dma_map_single(ring->dev->dev, |
397 | buf, len, | 397 | buf, len, |
398 | DMA_TO_DEVICE); | 398 | DMA_TO_DEVICE); |
399 | else | 399 | else |
400 | dmaaddr = dma_map_single(ring->dev->dev->dma_dev, | 400 | dmaaddr = ssb_dma_map_single(ring->dev->dev, |
401 | buf, len, | 401 | buf, len, |
402 | DMA_FROM_DEVICE); | 402 | DMA_FROM_DEVICE); |
403 | 403 | ||
404 | return dmaaddr; | 404 | return dmaaddr; |
405 | } | 405 | } |
@@ -411,13 +411,13 @@ void unmap_descbuffer(struct b43legacy_dmaring *ring, | |||
411 | int tx) | 411 | int tx) |
412 | { | 412 | { |
413 | if (tx) | 413 | if (tx) |
414 | dma_unmap_single(ring->dev->dev->dma_dev, | 414 | ssb_dma_unmap_single(ring->dev->dev, |
415 | addr, len, | 415 | addr, len, |
416 | DMA_TO_DEVICE); | 416 | DMA_TO_DEVICE); |
417 | else | 417 | else |
418 | dma_unmap_single(ring->dev->dev->dma_dev, | 418 | ssb_dma_unmap_single(ring->dev->dev, |
419 | addr, len, | 419 | addr, len, |
420 | DMA_FROM_DEVICE); | 420 | DMA_FROM_DEVICE); |
421 | } | 421 | } |
422 | 422 | ||
423 | static inline | 423 | static inline |
@@ -427,8 +427,8 @@ void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring, | |||
427 | { | 427 | { |
428 | B43legacy_WARN_ON(ring->tx); | 428 | B43legacy_WARN_ON(ring->tx); |
429 | 429 | ||
430 | dma_sync_single_for_cpu(ring->dev->dev->dma_dev, | 430 | ssb_dma_sync_single_for_cpu(ring->dev->dev, |
431 | addr, len, DMA_FROM_DEVICE); | 431 | addr, len, DMA_FROM_DEVICE); |
432 | } | 432 | } |
433 | 433 | ||
434 | static inline | 434 | static inline |
@@ -438,8 +438,8 @@ void sync_descbuffer_for_device(struct b43legacy_dmaring *ring, | |||
438 | { | 438 | { |
439 | B43legacy_WARN_ON(ring->tx); | 439 | B43legacy_WARN_ON(ring->tx); |
440 | 440 | ||
441 | dma_sync_single_for_device(ring->dev->dev->dma_dev, | 441 | ssb_dma_sync_single_for_device(ring->dev->dev, |
442 | addr, len, DMA_FROM_DEVICE); | 442 | addr, len, DMA_FROM_DEVICE); |
443 | } | 443 | } |
444 | 444 | ||
445 | static inline | 445 | static inline |
@@ -458,10 +458,11 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring, | |||
458 | 458 | ||
459 | static int alloc_ringmemory(struct b43legacy_dmaring *ring) | 459 | static int alloc_ringmemory(struct b43legacy_dmaring *ring) |
460 | { | 460 | { |
461 | struct device *dma_dev = ring->dev->dev->dma_dev; | 461 | /* GFP flags must match the flags in free_ringmemory()! */ |
462 | 462 | ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, | |
463 | ring->descbase = dma_alloc_coherent(dma_dev, B43legacy_DMA_RINGMEMSIZE, | 463 | B43legacy_DMA_RINGMEMSIZE, |
464 | &(ring->dmabase), GFP_KERNEL); | 464 | &(ring->dmabase), |
465 | GFP_KERNEL); | ||
465 | if (!ring->descbase) { | 466 | if (!ring->descbase) { |
466 | b43legacyerr(ring->dev->wl, "DMA ringmemory allocation" | 467 | b43legacyerr(ring->dev->wl, "DMA ringmemory allocation" |
467 | " failed\n"); | 468 | " failed\n"); |
@@ -474,10 +475,8 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring) | |||
474 | 475 | ||
475 | static void free_ringmemory(struct b43legacy_dmaring *ring) | 476 | static void free_ringmemory(struct b43legacy_dmaring *ring) |
476 | { | 477 | { |
477 | struct device *dma_dev = ring->dev->dev->dma_dev; | 478 | ssb_dma_free_consistent(ring->dev->dev, B43legacy_DMA_RINGMEMSIZE, |
478 | 479 | ring->descbase, ring->dmabase, GFP_KERNEL); | |
479 | dma_free_coherent(dma_dev, B43legacy_DMA_RINGMEMSIZE, | ||
480 | ring->descbase, ring->dmabase); | ||
481 | } | 480 | } |
482 | 481 | ||
483 | /* Reset the RX DMA channel */ | 482 | /* Reset the RX DMA channel */ |
@@ -589,7 +588,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, | |||
589 | size_t buffersize, | 588 | size_t buffersize, |
590 | bool dma_to_device) | 589 | bool dma_to_device) |
591 | { | 590 | { |
592 | if (unlikely(dma_mapping_error(addr))) | 591 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) |
593 | return 1; | 592 | return 1; |
594 | 593 | ||
595 | switch (ring->type) { | 594 | switch (ring->type) { |
@@ -894,9 +893,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
894 | goto err_kfree_meta; | 893 | goto err_kfree_meta; |
895 | 894 | ||
896 | /* test for ability to dma to txhdr_cache */ | 895 | /* test for ability to dma to txhdr_cache */ |
897 | dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache, | 896 | dma_test = ssb_dma_map_single(dev->dev, ring->txhdr_cache, |
898 | sizeof(struct b43legacy_txhdr_fw3), | 897 | sizeof(struct b43legacy_txhdr_fw3), |
899 | DMA_TO_DEVICE); | 898 | DMA_TO_DEVICE); |
900 | 899 | ||
901 | if (b43legacy_dma_mapping_error(ring, dma_test, | 900 | if (b43legacy_dma_mapping_error(ring, dma_test, |
902 | sizeof(struct b43legacy_txhdr_fw3), 1)) { | 901 | sizeof(struct b43legacy_txhdr_fw3), 1)) { |
@@ -908,7 +907,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
908 | if (!ring->txhdr_cache) | 907 | if (!ring->txhdr_cache) |
909 | goto err_kfree_meta; | 908 | goto err_kfree_meta; |
910 | 909 | ||
911 | dma_test = dma_map_single(dev->dev->dma_dev, | 910 | dma_test = ssb_dma_map_single(dev->dev, |
912 | ring->txhdr_cache, | 911 | ring->txhdr_cache, |
913 | sizeof(struct b43legacy_txhdr_fw3), | 912 | sizeof(struct b43legacy_txhdr_fw3), |
914 | DMA_TO_DEVICE); | 913 | DMA_TO_DEVICE); |
@@ -918,9 +917,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
918 | goto err_kfree_txhdr_cache; | 917 | goto err_kfree_txhdr_cache; |
919 | } | 918 | } |
920 | 919 | ||
921 | dma_unmap_single(dev->dev->dma_dev, | 920 | ssb_dma_unmap_single(dev->dev, dma_test, |
922 | dma_test, sizeof(struct b43legacy_txhdr_fw3), | 921 | sizeof(struct b43legacy_txhdr_fw3), |
923 | DMA_TO_DEVICE); | 922 | DMA_TO_DEVICE); |
924 | } | 923 | } |
925 | 924 | ||
926 | ring->nr_slots = nr_slots; | 925 | ring->nr_slots = nr_slots; |
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index d178dfbb1c9f..8935a302b220 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c | |||
@@ -90,7 +90,7 @@ static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state) | |||
90 | goto out_unlock; | 90 | goto out_unlock; |
91 | err = 0; | 91 | err = 0; |
92 | switch (state) { | 92 | switch (state) { |
93 | case RFKILL_STATE_ON: | 93 | case RFKILL_STATE_UNBLOCKED: |
94 | if (!dev->radio_hw_enable) { | 94 | if (!dev->radio_hw_enable) { |
95 | /* No luck. We can't toggle the hardware RF-kill | 95 | /* No luck. We can't toggle the hardware RF-kill |
96 | * button from software. */ | 96 | * button from software. */ |
@@ -100,10 +100,14 @@ static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state) | |||
100 | if (!dev->phy.radio_on) | 100 | if (!dev->phy.radio_on) |
101 | b43legacy_radio_turn_on(dev); | 101 | b43legacy_radio_turn_on(dev); |
102 | break; | 102 | break; |
103 | case RFKILL_STATE_OFF: | 103 | case RFKILL_STATE_SOFT_BLOCKED: |
104 | if (dev->phy.radio_on) | 104 | if (dev->phy.radio_on) |
105 | b43legacy_radio_turn_off(dev, 0); | 105 | b43legacy_radio_turn_off(dev, 0); |
106 | break; | 106 | break; |
107 | default: | ||
108 | b43legacywarn(wl, "Received unexpected rfkill state %d.\n", | ||
109 | state); | ||
110 | break; | ||
107 | } | 111 | } |
108 | 112 | ||
109 | out_unlock: | 113 | out_unlock: |
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 82dc04d59446..a3540787eb50 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c | |||
@@ -442,7 +442,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev, | |||
442 | struct b43legacy_plcp_hdr6 *plcp; | 442 | struct b43legacy_plcp_hdr6 *plcp; |
443 | struct ieee80211_hdr *wlhdr; | 443 | struct ieee80211_hdr *wlhdr; |
444 | const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr; | 444 | const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr; |
445 | u16 fctl; | 445 | __le16 fctl; |
446 | u16 phystat0; | 446 | u16 phystat0; |
447 | u16 phystat3; | 447 | u16 phystat3; |
448 | u16 chanstat; | 448 | u16 chanstat; |
@@ -480,7 +480,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev, | |||
480 | goto drop; | 480 | goto drop; |
481 | } | 481 | } |
482 | wlhdr = (struct ieee80211_hdr *)(skb->data); | 482 | wlhdr = (struct ieee80211_hdr *)(skb->data); |
483 | fctl = le16_to_cpu(wlhdr->frame_control); | 483 | fctl = wlhdr->frame_control; |
484 | 484 | ||
485 | if ((macstat & B43legacy_RX_MAC_DEC) && | 485 | if ((macstat & B43legacy_RX_MAC_DEC) && |
486 | !(macstat & B43legacy_RX_MAC_DECERR)) { | 486 | !(macstat & B43legacy_RX_MAC_DECERR)) { |
@@ -499,11 +499,11 @@ void b43legacy_rx(struct b43legacy_wldev *dev, | |||
499 | 499 | ||
500 | if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) { | 500 | if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) { |
501 | /* Remove PROTECTED flag to mark it as decrypted. */ | 501 | /* Remove PROTECTED flag to mark it as decrypted. */ |
502 | B43legacy_WARN_ON(!(fctl & IEEE80211_FCTL_PROTECTED)); | 502 | B43legacy_WARN_ON(!ieee80211_has_protected(fctl)); |
503 | fctl &= ~IEEE80211_FCTL_PROTECTED; | 503 | fctl &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
504 | wlhdr->frame_control = cpu_to_le16(fctl); | 504 | wlhdr->frame_control = fctl; |
505 | 505 | ||
506 | wlhdr_len = ieee80211_get_hdrlen(fctl); | 506 | wlhdr_len = ieee80211_hdrlen(fctl); |
507 | if (unlikely(skb->len < (wlhdr_len + 3))) { | 507 | if (unlikely(skb->len < (wlhdr_len + 3))) { |
508 | b43legacydbg(dev->wl, "RX: Packet size" | 508 | b43legacydbg(dev->wl, "RX: Packet size" |
509 | " underrun3\n"); | 509 | " underrun3\n"); |
@@ -556,9 +556,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev, | |||
556 | * of timestamp, i.e. about 65 milliseconds after the PHY received | 556 | * of timestamp, i.e. about 65 milliseconds after the PHY received |
557 | * the first symbol. | 557 | * the first symbol. |
558 | */ | 558 | */ |
559 | if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) | 559 | if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { |
560 | == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) || | ||
561 | dev->wl->radiotap_enabled) { | ||
562 | u16 low_mactime_now; | 560 | u16 low_mactime_now; |
563 | 561 | ||
564 | b43legacy_tsf_read(dev, &status.mactime); | 562 | b43legacy_tsf_read(dev, &status.mactime); |
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h index 547ba84dc797..3a386a636cca 100644 --- a/drivers/net/wireless/hostap/hostap.h +++ b/drivers/net/wireless/hostap/hostap.h | |||
@@ -67,7 +67,8 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, | |||
67 | int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], | 67 | int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], |
68 | struct iw_quality qual[], int buf_size, | 68 | struct iw_quality qual[], int buf_size, |
69 | int aplist); | 69 | int aplist); |
70 | int prism2_ap_translate_scan(struct net_device *dev, char *buffer); | 70 | int prism2_ap_translate_scan(struct net_device *dev, |
71 | struct iw_request_info *info, char *buffer); | ||
71 | int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param); | 72 | int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param); |
72 | 73 | ||
73 | 74 | ||
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 0acd9589c48c..06b23df8f69b 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c | |||
@@ -2420,7 +2420,8 @@ int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], | |||
2420 | 2420 | ||
2421 | /* Translate our list of Access Points & Stations to a card independant | 2421 | /* Translate our list of Access Points & Stations to a card independant |
2422 | * format that the Wireless Tools will understand - Jean II */ | 2422 | * format that the Wireless Tools will understand - Jean II */ |
2423 | int prism2_ap_translate_scan(struct net_device *dev, char *buffer) | 2423 | int prism2_ap_translate_scan(struct net_device *dev, |
2424 | struct iw_request_info *info, char *buffer) | ||
2424 | { | 2425 | { |
2425 | struct hostap_interface *iface; | 2426 | struct hostap_interface *iface; |
2426 | local_info_t *local; | 2427 | local_info_t *local; |
@@ -2449,8 +2450,8 @@ int prism2_ap_translate_scan(struct net_device *dev, char *buffer) | |||
2449 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 2450 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
2450 | memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN); | 2451 | memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN); |
2451 | iwe.len = IW_EV_ADDR_LEN; | 2452 | iwe.len = IW_EV_ADDR_LEN; |
2452 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 2453 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
2453 | IW_EV_ADDR_LEN); | 2454 | &iwe, IW_EV_ADDR_LEN); |
2454 | 2455 | ||
2455 | /* Use the mode to indicate if it's a station or | 2456 | /* Use the mode to indicate if it's a station or |
2456 | * an Access Point */ | 2457 | * an Access Point */ |
@@ -2461,8 +2462,8 @@ int prism2_ap_translate_scan(struct net_device *dev, char *buffer) | |||
2461 | else | 2462 | else |
2462 | iwe.u.mode = IW_MODE_INFRA; | 2463 | iwe.u.mode = IW_MODE_INFRA; |
2463 | iwe.len = IW_EV_UINT_LEN; | 2464 | iwe.len = IW_EV_UINT_LEN; |
2464 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 2465 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
2465 | IW_EV_UINT_LEN); | 2466 | &iwe, IW_EV_UINT_LEN); |
2466 | 2467 | ||
2467 | /* Some quality */ | 2468 | /* Some quality */ |
2468 | memset(&iwe, 0, sizeof(iwe)); | 2469 | memset(&iwe, 0, sizeof(iwe)); |
@@ -2477,8 +2478,8 @@ int prism2_ap_translate_scan(struct net_device *dev, char *buffer) | |||
2477 | iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); | 2478 | iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); |
2478 | iwe.u.qual.updated = sta->last_rx_updated; | 2479 | iwe.u.qual.updated = sta->last_rx_updated; |
2479 | iwe.len = IW_EV_QUAL_LEN; | 2480 | iwe.len = IW_EV_QUAL_LEN; |
2480 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 2481 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
2481 | IW_EV_QUAL_LEN); | 2482 | &iwe, IW_EV_QUAL_LEN); |
2482 | 2483 | ||
2483 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT | 2484 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT |
2484 | if (sta->ap) { | 2485 | if (sta->ap) { |
@@ -2486,8 +2487,8 @@ int prism2_ap_translate_scan(struct net_device *dev, char *buffer) | |||
2486 | iwe.cmd = SIOCGIWESSID; | 2487 | iwe.cmd = SIOCGIWESSID; |
2487 | iwe.u.data.length = sta->u.ap.ssid_len; | 2488 | iwe.u.data.length = sta->u.ap.ssid_len; |
2488 | iwe.u.data.flags = 1; | 2489 | iwe.u.data.flags = 1; |
2489 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 2490 | current_ev = iwe_stream_add_point(info, current_ev, |
2490 | &iwe, | 2491 | end_buf, &iwe, |
2491 | sta->u.ap.ssid); | 2492 | sta->u.ap.ssid); |
2492 | 2493 | ||
2493 | memset(&iwe, 0, sizeof(iwe)); | 2494 | memset(&iwe, 0, sizeof(iwe)); |
@@ -2497,10 +2498,9 @@ int prism2_ap_translate_scan(struct net_device *dev, char *buffer) | |||
2497 | IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | 2498 | IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; |
2498 | else | 2499 | else |
2499 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 2500 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
2500 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 2501 | current_ev = iwe_stream_add_point(info, current_ev, |
2501 | &iwe, | 2502 | end_buf, &iwe, |
2502 | sta->u.ap.ssid | 2503 | sta->u.ap.ssid); |
2503 | /* 0 byte memcpy */); | ||
2504 | 2504 | ||
2505 | if (sta->u.ap.channel > 0 && | 2505 | if (sta->u.ap.channel > 0 && |
2506 | sta->u.ap.channel <= FREQ_COUNT) { | 2506 | sta->u.ap.channel <= FREQ_COUNT) { |
@@ -2510,7 +2510,7 @@ int prism2_ap_translate_scan(struct net_device *dev, char *buffer) | |||
2510 | * 100000; | 2510 | * 100000; |
2511 | iwe.u.freq.e = 1; | 2511 | iwe.u.freq.e = 1; |
2512 | current_ev = iwe_stream_add_event( | 2512 | current_ev = iwe_stream_add_event( |
2513 | current_ev, end_buf, &iwe, | 2513 | info, current_ev, end_buf, &iwe, |
2514 | IW_EV_FREQ_LEN); | 2514 | IW_EV_FREQ_LEN); |
2515 | } | 2515 | } |
2516 | 2516 | ||
@@ -2519,8 +2519,8 @@ int prism2_ap_translate_scan(struct net_device *dev, char *buffer) | |||
2519 | sprintf(buf, "beacon_interval=%d", | 2519 | sprintf(buf, "beacon_interval=%d", |
2520 | sta->listen_interval); | 2520 | sta->listen_interval); |
2521 | iwe.u.data.length = strlen(buf); | 2521 | iwe.u.data.length = strlen(buf); |
2522 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 2522 | current_ev = iwe_stream_add_point(info, current_ev, |
2523 | &iwe, buf); | 2523 | end_buf, &iwe, buf); |
2524 | } | 2524 | } |
2525 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 2525 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
2526 | 2526 | ||
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 0ca0bfeb0ada..ed52d98317cd 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -1793,6 +1793,7 @@ static int prism2_ioctl_siwscan(struct net_device *dev, | |||
1793 | 1793 | ||
1794 | #ifndef PRISM2_NO_STATION_MODES | 1794 | #ifndef PRISM2_NO_STATION_MODES |
1795 | static char * __prism2_translate_scan(local_info_t *local, | 1795 | static char * __prism2_translate_scan(local_info_t *local, |
1796 | struct iw_request_info *info, | ||
1796 | struct hfa384x_hostscan_result *scan, | 1797 | struct hfa384x_hostscan_result *scan, |
1797 | struct hostap_bss_info *bss, | 1798 | struct hostap_bss_info *bss, |
1798 | char *current_ev, char *end_buf) | 1799 | char *current_ev, char *end_buf) |
@@ -1823,7 +1824,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1823 | iwe.cmd = SIOCGIWAP; | 1824 | iwe.cmd = SIOCGIWAP; |
1824 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 1825 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
1825 | memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN); | 1826 | memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN); |
1826 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1827 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
1827 | IW_EV_ADDR_LEN); | 1828 | IW_EV_ADDR_LEN); |
1828 | 1829 | ||
1829 | /* Other entries will be displayed in the order we give them */ | 1830 | /* Other entries will be displayed in the order we give them */ |
@@ -1832,7 +1833,8 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1832 | iwe.cmd = SIOCGIWESSID; | 1833 | iwe.cmd = SIOCGIWESSID; |
1833 | iwe.u.data.length = ssid_len; | 1834 | iwe.u.data.length = ssid_len; |
1834 | iwe.u.data.flags = 1; | 1835 | iwe.u.data.flags = 1; |
1835 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid); | 1836 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1837 | &iwe, ssid); | ||
1836 | 1838 | ||
1837 | memset(&iwe, 0, sizeof(iwe)); | 1839 | memset(&iwe, 0, sizeof(iwe)); |
1838 | iwe.cmd = SIOCGIWMODE; | 1840 | iwe.cmd = SIOCGIWMODE; |
@@ -1847,8 +1849,8 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1847 | iwe.u.mode = IW_MODE_MASTER; | 1849 | iwe.u.mode = IW_MODE_MASTER; |
1848 | else | 1850 | else |
1849 | iwe.u.mode = IW_MODE_ADHOC; | 1851 | iwe.u.mode = IW_MODE_ADHOC; |
1850 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1852 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
1851 | IW_EV_UINT_LEN); | 1853 | &iwe, IW_EV_UINT_LEN); |
1852 | } | 1854 | } |
1853 | 1855 | ||
1854 | memset(&iwe, 0, sizeof(iwe)); | 1856 | memset(&iwe, 0, sizeof(iwe)); |
@@ -1864,8 +1866,8 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1864 | if (chan > 0) { | 1866 | if (chan > 0) { |
1865 | iwe.u.freq.m = freq_list[chan - 1] * 100000; | 1867 | iwe.u.freq.m = freq_list[chan - 1] * 100000; |
1866 | iwe.u.freq.e = 1; | 1868 | iwe.u.freq.e = 1; |
1867 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1869 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
1868 | IW_EV_FREQ_LEN); | 1870 | &iwe, IW_EV_FREQ_LEN); |
1869 | } | 1871 | } |
1870 | 1872 | ||
1871 | if (scan) { | 1873 | if (scan) { |
@@ -1884,8 +1886,8 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1884 | | IW_QUAL_NOISE_UPDATED | 1886 | | IW_QUAL_NOISE_UPDATED |
1885 | | IW_QUAL_QUAL_INVALID | 1887 | | IW_QUAL_QUAL_INVALID |
1886 | | IW_QUAL_DBM; | 1888 | | IW_QUAL_DBM; |
1887 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1889 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
1888 | IW_EV_QUAL_LEN); | 1890 | &iwe, IW_EV_QUAL_LEN); |
1889 | } | 1891 | } |
1890 | 1892 | ||
1891 | memset(&iwe, 0, sizeof(iwe)); | 1893 | memset(&iwe, 0, sizeof(iwe)); |
@@ -1895,13 +1897,13 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1895 | else | 1897 | else |
1896 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 1898 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
1897 | iwe.u.data.length = 0; | 1899 | iwe.u.data.length = 0; |
1898 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ""); | 1900 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, ""); |
1899 | 1901 | ||
1900 | /* TODO: add SuppRates into BSS table */ | 1902 | /* TODO: add SuppRates into BSS table */ |
1901 | if (scan) { | 1903 | if (scan) { |
1902 | memset(&iwe, 0, sizeof(iwe)); | 1904 | memset(&iwe, 0, sizeof(iwe)); |
1903 | iwe.cmd = SIOCGIWRATE; | 1905 | iwe.cmd = SIOCGIWRATE; |
1904 | current_val = current_ev + IW_EV_LCP_LEN; | 1906 | current_val = current_ev + iwe_stream_lcp_len(info); |
1905 | pos = scan->sup_rates; | 1907 | pos = scan->sup_rates; |
1906 | for (i = 0; i < sizeof(scan->sup_rates); i++) { | 1908 | for (i = 0; i < sizeof(scan->sup_rates); i++) { |
1907 | if (pos[i] == 0) | 1909 | if (pos[i] == 0) |
@@ -1909,11 +1911,11 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1909 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | 1911 | /* Bit rate given in 500 kb/s units (+ 0x80) */ |
1910 | iwe.u.bitrate.value = ((pos[i] & 0x7f) * 500000); | 1912 | iwe.u.bitrate.value = ((pos[i] & 0x7f) * 500000); |
1911 | current_val = iwe_stream_add_value( | 1913 | current_val = iwe_stream_add_value( |
1912 | current_ev, current_val, end_buf, &iwe, | 1914 | info, current_ev, current_val, end_buf, &iwe, |
1913 | IW_EV_PARAM_LEN); | 1915 | IW_EV_PARAM_LEN); |
1914 | } | 1916 | } |
1915 | /* Check if we added any event */ | 1917 | /* Check if we added any event */ |
1916 | if ((current_val - current_ev) > IW_EV_LCP_LEN) | 1918 | if ((current_val - current_ev) > iwe_stream_lcp_len(info)) |
1917 | current_ev = current_val; | 1919 | current_ev = current_val; |
1918 | } | 1920 | } |
1919 | 1921 | ||
@@ -1924,15 +1926,15 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1924 | iwe.cmd = IWEVCUSTOM; | 1926 | iwe.cmd = IWEVCUSTOM; |
1925 | sprintf(buf, "bcn_int=%d", le16_to_cpu(scan->beacon_interval)); | 1927 | sprintf(buf, "bcn_int=%d", le16_to_cpu(scan->beacon_interval)); |
1926 | iwe.u.data.length = strlen(buf); | 1928 | iwe.u.data.length = strlen(buf); |
1927 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 1929 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1928 | buf); | 1930 | &iwe, buf); |
1929 | 1931 | ||
1930 | memset(&iwe, 0, sizeof(iwe)); | 1932 | memset(&iwe, 0, sizeof(iwe)); |
1931 | iwe.cmd = IWEVCUSTOM; | 1933 | iwe.cmd = IWEVCUSTOM; |
1932 | sprintf(buf, "resp_rate=%d", le16_to_cpu(scan->rate)); | 1934 | sprintf(buf, "resp_rate=%d", le16_to_cpu(scan->rate)); |
1933 | iwe.u.data.length = strlen(buf); | 1935 | iwe.u.data.length = strlen(buf); |
1934 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 1936 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1935 | buf); | 1937 | &iwe, buf); |
1936 | 1938 | ||
1937 | if (local->last_scan_type == PRISM2_HOSTSCAN && | 1939 | if (local->last_scan_type == PRISM2_HOSTSCAN && |
1938 | (capabilities & WLAN_CAPABILITY_IBSS)) { | 1940 | (capabilities & WLAN_CAPABILITY_IBSS)) { |
@@ -1940,8 +1942,8 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1940 | iwe.cmd = IWEVCUSTOM; | 1942 | iwe.cmd = IWEVCUSTOM; |
1941 | sprintf(buf, "atim=%d", le16_to_cpu(scan->atim)); | 1943 | sprintf(buf, "atim=%d", le16_to_cpu(scan->atim)); |
1942 | iwe.u.data.length = strlen(buf); | 1944 | iwe.u.data.length = strlen(buf); |
1943 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 1945 | current_ev = iwe_stream_add_point(info, current_ev, |
1944 | &iwe, buf); | 1946 | end_buf, &iwe, buf); |
1945 | } | 1947 | } |
1946 | } | 1948 | } |
1947 | kfree(buf); | 1949 | kfree(buf); |
@@ -1950,16 +1952,16 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1950 | memset(&iwe, 0, sizeof(iwe)); | 1952 | memset(&iwe, 0, sizeof(iwe)); |
1951 | iwe.cmd = IWEVGENIE; | 1953 | iwe.cmd = IWEVGENIE; |
1952 | iwe.u.data.length = bss->wpa_ie_len; | 1954 | iwe.u.data.length = bss->wpa_ie_len; |
1953 | current_ev = iwe_stream_add_point( | 1955 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1954 | current_ev, end_buf, &iwe, bss->wpa_ie); | 1956 | &iwe, bss->wpa_ie); |
1955 | } | 1957 | } |
1956 | 1958 | ||
1957 | if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) { | 1959 | if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) { |
1958 | memset(&iwe, 0, sizeof(iwe)); | 1960 | memset(&iwe, 0, sizeof(iwe)); |
1959 | iwe.cmd = IWEVGENIE; | 1961 | iwe.cmd = IWEVGENIE; |
1960 | iwe.u.data.length = bss->rsn_ie_len; | 1962 | iwe.u.data.length = bss->rsn_ie_len; |
1961 | current_ev = iwe_stream_add_point( | 1963 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1962 | current_ev, end_buf, &iwe, bss->rsn_ie); | 1964 | &iwe, bss->rsn_ie); |
1963 | } | 1965 | } |
1964 | 1966 | ||
1965 | return current_ev; | 1967 | return current_ev; |
@@ -1969,6 +1971,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1969 | /* Translate scan data returned from the card to a card independant | 1971 | /* Translate scan data returned from the card to a card independant |
1970 | * format that the Wireless Tools will understand - Jean II */ | 1972 | * format that the Wireless Tools will understand - Jean II */ |
1971 | static inline int prism2_translate_scan(local_info_t *local, | 1973 | static inline int prism2_translate_scan(local_info_t *local, |
1974 | struct iw_request_info *info, | ||
1972 | char *buffer, int buflen) | 1975 | char *buffer, int buflen) |
1973 | { | 1976 | { |
1974 | struct hfa384x_hostscan_result *scan; | 1977 | struct hfa384x_hostscan_result *scan; |
@@ -1999,13 +2002,14 @@ static inline int prism2_translate_scan(local_info_t *local, | |||
1999 | if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) { | 2002 | if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) { |
2000 | bss->included = 1; | 2003 | bss->included = 1; |
2001 | current_ev = __prism2_translate_scan( | 2004 | current_ev = __prism2_translate_scan( |
2002 | local, scan, bss, current_ev, end_buf); | 2005 | local, info, scan, bss, current_ev, |
2006 | end_buf); | ||
2003 | found++; | 2007 | found++; |
2004 | } | 2008 | } |
2005 | } | 2009 | } |
2006 | if (!found) { | 2010 | if (!found) { |
2007 | current_ev = __prism2_translate_scan( | 2011 | current_ev = __prism2_translate_scan( |
2008 | local, scan, NULL, current_ev, end_buf); | 2012 | local, info, scan, NULL, current_ev, end_buf); |
2009 | } | 2013 | } |
2010 | /* Check if there is space for one more entry */ | 2014 | /* Check if there is space for one more entry */ |
2011 | if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { | 2015 | if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { |
@@ -2023,7 +2027,7 @@ static inline int prism2_translate_scan(local_info_t *local, | |||
2023 | bss = list_entry(ptr, struct hostap_bss_info, list); | 2027 | bss = list_entry(ptr, struct hostap_bss_info, list); |
2024 | if (bss->included) | 2028 | if (bss->included) |
2025 | continue; | 2029 | continue; |
2026 | current_ev = __prism2_translate_scan(local, NULL, bss, | 2030 | current_ev = __prism2_translate_scan(local, info, NULL, bss, |
2027 | current_ev, end_buf); | 2031 | current_ev, end_buf); |
2028 | /* Check if there is space for one more entry */ | 2032 | /* Check if there is space for one more entry */ |
2029 | if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { | 2033 | if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { |
@@ -2070,7 +2074,7 @@ static inline int prism2_ioctl_giwscan_sta(struct net_device *dev, | |||
2070 | } | 2074 | } |
2071 | local->scan_timestamp = 0; | 2075 | local->scan_timestamp = 0; |
2072 | 2076 | ||
2073 | res = prism2_translate_scan(local, extra, data->length); | 2077 | res = prism2_translate_scan(local, info, extra, data->length); |
2074 | 2078 | ||
2075 | if (res >= 0) { | 2079 | if (res >= 0) { |
2076 | data->length = res; | 2080 | data->length = res; |
@@ -2103,7 +2107,7 @@ static int prism2_ioctl_giwscan(struct net_device *dev, | |||
2103 | * Jean II */ | 2107 | * Jean II */ |
2104 | 2108 | ||
2105 | /* Translate to WE format */ | 2109 | /* Translate to WE format */ |
2106 | res = prism2_ap_translate_scan(dev, extra); | 2110 | res = prism2_ap_translate_scan(dev, info, extra); |
2107 | if (res >= 0) { | 2111 | if (res >= 0) { |
2108 | printk(KERN_DEBUG "Scan result translation succeeded " | 2112 | printk(KERN_DEBUG "Scan result translation succeeded " |
2109 | "(length=%d)\n", res); | 2113 | "(length=%d)\n", res); |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index a382c0078923..d7ea32f39694 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -8,7 +8,7 @@ config IWLCORE | |||
8 | select MAC80211_LEDS if IWLWIFI_LEDS | 8 | select MAC80211_LEDS if IWLWIFI_LEDS |
9 | select LEDS_CLASS if IWLWIFI_LEDS | 9 | select LEDS_CLASS if IWLWIFI_LEDS |
10 | select RFKILL if IWLWIFI_RFKILL | 10 | select RFKILL if IWLWIFI_RFKILL |
11 | select RFKILL_INPUT if IWLWIFI_RFKILL | 11 | select RFKILL_INPUT if (IWLWIFI_RFKILL && INPUT) |
12 | 12 | ||
13 | config IWLWIFI_LEDS | 13 | config IWLWIFI_LEDS |
14 | bool | 14 | bool |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 5f098747cf95..ffefbb487e12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c | |||
@@ -54,17 +54,20 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
54 | mutex_lock(&priv->mutex); | 54 | mutex_lock(&priv->mutex); |
55 | 55 | ||
56 | switch (state) { | 56 | switch (state) { |
57 | case RFKILL_STATE_ON: | 57 | case RFKILL_STATE_UNBLOCKED: |
58 | iwl_radio_kill_sw_enable_radio(priv); | 58 | iwl_radio_kill_sw_enable_radio(priv); |
59 | /* if HW rf-kill is set dont allow ON state */ | 59 | /* if HW rf-kill is set dont allow ON state */ |
60 | if (iwl_is_rfkill(priv)) | 60 | if (iwl_is_rfkill(priv)) |
61 | err = -EBUSY; | 61 | err = -EBUSY; |
62 | break; | 62 | break; |
63 | case RFKILL_STATE_OFF: | 63 | case RFKILL_STATE_SOFT_BLOCKED: |
64 | iwl_radio_kill_sw_disable_radio(priv); | 64 | iwl_radio_kill_sw_disable_radio(priv); |
65 | if (!iwl_is_rfkill(priv)) | 65 | if (!iwl_is_rfkill(priv)) |
66 | err = -EBUSY; | 66 | err = -EBUSY; |
67 | break; | 67 | break; |
68 | default: | ||
69 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); | ||
70 | break; | ||
68 | } | 71 | } |
69 | mutex_unlock(&priv->mutex); | 72 | mutex_unlock(&priv->mutex); |
70 | 73 | ||
@@ -95,6 +98,7 @@ int iwl_rfkill_init(struct iwl_priv *priv) | |||
95 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | 98 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; |
96 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | 99 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; |
97 | 100 | ||
101 | #if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) | ||
98 | priv->rfkill_mngr.input_dev = input_allocate_device(); | 102 | priv->rfkill_mngr.input_dev = input_allocate_device(); |
99 | if (!priv->rfkill_mngr.input_dev) { | 103 | if (!priv->rfkill_mngr.input_dev) { |
100 | IWL_ERROR("Unable to allocate rfkill input device.\n"); | 104 | IWL_ERROR("Unable to allocate rfkill input device.\n"); |
@@ -109,6 +113,7 @@ int iwl_rfkill_init(struct iwl_priv *priv) | |||
109 | priv->rfkill_mngr.input_dev->dev.parent = device; | 113 | priv->rfkill_mngr.input_dev->dev.parent = device; |
110 | priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); | 114 | priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); |
111 | set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); | 115 | set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); |
116 | #endif | ||
112 | 117 | ||
113 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | 118 | ret = rfkill_register(priv->rfkill_mngr.rfkill); |
114 | if (ret) { | 119 | if (ret) { |
@@ -116,11 +121,13 @@ int iwl_rfkill_init(struct iwl_priv *priv) | |||
116 | goto free_input_dev; | 121 | goto free_input_dev; |
117 | } | 122 | } |
118 | 123 | ||
124 | #if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) | ||
119 | ret = input_register_device(priv->rfkill_mngr.input_dev); | 125 | ret = input_register_device(priv->rfkill_mngr.input_dev); |
120 | if (ret) { | 126 | if (ret) { |
121 | IWL_ERROR("Unable to register rfkill input device: %d\n", ret); | 127 | IWL_ERROR("Unable to register rfkill input device: %d\n", ret); |
122 | goto unregister_rfkill; | 128 | goto unregister_rfkill; |
123 | } | 129 | } |
130 | #endif | ||
124 | 131 | ||
125 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 132 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
126 | return ret; | 133 | return ret; |
@@ -130,8 +137,10 @@ unregister_rfkill: | |||
130 | priv->rfkill_mngr.rfkill = NULL; | 137 | priv->rfkill_mngr.rfkill = NULL; |
131 | 138 | ||
132 | free_input_dev: | 139 | free_input_dev: |
140 | #if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) | ||
133 | input_free_device(priv->rfkill_mngr.input_dev); | 141 | input_free_device(priv->rfkill_mngr.input_dev); |
134 | priv->rfkill_mngr.input_dev = NULL; | 142 | priv->rfkill_mngr.input_dev = NULL; |
143 | #endif | ||
135 | 144 | ||
136 | freed_rfkill: | 145 | freed_rfkill: |
137 | if (priv->rfkill_mngr.rfkill != NULL) | 146 | if (priv->rfkill_mngr.rfkill != NULL) |
@@ -147,13 +156,16 @@ EXPORT_SYMBOL(iwl_rfkill_init); | |||
147 | void iwl_rfkill_unregister(struct iwl_priv *priv) | 156 | void iwl_rfkill_unregister(struct iwl_priv *priv) |
148 | { | 157 | { |
149 | 158 | ||
159 | #if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) | ||
150 | if (priv->rfkill_mngr.input_dev) | 160 | if (priv->rfkill_mngr.input_dev) |
151 | input_unregister_device(priv->rfkill_mngr.input_dev); | 161 | input_unregister_device(priv->rfkill_mngr.input_dev); |
162 | input_free_device(priv->rfkill_mngr.input_dev); | ||
163 | priv->rfkill_mngr.input_dev = NULL; | ||
164 | #endif | ||
152 | 165 | ||
153 | if (priv->rfkill_mngr.rfkill) | 166 | if (priv->rfkill_mngr.rfkill) |
154 | rfkill_unregister(priv->rfkill_mngr.rfkill); | 167 | rfkill_unregister(priv->rfkill_mngr.rfkill); |
155 | 168 | ||
156 | priv->rfkill_mngr.input_dev = NULL; | ||
157 | priv->rfkill_mngr.rfkill = NULL; | 169 | priv->rfkill_mngr.rfkill = NULL; |
158 | } | 170 | } |
159 | EXPORT_SYMBOL(iwl_rfkill_unregister); | 171 | EXPORT_SYMBOL(iwl_rfkill_unregister); |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index d448c9702a0f..343ed38f772d 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -776,8 +776,9 @@ out: | |||
776 | #define MAX_CUSTOM_LEN 64 | 776 | #define MAX_CUSTOM_LEN 64 |
777 | 777 | ||
778 | static inline char *lbs_translate_scan(struct lbs_private *priv, | 778 | static inline char *lbs_translate_scan(struct lbs_private *priv, |
779 | char *start, char *stop, | 779 | struct iw_request_info *info, |
780 | struct bss_descriptor *bss) | 780 | char *start, char *stop, |
781 | struct bss_descriptor *bss) | ||
781 | { | 782 | { |
782 | struct chan_freq_power *cfp; | 783 | struct chan_freq_power *cfp; |
783 | char *current_val; /* For rates */ | 784 | char *current_val; /* For rates */ |
@@ -801,24 +802,24 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
801 | iwe.cmd = SIOCGIWAP; | 802 | iwe.cmd = SIOCGIWAP; |
802 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 803 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
803 | memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); | 804 | memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); |
804 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN); | 805 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); |
805 | 806 | ||
806 | /* SSID */ | 807 | /* SSID */ |
807 | iwe.cmd = SIOCGIWESSID; | 808 | iwe.cmd = SIOCGIWESSID; |
808 | iwe.u.data.flags = 1; | 809 | iwe.u.data.flags = 1; |
809 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); | 810 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); |
810 | start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); | 811 | start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); |
811 | 812 | ||
812 | /* Mode */ | 813 | /* Mode */ |
813 | iwe.cmd = SIOCGIWMODE; | 814 | iwe.cmd = SIOCGIWMODE; |
814 | iwe.u.mode = bss->mode; | 815 | iwe.u.mode = bss->mode; |
815 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN); | 816 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); |
816 | 817 | ||
817 | /* Frequency */ | 818 | /* Frequency */ |
818 | iwe.cmd = SIOCGIWFREQ; | 819 | iwe.cmd = SIOCGIWFREQ; |
819 | iwe.u.freq.m = (long)cfp->freq * 100000; | 820 | iwe.u.freq.m = (long)cfp->freq * 100000; |
820 | iwe.u.freq.e = 1; | 821 | iwe.u.freq.e = 1; |
821 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN); | 822 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); |
822 | 823 | ||
823 | /* Add quality statistics */ | 824 | /* Add quality statistics */ |
824 | iwe.cmd = IWEVQUAL; | 825 | iwe.cmd = IWEVQUAL; |
@@ -852,7 +853,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
852 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | 853 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
853 | iwe.u.qual.level = CAL_RSSI(snr, nf); | 854 | iwe.u.qual.level = CAL_RSSI(snr, nf); |
854 | } | 855 | } |
855 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); | 856 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); |
856 | 857 | ||
857 | /* Add encryption capability */ | 858 | /* Add encryption capability */ |
858 | iwe.cmd = SIOCGIWENCODE; | 859 | iwe.cmd = SIOCGIWENCODE; |
@@ -862,9 +863,9 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
862 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 863 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
863 | } | 864 | } |
864 | iwe.u.data.length = 0; | 865 | iwe.u.data.length = 0; |
865 | start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); | 866 | start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); |
866 | 867 | ||
867 | current_val = start + IW_EV_LCP_LEN; | 868 | current_val = start + iwe_stream_lcp_len(info); |
868 | 869 | ||
869 | iwe.cmd = SIOCGIWRATE; | 870 | iwe.cmd = SIOCGIWRATE; |
870 | iwe.u.bitrate.fixed = 0; | 871 | iwe.u.bitrate.fixed = 0; |
@@ -874,19 +875,19 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
874 | for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) { | 875 | for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) { |
875 | /* Bit rate given in 500 kb/s units */ | 876 | /* Bit rate given in 500 kb/s units */ |
876 | iwe.u.bitrate.value = bss->rates[j] * 500000; | 877 | iwe.u.bitrate.value = bss->rates[j] * 500000; |
877 | current_val = iwe_stream_add_value(start, current_val, | 878 | current_val = iwe_stream_add_value(info, start, current_val, |
878 | stop, &iwe, IW_EV_PARAM_LEN); | 879 | stop, &iwe, IW_EV_PARAM_LEN); |
879 | } | 880 | } |
880 | if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate | 881 | if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate |
881 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | 882 | && !lbs_ssid_cmp(priv->curbssparams.ssid, |
882 | priv->curbssparams.ssid_len, | 883 | priv->curbssparams.ssid_len, |
883 | bss->ssid, bss->ssid_len)) { | 884 | bss->ssid, bss->ssid_len)) { |
884 | iwe.u.bitrate.value = 22 * 500000; | 885 | iwe.u.bitrate.value = 22 * 500000; |
885 | current_val = iwe_stream_add_value(start, current_val, | 886 | current_val = iwe_stream_add_value(info, start, current_val, |
886 | stop, &iwe, IW_EV_PARAM_LEN); | 887 | stop, &iwe, IW_EV_PARAM_LEN); |
887 | } | 888 | } |
888 | /* Check if we added any event */ | 889 | /* Check if we added any event */ |
889 | if((current_val - start) > IW_EV_LCP_LEN) | 890 | if ((current_val - start) > iwe_stream_lcp_len(info)) |
890 | start = current_val; | 891 | start = current_val; |
891 | 892 | ||
892 | memset(&iwe, 0, sizeof(iwe)); | 893 | memset(&iwe, 0, sizeof(iwe)); |
@@ -895,7 +896,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
895 | memcpy(buf, bss->wpa_ie, bss->wpa_ie_len); | 896 | memcpy(buf, bss->wpa_ie, bss->wpa_ie_len); |
896 | iwe.cmd = IWEVGENIE; | 897 | iwe.cmd = IWEVGENIE; |
897 | iwe.u.data.length = bss->wpa_ie_len; | 898 | iwe.u.data.length = bss->wpa_ie_len; |
898 | start = iwe_stream_add_point(start, stop, &iwe, buf); | 899 | start = iwe_stream_add_point(info, start, stop, &iwe, buf); |
899 | } | 900 | } |
900 | 901 | ||
901 | memset(&iwe, 0, sizeof(iwe)); | 902 | memset(&iwe, 0, sizeof(iwe)); |
@@ -904,7 +905,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
904 | memcpy(buf, bss->rsn_ie, bss->rsn_ie_len); | 905 | memcpy(buf, bss->rsn_ie, bss->rsn_ie_len); |
905 | iwe.cmd = IWEVGENIE; | 906 | iwe.cmd = IWEVGENIE; |
906 | iwe.u.data.length = bss->rsn_ie_len; | 907 | iwe.u.data.length = bss->rsn_ie_len; |
907 | start = iwe_stream_add_point(start, stop, &iwe, buf); | 908 | start = iwe_stream_add_point(info, start, stop, &iwe, buf); |
908 | } | 909 | } |
909 | 910 | ||
910 | if (bss->mesh) { | 911 | if (bss->mesh) { |
@@ -915,7 +916,8 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
915 | p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); | 916 | p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); |
916 | iwe.u.data.length = p - custom; | 917 | iwe.u.data.length = p - custom; |
917 | if (iwe.u.data.length) | 918 | if (iwe.u.data.length) |
918 | start = iwe_stream_add_point(start, stop, &iwe, custom); | 919 | start = iwe_stream_add_point(info, start, stop, |
920 | &iwe, custom); | ||
919 | } | 921 | } |
920 | 922 | ||
921 | out: | 923 | out: |
@@ -1036,7 +1038,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1036 | } | 1038 | } |
1037 | 1039 | ||
1038 | /* Translate to WE format this entry */ | 1040 | /* Translate to WE format this entry */ |
1039 | next_ev = lbs_translate_scan(priv, ev, stop, iter_bss); | 1041 | next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss); |
1040 | if (next_ev == NULL) | 1042 | if (next_ev == NULL) |
1041 | continue; | 1043 | continue; |
1042 | ev = next_ev; | 1044 | ev = next_ev; |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 8da352ae6825..5d30c57e3969 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -430,15 +430,16 @@ static int __init init_mac80211_hwsim(void) | |||
430 | hwsim_radios[i] = hw; | 430 | hwsim_radios[i] = hw; |
431 | 431 | ||
432 | data = hw->priv; | 432 | data = hw->priv; |
433 | data->dev = device_create(hwsim_class, NULL, 0, "hwsim%d", i); | 433 | data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw, |
434 | "hwsim%d", i); | ||
434 | if (IS_ERR(data->dev)) { | 435 | if (IS_ERR(data->dev)) { |
435 | printk(KERN_DEBUG "mac80211_hwsim: device_create " | 436 | printk(KERN_DEBUG |
437 | "mac80211_hwsim: device_create_drvdata " | ||
436 | "failed (%ld)\n", PTR_ERR(data->dev)); | 438 | "failed (%ld)\n", PTR_ERR(data->dev)); |
437 | err = -ENOMEM; | 439 | err = -ENOMEM; |
438 | goto failed; | 440 | goto failed; |
439 | } | 441 | } |
440 | data->dev->driver = &mac80211_hwsim_driver; | 442 | data->dev->driver = &mac80211_hwsim_driver; |
441 | dev_set_drvdata(data->dev, hw); | ||
442 | 443 | ||
443 | SET_IEEE80211_DEV(hw, data->dev); | 444 | SET_IEEE80211_DEV(hw, data->dev); |
444 | addr[3] = i >> 8; | 445 | addr[3] = i >> 8; |
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 6d13a0d15a0c..b047306bf386 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -4046,6 +4046,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev, | |||
4046 | * format that the Wireless Tools will understand - Jean II | 4046 | * format that the Wireless Tools will understand - Jean II |
4047 | * Return message length or -errno for fatal errors */ | 4047 | * Return message length or -errno for fatal errors */ |
4048 | static inline char *orinoco_translate_scan(struct net_device *dev, | 4048 | static inline char *orinoco_translate_scan(struct net_device *dev, |
4049 | struct iw_request_info *info, | ||
4049 | char *current_ev, | 4050 | char *current_ev, |
4050 | char *end_buf, | 4051 | char *end_buf, |
4051 | union hermes_scan_info *bss, | 4052 | union hermes_scan_info *bss, |
@@ -4062,7 +4063,8 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
4062 | iwe.cmd = SIOCGIWAP; | 4063 | iwe.cmd = SIOCGIWAP; |
4063 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 4064 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
4064 | memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN); | 4065 | memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN); |
4065 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); | 4066 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
4067 | &iwe, IW_EV_ADDR_LEN); | ||
4066 | 4068 | ||
4067 | /* Other entries will be displayed in the order we give them */ | 4069 | /* Other entries will be displayed in the order we give them */ |
4068 | 4070 | ||
@@ -4072,7 +4074,8 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
4072 | iwe.u.data.length = 32; | 4074 | iwe.u.data.length = 32; |
4073 | iwe.cmd = SIOCGIWESSID; | 4075 | iwe.cmd = SIOCGIWESSID; |
4074 | iwe.u.data.flags = 1; | 4076 | iwe.u.data.flags = 1; |
4075 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->a.essid); | 4077 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4078 | &iwe, bss->a.essid); | ||
4076 | 4079 | ||
4077 | /* Add mode */ | 4080 | /* Add mode */ |
4078 | iwe.cmd = SIOCGIWMODE; | 4081 | iwe.cmd = SIOCGIWMODE; |
@@ -4082,7 +4085,8 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
4082 | iwe.u.mode = IW_MODE_MASTER; | 4085 | iwe.u.mode = IW_MODE_MASTER; |
4083 | else | 4086 | else |
4084 | iwe.u.mode = IW_MODE_ADHOC; | 4087 | iwe.u.mode = IW_MODE_ADHOC; |
4085 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); | 4088 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
4089 | &iwe, IW_EV_UINT_LEN); | ||
4086 | } | 4090 | } |
4087 | 4091 | ||
4088 | channel = bss->s.channel; | 4092 | channel = bss->s.channel; |
@@ -4091,7 +4095,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
4091 | iwe.cmd = SIOCGIWFREQ; | 4095 | iwe.cmd = SIOCGIWFREQ; |
4092 | iwe.u.freq.m = channel_frequency[channel-1] * 100000; | 4096 | iwe.u.freq.m = channel_frequency[channel-1] * 100000; |
4093 | iwe.u.freq.e = 1; | 4097 | iwe.u.freq.e = 1; |
4094 | current_ev = iwe_stream_add_event(current_ev, end_buf, | 4098 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
4095 | &iwe, IW_EV_FREQ_LEN); | 4099 | &iwe, IW_EV_FREQ_LEN); |
4096 | } | 4100 | } |
4097 | 4101 | ||
@@ -4106,7 +4110,8 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
4106 | iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; | 4110 | iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; |
4107 | else | 4111 | else |
4108 | iwe.u.qual.qual = 0; | 4112 | iwe.u.qual.qual = 0; |
4109 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); | 4113 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
4114 | &iwe, IW_EV_QUAL_LEN); | ||
4110 | 4115 | ||
4111 | /* Add encryption capability */ | 4116 | /* Add encryption capability */ |
4112 | iwe.cmd = SIOCGIWENCODE; | 4117 | iwe.cmd = SIOCGIWENCODE; |
@@ -4115,7 +4120,8 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
4115 | else | 4120 | else |
4116 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 4121 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
4117 | iwe.u.data.length = 0; | 4122 | iwe.u.data.length = 0; |
4118 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->a.essid); | 4123 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4124 | &iwe, bss->a.essid); | ||
4119 | 4125 | ||
4120 | /* Add EXTRA: Age to display seconds since last beacon/probe response | 4126 | /* Add EXTRA: Age to display seconds since last beacon/probe response |
4121 | * for given network. */ | 4127 | * for given network. */ |
@@ -4126,11 +4132,12 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
4126 | jiffies_to_msecs(jiffies - last_scanned)); | 4132 | jiffies_to_msecs(jiffies - last_scanned)); |
4127 | iwe.u.data.length = p - custom; | 4133 | iwe.u.data.length = p - custom; |
4128 | if (iwe.u.data.length) | 4134 | if (iwe.u.data.length) |
4129 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, custom); | 4135 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4136 | &iwe, custom); | ||
4130 | 4137 | ||
4131 | /* Bit rate is not available in Lucent/Agere firmwares */ | 4138 | /* Bit rate is not available in Lucent/Agere firmwares */ |
4132 | if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { | 4139 | if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { |
4133 | char *current_val = current_ev + IW_EV_LCP_LEN; | 4140 | char *current_val = current_ev + iwe_stream_lcp_len(info); |
4134 | int i; | 4141 | int i; |
4135 | int step; | 4142 | int step; |
4136 | 4143 | ||
@@ -4149,12 +4156,13 @@ static inline char *orinoco_translate_scan(struct net_device *dev, | |||
4149 | break; | 4156 | break; |
4150 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | 4157 | /* Bit rate given in 500 kb/s units (+ 0x80) */ |
4151 | iwe.u.bitrate.value = ((bss->p.rates[i] & 0x7f) * 500000); | 4158 | iwe.u.bitrate.value = ((bss->p.rates[i] & 0x7f) * 500000); |
4152 | current_val = iwe_stream_add_value(current_ev, current_val, | 4159 | current_val = iwe_stream_add_value(info, current_ev, |
4160 | current_val, | ||
4153 | end_buf, &iwe, | 4161 | end_buf, &iwe, |
4154 | IW_EV_PARAM_LEN); | 4162 | IW_EV_PARAM_LEN); |
4155 | } | 4163 | } |
4156 | /* Check if we added any event */ | 4164 | /* Check if we added any event */ |
4157 | if ((current_val - current_ev) > IW_EV_LCP_LEN) | 4165 | if ((current_val - current_ev) > iwe_stream_lcp_len(info)) |
4158 | current_ev = current_val; | 4166 | current_ev = current_val; |
4159 | } | 4167 | } |
4160 | 4168 | ||
@@ -4190,7 +4198,7 @@ static int orinoco_ioctl_getscan(struct net_device *dev, | |||
4190 | 4198 | ||
4191 | list_for_each_entry(bss, &priv->bss_list, list) { | 4199 | list_for_each_entry(bss, &priv->bss_list, list) { |
4192 | /* Translate to WE format this entry */ | 4200 | /* Translate to WE format this entry */ |
4193 | current_ev = orinoco_translate_scan(dev, current_ev, | 4201 | current_ev = orinoco_translate_scan(dev, info, current_ev, |
4194 | extra + srq->length, | 4202 | extra + srq->length, |
4195 | &bss->bss, | 4203 | &bss->bss, |
4196 | bss->last_scanned); | 4204 | bss->last_scanned); |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 5b375b289036..97fa14e0a479 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
@@ -571,8 +571,9 @@ prism54_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
571 | */ | 571 | */ |
572 | 572 | ||
573 | static char * | 573 | static char * |
574 | prism54_translate_bss(struct net_device *ndev, char *current_ev, | 574 | prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, |
575 | char *end_buf, struct obj_bss *bss, char noise) | 575 | char *current_ev, char *end_buf, struct obj_bss *bss, |
576 | char noise) | ||
576 | { | 577 | { |
577 | struct iw_event iwe; /* Temporary buffer */ | 578 | struct iw_event iwe; /* Temporary buffer */ |
578 | short cap; | 579 | short cap; |
@@ -584,8 +585,8 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, | |||
584 | memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); | 585 | memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); |
585 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 586 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
586 | iwe.cmd = SIOCGIWAP; | 587 | iwe.cmd = SIOCGIWAP; |
587 | current_ev = | 588 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
588 | iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); | 589 | &iwe, IW_EV_ADDR_LEN); |
589 | 590 | ||
590 | /* The following entries will be displayed in the same order we give them */ | 591 | /* The following entries will be displayed in the same order we give them */ |
591 | 592 | ||
@@ -593,7 +594,7 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, | |||
593 | iwe.u.data.length = bss->ssid.length; | 594 | iwe.u.data.length = bss->ssid.length; |
594 | iwe.u.data.flags = 1; | 595 | iwe.u.data.flags = 1; |
595 | iwe.cmd = SIOCGIWESSID; | 596 | iwe.cmd = SIOCGIWESSID; |
596 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 597 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
597 | &iwe, bss->ssid.octets); | 598 | &iwe, bss->ssid.octets); |
598 | 599 | ||
599 | /* Capabilities */ | 600 | /* Capabilities */ |
@@ -610,9 +611,8 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, | |||
610 | iwe.u.mode = IW_MODE_ADHOC; | 611 | iwe.u.mode = IW_MODE_ADHOC; |
611 | iwe.cmd = SIOCGIWMODE; | 612 | iwe.cmd = SIOCGIWMODE; |
612 | if (iwe.u.mode) | 613 | if (iwe.u.mode) |
613 | current_ev = | 614 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
614 | iwe_stream_add_event(current_ev, end_buf, &iwe, | 615 | &iwe, IW_EV_UINT_LEN); |
615 | IW_EV_UINT_LEN); | ||
616 | 616 | ||
617 | /* Encryption capability */ | 617 | /* Encryption capability */ |
618 | if (cap & CAP_CRYPT) | 618 | if (cap & CAP_CRYPT) |
@@ -621,14 +621,15 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, | |||
621 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 621 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
622 | iwe.u.data.length = 0; | 622 | iwe.u.data.length = 0; |
623 | iwe.cmd = SIOCGIWENCODE; | 623 | iwe.cmd = SIOCGIWENCODE; |
624 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); | 624 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
625 | &iwe, NULL); | ||
625 | 626 | ||
626 | /* Add frequency. (short) bss->channel is the frequency in MHz */ | 627 | /* Add frequency. (short) bss->channel is the frequency in MHz */ |
627 | iwe.u.freq.m = bss->channel; | 628 | iwe.u.freq.m = bss->channel; |
628 | iwe.u.freq.e = 6; | 629 | iwe.u.freq.e = 6; |
629 | iwe.cmd = SIOCGIWFREQ; | 630 | iwe.cmd = SIOCGIWFREQ; |
630 | current_ev = | 631 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
631 | iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); | 632 | &iwe, IW_EV_FREQ_LEN); |
632 | 633 | ||
633 | /* Add quality statistics */ | 634 | /* Add quality statistics */ |
634 | iwe.u.qual.level = bss->rssi; | 635 | iwe.u.qual.level = bss->rssi; |
@@ -636,20 +637,20 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, | |||
636 | /* do a simple SNR for quality */ | 637 | /* do a simple SNR for quality */ |
637 | iwe.u.qual.qual = bss->rssi - noise; | 638 | iwe.u.qual.qual = bss->rssi - noise; |
638 | iwe.cmd = IWEVQUAL; | 639 | iwe.cmd = IWEVQUAL; |
639 | current_ev = | 640 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
640 | iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); | 641 | &iwe, IW_EV_QUAL_LEN); |
641 | 642 | ||
642 | /* Add WPA/RSN Information Element, if any */ | 643 | /* Add WPA/RSN Information Element, if any */ |
643 | wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie); | 644 | wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie); |
644 | if (wpa_ie_len > 0) { | 645 | if (wpa_ie_len > 0) { |
645 | iwe.cmd = IWEVGENIE; | 646 | iwe.cmd = IWEVGENIE; |
646 | iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN); | 647 | iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN); |
647 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 648 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
648 | &iwe, wpa_ie); | 649 | &iwe, wpa_ie); |
649 | } | 650 | } |
650 | /* Do the bitrates */ | 651 | /* Do the bitrates */ |
651 | { | 652 | { |
652 | char * current_val = current_ev + IW_EV_LCP_LEN; | 653 | char *current_val = current_ev + iwe_stream_lcp_len(info); |
653 | int i; | 654 | int i; |
654 | int mask; | 655 | int mask; |
655 | 656 | ||
@@ -662,14 +663,14 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, | |||
662 | for(i = 0; i < sizeof(scan_rate_list); i++) { | 663 | for(i = 0; i < sizeof(scan_rate_list); i++) { |
663 | if(bss->rates & mask) { | 664 | if(bss->rates & mask) { |
664 | iwe.u.bitrate.value = (scan_rate_list[i] * 500000); | 665 | iwe.u.bitrate.value = (scan_rate_list[i] * 500000); |
665 | current_val = iwe_stream_add_value(current_ev, current_val, | 666 | current_val = iwe_stream_add_value( |
666 | end_buf, &iwe, | 667 | info, current_ev, current_val, |
667 | IW_EV_PARAM_LEN); | 668 | end_buf, &iwe, IW_EV_PARAM_LEN); |
668 | } | 669 | } |
669 | mask <<= 1; | 670 | mask <<= 1; |
670 | } | 671 | } |
671 | /* Check if we added any event */ | 672 | /* Check if we added any event */ |
672 | if ((current_val - current_ev) > IW_EV_LCP_LEN) | 673 | if ((current_val - current_ev) > iwe_stream_lcp_len(info)) |
673 | current_ev = current_val; | 674 | current_ev = current_val; |
674 | } | 675 | } |
675 | 676 | ||
@@ -710,7 +711,7 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info, | |||
710 | 711 | ||
711 | /* ok now, scan the list and translate its info */ | 712 | /* ok now, scan the list and translate its info */ |
712 | for (i = 0; i < (int) bsslist->nr; i++) { | 713 | for (i = 0; i < (int) bsslist->nr; i++) { |
713 | current_ev = prism54_translate_bss(ndev, current_ev, | 714 | current_ev = prism54_translate_bss(ndev, info, current_ev, |
714 | extra + dwrq->length, | 715 | extra + dwrq->length, |
715 | &(bsslist->bsslist[i]), | 716 | &(bsslist->bsslist[i]), |
716 | noise); | 717 | noise); |
@@ -2704,6 +2705,7 @@ prism2_ioctl_scan_req(struct net_device *ndev, | |||
2704 | struct prism2_hostapd_param *param) | 2705 | struct prism2_hostapd_param *param) |
2705 | { | 2706 | { |
2706 | islpci_private *priv = netdev_priv(ndev); | 2707 | islpci_private *priv = netdev_priv(ndev); |
2708 | struct iw_request_info info; | ||
2707 | int i, rvalue; | 2709 | int i, rvalue; |
2708 | struct obj_bsslist *bsslist; | 2710 | struct obj_bsslist *bsslist; |
2709 | u32 noise = 0; | 2711 | u32 noise = 0; |
@@ -2727,9 +2729,12 @@ prism2_ioctl_scan_req(struct net_device *ndev, | |||
2727 | rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); | 2729 | rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); |
2728 | bsslist = r.ptr; | 2730 | bsslist = r.ptr; |
2729 | 2731 | ||
2732 | info.cmd = PRISM54_HOSTAPD; | ||
2733 | info.flags = 0; | ||
2734 | |||
2730 | /* ok now, scan the list and translate its info */ | 2735 | /* ok now, scan the list and translate its info */ |
2731 | for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) | 2736 | for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) |
2732 | current_ev = prism54_translate_bss(ndev, current_ev, | 2737 | current_ev = prism54_translate_bss(ndev, &info, current_ev, |
2733 | extra + IW_SCAN_MAX_DATA, | 2738 | extra + IW_SCAN_MAX_DATA, |
2734 | &(bsslist->bsslist[i]), | 2739 | &(bsslist->bsslist[i]), |
2735 | noise); | 2740 | noise); |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index f001f2afd05e..00e965b9da75 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -1648,7 +1648,9 @@ static int rndis_iw_set_scan(struct net_device *dev, | |||
1648 | 1648 | ||
1649 | 1649 | ||
1650 | static char *rndis_translate_scan(struct net_device *dev, | 1650 | static char *rndis_translate_scan(struct net_device *dev, |
1651 | char *cev, char *end_buf, struct ndis_80211_bssid_ex *bssid) | 1651 | struct iw_request_info *info, char *cev, |
1652 | char *end_buf, | ||
1653 | struct ndis_80211_bssid_ex *bssid) | ||
1652 | { | 1654 | { |
1653 | #ifdef DEBUG | 1655 | #ifdef DEBUG |
1654 | struct usbnet *usbdev = dev->priv; | 1656 | struct usbnet *usbdev = dev->priv; |
@@ -1667,14 +1669,14 @@ static char *rndis_translate_scan(struct net_device *dev, | |||
1667 | iwe.cmd = SIOCGIWAP; | 1669 | iwe.cmd = SIOCGIWAP; |
1668 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 1670 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
1669 | memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); | 1671 | memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); |
1670 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); | 1672 | cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_ADDR_LEN); |
1671 | 1673 | ||
1672 | devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length), | 1674 | devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length), |
1673 | bssid->ssid.essid); | 1675 | bssid->ssid.essid); |
1674 | iwe.cmd = SIOCGIWESSID; | 1676 | iwe.cmd = SIOCGIWESSID; |
1675 | iwe.u.essid.length = le32_to_cpu(bssid->ssid.length); | 1677 | iwe.u.essid.length = le32_to_cpu(bssid->ssid.length); |
1676 | iwe.u.essid.flags = 1; | 1678 | iwe.u.essid.flags = 1; |
1677 | cev = iwe_stream_add_point(cev, end_buf, &iwe, bssid->ssid.essid); | 1679 | cev = iwe_stream_add_point(info, cev, end_buf, &iwe, bssid->ssid.essid); |
1678 | 1680 | ||
1679 | devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra)); | 1681 | devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra)); |
1680 | iwe.cmd = SIOCGIWMODE; | 1682 | iwe.cmd = SIOCGIWMODE; |
@@ -1690,12 +1692,12 @@ static char *rndis_translate_scan(struct net_device *dev, | |||
1690 | iwe.u.mode = IW_MODE_AUTO; | 1692 | iwe.u.mode = IW_MODE_AUTO; |
1691 | break; | 1693 | break; |
1692 | } | 1694 | } |
1693 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); | 1695 | cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_UINT_LEN); |
1694 | 1696 | ||
1695 | devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config)); | 1697 | devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config)); |
1696 | iwe.cmd = SIOCGIWFREQ; | 1698 | iwe.cmd = SIOCGIWFREQ; |
1697 | dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq); | 1699 | dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq); |
1698 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); | 1700 | cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_FREQ_LEN); |
1699 | 1701 | ||
1700 | devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi)); | 1702 | devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi)); |
1701 | iwe.cmd = IWEVQUAL; | 1703 | iwe.cmd = IWEVQUAL; |
@@ -1704,7 +1706,7 @@ static char *rndis_translate_scan(struct net_device *dev, | |||
1704 | iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | 1706 | iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED |
1705 | | IW_QUAL_LEVEL_UPDATED | 1707 | | IW_QUAL_LEVEL_UPDATED |
1706 | | IW_QUAL_NOISE_INVALID; | 1708 | | IW_QUAL_NOISE_INVALID; |
1707 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); | 1709 | cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_QUAL_LEN); |
1708 | 1710 | ||
1709 | devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy)); | 1711 | devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy)); |
1710 | iwe.cmd = SIOCGIWENCODE; | 1712 | iwe.cmd = SIOCGIWENCODE; |
@@ -1714,10 +1716,10 @@ static char *rndis_translate_scan(struct net_device *dev, | |||
1714 | else | 1716 | else |
1715 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | 1717 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; |
1716 | 1718 | ||
1717 | cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); | 1719 | cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL); |
1718 | 1720 | ||
1719 | devdbg(usbdev, "RATES:"); | 1721 | devdbg(usbdev, "RATES:"); |
1720 | current_val = cev + IW_EV_LCP_LEN; | 1722 | current_val = cev + iwe_stream_lcp_len(info); |
1721 | iwe.cmd = SIOCGIWRATE; | 1723 | iwe.cmd = SIOCGIWRATE; |
1722 | for (i = 0; i < sizeof(bssid->rates); i++) { | 1724 | for (i = 0; i < sizeof(bssid->rates); i++) { |
1723 | if (bssid->rates[i] & 0x7f) { | 1725 | if (bssid->rates[i] & 0x7f) { |
@@ -1725,13 +1727,13 @@ static char *rndis_translate_scan(struct net_device *dev, | |||
1725 | ((bssid->rates[i] & 0x7f) * | 1727 | ((bssid->rates[i] & 0x7f) * |
1726 | 500000); | 1728 | 500000); |
1727 | devdbg(usbdev, " %d", iwe.u.bitrate.value); | 1729 | devdbg(usbdev, " %d", iwe.u.bitrate.value); |
1728 | current_val = iwe_stream_add_value(cev, | 1730 | current_val = iwe_stream_add_value(info, cev, |
1729 | current_val, end_buf, &iwe, | 1731 | current_val, end_buf, &iwe, |
1730 | IW_EV_PARAM_LEN); | 1732 | IW_EV_PARAM_LEN); |
1731 | } | 1733 | } |
1732 | } | 1734 | } |
1733 | 1735 | ||
1734 | if ((current_val - cev) > IW_EV_LCP_LEN) | 1736 | if ((current_val - cev) > iwe_stream_lcp_len(info)) |
1735 | cev = current_val; | 1737 | cev = current_val; |
1736 | 1738 | ||
1737 | beacon = le32_to_cpu(bssid->config.beacon_period); | 1739 | beacon = le32_to_cpu(bssid->config.beacon_period); |
@@ -1739,14 +1741,14 @@ static char *rndis_translate_scan(struct net_device *dev, | |||
1739 | iwe.cmd = IWEVCUSTOM; | 1741 | iwe.cmd = IWEVCUSTOM; |
1740 | snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon); | 1742 | snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon); |
1741 | iwe.u.data.length = strlen(sbuf); | 1743 | iwe.u.data.length = strlen(sbuf); |
1742 | cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); | 1744 | cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf); |
1743 | 1745 | ||
1744 | atim = le32_to_cpu(bssid->config.atim_window); | 1746 | atim = le32_to_cpu(bssid->config.atim_window); |
1745 | devdbg(usbdev, "ATIM %d", atim); | 1747 | devdbg(usbdev, "ATIM %d", atim); |
1746 | iwe.cmd = IWEVCUSTOM; | 1748 | iwe.cmd = IWEVCUSTOM; |
1747 | snprintf(sbuf, sizeof(sbuf), "atim=%u", atim); | 1749 | snprintf(sbuf, sizeof(sbuf), "atim=%u", atim); |
1748 | iwe.u.data.length = strlen(sbuf); | 1750 | iwe.u.data.length = strlen(sbuf); |
1749 | cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); | 1751 | cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf); |
1750 | 1752 | ||
1751 | ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); | 1753 | ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); |
1752 | ie_len = min(bssid_len - (int)sizeof(*bssid), | 1754 | ie_len = min(bssid_len - (int)sizeof(*bssid), |
@@ -1760,7 +1762,7 @@ static char *rndis_translate_scan(struct net_device *dev, | |||
1760 | (ie->id == MFIE_TYPE_RSN) ? 2 : 1); | 1762 | (ie->id == MFIE_TYPE_RSN) ? 2 : 1); |
1761 | iwe.cmd = IWEVGENIE; | 1763 | iwe.cmd = IWEVGENIE; |
1762 | iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN); | 1764 | iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN); |
1763 | cev = iwe_stream_add_point(cev, end_buf, &iwe, | 1765 | cev = iwe_stream_add_point(info, cev, end_buf, &iwe, |
1764 | (u8 *)ie); | 1766 | (u8 *)ie); |
1765 | } | 1767 | } |
1766 | 1768 | ||
@@ -1803,8 +1805,8 @@ static int rndis_iw_get_scan(struct net_device *dev, | |||
1803 | devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count); | 1805 | devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count); |
1804 | 1806 | ||
1805 | while (count && ((void *)bssid + bssid_len) <= (buf + len)) { | 1807 | while (count && ((void *)bssid + bssid_len) <= (buf + len)) { |
1806 | cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA, | 1808 | cev = rndis_translate_scan(dev, info, cev, |
1807 | bssid); | 1809 | extra + IW_SCAN_MAX_DATA, bssid); |
1808 | bssid = (void *)bssid + bssid_len; | 1810 | bssid = (void *)bssid + bssid_len; |
1809 | bssid_len = le32_to_cpu(bssid->length); | 1811 | bssid_len = le32_to_cpu(bssid->length); |
1810 | count--; | 1812 | count--; |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index bb3d83560d02..b3dffcfed835 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -632,15 +632,15 @@ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev, | |||
632 | struct queue_entry *entry) | 632 | struct queue_entry *entry) |
633 | { | 633 | { |
634 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 634 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
635 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
635 | u32 word; | 636 | u32 word; |
636 | 637 | ||
637 | rt2x00_desc_read(entry_priv->desc, 2, &word); | 638 | rt2x00_desc_read(entry_priv->desc, 2, &word); |
638 | rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, | 639 | rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len); |
639 | entry->queue->data_size); | ||
640 | rt2x00_desc_write(entry_priv->desc, 2, word); | 640 | rt2x00_desc_write(entry_priv->desc, 2, word); |
641 | 641 | ||
642 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 642 | rt2x00_desc_read(entry_priv->desc, 1, &word); |
643 | rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry_priv->data_dma); | 643 | rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); |
644 | rt2x00_desc_write(entry_priv->desc, 1, word); | 644 | rt2x00_desc_write(entry_priv->desc, 1, word); |
645 | 645 | ||
646 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 646 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
@@ -1012,7 +1012,7 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1012 | * Start writing the descriptor words. | 1012 | * Start writing the descriptor words. |
1013 | */ | 1013 | */ |
1014 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 1014 | rt2x00_desc_read(entry_priv->desc, 1, &word); |
1015 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry_priv->data_dma); | 1015 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); |
1016 | rt2x00_desc_write(entry_priv->desc, 1, word); | 1016 | rt2x00_desc_write(entry_priv->desc, 1, word); |
1017 | 1017 | ||
1018 | rt2x00_desc_read(txd, 2, &word); | 1018 | rt2x00_desc_read(txd, 2, &word); |
@@ -1154,7 +1154,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1154 | } | 1154 | } |
1155 | txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); | 1155 | txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); |
1156 | 1156 | ||
1157 | rt2x00pci_txdone(rt2x00dev, entry, &txdesc); | 1157 | rt2x00lib_txdone(entry, &txdesc); |
1158 | } | 1158 | } |
1159 | } | 1159 | } |
1160 | 1160 | ||
@@ -1366,7 +1366,7 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1366 | IEEE80211_HW_SIGNAL_DBM; | 1366 | IEEE80211_HW_SIGNAL_DBM; |
1367 | rt2x00dev->hw->extra_tx_headroom = 0; | 1367 | rt2x00dev->hw->extra_tx_headroom = 0; |
1368 | 1368 | ||
1369 | SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); | 1369 | SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); |
1370 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, | 1370 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, |
1371 | rt2x00_eeprom_addr(rt2x00dev, | 1371 | rt2x00_eeprom_addr(rt2x00dev, |
1372 | EEPROM_MAC_ADDR_0)); | 1372 | EEPROM_MAC_ADDR_0)); |
@@ -1412,9 +1412,10 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1412 | rt2400pci_probe_hw_mode(rt2x00dev); | 1412 | rt2400pci_probe_hw_mode(rt2x00dev); |
1413 | 1413 | ||
1414 | /* | 1414 | /* |
1415 | * This device requires the atim queue | 1415 | * This device requires the atim queue and DMA-mapped skbs. |
1416 | */ | 1416 | */ |
1417 | __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); | 1417 | __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); |
1418 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | ||
1418 | 1419 | ||
1419 | /* | 1420 | /* |
1420 | * Set the rssi offset. | 1421 | * Set the rssi offset. |
@@ -1526,7 +1527,7 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1526 | * Write entire beacon with descriptor to register, | 1527 | * Write entire beacon with descriptor to register, |
1527 | * and kick the beacon generator. | 1528 | * and kick the beacon generator. |
1528 | */ | 1529 | */ |
1529 | memcpy(entry_priv->data, skb->data, skb->len); | 1530 | rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); |
1530 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | 1531 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); |
1531 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); | 1532 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); |
1532 | 1533 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 3c956b91c4e3..0423c251c78e 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -727,10 +727,11 @@ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev, | |||
727 | struct queue_entry *entry) | 727 | struct queue_entry *entry) |
728 | { | 728 | { |
729 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 729 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
730 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
730 | u32 word; | 731 | u32 word; |
731 | 732 | ||
732 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 733 | rt2x00_desc_read(entry_priv->desc, 1, &word); |
733 | rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry_priv->data_dma); | 734 | rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); |
734 | rt2x00_desc_write(entry_priv->desc, 1, word); | 735 | rt2x00_desc_write(entry_priv->desc, 1, word); |
735 | 736 | ||
736 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 737 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
@@ -1171,7 +1172,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1171 | * Start writing the descriptor words. | 1172 | * Start writing the descriptor words. |
1172 | */ | 1173 | */ |
1173 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 1174 | rt2x00_desc_read(entry_priv->desc, 1, &word); |
1174 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry_priv->data_dma); | 1175 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); |
1175 | rt2x00_desc_write(entry_priv->desc, 1, word); | 1176 | rt2x00_desc_write(entry_priv->desc, 1, word); |
1176 | 1177 | ||
1177 | rt2x00_desc_read(txd, 2, &word); | 1178 | rt2x00_desc_read(txd, 2, &word); |
@@ -1311,7 +1312,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1311 | } | 1312 | } |
1312 | txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); | 1313 | txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); |
1313 | 1314 | ||
1314 | rt2x00pci_txdone(rt2x00dev, entry, &txdesc); | 1315 | rt2x00lib_txdone(entry, &txdesc); |
1315 | } | 1316 | } |
1316 | } | 1317 | } |
1317 | 1318 | ||
@@ -1688,7 +1689,7 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1688 | 1689 | ||
1689 | rt2x00dev->hw->extra_tx_headroom = 0; | 1690 | rt2x00dev->hw->extra_tx_headroom = 0; |
1690 | 1691 | ||
1691 | SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); | 1692 | SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); |
1692 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, | 1693 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, |
1693 | rt2x00_eeprom_addr(rt2x00dev, | 1694 | rt2x00_eeprom_addr(rt2x00dev, |
1694 | EEPROM_MAC_ADDR_0)); | 1695 | EEPROM_MAC_ADDR_0)); |
@@ -1752,9 +1753,10 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1752 | rt2500pci_probe_hw_mode(rt2x00dev); | 1753 | rt2500pci_probe_hw_mode(rt2x00dev); |
1753 | 1754 | ||
1754 | /* | 1755 | /* |
1755 | * This device requires the atim queue | 1756 | * This device requires the atim queue and DMA-mapped skbs. |
1756 | */ | 1757 | */ |
1757 | __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); | 1758 | __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); |
1759 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | ||
1758 | 1760 | ||
1759 | /* | 1761 | /* |
1760 | * Set the rssi offset. | 1762 | * Set the rssi offset. |
@@ -1842,7 +1844,7 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1842 | * Write entire beacon with descriptor to register, | 1844 | * Write entire beacon with descriptor to register, |
1843 | * and kick the beacon generator. | 1845 | * and kick the beacon generator. |
1844 | */ | 1846 | */ |
1845 | memcpy(entry_priv->data, skb->data, skb->len); | 1847 | rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); |
1846 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | 1848 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); |
1847 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); | 1849 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); |
1848 | 1850 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 0462d6d35b8a..0dd1cb537b92 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1594,7 +1594,7 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1594 | 1594 | ||
1595 | rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; | 1595 | rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; |
1596 | 1596 | ||
1597 | SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev); | 1597 | SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); |
1598 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, | 1598 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, |
1599 | rt2x00_eeprom_addr(rt2x00dev, | 1599 | rt2x00_eeprom_addr(rt2x00dev, |
1600 | EEPROM_MAC_ADDR_0)); | 1600 | EEPROM_MAC_ADDR_0)); |
@@ -1678,7 +1678,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1678 | static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | 1678 | static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) |
1679 | { | 1679 | { |
1680 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1680 | struct rt2x00_dev *rt2x00dev = hw->priv; |
1681 | struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); | 1681 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
1682 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1682 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1683 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | 1683 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); |
1684 | struct queue_entry_priv_usb_bcn *bcn_priv; | 1684 | struct queue_entry_priv_usb_bcn *bcn_priv; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 52d8e9688219..6842464dcf3e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -44,7 +44,7 @@ | |||
44 | /* | 44 | /* |
45 | * Module information. | 45 | * Module information. |
46 | */ | 46 | */ |
47 | #define DRV_VERSION "2.1.7" | 47 | #define DRV_VERSION "2.1.8" |
48 | #define DRV_PROJECT "http://rt2x00.serialmonkey.com" | 48 | #define DRV_PROJECT "http://rt2x00.serialmonkey.com" |
49 | 49 | ||
50 | /* | 50 | /* |
@@ -111,33 +111,6 @@ | |||
111 | #define EIFS ( SIFS + (8 * (IEEE80211_HEADER + ACK_SIZE)) ) | 111 | #define EIFS ( SIFS + (8 * (IEEE80211_HEADER + ACK_SIZE)) ) |
112 | 112 | ||
113 | /* | 113 | /* |
114 | * IEEE802.11 header defines | ||
115 | */ | ||
116 | static inline int is_rts_frame(u16 fc) | ||
117 | { | ||
118 | return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && | ||
119 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)); | ||
120 | } | ||
121 | |||
122 | static inline int is_cts_frame(u16 fc) | ||
123 | { | ||
124 | return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && | ||
125 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS)); | ||
126 | } | ||
127 | |||
128 | static inline int is_probe_resp(u16 fc) | ||
129 | { | ||
130 | return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && | ||
131 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)); | ||
132 | } | ||
133 | |||
134 | static inline int is_beacon(u16 fc) | ||
135 | { | ||
136 | return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && | ||
137 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Chipset identification | 114 | * Chipset identification |
142 | * The chipset on the device is composed of a RT and RF chip. | 115 | * The chipset on the device is composed of a RT and RF chip. |
143 | * The chipset combination is important for determining device capabilities. | 116 | * The chipset combination is important for determining device capabilities. |
@@ -628,6 +601,7 @@ enum rt2x00_flags { | |||
628 | DRIVER_REQUIRE_BEACON_GUARD, | 601 | DRIVER_REQUIRE_BEACON_GUARD, |
629 | DRIVER_REQUIRE_ATIM_QUEUE, | 602 | DRIVER_REQUIRE_ATIM_QUEUE, |
630 | DRIVER_REQUIRE_SCHEDULED, | 603 | DRIVER_REQUIRE_SCHEDULED, |
604 | DRIVER_REQUIRE_DMA, | ||
631 | 605 | ||
632 | /* | 606 | /* |
633 | * Driver configuration | 607 | * Driver configuration |
@@ -652,11 +626,7 @@ struct rt2x00_dev { | |||
652 | * When accessing this variable, the rt2x00dev_{pci,usb} | 626 | * When accessing this variable, the rt2x00dev_{pci,usb} |
653 | * macro's should be used for correct typecasting. | 627 | * macro's should be used for correct typecasting. |
654 | */ | 628 | */ |
655 | void *dev; | 629 | struct device *dev; |
656 | #define rt2x00dev_pci(__dev) ( (struct pci_dev *)(__dev)->dev ) | ||
657 | #define rt2x00dev_usb(__dev) ( (struct usb_interface *)(__dev)->dev ) | ||
658 | #define rt2x00dev_usb_dev(__dev)\ | ||
659 | ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) ) | ||
660 | 630 | ||
661 | /* | 631 | /* |
662 | * Callback functions. | 632 | * Callback functions. |
@@ -931,10 +901,11 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) | |||
931 | } | 901 | } |
932 | 902 | ||
933 | /** | 903 | /** |
934 | * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes. | 904 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. |
935 | * @queue: The queue for which the skb will be applicable. | 905 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
906 | * @skb: The skb to map. | ||
936 | */ | 907 | */ |
937 | struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue); | 908 | void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); |
938 | 909 | ||
939 | /** | 910 | /** |
940 | * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input | 911 | * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input |
@@ -985,26 +956,14 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, | |||
985 | struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, | 956 | struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, |
986 | enum queue_index index); | 957 | enum queue_index index); |
987 | 958 | ||
988 | /** | ||
989 | * rt2x00queue_index_inc - Index incrementation function | ||
990 | * @queue: Queue (&struct data_queue) to perform the action on. | ||
991 | * @index: Index type (&enum queue_index) to perform the action on. | ||
992 | * | ||
993 | * This function will increase the requested index on the queue, | ||
994 | * it will grab the appropriate locks and handle queue overflow events by | ||
995 | * resetting the index to the start of the queue. | ||
996 | */ | ||
997 | void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); | ||
998 | |||
999 | |||
1000 | /* | 959 | /* |
1001 | * Interrupt context handlers. | 960 | * Interrupt context handlers. |
1002 | */ | 961 | */ |
1003 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | 962 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); |
1004 | void rt2x00lib_txdone(struct queue_entry *entry, | 963 | void rt2x00lib_txdone(struct queue_entry *entry, |
1005 | struct txdone_entry_desc *txdesc); | 964 | struct txdone_entry_desc *txdesc); |
1006 | void rt2x00lib_rxdone(struct queue_entry *entry, | 965 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, |
1007 | struct rxdone_entry_desc *rxdesc); | 966 | struct queue_entry *entry); |
1008 | 967 | ||
1009 | /* | 968 | /* |
1010 | * mac80211 handlers. | 969 | * mac80211 handlers. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index cc4fee105ed6..ae8ab71fe474 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -469,12 +469,19 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work) | |||
469 | static void rt2x00lib_beacondone_iter(void *data, u8 *mac, | 469 | static void rt2x00lib_beacondone_iter(void *data, u8 *mac, |
470 | struct ieee80211_vif *vif) | 470 | struct ieee80211_vif *vif) |
471 | { | 471 | { |
472 | struct rt2x00_dev *rt2x00dev = data; | ||
472 | struct rt2x00_intf *intf = vif_to_intf(vif); | 473 | struct rt2x00_intf *intf = vif_to_intf(vif); |
473 | 474 | ||
474 | if (vif->type != IEEE80211_IF_TYPE_AP && | 475 | if (vif->type != IEEE80211_IF_TYPE_AP && |
475 | vif->type != IEEE80211_IF_TYPE_IBSS) | 476 | vif->type != IEEE80211_IF_TYPE_IBSS) |
476 | return; | 477 | return; |
477 | 478 | ||
479 | /* | ||
480 | * Clean up the beacon skb. | ||
481 | */ | ||
482 | rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb); | ||
483 | intf->beacon->skb = NULL; | ||
484 | |||
478 | spin_lock(&intf->lock); | 485 | spin_lock(&intf->lock); |
479 | intf->delayed_flags |= DELAYED_UPDATE_BEACON; | 486 | intf->delayed_flags |= DELAYED_UPDATE_BEACON; |
480 | spin_unlock(&intf->lock); | 487 | spin_unlock(&intf->lock); |
@@ -498,6 +505,12 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
498 | { | 505 | { |
499 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 506 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
500 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); | 507 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); |
508 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); | ||
509 | |||
510 | /* | ||
511 | * Unmap the skb. | ||
512 | */ | ||
513 | rt2x00queue_unmap_skb(rt2x00dev, entry->skb); | ||
501 | 514 | ||
502 | /* | 515 | /* |
503 | * Send frame to debugfs immediately, after this call is completed | 516 | * Send frame to debugfs immediately, after this call is completed |
@@ -546,39 +559,77 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
546 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | 559 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); |
547 | else | 560 | else |
548 | dev_kfree_skb_irq(entry->skb); | 561 | dev_kfree_skb_irq(entry->skb); |
562 | |||
563 | /* | ||
564 | * Make this entry available for reuse. | ||
565 | */ | ||
549 | entry->skb = NULL; | 566 | entry->skb = NULL; |
567 | entry->flags = 0; | ||
568 | |||
569 | rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry); | ||
570 | |||
571 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | ||
572 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | ||
573 | |||
574 | /* | ||
575 | * If the data queue was below the threshold before the txdone | ||
576 | * handler we must make sure the packet queue in the mac80211 stack | ||
577 | * is reenabled when the txdone handler has finished. | ||
578 | */ | ||
579 | if (!rt2x00queue_threshold(entry->queue)) | ||
580 | ieee80211_wake_queue(rt2x00dev->hw, qid); | ||
550 | } | 581 | } |
551 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); | 582 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); |
552 | 583 | ||
553 | void rt2x00lib_rxdone(struct queue_entry *entry, | 584 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, |
554 | struct rxdone_entry_desc *rxdesc) | 585 | struct queue_entry *entry) |
555 | { | 586 | { |
556 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 587 | struct rxdone_entry_desc rxdesc; |
588 | struct sk_buff *skb; | ||
557 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; | 589 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; |
558 | unsigned int header_size = ieee80211_get_hdrlen_from_skb(entry->skb); | ||
559 | struct ieee80211_supported_band *sband; | 590 | struct ieee80211_supported_band *sband; |
560 | struct ieee80211_hdr *hdr; | 591 | struct ieee80211_hdr *hdr; |
561 | const struct rt2x00_rate *rate; | 592 | const struct rt2x00_rate *rate; |
593 | unsigned int header_size; | ||
562 | unsigned int align; | 594 | unsigned int align; |
563 | unsigned int i; | 595 | unsigned int i; |
564 | int idx = -1; | 596 | int idx = -1; |
565 | u16 fc; | 597 | |
598 | /* | ||
599 | * Allocate a new sk_buffer. If no new buffer available, drop the | ||
600 | * received frame and reuse the existing buffer. | ||
601 | */ | ||
602 | skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry); | ||
603 | if (!skb) | ||
604 | return; | ||
605 | |||
606 | /* | ||
607 | * Unmap the skb. | ||
608 | */ | ||
609 | rt2x00queue_unmap_skb(rt2x00dev, entry->skb); | ||
610 | |||
611 | /* | ||
612 | * Extract the RXD details. | ||
613 | */ | ||
614 | memset(&rxdesc, 0, sizeof(rxdesc)); | ||
615 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | ||
566 | 616 | ||
567 | /* | 617 | /* |
568 | * The data behind the ieee80211 header must be | 618 | * The data behind the ieee80211 header must be |
569 | * aligned on a 4 byte boundary. | 619 | * aligned on a 4 byte boundary. |
570 | */ | 620 | */ |
621 | header_size = ieee80211_get_hdrlen_from_skb(entry->skb); | ||
571 | align = ((unsigned long)(entry->skb->data + header_size)) & 3; | 622 | align = ((unsigned long)(entry->skb->data + header_size)) & 3; |
572 | 623 | ||
573 | if (align) { | 624 | if (align) { |
574 | skb_push(entry->skb, align); | 625 | skb_push(entry->skb, align); |
575 | /* Move entire frame in 1 command */ | 626 | /* Move entire frame in 1 command */ |
576 | memmove(entry->skb->data, entry->skb->data + align, | 627 | memmove(entry->skb->data, entry->skb->data + align, |
577 | rxdesc->size); | 628 | rxdesc.size); |
578 | } | 629 | } |
579 | 630 | ||
580 | /* Update data pointers, trim buffer to correct size */ | 631 | /* Update data pointers, trim buffer to correct size */ |
581 | skb_trim(entry->skb, rxdesc->size); | 632 | skb_trim(entry->skb, rxdesc.size); |
582 | 633 | ||
583 | /* | 634 | /* |
584 | * Update RX statistics. | 635 | * Update RX statistics. |
@@ -587,10 +638,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
587 | for (i = 0; i < sband->n_bitrates; i++) { | 638 | for (i = 0; i < sband->n_bitrates; i++) { |
588 | rate = rt2x00_get_rate(sband->bitrates[i].hw_value); | 639 | rate = rt2x00_get_rate(sband->bitrates[i].hw_value); |
589 | 640 | ||
590 | if (((rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) && | 641 | if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && |
591 | (rate->plcp == rxdesc->signal)) || | 642 | (rate->plcp == rxdesc.signal)) || |
592 | (!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) && | 643 | (!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && |
593 | (rate->bitrate == rxdesc->signal))) { | 644 | (rate->bitrate == rxdesc.signal))) { |
594 | idx = i; | 645 | idx = i; |
595 | break; | 646 | break; |
596 | } | 647 | } |
@@ -598,8 +649,8 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
598 | 649 | ||
599 | if (idx < 0) { | 650 | if (idx < 0) { |
600 | WARNING(rt2x00dev, "Frame received with unrecognized signal," | 651 | WARNING(rt2x00dev, "Frame received with unrecognized signal," |
601 | "signal=0x%.2x, plcp=%d.\n", rxdesc->signal, | 652 | "signal=0x%.2x, plcp=%d.\n", rxdesc.signal, |
602 | !!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP)); | 653 | !!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP)); |
603 | idx = 0; | 654 | idx = 0; |
604 | } | 655 | } |
605 | 656 | ||
@@ -607,17 +658,17 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
607 | * Only update link status if this is a beacon frame carrying our bssid. | 658 | * Only update link status if this is a beacon frame carrying our bssid. |
608 | */ | 659 | */ |
609 | hdr = (struct ieee80211_hdr *)entry->skb->data; | 660 | hdr = (struct ieee80211_hdr *)entry->skb->data; |
610 | fc = le16_to_cpu(hdr->frame_control); | 661 | if (ieee80211_is_beacon(hdr->frame_control) && |
611 | if (is_beacon(fc) && (rxdesc->dev_flags & RXDONE_MY_BSS)) | 662 | (rxdesc.dev_flags & RXDONE_MY_BSS)) |
612 | rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi); | 663 | rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi); |
613 | 664 | ||
614 | rt2x00dev->link.qual.rx_success++; | 665 | rt2x00dev->link.qual.rx_success++; |
615 | 666 | ||
616 | rx_status->rate_idx = idx; | 667 | rx_status->rate_idx = idx; |
617 | rx_status->qual = | 668 | rx_status->qual = |
618 | rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi); | 669 | rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); |
619 | rx_status->signal = rxdesc->rssi; | 670 | rx_status->signal = rxdesc.rssi; |
620 | rx_status->flag = rxdesc->flags; | 671 | rx_status->flag = rxdesc.flags; |
621 | rx_status->antenna = rt2x00dev->link.ant.active.rx; | 672 | rx_status->antenna = rt2x00dev->link.ant.active.rx; |
622 | 673 | ||
623 | /* | 674 | /* |
@@ -626,7 +677,16 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
626 | */ | 677 | */ |
627 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | 678 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); |
628 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); | 679 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); |
629 | entry->skb = NULL; | 680 | |
681 | /* | ||
682 | * Replace the skb with the freshly allocated one. | ||
683 | */ | ||
684 | entry->skb = skb; | ||
685 | entry->flags = 0; | ||
686 | |||
687 | rt2x00dev->ops->lib->init_rxentry(rt2x00dev, entry); | ||
688 | |||
689 | rt2x00queue_index_inc(entry->queue, Q_INDEX); | ||
630 | } | 690 | } |
631 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); | 691 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); |
632 | 692 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 558f45bf27e3..1d1f0749375e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -98,10 +98,57 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
98 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | 98 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, |
99 | struct ieee80211_conf *conf, const int force_config); | 99 | struct ieee80211_conf *conf, const int force_config); |
100 | 100 | ||
101 | /* | 101 | /** |
102 | * Queue handlers. | 102 | * DOC: Queue handlers |
103 | */ | ||
104 | |||
105 | /** | ||
106 | * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes. | ||
107 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
108 | * @queue: The queue for which the skb will be applicable. | ||
109 | */ | ||
110 | struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, | ||
111 | struct queue_entry *entry); | ||
112 | |||
113 | /** | ||
114 | * rt2x00queue_unmap_skb - Unmap a skb from DMA. | ||
115 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
116 | * @skb: The skb to unmap. | ||
117 | */ | ||
118 | void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | ||
119 | |||
120 | /** | ||
121 | * rt2x00queue_free_skb - free a skb | ||
122 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
123 | * @skb: The skb to free. | ||
124 | */ | ||
125 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | ||
126 | |||
127 | /** | ||
128 | * rt2x00queue_free_skb - free a skb | ||
129 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
130 | * @skb: The skb to free. | ||
131 | */ | ||
132 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | ||
133 | |||
134 | /** | ||
135 | * rt2x00queue_write_tx_frame - Write TX frame to hardware | ||
136 | * @queue: Queue over which the frame should be send | ||
137 | * @skb: The skb to send | ||
103 | */ | 138 | */ |
104 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); | 139 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); |
140 | |||
141 | /** | ||
142 | * rt2x00queue_index_inc - Index incrementation function | ||
143 | * @queue: Queue (&struct data_queue) to perform the action on. | ||
144 | * @index: Index type (&enum queue_index) to perform the action on. | ||
145 | * | ||
146 | * This function will increase the requested index on the queue, | ||
147 | * it will grab the appropriate locks and handle queue overflow events by | ||
148 | * resetting the index to the start of the queue. | ||
149 | */ | ||
150 | void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); | ||
151 | |||
105 | void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev); | 152 | void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev); |
106 | void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev); | 153 | void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev); |
107 | int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); | 154 | int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 8d6ad18d3890..adf2876ed8ab 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -60,12 +60,8 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry) | |||
60 | * Fill in skb descriptor | 60 | * Fill in skb descriptor |
61 | */ | 61 | */ |
62 | skbdesc = get_skb_frame_desc(entry->skb); | 62 | skbdesc = get_skb_frame_desc(entry->skb); |
63 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
64 | skbdesc->desc = entry_priv->desc; | 63 | skbdesc->desc = entry_priv->desc; |
65 | skbdesc->desc_len = entry->queue->desc_size; | 64 | skbdesc->desc_len = entry->queue->desc_size; |
66 | skbdesc->entry = entry; | ||
67 | |||
68 | memcpy(entry_priv->data, entry->skb->data, entry->skb->len); | ||
69 | 65 | ||
70 | return 0; | 66 | return 0; |
71 | } | 67 | } |
@@ -80,7 +76,6 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | |||
80 | struct queue_entry *entry; | 76 | struct queue_entry *entry; |
81 | struct queue_entry_priv_pci *entry_priv; | 77 | struct queue_entry_priv_pci *entry_priv; |
82 | struct skb_frame_desc *skbdesc; | 78 | struct skb_frame_desc *skbdesc; |
83 | struct rxdone_entry_desc rxdesc; | ||
84 | u32 word; | 79 | u32 word; |
85 | 80 | ||
86 | while (1) { | 81 | while (1) { |
@@ -91,110 +86,27 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | |||
91 | if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) | 86 | if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) |
92 | break; | 87 | break; |
93 | 88 | ||
94 | memset(&rxdesc, 0, sizeof(rxdesc)); | ||
95 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | ||
96 | |||
97 | /* | 89 | /* |
98 | * Allocate the sk_buffer and copy all data into it. | 90 | * Fill in desc fields of the skb descriptor |
99 | */ | ||
100 | entry->skb = rt2x00queue_alloc_rxskb(queue); | ||
101 | if (!entry->skb) | ||
102 | return; | ||
103 | |||
104 | memcpy(entry->skb->data, entry_priv->data, rxdesc.size); | ||
105 | skb_trim(entry->skb, rxdesc.size); | ||
106 | |||
107 | /* | ||
108 | * Fill in skb descriptor | ||
109 | */ | 91 | */ |
110 | skbdesc = get_skb_frame_desc(entry->skb); | 92 | skbdesc = get_skb_frame_desc(entry->skb); |
111 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
112 | skbdesc->desc = entry_priv->desc; | 93 | skbdesc->desc = entry_priv->desc; |
113 | skbdesc->desc_len = queue->desc_size; | 94 | skbdesc->desc_len = entry->queue->desc_size; |
114 | skbdesc->entry = entry; | ||
115 | 95 | ||
116 | /* | 96 | /* |
117 | * Send the frame to rt2x00lib for further processing. | 97 | * Send the frame to rt2x00lib for further processing. |
118 | */ | 98 | */ |
119 | rt2x00lib_rxdone(entry, &rxdesc); | 99 | rt2x00lib_rxdone(rt2x00dev, entry); |
120 | |||
121 | if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) { | ||
122 | rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1); | ||
123 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
124 | } | ||
125 | |||
126 | rt2x00queue_index_inc(queue, Q_INDEX); | ||
127 | } | 100 | } |
128 | } | 101 | } |
129 | EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); | 102 | EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); |
130 | 103 | ||
131 | void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, | ||
132 | struct txdone_entry_desc *txdesc) | ||
133 | { | ||
134 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
135 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); | ||
136 | u32 word; | ||
137 | |||
138 | rt2x00lib_txdone(entry, txdesc); | ||
139 | |||
140 | /* | ||
141 | * Make this entry available for reuse. | ||
142 | */ | ||
143 | entry->flags = 0; | ||
144 | |||
145 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
146 | rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0); | ||
147 | rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0); | ||
148 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
149 | |||
150 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | ||
151 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | ||
152 | |||
153 | /* | ||
154 | * If the data queue was below the threshold before the txdone | ||
155 | * handler we must make sure the packet queue in the mac80211 stack | ||
156 | * is reenabled when the txdone handler has finished. | ||
157 | */ | ||
158 | if (!rt2x00queue_threshold(entry->queue)) | ||
159 | ieee80211_wake_queue(rt2x00dev->hw, qid); | ||
160 | |||
161 | } | ||
162 | EXPORT_SYMBOL_GPL(rt2x00pci_txdone); | ||
163 | |||
164 | /* | 104 | /* |
165 | * Device initialization handlers. | 105 | * Device initialization handlers. |
166 | */ | 106 | */ |
167 | #define desc_size(__queue) \ | ||
168 | ({ \ | ||
169 | ((__queue)->limit * (__queue)->desc_size);\ | ||
170 | }) | ||
171 | |||
172 | #define data_size(__queue) \ | ||
173 | ({ \ | ||
174 | ((__queue)->limit * (__queue)->data_size);\ | ||
175 | }) | ||
176 | |||
177 | #define dma_size(__queue) \ | ||
178 | ({ \ | ||
179 | data_size(__queue) + desc_size(__queue);\ | ||
180 | }) | ||
181 | |||
182 | #define desc_offset(__queue, __base, __i) \ | ||
183 | ({ \ | ||
184 | (__base) + data_size(__queue) + \ | ||
185 | ((__i) * (__queue)->desc_size); \ | ||
186 | }) | ||
187 | |||
188 | #define data_offset(__queue, __base, __i) \ | ||
189 | ({ \ | ||
190 | (__base) + \ | ||
191 | ((__i) * (__queue)->data_size); \ | ||
192 | }) | ||
193 | |||
194 | static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, | 107 | static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, |
195 | struct data_queue *queue) | 108 | struct data_queue *queue) |
196 | { | 109 | { |
197 | struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); | ||
198 | struct queue_entry_priv_pci *entry_priv; | 110 | struct queue_entry_priv_pci *entry_priv; |
199 | void *addr; | 111 | void *addr; |
200 | dma_addr_t dma; | 112 | dma_addr_t dma; |
@@ -203,21 +115,21 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, | |||
203 | /* | 115 | /* |
204 | * Allocate DMA memory for descriptor and buffer. | 116 | * Allocate DMA memory for descriptor and buffer. |
205 | */ | 117 | */ |
206 | addr = pci_alloc_consistent(pci_dev, dma_size(queue), &dma); | 118 | addr = dma_alloc_coherent(rt2x00dev->dev, |
119 | queue->limit * queue->desc_size, | ||
120 | &dma, GFP_KERNEL | GFP_DMA); | ||
207 | if (!addr) | 121 | if (!addr) |
208 | return -ENOMEM; | 122 | return -ENOMEM; |
209 | 123 | ||
210 | memset(addr, 0, dma_size(queue)); | 124 | memset(addr, 0, queue->limit * queue->desc_size); |
211 | 125 | ||
212 | /* | 126 | /* |
213 | * Initialize all queue entries to contain valid addresses. | 127 | * Initialize all queue entries to contain valid addresses. |
214 | */ | 128 | */ |
215 | for (i = 0; i < queue->limit; i++) { | 129 | for (i = 0; i < queue->limit; i++) { |
216 | entry_priv = queue->entries[i].priv_data; | 130 | entry_priv = queue->entries[i].priv_data; |
217 | entry_priv->desc = desc_offset(queue, addr, i); | 131 | entry_priv->desc = addr + i * queue->desc_size; |
218 | entry_priv->desc_dma = desc_offset(queue, dma, i); | 132 | entry_priv->desc_dma = dma + i * queue->desc_size; |
219 | entry_priv->data = data_offset(queue, addr, i); | ||
220 | entry_priv->data_dma = data_offset(queue, dma, i); | ||
221 | } | 133 | } |
222 | 134 | ||
223 | return 0; | 135 | return 0; |
@@ -226,19 +138,19 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, | |||
226 | static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, | 138 | static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, |
227 | struct data_queue *queue) | 139 | struct data_queue *queue) |
228 | { | 140 | { |
229 | struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); | ||
230 | struct queue_entry_priv_pci *entry_priv = | 141 | struct queue_entry_priv_pci *entry_priv = |
231 | queue->entries[0].priv_data; | 142 | queue->entries[0].priv_data; |
232 | 143 | ||
233 | if (entry_priv->data) | 144 | if (entry_priv->desc) |
234 | pci_free_consistent(pci_dev, dma_size(queue), | 145 | dma_free_coherent(rt2x00dev->dev, |
235 | entry_priv->data, entry_priv->data_dma); | 146 | queue->limit * queue->desc_size, |
236 | entry_priv->data = NULL; | 147 | entry_priv->desc, entry_priv->desc_dma); |
148 | entry_priv->desc = NULL; | ||
237 | } | 149 | } |
238 | 150 | ||
239 | int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) | 151 | int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) |
240 | { | 152 | { |
241 | struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); | 153 | struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); |
242 | struct data_queue *queue; | 154 | struct data_queue *queue; |
243 | int status; | 155 | int status; |
244 | 156 | ||
@@ -279,7 +191,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) | |||
279 | /* | 191 | /* |
280 | * Free irq line. | 192 | * Free irq line. |
281 | */ | 193 | */ |
282 | free_irq(rt2x00dev_pci(rt2x00dev)->irq, rt2x00dev); | 194 | free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev); |
283 | 195 | ||
284 | /* | 196 | /* |
285 | * Free DMA | 197 | * Free DMA |
@@ -308,7 +220,7 @@ static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) | |||
308 | 220 | ||
309 | static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev) | 221 | static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev) |
310 | { | 222 | { |
311 | struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); | 223 | struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); |
312 | 224 | ||
313 | rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0), | 225 | rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0), |
314 | pci_resource_len(pci_dev, 0)); | 226 | pci_resource_len(pci_dev, 0)); |
@@ -357,7 +269,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
357 | if (pci_set_mwi(pci_dev)) | 269 | if (pci_set_mwi(pci_dev)) |
358 | ERROR_PROBE("MWI not available.\n"); | 270 | ERROR_PROBE("MWI not available.\n"); |
359 | 271 | ||
360 | if (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) { | 272 | if (dma_set_mask(&pci_dev->dev, DMA_32BIT_MASK)) { |
361 | ERROR_PROBE("PCI DMA not supported.\n"); | 273 | ERROR_PROBE("PCI DMA not supported.\n"); |
362 | retval = -EIO; | 274 | retval = -EIO; |
363 | goto exit_disable_device; | 275 | goto exit_disable_device; |
@@ -373,7 +285,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
373 | pci_set_drvdata(pci_dev, hw); | 285 | pci_set_drvdata(pci_dev, hw); |
374 | 286 | ||
375 | rt2x00dev = hw->priv; | 287 | rt2x00dev = hw->priv; |
376 | rt2x00dev->dev = pci_dev; | 288 | rt2x00dev->dev = &pci_dev->dev; |
377 | rt2x00dev->ops = ops; | 289 | rt2x00dev->ops = ops; |
378 | rt2x00dev->hw = hw; | 290 | rt2x00dev->hw = hw; |
379 | 291 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 87c4a0cd78db..50c6df4f81db 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h | |||
@@ -107,9 +107,6 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry); | |||
107 | struct queue_entry_priv_pci { | 107 | struct queue_entry_priv_pci { |
108 | __le32 *desc; | 108 | __le32 *desc; |
109 | dma_addr_t desc_dma; | 109 | dma_addr_t desc_dma; |
110 | |||
111 | void *data; | ||
112 | dma_addr_t data_dma; | ||
113 | }; | 110 | }; |
114 | 111 | ||
115 | /** | 112 | /** |
@@ -118,15 +115,6 @@ struct queue_entry_priv_pci { | |||
118 | */ | 115 | */ |
119 | void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); | 116 | void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); |
120 | 117 | ||
121 | /** | ||
122 | * rt2x00pci_txdone - Handle TX done events | ||
123 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
124 | * @entry: Entry which has completed the transmission of a frame. | ||
125 | * @desc: TX done descriptor | ||
126 | */ | ||
127 | void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, | ||
128 | struct txdone_entry_desc *desc); | ||
129 | |||
130 | /* | 118 | /* |
131 | * Device initialization handlers. | 119 | * Device initialization handlers. |
132 | */ | 120 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 7b52039b01a6..8e86611791f0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -25,34 +25,30 @@ | |||
25 | 25 | ||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/dma-mapping.h> | ||
28 | 29 | ||
29 | #include "rt2x00.h" | 30 | #include "rt2x00.h" |
30 | #include "rt2x00lib.h" | 31 | #include "rt2x00lib.h" |
31 | 32 | ||
32 | struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue) | 33 | struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, |
34 | struct queue_entry *entry) | ||
33 | { | 35 | { |
34 | struct sk_buff *skb; | ||
35 | unsigned int frame_size; | 36 | unsigned int frame_size; |
36 | unsigned int reserved_size; | 37 | unsigned int reserved_size; |
38 | struct sk_buff *skb; | ||
39 | struct skb_frame_desc *skbdesc; | ||
37 | 40 | ||
38 | /* | 41 | /* |
39 | * The frame size includes descriptor size, because the | 42 | * The frame size includes descriptor size, because the |
40 | * hardware directly receive the frame into the skbuffer. | 43 | * hardware directly receive the frame into the skbuffer. |
41 | */ | 44 | */ |
42 | frame_size = queue->data_size + queue->desc_size; | 45 | frame_size = entry->queue->data_size + entry->queue->desc_size; |
43 | 46 | ||
44 | /* | 47 | /* |
45 | * For the allocation we should keep a few things in mind: | 48 | * Reserve a few bytes extra headroom to allow drivers some moving |
46 | * 1) 4byte alignment of 802.11 payload | 49 | * space (e.g. for alignment), while keeping the skb aligned. |
47 | * | ||
48 | * For (1) we need at most 4 bytes to guarentee the correct | ||
49 | * alignment. We are going to optimize the fact that the chance | ||
50 | * that the 802.11 header_size % 4 == 2 is much bigger then | ||
51 | * anything else. However since we need to move the frame up | ||
52 | * to 3 bytes to the front, which means we need to preallocate | ||
53 | * 6 bytes. | ||
54 | */ | 50 | */ |
55 | reserved_size = 6; | 51 | reserved_size = 8; |
56 | 52 | ||
57 | /* | 53 | /* |
58 | * Allocate skbuffer. | 54 | * Allocate skbuffer. |
@@ -64,9 +60,56 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue) | |||
64 | skb_reserve(skb, reserved_size); | 60 | skb_reserve(skb, reserved_size); |
65 | skb_put(skb, frame_size); | 61 | skb_put(skb, frame_size); |
66 | 62 | ||
63 | /* | ||
64 | * Populate skbdesc. | ||
65 | */ | ||
66 | skbdesc = get_skb_frame_desc(skb); | ||
67 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
68 | skbdesc->entry = entry; | ||
69 | |||
70 | if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) { | ||
71 | skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, | ||
72 | skb->data, | ||
73 | skb->len, | ||
74 | DMA_FROM_DEVICE); | ||
75 | skbdesc->flags |= SKBDESC_DMA_MAPPED_RX; | ||
76 | } | ||
77 | |||
67 | return skb; | 78 | return skb; |
68 | } | 79 | } |
69 | EXPORT_SYMBOL_GPL(rt2x00queue_alloc_rxskb); | 80 | |
81 | void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | ||
82 | { | ||
83 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | ||
84 | |||
85 | skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len, | ||
86 | DMA_TO_DEVICE); | ||
87 | skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; | ||
88 | } | ||
89 | EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); | ||
90 | |||
91 | void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | ||
92 | { | ||
93 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | ||
94 | |||
95 | if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) { | ||
96 | dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, | ||
97 | DMA_FROM_DEVICE); | ||
98 | skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX; | ||
99 | } | ||
100 | |||
101 | if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { | ||
102 | dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, | ||
103 | DMA_TO_DEVICE); | ||
104 | skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | ||
109 | { | ||
110 | rt2x00queue_unmap_skb(rt2x00dev, skb); | ||
111 | dev_kfree_skb_any(skb); | ||
112 | } | ||
70 | 113 | ||
71 | void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | 114 | void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, |
72 | struct txentry_desc *txdesc) | 115 | struct txentry_desc *txdesc) |
@@ -80,7 +123,6 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
80 | unsigned int data_length; | 123 | unsigned int data_length; |
81 | unsigned int duration; | 124 | unsigned int duration; |
82 | unsigned int residual; | 125 | unsigned int residual; |
83 | u16 frame_control; | ||
84 | 126 | ||
85 | memset(txdesc, 0, sizeof(*txdesc)); | 127 | memset(txdesc, 0, sizeof(*txdesc)); |
86 | 128 | ||
@@ -96,11 +138,6 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
96 | data_length = entry->skb->len + 4; | 138 | data_length = entry->skb->len + 4; |
97 | 139 | ||
98 | /* | 140 | /* |
99 | * Read required fields from ieee80211 header. | ||
100 | */ | ||
101 | frame_control = le16_to_cpu(hdr->frame_control); | ||
102 | |||
103 | /* | ||
104 | * Check whether this frame is to be acked. | 141 | * Check whether this frame is to be acked. |
105 | */ | 142 | */ |
106 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) | 143 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) |
@@ -109,9 +146,10 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
109 | /* | 146 | /* |
110 | * Check if this is a RTS/CTS frame | 147 | * Check if this is a RTS/CTS frame |
111 | */ | 148 | */ |
112 | if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { | 149 | if (ieee80211_is_rts(hdr->frame_control) || |
150 | ieee80211_is_cts(hdr->frame_control)) { | ||
113 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); | 151 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); |
114 | if (is_rts_frame(frame_control)) | 152 | if (ieee80211_is_rts(hdr->frame_control)) |
115 | __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags); | 153 | __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags); |
116 | else | 154 | else |
117 | __set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags); | 155 | __set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags); |
@@ -139,7 +177,8 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
139 | * Beacons and probe responses require the tsf timestamp | 177 | * Beacons and probe responses require the tsf timestamp |
140 | * to be inserted into the frame. | 178 | * to be inserted into the frame. |
141 | */ | 179 | */ |
142 | if (txdesc->queue == QID_BEACON || is_probe_resp(frame_control)) | 180 | if (ieee80211_is_beacon(hdr->frame_control) || |
181 | ieee80211_is_probe_resp(hdr->frame_control)) | ||
143 | __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); | 182 | __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); |
144 | 183 | ||
145 | /* | 184 | /* |
@@ -236,6 +275,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
236 | { | 275 | { |
237 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 276 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
238 | struct txentry_desc txdesc; | 277 | struct txentry_desc txdesc; |
278 | struct skb_frame_desc *skbdesc; | ||
239 | 279 | ||
240 | if (unlikely(rt2x00queue_full(queue))) | 280 | if (unlikely(rt2x00queue_full(queue))) |
241 | return -EINVAL; | 281 | return -EINVAL; |
@@ -256,11 +296,21 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
256 | entry->skb = skb; | 296 | entry->skb = skb; |
257 | rt2x00queue_create_tx_descriptor(entry, &txdesc); | 297 | rt2x00queue_create_tx_descriptor(entry, &txdesc); |
258 | 298 | ||
299 | /* | ||
300 | * skb->cb array is now ours and we are free to use it. | ||
301 | */ | ||
302 | skbdesc = get_skb_frame_desc(entry->skb); | ||
303 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
304 | skbdesc->entry = entry; | ||
305 | |||
259 | if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { | 306 | if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { |
260 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 307 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
261 | return -EIO; | 308 | return -EIO; |
262 | } | 309 | } |
263 | 310 | ||
311 | if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) | ||
312 | rt2x00queue_map_txskb(queue->rt2x00dev, skb); | ||
313 | |||
264 | __set_bit(ENTRY_DATA_PENDING, &entry->flags); | 314 | __set_bit(ENTRY_DATA_PENDING, &entry->flags); |
265 | 315 | ||
266 | rt2x00queue_index_inc(queue, Q_INDEX); | 316 | rt2x00queue_index_inc(queue, Q_INDEX); |
@@ -336,7 +386,6 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) | |||
336 | 386 | ||
337 | spin_unlock_irqrestore(&queue->lock, irqflags); | 387 | spin_unlock_irqrestore(&queue->lock, irqflags); |
338 | } | 388 | } |
339 | EXPORT_SYMBOL_GPL(rt2x00queue_index_inc); | ||
340 | 389 | ||
341 | static void rt2x00queue_reset(struct data_queue *queue) | 390 | static void rt2x00queue_reset(struct data_queue *queue) |
342 | { | 391 | { |
@@ -426,12 +475,41 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, | |||
426 | return 0; | 475 | return 0; |
427 | } | 476 | } |
428 | 477 | ||
478 | static void rt2x00queue_free_skbs(struct rt2x00_dev *rt2x00dev, | ||
479 | struct data_queue *queue) | ||
480 | { | ||
481 | unsigned int i; | ||
482 | |||
483 | if (!queue->entries) | ||
484 | return; | ||
485 | |||
486 | for (i = 0; i < queue->limit; i++) { | ||
487 | if (queue->entries[i].skb) | ||
488 | rt2x00queue_free_skb(rt2x00dev, queue->entries[i].skb); | ||
489 | } | ||
490 | } | ||
491 | |||
492 | static int rt2x00queue_alloc_rxskbs(struct rt2x00_dev *rt2x00dev, | ||
493 | struct data_queue *queue) | ||
494 | { | ||
495 | unsigned int i; | ||
496 | struct sk_buff *skb; | ||
497 | |||
498 | for (i = 0; i < queue->limit; i++) { | ||
499 | skb = rt2x00queue_alloc_rxskb(rt2x00dev, &queue->entries[i]); | ||
500 | if (!skb) | ||
501 | return -ENOMEM; | ||
502 | queue->entries[i].skb = skb; | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
429 | int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) | 508 | int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) |
430 | { | 509 | { |
431 | struct data_queue *queue; | 510 | struct data_queue *queue; |
432 | int status; | 511 | int status; |
433 | 512 | ||
434 | |||
435 | status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); | 513 | status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); |
436 | if (status) | 514 | if (status) |
437 | goto exit; | 515 | goto exit; |
@@ -446,11 +524,14 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) | |||
446 | if (status) | 524 | if (status) |
447 | goto exit; | 525 | goto exit; |
448 | 526 | ||
449 | if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) | 527 | if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) { |
450 | return 0; | 528 | status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], |
529 | rt2x00dev->ops->atim); | ||
530 | if (status) | ||
531 | goto exit; | ||
532 | } | ||
451 | 533 | ||
452 | status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], | 534 | status = rt2x00queue_alloc_rxskbs(rt2x00dev, rt2x00dev->rx); |
453 | rt2x00dev->ops->atim); | ||
454 | if (status) | 535 | if (status) |
455 | goto exit; | 536 | goto exit; |
456 | 537 | ||
@@ -468,6 +549,8 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) | |||
468 | { | 549 | { |
469 | struct data_queue *queue; | 550 | struct data_queue *queue; |
470 | 551 | ||
552 | rt2x00queue_free_skbs(rt2x00dev, rt2x00dev->rx); | ||
553 | |||
471 | queue_for_each(rt2x00dev, queue) { | 554 | queue_for_each(rt2x00dev, queue) { |
472 | kfree(queue->entries); | 555 | kfree(queue->entries); |
473 | queue->entries = NULL; | 556 | queue->entries = NULL; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index fcf52520b016..5dd9cca3c62c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -42,15 +42,18 @@ | |||
42 | /** | 42 | /** |
43 | * DOC: Number of entries per queue | 43 | * DOC: Number of entries per queue |
44 | * | 44 | * |
45 | * After research it was concluded that 12 entries in a RX and TX | 45 | * Under normal load without fragmentation 12 entries are sufficient |
46 | * queue would be sufficient. Although this is almost one third of | 46 | * without the queue being filled up to the maximum. When using fragmentation |
47 | * the amount the legacy driver allocated, the queues aren't getting | 47 | * and the queue threshold code we need to add some additional margins to |
48 | * filled to the maximum even when working with the maximum rate. | 48 | * make sure the queue will never (or only under extreme load) fill up |
49 | * completely. | ||
50 | * Since we don't use preallocated DMA having a large number of queue entries | ||
51 | * will have only minimal impact on the memory requirements for the queue. | ||
49 | */ | 52 | */ |
50 | #define RX_ENTRIES 12 | 53 | #define RX_ENTRIES 24 |
51 | #define TX_ENTRIES 12 | 54 | #define TX_ENTRIES 24 |
52 | #define BEACON_ENTRIES 1 | 55 | #define BEACON_ENTRIES 1 |
53 | #define ATIM_ENTRIES 1 | 56 | #define ATIM_ENTRIES 8 |
54 | 57 | ||
55 | /** | 58 | /** |
56 | * enum data_queue_qid: Queue identification | 59 | * enum data_queue_qid: Queue identification |
@@ -82,10 +85,13 @@ enum data_queue_qid { | |||
82 | /** | 85 | /** |
83 | * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc | 86 | * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc |
84 | * | 87 | * |
88 | * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX | ||
89 | * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX | ||
85 | */ | 90 | */ |
86 | //enum skb_frame_desc_flags { | 91 | enum skb_frame_desc_flags { |
87 | // TEMPORARILY EMPTY | 92 | SKBDESC_DMA_MAPPED_RX = (1 << 0), |
88 | //}; | 93 | SKBDESC_DMA_MAPPED_TX = (1 << 1), |
94 | }; | ||
89 | 95 | ||
90 | /** | 96 | /** |
91 | * struct skb_frame_desc: Descriptor information for the skb buffer | 97 | * struct skb_frame_desc: Descriptor information for the skb buffer |
@@ -94,19 +100,20 @@ enum data_queue_qid { | |||
94 | * this structure should not exceed the size of that array (40 bytes). | 100 | * this structure should not exceed the size of that array (40 bytes). |
95 | * | 101 | * |
96 | * @flags: Frame flags, see &enum skb_frame_desc_flags. | 102 | * @flags: Frame flags, see &enum skb_frame_desc_flags. |
97 | * @data: Pointer to data part of frame (Start of ieee80211 header). | 103 | * @desc_len: Length of the frame descriptor. |
98 | * @desc: Pointer to descriptor part of the frame. | 104 | * @desc: Pointer to descriptor part of the frame. |
99 | * Note that this pointer could point to something outside | 105 | * Note that this pointer could point to something outside |
100 | * of the scope of the skb->data pointer. | 106 | * of the scope of the skb->data pointer. |
101 | * @data_len: Length of the frame data. | 107 | * @skb_dma: (PCI-only) the DMA address associated with the sk buffer. |
102 | * @desc_len: Length of the frame descriptor. | ||
103 | * @entry: The entry to which this sk buffer belongs. | 108 | * @entry: The entry to which this sk buffer belongs. |
104 | */ | 109 | */ |
105 | struct skb_frame_desc { | 110 | struct skb_frame_desc { |
106 | unsigned int flags; | 111 | unsigned int flags; |
107 | 112 | ||
108 | void *desc; | ||
109 | unsigned int desc_len; | 113 | unsigned int desc_len; |
114 | void *desc; | ||
115 | |||
116 | dma_addr_t skb_dma; | ||
110 | 117 | ||
111 | struct queue_entry *entry; | 118 | struct queue_entry *entry; |
112 | }; | 119 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index fcef9885ab5e..207281cfa8b7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c | |||
@@ -45,14 +45,17 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) | |||
45 | if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags)) | 45 | if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags)) |
46 | return 0; | 46 | return 0; |
47 | 47 | ||
48 | if (state == RFKILL_STATE_ON) { | 48 | if (state == RFKILL_STATE_UNBLOCKED) { |
49 | INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n"); | 49 | INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n"); |
50 | __clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags); | 50 | __clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags); |
51 | retval = rt2x00lib_enable_radio(rt2x00dev); | 51 | retval = rt2x00lib_enable_radio(rt2x00dev); |
52 | } else if (state == RFKILL_STATE_OFF) { | 52 | } else if (state == RFKILL_STATE_SOFT_BLOCKED) { |
53 | INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n"); | 53 | INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n"); |
54 | __set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags); | 54 | __set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags); |
55 | rt2x00lib_disable_radio(rt2x00dev); | 55 | rt2x00lib_disable_radio(rt2x00dev); |
56 | } else { | ||
57 | WARNING(rt2x00dev, "Received unexpected rfkill state %d.\n", | ||
58 | state); | ||
56 | } | 59 | } |
57 | 60 | ||
58 | return retval; | 61 | return retval; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 3080969ae5b3..83862e7f7aec 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -40,7 +40,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, | |||
40 | void *buffer, const u16 buffer_length, | 40 | void *buffer, const u16 buffer_length, |
41 | const int timeout) | 41 | const int timeout) |
42 | { | 42 | { |
43 | struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); | 43 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
44 | int status; | 44 | int status; |
45 | unsigned int i; | 45 | unsigned int i; |
46 | unsigned int pipe = | 46 | unsigned int pipe = |
@@ -130,10 +130,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
130 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 130 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
131 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 131 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
132 | struct txdone_entry_desc txdesc; | 132 | struct txdone_entry_desc txdesc; |
133 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); | ||
134 | 133 | ||
135 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | 134 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || |
136 | !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 135 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
137 | return; | 136 | return; |
138 | 137 | ||
139 | /* | 138 | /* |
@@ -157,26 +156,12 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
157 | txdesc.retry = 0; | 156 | txdesc.retry = 0; |
158 | 157 | ||
159 | rt2x00lib_txdone(entry, &txdesc); | 158 | rt2x00lib_txdone(entry, &txdesc); |
160 | |||
161 | /* | ||
162 | * Make this entry available for reuse. | ||
163 | */ | ||
164 | entry->flags = 0; | ||
165 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | ||
166 | |||
167 | /* | ||
168 | * If the data queue was below the threshold before the txdone | ||
169 | * handler we must make sure the packet queue in the mac80211 stack | ||
170 | * is reenabled when the txdone handler has finished. | ||
171 | */ | ||
172 | if (!rt2x00queue_threshold(entry->queue)) | ||
173 | ieee80211_wake_queue(rt2x00dev->hw, qid); | ||
174 | } | 159 | } |
175 | 160 | ||
176 | int rt2x00usb_write_tx_data(struct queue_entry *entry) | 161 | int rt2x00usb_write_tx_data(struct queue_entry *entry) |
177 | { | 162 | { |
178 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 163 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
179 | struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); | 164 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
180 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 165 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
181 | struct skb_frame_desc *skbdesc; | 166 | struct skb_frame_desc *skbdesc; |
182 | u32 length; | 167 | u32 length; |
@@ -191,10 +176,8 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry) | |||
191 | * Fill in skb descriptor | 176 | * Fill in skb descriptor |
192 | */ | 177 | */ |
193 | skbdesc = get_skb_frame_desc(entry->skb); | 178 | skbdesc = get_skb_frame_desc(entry->skb); |
194 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
195 | skbdesc->desc = entry->skb->data; | 179 | skbdesc->desc = entry->skb->data; |
196 | skbdesc->desc_len = entry->queue->desc_size; | 180 | skbdesc->desc_len = entry->queue->desc_size; |
197 | skbdesc->entry = entry; | ||
198 | 181 | ||
199 | /* | 182 | /* |
200 | * USB devices cannot blindly pass the skb->len as the | 183 | * USB devices cannot blindly pass the skb->len as the |
@@ -264,13 +247,11 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
264 | { | 247 | { |
265 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 248 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
266 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 249 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
267 | struct sk_buff *skb; | 250 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
268 | struct skb_frame_desc *skbdesc; | ||
269 | struct rxdone_entry_desc rxdesc; | ||
270 | u8 rxd[32]; | 251 | u8 rxd[32]; |
271 | 252 | ||
272 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | 253 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || |
273 | !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 254 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
274 | return; | 255 | return; |
275 | 256 | ||
276 | /* | 257 | /* |
@@ -278,50 +259,22 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
278 | * to be actually valid, or if the urb is signaling | 259 | * to be actually valid, or if the urb is signaling |
279 | * a problem. | 260 | * a problem. |
280 | */ | 261 | */ |
281 | if (urb->actual_length < entry->queue->desc_size || urb->status) | 262 | if (urb->actual_length < entry->queue->desc_size || urb->status) { |
282 | goto skip_entry; | 263 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
264 | usb_submit_urb(urb, GFP_ATOMIC); | ||
265 | return; | ||
266 | } | ||
283 | 267 | ||
284 | /* | 268 | /* |
285 | * Fill in skb descriptor | 269 | * Fill in desc fields of the skb descriptor |
286 | */ | 270 | */ |
287 | skbdesc = get_skb_frame_desc(entry->skb); | ||
288 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
289 | skbdesc->entry = entry; | ||
290 | skbdesc->desc = rxd; | 271 | skbdesc->desc = rxd; |
291 | skbdesc->desc_len = entry->queue->desc_size; | 272 | skbdesc->desc_len = entry->queue->desc_size; |
292 | 273 | ||
293 | memset(&rxdesc, 0, sizeof(rxdesc)); | ||
294 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | ||
295 | |||
296 | /* | ||
297 | * Allocate a new sk buffer to replace the current one. | ||
298 | * If allocation fails, we should drop the current frame | ||
299 | * so we can recycle the existing sk buffer for the new frame. | ||
300 | */ | ||
301 | skb = rt2x00queue_alloc_rxskb(entry->queue); | ||
302 | if (!skb) | ||
303 | goto skip_entry; | ||
304 | |||
305 | /* | 274 | /* |
306 | * Send the frame to rt2x00lib for further processing. | 275 | * Send the frame to rt2x00lib for further processing. |
307 | */ | 276 | */ |
308 | rt2x00lib_rxdone(entry, &rxdesc); | 277 | rt2x00lib_rxdone(rt2x00dev, entry); |
309 | |||
310 | /* | ||
311 | * Replace current entry's skb with the newly allocated one, | ||
312 | * and reinitialize the urb. | ||
313 | */ | ||
314 | entry->skb = skb; | ||
315 | urb->transfer_buffer = entry->skb->data; | ||
316 | urb->transfer_buffer_length = entry->skb->len; | ||
317 | |||
318 | skip_entry: | ||
319 | if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) { | ||
320 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | ||
321 | usb_submit_urb(urb, GFP_ATOMIC); | ||
322 | } | ||
323 | |||
324 | rt2x00queue_index_inc(entry->queue, Q_INDEX); | ||
325 | } | 278 | } |
326 | 279 | ||
327 | /* | 280 | /* |
@@ -331,6 +284,7 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
331 | { | 284 | { |
332 | struct queue_entry_priv_usb *entry_priv; | 285 | struct queue_entry_priv_usb *entry_priv; |
333 | struct queue_entry_priv_usb_bcn *bcn_priv; | 286 | struct queue_entry_priv_usb_bcn *bcn_priv; |
287 | struct data_queue *queue; | ||
334 | unsigned int i; | 288 | unsigned int i; |
335 | 289 | ||
336 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, | 290 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, |
@@ -339,9 +293,11 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
339 | /* | 293 | /* |
340 | * Cancel all queues. | 294 | * Cancel all queues. |
341 | */ | 295 | */ |
342 | for (i = 0; i < rt2x00dev->rx->limit; i++) { | 296 | queue_for_each(rt2x00dev, queue) { |
343 | entry_priv = rt2x00dev->rx->entries[i].priv_data; | 297 | for (i = 0; i < queue->limit; i++) { |
344 | usb_kill_urb(entry_priv->urb); | 298 | entry_priv = queue->entries[i].priv_data; |
299 | usb_kill_urb(entry_priv->urb); | ||
300 | } | ||
345 | } | 301 | } |
346 | 302 | ||
347 | /* | 303 | /* |
@@ -364,7 +320,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); | |||
364 | void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, | 320 | void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, |
365 | struct queue_entry *entry) | 321 | struct queue_entry *entry) |
366 | { | 322 | { |
367 | struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); | 323 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
368 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 324 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
369 | 325 | ||
370 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, | 326 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, |
@@ -431,8 +387,6 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, | |||
431 | entry_priv = queue->entries[i].priv_data; | 387 | entry_priv = queue->entries[i].priv_data; |
432 | usb_kill_urb(entry_priv->urb); | 388 | usb_kill_urb(entry_priv->urb); |
433 | usb_free_urb(entry_priv->urb); | 389 | usb_free_urb(entry_priv->urb); |
434 | if (queue->entries[i].skb) | ||
435 | kfree_skb(queue->entries[i].skb); | ||
436 | } | 390 | } |
437 | 391 | ||
438 | /* | 392 | /* |
@@ -454,10 +408,7 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, | |||
454 | int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) | 408 | int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) |
455 | { | 409 | { |
456 | struct data_queue *queue; | 410 | struct data_queue *queue; |
457 | struct sk_buff *skb; | 411 | int status; |
458 | unsigned int entry_size; | ||
459 | unsigned int i; | ||
460 | int uninitialized_var(status); | ||
461 | 412 | ||
462 | /* | 413 | /* |
463 | * Allocate DMA | 414 | * Allocate DMA |
@@ -468,18 +419,6 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) | |||
468 | goto exit; | 419 | goto exit; |
469 | } | 420 | } |
470 | 421 | ||
471 | /* | ||
472 | * For the RX queue, skb's should be allocated. | ||
473 | */ | ||
474 | entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size; | ||
475 | for (i = 0; i < rt2x00dev->rx->limit; i++) { | ||
476 | skb = rt2x00queue_alloc_rxskb(rt2x00dev->rx); | ||
477 | if (!skb) | ||
478 | goto exit; | ||
479 | |||
480 | rt2x00dev->rx->entries[i].skb = skb; | ||
481 | } | ||
482 | |||
483 | return 0; | 422 | return 0; |
484 | 423 | ||
485 | exit: | 424 | exit: |
@@ -558,7 +497,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, | |||
558 | usb_set_intfdata(usb_intf, hw); | 497 | usb_set_intfdata(usb_intf, hw); |
559 | 498 | ||
560 | rt2x00dev = hw->priv; | 499 | rt2x00dev = hw->priv; |
561 | rt2x00dev->dev = usb_intf; | 500 | rt2x00dev->dev = &usb_intf->dev; |
562 | rt2x00dev->ops = ops; | 501 | rt2x00dev->ops = ops; |
563 | rt2x00dev->hw = hw; | 502 | rt2x00dev->hw = hw; |
564 | mutex_init(&rt2x00dev->usb_cache_mutex); | 503 | mutex_init(&rt2x00dev->usb_cache_mutex); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index b1187c812e7f..aad794adf52c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -26,6 +26,12 @@ | |||
26 | #ifndef RT2X00USB_H | 26 | #ifndef RT2X00USB_H |
27 | #define RT2X00USB_H | 27 | #define RT2X00USB_H |
28 | 28 | ||
29 | #define to_usb_device_intf(d) \ | ||
30 | ({ \ | ||
31 | struct usb_interface *intf = to_usb_interface(d); \ | ||
32 | interface_to_usbdev(intf); \ | ||
33 | }) | ||
34 | |||
29 | /* | 35 | /* |
30 | * This variable should be used with the | 36 | * This variable should be used with the |
31 | * usb_driver structure initialization. | 37 | * usb_driver structure initialization. |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 5b7267ece1b9..bbf1048f6400 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1030,11 +1030,12 @@ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, | |||
1030 | struct queue_entry *entry) | 1030 | struct queue_entry *entry) |
1031 | { | 1031 | { |
1032 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1032 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
1033 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1033 | u32 word; | 1034 | u32 word; |
1034 | 1035 | ||
1035 | rt2x00_desc_read(entry_priv->desc, 5, &word); | 1036 | rt2x00_desc_read(entry_priv->desc, 5, &word); |
1036 | rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, | 1037 | rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, |
1037 | entry_priv->data_dma); | 1038 | skbdesc->skb_dma); |
1038 | rt2x00_desc_write(entry_priv->desc, 5, word); | 1039 | rt2x00_desc_write(entry_priv->desc, 5, word); |
1039 | 1040 | ||
1040 | rt2x00_desc_read(entry_priv->desc, 0, &word); | 1041 | rt2x00_desc_read(entry_priv->desc, 0, &word); |
@@ -1522,7 +1523,6 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1522 | struct txentry_desc *txdesc) | 1523 | struct txentry_desc *txdesc) |
1523 | { | 1524 | { |
1524 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 1525 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
1525 | struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; | ||
1526 | __le32 *txd = skbdesc->desc; | 1526 | __le32 *txd = skbdesc->desc; |
1527 | u32 word; | 1527 | u32 word; |
1528 | 1528 | ||
@@ -1557,7 +1557,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1557 | 1557 | ||
1558 | rt2x00_desc_read(txd, 6, &word); | 1558 | rt2x00_desc_read(txd, 6, &word); |
1559 | rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, | 1559 | rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, |
1560 | entry_priv->data_dma); | 1560 | skbdesc->skb_dma); |
1561 | rt2x00_desc_write(txd, 6, word); | 1561 | rt2x00_desc_write(txd, 6, word); |
1562 | 1562 | ||
1563 | if (skbdesc->desc_len > TXINFO_SIZE) { | 1563 | if (skbdesc->desc_len > TXINFO_SIZE) { |
@@ -1767,7 +1767,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
1767 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | 1767 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); |
1768 | txdesc.retry = 0; | 1768 | txdesc.retry = 0; |
1769 | 1769 | ||
1770 | rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc); | 1770 | rt2x00lib_txdone(entry_done, &txdesc); |
1771 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 1771 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
1772 | } | 1772 | } |
1773 | 1773 | ||
@@ -1787,7 +1787,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
1787 | } | 1787 | } |
1788 | txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); | 1788 | txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); |
1789 | 1789 | ||
1790 | rt2x00pci_txdone(rt2x00dev, entry, &txdesc); | 1790 | rt2x00lib_txdone(entry, &txdesc); |
1791 | } | 1791 | } |
1792 | } | 1792 | } |
1793 | 1793 | ||
@@ -1973,7 +1973,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1973 | * To determine the RT chip we have to read the | 1973 | * To determine the RT chip we have to read the |
1974 | * PCI header of the device. | 1974 | * PCI header of the device. |
1975 | */ | 1975 | */ |
1976 | pci_read_config_word(rt2x00dev_pci(rt2x00dev), | 1976 | pci_read_config_word(to_pci_dev(rt2x00dev->dev), |
1977 | PCI_CONFIG_HEADER_DEVICE, &device); | 1977 | PCI_CONFIG_HEADER_DEVICE, &device); |
1978 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1978 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1979 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); | 1979 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); |
@@ -2239,7 +2239,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2239 | IEEE80211_HW_SIGNAL_DBM; | 2239 | IEEE80211_HW_SIGNAL_DBM; |
2240 | rt2x00dev->hw->extra_tx_headroom = 0; | 2240 | rt2x00dev->hw->extra_tx_headroom = 0; |
2241 | 2241 | ||
2242 | SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); | 2242 | SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); |
2243 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, | 2243 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, |
2244 | rt2x00_eeprom_addr(rt2x00dev, | 2244 | rt2x00_eeprom_addr(rt2x00dev, |
2245 | EEPROM_MAC_ADDR_0)); | 2245 | EEPROM_MAC_ADDR_0)); |
@@ -2302,9 +2302,10 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2302 | rt61pci_probe_hw_mode(rt2x00dev); | 2302 | rt61pci_probe_hw_mode(rt2x00dev); |
2303 | 2303 | ||
2304 | /* | 2304 | /* |
2305 | * This device requires firmware. | 2305 | * This device requires firmware and DMA mapped skbs. |
2306 | */ | 2306 | */ |
2307 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 2307 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
2308 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | ||
2308 | 2309 | ||
2309 | /* | 2310 | /* |
2310 | * Set the rssi offset. | 2311 | * Set the rssi offset. |
@@ -2402,6 +2403,12 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2402 | skb->data, skb->len); | 2403 | skb->data, skb->len); |
2403 | rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON); | 2404 | rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON); |
2404 | 2405 | ||
2406 | /* | ||
2407 | * Clean up beacon skb. | ||
2408 | */ | ||
2409 | dev_kfree_skb_any(skb); | ||
2410 | intf->beacon->skb = NULL; | ||
2411 | |||
2405 | return 0; | 2412 | return 0; |
2406 | } | 2413 | } |
2407 | 2414 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 675ff7900eee..3ef318e098e7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1827,7 +1827,7 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1827 | IEEE80211_HW_SIGNAL_DBM; | 1827 | IEEE80211_HW_SIGNAL_DBM; |
1828 | rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; | 1828 | rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; |
1829 | 1829 | ||
1830 | SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev); | 1830 | SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); |
1831 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, | 1831 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, |
1832 | rt2x00_eeprom_addr(rt2x00dev, | 1832 | rt2x00_eeprom_addr(rt2x00dev, |
1833 | EEPROM_MAC_ADDR_0)); | 1833 | EEPROM_MAC_ADDR_0)); |
@@ -2007,6 +2007,12 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2007 | REGISTER_TIMEOUT32(skb->len)); | 2007 | REGISTER_TIMEOUT32(skb->len)); |
2008 | rt73usb_kick_tx_queue(rt2x00dev, QID_BEACON); | 2008 | rt73usb_kick_tx_queue(rt2x00dev, QID_BEACON); |
2009 | 2009 | ||
2010 | /* | ||
2011 | * Clean up the beacon skb. | ||
2012 | */ | ||
2013 | dev_kfree_skb(skb); | ||
2014 | intf->beacon->skb = NULL; | ||
2015 | |||
2010 | return 0; | 2016 | return 0; |
2011 | } | 2017 | } |
2012 | 2018 | ||
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c deleted file mode 100644 index 883af891ebfb..000000000000 --- a/drivers/net/wireless/strip.c +++ /dev/null | |||
@@ -1,2804 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 1996 The Board of Trustees of The Leland Stanford | ||
3 | * Junior University. All Rights Reserved. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this | ||
6 | * software and its documentation for any purpose and without | ||
7 | * fee is hereby granted, provided that the above copyright | ||
8 | * notice appear in all copies. Stanford University | ||
9 | * makes no representations about the suitability of this | ||
10 | * software for any purpose. It is provided "as is" without | ||
11 | * express or implied warranty. | ||
12 | * | ||
13 | * strip.c This module implements Starmode Radio IP (STRIP) | ||
14 | * for kernel-based devices like TTY. It interfaces between a | ||
15 | * raw TTY, and the kernel's INET protocol layers (via DDI). | ||
16 | * | ||
17 | * Version: @(#)strip.c 1.3 July 1997 | ||
18 | * | ||
19 | * Author: Stuart Cheshire <cheshire@cs.stanford.edu> | ||
20 | * | ||
21 | * Fixes: v0.9 12th Feb 1996 (SC) | ||
22 | * New byte stuffing (2+6 run-length encoding) | ||
23 | * New watchdog timer task | ||
24 | * New Protocol key (SIP0) | ||
25 | * | ||
26 | * v0.9.1 3rd March 1996 (SC) | ||
27 | * Changed to dynamic device allocation -- no more compile | ||
28 | * time (or boot time) limit on the number of STRIP devices. | ||
29 | * | ||
30 | * v0.9.2 13th March 1996 (SC) | ||
31 | * Uses arp cache lookups (but doesn't send arp packets yet) | ||
32 | * | ||
33 | * v0.9.3 17th April 1996 (SC) | ||
34 | * Fixed bug where STR_ERROR flag was getting set unneccessarily | ||
35 | * (causing otherwise good packets to be unneccessarily dropped) | ||
36 | * | ||
37 | * v0.9.4 27th April 1996 (SC) | ||
38 | * First attempt at using "&COMMAND" Starmode AT commands | ||
39 | * | ||
40 | * v0.9.5 29th May 1996 (SC) | ||
41 | * First attempt at sending (unicast) ARP packets | ||
42 | * | ||
43 | * v0.9.6 5th June 1996 (Elliot) | ||
44 | * Put "message level" tags in every "printk" statement | ||
45 | * | ||
46 | * v0.9.7 13th June 1996 (laik) | ||
47 | * Added support for the /proc fs | ||
48 | * | ||
49 | * v0.9.8 July 1996 (Mema) | ||
50 | * Added packet logging | ||
51 | * | ||
52 | * v1.0 November 1996 (SC) | ||
53 | * Fixed (severe) memory leaks in the /proc fs code | ||
54 | * Fixed race conditions in the logging code | ||
55 | * | ||
56 | * v1.1 January 1997 (SC) | ||
57 | * Deleted packet logging (use tcpdump instead) | ||
58 | * Added support for Metricom Firmware v204 features | ||
59 | * (like message checksums) | ||
60 | * | ||
61 | * v1.2 January 1997 (SC) | ||
62 | * Put portables list back in | ||
63 | * | ||
64 | * v1.3 July 1997 (SC) | ||
65 | * Made STRIP driver set the radio's baud rate automatically. | ||
66 | * It is no longer necessarily to manually set the radio's | ||
67 | * rate permanently to 115200 -- the driver handles setting | ||
68 | * the rate automatically. | ||
69 | */ | ||
70 | |||
71 | #ifdef MODULE | ||
72 | static const char StripVersion[] = "1.3A-STUART.CHESHIRE-MODULAR"; | ||
73 | #else | ||
74 | static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; | ||
75 | #endif | ||
76 | |||
77 | #define TICKLE_TIMERS 0 | ||
78 | #define EXT_COUNTERS 1 | ||
79 | |||
80 | |||
81 | /************************************************************************/ | ||
82 | /* Header files */ | ||
83 | |||
84 | #include <linux/kernel.h> | ||
85 | #include <linux/module.h> | ||
86 | #include <linux/init.h> | ||
87 | #include <linux/bitops.h> | ||
88 | #include <asm/system.h> | ||
89 | #include <asm/uaccess.h> | ||
90 | |||
91 | # include <linux/ctype.h> | ||
92 | #include <linux/string.h> | ||
93 | #include <linux/mm.h> | ||
94 | #include <linux/interrupt.h> | ||
95 | #include <linux/in.h> | ||
96 | #include <linux/tty.h> | ||
97 | #include <linux/errno.h> | ||
98 | #include <linux/netdevice.h> | ||
99 | #include <linux/inetdevice.h> | ||
100 | #include <linux/etherdevice.h> | ||
101 | #include <linux/skbuff.h> | ||
102 | #include <linux/if_arp.h> | ||
103 | #include <linux/if_strip.h> | ||
104 | #include <linux/proc_fs.h> | ||
105 | #include <linux/seq_file.h> | ||
106 | #include <linux/serial.h> | ||
107 | #include <linux/serialP.h> | ||
108 | #include <linux/rcupdate.h> | ||
109 | #include <net/arp.h> | ||
110 | #include <net/net_namespace.h> | ||
111 | |||
112 | #include <linux/ip.h> | ||
113 | #include <linux/tcp.h> | ||
114 | #include <linux/time.h> | ||
115 | #include <linux/jiffies.h> | ||
116 | |||
117 | /************************************************************************/ | ||
118 | /* Useful structures and definitions */ | ||
119 | |||
120 | /* | ||
121 | * A MetricomKey identifies the protocol being carried inside a Metricom | ||
122 | * Starmode packet. | ||
123 | */ | ||
124 | |||
125 | typedef union { | ||
126 | __u8 c[4]; | ||
127 | __u32 l; | ||
128 | } MetricomKey; | ||
129 | |||
130 | /* | ||
131 | * An IP address can be viewed as four bytes in memory (which is what it is) or as | ||
132 | * a single 32-bit long (which is convenient for assignment, equality testing etc.) | ||
133 | */ | ||
134 | |||
135 | typedef union { | ||
136 | __u8 b[4]; | ||
137 | __u32 l; | ||
138 | } IPaddr; | ||
139 | |||
140 | /* | ||
141 | * A MetricomAddressString is used to hold a printable representation of | ||
142 | * a Metricom address. | ||
143 | */ | ||
144 | |||
145 | typedef struct { | ||
146 | __u8 c[24]; | ||
147 | } MetricomAddressString; | ||
148 | |||
149 | /* Encapsulation can expand packet of size x to 65/64x + 1 | ||
150 | * Sent packet looks like "<CR>*<address>*<key><encaps payload><CR>" | ||
151 | * 1 1 1-18 1 4 ? 1 | ||
152 | * eg. <CR>*0000-1234*SIP0<encaps payload><CR> | ||
153 | * We allow 31 bytes for the stars, the key, the address and the <CR>s | ||
154 | */ | ||
155 | #define STRIP_ENCAP_SIZE(X) (32 + (X)*65L/64L) | ||
156 | |||
157 | /* | ||
158 | * A STRIP_Header is never really sent over the radio, but making a dummy | ||
159 | * header for internal use within the kernel that looks like an Ethernet | ||
160 | * header makes certain other software happier. For example, tcpdump | ||
161 | * already understands Ethernet headers. | ||
162 | */ | ||
163 | |||
164 | typedef struct { | ||
165 | MetricomAddress dst_addr; /* Destination address, e.g. "0000-1234" */ | ||
166 | MetricomAddress src_addr; /* Source address, e.g. "0000-5678" */ | ||
167 | unsigned short protocol; /* The protocol type, using Ethernet codes */ | ||
168 | } STRIP_Header; | ||
169 | |||
170 | typedef struct { | ||
171 | char c[60]; | ||
172 | } MetricomNode; | ||
173 | |||
174 | #define NODE_TABLE_SIZE 32 | ||
175 | typedef struct { | ||
176 | struct timeval timestamp; | ||
177 | int num_nodes; | ||
178 | MetricomNode node[NODE_TABLE_SIZE]; | ||
179 | } MetricomNodeTable; | ||
180 | |||
181 | enum { FALSE = 0, TRUE = 1 }; | ||
182 | |||
183 | /* | ||
184 | * Holds the radio's firmware version. | ||
185 | */ | ||
186 | typedef struct { | ||
187 | char c[50]; | ||
188 | } FirmwareVersion; | ||
189 | |||
190 | /* | ||
191 | * Holds the radio's serial number. | ||
192 | */ | ||
193 | typedef struct { | ||
194 | char c[18]; | ||
195 | } SerialNumber; | ||
196 | |||
197 | /* | ||
198 | * Holds the radio's battery voltage. | ||
199 | */ | ||
200 | typedef struct { | ||
201 | char c[11]; | ||
202 | } BatteryVoltage; | ||
203 | |||
204 | typedef struct { | ||
205 | char c[8]; | ||
206 | } char8; | ||
207 | |||
208 | enum { | ||
209 | NoStructure = 0, /* Really old firmware */ | ||
210 | StructuredMessages = 1, /* Parsable AT response msgs */ | ||
211 | ChecksummedMessages = 2 /* Parsable AT response msgs with checksums */ | ||
212 | }; | ||
213 | |||
214 | struct strip { | ||
215 | int magic; | ||
216 | /* | ||
217 | * These are pointers to the malloc()ed frame buffers. | ||
218 | */ | ||
219 | |||
220 | unsigned char *rx_buff; /* buffer for received IP packet */ | ||
221 | unsigned char *sx_buff; /* buffer for received serial data */ | ||
222 | int sx_count; /* received serial data counter */ | ||
223 | int sx_size; /* Serial buffer size */ | ||
224 | unsigned char *tx_buff; /* transmitter buffer */ | ||
225 | unsigned char *tx_head; /* pointer to next byte to XMIT */ | ||
226 | int tx_left; /* bytes left in XMIT queue */ | ||
227 | int tx_size; /* Serial buffer size */ | ||
228 | |||
229 | /* | ||
230 | * STRIP interface statistics. | ||
231 | */ | ||
232 | |||
233 | unsigned long rx_packets; /* inbound frames counter */ | ||
234 | unsigned long tx_packets; /* outbound frames counter */ | ||
235 | unsigned long rx_errors; /* Parity, etc. errors */ | ||
236 | unsigned long tx_errors; /* Planned stuff */ | ||
237 | unsigned long rx_dropped; /* No memory for skb */ | ||
238 | unsigned long tx_dropped; /* When MTU change */ | ||
239 | unsigned long rx_over_errors; /* Frame bigger then STRIP buf. */ | ||
240 | |||
241 | unsigned long pps_timer; /* Timer to determine pps */ | ||
242 | unsigned long rx_pps_count; /* Counter to determine pps */ | ||
243 | unsigned long tx_pps_count; /* Counter to determine pps */ | ||
244 | unsigned long sx_pps_count; /* Counter to determine pps */ | ||
245 | unsigned long rx_average_pps; /* rx packets per second * 8 */ | ||
246 | unsigned long tx_average_pps; /* tx packets per second * 8 */ | ||
247 | unsigned long sx_average_pps; /* sent packets per second * 8 */ | ||
248 | |||
249 | #ifdef EXT_COUNTERS | ||
250 | unsigned long rx_bytes; /* total received bytes */ | ||
251 | unsigned long tx_bytes; /* total received bytes */ | ||
252 | unsigned long rx_rbytes; /* bytes thru radio i/f */ | ||
253 | unsigned long tx_rbytes; /* bytes thru radio i/f */ | ||
254 | unsigned long rx_sbytes; /* tot bytes thru serial i/f */ | ||
255 | unsigned long tx_sbytes; /* tot bytes thru serial i/f */ | ||
256 | unsigned long rx_ebytes; /* tot stat/err bytes */ | ||
257 | unsigned long tx_ebytes; /* tot stat/err bytes */ | ||
258 | #endif | ||
259 | |||
260 | /* | ||
261 | * Internal variables. | ||
262 | */ | ||
263 | |||
264 | struct list_head list; /* Linked list of devices */ | ||
265 | |||
266 | int discard; /* Set if serial error */ | ||
267 | int working; /* Is radio working correctly? */ | ||
268 | int firmware_level; /* Message structuring level */ | ||
269 | int next_command; /* Next periodic command */ | ||
270 | unsigned int user_baud; /* The user-selected baud rate */ | ||
271 | int mtu; /* Our mtu (to spot changes!) */ | ||
272 | long watchdog_doprobe; /* Next time to test the radio */ | ||
273 | long watchdog_doreset; /* Time to do next reset */ | ||
274 | long gratuitous_arp; /* Time to send next ARP refresh */ | ||
275 | long arp_interval; /* Next ARP interval */ | ||
276 | struct timer_list idle_timer; /* For periodic wakeup calls */ | ||
277 | MetricomAddress true_dev_addr; /* True address of radio */ | ||
278 | int manual_dev_addr; /* Hack: See note below */ | ||
279 | |||
280 | FirmwareVersion firmware_version; /* The radio's firmware version */ | ||
281 | SerialNumber serial_number; /* The radio's serial number */ | ||
282 | BatteryVoltage battery_voltage; /* The radio's battery voltage */ | ||
283 | |||
284 | /* | ||
285 | * Other useful structures. | ||
286 | */ | ||
287 | |||
288 | struct tty_struct *tty; /* ptr to TTY structure */ | ||
289 | struct net_device *dev; /* Our device structure */ | ||
290 | |||
291 | /* | ||
292 | * Neighbour radio records | ||
293 | */ | ||
294 | |||
295 | MetricomNodeTable portables; | ||
296 | MetricomNodeTable poletops; | ||
297 | }; | ||
298 | |||
299 | /* | ||
300 | * Note: manual_dev_addr hack | ||
301 | * | ||
302 | * It is not possible to change the hardware address of a Metricom radio, | ||
303 | * or to send packets with a user-specified hardware source address, thus | ||
304 | * trying to manually set a hardware source address is a questionable | ||
305 | * thing to do. However, if the user *does* manually set the hardware | ||
306 | * source address of a STRIP interface, then the kernel will believe it, | ||
307 | * and use it in certain places. For example, the hardware address listed | ||
308 | * by ifconfig will be the manual address, not the true one. | ||
309 | * (Both addresses are listed in /proc/net/strip.) | ||
310 | * Also, ARP packets will be sent out giving the user-specified address as | ||
311 | * the source address, not the real address. This is dangerous, because | ||
312 | * it means you won't receive any replies -- the ARP replies will go to | ||
313 | * the specified address, which will be some other radio. The case where | ||
314 | * this is useful is when that other radio is also connected to the same | ||
315 | * machine. This allows you to connect a pair of radios to one machine, | ||
316 | * and to use one exclusively for inbound traffic, and the other | ||
317 | * exclusively for outbound traffic. Pretty neat, huh? | ||
318 | * | ||
319 | * Here's the full procedure to set this up: | ||
320 | * | ||
321 | * 1. "slattach" two interfaces, e.g. st0 for outgoing packets, | ||
322 | * and st1 for incoming packets | ||
323 | * | ||
324 | * 2. "ifconfig" st0 (outbound radio) to have the hardware address | ||
325 | * which is the real hardware address of st1 (inbound radio). | ||
326 | * Now when it sends out packets, it will masquerade as st1, and | ||
327 | * replies will be sent to that radio, which is exactly what we want. | ||
328 | * | ||
329 | * 3. Set the route table entry ("route add default ..." or | ||
330 | * "route add -net ...", as appropriate) to send packets via the st0 | ||
331 | * interface (outbound radio). Do not add any route which sends packets | ||
332 | * out via the st1 interface -- that radio is for inbound traffic only. | ||
333 | * | ||
334 | * 4. "ifconfig" st1 (inbound radio) to have hardware address zero. | ||
335 | * This tells the STRIP driver to "shut down" that interface and not | ||
336 | * send any packets through it. In particular, it stops sending the | ||
337 | * periodic gratuitous ARP packets that a STRIP interface normally sends. | ||
338 | * Also, when packets arrive on that interface, it will search the | ||
339 | * interface list to see if there is another interface who's manual | ||
340 | * hardware address matches its own real address (i.e. st0 in this | ||
341 | * example) and if so it will transfer ownership of the skbuff to | ||
342 | * that interface, so that it looks to the kernel as if the packet | ||
343 | * arrived on that interface. This is necessary because when the | ||
344 | * kernel sends an ARP packet on st0, it expects to get a reply on | ||
345 | * st0, and if it sees the reply come from st1 then it will ignore | ||
346 | * it (to be accurate, it puts the entry in the ARP table, but | ||
347 | * labelled in such a way that st0 can't use it). | ||
348 | * | ||
349 | * Thanks to Petros Maniatis for coming up with the idea of splitting | ||
350 | * inbound and outbound traffic between two interfaces, which turned | ||
351 | * out to be really easy to implement, even if it is a bit of a hack. | ||
352 | * | ||
353 | * Having set a manual address on an interface, you can restore it | ||
354 | * to automatic operation (where the address is automatically kept | ||
355 | * consistent with the real address of the radio) by setting a manual | ||
356 | * address of all ones, e.g. "ifconfig st0 hw strip FFFFFFFFFFFF" | ||
357 | * This 'turns off' manual override mode for the device address. | ||
358 | * | ||
359 | * Note: The IEEE 802 headers reported in tcpdump will show the *real* | ||
360 | * radio addresses the packets were sent and received from, so that you | ||
361 | * can see what is really going on with packets, and which interfaces | ||
362 | * they are really going through. | ||
363 | */ | ||
364 | |||
365 | |||
366 | /************************************************************************/ | ||
367 | /* Constants */ | ||
368 | |||
369 | /* | ||
370 | * CommandString1 works on all radios | ||
371 | * Other CommandStrings are only used with firmware that provides structured responses. | ||
372 | * | ||
373 | * ats319=1 Enables Info message for node additions and deletions | ||
374 | * ats319=2 Enables Info message for a new best node | ||
375 | * ats319=4 Enables checksums | ||
376 | * ats319=8 Enables ACK messages | ||
377 | */ | ||
378 | |||
379 | static const int MaxCommandStringLength = 32; | ||
380 | static const int CompatibilityCommand = 1; | ||
381 | |||
382 | static const char CommandString0[] = "*&COMMAND*ATS319=7"; /* Turn on checksums & info messages */ | ||
383 | static const char CommandString1[] = "*&COMMAND*ATS305?"; /* Query radio name */ | ||
384 | static const char CommandString2[] = "*&COMMAND*ATS325?"; /* Query battery voltage */ | ||
385 | static const char CommandString3[] = "*&COMMAND*ATS300?"; /* Query version information */ | ||
386 | static const char CommandString4[] = "*&COMMAND*ATS311?"; /* Query poletop list */ | ||
387 | static const char CommandString5[] = "*&COMMAND*AT~LA"; /* Query portables list */ | ||
388 | typedef struct { | ||
389 | const char *string; | ||
390 | long length; | ||
391 | } StringDescriptor; | ||
392 | |||
393 | static const StringDescriptor CommandString[] = { | ||
394 | {CommandString0, sizeof(CommandString0) - 1}, | ||
395 | {CommandString1, sizeof(CommandString1) - 1}, | ||
396 | {CommandString2, sizeof(CommandString2) - 1}, | ||
397 | {CommandString3, sizeof(CommandString3) - 1}, | ||
398 | {CommandString4, sizeof(CommandString4) - 1}, | ||
399 | {CommandString5, sizeof(CommandString5) - 1} | ||
400 | }; | ||
401 | |||
402 | #define GOT_ALL_RADIO_INFO(S) \ | ||
403 | ((S)->firmware_version.c[0] && \ | ||
404 | (S)->battery_voltage.c[0] && \ | ||
405 | memcmp(&(S)->true_dev_addr, zero_address.c, sizeof(zero_address))) | ||
406 | |||
407 | static const char hextable[16] = "0123456789ABCDEF"; | ||
408 | |||
409 | static const MetricomAddress zero_address; | ||
410 | static const MetricomAddress broadcast_address = | ||
411 | { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} }; | ||
412 | |||
413 | static const MetricomKey SIP0Key = { "SIP0" }; | ||
414 | static const MetricomKey ARP0Key = { "ARP0" }; | ||
415 | static const MetricomKey ATR_Key = { "ATR " }; | ||
416 | static const MetricomKey ACK_Key = { "ACK_" }; | ||
417 | static const MetricomKey INF_Key = { "INF_" }; | ||
418 | static const MetricomKey ERR_Key = { "ERR_" }; | ||
419 | |||
420 | static const long MaxARPInterval = 60 * HZ; /* One minute */ | ||
421 | |||
422 | /* | ||
423 | * Maximum Starmode packet length is 1183 bytes. Allowing 4 bytes for | ||
424 | * protocol key, 4 bytes for checksum, one byte for CR, and 65/64 expansion | ||
425 | * for STRIP encoding, that translates to a maximum payload MTU of 1155. | ||
426 | * Note: A standard NFS 1K data packet is a total of 0x480 (1152) bytes | ||
427 | * long, including IP header, UDP header, and NFS header. Setting the STRIP | ||
428 | * MTU to 1152 allows us to send default sized NFS packets without fragmentation. | ||
429 | */ | ||
430 | static const unsigned short MAX_SEND_MTU = 1152; | ||
431 | static const unsigned short MAX_RECV_MTU = 1500; /* Hoping for Ethernet sized packets in the future! */ | ||
432 | static const unsigned short DEFAULT_STRIP_MTU = 1152; | ||
433 | static const int STRIP_MAGIC = 0x5303; | ||
434 | static const long LongTime = 0x7FFFFFFF; | ||
435 | |||
436 | /************************************************************************/ | ||
437 | /* Global variables */ | ||
438 | |||
439 | static LIST_HEAD(strip_list); | ||
440 | static DEFINE_SPINLOCK(strip_lock); | ||
441 | |||
442 | /************************************************************************/ | ||
443 | /* Macros */ | ||
444 | |||
445 | /* Returns TRUE if text T begins with prefix P */ | ||
446 | #define has_prefix(T,L,P) (((L) >= sizeof(P)-1) && !strncmp((T), (P), sizeof(P)-1)) | ||
447 | |||
448 | /* Returns TRUE if text T of length L is equal to string S */ | ||
449 | #define text_equal(T,L,S) (((L) == sizeof(S)-1) && !strncmp((T), (S), sizeof(S)-1)) | ||
450 | |||
451 | #define READHEX(X) ((X)>='0' && (X)<='9' ? (X)-'0' : \ | ||
452 | (X)>='a' && (X)<='f' ? (X)-'a'+10 : \ | ||
453 | (X)>='A' && (X)<='F' ? (X)-'A'+10 : 0 ) | ||
454 | |||
455 | #define READHEX16(X) ((__u16)(READHEX(X))) | ||
456 | |||
457 | #define READDEC(X) ((X)>='0' && (X)<='9' ? (X)-'0' : 0) | ||
458 | |||
459 | #define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)])) | ||
460 | |||
461 | #define JIFFIE_TO_SEC(X) ((X) / HZ) | ||
462 | |||
463 | |||
464 | /************************************************************************/ | ||
465 | /* Utility routines */ | ||
466 | |||
467 | static int arp_query(unsigned char *haddr, u32 paddr, | ||
468 | struct net_device *dev) | ||
469 | { | ||
470 | struct neighbour *neighbor_entry; | ||
471 | int ret = 0; | ||
472 | |||
473 | neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev); | ||
474 | |||
475 | if (neighbor_entry != NULL) { | ||
476 | neighbor_entry->used = jiffies; | ||
477 | if (neighbor_entry->nud_state & NUD_VALID) { | ||
478 | memcpy(haddr, neighbor_entry->ha, dev->addr_len); | ||
479 | ret = 1; | ||
480 | } | ||
481 | neigh_release(neighbor_entry); | ||
482 | } | ||
483 | return ret; | ||
484 | } | ||
485 | |||
486 | static void DumpData(char *msg, struct strip *strip_info, __u8 * ptr, | ||
487 | __u8 * end) | ||
488 | { | ||
489 | static const int MAX_DumpData = 80; | ||
490 | __u8 pkt_text[MAX_DumpData], *p = pkt_text; | ||
491 | |||
492 | *p++ = '\"'; | ||
493 | |||
494 | while (ptr < end && p < &pkt_text[MAX_DumpData - 4]) { | ||
495 | if (*ptr == '\\') { | ||
496 | *p++ = '\\'; | ||
497 | *p++ = '\\'; | ||
498 | } else { | ||
499 | if (*ptr >= 32 && *ptr <= 126) { | ||
500 | *p++ = *ptr; | ||
501 | } else { | ||
502 | sprintf(p, "\\%02X", *ptr); | ||
503 | p += 3; | ||
504 | } | ||
505 | } | ||
506 | ptr++; | ||
507 | } | ||
508 | |||
509 | if (ptr == end) | ||
510 | *p++ = '\"'; | ||
511 | *p++ = 0; | ||
512 | |||
513 | printk(KERN_INFO "%s: %-13s%s\n", strip_info->dev->name, msg, pkt_text); | ||
514 | } | ||
515 | |||
516 | |||
517 | /************************************************************************/ | ||
518 | /* Byte stuffing/unstuffing routines */ | ||
519 | |||
520 | /* Stuffing scheme: | ||
521 | * 00 Unused (reserved character) | ||
522 | * 01-3F Run of 2-64 different characters | ||
523 | * 40-7F Run of 1-64 different characters plus a single zero at the end | ||
524 | * 80-BF Run of 1-64 of the same character | ||
525 | * C0-FF Run of 1-64 zeroes (ASCII 0) | ||
526 | */ | ||
527 | |||
528 | typedef enum { | ||
529 | Stuff_Diff = 0x00, | ||
530 | Stuff_DiffZero = 0x40, | ||
531 | Stuff_Same = 0x80, | ||
532 | Stuff_Zero = 0xC0, | ||
533 | Stuff_NoCode = 0xFF, /* Special code, meaning no code selected */ | ||
534 | |||
535 | Stuff_CodeMask = 0xC0, | ||
536 | Stuff_CountMask = 0x3F, | ||
537 | Stuff_MaxCount = 0x3F, | ||
538 | Stuff_Magic = 0x0D /* The value we are eliminating */ | ||
539 | } StuffingCode; | ||
540 | |||
541 | /* StuffData encodes the data starting at "src" for "length" bytes. | ||
542 | * It writes it to the buffer pointed to by "dst" (which must be at least | ||
543 | * as long as 1 + 65/64 of the input length). The output may be up to 1.6% | ||
544 | * larger than the input for pathological input, but will usually be smaller. | ||
545 | * StuffData returns the new value of the dst pointer as its result. | ||
546 | * "code_ptr_ptr" points to a "__u8 *" which is used to hold encoding state | ||
547 | * between calls, allowing an encoded packet to be incrementally built up | ||
548 | * from small parts. On the first call, the "__u8 *" pointed to should be | ||
549 | * initialized to NULL; between subsequent calls the calling routine should | ||
550 | * leave the value alone and simply pass it back unchanged so that the | ||
551 | * encoder can recover its current state. | ||
552 | */ | ||
553 | |||
554 | #define StuffData_FinishBlock(X) \ | ||
555 | (*code_ptr = (X) ^ Stuff_Magic, code = Stuff_NoCode) | ||
556 | |||
557 | static __u8 *StuffData(__u8 * src, __u32 length, __u8 * dst, | ||
558 | __u8 ** code_ptr_ptr) | ||
559 | { | ||
560 | __u8 *end = src + length; | ||
561 | __u8 *code_ptr = *code_ptr_ptr; | ||
562 | __u8 code = Stuff_NoCode, count = 0; | ||
563 | |||
564 | if (!length) | ||
565 | return (dst); | ||
566 | |||
567 | if (code_ptr) { | ||
568 | /* | ||
569 | * Recover state from last call, if applicable | ||
570 | */ | ||
571 | code = (*code_ptr ^ Stuff_Magic) & Stuff_CodeMask; | ||
572 | count = (*code_ptr ^ Stuff_Magic) & Stuff_CountMask; | ||
573 | } | ||
574 | |||
575 | while (src < end) { | ||
576 | switch (code) { | ||
577 | /* Stuff_NoCode: If no current code, select one */ | ||
578 | case Stuff_NoCode: | ||
579 | /* Record where we're going to put this code */ | ||
580 | code_ptr = dst++; | ||
581 | count = 0; /* Reset the count (zero means one instance) */ | ||
582 | /* Tentatively start a new block */ | ||
583 | if (*src == 0) { | ||
584 | code = Stuff_Zero; | ||
585 | src++; | ||
586 | } else { | ||
587 | code = Stuff_Same; | ||
588 | *dst++ = *src++ ^ Stuff_Magic; | ||
589 | } | ||
590 | /* Note: We optimistically assume run of same -- */ | ||
591 | /* which will be fixed later in Stuff_Same */ | ||
592 | /* if it turns out not to be true. */ | ||
593 | break; | ||
594 | |||
595 | /* Stuff_Zero: We already have at least one zero encoded */ | ||
596 | case Stuff_Zero: | ||
597 | /* If another zero, count it, else finish this code block */ | ||
598 | if (*src == 0) { | ||
599 | count++; | ||
600 | src++; | ||
601 | } else { | ||
602 | StuffData_FinishBlock(Stuff_Zero + count); | ||
603 | } | ||
604 | break; | ||
605 | |||
606 | /* Stuff_Same: We already have at least one byte encoded */ | ||
607 | case Stuff_Same: | ||
608 | /* If another one the same, count it */ | ||
609 | if ((*src ^ Stuff_Magic) == code_ptr[1]) { | ||
610 | count++; | ||
611 | src++; | ||
612 | break; | ||
613 | } | ||
614 | /* else, this byte does not match this block. */ | ||
615 | /* If we already have two or more bytes encoded, finish this code block */ | ||
616 | if (count) { | ||
617 | StuffData_FinishBlock(Stuff_Same + count); | ||
618 | break; | ||
619 | } | ||
620 | /* else, we only have one so far, so switch to Stuff_Diff code */ | ||
621 | code = Stuff_Diff; | ||
622 | /* and fall through to Stuff_Diff case below | ||
623 | * Note cunning cleverness here: case Stuff_Diff compares | ||
624 | * the current character with the previous two to see if it | ||
625 | * has a run of three the same. Won't this be an error if | ||
626 | * there aren't two previous characters stored to compare with? | ||
627 | * No. Because we know the current character is *not* the same | ||
628 | * as the previous one, the first test below will necessarily | ||
629 | * fail and the send half of the "if" won't be executed. | ||
630 | */ | ||
631 | |||
632 | /* Stuff_Diff: We have at least two *different* bytes encoded */ | ||
633 | case Stuff_Diff: | ||
634 | /* If this is a zero, must encode a Stuff_DiffZero, and begin a new block */ | ||
635 | if (*src == 0) { | ||
636 | StuffData_FinishBlock(Stuff_DiffZero + | ||
637 | count); | ||
638 | } | ||
639 | /* else, if we have three in a row, it is worth starting a Stuff_Same block */ | ||
640 | else if ((*src ^ Stuff_Magic) == dst[-1] | ||
641 | && dst[-1] == dst[-2]) { | ||
642 | /* Back off the last two characters we encoded */ | ||
643 | code += count - 2; | ||
644 | /* Note: "Stuff_Diff + 0" is an illegal code */ | ||
645 | if (code == Stuff_Diff + 0) { | ||
646 | code = Stuff_Same + 0; | ||
647 | } | ||
648 | StuffData_FinishBlock(code); | ||
649 | code_ptr = dst - 2; | ||
650 | /* dst[-1] already holds the correct value */ | ||
651 | count = 2; /* 2 means three bytes encoded */ | ||
652 | code = Stuff_Same; | ||
653 | } | ||
654 | /* else, another different byte, so add it to the block */ | ||
655 | else { | ||
656 | *dst++ = *src ^ Stuff_Magic; | ||
657 | count++; | ||
658 | } | ||
659 | src++; /* Consume the byte */ | ||
660 | break; | ||
661 | } | ||
662 | if (count == Stuff_MaxCount) { | ||
663 | StuffData_FinishBlock(code + count); | ||
664 | } | ||
665 | } | ||
666 | if (code == Stuff_NoCode) { | ||
667 | *code_ptr_ptr = NULL; | ||
668 | } else { | ||
669 | *code_ptr_ptr = code_ptr; | ||
670 | StuffData_FinishBlock(code + count); | ||
671 | } | ||
672 | return (dst); | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * UnStuffData decodes the data at "src", up to (but not including) "end". | ||
677 | * It writes the decoded data into the buffer pointed to by "dst", up to a | ||
678 | * maximum of "dst_length", and returns the new value of "src" so that a | ||
679 | * follow-on call can read more data, continuing from where the first left off. | ||
680 | * | ||
681 | * There are three types of results: | ||
682 | * 1. The source data runs out before extracting "dst_length" bytes: | ||
683 | * UnStuffData returns NULL to indicate failure. | ||
684 | * 2. The source data produces exactly "dst_length" bytes: | ||
685 | * UnStuffData returns new_src = end to indicate that all bytes were consumed. | ||
686 | * 3. "dst_length" bytes are extracted, with more remaining. | ||
687 | * UnStuffData returns new_src < end to indicate that there are more bytes | ||
688 | * to be read. | ||
689 | * | ||
690 | * Note: The decoding may be destructive, in that it may alter the source | ||
691 | * data in the process of decoding it (this is necessary to allow a follow-on | ||
692 | * call to resume correctly). | ||
693 | */ | ||
694 | |||
695 | static __u8 *UnStuffData(__u8 * src, __u8 * end, __u8 * dst, | ||
696 | __u32 dst_length) | ||
697 | { | ||
698 | __u8 *dst_end = dst + dst_length; | ||
699 | /* Sanity check */ | ||
700 | if (!src || !end || !dst || !dst_length) | ||
701 | return (NULL); | ||
702 | while (src < end && dst < dst_end) { | ||
703 | int count = (*src ^ Stuff_Magic) & Stuff_CountMask; | ||
704 | switch ((*src ^ Stuff_Magic) & Stuff_CodeMask) { | ||
705 | case Stuff_Diff: | ||
706 | if (src + 1 + count >= end) | ||
707 | return (NULL); | ||
708 | do { | ||
709 | *dst++ = *++src ^ Stuff_Magic; | ||
710 | } | ||
711 | while (--count >= 0 && dst < dst_end); | ||
712 | if (count < 0) | ||
713 | src += 1; | ||
714 | else { | ||
715 | if (count == 0) | ||
716 | *src = Stuff_Same ^ Stuff_Magic; | ||
717 | else | ||
718 | *src = | ||
719 | (Stuff_Diff + | ||
720 | count) ^ Stuff_Magic; | ||
721 | } | ||
722 | break; | ||
723 | case Stuff_DiffZero: | ||
724 | if (src + 1 + count >= end) | ||
725 | return (NULL); | ||
726 | do { | ||
727 | *dst++ = *++src ^ Stuff_Magic; | ||
728 | } | ||
729 | while (--count >= 0 && dst < dst_end); | ||
730 | if (count < 0) | ||
731 | *src = Stuff_Zero ^ Stuff_Magic; | ||
732 | else | ||
733 | *src = | ||
734 | (Stuff_DiffZero + count) ^ Stuff_Magic; | ||
735 | break; | ||
736 | case Stuff_Same: | ||
737 | if (src + 1 >= end) | ||
738 | return (NULL); | ||
739 | do { | ||
740 | *dst++ = src[1] ^ Stuff_Magic; | ||
741 | } | ||
742 | while (--count >= 0 && dst < dst_end); | ||
743 | if (count < 0) | ||
744 | src += 2; | ||
745 | else | ||
746 | *src = (Stuff_Same + count) ^ Stuff_Magic; | ||
747 | break; | ||
748 | case Stuff_Zero: | ||
749 | do { | ||
750 | *dst++ = 0; | ||
751 | } | ||
752 | while (--count >= 0 && dst < dst_end); | ||
753 | if (count < 0) | ||
754 | src += 1; | ||
755 | else | ||
756 | *src = (Stuff_Zero + count) ^ Stuff_Magic; | ||
757 | break; | ||
758 | } | ||
759 | } | ||
760 | if (dst < dst_end) | ||
761 | return (NULL); | ||
762 | else | ||
763 | return (src); | ||
764 | } | ||
765 | |||
766 | |||
767 | /************************************************************************/ | ||
768 | /* General routines for STRIP */ | ||
769 | |||
770 | /* | ||
771 | * set_baud sets the baud rate to the rate defined by baudcode | ||
772 | */ | ||
773 | static void set_baud(struct tty_struct *tty, speed_t baudrate) | ||
774 | { | ||
775 | struct ktermios old_termios; | ||
776 | |||
777 | mutex_lock(&tty->termios_mutex); | ||
778 | old_termios =*(tty->termios); | ||
779 | tty_encode_baud_rate(tty, baudrate, baudrate); | ||
780 | tty->ops->set_termios(tty, &old_termios); | ||
781 | mutex_unlock(&tty->termios_mutex); | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * Convert a string to a Metricom Address. | ||
786 | */ | ||
787 | |||
788 | #define IS_RADIO_ADDRESS(p) ( \ | ||
789 | isdigit((p)[0]) && isdigit((p)[1]) && isdigit((p)[2]) && isdigit((p)[3]) && \ | ||
790 | (p)[4] == '-' && \ | ||
791 | isdigit((p)[5]) && isdigit((p)[6]) && isdigit((p)[7]) && isdigit((p)[8]) ) | ||
792 | |||
793 | static int string_to_radio_address(MetricomAddress * addr, __u8 * p) | ||
794 | { | ||
795 | if (!IS_RADIO_ADDRESS(p)) | ||
796 | return (1); | ||
797 | addr->c[0] = 0; | ||
798 | addr->c[1] = 0; | ||
799 | addr->c[2] = READHEX(p[0]) << 4 | READHEX(p[1]); | ||
800 | addr->c[3] = READHEX(p[2]) << 4 | READHEX(p[3]); | ||
801 | addr->c[4] = READHEX(p[5]) << 4 | READHEX(p[6]); | ||
802 | addr->c[5] = READHEX(p[7]) << 4 | READHEX(p[8]); | ||
803 | return (0); | ||
804 | } | ||
805 | |||
806 | /* | ||
807 | * Convert a Metricom Address to a string. | ||
808 | */ | ||
809 | |||
810 | static __u8 *radio_address_to_string(const MetricomAddress * addr, | ||
811 | MetricomAddressString * p) | ||
812 | { | ||
813 | sprintf(p->c, "%02X%02X-%02X%02X", addr->c[2], addr->c[3], | ||
814 | addr->c[4], addr->c[5]); | ||
815 | return (p->c); | ||
816 | } | ||
817 | |||
818 | /* | ||
819 | * Note: Must make sure sx_size is big enough to receive a stuffed | ||
820 | * MAX_RECV_MTU packet. Additionally, we also want to ensure that it's | ||
821 | * big enough to receive a large radio neighbour list (currently 4K). | ||
822 | */ | ||
823 | |||
824 | static int allocate_buffers(struct strip *strip_info, int mtu) | ||
825 | { | ||
826 | struct net_device *dev = strip_info->dev; | ||
827 | int sx_size = max_t(int, STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096); | ||
828 | int tx_size = STRIP_ENCAP_SIZE(mtu) + MaxCommandStringLength; | ||
829 | __u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC); | ||
830 | __u8 *s = kmalloc(sx_size, GFP_ATOMIC); | ||
831 | __u8 *t = kmalloc(tx_size, GFP_ATOMIC); | ||
832 | if (r && s && t) { | ||
833 | strip_info->rx_buff = r; | ||
834 | strip_info->sx_buff = s; | ||
835 | strip_info->tx_buff = t; | ||
836 | strip_info->sx_size = sx_size; | ||
837 | strip_info->tx_size = tx_size; | ||
838 | strip_info->mtu = dev->mtu = mtu; | ||
839 | return (1); | ||
840 | } | ||
841 | kfree(r); | ||
842 | kfree(s); | ||
843 | kfree(t); | ||
844 | return (0); | ||
845 | } | ||
846 | |||
847 | /* | ||
848 | * MTU has been changed by the IP layer. | ||
849 | * We could be in | ||
850 | * an upcall from the tty driver, or in an ip packet queue. | ||
851 | */ | ||
852 | static int strip_change_mtu(struct net_device *dev, int new_mtu) | ||
853 | { | ||
854 | struct strip *strip_info = netdev_priv(dev); | ||
855 | int old_mtu = strip_info->mtu; | ||
856 | unsigned char *orbuff = strip_info->rx_buff; | ||
857 | unsigned char *osbuff = strip_info->sx_buff; | ||
858 | unsigned char *otbuff = strip_info->tx_buff; | ||
859 | |||
860 | if (new_mtu > MAX_SEND_MTU) { | ||
861 | printk(KERN_ERR | ||
862 | "%s: MTU exceeds maximum allowable (%d), MTU change cancelled.\n", | ||
863 | strip_info->dev->name, MAX_SEND_MTU); | ||
864 | return -EINVAL; | ||
865 | } | ||
866 | |||
867 | spin_lock_bh(&strip_lock); | ||
868 | if (!allocate_buffers(strip_info, new_mtu)) { | ||
869 | printk(KERN_ERR "%s: unable to grow strip buffers, MTU change cancelled.\n", | ||
870 | strip_info->dev->name); | ||
871 | spin_unlock_bh(&strip_lock); | ||
872 | return -ENOMEM; | ||
873 | } | ||
874 | |||
875 | if (strip_info->sx_count) { | ||
876 | if (strip_info->sx_count <= strip_info->sx_size) | ||
877 | memcpy(strip_info->sx_buff, osbuff, | ||
878 | strip_info->sx_count); | ||
879 | else { | ||
880 | strip_info->discard = strip_info->sx_count; | ||
881 | strip_info->rx_over_errors++; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | if (strip_info->tx_left) { | ||
886 | if (strip_info->tx_left <= strip_info->tx_size) | ||
887 | memcpy(strip_info->tx_buff, strip_info->tx_head, | ||
888 | strip_info->tx_left); | ||
889 | else { | ||
890 | strip_info->tx_left = 0; | ||
891 | strip_info->tx_dropped++; | ||
892 | } | ||
893 | } | ||
894 | strip_info->tx_head = strip_info->tx_buff; | ||
895 | spin_unlock_bh(&strip_lock); | ||
896 | |||
897 | printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n", | ||
898 | strip_info->dev->name, old_mtu, strip_info->mtu); | ||
899 | |||
900 | kfree(orbuff); | ||
901 | kfree(osbuff); | ||
902 | kfree(otbuff); | ||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | static void strip_unlock(struct strip *strip_info) | ||
907 | { | ||
908 | /* | ||
909 | * Set the timer to go off in one second. | ||
910 | */ | ||
911 | strip_info->idle_timer.expires = jiffies + 1 * HZ; | ||
912 | add_timer(&strip_info->idle_timer); | ||
913 | netif_wake_queue(strip_info->dev); | ||
914 | } | ||
915 | |||
916 | |||
917 | |||
918 | /* | ||
919 | * If the time is in the near future, time_delta prints the number of | ||
920 | * seconds to go into the buffer and returns the address of the buffer. | ||
921 | * If the time is not in the near future, it returns the address of the | ||
922 | * string "Not scheduled" The buffer must be long enough to contain the | ||
923 | * ascii representation of the number plus 9 charactes for the " seconds" | ||
924 | * and the null character. | ||
925 | */ | ||
926 | #ifdef CONFIG_PROC_FS | ||
927 | static char *time_delta(char buffer[], long time) | ||
928 | { | ||
929 | time -= jiffies; | ||
930 | if (time > LongTime / 2) | ||
931 | return ("Not scheduled"); | ||
932 | if (time < 0) | ||
933 | time = 0; /* Don't print negative times */ | ||
934 | sprintf(buffer, "%ld seconds", time / HZ); | ||
935 | return (buffer); | ||
936 | } | ||
937 | |||
938 | /* get Nth element of the linked list */ | ||
939 | static struct strip *strip_get_idx(loff_t pos) | ||
940 | { | ||
941 | struct strip *str; | ||
942 | int i = 0; | ||
943 | |||
944 | list_for_each_entry_rcu(str, &strip_list, list) { | ||
945 | if (pos == i) | ||
946 | return str; | ||
947 | ++i; | ||
948 | } | ||
949 | return NULL; | ||
950 | } | ||
951 | |||
952 | static void *strip_seq_start(struct seq_file *seq, loff_t *pos) | ||
953 | { | ||
954 | rcu_read_lock(); | ||
955 | return *pos ? strip_get_idx(*pos - 1) : SEQ_START_TOKEN; | ||
956 | } | ||
957 | |||
958 | static void *strip_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
959 | { | ||
960 | struct list_head *l; | ||
961 | struct strip *s; | ||
962 | |||
963 | ++*pos; | ||
964 | if (v == SEQ_START_TOKEN) | ||
965 | return strip_get_idx(1); | ||
966 | |||
967 | s = v; | ||
968 | l = &s->list; | ||
969 | list_for_each_continue_rcu(l, &strip_list) { | ||
970 | return list_entry(l, struct strip, list); | ||
971 | } | ||
972 | return NULL; | ||
973 | } | ||
974 | |||
975 | static void strip_seq_stop(struct seq_file *seq, void *v) | ||
976 | { | ||
977 | rcu_read_unlock(); | ||
978 | } | ||
979 | |||
980 | static void strip_seq_neighbours(struct seq_file *seq, | ||
981 | const MetricomNodeTable * table, | ||
982 | const char *title) | ||
983 | { | ||
984 | /* We wrap this in a do/while loop, so if the table changes */ | ||
985 | /* while we're reading it, we just go around and try again. */ | ||
986 | struct timeval t; | ||
987 | |||
988 | do { | ||
989 | int i; | ||
990 | t = table->timestamp; | ||
991 | if (table->num_nodes) | ||
992 | seq_printf(seq, "\n %s\n", title); | ||
993 | for (i = 0; i < table->num_nodes; i++) { | ||
994 | MetricomNode node; | ||
995 | |||
996 | spin_lock_bh(&strip_lock); | ||
997 | node = table->node[i]; | ||
998 | spin_unlock_bh(&strip_lock); | ||
999 | seq_printf(seq, " %s\n", node.c); | ||
1000 | } | ||
1001 | } while (table->timestamp.tv_sec != t.tv_sec | ||
1002 | || table->timestamp.tv_usec != t.tv_usec); | ||
1003 | } | ||
1004 | |||
1005 | /* | ||
1006 | * This function prints radio status information via the seq_file | ||
1007 | * interface. The interface takes care of buffer size and over | ||
1008 | * run issues. | ||
1009 | * | ||
1010 | * The buffer in seq_file is PAGESIZE (4K) | ||
1011 | * so this routine should never print more or it will get truncated. | ||
1012 | * With the maximum of 32 portables and 32 poletops | ||
1013 | * reported, the routine outputs 3107 bytes into the buffer. | ||
1014 | */ | ||
1015 | static void strip_seq_status_info(struct seq_file *seq, | ||
1016 | const struct strip *strip_info) | ||
1017 | { | ||
1018 | char temp[32]; | ||
1019 | MetricomAddressString addr_string; | ||
1020 | |||
1021 | /* First, we must copy all of our data to a safe place, */ | ||
1022 | /* in case a serial interrupt comes in and changes it. */ | ||
1023 | int tx_left = strip_info->tx_left; | ||
1024 | unsigned long rx_average_pps = strip_info->rx_average_pps; | ||
1025 | unsigned long tx_average_pps = strip_info->tx_average_pps; | ||
1026 | unsigned long sx_average_pps = strip_info->sx_average_pps; | ||
1027 | int working = strip_info->working; | ||
1028 | int firmware_level = strip_info->firmware_level; | ||
1029 | long watchdog_doprobe = strip_info->watchdog_doprobe; | ||
1030 | long watchdog_doreset = strip_info->watchdog_doreset; | ||
1031 | long gratuitous_arp = strip_info->gratuitous_arp; | ||
1032 | long arp_interval = strip_info->arp_interval; | ||
1033 | FirmwareVersion firmware_version = strip_info->firmware_version; | ||
1034 | SerialNumber serial_number = strip_info->serial_number; | ||
1035 | BatteryVoltage battery_voltage = strip_info->battery_voltage; | ||
1036 | char *if_name = strip_info->dev->name; | ||
1037 | MetricomAddress true_dev_addr = strip_info->true_dev_addr; | ||
1038 | MetricomAddress dev_dev_addr = | ||
1039 | *(MetricomAddress *) strip_info->dev->dev_addr; | ||
1040 | int manual_dev_addr = strip_info->manual_dev_addr; | ||
1041 | #ifdef EXT_COUNTERS | ||
1042 | unsigned long rx_bytes = strip_info->rx_bytes; | ||
1043 | unsigned long tx_bytes = strip_info->tx_bytes; | ||
1044 | unsigned long rx_rbytes = strip_info->rx_rbytes; | ||
1045 | unsigned long tx_rbytes = strip_info->tx_rbytes; | ||
1046 | unsigned long rx_sbytes = strip_info->rx_sbytes; | ||
1047 | unsigned long tx_sbytes = strip_info->tx_sbytes; | ||
1048 | unsigned long rx_ebytes = strip_info->rx_ebytes; | ||
1049 | unsigned long tx_ebytes = strip_info->tx_ebytes; | ||
1050 | #endif | ||
1051 | |||
1052 | seq_printf(seq, "\nInterface name\t\t%s\n", if_name); | ||
1053 | seq_printf(seq, " Radio working:\t\t%s\n", working ? "Yes" : "No"); | ||
1054 | radio_address_to_string(&true_dev_addr, &addr_string); | ||
1055 | seq_printf(seq, " Radio address:\t\t%s\n", addr_string.c); | ||
1056 | if (manual_dev_addr) { | ||
1057 | radio_address_to_string(&dev_dev_addr, &addr_string); | ||
1058 | seq_printf(seq, " Device address:\t%s\n", addr_string.c); | ||
1059 | } | ||
1060 | seq_printf(seq, " Firmware version:\t%s", !working ? "Unknown" : | ||
1061 | !firmware_level ? "Should be upgraded" : | ||
1062 | firmware_version.c); | ||
1063 | if (firmware_level >= ChecksummedMessages) | ||
1064 | seq_printf(seq, " (Checksums Enabled)"); | ||
1065 | seq_printf(seq, "\n"); | ||
1066 | seq_printf(seq, " Serial number:\t\t%s\n", serial_number.c); | ||
1067 | seq_printf(seq, " Battery voltage:\t%s\n", battery_voltage.c); | ||
1068 | seq_printf(seq, " Transmit queue (bytes):%d\n", tx_left); | ||
1069 | seq_printf(seq, " Receive packet rate: %ld packets per second\n", | ||
1070 | rx_average_pps / 8); | ||
1071 | seq_printf(seq, " Transmit packet rate: %ld packets per second\n", | ||
1072 | tx_average_pps / 8); | ||
1073 | seq_printf(seq, " Sent packet rate: %ld packets per second\n", | ||
1074 | sx_average_pps / 8); | ||
1075 | seq_printf(seq, " Next watchdog probe:\t%s\n", | ||
1076 | time_delta(temp, watchdog_doprobe)); | ||
1077 | seq_printf(seq, " Next watchdog reset:\t%s\n", | ||
1078 | time_delta(temp, watchdog_doreset)); | ||
1079 | seq_printf(seq, " Next gratuitous ARP:\t"); | ||
1080 | |||
1081 | if (!memcmp | ||
1082 | (strip_info->dev->dev_addr, zero_address.c, | ||
1083 | sizeof(zero_address))) | ||
1084 | seq_printf(seq, "Disabled\n"); | ||
1085 | else { | ||
1086 | seq_printf(seq, "%s\n", time_delta(temp, gratuitous_arp)); | ||
1087 | seq_printf(seq, " Next ARP interval:\t%ld seconds\n", | ||
1088 | JIFFIE_TO_SEC(arp_interval)); | ||
1089 | } | ||
1090 | |||
1091 | if (working) { | ||
1092 | #ifdef EXT_COUNTERS | ||
1093 | seq_printf(seq, "\n"); | ||
1094 | seq_printf(seq, | ||
1095 | " Total bytes: \trx:\t%lu\ttx:\t%lu\n", | ||
1096 | rx_bytes, tx_bytes); | ||
1097 | seq_printf(seq, | ||
1098 | " thru radio: \trx:\t%lu\ttx:\t%lu\n", | ||
1099 | rx_rbytes, tx_rbytes); | ||
1100 | seq_printf(seq, | ||
1101 | " thru serial port: \trx:\t%lu\ttx:\t%lu\n", | ||
1102 | rx_sbytes, tx_sbytes); | ||
1103 | seq_printf(seq, | ||
1104 | " Total stat/err bytes:\trx:\t%lu\ttx:\t%lu\n", | ||
1105 | rx_ebytes, tx_ebytes); | ||
1106 | #endif | ||
1107 | strip_seq_neighbours(seq, &strip_info->poletops, | ||
1108 | "Poletops:"); | ||
1109 | strip_seq_neighbours(seq, &strip_info->portables, | ||
1110 | "Portables:"); | ||
1111 | } | ||
1112 | } | ||
1113 | |||
1114 | /* | ||
1115 | * This function is exports status information from the STRIP driver through | ||
1116 | * the /proc file system. | ||
1117 | */ | ||
1118 | static int strip_seq_show(struct seq_file *seq, void *v) | ||
1119 | { | ||
1120 | if (v == SEQ_START_TOKEN) | ||
1121 | seq_printf(seq, "strip_version: %s\n", StripVersion); | ||
1122 | else | ||
1123 | strip_seq_status_info(seq, (const struct strip *)v); | ||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | static struct seq_operations strip_seq_ops = { | ||
1129 | .start = strip_seq_start, | ||
1130 | .next = strip_seq_next, | ||
1131 | .stop = strip_seq_stop, | ||
1132 | .show = strip_seq_show, | ||
1133 | }; | ||
1134 | |||
1135 | static int strip_seq_open(struct inode *inode, struct file *file) | ||
1136 | { | ||
1137 | return seq_open(file, &strip_seq_ops); | ||
1138 | } | ||
1139 | |||
1140 | static const struct file_operations strip_seq_fops = { | ||
1141 | .owner = THIS_MODULE, | ||
1142 | .open = strip_seq_open, | ||
1143 | .read = seq_read, | ||
1144 | .llseek = seq_lseek, | ||
1145 | .release = seq_release, | ||
1146 | }; | ||
1147 | #endif | ||
1148 | |||
1149 | |||
1150 | |||
1151 | /************************************************************************/ | ||
1152 | /* Sending routines */ | ||
1153 | |||
1154 | static void ResetRadio(struct strip *strip_info) | ||
1155 | { | ||
1156 | struct tty_struct *tty = strip_info->tty; | ||
1157 | static const char init[] = "ate0q1dt**starmode\r**"; | ||
1158 | StringDescriptor s = { init, sizeof(init) - 1 }; | ||
1159 | |||
1160 | /* | ||
1161 | * If the radio isn't working anymore, | ||
1162 | * we should clear the old status information. | ||
1163 | */ | ||
1164 | if (strip_info->working) { | ||
1165 | printk(KERN_INFO "%s: No response: Resetting radio.\n", | ||
1166 | strip_info->dev->name); | ||
1167 | strip_info->firmware_version.c[0] = '\0'; | ||
1168 | strip_info->serial_number.c[0] = '\0'; | ||
1169 | strip_info->battery_voltage.c[0] = '\0'; | ||
1170 | strip_info->portables.num_nodes = 0; | ||
1171 | do_gettimeofday(&strip_info->portables.timestamp); | ||
1172 | strip_info->poletops.num_nodes = 0; | ||
1173 | do_gettimeofday(&strip_info->poletops.timestamp); | ||
1174 | } | ||
1175 | |||
1176 | strip_info->pps_timer = jiffies; | ||
1177 | strip_info->rx_pps_count = 0; | ||
1178 | strip_info->tx_pps_count = 0; | ||
1179 | strip_info->sx_pps_count = 0; | ||
1180 | strip_info->rx_average_pps = 0; | ||
1181 | strip_info->tx_average_pps = 0; | ||
1182 | strip_info->sx_average_pps = 0; | ||
1183 | |||
1184 | /* Mark radio address as unknown */ | ||
1185 | *(MetricomAddress *) & strip_info->true_dev_addr = zero_address; | ||
1186 | if (!strip_info->manual_dev_addr) | ||
1187 | *(MetricomAddress *) strip_info->dev->dev_addr = | ||
1188 | zero_address; | ||
1189 | strip_info->working = FALSE; | ||
1190 | strip_info->firmware_level = NoStructure; | ||
1191 | strip_info->next_command = CompatibilityCommand; | ||
1192 | strip_info->watchdog_doprobe = jiffies + 10 * HZ; | ||
1193 | strip_info->watchdog_doreset = jiffies + 1 * HZ; | ||
1194 | |||
1195 | /* If the user has selected a baud rate above 38.4 see what magic we have to do */ | ||
1196 | if (strip_info->user_baud > 38400) { | ||
1197 | /* | ||
1198 | * Subtle stuff: Pay attention :-) | ||
1199 | * If the serial port is currently at the user's selected (>38.4) rate, | ||
1200 | * then we temporarily switch to 19.2 and issue the ATS304 command | ||
1201 | * to tell the radio to switch to the user's selected rate. | ||
1202 | * If the serial port is not currently at that rate, that means we just | ||
1203 | * issued the ATS304 command last time through, so this time we restore | ||
1204 | * the user's selected rate and issue the normal starmode reset string. | ||
1205 | */ | ||
1206 | if (strip_info->user_baud == tty_get_baud_rate(tty)) { | ||
1207 | static const char b0[] = "ate0q1s304=57600\r"; | ||
1208 | static const char b1[] = "ate0q1s304=115200\r"; | ||
1209 | static const StringDescriptor baudstring[2] = | ||
1210 | { {b0, sizeof(b0) - 1} | ||
1211 | , {b1, sizeof(b1) - 1} | ||
1212 | }; | ||
1213 | set_baud(tty, 19200); | ||
1214 | if (strip_info->user_baud == 57600) | ||
1215 | s = baudstring[0]; | ||
1216 | else if (strip_info->user_baud == 115200) | ||
1217 | s = baudstring[1]; | ||
1218 | else | ||
1219 | s = baudstring[1]; /* For now */ | ||
1220 | } else | ||
1221 | set_baud(tty, strip_info->user_baud); | ||
1222 | } | ||
1223 | |||
1224 | tty->ops->write(tty, s.string, s.length); | ||
1225 | #ifdef EXT_COUNTERS | ||
1226 | strip_info->tx_ebytes += s.length; | ||
1227 | #endif | ||
1228 | } | ||
1229 | |||
1230 | /* | ||
1231 | * Called by the driver when there's room for more data. If we have | ||
1232 | * more packets to send, we send them here. | ||
1233 | */ | ||
1234 | |||
1235 | static void strip_write_some_more(struct tty_struct *tty) | ||
1236 | { | ||
1237 | struct strip *strip_info = (struct strip *) tty->disc_data; | ||
1238 | |||
1239 | /* First make sure we're connected. */ | ||
1240 | if (!strip_info || strip_info->magic != STRIP_MAGIC || | ||
1241 | !netif_running(strip_info->dev)) | ||
1242 | return; | ||
1243 | |||
1244 | if (strip_info->tx_left > 0) { | ||
1245 | int num_written = | ||
1246 | tty->ops->write(tty, strip_info->tx_head, | ||
1247 | strip_info->tx_left); | ||
1248 | strip_info->tx_left -= num_written; | ||
1249 | strip_info->tx_head += num_written; | ||
1250 | #ifdef EXT_COUNTERS | ||
1251 | strip_info->tx_sbytes += num_written; | ||
1252 | #endif | ||
1253 | } else { /* Else start transmission of another packet */ | ||
1254 | |||
1255 | tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); | ||
1256 | strip_unlock(strip_info); | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | static __u8 *add_checksum(__u8 * buffer, __u8 * end) | ||
1261 | { | ||
1262 | __u16 sum = 0; | ||
1263 | __u8 *p = buffer; | ||
1264 | while (p < end) | ||
1265 | sum += *p++; | ||
1266 | end[3] = hextable[sum & 0xF]; | ||
1267 | sum >>= 4; | ||
1268 | end[2] = hextable[sum & 0xF]; | ||
1269 | sum >>= 4; | ||
1270 | end[1] = hextable[sum & 0xF]; | ||
1271 | sum >>= 4; | ||
1272 | end[0] = hextable[sum & 0xF]; | ||
1273 | return (end + 4); | ||
1274 | } | ||
1275 | |||
1276 | static unsigned char *strip_make_packet(unsigned char *buffer, | ||
1277 | struct strip *strip_info, | ||
1278 | struct sk_buff *skb) | ||
1279 | { | ||
1280 | __u8 *ptr = buffer; | ||
1281 | __u8 *stuffstate = NULL; | ||
1282 | STRIP_Header *header = (STRIP_Header *) skb->data; | ||
1283 | MetricomAddress haddr = header->dst_addr; | ||
1284 | int len = skb->len - sizeof(STRIP_Header); | ||
1285 | MetricomKey key; | ||
1286 | |||
1287 | /*HexDump("strip_make_packet", strip_info, skb->data, skb->data + skb->len); */ | ||
1288 | |||
1289 | if (header->protocol == htons(ETH_P_IP)) | ||
1290 | key = SIP0Key; | ||
1291 | else if (header->protocol == htons(ETH_P_ARP)) | ||
1292 | key = ARP0Key; | ||
1293 | else { | ||
1294 | printk(KERN_ERR | ||
1295 | "%s: strip_make_packet: Unknown packet type 0x%04X\n", | ||
1296 | strip_info->dev->name, ntohs(header->protocol)); | ||
1297 | return (NULL); | ||
1298 | } | ||
1299 | |||
1300 | if (len > strip_info->mtu) { | ||
1301 | printk(KERN_ERR | ||
1302 | "%s: Dropping oversized transmit packet: %d bytes\n", | ||
1303 | strip_info->dev->name, len); | ||
1304 | return (NULL); | ||
1305 | } | ||
1306 | |||
1307 | /* | ||
1308 | * If we're sending to ourselves, discard the packet. | ||
1309 | * (Metricom radios choke if they try to send a packet to their own address.) | ||
1310 | */ | ||
1311 | if (!memcmp(haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) { | ||
1312 | printk(KERN_ERR "%s: Dropping packet addressed to self\n", | ||
1313 | strip_info->dev->name); | ||
1314 | return (NULL); | ||
1315 | } | ||
1316 | |||
1317 | /* | ||
1318 | * If this is a broadcast packet, send it to our designated Metricom | ||
1319 | * 'broadcast hub' radio (First byte of address being 0xFF means broadcast) | ||
1320 | */ | ||
1321 | if (haddr.c[0] == 0xFF) { | ||
1322 | __be32 brd = 0; | ||
1323 | struct in_device *in_dev; | ||
1324 | |||
1325 | rcu_read_lock(); | ||
1326 | in_dev = __in_dev_get_rcu(strip_info->dev); | ||
1327 | if (in_dev == NULL) { | ||
1328 | rcu_read_unlock(); | ||
1329 | return NULL; | ||
1330 | } | ||
1331 | if (in_dev->ifa_list) | ||
1332 | brd = in_dev->ifa_list->ifa_broadcast; | ||
1333 | rcu_read_unlock(); | ||
1334 | |||
1335 | /* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */ | ||
1336 | if (!arp_query(haddr.c, brd, strip_info->dev)) { | ||
1337 | printk(KERN_ERR | ||
1338 | "%s: Unable to send packet (no broadcast hub configured)\n", | ||
1339 | strip_info->dev->name); | ||
1340 | return (NULL); | ||
1341 | } | ||
1342 | /* | ||
1343 | * If we are the broadcast hub, don't bother sending to ourselves. | ||
1344 | * (Metricom radios choke if they try to send a packet to their own address.) | ||
1345 | */ | ||
1346 | if (!memcmp | ||
1347 | (haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) | ||
1348 | return (NULL); | ||
1349 | } | ||
1350 | |||
1351 | *ptr++ = 0x0D; | ||
1352 | *ptr++ = '*'; | ||
1353 | *ptr++ = hextable[haddr.c[2] >> 4]; | ||
1354 | *ptr++ = hextable[haddr.c[2] & 0xF]; | ||
1355 | *ptr++ = hextable[haddr.c[3] >> 4]; | ||
1356 | *ptr++ = hextable[haddr.c[3] & 0xF]; | ||
1357 | *ptr++ = '-'; | ||
1358 | *ptr++ = hextable[haddr.c[4] >> 4]; | ||
1359 | *ptr++ = hextable[haddr.c[4] & 0xF]; | ||
1360 | *ptr++ = hextable[haddr.c[5] >> 4]; | ||
1361 | *ptr++ = hextable[haddr.c[5] & 0xF]; | ||
1362 | *ptr++ = '*'; | ||
1363 | *ptr++ = key.c[0]; | ||
1364 | *ptr++ = key.c[1]; | ||
1365 | *ptr++ = key.c[2]; | ||
1366 | *ptr++ = key.c[3]; | ||
1367 | |||
1368 | ptr = | ||
1369 | StuffData(skb->data + sizeof(STRIP_Header), len, ptr, | ||
1370 | &stuffstate); | ||
1371 | |||
1372 | if (strip_info->firmware_level >= ChecksummedMessages) | ||
1373 | ptr = add_checksum(buffer + 1, ptr); | ||
1374 | |||
1375 | *ptr++ = 0x0D; | ||
1376 | return (ptr); | ||
1377 | } | ||
1378 | |||
1379 | static void strip_send(struct strip *strip_info, struct sk_buff *skb) | ||
1380 | { | ||
1381 | MetricomAddress haddr; | ||
1382 | unsigned char *ptr = strip_info->tx_buff; | ||
1383 | int doreset = (long) jiffies - strip_info->watchdog_doreset >= 0; | ||
1384 | int doprobe = (long) jiffies - strip_info->watchdog_doprobe >= 0 | ||
1385 | && !doreset; | ||
1386 | __be32 addr, brd; | ||
1387 | |||
1388 | /* | ||
1389 | * 1. If we have a packet, encapsulate it and put it in the buffer | ||
1390 | */ | ||
1391 | if (skb) { | ||
1392 | char *newptr = strip_make_packet(ptr, strip_info, skb); | ||
1393 | strip_info->tx_pps_count++; | ||
1394 | if (!newptr) | ||
1395 | strip_info->tx_dropped++; | ||
1396 | else { | ||
1397 | ptr = newptr; | ||
1398 | strip_info->sx_pps_count++; | ||
1399 | strip_info->tx_packets++; /* Count another successful packet */ | ||
1400 | #ifdef EXT_COUNTERS | ||
1401 | strip_info->tx_bytes += skb->len; | ||
1402 | strip_info->tx_rbytes += ptr - strip_info->tx_buff; | ||
1403 | #endif | ||
1404 | /*DumpData("Sending:", strip_info, strip_info->tx_buff, ptr); */ | ||
1405 | /*HexDump("Sending", strip_info, strip_info->tx_buff, ptr); */ | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | /* | ||
1410 | * 2. If it is time for another tickle, tack it on, after the packet | ||
1411 | */ | ||
1412 | if (doprobe) { | ||
1413 | StringDescriptor ts = CommandString[strip_info->next_command]; | ||
1414 | #if TICKLE_TIMERS | ||
1415 | { | ||
1416 | struct timeval tv; | ||
1417 | do_gettimeofday(&tv); | ||
1418 | printk(KERN_INFO "**** Sending tickle string %d at %02d.%06d\n", | ||
1419 | strip_info->next_command, tv.tv_sec % 100, | ||
1420 | tv.tv_usec); | ||
1421 | } | ||
1422 | #endif | ||
1423 | if (ptr == strip_info->tx_buff) | ||
1424 | *ptr++ = 0x0D; | ||
1425 | |||
1426 | *ptr++ = '*'; /* First send "**" to provoke an error message */ | ||
1427 | *ptr++ = '*'; | ||
1428 | |||
1429 | /* Then add the command */ | ||
1430 | memcpy(ptr, ts.string, ts.length); | ||
1431 | |||
1432 | /* Add a checksum ? */ | ||
1433 | if (strip_info->firmware_level < ChecksummedMessages) | ||
1434 | ptr += ts.length; | ||
1435 | else | ||
1436 | ptr = add_checksum(ptr, ptr + ts.length); | ||
1437 | |||
1438 | *ptr++ = 0x0D; /* Terminate the command with a <CR> */ | ||
1439 | |||
1440 | /* Cycle to next periodic command? */ | ||
1441 | if (strip_info->firmware_level >= StructuredMessages) | ||
1442 | if (++strip_info->next_command >= | ||
1443 | ARRAY_SIZE(CommandString)) | ||
1444 | strip_info->next_command = 0; | ||
1445 | #ifdef EXT_COUNTERS | ||
1446 | strip_info->tx_ebytes += ts.length; | ||
1447 | #endif | ||
1448 | strip_info->watchdog_doprobe = jiffies + 10 * HZ; | ||
1449 | strip_info->watchdog_doreset = jiffies + 1 * HZ; | ||
1450 | /*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev->name); */ | ||
1451 | } | ||
1452 | |||
1453 | /* | ||
1454 | * 3. Set up the strip_info ready to send the data (if any). | ||
1455 | */ | ||
1456 | strip_info->tx_head = strip_info->tx_buff; | ||
1457 | strip_info->tx_left = ptr - strip_info->tx_buff; | ||
1458 | strip_info->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); | ||
1459 | |||
1460 | /* | ||
1461 | * 4. Debugging check to make sure we're not overflowing the buffer. | ||
1462 | */ | ||
1463 | if (strip_info->tx_size - strip_info->tx_left < 20) | ||
1464 | printk(KERN_ERR "%s: Sending%5d bytes;%5d bytes free.\n", | ||
1465 | strip_info->dev->name, strip_info->tx_left, | ||
1466 | strip_info->tx_size - strip_info->tx_left); | ||
1467 | |||
1468 | /* | ||
1469 | * 5. If watchdog has expired, reset the radio. Note: if there's data waiting in | ||
1470 | * the buffer, strip_write_some_more will send it after the reset has finished | ||
1471 | */ | ||
1472 | if (doreset) { | ||
1473 | ResetRadio(strip_info); | ||
1474 | return; | ||
1475 | } | ||
1476 | |||
1477 | if (1) { | ||
1478 | struct in_device *in_dev; | ||
1479 | |||
1480 | brd = addr = 0; | ||
1481 | rcu_read_lock(); | ||
1482 | in_dev = __in_dev_get_rcu(strip_info->dev); | ||
1483 | if (in_dev) { | ||
1484 | if (in_dev->ifa_list) { | ||
1485 | brd = in_dev->ifa_list->ifa_broadcast; | ||
1486 | addr = in_dev->ifa_list->ifa_local; | ||
1487 | } | ||
1488 | } | ||
1489 | rcu_read_unlock(); | ||
1490 | } | ||
1491 | |||
1492 | |||
1493 | /* | ||
1494 | * 6. If it is time for a periodic ARP, queue one up to be sent. | ||
1495 | * We only do this if: | ||
1496 | * 1. The radio is working | ||
1497 | * 2. It's time to send another periodic ARP | ||
1498 | * 3. We really know what our address is (and it is not manually set to zero) | ||
1499 | * 4. We have a designated broadcast address configured | ||
1500 | * If we queue up an ARP packet when we don't have a designated broadcast | ||
1501 | * address configured, then the packet will just have to be discarded in | ||
1502 | * strip_make_packet. This is not fatal, but it causes misleading information | ||
1503 | * to be displayed in tcpdump. tcpdump will report that periodic APRs are | ||
1504 | * being sent, when in fact they are not, because they are all being dropped | ||
1505 | * in the strip_make_packet routine. | ||
1506 | */ | ||
1507 | if (strip_info->working | ||
1508 | && (long) jiffies - strip_info->gratuitous_arp >= 0 | ||
1509 | && memcmp(strip_info->dev->dev_addr, zero_address.c, | ||
1510 | sizeof(zero_address)) | ||
1511 | && arp_query(haddr.c, brd, strip_info->dev)) { | ||
1512 | /*printk(KERN_INFO "%s: Sending gratuitous ARP with interval %ld\n", | ||
1513 | strip_info->dev->name, strip_info->arp_interval / HZ); */ | ||
1514 | strip_info->gratuitous_arp = | ||
1515 | jiffies + strip_info->arp_interval; | ||
1516 | strip_info->arp_interval *= 2; | ||
1517 | if (strip_info->arp_interval > MaxARPInterval) | ||
1518 | strip_info->arp_interval = MaxARPInterval; | ||
1519 | if (addr) | ||
1520 | arp_send(ARPOP_REPLY, ETH_P_ARP, addr, /* Target address of ARP packet is our address */ | ||
1521 | strip_info->dev, /* Device to send packet on */ | ||
1522 | addr, /* Source IP address this ARP packet comes from */ | ||
1523 | NULL, /* Destination HW address is NULL (broadcast it) */ | ||
1524 | strip_info->dev->dev_addr, /* Source HW address is our HW address */ | ||
1525 | strip_info->dev->dev_addr); /* Target HW address is our HW address (redundant) */ | ||
1526 | } | ||
1527 | |||
1528 | /* | ||
1529 | * 7. All ready. Start the transmission | ||
1530 | */ | ||
1531 | strip_write_some_more(strip_info->tty); | ||
1532 | } | ||
1533 | |||
1534 | /* Encapsulate a datagram and kick it into a TTY queue. */ | ||
1535 | static int strip_xmit(struct sk_buff *skb, struct net_device *dev) | ||
1536 | { | ||
1537 | struct strip *strip_info = netdev_priv(dev); | ||
1538 | |||
1539 | if (!netif_running(dev)) { | ||
1540 | printk(KERN_ERR "%s: xmit call when iface is down\n", | ||
1541 | dev->name); | ||
1542 | return (1); | ||
1543 | } | ||
1544 | |||
1545 | netif_stop_queue(dev); | ||
1546 | |||
1547 | del_timer(&strip_info->idle_timer); | ||
1548 | |||
1549 | |||
1550 | if (time_after(jiffies, strip_info->pps_timer + HZ)) { | ||
1551 | unsigned long t = jiffies - strip_info->pps_timer; | ||
1552 | unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t; | ||
1553 | unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t; | ||
1554 | unsigned long sx_pps_count = (strip_info->sx_pps_count * HZ * 8 + t / 2) / t; | ||
1555 | |||
1556 | strip_info->pps_timer = jiffies; | ||
1557 | strip_info->rx_pps_count = 0; | ||
1558 | strip_info->tx_pps_count = 0; | ||
1559 | strip_info->sx_pps_count = 0; | ||
1560 | |||
1561 | strip_info->rx_average_pps = (strip_info->rx_average_pps + rx_pps_count + 1) / 2; | ||
1562 | strip_info->tx_average_pps = (strip_info->tx_average_pps + tx_pps_count + 1) / 2; | ||
1563 | strip_info->sx_average_pps = (strip_info->sx_average_pps + sx_pps_count + 1) / 2; | ||
1564 | |||
1565 | if (rx_pps_count / 8 >= 10) | ||
1566 | printk(KERN_INFO "%s: WARNING: Receiving %ld packets per second.\n", | ||
1567 | strip_info->dev->name, rx_pps_count / 8); | ||
1568 | if (tx_pps_count / 8 >= 10) | ||
1569 | printk(KERN_INFO "%s: WARNING: Tx %ld packets per second.\n", | ||
1570 | strip_info->dev->name, tx_pps_count / 8); | ||
1571 | if (sx_pps_count / 8 >= 10) | ||
1572 | printk(KERN_INFO "%s: WARNING: Sending %ld packets per second.\n", | ||
1573 | strip_info->dev->name, sx_pps_count / 8); | ||
1574 | } | ||
1575 | |||
1576 | spin_lock_bh(&strip_lock); | ||
1577 | |||
1578 | strip_send(strip_info, skb); | ||
1579 | |||
1580 | spin_unlock_bh(&strip_lock); | ||
1581 | |||
1582 | if (skb) | ||
1583 | dev_kfree_skb(skb); | ||
1584 | return 0; | ||
1585 | } | ||
1586 | |||
1587 | /* | ||
1588 | * IdleTask periodically calls strip_xmit, so even when we have no IP packets | ||
1589 | * to send for an extended period of time, the watchdog processing still gets | ||
1590 | * done to ensure that the radio stays in Starmode | ||
1591 | */ | ||
1592 | |||
1593 | static void strip_IdleTask(unsigned long parameter) | ||
1594 | { | ||
1595 | strip_xmit(NULL, (struct net_device *) parameter); | ||
1596 | } | ||
1597 | |||
1598 | /* | ||
1599 | * Create the MAC header for an arbitrary protocol layer | ||
1600 | * | ||
1601 | * saddr!=NULL means use this specific address (n/a for Metricom) | ||
1602 | * saddr==NULL means use default device source address | ||
1603 | * daddr!=NULL means use this destination address | ||
1604 | * daddr==NULL means leave destination address alone | ||
1605 | * (e.g. unresolved arp -- kernel will call | ||
1606 | * rebuild_header later to fill in the address) | ||
1607 | */ | ||
1608 | |||
1609 | static int strip_header(struct sk_buff *skb, struct net_device *dev, | ||
1610 | unsigned short type, const void *daddr, | ||
1611 | const void *saddr, unsigned len) | ||
1612 | { | ||
1613 | struct strip *strip_info = netdev_priv(dev); | ||
1614 | STRIP_Header *header = (STRIP_Header *) skb_push(skb, sizeof(STRIP_Header)); | ||
1615 | |||
1616 | /*printk(KERN_INFO "%s: strip_header 0x%04X %s\n", dev->name, type, | ||
1617 | type == ETH_P_IP ? "IP" : type == ETH_P_ARP ? "ARP" : ""); */ | ||
1618 | |||
1619 | header->src_addr = strip_info->true_dev_addr; | ||
1620 | header->protocol = htons(type); | ||
1621 | |||
1622 | /*HexDump("strip_header", netdev_priv(dev), skb->data, skb->data + skb->len); */ | ||
1623 | |||
1624 | if (!daddr) | ||
1625 | return (-dev->hard_header_len); | ||
1626 | |||
1627 | header->dst_addr = *(MetricomAddress *) daddr; | ||
1628 | return (dev->hard_header_len); | ||
1629 | } | ||
1630 | |||
1631 | /* | ||
1632 | * Rebuild the MAC header. This is called after an ARP | ||
1633 | * (or in future other address resolution) has completed on this | ||
1634 | * sk_buff. We now let ARP fill in the other fields. | ||
1635 | * I think this should return zero if packet is ready to send, | ||
1636 | * or non-zero if it needs more time to do an address lookup | ||
1637 | */ | ||
1638 | |||
1639 | static int strip_rebuild_header(struct sk_buff *skb) | ||
1640 | { | ||
1641 | #ifdef CONFIG_INET | ||
1642 | STRIP_Header *header = (STRIP_Header *) skb->data; | ||
1643 | |||
1644 | /* Arp find returns zero if if knows the address, */ | ||
1645 | /* or if it doesn't know the address it sends an ARP packet and returns non-zero */ | ||
1646 | return arp_find(header->dst_addr.c, skb) ? 1 : 0; | ||
1647 | #else | ||
1648 | return 0; | ||
1649 | #endif | ||
1650 | } | ||
1651 | |||
1652 | |||
1653 | /************************************************************************/ | ||
1654 | /* Receiving routines */ | ||
1655 | |||
1656 | /* | ||
1657 | * This function parses the response to the ATS300? command, | ||
1658 | * extracting the radio version and serial number. | ||
1659 | */ | ||
1660 | static void get_radio_version(struct strip *strip_info, __u8 * ptr, __u8 * end) | ||
1661 | { | ||
1662 | __u8 *p, *value_begin, *value_end; | ||
1663 | int len; | ||
1664 | |||
1665 | /* Determine the beginning of the second line of the payload */ | ||
1666 | p = ptr; | ||
1667 | while (p < end && *p != 10) | ||
1668 | p++; | ||
1669 | if (p >= end) | ||
1670 | return; | ||
1671 | p++; | ||
1672 | value_begin = p; | ||
1673 | |||
1674 | /* Determine the end of line */ | ||
1675 | while (p < end && *p != 10) | ||
1676 | p++; | ||
1677 | if (p >= end) | ||
1678 | return; | ||
1679 | value_end = p; | ||
1680 | p++; | ||
1681 | |||
1682 | len = value_end - value_begin; | ||
1683 | len = min_t(int, len, sizeof(FirmwareVersion) - 1); | ||
1684 | if (strip_info->firmware_version.c[0] == 0) | ||
1685 | printk(KERN_INFO "%s: Radio Firmware: %.*s\n", | ||
1686 | strip_info->dev->name, len, value_begin); | ||
1687 | sprintf(strip_info->firmware_version.c, "%.*s", len, value_begin); | ||
1688 | |||
1689 | /* Look for the first colon */ | ||
1690 | while (p < end && *p != ':') | ||
1691 | p++; | ||
1692 | if (p >= end) | ||
1693 | return; | ||
1694 | /* Skip over the space */ | ||
1695 | p += 2; | ||
1696 | len = sizeof(SerialNumber) - 1; | ||
1697 | if (p + len <= end) { | ||
1698 | sprintf(strip_info->serial_number.c, "%.*s", len, p); | ||
1699 | } else { | ||
1700 | printk(KERN_DEBUG | ||
1701 | "STRIP: radio serial number shorter (%zd) than expected (%d)\n", | ||
1702 | end - p, len); | ||
1703 | } | ||
1704 | } | ||
1705 | |||
1706 | /* | ||
1707 | * This function parses the response to the ATS325? command, | ||
1708 | * extracting the radio battery voltage. | ||
1709 | */ | ||
1710 | static void get_radio_voltage(struct strip *strip_info, __u8 * ptr, __u8 * end) | ||
1711 | { | ||
1712 | int len; | ||
1713 | |||
1714 | len = sizeof(BatteryVoltage) - 1; | ||
1715 | if (ptr + len <= end) { | ||
1716 | sprintf(strip_info->battery_voltage.c, "%.*s", len, ptr); | ||
1717 | } else { | ||
1718 | printk(KERN_DEBUG | ||
1719 | "STRIP: radio voltage string shorter (%zd) than expected (%d)\n", | ||
1720 | end - ptr, len); | ||
1721 | } | ||
1722 | } | ||
1723 | |||
1724 | /* | ||
1725 | * This function parses the responses to the AT~LA and ATS311 commands, | ||
1726 | * which list the radio's neighbours. | ||
1727 | */ | ||
1728 | static void get_radio_neighbours(MetricomNodeTable * table, __u8 * ptr, __u8 * end) | ||
1729 | { | ||
1730 | table->num_nodes = 0; | ||
1731 | while (ptr < end && table->num_nodes < NODE_TABLE_SIZE) { | ||
1732 | MetricomNode *node = &table->node[table->num_nodes++]; | ||
1733 | char *dst = node->c, *limit = dst + sizeof(*node) - 1; | ||
1734 | while (ptr < end && *ptr <= 32) | ||
1735 | ptr++; | ||
1736 | while (ptr < end && dst < limit && *ptr != 10) | ||
1737 | *dst++ = *ptr++; | ||
1738 | *dst++ = 0; | ||
1739 | while (ptr < end && ptr[-1] != 10) | ||
1740 | ptr++; | ||
1741 | } | ||
1742 | do_gettimeofday(&table->timestamp); | ||
1743 | } | ||
1744 | |||
1745 | static int get_radio_address(struct strip *strip_info, __u8 * p) | ||
1746 | { | ||
1747 | MetricomAddress addr; | ||
1748 | |||
1749 | if (string_to_radio_address(&addr, p)) | ||
1750 | return (1); | ||
1751 | |||
1752 | /* See if our radio address has changed */ | ||
1753 | if (memcmp(strip_info->true_dev_addr.c, addr.c, sizeof(addr))) { | ||
1754 | MetricomAddressString addr_string; | ||
1755 | radio_address_to_string(&addr, &addr_string); | ||
1756 | printk(KERN_INFO "%s: Radio address = %s\n", | ||
1757 | strip_info->dev->name, addr_string.c); | ||
1758 | strip_info->true_dev_addr = addr; | ||
1759 | if (!strip_info->manual_dev_addr) | ||
1760 | *(MetricomAddress *) strip_info->dev->dev_addr = | ||
1761 | addr; | ||
1762 | /* Give the radio a few seconds to get its head straight, then send an arp */ | ||
1763 | strip_info->gratuitous_arp = jiffies + 15 * HZ; | ||
1764 | strip_info->arp_interval = 1 * HZ; | ||
1765 | } | ||
1766 | return (0); | ||
1767 | } | ||
1768 | |||
1769 | static int verify_checksum(struct strip *strip_info) | ||
1770 | { | ||
1771 | __u8 *p = strip_info->sx_buff; | ||
1772 | __u8 *end = strip_info->sx_buff + strip_info->sx_count - 4; | ||
1773 | u_short sum = | ||
1774 | (READHEX16(end[0]) << 12) | (READHEX16(end[1]) << 8) | | ||
1775 | (READHEX16(end[2]) << 4) | (READHEX16(end[3])); | ||
1776 | while (p < end) | ||
1777 | sum -= *p++; | ||
1778 | if (sum == 0 && strip_info->firmware_level == StructuredMessages) { | ||
1779 | strip_info->firmware_level = ChecksummedMessages; | ||
1780 | printk(KERN_INFO "%s: Radio provides message checksums\n", | ||
1781 | strip_info->dev->name); | ||
1782 | } | ||
1783 | return (sum == 0); | ||
1784 | } | ||
1785 | |||
1786 | static void RecvErr(char *msg, struct strip *strip_info) | ||
1787 | { | ||
1788 | __u8 *ptr = strip_info->sx_buff; | ||
1789 | __u8 *end = strip_info->sx_buff + strip_info->sx_count; | ||
1790 | DumpData(msg, strip_info, ptr, end); | ||
1791 | strip_info->rx_errors++; | ||
1792 | } | ||
1793 | |||
1794 | static void RecvErr_Message(struct strip *strip_info, __u8 * sendername, | ||
1795 | const __u8 * msg, u_long len) | ||
1796 | { | ||
1797 | if (has_prefix(msg, len, "001")) { /* Not in StarMode! */ | ||
1798 | RecvErr("Error Msg:", strip_info); | ||
1799 | printk(KERN_INFO "%s: Radio %s is not in StarMode\n", | ||
1800 | strip_info->dev->name, sendername); | ||
1801 | } | ||
1802 | |||
1803 | else if (has_prefix(msg, len, "002")) { /* Remap handle */ | ||
1804 | /* We ignore "Remap handle" messages for now */ | ||
1805 | } | ||
1806 | |||
1807 | else if (has_prefix(msg, len, "003")) { /* Can't resolve name */ | ||
1808 | RecvErr("Error Msg:", strip_info); | ||
1809 | printk(KERN_INFO "%s: Destination radio name is unknown\n", | ||
1810 | strip_info->dev->name); | ||
1811 | } | ||
1812 | |||
1813 | else if (has_prefix(msg, len, "004")) { /* Name too small or missing */ | ||
1814 | strip_info->watchdog_doreset = jiffies + LongTime; | ||
1815 | #if TICKLE_TIMERS | ||
1816 | { | ||
1817 | struct timeval tv; | ||
1818 | do_gettimeofday(&tv); | ||
1819 | printk(KERN_INFO | ||
1820 | "**** Got ERR_004 response at %02d.%06d\n", | ||
1821 | tv.tv_sec % 100, tv.tv_usec); | ||
1822 | } | ||
1823 | #endif | ||
1824 | if (!strip_info->working) { | ||
1825 | strip_info->working = TRUE; | ||
1826 | printk(KERN_INFO "%s: Radio now in starmode\n", | ||
1827 | strip_info->dev->name); | ||
1828 | /* | ||
1829 | * If the radio has just entered a working state, we should do our first | ||
1830 | * probe ASAP, so that we find out our radio address etc. without delay. | ||
1831 | */ | ||
1832 | strip_info->watchdog_doprobe = jiffies; | ||
1833 | } | ||
1834 | if (strip_info->firmware_level == NoStructure && sendername) { | ||
1835 | strip_info->firmware_level = StructuredMessages; | ||
1836 | strip_info->next_command = 0; /* Try to enable checksums ASAP */ | ||
1837 | printk(KERN_INFO | ||
1838 | "%s: Radio provides structured messages\n", | ||
1839 | strip_info->dev->name); | ||
1840 | } | ||
1841 | if (strip_info->firmware_level >= StructuredMessages) { | ||
1842 | /* | ||
1843 | * If this message has a valid checksum on the end, then the call to verify_checksum | ||
1844 | * will elevate the firmware_level to ChecksummedMessages for us. (The actual return | ||
1845 | * code from verify_checksum is ignored here.) | ||
1846 | */ | ||
1847 | verify_checksum(strip_info); | ||
1848 | /* | ||
1849 | * If the radio has structured messages but we don't yet have all our information about it, | ||
1850 | * we should do probes without delay, until we have gathered all the information | ||
1851 | */ | ||
1852 | if (!GOT_ALL_RADIO_INFO(strip_info)) | ||
1853 | strip_info->watchdog_doprobe = jiffies; | ||
1854 | } | ||
1855 | } | ||
1856 | |||
1857 | else if (has_prefix(msg, len, "005")) /* Bad count specification */ | ||
1858 | RecvErr("Error Msg:", strip_info); | ||
1859 | |||
1860 | else if (has_prefix(msg, len, "006")) /* Header too big */ | ||
1861 | RecvErr("Error Msg:", strip_info); | ||
1862 | |||
1863 | else if (has_prefix(msg, len, "007")) { /* Body too big */ | ||
1864 | RecvErr("Error Msg:", strip_info); | ||
1865 | printk(KERN_ERR | ||
1866 | "%s: Error! Packet size too big for radio.\n", | ||
1867 | strip_info->dev->name); | ||
1868 | } | ||
1869 | |||
1870 | else if (has_prefix(msg, len, "008")) { /* Bad character in name */ | ||
1871 | RecvErr("Error Msg:", strip_info); | ||
1872 | printk(KERN_ERR | ||
1873 | "%s: Radio name contains illegal character\n", | ||
1874 | strip_info->dev->name); | ||
1875 | } | ||
1876 | |||
1877 | else if (has_prefix(msg, len, "009")) /* No count or line terminator */ | ||
1878 | RecvErr("Error Msg:", strip_info); | ||
1879 | |||
1880 | else if (has_prefix(msg, len, "010")) /* Invalid checksum */ | ||
1881 | RecvErr("Error Msg:", strip_info); | ||
1882 | |||
1883 | else if (has_prefix(msg, len, "011")) /* Checksum didn't match */ | ||
1884 | RecvErr("Error Msg:", strip_info); | ||
1885 | |||
1886 | else if (has_prefix(msg, len, "012")) /* Failed to transmit packet */ | ||
1887 | RecvErr("Error Msg:", strip_info); | ||
1888 | |||
1889 | else | ||
1890 | RecvErr("Error Msg:", strip_info); | ||
1891 | } | ||
1892 | |||
1893 | static void process_AT_response(struct strip *strip_info, __u8 * ptr, | ||
1894 | __u8 * end) | ||
1895 | { | ||
1896 | u_long len; | ||
1897 | __u8 *p = ptr; | ||
1898 | while (p < end && p[-1] != 10) | ||
1899 | p++; /* Skip past first newline character */ | ||
1900 | /* Now ptr points to the AT command, and p points to the text of the response. */ | ||
1901 | len = p - ptr; | ||
1902 | |||
1903 | #if TICKLE_TIMERS | ||
1904 | { | ||
1905 | struct timeval tv; | ||
1906 | do_gettimeofday(&tv); | ||
1907 | printk(KERN_INFO "**** Got AT response %.7s at %02d.%06d\n", | ||
1908 | ptr, tv.tv_sec % 100, tv.tv_usec); | ||
1909 | } | ||
1910 | #endif | ||
1911 | |||
1912 | if (has_prefix(ptr, len, "ATS300?")) | ||
1913 | get_radio_version(strip_info, p, end); | ||
1914 | else if (has_prefix(ptr, len, "ATS305?")) | ||
1915 | get_radio_address(strip_info, p); | ||
1916 | else if (has_prefix(ptr, len, "ATS311?")) | ||
1917 | get_radio_neighbours(&strip_info->poletops, p, end); | ||
1918 | else if (has_prefix(ptr, len, "ATS319=7")) | ||
1919 | verify_checksum(strip_info); | ||
1920 | else if (has_prefix(ptr, len, "ATS325?")) | ||
1921 | get_radio_voltage(strip_info, p, end); | ||
1922 | else if (has_prefix(ptr, len, "AT~LA")) | ||
1923 | get_radio_neighbours(&strip_info->portables, p, end); | ||
1924 | else | ||
1925 | RecvErr("Unknown AT Response:", strip_info); | ||
1926 | } | ||
1927 | |||
1928 | static void process_ACK(struct strip *strip_info, __u8 * ptr, __u8 * end) | ||
1929 | { | ||
1930 | /* Currently we don't do anything with ACKs from the radio */ | ||
1931 | } | ||
1932 | |||
1933 | static void process_Info(struct strip *strip_info, __u8 * ptr, __u8 * end) | ||
1934 | { | ||
1935 | if (ptr + 16 > end) | ||
1936 | RecvErr("Bad Info Msg:", strip_info); | ||
1937 | } | ||
1938 | |||
1939 | static struct net_device *get_strip_dev(struct strip *strip_info) | ||
1940 | { | ||
1941 | /* If our hardware address is *manually set* to zero, and we know our */ | ||
1942 | /* real radio hardware address, try to find another strip device that has been */ | ||
1943 | /* manually set to that address that we can 'transfer ownership' of this packet to */ | ||
1944 | if (strip_info->manual_dev_addr && | ||
1945 | !memcmp(strip_info->dev->dev_addr, zero_address.c, | ||
1946 | sizeof(zero_address)) | ||
1947 | && memcmp(&strip_info->true_dev_addr, zero_address.c, | ||
1948 | sizeof(zero_address))) { | ||
1949 | struct net_device *dev; | ||
1950 | read_lock_bh(&dev_base_lock); | ||
1951 | for_each_netdev(&init_net, dev) { | ||
1952 | if (dev->type == strip_info->dev->type && | ||
1953 | !memcmp(dev->dev_addr, | ||
1954 | &strip_info->true_dev_addr, | ||
1955 | sizeof(MetricomAddress))) { | ||
1956 | printk(KERN_INFO | ||
1957 | "%s: Transferred packet ownership to %s.\n", | ||
1958 | strip_info->dev->name, dev->name); | ||
1959 | read_unlock_bh(&dev_base_lock); | ||
1960 | return (dev); | ||
1961 | } | ||
1962 | } | ||
1963 | read_unlock_bh(&dev_base_lock); | ||
1964 | } | ||
1965 | return (strip_info->dev); | ||
1966 | } | ||
1967 | |||
1968 | /* | ||
1969 | * Send one completely decapsulated datagram to the next layer. | ||
1970 | */ | ||
1971 | |||
1972 | static void deliver_packet(struct strip *strip_info, STRIP_Header * header, | ||
1973 | __u16 packetlen) | ||
1974 | { | ||
1975 | struct sk_buff *skb = dev_alloc_skb(sizeof(STRIP_Header) + packetlen); | ||
1976 | if (!skb) { | ||
1977 | printk(KERN_ERR "%s: memory squeeze, dropping packet.\n", | ||
1978 | strip_info->dev->name); | ||
1979 | strip_info->rx_dropped++; | ||
1980 | } else { | ||
1981 | memcpy(skb_put(skb, sizeof(STRIP_Header)), header, | ||
1982 | sizeof(STRIP_Header)); | ||
1983 | memcpy(skb_put(skb, packetlen), strip_info->rx_buff, | ||
1984 | packetlen); | ||
1985 | skb->dev = get_strip_dev(strip_info); | ||
1986 | skb->protocol = header->protocol; | ||
1987 | skb_reset_mac_header(skb); | ||
1988 | |||
1989 | /* Having put a fake header on the front of the sk_buff for the */ | ||
1990 | /* benefit of tools like tcpdump, skb_pull now 'consumes' that */ | ||
1991 | /* fake header before we hand the packet up to the next layer. */ | ||
1992 | skb_pull(skb, sizeof(STRIP_Header)); | ||
1993 | |||
1994 | /* Finally, hand the packet up to the next layer (e.g. IP or ARP, etc.) */ | ||
1995 | strip_info->rx_packets++; | ||
1996 | strip_info->rx_pps_count++; | ||
1997 | #ifdef EXT_COUNTERS | ||
1998 | strip_info->rx_bytes += packetlen; | ||
1999 | #endif | ||
2000 | skb->dev->last_rx = jiffies; | ||
2001 | netif_rx(skb); | ||
2002 | } | ||
2003 | } | ||
2004 | |||
2005 | static void process_IP_packet(struct strip *strip_info, | ||
2006 | STRIP_Header * header, __u8 * ptr, | ||
2007 | __u8 * end) | ||
2008 | { | ||
2009 | __u16 packetlen; | ||
2010 | |||
2011 | /* Decode start of the IP packet header */ | ||
2012 | ptr = UnStuffData(ptr, end, strip_info->rx_buff, 4); | ||
2013 | if (!ptr) { | ||
2014 | RecvErr("IP Packet too short", strip_info); | ||
2015 | return; | ||
2016 | } | ||
2017 | |||
2018 | packetlen = ((__u16) strip_info->rx_buff[2] << 8) | strip_info->rx_buff[3]; | ||
2019 | |||
2020 | if (packetlen > MAX_RECV_MTU) { | ||
2021 | printk(KERN_INFO "%s: Dropping oversized received IP packet: %d bytes\n", | ||
2022 | strip_info->dev->name, packetlen); | ||
2023 | strip_info->rx_dropped++; | ||
2024 | return; | ||
2025 | } | ||
2026 | |||
2027 | /*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev->name, packetlen); */ | ||
2028 | |||
2029 | /* Decode remainder of the IP packet */ | ||
2030 | ptr = | ||
2031 | UnStuffData(ptr, end, strip_info->rx_buff + 4, packetlen - 4); | ||
2032 | if (!ptr) { | ||
2033 | RecvErr("IP Packet too short", strip_info); | ||
2034 | return; | ||
2035 | } | ||
2036 | |||
2037 | if (ptr < end) { | ||
2038 | RecvErr("IP Packet too long", strip_info); | ||
2039 | return; | ||
2040 | } | ||
2041 | |||
2042 | header->protocol = htons(ETH_P_IP); | ||
2043 | |||
2044 | deliver_packet(strip_info, header, packetlen); | ||
2045 | } | ||
2046 | |||
2047 | static void process_ARP_packet(struct strip *strip_info, | ||
2048 | STRIP_Header * header, __u8 * ptr, | ||
2049 | __u8 * end) | ||
2050 | { | ||
2051 | __u16 packetlen; | ||
2052 | struct arphdr *arphdr = (struct arphdr *) strip_info->rx_buff; | ||
2053 | |||
2054 | /* Decode start of the ARP packet */ | ||
2055 | ptr = UnStuffData(ptr, end, strip_info->rx_buff, 8); | ||
2056 | if (!ptr) { | ||
2057 | RecvErr("ARP Packet too short", strip_info); | ||
2058 | return; | ||
2059 | } | ||
2060 | |||
2061 | packetlen = 8 + (arphdr->ar_hln + arphdr->ar_pln) * 2; | ||
2062 | |||
2063 | if (packetlen > MAX_RECV_MTU) { | ||
2064 | printk(KERN_INFO | ||
2065 | "%s: Dropping oversized received ARP packet: %d bytes\n", | ||
2066 | strip_info->dev->name, packetlen); | ||
2067 | strip_info->rx_dropped++; | ||
2068 | return; | ||
2069 | } | ||
2070 | |||
2071 | /*printk(KERN_INFO "%s: Got %d byte ARP %s\n", | ||
2072 | strip_info->dev->name, packetlen, | ||
2073 | ntohs(arphdr->ar_op) == ARPOP_REQUEST ? "request" : "reply"); */ | ||
2074 | |||
2075 | /* Decode remainder of the ARP packet */ | ||
2076 | ptr = | ||
2077 | UnStuffData(ptr, end, strip_info->rx_buff + 8, packetlen - 8); | ||
2078 | if (!ptr) { | ||
2079 | RecvErr("ARP Packet too short", strip_info); | ||
2080 | return; | ||
2081 | } | ||
2082 | |||
2083 | if (ptr < end) { | ||
2084 | RecvErr("ARP Packet too long", strip_info); | ||
2085 | return; | ||
2086 | } | ||
2087 | |||
2088 | header->protocol = htons(ETH_P_ARP); | ||
2089 | |||
2090 | deliver_packet(strip_info, header, packetlen); | ||
2091 | } | ||
2092 | |||
2093 | /* | ||
2094 | * process_text_message processes a <CR>-terminated block of data received | ||
2095 | * from the radio that doesn't begin with a '*' character. All normal | ||
2096 | * Starmode communication messages with the radio begin with a '*', | ||
2097 | * so any text that does not indicates a serial port error, a radio that | ||
2098 | * is in Hayes command mode instead of Starmode, or a radio with really | ||
2099 | * old firmware that doesn't frame its Starmode responses properly. | ||
2100 | */ | ||
2101 | static void process_text_message(struct strip *strip_info) | ||
2102 | { | ||
2103 | __u8 *msg = strip_info->sx_buff; | ||
2104 | int len = strip_info->sx_count; | ||
2105 | |||
2106 | /* Check for anything that looks like it might be our radio name */ | ||
2107 | /* (This is here for backwards compatibility with old firmware) */ | ||
2108 | if (len == 9 && get_radio_address(strip_info, msg) == 0) | ||
2109 | return; | ||
2110 | |||
2111 | if (text_equal(msg, len, "OK")) | ||
2112 | return; /* Ignore 'OK' responses from prior commands */ | ||
2113 | if (text_equal(msg, len, "ERROR")) | ||
2114 | return; /* Ignore 'ERROR' messages */ | ||
2115 | if (has_prefix(msg, len, "ate0q1")) | ||
2116 | return; /* Ignore character echo back from the radio */ | ||
2117 | |||
2118 | /* Catch other error messages */ | ||
2119 | /* (This is here for backwards compatibility with old firmware) */ | ||
2120 | if (has_prefix(msg, len, "ERR_")) { | ||
2121 | RecvErr_Message(strip_info, NULL, &msg[4], len - 4); | ||
2122 | return; | ||
2123 | } | ||
2124 | |||
2125 | RecvErr("No initial *", strip_info); | ||
2126 | } | ||
2127 | |||
2128 | /* | ||
2129 | * process_message processes a <CR>-terminated block of data received | ||
2130 | * from the radio. If the radio is not in Starmode or has old firmware, | ||
2131 | * it may be a line of text in response to an AT command. Ideally, with | ||
2132 | * a current radio that's properly in Starmode, all data received should | ||
2133 | * be properly framed and checksummed radio message blocks, containing | ||
2134 | * either a starmode packet, or a other communication from the radio | ||
2135 | * firmware, like "INF_" Info messages and &COMMAND responses. | ||
2136 | */ | ||
2137 | static void process_message(struct strip *strip_info) | ||
2138 | { | ||
2139 | STRIP_Header header = { zero_address, zero_address, 0 }; | ||
2140 | __u8 *ptr = strip_info->sx_buff; | ||
2141 | __u8 *end = strip_info->sx_buff + strip_info->sx_count; | ||
2142 | __u8 sendername[32], *sptr = sendername; | ||
2143 | MetricomKey key; | ||
2144 | |||
2145 | /*HexDump("Receiving", strip_info, ptr, end); */ | ||
2146 | |||
2147 | /* Check for start of address marker, and then skip over it */ | ||
2148 | if (*ptr == '*') | ||
2149 | ptr++; | ||
2150 | else { | ||
2151 | process_text_message(strip_info); | ||
2152 | return; | ||
2153 | } | ||
2154 | |||
2155 | /* Copy out the return address */ | ||
2156 | while (ptr < end && *ptr != '*' | ||
2157 | && sptr < ARRAY_END(sendername) - 1) | ||
2158 | *sptr++ = *ptr++; | ||
2159 | *sptr = 0; /* Null terminate the sender name */ | ||
2160 | |||
2161 | /* Check for end of address marker, and skip over it */ | ||
2162 | if (ptr >= end || *ptr != '*') { | ||
2163 | RecvErr("No second *", strip_info); | ||
2164 | return; | ||
2165 | } | ||
2166 | ptr++; /* Skip the second '*' */ | ||
2167 | |||
2168 | /* If the sender name is "&COMMAND", ignore this 'packet' */ | ||
2169 | /* (This is here for backwards compatibility with old firmware) */ | ||
2170 | if (!strcmp(sendername, "&COMMAND")) { | ||
2171 | strip_info->firmware_level = NoStructure; | ||
2172 | strip_info->next_command = CompatibilityCommand; | ||
2173 | return; | ||
2174 | } | ||
2175 | |||
2176 | if (ptr + 4 > end) { | ||
2177 | RecvErr("No proto key", strip_info); | ||
2178 | return; | ||
2179 | } | ||
2180 | |||
2181 | /* Get the protocol key out of the buffer */ | ||
2182 | key.c[0] = *ptr++; | ||
2183 | key.c[1] = *ptr++; | ||
2184 | key.c[2] = *ptr++; | ||
2185 | key.c[3] = *ptr++; | ||
2186 | |||
2187 | /* If we're using checksums, verify the checksum at the end of the packet */ | ||
2188 | if (strip_info->firmware_level >= ChecksummedMessages) { | ||
2189 | end -= 4; /* Chop the last four bytes off the packet (they're the checksum) */ | ||
2190 | if (ptr > end) { | ||
2191 | RecvErr("Missing Checksum", strip_info); | ||
2192 | return; | ||
2193 | } | ||
2194 | if (!verify_checksum(strip_info)) { | ||
2195 | RecvErr("Bad Checksum", strip_info); | ||
2196 | return; | ||
2197 | } | ||
2198 | } | ||
2199 | |||
2200 | /*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev->name, sendername); */ | ||
2201 | |||
2202 | /* | ||
2203 | * Fill in (pseudo) source and destination addresses in the packet. | ||
2204 | * We assume that the destination address was our address (the radio does not | ||
2205 | * tell us this). If the radio supplies a source address, then we use it. | ||
2206 | */ | ||
2207 | header.dst_addr = strip_info->true_dev_addr; | ||
2208 | string_to_radio_address(&header.src_addr, sendername); | ||
2209 | |||
2210 | #ifdef EXT_COUNTERS | ||
2211 | if (key.l == SIP0Key.l) { | ||
2212 | strip_info->rx_rbytes += (end - ptr); | ||
2213 | process_IP_packet(strip_info, &header, ptr, end); | ||
2214 | } else if (key.l == ARP0Key.l) { | ||
2215 | strip_info->rx_rbytes += (end - ptr); | ||
2216 | process_ARP_packet(strip_info, &header, ptr, end); | ||
2217 | } else if (key.l == ATR_Key.l) { | ||
2218 | strip_info->rx_ebytes += (end - ptr); | ||
2219 | process_AT_response(strip_info, ptr, end); | ||
2220 | } else if (key.l == ACK_Key.l) { | ||
2221 | strip_info->rx_ebytes += (end - ptr); | ||
2222 | process_ACK(strip_info, ptr, end); | ||
2223 | } else if (key.l == INF_Key.l) { | ||
2224 | strip_info->rx_ebytes += (end - ptr); | ||
2225 | process_Info(strip_info, ptr, end); | ||
2226 | } else if (key.l == ERR_Key.l) { | ||
2227 | strip_info->rx_ebytes += (end - ptr); | ||
2228 | RecvErr_Message(strip_info, sendername, ptr, end - ptr); | ||
2229 | } else | ||
2230 | RecvErr("Unrecognized protocol key", strip_info); | ||
2231 | #else | ||
2232 | if (key.l == SIP0Key.l) | ||
2233 | process_IP_packet(strip_info, &header, ptr, end); | ||
2234 | else if (key.l == ARP0Key.l) | ||
2235 | process_ARP_packet(strip_info, &header, ptr, end); | ||
2236 | else if (key.l == ATR_Key.l) | ||
2237 | process_AT_response(strip_info, ptr, end); | ||
2238 | else if (key.l == ACK_Key.l) | ||
2239 | process_ACK(strip_info, ptr, end); | ||
2240 | else if (key.l == INF_Key.l) | ||
2241 | process_Info(strip_info, ptr, end); | ||
2242 | else if (key.l == ERR_Key.l) | ||
2243 | RecvErr_Message(strip_info, sendername, ptr, end - ptr); | ||
2244 | else | ||
2245 | RecvErr("Unrecognized protocol key", strip_info); | ||
2246 | #endif | ||
2247 | } | ||
2248 | |||
2249 | #define TTYERROR(X) ((X) == TTY_BREAK ? "Break" : \ | ||
2250 | (X) == TTY_FRAME ? "Framing Error" : \ | ||
2251 | (X) == TTY_PARITY ? "Parity Error" : \ | ||
2252 | (X) == TTY_OVERRUN ? "Hardware Overrun" : "Unknown Error") | ||
2253 | |||
2254 | /* | ||
2255 | * Handle the 'receiver data ready' interrupt. | ||
2256 | * This function is called by the 'tty_io' module in the kernel when | ||
2257 | * a block of STRIP data has been received, which can now be decapsulated | ||
2258 | * and sent on to some IP layer for further processing. | ||
2259 | */ | ||
2260 | |||
2261 | static void strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, | ||
2262 | char *fp, int count) | ||
2263 | { | ||
2264 | struct strip *strip_info = (struct strip *) tty->disc_data; | ||
2265 | const unsigned char *end = cp + count; | ||
2266 | |||
2267 | if (!strip_info || strip_info->magic != STRIP_MAGIC | ||
2268 | || !netif_running(strip_info->dev)) | ||
2269 | return; | ||
2270 | |||
2271 | spin_lock_bh(&strip_lock); | ||
2272 | #if 0 | ||
2273 | { | ||
2274 | struct timeval tv; | ||
2275 | do_gettimeofday(&tv); | ||
2276 | printk(KERN_INFO | ||
2277 | "**** strip_receive_buf: %3d bytes at %02d.%06d\n", | ||
2278 | count, tv.tv_sec % 100, tv.tv_usec); | ||
2279 | } | ||
2280 | #endif | ||
2281 | |||
2282 | #ifdef EXT_COUNTERS | ||
2283 | strip_info->rx_sbytes += count; | ||
2284 | #endif | ||
2285 | |||
2286 | /* Read the characters out of the buffer */ | ||
2287 | while (cp < end) { | ||
2288 | if (fp && *fp) | ||
2289 | printk(KERN_INFO "%s: %s on serial port\n", | ||
2290 | strip_info->dev->name, TTYERROR(*fp)); | ||
2291 | if (fp && *fp++ && !strip_info->discard) { /* If there's a serial error, record it */ | ||
2292 | /* If we have some characters in the buffer, discard them */ | ||
2293 | strip_info->discard = strip_info->sx_count; | ||
2294 | strip_info->rx_errors++; | ||
2295 | } | ||
2296 | |||
2297 | /* Leading control characters (CR, NL, Tab, etc.) are ignored */ | ||
2298 | if (strip_info->sx_count > 0 || *cp >= ' ') { | ||
2299 | if (*cp == 0x0D) { /* If end of packet, decide what to do with it */ | ||
2300 | if (strip_info->sx_count > 3000) | ||
2301 | printk(KERN_INFO | ||
2302 | "%s: Cut a %d byte packet (%zd bytes remaining)%s\n", | ||
2303 | strip_info->dev->name, | ||
2304 | strip_info->sx_count, | ||
2305 | end - cp - 1, | ||
2306 | strip_info-> | ||
2307 | discard ? " (discarded)" : | ||
2308 | ""); | ||
2309 | if (strip_info->sx_count > | ||
2310 | strip_info->sx_size) { | ||
2311 | strip_info->rx_over_errors++; | ||
2312 | printk(KERN_INFO | ||
2313 | "%s: sx_buff overflow (%d bytes total)\n", | ||
2314 | strip_info->dev->name, | ||
2315 | strip_info->sx_count); | ||
2316 | } else if (strip_info->discard) | ||
2317 | printk(KERN_INFO | ||
2318 | "%s: Discarding bad packet (%d/%d)\n", | ||
2319 | strip_info->dev->name, | ||
2320 | strip_info->discard, | ||
2321 | strip_info->sx_count); | ||
2322 | else | ||
2323 | process_message(strip_info); | ||
2324 | strip_info->discard = 0; | ||
2325 | strip_info->sx_count = 0; | ||
2326 | } else { | ||
2327 | /* Make sure we have space in the buffer */ | ||
2328 | if (strip_info->sx_count < | ||
2329 | strip_info->sx_size) | ||
2330 | strip_info->sx_buff[strip_info-> | ||
2331 | sx_count] = | ||
2332 | *cp; | ||
2333 | strip_info->sx_count++; | ||
2334 | } | ||
2335 | } | ||
2336 | cp++; | ||
2337 | } | ||
2338 | spin_unlock_bh(&strip_lock); | ||
2339 | } | ||
2340 | |||
2341 | |||
2342 | /************************************************************************/ | ||
2343 | /* General control routines */ | ||
2344 | |||
2345 | static int set_mac_address(struct strip *strip_info, | ||
2346 | MetricomAddress * addr) | ||
2347 | { | ||
2348 | /* | ||
2349 | * We're using a manually specified address if the address is set | ||
2350 | * to anything other than all ones. Setting the address to all ones | ||
2351 | * disables manual mode and goes back to automatic address determination | ||
2352 | * (tracking the true address that the radio has). | ||
2353 | */ | ||
2354 | strip_info->manual_dev_addr = | ||
2355 | memcmp(addr->c, broadcast_address.c, | ||
2356 | sizeof(broadcast_address)); | ||
2357 | if (strip_info->manual_dev_addr) | ||
2358 | *(MetricomAddress *) strip_info->dev->dev_addr = *addr; | ||
2359 | else | ||
2360 | *(MetricomAddress *) strip_info->dev->dev_addr = | ||
2361 | strip_info->true_dev_addr; | ||
2362 | return 0; | ||
2363 | } | ||
2364 | |||
2365 | static int strip_set_mac_address(struct net_device *dev, void *addr) | ||
2366 | { | ||
2367 | struct strip *strip_info = netdev_priv(dev); | ||
2368 | struct sockaddr *sa = addr; | ||
2369 | printk(KERN_INFO "%s: strip_set_dev_mac_address called\n", dev->name); | ||
2370 | set_mac_address(strip_info, (MetricomAddress *) sa->sa_data); | ||
2371 | return 0; | ||
2372 | } | ||
2373 | |||
2374 | static struct net_device_stats *strip_get_stats(struct net_device *dev) | ||
2375 | { | ||
2376 | struct strip *strip_info = netdev_priv(dev); | ||
2377 | static struct net_device_stats stats; | ||
2378 | |||
2379 | memset(&stats, 0, sizeof(struct net_device_stats)); | ||
2380 | |||
2381 | stats.rx_packets = strip_info->rx_packets; | ||
2382 | stats.tx_packets = strip_info->tx_packets; | ||
2383 | stats.rx_dropped = strip_info->rx_dropped; | ||
2384 | stats.tx_dropped = strip_info->tx_dropped; | ||
2385 | stats.tx_errors = strip_info->tx_errors; | ||
2386 | stats.rx_errors = strip_info->rx_errors; | ||
2387 | stats.rx_over_errors = strip_info->rx_over_errors; | ||
2388 | return (&stats); | ||
2389 | } | ||
2390 | |||
2391 | |||
2392 | /************************************************************************/ | ||
2393 | /* Opening and closing */ | ||
2394 | |||
2395 | /* | ||
2396 | * Here's the order things happen: | ||
2397 | * When the user runs "slattach -p strip ..." | ||
2398 | * 1. The TTY module calls strip_open;; | ||
2399 | * 2. strip_open calls strip_alloc | ||
2400 | * 3. strip_alloc calls register_netdev | ||
2401 | * 4. register_netdev calls strip_dev_init | ||
2402 | * 5. then strip_open finishes setting up the strip_info | ||
2403 | * | ||
2404 | * When the user runs "ifconfig st<x> up address netmask ..." | ||
2405 | * 6. strip_open_low gets called | ||
2406 | * | ||
2407 | * When the user runs "ifconfig st<x> down" | ||
2408 | * 7. strip_close_low gets called | ||
2409 | * | ||
2410 | * When the user kills the slattach process | ||
2411 | * 8. strip_close gets called | ||
2412 | * 9. strip_close calls dev_close | ||
2413 | * 10. if the device is still up, then dev_close calls strip_close_low | ||
2414 | * 11. strip_close calls strip_free | ||
2415 | */ | ||
2416 | |||
2417 | /* Open the low-level part of the STRIP channel. Easy! */ | ||
2418 | |||
2419 | static int strip_open_low(struct net_device *dev) | ||
2420 | { | ||
2421 | struct strip *strip_info = netdev_priv(dev); | ||
2422 | |||
2423 | if (strip_info->tty == NULL) | ||
2424 | return (-ENODEV); | ||
2425 | |||
2426 | if (!allocate_buffers(strip_info, dev->mtu)) | ||
2427 | return (-ENOMEM); | ||
2428 | |||
2429 | strip_info->sx_count = 0; | ||
2430 | strip_info->tx_left = 0; | ||
2431 | |||
2432 | strip_info->discard = 0; | ||
2433 | strip_info->working = FALSE; | ||
2434 | strip_info->firmware_level = NoStructure; | ||
2435 | strip_info->next_command = CompatibilityCommand; | ||
2436 | strip_info->user_baud = tty_get_baud_rate(strip_info->tty); | ||
2437 | |||
2438 | printk(KERN_INFO "%s: Initializing Radio.\n", | ||
2439 | strip_info->dev->name); | ||
2440 | ResetRadio(strip_info); | ||
2441 | strip_info->idle_timer.expires = jiffies + 1 * HZ; | ||
2442 | add_timer(&strip_info->idle_timer); | ||
2443 | netif_wake_queue(dev); | ||
2444 | return (0); | ||
2445 | } | ||
2446 | |||
2447 | |||
2448 | /* | ||
2449 | * Close the low-level part of the STRIP channel. Easy! | ||
2450 | */ | ||
2451 | |||
2452 | static int strip_close_low(struct net_device *dev) | ||
2453 | { | ||
2454 | struct strip *strip_info = netdev_priv(dev); | ||
2455 | |||
2456 | if (strip_info->tty == NULL) | ||
2457 | return -EBUSY; | ||
2458 | strip_info->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); | ||
2459 | |||
2460 | netif_stop_queue(dev); | ||
2461 | |||
2462 | /* | ||
2463 | * Free all STRIP frame buffers. | ||
2464 | */ | ||
2465 | kfree(strip_info->rx_buff); | ||
2466 | strip_info->rx_buff = NULL; | ||
2467 | kfree(strip_info->sx_buff); | ||
2468 | strip_info->sx_buff = NULL; | ||
2469 | kfree(strip_info->tx_buff); | ||
2470 | strip_info->tx_buff = NULL; | ||
2471 | |||
2472 | del_timer(&strip_info->idle_timer); | ||
2473 | return 0; | ||
2474 | } | ||
2475 | |||
2476 | static const struct header_ops strip_header_ops = { | ||
2477 | .create = strip_header, | ||
2478 | .rebuild = strip_rebuild_header, | ||
2479 | }; | ||
2480 | |||
2481 | /* | ||
2482 | * This routine is called by DDI when the | ||
2483 | * (dynamically assigned) device is registered | ||
2484 | */ | ||
2485 | |||
2486 | static void strip_dev_setup(struct net_device *dev) | ||
2487 | { | ||
2488 | /* | ||
2489 | * Finish setting up the DEVICE info. | ||
2490 | */ | ||
2491 | |||
2492 | dev->trans_start = 0; | ||
2493 | dev->last_rx = 0; | ||
2494 | dev->tx_queue_len = 30; /* Drop after 30 frames queued */ | ||
2495 | |||
2496 | dev->flags = 0; | ||
2497 | dev->mtu = DEFAULT_STRIP_MTU; | ||
2498 | dev->type = ARPHRD_METRICOM; /* dtang */ | ||
2499 | dev->hard_header_len = sizeof(STRIP_Header); | ||
2500 | /* | ||
2501 | * dev->priv Already holds a pointer to our struct strip | ||
2502 | */ | ||
2503 | |||
2504 | *(MetricomAddress *) & dev->broadcast = broadcast_address; | ||
2505 | dev->dev_addr[0] = 0; | ||
2506 | dev->addr_len = sizeof(MetricomAddress); | ||
2507 | |||
2508 | /* | ||
2509 | * Pointers to interface service routines. | ||
2510 | */ | ||
2511 | |||
2512 | dev->open = strip_open_low; | ||
2513 | dev->stop = strip_close_low; | ||
2514 | dev->hard_start_xmit = strip_xmit; | ||
2515 | dev->header_ops = &strip_header_ops; | ||
2516 | |||
2517 | dev->set_mac_address = strip_set_mac_address; | ||
2518 | dev->get_stats = strip_get_stats; | ||
2519 | dev->change_mtu = strip_change_mtu; | ||
2520 | } | ||
2521 | |||
2522 | /* | ||
2523 | * Free a STRIP channel. | ||
2524 | */ | ||
2525 | |||
2526 | static void strip_free(struct strip *strip_info) | ||
2527 | { | ||
2528 | spin_lock_bh(&strip_lock); | ||
2529 | list_del_rcu(&strip_info->list); | ||
2530 | spin_unlock_bh(&strip_lock); | ||
2531 | |||
2532 | strip_info->magic = 0; | ||
2533 | |||
2534 | free_netdev(strip_info->dev); | ||
2535 | } | ||
2536 | |||
2537 | |||
2538 | /* | ||
2539 | * Allocate a new free STRIP channel | ||
2540 | */ | ||
2541 | static struct strip *strip_alloc(void) | ||
2542 | { | ||
2543 | struct list_head *n; | ||
2544 | struct net_device *dev; | ||
2545 | struct strip *strip_info; | ||
2546 | |||
2547 | dev = alloc_netdev(sizeof(struct strip), "st%d", | ||
2548 | strip_dev_setup); | ||
2549 | |||
2550 | if (!dev) | ||
2551 | return NULL; /* If no more memory, return */ | ||
2552 | |||
2553 | |||
2554 | strip_info = netdev_priv(dev); | ||
2555 | strip_info->dev = dev; | ||
2556 | |||
2557 | strip_info->magic = STRIP_MAGIC; | ||
2558 | strip_info->tty = NULL; | ||
2559 | |||
2560 | strip_info->gratuitous_arp = jiffies + LongTime; | ||
2561 | strip_info->arp_interval = 0; | ||
2562 | init_timer(&strip_info->idle_timer); | ||
2563 | strip_info->idle_timer.data = (long) dev; | ||
2564 | strip_info->idle_timer.function = strip_IdleTask; | ||
2565 | |||
2566 | |||
2567 | spin_lock_bh(&strip_lock); | ||
2568 | rescan: | ||
2569 | /* | ||
2570 | * Search the list to find where to put our new entry | ||
2571 | * (and in the process decide what channel number it is | ||
2572 | * going to be) | ||
2573 | */ | ||
2574 | list_for_each(n, &strip_list) { | ||
2575 | struct strip *s = hlist_entry(n, struct strip, list); | ||
2576 | |||
2577 | if (s->dev->base_addr == dev->base_addr) { | ||
2578 | ++dev->base_addr; | ||
2579 | goto rescan; | ||
2580 | } | ||
2581 | } | ||
2582 | |||
2583 | sprintf(dev->name, "st%ld", dev->base_addr); | ||
2584 | |||
2585 | list_add_tail_rcu(&strip_info->list, &strip_list); | ||
2586 | spin_unlock_bh(&strip_lock); | ||
2587 | |||
2588 | return strip_info; | ||
2589 | } | ||
2590 | |||
2591 | /* | ||
2592 | * Open the high-level part of the STRIP channel. | ||
2593 | * This function is called by the TTY module when the | ||
2594 | * STRIP line discipline is called for. Because we are | ||
2595 | * sure the tty line exists, we only have to link it to | ||
2596 | * a free STRIP channel... | ||
2597 | */ | ||
2598 | |||
2599 | static int strip_open(struct tty_struct *tty) | ||
2600 | { | ||
2601 | struct strip *strip_info = (struct strip *) tty->disc_data; | ||
2602 | |||
2603 | /* | ||
2604 | * First make sure we're not already connected. | ||
2605 | */ | ||
2606 | |||
2607 | if (strip_info && strip_info->magic == STRIP_MAGIC) | ||
2608 | return -EEXIST; | ||
2609 | |||
2610 | /* | ||
2611 | * We need a write method. | ||
2612 | */ | ||
2613 | |||
2614 | if (tty->ops->write == NULL || tty->ops->set_termios == NULL) | ||
2615 | return -EOPNOTSUPP; | ||
2616 | |||
2617 | /* | ||
2618 | * OK. Find a free STRIP channel to use. | ||
2619 | */ | ||
2620 | if ((strip_info = strip_alloc()) == NULL) | ||
2621 | return -ENFILE; | ||
2622 | |||
2623 | /* | ||
2624 | * Register our newly created device so it can be ifconfig'd | ||
2625 | * strip_dev_init() will be called as a side-effect | ||
2626 | */ | ||
2627 | |||
2628 | if (register_netdev(strip_info->dev) != 0) { | ||
2629 | printk(KERN_ERR "strip: register_netdev() failed.\n"); | ||
2630 | strip_free(strip_info); | ||
2631 | return -ENFILE; | ||
2632 | } | ||
2633 | |||
2634 | strip_info->tty = tty; | ||
2635 | tty->disc_data = strip_info; | ||
2636 | tty->receive_room = 65536; | ||
2637 | |||
2638 | tty_driver_flush_buffer(tty); | ||
2639 | |||
2640 | /* | ||
2641 | * Restore default settings | ||
2642 | */ | ||
2643 | |||
2644 | strip_info->dev->type = ARPHRD_METRICOM; /* dtang */ | ||
2645 | |||
2646 | /* | ||
2647 | * Set tty options | ||
2648 | */ | ||
2649 | |||
2650 | tty->termios->c_iflag |= IGNBRK | IGNPAR; /* Ignore breaks and parity errors. */ | ||
2651 | tty->termios->c_cflag |= CLOCAL; /* Ignore modem control signals. */ | ||
2652 | tty->termios->c_cflag &= ~HUPCL; /* Don't close on hup */ | ||
2653 | |||
2654 | printk(KERN_INFO "STRIP: device \"%s\" activated\n", | ||
2655 | strip_info->dev->name); | ||
2656 | |||
2657 | /* | ||
2658 | * Done. We have linked the TTY line to a channel. | ||
2659 | */ | ||
2660 | return (strip_info->dev->base_addr); | ||
2661 | } | ||
2662 | |||
2663 | /* | ||
2664 | * Close down a STRIP channel. | ||
2665 | * This means flushing out any pending queues, and then restoring the | ||
2666 | * TTY line discipline to what it was before it got hooked to STRIP | ||
2667 | * (which usually is TTY again). | ||
2668 | */ | ||
2669 | |||
2670 | static void strip_close(struct tty_struct *tty) | ||
2671 | { | ||
2672 | struct strip *strip_info = (struct strip *) tty->disc_data; | ||
2673 | |||
2674 | /* | ||
2675 | * First make sure we're connected. | ||
2676 | */ | ||
2677 | |||
2678 | if (!strip_info || strip_info->magic != STRIP_MAGIC) | ||
2679 | return; | ||
2680 | |||
2681 | unregister_netdev(strip_info->dev); | ||
2682 | |||
2683 | tty->disc_data = NULL; | ||
2684 | strip_info->tty = NULL; | ||
2685 | printk(KERN_INFO "STRIP: device \"%s\" closed down\n", | ||
2686 | strip_info->dev->name); | ||
2687 | strip_free(strip_info); | ||
2688 | tty->disc_data = NULL; | ||
2689 | } | ||
2690 | |||
2691 | |||
2692 | /************************************************************************/ | ||
2693 | /* Perform I/O control calls on an active STRIP channel. */ | ||
2694 | |||
2695 | static int strip_ioctl(struct tty_struct *tty, struct file *file, | ||
2696 | unsigned int cmd, unsigned long arg) | ||
2697 | { | ||
2698 | struct strip *strip_info = (struct strip *) tty->disc_data; | ||
2699 | |||
2700 | /* | ||
2701 | * First make sure we're connected. | ||
2702 | */ | ||
2703 | |||
2704 | if (!strip_info || strip_info->magic != STRIP_MAGIC) | ||
2705 | return -EINVAL; | ||
2706 | |||
2707 | switch (cmd) { | ||
2708 | case SIOCGIFNAME: | ||
2709 | if(copy_to_user((void __user *) arg, strip_info->dev->name, strlen(strip_info->dev->name) + 1)) | ||
2710 | return -EFAULT; | ||
2711 | break; | ||
2712 | case SIOCSIFHWADDR: | ||
2713 | { | ||
2714 | MetricomAddress addr; | ||
2715 | //printk(KERN_INFO "%s: SIOCSIFHWADDR\n", strip_info->dev->name); | ||
2716 | if(copy_from_user(&addr, (void __user *) arg, sizeof(MetricomAddress))) | ||
2717 | return -EFAULT; | ||
2718 | return set_mac_address(strip_info, &addr); | ||
2719 | } | ||
2720 | default: | ||
2721 | return tty_mode_ioctl(tty, file, cmd, arg); | ||
2722 | break; | ||
2723 | } | ||
2724 | return 0; | ||
2725 | } | ||
2726 | |||
2727 | |||
2728 | /************************************************************************/ | ||
2729 | /* Initialization */ | ||
2730 | |||
2731 | static struct tty_ldisc strip_ldisc = { | ||
2732 | .magic = TTY_LDISC_MAGIC, | ||
2733 | .name = "strip", | ||
2734 | .owner = THIS_MODULE, | ||
2735 | .open = strip_open, | ||
2736 | .close = strip_close, | ||
2737 | .ioctl = strip_ioctl, | ||
2738 | .receive_buf = strip_receive_buf, | ||
2739 | .write_wakeup = strip_write_some_more, | ||
2740 | }; | ||
2741 | |||
2742 | /* | ||
2743 | * Initialize the STRIP driver. | ||
2744 | * This routine is called at boot time, to bootstrap the multi-channel | ||
2745 | * STRIP driver | ||
2746 | */ | ||
2747 | |||
2748 | static char signon[] __initdata = | ||
2749 | KERN_INFO "STRIP: Version %s (unlimited channels)\n"; | ||
2750 | |||
2751 | static int __init strip_init_driver(void) | ||
2752 | { | ||
2753 | int status; | ||
2754 | |||
2755 | printk(signon, StripVersion); | ||
2756 | |||
2757 | |||
2758 | /* | ||
2759 | * Fill in our line protocol discipline, and register it | ||
2760 | */ | ||
2761 | if ((status = tty_register_ldisc(N_STRIP, &strip_ldisc))) | ||
2762 | printk(KERN_ERR "STRIP: can't register line discipline (err = %d)\n", | ||
2763 | status); | ||
2764 | |||
2765 | /* | ||
2766 | * Register the status file with /proc | ||
2767 | */ | ||
2768 | proc_net_fops_create(&init_net, "strip", S_IFREG | S_IRUGO, &strip_seq_fops); | ||
2769 | |||
2770 | return status; | ||
2771 | } | ||
2772 | |||
2773 | module_init(strip_init_driver); | ||
2774 | |||
2775 | static const char signoff[] __exitdata = | ||
2776 | KERN_INFO "STRIP: Module Unloaded\n"; | ||
2777 | |||
2778 | static void __exit strip_exit_driver(void) | ||
2779 | { | ||
2780 | int i; | ||
2781 | struct list_head *p,*n; | ||
2782 | |||
2783 | /* module ref count rules assure that all entries are unregistered */ | ||
2784 | list_for_each_safe(p, n, &strip_list) { | ||
2785 | struct strip *s = list_entry(p, struct strip, list); | ||
2786 | strip_free(s); | ||
2787 | } | ||
2788 | |||
2789 | /* Unregister with the /proc/net file here. */ | ||
2790 | proc_net_remove(&init_net, "strip"); | ||
2791 | |||
2792 | if ((i = tty_unregister_ldisc(N_STRIP))) | ||
2793 | printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i); | ||
2794 | |||
2795 | printk(signoff); | ||
2796 | } | ||
2797 | |||
2798 | module_exit(strip_exit_driver); | ||
2799 | |||
2800 | MODULE_AUTHOR("Stuart Cheshire <cheshire@cs.stanford.edu>"); | ||
2801 | MODULE_DESCRIPTION("Starmode Radio IP (STRIP) Device Driver"); | ||
2802 | MODULE_LICENSE("Dual BSD/GPL"); | ||
2803 | |||
2804 | MODULE_SUPPORTED_DEVICE("Starmode Radio IP (STRIP) modem"); | ||
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 42a36b3f3ff7..377141995e36 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -1624,25 +1624,25 @@ static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1624 | iwe.cmd = SIOCGIWAP; | 1624 | iwe.cmd = SIOCGIWAP; |
1625 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 1625 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
1626 | memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN); | 1626 | memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN); |
1627 | current_ev = iwe_stream_add_event(current_ev, | 1627 | current_ev = iwe_stream_add_event(info, current_ev, |
1628 | extra + IW_SCAN_MAX_DATA, | 1628 | extra + IW_SCAN_MAX_DATA, |
1629 | &iwe, IW_EV_ADDR_LEN); | 1629 | &iwe, IW_EV_ADDR_LEN); |
1630 | iwe.cmd = SIOCGIWESSID; | 1630 | iwe.cmd = SIOCGIWESSID; |
1631 | iwe.u.data.flags = 1; | 1631 | iwe.u.data.flags = 1; |
1632 | iwe.u.data.length = this->bss_set[i].ssid.el.len; | 1632 | iwe.u.data.length = this->bss_set[i].ssid.el.len; |
1633 | current_ev = iwe_stream_add_point(current_ev, | 1633 | current_ev = iwe_stream_add_point(info, current_ev, |
1634 | extra + IW_SCAN_MAX_DATA, | 1634 | extra + IW_SCAN_MAX_DATA, |
1635 | &iwe, | 1635 | &iwe, |
1636 | this->bss_set[i].ssid.essid); | 1636 | this->bss_set[i].ssid.essid); |
1637 | iwe.cmd = SIOCGIWMODE; | 1637 | iwe.cmd = SIOCGIWMODE; |
1638 | iwe.u.mode = this->bss_set[i].bss_type; | 1638 | iwe.u.mode = this->bss_set[i].bss_type; |
1639 | current_ev = iwe_stream_add_event(current_ev, | 1639 | current_ev = iwe_stream_add_event(info, current_ev, |
1640 | extra + IW_SCAN_MAX_DATA, | 1640 | extra + IW_SCAN_MAX_DATA, |
1641 | &iwe, IW_EV_UINT_LEN); | 1641 | &iwe, IW_EV_UINT_LEN); |
1642 | iwe.cmd = SIOCGIWFREQ; | 1642 | iwe.cmd = SIOCGIWFREQ; |
1643 | iwe.u.freq.m = this->bss_set[i].ds_pset.chan; | 1643 | iwe.u.freq.m = this->bss_set[i].ds_pset.chan; |
1644 | iwe.u.freq.e = 0; | 1644 | iwe.u.freq.e = 0; |
1645 | current_ev = iwe_stream_add_event(current_ev, | 1645 | current_ev = iwe_stream_add_event(info, current_ev, |
1646 | extra + IW_SCAN_MAX_DATA, | 1646 | extra + IW_SCAN_MAX_DATA, |
1647 | &iwe, IW_EV_FREQ_LEN); | 1647 | &iwe, IW_EV_FREQ_LEN); |
1648 | iwe.cmd = SIOCGIWENCODE; | 1648 | iwe.cmd = SIOCGIWENCODE; |
@@ -1651,7 +1651,7 @@ static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1651 | else | 1651 | else |
1652 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 1652 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
1653 | iwe.u.data.length = 0; | 1653 | iwe.u.data.length = 0; |
1654 | current_ev = iwe_stream_add_point(current_ev, | 1654 | current_ev = iwe_stream_add_point(info, current_ev, |
1655 | extra + IW_SCAN_MAX_DATA, | 1655 | extra + IW_SCAN_MAX_DATA, |
1656 | &iwe, NULL); | 1656 | &iwe, NULL); |
1657 | } | 1657 | } |
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index d5c0c66188ca..07e4d1f73207 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c | |||
@@ -1152,32 +1152,36 @@ static int zd1201_get_scan(struct net_device *dev, | |||
1152 | iwe.cmd = SIOCGIWAP; | 1152 | iwe.cmd = SIOCGIWAP; |
1153 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 1153 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
1154 | memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); | 1154 | memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); |
1155 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); | 1155 | cev = iwe_stream_add_event(info, cev, end_buf, |
1156 | &iwe, IW_EV_ADDR_LEN); | ||
1156 | 1157 | ||
1157 | iwe.cmd = SIOCGIWESSID; | 1158 | iwe.cmd = SIOCGIWESSID; |
1158 | iwe.u.data.length = zd->rxdata[i+16]; | 1159 | iwe.u.data.length = zd->rxdata[i+16]; |
1159 | iwe.u.data.flags = 1; | 1160 | iwe.u.data.flags = 1; |
1160 | cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); | 1161 | cev = iwe_stream_add_point(info, cev, end_buf, |
1162 | &iwe, zd->rxdata+i+18); | ||
1161 | 1163 | ||
1162 | iwe.cmd = SIOCGIWMODE; | 1164 | iwe.cmd = SIOCGIWMODE; |
1163 | if (zd->rxdata[i+14]&0x01) | 1165 | if (zd->rxdata[i+14]&0x01) |
1164 | iwe.u.mode = IW_MODE_MASTER; | 1166 | iwe.u.mode = IW_MODE_MASTER; |
1165 | else | 1167 | else |
1166 | iwe.u.mode = IW_MODE_ADHOC; | 1168 | iwe.u.mode = IW_MODE_ADHOC; |
1167 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); | 1169 | cev = iwe_stream_add_event(info, cev, end_buf, |
1170 | &iwe, IW_EV_UINT_LEN); | ||
1168 | 1171 | ||
1169 | iwe.cmd = SIOCGIWFREQ; | 1172 | iwe.cmd = SIOCGIWFREQ; |
1170 | iwe.u.freq.m = zd->rxdata[i+0]; | 1173 | iwe.u.freq.m = zd->rxdata[i+0]; |
1171 | iwe.u.freq.e = 0; | 1174 | iwe.u.freq.e = 0; |
1172 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); | 1175 | cev = iwe_stream_add_event(info, cev, end_buf, |
1176 | &iwe, IW_EV_FREQ_LEN); | ||
1173 | 1177 | ||
1174 | iwe.cmd = SIOCGIWRATE; | 1178 | iwe.cmd = SIOCGIWRATE; |
1175 | iwe.u.bitrate.fixed = 0; | 1179 | iwe.u.bitrate.fixed = 0; |
1176 | iwe.u.bitrate.disabled = 0; | 1180 | iwe.u.bitrate.disabled = 0; |
1177 | for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { | 1181 | for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { |
1178 | iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; | 1182 | iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; |
1179 | cev=iwe_stream_add_event(cev, end_buf, &iwe, | 1183 | cev = iwe_stream_add_event(info, cev, end_buf, |
1180 | IW_EV_PARAM_LEN); | 1184 | &iwe, IW_EV_PARAM_LEN); |
1181 | } | 1185 | } |
1182 | 1186 | ||
1183 | iwe.cmd = SIOCGIWENCODE; | 1187 | iwe.cmd = SIOCGIWENCODE; |
@@ -1186,14 +1190,15 @@ static int zd1201_get_scan(struct net_device *dev, | |||
1186 | iwe.u.data.flags = IW_ENCODE_ENABLED; | 1190 | iwe.u.data.flags = IW_ENCODE_ENABLED; |
1187 | else | 1191 | else |
1188 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 1192 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
1189 | cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); | 1193 | cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL); |
1190 | 1194 | ||
1191 | iwe.cmd = IWEVQUAL; | 1195 | iwe.cmd = IWEVQUAL; |
1192 | iwe.u.qual.qual = zd->rxdata[i+4]; | 1196 | iwe.u.qual.qual = zd->rxdata[i+4]; |
1193 | iwe.u.qual.noise= zd->rxdata[i+2]/10-100; | 1197 | iwe.u.qual.noise= zd->rxdata[i+2]/10-100; |
1194 | iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; | 1198 | iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; |
1195 | iwe.u.qual.updated = 7; | 1199 | iwe.u.qual.updated = 7; |
1196 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); | 1200 | cev = iwe_stream_add_event(info, cev, end_buf, |
1201 | &iwe, IW_EV_QUAL_LEN); | ||
1197 | } | 1202 | } |
1198 | 1203 | ||
1199 | if (!enabled_save) | 1204 | if (!enabled_save) |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6d86b365f150..317c5e24f80c 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -376,8 +376,6 @@ static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length) | |||
376 | static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | 376 | static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, |
377 | struct ieee80211_hdr *header, u32 flags) | 377 | struct ieee80211_hdr *header, u32 flags) |
378 | { | 378 | { |
379 | u16 fctl = le16_to_cpu(header->frame_control); | ||
380 | |||
381 | /* | 379 | /* |
382 | * CONTROL TODO: | 380 | * CONTROL TODO: |
383 | * - if backoff needed, enable bit 0 | 381 | * - if backoff needed, enable bit 0 |
@@ -395,8 +393,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
395 | cs->control |= ZD_CS_MULTICAST; | 393 | cs->control |= ZD_CS_MULTICAST; |
396 | 394 | ||
397 | /* PS-POLL */ | 395 | /* PS-POLL */ |
398 | if ((fctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) == | 396 | if (ieee80211_is_pspoll(header->frame_control)) |
399 | (IEEE80211_FTYPE_CTL|IEEE80211_STYPE_PSPOLL)) | ||
400 | cs->control |= ZD_CS_PS_POLL_FRAME; | 397 | cs->control |= ZD_CS_PS_POLL_FRAME; |
401 | 398 | ||
402 | if (flags & IEEE80211_TX_CTL_USE_RTS_CTS) | 399 | if (flags & IEEE80211_TX_CTL_USE_RTS_CTS) |
@@ -550,13 +547,11 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
550 | static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, | 547 | static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, |
551 | struct ieee80211_rx_status *stats) | 548 | struct ieee80211_rx_status *stats) |
552 | { | 549 | { |
553 | u16 fc = le16_to_cpu(rx_hdr->frame_control); | ||
554 | struct sk_buff *skb; | 550 | struct sk_buff *skb; |
555 | struct sk_buff_head *q; | 551 | struct sk_buff_head *q; |
556 | unsigned long flags; | 552 | unsigned long flags; |
557 | 553 | ||
558 | if ((fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) != | 554 | if (!ieee80211_is_ack(rx_hdr->frame_control)) |
559 | (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK)) | ||
560 | return 0; | 555 | return 0; |
561 | 556 | ||
562 | q = &zd_hw_mac(hw)->ack_wait_queue; | 557 | q = &zd_hw_mac(hw)->ack_wait_queue; |
@@ -584,8 +579,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
584 | const struct rx_status *status; | 579 | const struct rx_status *status; |
585 | struct sk_buff *skb; | 580 | struct sk_buff *skb; |
586 | int bad_frame = 0; | 581 | int bad_frame = 0; |
587 | u16 fc; | 582 | __le16 fc; |
588 | bool is_qos, is_4addr, need_padding; | 583 | int need_padding; |
589 | int i; | 584 | int i; |
590 | u8 rate; | 585 | u8 rate; |
591 | 586 | ||
@@ -644,13 +639,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
644 | && !mac->pass_ctrl) | 639 | && !mac->pass_ctrl) |
645 | return 0; | 640 | return 0; |
646 | 641 | ||
647 | fc = le16_to_cpu(*((__le16 *) buffer)); | 642 | fc = *(__le16 *)buffer; |
648 | 643 | need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc); | |
649 | is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | ||
650 | (fc & IEEE80211_STYPE_QOS_DATA); | ||
651 | is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | ||
652 | (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); | ||
653 | need_padding = is_qos ^ is_4addr; | ||
654 | 644 | ||
655 | skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); | 645 | skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); |
656 | if (skb == NULL) | 646 | if (skb == NULL) |
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index cd845b8acd17..307b1f62d949 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig | |||
@@ -2,7 +2,7 @@ menu "Sonics Silicon Backplane" | |||
2 | 2 | ||
3 | config SSB_POSSIBLE | 3 | config SSB_POSSIBLE |
4 | bool | 4 | bool |
5 | depends on HAS_IOMEM | 5 | depends on HAS_IOMEM && HAS_DMA |
6 | default y | 6 | default y |
7 | 7 | ||
8 | config SSB | 8 | config SSB |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index d184f2aea78d..d831a2beff39 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -462,18 +462,15 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
462 | #ifdef CONFIG_SSB_PCIHOST | 462 | #ifdef CONFIG_SSB_PCIHOST |
463 | sdev->irq = bus->host_pci->irq; | 463 | sdev->irq = bus->host_pci->irq; |
464 | dev->parent = &bus->host_pci->dev; | 464 | dev->parent = &bus->host_pci->dev; |
465 | sdev->dma_dev = &bus->host_pci->dev; | ||
466 | #endif | 465 | #endif |
467 | break; | 466 | break; |
468 | case SSB_BUSTYPE_PCMCIA: | 467 | case SSB_BUSTYPE_PCMCIA: |
469 | #ifdef CONFIG_SSB_PCMCIAHOST | 468 | #ifdef CONFIG_SSB_PCMCIAHOST |
470 | sdev->irq = bus->host_pcmcia->irq.AssignedIRQ; | 469 | sdev->irq = bus->host_pcmcia->irq.AssignedIRQ; |
471 | dev->parent = &bus->host_pcmcia->dev; | 470 | dev->parent = &bus->host_pcmcia->dev; |
472 | sdev->dma_dev = &bus->host_pcmcia->dev; | ||
473 | #endif | 471 | #endif |
474 | break; | 472 | break; |
475 | case SSB_BUSTYPE_SSB: | 473 | case SSB_BUSTYPE_SSB: |
476 | sdev->dma_dev = dev; | ||
477 | break; | 474 | break; |
478 | } | 475 | } |
479 | 476 | ||
@@ -1156,36 +1153,82 @@ u32 ssb_dma_translation(struct ssb_device *dev) | |||
1156 | { | 1153 | { |
1157 | switch (dev->bus->bustype) { | 1154 | switch (dev->bus->bustype) { |
1158 | case SSB_BUSTYPE_SSB: | 1155 | case SSB_BUSTYPE_SSB: |
1159 | case SSB_BUSTYPE_PCMCIA: | ||
1160 | return 0; | 1156 | return 0; |
1161 | case SSB_BUSTYPE_PCI: | 1157 | case SSB_BUSTYPE_PCI: |
1162 | return SSB_PCI_DMA; | 1158 | return SSB_PCI_DMA; |
1159 | default: | ||
1160 | __ssb_dma_not_implemented(dev); | ||
1163 | } | 1161 | } |
1164 | return 0; | 1162 | return 0; |
1165 | } | 1163 | } |
1166 | EXPORT_SYMBOL(ssb_dma_translation); | 1164 | EXPORT_SYMBOL(ssb_dma_translation); |
1167 | 1165 | ||
1168 | int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask) | 1166 | int ssb_dma_set_mask(struct ssb_device *dev, u64 mask) |
1169 | { | 1167 | { |
1170 | struct device *dma_dev = ssb_dev->dma_dev; | 1168 | int err; |
1171 | int err = 0; | ||
1172 | 1169 | ||
1173 | #ifdef CONFIG_SSB_PCIHOST | 1170 | switch (dev->bus->bustype) { |
1174 | if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI) { | 1171 | case SSB_BUSTYPE_PCI: |
1175 | err = pci_set_dma_mask(ssb_dev->bus->host_pci, mask); | 1172 | err = pci_set_dma_mask(dev->bus->host_pci, mask); |
1176 | if (err) | 1173 | if (err) |
1177 | return err; | 1174 | return err; |
1178 | err = pci_set_consistent_dma_mask(ssb_dev->bus->host_pci, mask); | 1175 | err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask); |
1179 | return err; | 1176 | return err; |
1177 | case SSB_BUSTYPE_SSB: | ||
1178 | return dma_set_mask(dev->dev, mask); | ||
1179 | default: | ||
1180 | __ssb_dma_not_implemented(dev); | ||
1180 | } | 1181 | } |
1181 | #endif | 1182 | return -ENOSYS; |
1182 | dma_dev->coherent_dma_mask = mask; | ||
1183 | dma_dev->dma_mask = &dma_dev->coherent_dma_mask; | ||
1184 | |||
1185 | return err; | ||
1186 | } | 1183 | } |
1187 | EXPORT_SYMBOL(ssb_dma_set_mask); | 1184 | EXPORT_SYMBOL(ssb_dma_set_mask); |
1188 | 1185 | ||
1186 | void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, | ||
1187 | dma_addr_t *dma_handle, gfp_t gfp_flags) | ||
1188 | { | ||
1189 | switch (dev->bus->bustype) { | ||
1190 | case SSB_BUSTYPE_PCI: | ||
1191 | if (gfp_flags & GFP_DMA) { | ||
1192 | /* Workaround: The PCI API does not support passing | ||
1193 | * a GFP flag. */ | ||
1194 | return dma_alloc_coherent(&dev->bus->host_pci->dev, | ||
1195 | size, dma_handle, gfp_flags); | ||
1196 | } | ||
1197 | return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle); | ||
1198 | case SSB_BUSTYPE_SSB: | ||
1199 | return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags); | ||
1200 | default: | ||
1201 | __ssb_dma_not_implemented(dev); | ||
1202 | } | ||
1203 | return NULL; | ||
1204 | } | ||
1205 | EXPORT_SYMBOL(ssb_dma_alloc_consistent); | ||
1206 | |||
1207 | void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, | ||
1208 | void *vaddr, dma_addr_t dma_handle, | ||
1209 | gfp_t gfp_flags) | ||
1210 | { | ||
1211 | switch (dev->bus->bustype) { | ||
1212 | case SSB_BUSTYPE_PCI: | ||
1213 | if (gfp_flags & GFP_DMA) { | ||
1214 | /* Workaround: The PCI API does not support passing | ||
1215 | * a GFP flag. */ | ||
1216 | dma_free_coherent(&dev->bus->host_pci->dev, | ||
1217 | size, vaddr, dma_handle); | ||
1218 | return; | ||
1219 | } | ||
1220 | pci_free_consistent(dev->bus->host_pci, size, | ||
1221 | vaddr, dma_handle); | ||
1222 | return; | ||
1223 | case SSB_BUSTYPE_SSB: | ||
1224 | dma_free_coherent(dev->dev, size, vaddr, dma_handle); | ||
1225 | return; | ||
1226 | default: | ||
1227 | __ssb_dma_not_implemented(dev); | ||
1228 | } | ||
1229 | } | ||
1230 | EXPORT_SYMBOL(ssb_dma_free_consistent); | ||
1231 | |||
1189 | int ssb_bus_may_powerdown(struct ssb_bus *bus) | 1232 | int ssb_bus_may_powerdown(struct ssb_bus *bus) |
1190 | { | 1233 | { |
1191 | struct ssb_chipcommon *cc; | 1234 | struct ssb_chipcommon *cc; |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 97dba0d92348..05ec7eef8690 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -58,7 +58,6 @@ | |||
58 | #include <linux/syscalls.h> | 58 | #include <linux/syscalls.h> |
59 | #include <linux/i2c.h> | 59 | #include <linux/i2c.h> |
60 | #include <linux/i2c-dev.h> | 60 | #include <linux/i2c-dev.h> |
61 | #include <linux/wireless.h> | ||
62 | #include <linux/atalk.h> | 61 | #include <linux/atalk.h> |
63 | #include <linux/loop.h> | 62 | #include <linux/loop.h> |
64 | 63 | ||
@@ -1757,64 +1756,6 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long a | |||
1757 | return sys_ioctl(fd, cmd, (unsigned long)tdata); | 1756 | return sys_ioctl(fd, cmd, (unsigned long)tdata); |
1758 | } | 1757 | } |
1759 | 1758 | ||
1760 | struct compat_iw_point { | ||
1761 | compat_caddr_t pointer; | ||
1762 | __u16 length; | ||
1763 | __u16 flags; | ||
1764 | }; | ||
1765 | |||
1766 | static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
1767 | { | ||
1768 | struct iwreq __user *iwr; | ||
1769 | struct iwreq __user *iwr_u; | ||
1770 | struct iw_point __user *iwp; | ||
1771 | struct compat_iw_point __user *iwp_u; | ||
1772 | compat_caddr_t pointer_u; | ||
1773 | void __user *pointer; | ||
1774 | __u16 length, flags; | ||
1775 | int ret; | ||
1776 | |||
1777 | iwr_u = compat_ptr(arg); | ||
1778 | iwp_u = (struct compat_iw_point __user *) &iwr_u->u.data; | ||
1779 | iwr = compat_alloc_user_space(sizeof(*iwr)); | ||
1780 | if (iwr == NULL) | ||
1781 | return -ENOMEM; | ||
1782 | |||
1783 | iwp = &iwr->u.data; | ||
1784 | |||
1785 | if (!access_ok(VERIFY_WRITE, iwr, sizeof(*iwr))) | ||
1786 | return -EFAULT; | ||
1787 | |||
1788 | if (__copy_in_user(&iwr->ifr_ifrn.ifrn_name[0], | ||
1789 | &iwr_u->ifr_ifrn.ifrn_name[0], | ||
1790 | sizeof(iwr->ifr_ifrn.ifrn_name))) | ||
1791 | return -EFAULT; | ||
1792 | |||
1793 | if (__get_user(pointer_u, &iwp_u->pointer) || | ||
1794 | __get_user(length, &iwp_u->length) || | ||
1795 | __get_user(flags, &iwp_u->flags)) | ||
1796 | return -EFAULT; | ||
1797 | |||
1798 | if (__put_user(compat_ptr(pointer_u), &iwp->pointer) || | ||
1799 | __put_user(length, &iwp->length) || | ||
1800 | __put_user(flags, &iwp->flags)) | ||
1801 | return -EFAULT; | ||
1802 | |||
1803 | ret = sys_ioctl(fd, cmd, (unsigned long) iwr); | ||
1804 | |||
1805 | if (__get_user(pointer, &iwp->pointer) || | ||
1806 | __get_user(length, &iwp->length) || | ||
1807 | __get_user(flags, &iwp->flags)) | ||
1808 | return -EFAULT; | ||
1809 | |||
1810 | if (__put_user(ptr_to_compat(pointer), &iwp_u->pointer) || | ||
1811 | __put_user(length, &iwp_u->length) || | ||
1812 | __put_user(flags, &iwp_u->flags)) | ||
1813 | return -EFAULT; | ||
1814 | |||
1815 | return ret; | ||
1816 | } | ||
1817 | |||
1818 | /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE | 1759 | /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE |
1819 | * for some operations; this forces use of the newer bridge-utils that | 1760 | * for some operations; this forces use of the newer bridge-utils that |
1820 | * use compatiable ioctls | 1761 | * use compatiable ioctls |
@@ -2495,36 +2436,6 @@ COMPATIBLE_IOCTL(I2C_TENBIT) | |||
2495 | COMPATIBLE_IOCTL(I2C_PEC) | 2436 | COMPATIBLE_IOCTL(I2C_PEC) |
2496 | COMPATIBLE_IOCTL(I2C_RETRIES) | 2437 | COMPATIBLE_IOCTL(I2C_RETRIES) |
2497 | COMPATIBLE_IOCTL(I2C_TIMEOUT) | 2438 | COMPATIBLE_IOCTL(I2C_TIMEOUT) |
2498 | /* wireless */ | ||
2499 | COMPATIBLE_IOCTL(SIOCSIWCOMMIT) | ||
2500 | COMPATIBLE_IOCTL(SIOCGIWNAME) | ||
2501 | COMPATIBLE_IOCTL(SIOCSIWNWID) | ||
2502 | COMPATIBLE_IOCTL(SIOCGIWNWID) | ||
2503 | COMPATIBLE_IOCTL(SIOCSIWFREQ) | ||
2504 | COMPATIBLE_IOCTL(SIOCGIWFREQ) | ||
2505 | COMPATIBLE_IOCTL(SIOCSIWMODE) | ||
2506 | COMPATIBLE_IOCTL(SIOCGIWMODE) | ||
2507 | COMPATIBLE_IOCTL(SIOCSIWSENS) | ||
2508 | COMPATIBLE_IOCTL(SIOCGIWSENS) | ||
2509 | COMPATIBLE_IOCTL(SIOCSIWRANGE) | ||
2510 | COMPATIBLE_IOCTL(SIOCSIWPRIV) | ||
2511 | COMPATIBLE_IOCTL(SIOCSIWSTATS) | ||
2512 | COMPATIBLE_IOCTL(SIOCSIWAP) | ||
2513 | COMPATIBLE_IOCTL(SIOCGIWAP) | ||
2514 | COMPATIBLE_IOCTL(SIOCSIWRATE) | ||
2515 | COMPATIBLE_IOCTL(SIOCGIWRATE) | ||
2516 | COMPATIBLE_IOCTL(SIOCSIWRTS) | ||
2517 | COMPATIBLE_IOCTL(SIOCGIWRTS) | ||
2518 | COMPATIBLE_IOCTL(SIOCSIWFRAG) | ||
2519 | COMPATIBLE_IOCTL(SIOCGIWFRAG) | ||
2520 | COMPATIBLE_IOCTL(SIOCSIWTXPOW) | ||
2521 | COMPATIBLE_IOCTL(SIOCGIWTXPOW) | ||
2522 | COMPATIBLE_IOCTL(SIOCSIWRETRY) | ||
2523 | COMPATIBLE_IOCTL(SIOCGIWRETRY) | ||
2524 | COMPATIBLE_IOCTL(SIOCSIWPOWER) | ||
2525 | COMPATIBLE_IOCTL(SIOCGIWPOWER) | ||
2526 | COMPATIBLE_IOCTL(SIOCSIWAUTH) | ||
2527 | COMPATIBLE_IOCTL(SIOCGIWAUTH) | ||
2528 | /* hiddev */ | 2439 | /* hiddev */ |
2529 | COMPATIBLE_IOCTL(HIDIOCGVERSION) | 2440 | COMPATIBLE_IOCTL(HIDIOCGVERSION) |
2530 | COMPATIBLE_IOCTL(HIDIOCAPPLICATION) | 2441 | COMPATIBLE_IOCTL(HIDIOCAPPLICATION) |
@@ -2755,29 +2666,7 @@ COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) | |||
2755 | HANDLE_IOCTL(I2C_FUNCS, w_long) | 2666 | HANDLE_IOCTL(I2C_FUNCS, w_long) |
2756 | HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) | 2667 | HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) |
2757 | HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) | 2668 | HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) |
2758 | /* wireless */ | 2669 | /* bridge */ |
2759 | HANDLE_IOCTL(SIOCGIWRANGE, do_wireless_ioctl) | ||
2760 | HANDLE_IOCTL(SIOCGIWPRIV, do_wireless_ioctl) | ||
2761 | HANDLE_IOCTL(SIOCGIWSTATS, do_wireless_ioctl) | ||
2762 | HANDLE_IOCTL(SIOCSIWSPY, do_wireless_ioctl) | ||
2763 | HANDLE_IOCTL(SIOCGIWSPY, do_wireless_ioctl) | ||
2764 | HANDLE_IOCTL(SIOCSIWTHRSPY, do_wireless_ioctl) | ||
2765 | HANDLE_IOCTL(SIOCGIWTHRSPY, do_wireless_ioctl) | ||
2766 | HANDLE_IOCTL(SIOCSIWMLME, do_wireless_ioctl) | ||
2767 | HANDLE_IOCTL(SIOCGIWAPLIST, do_wireless_ioctl) | ||
2768 | HANDLE_IOCTL(SIOCSIWSCAN, do_wireless_ioctl) | ||
2769 | HANDLE_IOCTL(SIOCGIWSCAN, do_wireless_ioctl) | ||
2770 | HANDLE_IOCTL(SIOCSIWESSID, do_wireless_ioctl) | ||
2771 | HANDLE_IOCTL(SIOCGIWESSID, do_wireless_ioctl) | ||
2772 | HANDLE_IOCTL(SIOCSIWNICKN, do_wireless_ioctl) | ||
2773 | HANDLE_IOCTL(SIOCGIWNICKN, do_wireless_ioctl) | ||
2774 | HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl) | ||
2775 | HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl) | ||
2776 | HANDLE_IOCTL(SIOCSIWGENIE, do_wireless_ioctl) | ||
2777 | HANDLE_IOCTL(SIOCGIWGENIE, do_wireless_ioctl) | ||
2778 | HANDLE_IOCTL(SIOCSIWENCODEEXT, do_wireless_ioctl) | ||
2779 | HANDLE_IOCTL(SIOCGIWENCODEEXT, do_wireless_ioctl) | ||
2780 | HANDLE_IOCTL(SIOCSIWPMKSA, do_wireless_ioctl) | ||
2781 | HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) | 2670 | HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) |
2782 | HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl) | 2671 | HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl) |
2783 | /* Not implemented in the native kernel */ | 2672 | /* Not implemented in the native kernel */ |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 2998e3b5f166..cffd6d0094f9 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -469,6 +469,40 @@ struct ieee80211s_hdr { | |||
469 | u8 eaddr3[6]; | 469 | u8 eaddr3[6]; |
470 | } __attribute__ ((packed)); | 470 | } __attribute__ ((packed)); |
471 | 471 | ||
472 | /** | ||
473 | * struct ieee80211_quiet_ie | ||
474 | * | ||
475 | * This structure refers to "Quiet information element" | ||
476 | */ | ||
477 | struct ieee80211_quiet_ie { | ||
478 | u8 count; | ||
479 | u8 period; | ||
480 | __le16 duration; | ||
481 | __le16 offset; | ||
482 | } __attribute__ ((packed)); | ||
483 | |||
484 | /** | ||
485 | * struct ieee80211_msrment_ie | ||
486 | * | ||
487 | * This structure refers to "Measurement Request/Report information element" | ||
488 | */ | ||
489 | struct ieee80211_msrment_ie { | ||
490 | u8 token; | ||
491 | u8 mode; | ||
492 | u8 type; | ||
493 | u8 request[0]; | ||
494 | } __attribute__ ((packed)); | ||
495 | |||
496 | /** | ||
497 | * struct ieee80211_channel_sw_ie | ||
498 | * | ||
499 | * This structure refers to "Channel Switch Announcement information element" | ||
500 | */ | ||
501 | struct ieee80211_channel_sw_ie { | ||
502 | u8 mode; | ||
503 | u8 new_ch_num; | ||
504 | u8 count; | ||
505 | } __attribute__ ((packed)); | ||
472 | 506 | ||
473 | struct ieee80211_mgmt { | 507 | struct ieee80211_mgmt { |
474 | __le16 frame_control; | 508 | __le16 frame_control; |
@@ -544,13 +578,18 @@ struct ieee80211_mgmt { | |||
544 | u8 action_code; | 578 | u8 action_code; |
545 | u8 element_id; | 579 | u8 element_id; |
546 | u8 length; | 580 | u8 length; |
547 | u8 switch_mode; | 581 | struct ieee80211_channel_sw_ie sw_elem; |
548 | u8 new_chan; | ||
549 | u8 switch_count; | ||
550 | } __attribute__((packed)) chan_switch; | 582 | } __attribute__((packed)) chan_switch; |
551 | struct{ | 583 | struct{ |
552 | u8 action_code; | 584 | u8 action_code; |
553 | u8 dialog_token; | 585 | u8 dialog_token; |
586 | u8 element_id; | ||
587 | u8 length; | ||
588 | struct ieee80211_msrment_ie msr_elem; | ||
589 | } __attribute__((packed)) measurement; | ||
590 | struct{ | ||
591 | u8 action_code; | ||
592 | u8 dialog_token; | ||
554 | __le16 capab; | 593 | __le16 capab; |
555 | __le16 timeout; | 594 | __le16 timeout; |
556 | __le16 start_seq_num; | 595 | __le16 start_seq_num; |
@@ -700,11 +739,21 @@ struct ieee80211_ht_addt_info { | |||
700 | #define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) | 739 | #define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) |
701 | #define WLAN_CAPABILITY_PBCC (1<<6) | 740 | #define WLAN_CAPABILITY_PBCC (1<<6) |
702 | #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) | 741 | #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) |
742 | |||
703 | /* 802.11h */ | 743 | /* 802.11h */ |
704 | #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) | 744 | #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) |
705 | #define WLAN_CAPABILITY_QOS (1<<9) | 745 | #define WLAN_CAPABILITY_QOS (1<<9) |
706 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) | 746 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) |
707 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) | 747 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) |
748 | /* measurement */ | ||
749 | #define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) | ||
750 | #define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) | ||
751 | #define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) | ||
752 | |||
753 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 | ||
754 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 | ||
755 | #define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 | ||
756 | |||
708 | 757 | ||
709 | /* 802.11g ERP information element */ | 758 | /* 802.11g ERP information element */ |
710 | #define WLAN_ERP_NON_ERP_PRESENT (1<<0) | 759 | #define WLAN_ERP_NON_ERP_PRESENT (1<<0) |
@@ -875,6 +924,15 @@ enum ieee80211_category { | |||
875 | WLAN_CATEGORY_WMM = 17, | 924 | WLAN_CATEGORY_WMM = 17, |
876 | }; | 925 | }; |
877 | 926 | ||
927 | /* SPECTRUM_MGMT action code */ | ||
928 | enum ieee80211_spectrum_mgmt_actioncode { | ||
929 | WLAN_ACTION_SPCT_MSR_REQ = 0, | ||
930 | WLAN_ACTION_SPCT_MSR_RPRT = 1, | ||
931 | WLAN_ACTION_SPCT_TPC_REQ = 2, | ||
932 | WLAN_ACTION_SPCT_TPC_RPRT = 3, | ||
933 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, | ||
934 | }; | ||
935 | |||
878 | /* BACK action code */ | 936 | /* BACK action code */ |
879 | enum ieee80211_back_actioncode { | 937 | enum ieee80211_back_actioncode { |
880 | WLAN_ACTION_ADDBA_REQ = 0, | 938 | WLAN_ACTION_ADDBA_REQ = 0, |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index aa8411e2a160..2be7c63bc0f2 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -241,7 +241,10 @@ enum nl80211_attrs { | |||
241 | NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 | 241 | NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 |
242 | }; | 242 | }; |
243 | 243 | ||
244 | #define NL80211_MAX_SUPP_RATES 32 | 244 | #define NL80211_MAX_SUPP_RATES 32 |
245 | #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 | ||
246 | #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 | ||
247 | #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 | ||
245 | 248 | ||
246 | /** | 249 | /** |
247 | * enum nl80211_iftype - (virtual) interface types | 250 | * enum nl80211_iftype - (virtual) interface types |
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index e3ab21d7fc7f..c5f6e54ec6ae 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h | |||
@@ -34,26 +34,37 @@ | |||
34 | * RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. | 34 | * RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. |
35 | * RFKILL_TYPE_UWB: switch is on a ultra wideband device. | 35 | * RFKILL_TYPE_UWB: switch is on a ultra wideband device. |
36 | * RFKILL_TYPE_WIMAX: switch is on a WiMAX device. | 36 | * RFKILL_TYPE_WIMAX: switch is on a WiMAX device. |
37 | * RFKILL_TYPE_WWAN: switch is on a wireless WAN device. | ||
37 | */ | 38 | */ |
38 | enum rfkill_type { | 39 | enum rfkill_type { |
39 | RFKILL_TYPE_WLAN , | 40 | RFKILL_TYPE_WLAN , |
40 | RFKILL_TYPE_BLUETOOTH, | 41 | RFKILL_TYPE_BLUETOOTH, |
41 | RFKILL_TYPE_UWB, | 42 | RFKILL_TYPE_UWB, |
42 | RFKILL_TYPE_WIMAX, | 43 | RFKILL_TYPE_WIMAX, |
44 | RFKILL_TYPE_WWAN, | ||
43 | RFKILL_TYPE_MAX, | 45 | RFKILL_TYPE_MAX, |
44 | }; | 46 | }; |
45 | 47 | ||
46 | enum rfkill_state { | 48 | enum rfkill_state { |
47 | RFKILL_STATE_OFF = 0, | 49 | RFKILL_STATE_SOFT_BLOCKED = 0, /* Radio output blocked */ |
48 | RFKILL_STATE_ON = 1, | 50 | RFKILL_STATE_UNBLOCKED = 1, /* Radio output allowed */ |
51 | RFKILL_STATE_HARD_BLOCKED = 2, /* Output blocked, non-overrideable */ | ||
49 | }; | 52 | }; |
50 | 53 | ||
54 | /* | ||
55 | * These are DEPRECATED, drivers using them should be verified to | ||
56 | * comply with the rfkill usage guidelines in Documentation/rfkill.txt | ||
57 | * and then converted to use the new names for rfkill_state | ||
58 | */ | ||
59 | #define RFKILL_STATE_OFF RFKILL_STATE_SOFT_BLOCKED | ||
60 | #define RFKILL_STATE_ON RFKILL_STATE_UNBLOCKED | ||
61 | |||
51 | /** | 62 | /** |
52 | * struct rfkill - rfkill control structure. | 63 | * struct rfkill - rfkill control structure. |
53 | * @name: Name of the switch. | 64 | * @name: Name of the switch. |
54 | * @type: Radio type which the button controls, the value stored | 65 | * @type: Radio type which the button controls, the value stored |
55 | * here should be a value from enum rfkill_type. | 66 | * here should be a value from enum rfkill_type. |
56 | * @state: State of the switch (on/off). | 67 | * @state: State of the switch, "UNBLOCKED" means radio can operate. |
57 | * @user_claim_unsupported: Whether the hardware supports exclusive | 68 | * @user_claim_unsupported: Whether the hardware supports exclusive |
58 | * RF-kill control by userspace. Set this before registering. | 69 | * RF-kill control by userspace. Set this before registering. |
59 | * @user_claim: Set when the switch is controlled exlusively by userspace. | 70 | * @user_claim: Set when the switch is controlled exlusively by userspace. |
@@ -61,6 +72,12 @@ enum rfkill_state { | |||
61 | * @data: Pointer to the RF button drivers private data which will be | 72 | * @data: Pointer to the RF button drivers private data which will be |
62 | * passed along when toggling radio state. | 73 | * passed along when toggling radio state. |
63 | * @toggle_radio(): Mandatory handler to control state of the radio. | 74 | * @toggle_radio(): Mandatory handler to control state of the radio. |
75 | * only RFKILL_STATE_SOFT_BLOCKED and RFKILL_STATE_UNBLOCKED are | ||
76 | * valid parameters. | ||
77 | * @get_state(): handler to read current radio state from hardware, | ||
78 | * may be called from atomic context, should return 0 on success. | ||
79 | * Either this handler OR judicious use of rfkill_force_state() is | ||
80 | * MANDATORY for any driver capable of RFKILL_STATE_HARD_BLOCKED. | ||
64 | * @led_trigger: A LED trigger for this button's LED. | 81 | * @led_trigger: A LED trigger for this button's LED. |
65 | * @dev: Device structure integrating the switch into device tree. | 82 | * @dev: Device structure integrating the switch into device tree. |
66 | * @node: Used to place switch into list of all switches known to the | 83 | * @node: Used to place switch into list of all switches known to the |
@@ -80,6 +97,7 @@ struct rfkill { | |||
80 | 97 | ||
81 | void *data; | 98 | void *data; |
82 | int (*toggle_radio)(void *data, enum rfkill_state state); | 99 | int (*toggle_radio)(void *data, enum rfkill_state state); |
100 | int (*get_state)(void *data, enum rfkill_state *state); | ||
83 | 101 | ||
84 | #ifdef CONFIG_RFKILL_LEDS | 102 | #ifdef CONFIG_RFKILL_LEDS |
85 | struct led_trigger led_trigger; | 103 | struct led_trigger led_trigger; |
@@ -95,6 +113,21 @@ void rfkill_free(struct rfkill *rfkill); | |||
95 | int rfkill_register(struct rfkill *rfkill); | 113 | int rfkill_register(struct rfkill *rfkill); |
96 | void rfkill_unregister(struct rfkill *rfkill); | 114 | void rfkill_unregister(struct rfkill *rfkill); |
97 | 115 | ||
116 | int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state); | ||
117 | |||
118 | /** | ||
119 | * rfkill_state_complement - return complementar state | ||
120 | * @state: state to return the complement of | ||
121 | * | ||
122 | * Returns RFKILL_STATE_SOFT_BLOCKED if @state is RFKILL_STATE_UNBLOCKED, | ||
123 | * returns RFKILL_STATE_UNBLOCKED otherwise. | ||
124 | */ | ||
125 | static inline enum rfkill_state rfkill_state_complement(enum rfkill_state state) | ||
126 | { | ||
127 | return (state == RFKILL_STATE_UNBLOCKED) ? | ||
128 | RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; | ||
129 | } | ||
130 | |||
98 | /** | 131 | /** |
99 | * rfkill_get_led_name - Get the LED trigger name for the button's LED. | 132 | * rfkill_get_led_name - Get the LED trigger name for the button's LED. |
100 | * This function might return a NULL pointer if registering of the | 133 | * This function might return a NULL pointer if registering of the |
@@ -110,4 +143,11 @@ static inline char *rfkill_get_led_name(struct rfkill *rfkill) | |||
110 | #endif | 143 | #endif |
111 | } | 144 | } |
112 | 145 | ||
146 | /* rfkill notification chain */ | ||
147 | #define RFKILL_STATE_CHANGED 0x0001 /* state of a normal rfkill | ||
148 | switch has changed */ | ||
149 | |||
150 | int register_rfkill_notifier(struct notifier_block *nb); | ||
151 | int unregister_rfkill_notifier(struct notifier_block *nb); | ||
152 | |||
113 | #endif /* RFKILL_H */ | 153 | #endif /* RFKILL_H */ |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 50dfd0dc4093..0fe5a0ded3ea 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -137,9 +137,6 @@ struct ssb_device { | |||
137 | const struct ssb_bus_ops *ops; | 137 | const struct ssb_bus_ops *ops; |
138 | 138 | ||
139 | struct device *dev; | 139 | struct device *dev; |
140 | /* Pointer to the device that has to be used for | ||
141 | * any DMA related operation. */ | ||
142 | struct device *dma_dev; | ||
143 | 140 | ||
144 | struct ssb_bus *bus; | 141 | struct ssb_bus *bus; |
145 | struct ssb_device_id id; | 142 | struct ssb_device_id id; |
@@ -399,13 +396,151 @@ static inline void ssb_block_write(struct ssb_device *dev, const void *buffer, | |||
399 | #endif /* CONFIG_SSB_BLOCKIO */ | 396 | #endif /* CONFIG_SSB_BLOCKIO */ |
400 | 397 | ||
401 | 398 | ||
399 | /* The SSB DMA API. Use this API for any DMA operation on the device. | ||
400 | * This API basically is a wrapper that calls the correct DMA API for | ||
401 | * the host device type the SSB device is attached to. */ | ||
402 | |||
402 | /* Translation (routing) bits that need to be ORed to DMA | 403 | /* Translation (routing) bits that need to be ORed to DMA |
403 | * addresses before they are given to a device. */ | 404 | * addresses before they are given to a device. */ |
404 | extern u32 ssb_dma_translation(struct ssb_device *dev); | 405 | extern u32 ssb_dma_translation(struct ssb_device *dev); |
405 | #define SSB_DMA_TRANSLATION_MASK 0xC0000000 | 406 | #define SSB_DMA_TRANSLATION_MASK 0xC0000000 |
406 | #define SSB_DMA_TRANSLATION_SHIFT 30 | 407 | #define SSB_DMA_TRANSLATION_SHIFT 30 |
407 | 408 | ||
408 | extern int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask); | 409 | extern int ssb_dma_set_mask(struct ssb_device *dev, u64 mask); |
410 | |||
411 | extern void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, | ||
412 | dma_addr_t *dma_handle, gfp_t gfp_flags); | ||
413 | extern void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, | ||
414 | void *vaddr, dma_addr_t dma_handle, | ||
415 | gfp_t gfp_flags); | ||
416 | |||
417 | static inline void __cold __ssb_dma_not_implemented(struct ssb_device *dev) | ||
418 | { | ||
419 | #ifdef CONFIG_SSB_DEBUG | ||
420 | printk(KERN_ERR "SSB: BUG! Calling DMA API for " | ||
421 | "unsupported bustype %d\n", dev->bus->bustype); | ||
422 | #endif /* DEBUG */ | ||
423 | } | ||
424 | |||
425 | static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr) | ||
426 | { | ||
427 | switch (dev->bus->bustype) { | ||
428 | case SSB_BUSTYPE_PCI: | ||
429 | return pci_dma_mapping_error(addr); | ||
430 | case SSB_BUSTYPE_SSB: | ||
431 | return dma_mapping_error(addr); | ||
432 | default: | ||
433 | __ssb_dma_not_implemented(dev); | ||
434 | } | ||
435 | return -ENOSYS; | ||
436 | } | ||
437 | |||
438 | static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p, | ||
439 | size_t size, enum dma_data_direction dir) | ||
440 | { | ||
441 | switch (dev->bus->bustype) { | ||
442 | case SSB_BUSTYPE_PCI: | ||
443 | return pci_map_single(dev->bus->host_pci, p, size, dir); | ||
444 | case SSB_BUSTYPE_SSB: | ||
445 | return dma_map_single(dev->dev, p, size, dir); | ||
446 | default: | ||
447 | __ssb_dma_not_implemented(dev); | ||
448 | } | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_addr, | ||
453 | size_t size, enum dma_data_direction dir) | ||
454 | { | ||
455 | switch (dev->bus->bustype) { | ||
456 | case SSB_BUSTYPE_PCI: | ||
457 | pci_unmap_single(dev->bus->host_pci, dma_addr, size, dir); | ||
458 | return; | ||
459 | case SSB_BUSTYPE_SSB: | ||
460 | dma_unmap_single(dev->dev, dma_addr, size, dir); | ||
461 | return; | ||
462 | default: | ||
463 | __ssb_dma_not_implemented(dev); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev, | ||
468 | dma_addr_t dma_addr, | ||
469 | size_t size, | ||
470 | enum dma_data_direction dir) | ||
471 | { | ||
472 | switch (dev->bus->bustype) { | ||
473 | case SSB_BUSTYPE_PCI: | ||
474 | pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr, | ||
475 | size, dir); | ||
476 | return; | ||
477 | case SSB_BUSTYPE_SSB: | ||
478 | dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir); | ||
479 | return; | ||
480 | default: | ||
481 | __ssb_dma_not_implemented(dev); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev, | ||
486 | dma_addr_t dma_addr, | ||
487 | size_t size, | ||
488 | enum dma_data_direction dir) | ||
489 | { | ||
490 | switch (dev->bus->bustype) { | ||
491 | case SSB_BUSTYPE_PCI: | ||
492 | pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr, | ||
493 | size, dir); | ||
494 | return; | ||
495 | case SSB_BUSTYPE_SSB: | ||
496 | dma_sync_single_for_device(dev->dev, dma_addr, size, dir); | ||
497 | return; | ||
498 | default: | ||
499 | __ssb_dma_not_implemented(dev); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev, | ||
504 | dma_addr_t dma_addr, | ||
505 | unsigned long offset, | ||
506 | size_t size, | ||
507 | enum dma_data_direction dir) | ||
508 | { | ||
509 | switch (dev->bus->bustype) { | ||
510 | case SSB_BUSTYPE_PCI: | ||
511 | /* Just sync everything. That's all the PCI API can do. */ | ||
512 | pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr, | ||
513 | offset + size, dir); | ||
514 | return; | ||
515 | case SSB_BUSTYPE_SSB: | ||
516 | dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset, | ||
517 | size, dir); | ||
518 | return; | ||
519 | default: | ||
520 | __ssb_dma_not_implemented(dev); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev, | ||
525 | dma_addr_t dma_addr, | ||
526 | unsigned long offset, | ||
527 | size_t size, | ||
528 | enum dma_data_direction dir) | ||
529 | { | ||
530 | switch (dev->bus->bustype) { | ||
531 | case SSB_BUSTYPE_PCI: | ||
532 | /* Just sync everything. That's all the PCI API can do. */ | ||
533 | pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr, | ||
534 | offset + size, dir); | ||
535 | return; | ||
536 | case SSB_BUSTYPE_SSB: | ||
537 | dma_sync_single_range_for_device(dev->dev, dma_addr, offset, | ||
538 | size, dir); | ||
539 | return; | ||
540 | default: | ||
541 | __ssb_dma_not_implemented(dev); | ||
542 | } | ||
543 | } | ||
409 | 544 | ||
410 | 545 | ||
411 | #ifdef CONFIG_SSB_PCIHOST | 546 | #ifdef CONFIG_SSB_PCIHOST |
diff --git a/include/linux/wireless.h b/include/linux/wireless.h index 4a95a0e5eeca..d7958f9b52cb 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h | |||
@@ -677,6 +677,19 @@ struct iw_point | |||
677 | __u16 flags; /* Optional params */ | 677 | __u16 flags; /* Optional params */ |
678 | }; | 678 | }; |
679 | 679 | ||
680 | #ifdef __KERNEL__ | ||
681 | #ifdef CONFIG_COMPAT | ||
682 | |||
683 | #include <linux/compat.h> | ||
684 | |||
685 | struct compat_iw_point { | ||
686 | compat_caddr_t pointer; | ||
687 | __u16 length; | ||
688 | __u16 flags; | ||
689 | }; | ||
690 | #endif | ||
691 | #endif | ||
692 | |||
680 | /* | 693 | /* |
681 | * A frequency | 694 | * A frequency |
682 | * For numbers lower than 10^9, we encode the number in 'm' and | 695 | * For numbers lower than 10^9, we encode the number in 'm' and |
@@ -1100,6 +1113,21 @@ struct iw_event | |||
1100 | #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ | 1113 | #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ |
1101 | IW_EV_POINT_OFF) | 1114 | IW_EV_POINT_OFF) |
1102 | 1115 | ||
1116 | #ifdef __KERNEL__ | ||
1117 | #ifdef CONFIG_COMPAT | ||
1118 | struct __compat_iw_event { | ||
1119 | __u16 len; /* Real length of this stuff */ | ||
1120 | __u16 cmd; /* Wireless IOCTL */ | ||
1121 | compat_caddr_t pointer; | ||
1122 | }; | ||
1123 | #define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer) | ||
1124 | #define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length) | ||
1125 | #define IW_EV_COMPAT_POINT_LEN \ | ||
1126 | (IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \ | ||
1127 | IW_EV_COMPAT_POINT_OFF) | ||
1128 | #endif | ||
1129 | #endif | ||
1130 | |||
1103 | /* Size of the Event prefix when packed in stream */ | 1131 | /* Size of the Event prefix when packed in stream */ |
1104 | #define IW_EV_LCP_PK_LEN (4) | 1132 | #define IW_EV_LCP_PK_LEN (4) |
1105 | /* Size of the various events when packed in stream */ | 1133 | /* Size of the various events when packed in stream */ |
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index 369d50e08b99..51b9a37de991 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h | |||
@@ -256,7 +256,7 @@ | |||
256 | #define EIWCOMMIT EINPROGRESS | 256 | #define EIWCOMMIT EINPROGRESS |
257 | 257 | ||
258 | /* Flags available in struct iw_request_info */ | 258 | /* Flags available in struct iw_request_info */ |
259 | #define IW_REQUEST_FLAG_NONE 0x0000 /* No flag so far */ | 259 | #define IW_REQUEST_FLAG_COMPAT 0x0001 /* Compat ioctl call */ |
260 | 260 | ||
261 | /* Type of headers we know about (basically union iwreq_data) */ | 261 | /* Type of headers we know about (basically union iwreq_data) */ |
262 | #define IW_HEADER_TYPE_NULL 0 /* Not available */ | 262 | #define IW_HEADER_TYPE_NULL 0 /* Not available */ |
@@ -478,105 +478,58 @@ extern void wireless_spy_update(struct net_device * dev, | |||
478 | * Function that are so simple that it's more efficient inlining them | 478 | * Function that are so simple that it's more efficient inlining them |
479 | */ | 479 | */ |
480 | 480 | ||
481 | /*------------------------------------------------------------------*/ | 481 | static inline int iwe_stream_lcp_len(struct iw_request_info *info) |
482 | /* | ||
483 | * Wrapper to add an Wireless Event to a stream of events. | ||
484 | */ | ||
485 | static inline char * | ||
486 | iwe_stream_add_event(char * stream, /* Stream of events */ | ||
487 | char * ends, /* End of stream */ | ||
488 | struct iw_event *iwe, /* Payload */ | ||
489 | int event_len) /* Real size of payload */ | ||
490 | { | 482 | { |
491 | /* Check if it's possible */ | 483 | #ifdef CONFIG_COMPAT |
492 | if(likely((stream + event_len) < ends)) { | 484 | if (info->flags & IW_REQUEST_FLAG_COMPAT) |
493 | iwe->len = event_len; | 485 | return IW_EV_COMPAT_LCP_LEN; |
494 | /* Beware of alignement issues on 64 bits */ | 486 | #endif |
495 | memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); | 487 | return IW_EV_LCP_LEN; |
496 | memcpy(stream + IW_EV_LCP_LEN, | ||
497 | ((char *) iwe) + IW_EV_LCP_LEN, | ||
498 | event_len - IW_EV_LCP_LEN); | ||
499 | stream += event_len; | ||
500 | } | ||
501 | return stream; | ||
502 | } | 488 | } |
503 | 489 | ||
504 | /*------------------------------------------------------------------*/ | 490 | static inline int iwe_stream_point_len(struct iw_request_info *info) |
505 | /* | ||
506 | * Wrapper to add an short Wireless Event containing a pointer to a | ||
507 | * stream of events. | ||
508 | */ | ||
509 | static inline char * | ||
510 | iwe_stream_add_point(char * stream, /* Stream of events */ | ||
511 | char * ends, /* End of stream */ | ||
512 | struct iw_event *iwe, /* Payload length + flags */ | ||
513 | char * extra) /* More payload */ | ||
514 | { | 491 | { |
515 | int event_len = IW_EV_POINT_LEN + iwe->u.data.length; | 492 | #ifdef CONFIG_COMPAT |
516 | /* Check if it's possible */ | 493 | if (info->flags & IW_REQUEST_FLAG_COMPAT) |
517 | if(likely((stream + event_len) < ends)) { | 494 | return IW_EV_COMPAT_POINT_LEN; |
518 | iwe->len = event_len; | 495 | #endif |
519 | memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); | 496 | return IW_EV_POINT_LEN; |
520 | memcpy(stream + IW_EV_LCP_LEN, | ||
521 | ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF, | ||
522 | IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); | ||
523 | memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length); | ||
524 | stream += event_len; | ||
525 | } | ||
526 | return stream; | ||
527 | } | 497 | } |
528 | 498 | ||
529 | /*------------------------------------------------------------------*/ | 499 | static inline int iwe_stream_event_len_adjust(struct iw_request_info *info, |
530 | /* | 500 | int event_len) |
531 | * Wrapper to add a value to a Wireless Event in a stream of events. | ||
532 | * Be careful, this one is tricky to use properly : | ||
533 | * At the first run, you need to have (value = event + IW_EV_LCP_LEN). | ||
534 | */ | ||
535 | static inline char * | ||
536 | iwe_stream_add_value(char * event, /* Event in the stream */ | ||
537 | char * value, /* Value in event */ | ||
538 | char * ends, /* End of stream */ | ||
539 | struct iw_event *iwe, /* Payload */ | ||
540 | int event_len) /* Real size of payload */ | ||
541 | { | 501 | { |
542 | /* Don't duplicate LCP */ | 502 | #ifdef CONFIG_COMPAT |
543 | event_len -= IW_EV_LCP_LEN; | 503 | if (info->flags & IW_REQUEST_FLAG_COMPAT) { |
544 | 504 | event_len -= IW_EV_LCP_LEN; | |
545 | /* Check if it's possible */ | 505 | event_len += IW_EV_COMPAT_LCP_LEN; |
546 | if(likely((value + event_len) < ends)) { | ||
547 | /* Add new value */ | ||
548 | memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len); | ||
549 | value += event_len; | ||
550 | /* Patch LCP */ | ||
551 | iwe->len = value - event; | ||
552 | memcpy(event, (char *) iwe, IW_EV_LCP_LEN); | ||
553 | } | 506 | } |
554 | return value; | 507 | #endif |
508 | |||
509 | return event_len; | ||
555 | } | 510 | } |
556 | 511 | ||
557 | /*------------------------------------------------------------------*/ | 512 | /*------------------------------------------------------------------*/ |
558 | /* | 513 | /* |
559 | * Wrapper to add an Wireless Event to a stream of events. | 514 | * Wrapper to add an Wireless Event to a stream of events. |
560 | * Same as above, with explicit error check... | ||
561 | */ | 515 | */ |
562 | static inline char * | 516 | static inline char * |
563 | iwe_stream_check_add_event(char * stream, /* Stream of events */ | 517 | iwe_stream_add_event(struct iw_request_info *info, char *stream, char *ends, |
564 | char * ends, /* End of stream */ | 518 | struct iw_event *iwe, int event_len) |
565 | struct iw_event *iwe, /* Payload */ | ||
566 | int event_len, /* Size of payload */ | ||
567 | int * perr) /* Error report */ | ||
568 | { | 519 | { |
569 | /* Check if it's possible, set error if not */ | 520 | int lcp_len = iwe_stream_lcp_len(info); |
521 | |||
522 | event_len = iwe_stream_event_len_adjust(info, event_len); | ||
523 | |||
524 | /* Check if it's possible */ | ||
570 | if(likely((stream + event_len) < ends)) { | 525 | if(likely((stream + event_len) < ends)) { |
571 | iwe->len = event_len; | 526 | iwe->len = event_len; |
572 | /* Beware of alignement issues on 64 bits */ | 527 | /* Beware of alignement issues on 64 bits */ |
573 | memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); | 528 | memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); |
574 | memcpy(stream + IW_EV_LCP_LEN, | 529 | memcpy(stream + lcp_len, &iwe->u, |
575 | ((char *) iwe) + IW_EV_LCP_LEN, | 530 | event_len - lcp_len); |
576 | event_len - IW_EV_LCP_LEN); | ||
577 | stream += event_len; | 531 | stream += event_len; |
578 | } else | 532 | } |
579 | *perr = -E2BIG; | ||
580 | return stream; | 533 | return stream; |
581 | } | 534 | } |
582 | 535 | ||
@@ -584,27 +537,25 @@ iwe_stream_check_add_event(char * stream, /* Stream of events */ | |||
584 | /* | 537 | /* |
585 | * Wrapper to add an short Wireless Event containing a pointer to a | 538 | * Wrapper to add an short Wireless Event containing a pointer to a |
586 | * stream of events. | 539 | * stream of events. |
587 | * Same as above, with explicit error check... | ||
588 | */ | 540 | */ |
589 | static inline char * | 541 | static inline char * |
590 | iwe_stream_check_add_point(char * stream, /* Stream of events */ | 542 | iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends, |
591 | char * ends, /* End of stream */ | 543 | struct iw_event *iwe, char *extra) |
592 | struct iw_event *iwe, /* Payload length + flags */ | ||
593 | char * extra, /* More payload */ | ||
594 | int * perr) /* Error report */ | ||
595 | { | 544 | { |
596 | int event_len = IW_EV_POINT_LEN + iwe->u.data.length; | 545 | int event_len = iwe_stream_point_len(info) + iwe->u.data.length; |
546 | int point_len = iwe_stream_point_len(info); | ||
547 | int lcp_len = iwe_stream_lcp_len(info); | ||
548 | |||
597 | /* Check if it's possible */ | 549 | /* Check if it's possible */ |
598 | if(likely((stream + event_len) < ends)) { | 550 | if(likely((stream + event_len) < ends)) { |
599 | iwe->len = event_len; | 551 | iwe->len = event_len; |
600 | memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); | 552 | memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); |
601 | memcpy(stream + IW_EV_LCP_LEN, | 553 | memcpy(stream + lcp_len, |
602 | ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF, | 554 | ((char *) &iwe->u) + IW_EV_POINT_OFF, |
603 | IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); | 555 | IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
604 | memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length); | 556 | memcpy(stream + point_len, extra, iwe->u.data.length); |
605 | stream += event_len; | 557 | stream += event_len; |
606 | } else | 558 | } |
607 | *perr = -E2BIG; | ||
608 | return stream; | 559 | return stream; |
609 | } | 560 | } |
610 | 561 | ||
@@ -613,29 +564,25 @@ iwe_stream_check_add_point(char * stream, /* Stream of events */ | |||
613 | * Wrapper to add a value to a Wireless Event in a stream of events. | 564 | * Wrapper to add a value to a Wireless Event in a stream of events. |
614 | * Be careful, this one is tricky to use properly : | 565 | * Be careful, this one is tricky to use properly : |
615 | * At the first run, you need to have (value = event + IW_EV_LCP_LEN). | 566 | * At the first run, you need to have (value = event + IW_EV_LCP_LEN). |
616 | * Same as above, with explicit error check... | ||
617 | */ | 567 | */ |
618 | static inline char * | 568 | static inline char * |
619 | iwe_stream_check_add_value(char * event, /* Event in the stream */ | 569 | iwe_stream_add_value(struct iw_request_info *info, char *event, char *value, |
620 | char * value, /* Value in event */ | 570 | char *ends, struct iw_event *iwe, int event_len) |
621 | char * ends, /* End of stream */ | ||
622 | struct iw_event *iwe, /* Payload */ | ||
623 | int event_len, /* Size of payload */ | ||
624 | int * perr) /* Error report */ | ||
625 | { | 571 | { |
572 | int lcp_len = iwe_stream_lcp_len(info); | ||
573 | |||
626 | /* Don't duplicate LCP */ | 574 | /* Don't duplicate LCP */ |
627 | event_len -= IW_EV_LCP_LEN; | 575 | event_len -= IW_EV_LCP_LEN; |
628 | 576 | ||
629 | /* Check if it's possible */ | 577 | /* Check if it's possible */ |
630 | if(likely((value + event_len) < ends)) { | 578 | if(likely((value + event_len) < ends)) { |
631 | /* Add new value */ | 579 | /* Add new value */ |
632 | memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len); | 580 | memcpy(value, &iwe->u, event_len); |
633 | value += event_len; | 581 | value += event_len; |
634 | /* Patch LCP */ | 582 | /* Patch LCP */ |
635 | iwe->len = value - event; | 583 | iwe->len = value - event; |
636 | memcpy(event, (char *) iwe, IW_EV_LCP_LEN); | 584 | memcpy(event, (char *) iwe, lcp_len); |
637 | } else | 585 | } |
638 | *perr = -E2BIG; | ||
639 | return value; | 586 | return value; |
640 | } | 587 | } |
641 | 588 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7ab4ff6159a2..02c79e6b309e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -595,7 +595,12 @@ enum ieee80211_key_flags { | |||
595 | * @flags: key flags, see &enum ieee80211_key_flags. | 595 | * @flags: key flags, see &enum ieee80211_key_flags. |
596 | * @keyidx: the key index (0-3) | 596 | * @keyidx: the key index (0-3) |
597 | * @keylen: key material length | 597 | * @keylen: key material length |
598 | * @key: key material | 598 | * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte) |
599 | * data block: | ||
600 | * - Temporal Encryption Key (128 bits) | ||
601 | * - Temporal Authenticator Tx MIC Key (64 bits) | ||
602 | * - Temporal Authenticator Rx MIC Key (64 bits) | ||
603 | * | ||
599 | */ | 604 | */ |
600 | struct ieee80211_key_conf { | 605 | struct ieee80211_key_conf { |
601 | enum ieee80211_key_alg alg; | 606 | enum ieee80211_key_alg alg; |
@@ -733,8 +738,11 @@ enum ieee80211_hw_flags { | |||
733 | * @conf: &struct ieee80211_conf, device configuration, don't use. | 738 | * @conf: &struct ieee80211_conf, device configuration, don't use. |
734 | * | 739 | * |
735 | * @workqueue: single threaded workqueue available for driver use, | 740 | * @workqueue: single threaded workqueue available for driver use, |
736 | * allocated by mac80211 on registration and flushed on | 741 | * allocated by mac80211 on registration and flushed when an |
737 | * unregistration. | 742 | * interface is removed. |
743 | * NOTICE: All work performed on this workqueue should NEVER | ||
744 | * acquire the RTNL lock (i.e. Don't use the function | ||
745 | * ieee80211_iterate_active_interfaces()) | ||
738 | * | 746 | * |
739 | * @priv: pointer to private area that was allocated for driver use | 747 | * @priv: pointer to private area that was allocated for driver use |
740 | * along with this structure. | 748 | * along with this structure. |
diff --git a/include/net/wext.h b/include/net/wext.h index 80b31d826b7a..6d76a39a9c5b 100644 --- a/include/net/wext.h +++ b/include/net/wext.h | |||
@@ -12,6 +12,8 @@ extern int wext_proc_init(struct net *net); | |||
12 | extern void wext_proc_exit(struct net *net); | 12 | extern void wext_proc_exit(struct net *net); |
13 | extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | 13 | extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, |
14 | void __user *arg); | 14 | void __user *arg); |
15 | extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | ||
16 | unsigned long arg); | ||
15 | #else | 17 | #else |
16 | static inline int wext_proc_init(struct net *net) | 18 | static inline int wext_proc_init(struct net *net) |
17 | { | 19 | { |
@@ -26,6 +28,11 @@ static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned | |||
26 | { | 28 | { |
27 | return -EINVAL; | 29 | return -EINVAL; |
28 | } | 30 | } |
31 | static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | ||
32 | unsigned long arg) | ||
33 | { | ||
34 | return -EINVAL; | ||
35 | } | ||
29 | #endif | 36 | #endif |
30 | 37 | ||
31 | #endif /* __NET_WEXT_H */ | 38 | #endif /* __NET_WEXT_H */ |
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 822606b615ca..973832dd7faf 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c | |||
@@ -43,8 +43,9 @@ static const char *ieee80211_modes[] = { | |||
43 | 43 | ||
44 | #define MAX_CUSTOM_LEN 64 | 44 | #define MAX_CUSTOM_LEN 64 |
45 | static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | 45 | static char *ieee80211_translate_scan(struct ieee80211_device *ieee, |
46 | char *start, char *stop, | 46 | char *start, char *stop, |
47 | struct ieee80211_network *network) | 47 | struct ieee80211_network *network, |
48 | struct iw_request_info *info) | ||
48 | { | 49 | { |
49 | char custom[MAX_CUSTOM_LEN]; | 50 | char custom[MAX_CUSTOM_LEN]; |
50 | char *p; | 51 | char *p; |
@@ -57,7 +58,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
57 | iwe.cmd = SIOCGIWAP; | 58 | iwe.cmd = SIOCGIWAP; |
58 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 59 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
59 | memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN); | 60 | memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN); |
60 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN); | 61 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); |
61 | 62 | ||
62 | /* Remaining entries will be displayed in the order we provide them */ | 63 | /* Remaining entries will be displayed in the order we provide them */ |
63 | 64 | ||
@@ -66,17 +67,19 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
66 | iwe.u.data.flags = 1; | 67 | iwe.u.data.flags = 1; |
67 | if (network->flags & NETWORK_EMPTY_ESSID) { | 68 | if (network->flags & NETWORK_EMPTY_ESSID) { |
68 | iwe.u.data.length = sizeof("<hidden>"); | 69 | iwe.u.data.length = sizeof("<hidden>"); |
69 | start = iwe_stream_add_point(start, stop, &iwe, "<hidden>"); | 70 | start = iwe_stream_add_point(info, start, stop, |
71 | &iwe, "<hidden>"); | ||
70 | } else { | 72 | } else { |
71 | iwe.u.data.length = min(network->ssid_len, (u8) 32); | 73 | iwe.u.data.length = min(network->ssid_len, (u8) 32); |
72 | start = iwe_stream_add_point(start, stop, &iwe, network->ssid); | 74 | start = iwe_stream_add_point(info, start, stop, |
75 | &iwe, network->ssid); | ||
73 | } | 76 | } |
74 | 77 | ||
75 | /* Add the protocol name */ | 78 | /* Add the protocol name */ |
76 | iwe.cmd = SIOCGIWNAME; | 79 | iwe.cmd = SIOCGIWNAME; |
77 | snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", | 80 | snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", |
78 | ieee80211_modes[network->mode]); | 81 | ieee80211_modes[network->mode]); |
79 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN); | 82 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); |
80 | 83 | ||
81 | /* Add mode */ | 84 | /* Add mode */ |
82 | iwe.cmd = SIOCGIWMODE; | 85 | iwe.cmd = SIOCGIWMODE; |
@@ -86,7 +89,8 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
86 | else | 89 | else |
87 | iwe.u.mode = IW_MODE_ADHOC; | 90 | iwe.u.mode = IW_MODE_ADHOC; |
88 | 91 | ||
89 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN); | 92 | start = iwe_stream_add_event(info, start, stop, |
93 | &iwe, IW_EV_UINT_LEN); | ||
90 | } | 94 | } |
91 | 95 | ||
92 | /* Add channel and frequency */ | 96 | /* Add channel and frequency */ |
@@ -95,7 +99,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
95 | iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel); | 99 | iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel); |
96 | iwe.u.freq.e = 6; | 100 | iwe.u.freq.e = 6; |
97 | iwe.u.freq.i = 0; | 101 | iwe.u.freq.i = 0; |
98 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN); | 102 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); |
99 | 103 | ||
100 | /* Add encryption capability */ | 104 | /* Add encryption capability */ |
101 | iwe.cmd = SIOCGIWENCODE; | 105 | iwe.cmd = SIOCGIWENCODE; |
@@ -104,12 +108,13 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
104 | else | 108 | else |
105 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 109 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
106 | iwe.u.data.length = 0; | 110 | iwe.u.data.length = 0; |
107 | start = iwe_stream_add_point(start, stop, &iwe, network->ssid); | 111 | start = iwe_stream_add_point(info, start, stop, |
112 | &iwe, network->ssid); | ||
108 | 113 | ||
109 | /* Add basic and extended rates */ | 114 | /* Add basic and extended rates */ |
110 | /* Rate : stuffing multiple values in a single event require a bit | 115 | /* Rate : stuffing multiple values in a single event require a bit |
111 | * more of magic - Jean II */ | 116 | * more of magic - Jean II */ |
112 | current_val = start + IW_EV_LCP_LEN; | 117 | current_val = start + iwe_stream_lcp_len(info); |
113 | iwe.cmd = SIOCGIWRATE; | 118 | iwe.cmd = SIOCGIWRATE; |
114 | /* Those two flags are ignored... */ | 119 | /* Those two flags are ignored... */ |
115 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | 120 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; |
@@ -124,17 +129,19 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
124 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | 129 | /* Bit rate given in 500 kb/s units (+ 0x80) */ |
125 | iwe.u.bitrate.value = ((rate & 0x7f) * 500000); | 130 | iwe.u.bitrate.value = ((rate & 0x7f) * 500000); |
126 | /* Add new value to event */ | 131 | /* Add new value to event */ |
127 | current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN); | 132 | current_val = iwe_stream_add_value(info, start, current_val, |
133 | stop, &iwe, IW_EV_PARAM_LEN); | ||
128 | } | 134 | } |
129 | for (; j < network->rates_ex_len; j++) { | 135 | for (; j < network->rates_ex_len; j++) { |
130 | rate = network->rates_ex[j] & 0x7F; | 136 | rate = network->rates_ex[j] & 0x7F; |
131 | /* Bit rate given in 500 kb/s units (+ 0x80) */ | 137 | /* Bit rate given in 500 kb/s units (+ 0x80) */ |
132 | iwe.u.bitrate.value = ((rate & 0x7f) * 500000); | 138 | iwe.u.bitrate.value = ((rate & 0x7f) * 500000); |
133 | /* Add new value to event */ | 139 | /* Add new value to event */ |
134 | current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN); | 140 | current_val = iwe_stream_add_value(info, start, current_val, |
141 | stop, &iwe, IW_EV_PARAM_LEN); | ||
135 | } | 142 | } |
136 | /* Check if we added any rate */ | 143 | /* Check if we added any rate */ |
137 | if((current_val - start) > IW_EV_LCP_LEN) | 144 | if ((current_val - start) > iwe_stream_lcp_len(info)) |
138 | start = current_val; | 145 | start = current_val; |
139 | 146 | ||
140 | /* Add quality statistics */ | 147 | /* Add quality statistics */ |
@@ -181,14 +188,14 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
181 | iwe.u.qual.level = network->stats.signal; | 188 | iwe.u.qual.level = network->stats.signal; |
182 | } | 189 | } |
183 | 190 | ||
184 | start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); | 191 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); |
185 | 192 | ||
186 | iwe.cmd = IWEVCUSTOM; | 193 | iwe.cmd = IWEVCUSTOM; |
187 | p = custom; | 194 | p = custom; |
188 | 195 | ||
189 | iwe.u.data.length = p - custom; | 196 | iwe.u.data.length = p - custom; |
190 | if (iwe.u.data.length) | 197 | if (iwe.u.data.length) |
191 | start = iwe_stream_add_point(start, stop, &iwe, custom); | 198 | start = iwe_stream_add_point(info, start, stop, &iwe, custom); |
192 | 199 | ||
193 | memset(&iwe, 0, sizeof(iwe)); | 200 | memset(&iwe, 0, sizeof(iwe)); |
194 | if (network->wpa_ie_len) { | 201 | if (network->wpa_ie_len) { |
@@ -196,7 +203,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
196 | memcpy(buf, network->wpa_ie, network->wpa_ie_len); | 203 | memcpy(buf, network->wpa_ie, network->wpa_ie_len); |
197 | iwe.cmd = IWEVGENIE; | 204 | iwe.cmd = IWEVGENIE; |
198 | iwe.u.data.length = network->wpa_ie_len; | 205 | iwe.u.data.length = network->wpa_ie_len; |
199 | start = iwe_stream_add_point(start, stop, &iwe, buf); | 206 | start = iwe_stream_add_point(info, start, stop, &iwe, buf); |
200 | } | 207 | } |
201 | 208 | ||
202 | memset(&iwe, 0, sizeof(iwe)); | 209 | memset(&iwe, 0, sizeof(iwe)); |
@@ -205,7 +212,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
205 | memcpy(buf, network->rsn_ie, network->rsn_ie_len); | 212 | memcpy(buf, network->rsn_ie, network->rsn_ie_len); |
206 | iwe.cmd = IWEVGENIE; | 213 | iwe.cmd = IWEVGENIE; |
207 | iwe.u.data.length = network->rsn_ie_len; | 214 | iwe.u.data.length = network->rsn_ie_len; |
208 | start = iwe_stream_add_point(start, stop, &iwe, buf); | 215 | start = iwe_stream_add_point(info, start, stop, &iwe, buf); |
209 | } | 216 | } |
210 | 217 | ||
211 | /* Add EXTRA: Age to display seconds since last beacon/probe response | 218 | /* Add EXTRA: Age to display seconds since last beacon/probe response |
@@ -217,7 +224,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
217 | jiffies_to_msecs(jiffies - network->last_scanned)); | 224 | jiffies_to_msecs(jiffies - network->last_scanned)); |
218 | iwe.u.data.length = p - custom; | 225 | iwe.u.data.length = p - custom; |
219 | if (iwe.u.data.length) | 226 | if (iwe.u.data.length) |
220 | start = iwe_stream_add_point(start, stop, &iwe, custom); | 227 | start = iwe_stream_add_point(info, start, stop, &iwe, custom); |
221 | 228 | ||
222 | /* Add spectrum management information */ | 229 | /* Add spectrum management information */ |
223 | iwe.cmd = -1; | 230 | iwe.cmd = -1; |
@@ -238,7 +245,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, | |||
238 | 245 | ||
239 | if (iwe.cmd == IWEVCUSTOM) { | 246 | if (iwe.cmd == IWEVCUSTOM) { |
240 | iwe.u.data.length = p - custom; | 247 | iwe.u.data.length = p - custom; |
241 | start = iwe_stream_add_point(start, stop, &iwe, custom); | 248 | start = iwe_stream_add_point(info, start, stop, &iwe, custom); |
242 | } | 249 | } |
243 | 250 | ||
244 | return start; | 251 | return start; |
@@ -272,7 +279,8 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee, | |||
272 | 279 | ||
273 | if (ieee->scan_age == 0 || | 280 | if (ieee->scan_age == 0 || |
274 | time_after(network->last_scanned + ieee->scan_age, jiffies)) | 281 | time_after(network->last_scanned + ieee->scan_age, jiffies)) |
275 | ev = ieee80211_translate_scan(ieee, ev, stop, network); | 282 | ev = ieee80211_translate_scan(ieee, ev, stop, network, |
283 | info); | ||
276 | else | 284 | else |
277 | IEEE80211_DEBUG_SCAN("Not showing network '%s (" | 285 | IEEE80211_DEBUG_SCAN("Not showing network '%s (" |
278 | "%s)' due to age (%dms).\n", | 286 | "%s)' due to age (%dms).\n", |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 590e00b2766c..0d3661d9b6a0 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -150,7 +150,7 @@ config MAC80211_LOWTX_FRAME_DUMP | |||
150 | If unsure, say N and insert the debugging code | 150 | If unsure, say N and insert the debugging code |
151 | you require into the driver you are debugging. | 151 | you require into the driver you are debugging. |
152 | 152 | ||
153 | config TKIP_DEBUG | 153 | config MAC80211_TKIP_DEBUG |
154 | bool "TKIP debugging" | 154 | bool "TKIP debugging" |
155 | depends on MAC80211_DEBUG | 155 | depends on MAC80211_DEBUG |
156 | 156 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 14fccf16b80f..af352c05c983 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <net/wireless.h> | 26 | #include <net/wireless.h> |
27 | #include <net/iw_handler.h> | ||
27 | #include "key.h" | 28 | #include "key.h" |
28 | #include "sta_info.h" | 29 | #include "sta_info.h" |
29 | 30 | ||
@@ -790,6 +791,10 @@ struct ieee802_11_elems { | |||
790 | u8 *preq; | 791 | u8 *preq; |
791 | u8 *prep; | 792 | u8 *prep; |
792 | u8 *perr; | 793 | u8 *perr; |
794 | u8 *ch_switch_elem; | ||
795 | u8 *country_elem; | ||
796 | u8 *pwr_constr_elem; | ||
797 | u8 *quiet_elem; /* first quite element */ | ||
793 | 798 | ||
794 | /* length of them, respectively */ | 799 | /* length of them, respectively */ |
795 | u8 ssid_len; | 800 | u8 ssid_len; |
@@ -814,6 +819,11 @@ struct ieee802_11_elems { | |||
814 | u8 preq_len; | 819 | u8 preq_len; |
815 | u8 prep_len; | 820 | u8 prep_len; |
816 | u8 perr_len; | 821 | u8 perr_len; |
822 | u8 ch_switch_elem_len; | ||
823 | u8 country_elem_len; | ||
824 | u8 pwr_constr_elem_len; | ||
825 | u8 quiet_elem_len; | ||
826 | u8 num_of_quiet_elem; /* can be more the one */ | ||
817 | }; | 827 | }; |
818 | 828 | ||
819 | static inline struct ieee80211_local *hw_to_local( | 829 | static inline struct ieee80211_local *hw_to_local( |
@@ -867,7 +877,9 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid); | |||
867 | int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); | 877 | int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); |
868 | void ieee80211_sta_req_auth(struct net_device *dev, | 878 | void ieee80211_sta_req_auth(struct net_device *dev, |
869 | struct ieee80211_if_sta *ifsta); | 879 | struct ieee80211_if_sta *ifsta); |
870 | int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len); | 880 | int ieee80211_sta_scan_results(struct net_device *dev, |
881 | struct iw_request_info *info, | ||
882 | char *buf, size_t len); | ||
871 | ieee80211_rx_result ieee80211_sta_rx_scan( | 883 | ieee80211_rx_result ieee80211_sta_rx_scan( |
872 | struct net_device *dev, struct sk_buff *skb, | 884 | struct net_device *dev, struct sk_buff *skb, |
873 | struct ieee80211_rx_status *rx_status); | 885 | struct ieee80211_rx_status *rx_status); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index a0f774aafa45..425816e0996c 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -16,31 +16,18 @@ | |||
16 | #include <linux/rcupdate.h> | 16 | #include <linux/rcupdate.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | 18 | ||
19 | /* ALG_TKIP | 19 | #define WEP_IV_LEN 4 |
20 | * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block: | 20 | #define WEP_ICV_LEN 4 |
21 | * Temporal Encryption Key (128 bits) | 21 | #define ALG_TKIP_KEY_LEN 32 |
22 | * Temporal Authenticator Tx MIC Key (64 bits) | 22 | #define ALG_CCMP_KEY_LEN 16 |
23 | * Temporal Authenticator Rx MIC Key (64 bits) | 23 | #define CCMP_HDR_LEN 8 |
24 | */ | 24 | #define CCMP_MIC_LEN 8 |
25 | 25 | #define CCMP_TK_LEN 16 | |
26 | #define WEP_IV_LEN 4 | 26 | #define CCMP_PN_LEN 6 |
27 | #define WEP_ICV_LEN 4 | 27 | #define TKIP_IV_LEN 8 |
28 | 28 | #define TKIP_ICV_LEN 4 | |
29 | #define ALG_TKIP_KEY_LEN 32 | 29 | |
30 | /* Starting offsets for each key */ | 30 | #define NUM_RX_DATA_QUEUES 17 |
31 | #define ALG_TKIP_TEMP_ENCR_KEY 0 | ||
32 | #define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16 | ||
33 | #define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24 | ||
34 | #define TKIP_IV_LEN 8 | ||
35 | #define TKIP_ICV_LEN 4 | ||
36 | |||
37 | #define ALG_CCMP_KEY_LEN 16 | ||
38 | #define CCMP_HDR_LEN 8 | ||
39 | #define CCMP_MIC_LEN 8 | ||
40 | #define CCMP_TK_LEN 16 | ||
41 | #define CCMP_PN_LEN 6 | ||
42 | |||
43 | #define NUM_RX_DATA_QUEUES 17 | ||
44 | 31 | ||
45 | struct ieee80211_local; | 32 | struct ieee80211_local; |
46 | struct ieee80211_sub_if_data; | 33 | struct ieee80211_sub_if_data; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5c5396edad32..b661ee5bb824 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1691,7 +1691,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1691 | list_add_tail(&sdata->list, &local->interfaces); | 1691 | list_add_tail(&sdata->list, &local->interfaces); |
1692 | 1692 | ||
1693 | name = wiphy_dev(local->hw.wiphy)->driver->name; | 1693 | name = wiphy_dev(local->hw.wiphy)->driver->name; |
1694 | local->hw.workqueue = create_singlethread_workqueue(name); | 1694 | local->hw.workqueue = create_freezeable_workqueue(name); |
1695 | if (!local->hw.workqueue) { | 1695 | if (!local->hw.workqueue) { |
1696 | result = -ENOMEM; | 1696 | result = -ENOMEM; |
1697 | goto fail_workqueue; | 1697 | goto fail_workqueue; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 55659a730dc1..7b4d4d46843b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -204,6 +204,25 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
204 | elems->perr = pos; | 204 | elems->perr = pos; |
205 | elems->perr_len = elen; | 205 | elems->perr_len = elen; |
206 | break; | 206 | break; |
207 | case WLAN_EID_CHANNEL_SWITCH: | ||
208 | elems->ch_switch_elem = pos; | ||
209 | elems->ch_switch_elem_len = elen; | ||
210 | break; | ||
211 | case WLAN_EID_QUIET: | ||
212 | if (!elems->quiet_elem) { | ||
213 | elems->quiet_elem = pos; | ||
214 | elems->quiet_elem_len = elen; | ||
215 | } | ||
216 | elems->num_of_quiet_elem++; | ||
217 | break; | ||
218 | case WLAN_EID_COUNTRY: | ||
219 | elems->country_elem = pos; | ||
220 | elems->country_elem_len = elen; | ||
221 | break; | ||
222 | case WLAN_EID_PWR_CONSTRAINT: | ||
223 | elems->pwr_constr_elem = pos; | ||
224 | elems->pwr_constr_elem_len = elen; | ||
225 | break; | ||
207 | default: | 226 | default: |
208 | break; | 227 | break; |
209 | } | 228 | } |
@@ -1701,6 +1720,71 @@ void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) | |||
1701 | } | 1720 | } |
1702 | } | 1721 | } |
1703 | 1722 | ||
1723 | static void ieee80211_send_refuse_measurement_request(struct net_device *dev, | ||
1724 | struct ieee80211_msrment_ie *request_ie, | ||
1725 | const u8 *da, const u8 *bssid, | ||
1726 | u8 dialog_token) | ||
1727 | { | ||
1728 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1729 | struct sk_buff *skb; | ||
1730 | struct ieee80211_mgmt *msr_report; | ||
1731 | |||
1732 | skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + | ||
1733 | sizeof(struct ieee80211_msrment_ie)); | ||
1734 | |||
1735 | if (!skb) { | ||
1736 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
1737 | "measurement report frame\n", dev->name); | ||
1738 | return; | ||
1739 | } | ||
1740 | |||
1741 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1742 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | ||
1743 | memset(msr_report, 0, 24); | ||
1744 | memcpy(msr_report->da, da, ETH_ALEN); | ||
1745 | memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); | ||
1746 | memcpy(msr_report->bssid, bssid, ETH_ALEN); | ||
1747 | msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1748 | IEEE80211_STYPE_ACTION); | ||
1749 | |||
1750 | skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); | ||
1751 | msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
1752 | msr_report->u.action.u.measurement.action_code = | ||
1753 | WLAN_ACTION_SPCT_MSR_RPRT; | ||
1754 | msr_report->u.action.u.measurement.dialog_token = dialog_token; | ||
1755 | |||
1756 | msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; | ||
1757 | msr_report->u.action.u.measurement.length = | ||
1758 | sizeof(struct ieee80211_msrment_ie); | ||
1759 | |||
1760 | memset(&msr_report->u.action.u.measurement.msr_elem, 0, | ||
1761 | sizeof(struct ieee80211_msrment_ie)); | ||
1762 | msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; | ||
1763 | msr_report->u.action.u.measurement.msr_elem.mode |= | ||
1764 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; | ||
1765 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; | ||
1766 | |||
1767 | ieee80211_sta_tx(dev, skb, 0); | ||
1768 | } | ||
1769 | |||
1770 | static void ieee80211_sta_process_measurement_req(struct net_device *dev, | ||
1771 | struct ieee80211_mgmt *mgmt, | ||
1772 | size_t len) | ||
1773 | { | ||
1774 | /* | ||
1775 | * Ignoring measurement request is spec violation. | ||
1776 | * Mandatory measurements must be reported optional | ||
1777 | * measurements might be refused or reported incapable | ||
1778 | * For now just refuse | ||
1779 | * TODO: Answer basic measurement as unmeasured | ||
1780 | */ | ||
1781 | ieee80211_send_refuse_measurement_request(dev, | ||
1782 | &mgmt->u.action.u.measurement.msr_elem, | ||
1783 | mgmt->sa, mgmt->bssid, | ||
1784 | mgmt->u.action.u.measurement.dialog_token); | ||
1785 | } | ||
1786 | |||
1787 | |||
1704 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, | 1788 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, |
1705 | struct ieee80211_if_sta *ifsta, | 1789 | struct ieee80211_if_sta *ifsta, |
1706 | struct ieee80211_mgmt *mgmt, | 1790 | struct ieee80211_mgmt *mgmt, |
@@ -1753,11 +1837,12 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1753 | auth_transaction, status_code); | 1837 | auth_transaction, status_code); |
1754 | 1838 | ||
1755 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1839 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { |
1756 | /* IEEE 802.11 standard does not require authentication in IBSS | 1840 | /* |
1841 | * IEEE 802.11 standard does not require authentication in IBSS | ||
1757 | * networks and most implementations do not seem to use it. | 1842 | * networks and most implementations do not seem to use it. |
1758 | * However, try to reply to authentication attempts if someone | 1843 | * However, try to reply to authentication attempts if someone |
1759 | * has actually implemented this. | 1844 | * has actually implemented this. |
1760 | * TODO: Could implement shared key authentication. */ | 1845 | */ |
1761 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) { | 1846 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) { |
1762 | printk(KERN_DEBUG "%s: unexpected IBSS authentication " | 1847 | printk(KERN_DEBUG "%s: unexpected IBSS authentication " |
1763 | "frame (alg=%d transaction=%d)\n", | 1848 | "frame (alg=%d transaction=%d)\n", |
@@ -3025,11 +3110,24 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, | |||
3025 | struct ieee80211_rx_status *rx_status) | 3110 | struct ieee80211_rx_status *rx_status) |
3026 | { | 3111 | { |
3027 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3112 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3113 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3028 | 3114 | ||
3029 | if (len < IEEE80211_MIN_ACTION_SIZE) | 3115 | if (len < IEEE80211_MIN_ACTION_SIZE) |
3030 | return; | 3116 | return; |
3031 | 3117 | ||
3032 | switch (mgmt->u.action.category) { | 3118 | switch (mgmt->u.action.category) { |
3119 | case WLAN_CATEGORY_SPECTRUM_MGMT: | ||
3120 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | ||
3121 | break; | ||
3122 | switch (mgmt->u.action.u.chan_switch.action_code) { | ||
3123 | case WLAN_ACTION_SPCT_MSR_REQ: | ||
3124 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3125 | sizeof(mgmt->u.action.u.measurement))) | ||
3126 | break; | ||
3127 | ieee80211_sta_process_measurement_req(dev, mgmt, len); | ||
3128 | break; | ||
3129 | } | ||
3130 | break; | ||
3033 | case WLAN_CATEGORY_BACK: | 3131 | case WLAN_CATEGORY_BACK: |
3034 | switch (mgmt->u.action.u.addba_req.action_code) { | 3132 | switch (mgmt->u.action.u.addba_req.action_code) { |
3035 | case WLAN_ACTION_ADDBA_REQ: | 3133 | case WLAN_ACTION_ADDBA_REQ: |
@@ -3173,33 +3271,32 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, | |||
3173 | struct ieee80211_rx_status *rx_status) | 3271 | struct ieee80211_rx_status *rx_status) |
3174 | { | 3272 | { |
3175 | struct ieee80211_mgmt *mgmt; | 3273 | struct ieee80211_mgmt *mgmt; |
3176 | u16 fc; | 3274 | __le16 fc; |
3177 | 3275 | ||
3178 | if (skb->len < 2) | 3276 | if (skb->len < 2) |
3179 | return RX_DROP_UNUSABLE; | 3277 | return RX_DROP_UNUSABLE; |
3180 | 3278 | ||
3181 | mgmt = (struct ieee80211_mgmt *) skb->data; | 3279 | mgmt = (struct ieee80211_mgmt *) skb->data; |
3182 | fc = le16_to_cpu(mgmt->frame_control); | 3280 | fc = mgmt->frame_control; |
3183 | 3281 | ||
3184 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) | 3282 | if (ieee80211_is_ctl(fc)) |
3185 | return RX_CONTINUE; | 3283 | return RX_CONTINUE; |
3186 | 3284 | ||
3187 | if (skb->len < 24) | 3285 | if (skb->len < 24) |
3188 | return RX_DROP_MONITOR; | 3286 | return RX_DROP_MONITOR; |
3189 | 3287 | ||
3190 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { | 3288 | if (ieee80211_is_probe_resp(fc)) { |
3191 | if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) { | 3289 | ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); |
3192 | ieee80211_rx_mgmt_probe_resp(dev, mgmt, | 3290 | dev_kfree_skb(skb); |
3193 | skb->len, rx_status); | 3291 | return RX_QUEUED; |
3194 | dev_kfree_skb(skb); | ||
3195 | return RX_QUEUED; | ||
3196 | } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) { | ||
3197 | ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, | ||
3198 | rx_status); | ||
3199 | dev_kfree_skb(skb); | ||
3200 | return RX_QUEUED; | ||
3201 | } | ||
3202 | } | 3292 | } |
3293 | |||
3294 | if (ieee80211_is_beacon(fc)) { | ||
3295 | ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); | ||
3296 | dev_kfree_skb(skb); | ||
3297 | return RX_QUEUED; | ||
3298 | } | ||
3299 | |||
3203 | return RX_CONTINUE; | 3300 | return RX_CONTINUE; |
3204 | } | 3301 | } |
3205 | 3302 | ||
@@ -3777,7 +3874,7 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
3777 | { | 3874 | { |
3778 | struct sk_buff *skb; | 3875 | struct sk_buff *skb; |
3779 | struct ieee80211_hdr *nullfunc; | 3876 | struct ieee80211_hdr *nullfunc; |
3780 | u16 fc; | 3877 | __le16 fc; |
3781 | 3878 | ||
3782 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | 3879 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); |
3783 | if (!skb) { | 3880 | if (!skb) { |
@@ -3789,11 +3886,11 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
3789 | 3886 | ||
3790 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); | 3887 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); |
3791 | memset(nullfunc, 0, 24); | 3888 | memset(nullfunc, 0, 24); |
3792 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | 3889 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | |
3793 | IEEE80211_FCTL_TODS; | 3890 | IEEE80211_FCTL_TODS); |
3794 | if (powersave) | 3891 | if (powersave) |
3795 | fc |= IEEE80211_FCTL_PM; | 3892 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); |
3796 | nullfunc->frame_control = cpu_to_le16(fc); | 3893 | nullfunc->frame_control = fc; |
3797 | memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); | 3894 | memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); |
3798 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | 3895 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); |
3799 | memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); | 3896 | memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); |
@@ -4087,6 +4184,7 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) | |||
4087 | 4184 | ||
4088 | static char * | 4185 | static char * |
4089 | ieee80211_sta_scan_result(struct net_device *dev, | 4186 | ieee80211_sta_scan_result(struct net_device *dev, |
4187 | struct iw_request_info *info, | ||
4090 | struct ieee80211_sta_bss *bss, | 4188 | struct ieee80211_sta_bss *bss, |
4091 | char *current_ev, char *end_buf) | 4189 | char *current_ev, char *end_buf) |
4092 | { | 4190 | { |
@@ -4101,7 +4199,7 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4101 | iwe.cmd = SIOCGIWAP; | 4199 | iwe.cmd = SIOCGIWAP; |
4102 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 4200 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
4103 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 4201 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
4104 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4202 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
4105 | IW_EV_ADDR_LEN); | 4203 | IW_EV_ADDR_LEN); |
4106 | 4204 | ||
4107 | memset(&iwe, 0, sizeof(iwe)); | 4205 | memset(&iwe, 0, sizeof(iwe)); |
@@ -4109,13 +4207,13 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4109 | if (bss_mesh_cfg(bss)) { | 4207 | if (bss_mesh_cfg(bss)) { |
4110 | iwe.u.data.length = bss_mesh_id_len(bss); | 4208 | iwe.u.data.length = bss_mesh_id_len(bss); |
4111 | iwe.u.data.flags = 1; | 4209 | iwe.u.data.flags = 1; |
4112 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4210 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4113 | bss_mesh_id(bss)); | 4211 | &iwe, bss_mesh_id(bss)); |
4114 | } else { | 4212 | } else { |
4115 | iwe.u.data.length = bss->ssid_len; | 4213 | iwe.u.data.length = bss->ssid_len; |
4116 | iwe.u.data.flags = 1; | 4214 | iwe.u.data.flags = 1; |
4117 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4215 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4118 | bss->ssid); | 4216 | &iwe, bss->ssid); |
4119 | } | 4217 | } |
4120 | 4218 | ||
4121 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | 4219 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) |
@@ -4128,22 +4226,22 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4128 | iwe.u.mode = IW_MODE_MASTER; | 4226 | iwe.u.mode = IW_MODE_MASTER; |
4129 | else | 4227 | else |
4130 | iwe.u.mode = IW_MODE_ADHOC; | 4228 | iwe.u.mode = IW_MODE_ADHOC; |
4131 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4229 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
4132 | IW_EV_UINT_LEN); | 4230 | &iwe, IW_EV_UINT_LEN); |
4133 | } | 4231 | } |
4134 | 4232 | ||
4135 | memset(&iwe, 0, sizeof(iwe)); | 4233 | memset(&iwe, 0, sizeof(iwe)); |
4136 | iwe.cmd = SIOCGIWFREQ; | 4234 | iwe.cmd = SIOCGIWFREQ; |
4137 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); | 4235 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); |
4138 | iwe.u.freq.e = 0; | 4236 | iwe.u.freq.e = 0; |
4139 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4237 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
4140 | IW_EV_FREQ_LEN); | 4238 | IW_EV_FREQ_LEN); |
4141 | 4239 | ||
4142 | memset(&iwe, 0, sizeof(iwe)); | 4240 | memset(&iwe, 0, sizeof(iwe)); |
4143 | iwe.cmd = SIOCGIWFREQ; | 4241 | iwe.cmd = SIOCGIWFREQ; |
4144 | iwe.u.freq.m = bss->freq; | 4242 | iwe.u.freq.m = bss->freq; |
4145 | iwe.u.freq.e = 6; | 4243 | iwe.u.freq.e = 6; |
4146 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4244 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
4147 | IW_EV_FREQ_LEN); | 4245 | IW_EV_FREQ_LEN); |
4148 | memset(&iwe, 0, sizeof(iwe)); | 4246 | memset(&iwe, 0, sizeof(iwe)); |
4149 | iwe.cmd = IWEVQUAL; | 4247 | iwe.cmd = IWEVQUAL; |
@@ -4151,7 +4249,7 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4151 | iwe.u.qual.level = bss->signal; | 4249 | iwe.u.qual.level = bss->signal; |
4152 | iwe.u.qual.noise = bss->noise; | 4250 | iwe.u.qual.noise = bss->noise; |
4153 | iwe.u.qual.updated = local->wstats_flags; | 4251 | iwe.u.qual.updated = local->wstats_flags; |
4154 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4252 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
4155 | IW_EV_QUAL_LEN); | 4253 | IW_EV_QUAL_LEN); |
4156 | 4254 | ||
4157 | memset(&iwe, 0, sizeof(iwe)); | 4255 | memset(&iwe, 0, sizeof(iwe)); |
@@ -4161,35 +4259,36 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4161 | else | 4259 | else |
4162 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 4260 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
4163 | iwe.u.data.length = 0; | 4261 | iwe.u.data.length = 0; |
4164 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ""); | 4262 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4263 | &iwe, ""); | ||
4165 | 4264 | ||
4166 | if (bss && bss->wpa_ie) { | 4265 | if (bss && bss->wpa_ie) { |
4167 | memset(&iwe, 0, sizeof(iwe)); | 4266 | memset(&iwe, 0, sizeof(iwe)); |
4168 | iwe.cmd = IWEVGENIE; | 4267 | iwe.cmd = IWEVGENIE; |
4169 | iwe.u.data.length = bss->wpa_ie_len; | 4268 | iwe.u.data.length = bss->wpa_ie_len; |
4170 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4269 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4171 | bss->wpa_ie); | 4270 | &iwe, bss->wpa_ie); |
4172 | } | 4271 | } |
4173 | 4272 | ||
4174 | if (bss && bss->rsn_ie) { | 4273 | if (bss && bss->rsn_ie) { |
4175 | memset(&iwe, 0, sizeof(iwe)); | 4274 | memset(&iwe, 0, sizeof(iwe)); |
4176 | iwe.cmd = IWEVGENIE; | 4275 | iwe.cmd = IWEVGENIE; |
4177 | iwe.u.data.length = bss->rsn_ie_len; | 4276 | iwe.u.data.length = bss->rsn_ie_len; |
4178 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4277 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4179 | bss->rsn_ie); | 4278 | &iwe, bss->rsn_ie); |
4180 | } | 4279 | } |
4181 | 4280 | ||
4182 | if (bss && bss->ht_ie) { | 4281 | if (bss && bss->ht_ie) { |
4183 | memset(&iwe, 0, sizeof(iwe)); | 4282 | memset(&iwe, 0, sizeof(iwe)); |
4184 | iwe.cmd = IWEVGENIE; | 4283 | iwe.cmd = IWEVGENIE; |
4185 | iwe.u.data.length = bss->ht_ie_len; | 4284 | iwe.u.data.length = bss->ht_ie_len; |
4186 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4285 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4187 | bss->ht_ie); | 4286 | &iwe, bss->ht_ie); |
4188 | } | 4287 | } |
4189 | 4288 | ||
4190 | if (bss && bss->supp_rates_len > 0) { | 4289 | if (bss && bss->supp_rates_len > 0) { |
4191 | /* display all supported rates in readable format */ | 4290 | /* display all supported rates in readable format */ |
4192 | char *p = current_ev + IW_EV_LCP_LEN; | 4291 | char *p = current_ev + iwe_stream_lcp_len(info); |
4193 | int i; | 4292 | int i; |
4194 | 4293 | ||
4195 | memset(&iwe, 0, sizeof(iwe)); | 4294 | memset(&iwe, 0, sizeof(iwe)); |
@@ -4200,7 +4299,7 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4200 | for (i = 0; i < bss->supp_rates_len; i++) { | 4299 | for (i = 0; i < bss->supp_rates_len; i++) { |
4201 | iwe.u.bitrate.value = ((bss->supp_rates[i] & | 4300 | iwe.u.bitrate.value = ((bss->supp_rates[i] & |
4202 | 0x7f) * 500000); | 4301 | 0x7f) * 500000); |
4203 | p = iwe_stream_add_value(current_ev, p, | 4302 | p = iwe_stream_add_value(info, current_ev, p, |
4204 | end_buf, &iwe, IW_EV_PARAM_LEN); | 4303 | end_buf, &iwe, IW_EV_PARAM_LEN); |
4205 | } | 4304 | } |
4206 | current_ev = p; | 4305 | current_ev = p; |
@@ -4214,7 +4313,8 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4214 | iwe.cmd = IWEVCUSTOM; | 4313 | iwe.cmd = IWEVCUSTOM; |
4215 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); | 4314 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); |
4216 | iwe.u.data.length = strlen(buf); | 4315 | iwe.u.data.length = strlen(buf); |
4217 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4316 | current_ev = iwe_stream_add_point(info, current_ev, |
4317 | end_buf, | ||
4218 | &iwe, buf); | 4318 | &iwe, buf); |
4219 | kfree(buf); | 4319 | kfree(buf); |
4220 | } | 4320 | } |
@@ -4229,31 +4329,36 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4229 | iwe.cmd = IWEVCUSTOM; | 4329 | iwe.cmd = IWEVCUSTOM; |
4230 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | 4330 | sprintf(buf, "Mesh network (version %d)", cfg[0]); |
4231 | iwe.u.data.length = strlen(buf); | 4331 | iwe.u.data.length = strlen(buf); |
4232 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4332 | current_ev = iwe_stream_add_point(info, current_ev, |
4333 | end_buf, | ||
4233 | &iwe, buf); | 4334 | &iwe, buf); |
4234 | sprintf(buf, "Path Selection Protocol ID: " | 4335 | sprintf(buf, "Path Selection Protocol ID: " |
4235 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | 4336 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], |
4236 | cfg[4]); | 4337 | cfg[4]); |
4237 | iwe.u.data.length = strlen(buf); | 4338 | iwe.u.data.length = strlen(buf); |
4238 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4339 | current_ev = iwe_stream_add_point(info, current_ev, |
4340 | end_buf, | ||
4239 | &iwe, buf); | 4341 | &iwe, buf); |
4240 | sprintf(buf, "Path Selection Metric ID: " | 4342 | sprintf(buf, "Path Selection Metric ID: " |
4241 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | 4343 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], |
4242 | cfg[8]); | 4344 | cfg[8]); |
4243 | iwe.u.data.length = strlen(buf); | 4345 | iwe.u.data.length = strlen(buf); |
4244 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4346 | current_ev = iwe_stream_add_point(info, current_ev, |
4347 | end_buf, | ||
4245 | &iwe, buf); | 4348 | &iwe, buf); |
4246 | sprintf(buf, "Congestion Control Mode ID: " | 4349 | sprintf(buf, "Congestion Control Mode ID: " |
4247 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | 4350 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], |
4248 | cfg[11], cfg[12]); | 4351 | cfg[11], cfg[12]); |
4249 | iwe.u.data.length = strlen(buf); | 4352 | iwe.u.data.length = strlen(buf); |
4250 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4353 | current_ev = iwe_stream_add_point(info, current_ev, |
4354 | end_buf, | ||
4251 | &iwe, buf); | 4355 | &iwe, buf); |
4252 | sprintf(buf, "Channel Precedence: " | 4356 | sprintf(buf, "Channel Precedence: " |
4253 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | 4357 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], |
4254 | cfg[15], cfg[16]); | 4358 | cfg[15], cfg[16]); |
4255 | iwe.u.data.length = strlen(buf); | 4359 | iwe.u.data.length = strlen(buf); |
4256 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4360 | current_ev = iwe_stream_add_point(info, current_ev, |
4361 | end_buf, | ||
4257 | &iwe, buf); | 4362 | &iwe, buf); |
4258 | kfree(buf); | 4363 | kfree(buf); |
4259 | } | 4364 | } |
@@ -4263,7 +4368,9 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4263 | } | 4368 | } |
4264 | 4369 | ||
4265 | 4370 | ||
4266 | int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len) | 4371 | int ieee80211_sta_scan_results(struct net_device *dev, |
4372 | struct iw_request_info *info, | ||
4373 | char *buf, size_t len) | ||
4267 | { | 4374 | { |
4268 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 4375 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
4269 | char *current_ev = buf; | 4376 | char *current_ev = buf; |
@@ -4276,8 +4383,8 @@ int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len) | |||
4276 | spin_unlock_bh(&local->sta_bss_lock); | 4383 | spin_unlock_bh(&local->sta_bss_lock); |
4277 | return -E2BIG; | 4384 | return -E2BIG; |
4278 | } | 4385 | } |
4279 | current_ev = ieee80211_sta_scan_result(dev, bss, current_ev, | 4386 | current_ev = ieee80211_sta_scan_result(dev, info, bss, |
4280 | end_buf); | 4387 | current_ev, end_buf); |
4281 | } | 4388 | } |
4282 | spin_unlock_bh(&local->sta_bss_lock); | 4389 | spin_unlock_bh(&local->sta_bss_lock); |
4283 | return current_ev - buf; | 4390 | return current_ev - buf; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c32a0bcd53b7..8962d1355f04 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -61,7 +61,7 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status, | |||
61 | int present_fcs_len, | 61 | int present_fcs_len, |
62 | int radiotap_len) | 62 | int radiotap_len) |
63 | { | 63 | { |
64 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 64 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
65 | 65 | ||
66 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 66 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) |
67 | return 1; | 67 | return 1; |
@@ -2123,7 +2123,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2123 | struct tid_ampdu_rx *tid_agg_rx; | 2123 | struct tid_ampdu_rx *tid_agg_rx; |
2124 | u16 sc; | 2124 | u16 sc; |
2125 | u16 mpdu_seq_num; | 2125 | u16 mpdu_seq_num; |
2126 | u8 ret = 0, *qc; | 2126 | u8 ret = 0; |
2127 | int tid; | 2127 | int tid; |
2128 | 2128 | ||
2129 | sta = sta_info_get(local, hdr->addr2); | 2129 | sta = sta_info_get(local, hdr->addr2); |
@@ -2135,8 +2135,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2135 | if (!ieee80211_is_data_qos(hdr->frame_control)) | 2135 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
2136 | goto end_reorder; | 2136 | goto end_reorder; |
2137 | 2137 | ||
2138 | qc = ieee80211_get_qos_ctl(hdr); | 2138 | tid = *ieee80211_get_qos_ctl(hdr) & QOS_CONTROL_TID_MASK; |
2139 | tid = qc[0] & QOS_CONTROL_TID_MASK; | ||
2140 | 2139 | ||
2141 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 2140 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) |
2142 | goto end_reorder; | 2141 | goto end_reorder; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c24770cb02c5..b3c733162fc1 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -235,6 +235,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
235 | return NULL; | 235 | return NULL; |
236 | 236 | ||
237 | spin_lock_init(&sta->lock); | 237 | spin_lock_init(&sta->lock); |
238 | spin_lock_init(&sta->flaglock); | ||
238 | 239 | ||
239 | memcpy(sta->addr, addr, ETH_ALEN); | 240 | memcpy(sta->addr, addr, ETH_ALEN); |
240 | sta->local = local; | 241 | sta->local = local; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 95753f860acf..fd228c198e31 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -164,6 +164,7 @@ struct sta_ampdu_mlme { | |||
164 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), | 164 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), |
165 | * only used in AP (and IBSS?) mode | 165 | * only used in AP (and IBSS?) mode |
166 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 166 | * @flags: STA flags, see &enum ieee80211_sta_info_flags |
167 | * @flaglock: spinlock for flags accesses | ||
167 | * @ps_tx_buf: buffer of frames to transmit to this station | 168 | * @ps_tx_buf: buffer of frames to transmit to this station |
168 | * when it leaves power saving state | 169 | * when it leaves power saving state |
169 | * @tx_filtered: buffer of frames we already tried to transmit | 170 | * @tx_filtered: buffer of frames we already tried to transmit |
@@ -186,6 +187,7 @@ struct sta_info { | |||
186 | struct rate_control_ref *rate_ctrl; | 187 | struct rate_control_ref *rate_ctrl; |
187 | void *rate_ctrl_priv; | 188 | void *rate_ctrl_priv; |
188 | spinlock_t lock; | 189 | spinlock_t lock; |
190 | spinlock_t flaglock; | ||
189 | struct ieee80211_ht_info ht_info; | 191 | struct ieee80211_ht_info ht_info; |
190 | u64 supp_rates[IEEE80211_NUM_BANDS]; | 192 | u64 supp_rates[IEEE80211_NUM_BANDS]; |
191 | u8 addr[ETH_ALEN]; | 193 | u8 addr[ETH_ALEN]; |
@@ -198,7 +200,10 @@ struct sta_info { | |||
198 | */ | 200 | */ |
199 | u8 pin_status; | 201 | u8 pin_status; |
200 | 202 | ||
201 | /* frequently updated information, locked with lock spinlock */ | 203 | /* |
204 | * frequently updated, locked with own spinlock (flaglock), | ||
205 | * use the accessors defined below | ||
206 | */ | ||
202 | u32 flags; | 207 | u32 flags; |
203 | 208 | ||
204 | /* | 209 | /* |
@@ -293,34 +298,41 @@ static inline enum plink_state sta_plink_state(struct sta_info *sta) | |||
293 | 298 | ||
294 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) | 299 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) |
295 | { | 300 | { |
296 | spin_lock_bh(&sta->lock); | 301 | unsigned long irqfl; |
302 | |||
303 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
297 | sta->flags |= flags; | 304 | sta->flags |= flags; |
298 | spin_unlock_bh(&sta->lock); | 305 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
299 | } | 306 | } |
300 | 307 | ||
301 | static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) | 308 | static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) |
302 | { | 309 | { |
303 | spin_lock_bh(&sta->lock); | 310 | unsigned long irqfl; |
311 | |||
312 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
304 | sta->flags &= ~flags; | 313 | sta->flags &= ~flags; |
305 | spin_unlock_bh(&sta->lock); | 314 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
306 | } | 315 | } |
307 | 316 | ||
308 | static inline void set_and_clear_sta_flags(struct sta_info *sta, | 317 | static inline void set_and_clear_sta_flags(struct sta_info *sta, |
309 | const u32 set, const u32 clear) | 318 | const u32 set, const u32 clear) |
310 | { | 319 | { |
311 | spin_lock_bh(&sta->lock); | 320 | unsigned long irqfl; |
321 | |||
322 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
312 | sta->flags |= set; | 323 | sta->flags |= set; |
313 | sta->flags &= ~clear; | 324 | sta->flags &= ~clear; |
314 | spin_unlock_bh(&sta->lock); | 325 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
315 | } | 326 | } |
316 | 327 | ||
317 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) | 328 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) |
318 | { | 329 | { |
319 | u32 ret; | 330 | u32 ret; |
331 | unsigned long irqfl; | ||
320 | 332 | ||
321 | spin_lock_bh(&sta->lock); | 333 | spin_lock_irqsave(&sta->flaglock, irqfl); |
322 | ret = sta->flags & flags; | 334 | ret = sta->flags & flags; |
323 | spin_unlock_bh(&sta->lock); | 335 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
324 | 336 | ||
325 | return ret; | 337 | return ret; |
326 | } | 338 | } |
@@ -329,11 +341,12 @@ static inline u32 test_and_clear_sta_flags(struct sta_info *sta, | |||
329 | const u32 flags) | 341 | const u32 flags) |
330 | { | 342 | { |
331 | u32 ret; | 343 | u32 ret; |
344 | unsigned long irqfl; | ||
332 | 345 | ||
333 | spin_lock_bh(&sta->lock); | 346 | spin_lock_irqsave(&sta->flaglock, irqfl); |
334 | ret = sta->flags & flags; | 347 | ret = sta->flags & flags; |
335 | sta->flags &= ~flags; | 348 | sta->flags &= ~flags; |
336 | spin_unlock_bh(&sta->lock); | 349 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
337 | 350 | ||
338 | return ret; | 351 | return ret; |
339 | } | 352 | } |
@@ -341,10 +354,11 @@ static inline u32 test_and_clear_sta_flags(struct sta_info *sta, | |||
341 | static inline u32 get_sta_flags(struct sta_info *sta) | 354 | static inline u32 get_sta_flags(struct sta_info *sta) |
342 | { | 355 | { |
343 | u32 ret; | 356 | u32 ret; |
357 | unsigned long irqfl; | ||
344 | 358 | ||
345 | spin_lock_bh(&sta->lock); | 359 | spin_lock_irqsave(&sta->flaglock, irqfl); |
346 | ret = sta->flags; | 360 | ret = sta->flags; |
347 | spin_unlock_bh(&sta->lock); | 361 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
348 | 362 | ||
349 | return ret; | 363 | return ret; |
350 | } | 364 | } |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index e710243d82e2..995f7af3d25e 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -164,10 +164,10 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
164 | iv16 = data[2] | (data[0] << 8); | 164 | iv16 = data[2] | (data[0] << 8); |
165 | iv32 = get_unaligned_le32(&data[4]); | 165 | iv32 = get_unaligned_le32(&data[4]); |
166 | 166 | ||
167 | tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; | 167 | tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
168 | ctx = &key->u.tkip.tx; | 168 | ctx = &key->u.tkip.tx; |
169 | 169 | ||
170 | #ifdef CONFIG_TKIP_DEBUG | 170 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
171 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", | 171 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", |
172 | iv16, iv32); | 172 | iv16, iv32); |
173 | 173 | ||
@@ -177,7 +177,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
177 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " | 177 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " |
178 | "fragmented packet\n"); | 178 | "fragmented packet\n"); |
179 | } | 179 | } |
180 | #endif /* CONFIG_TKIP_DEBUG */ | 180 | #endif |
181 | 181 | ||
182 | /* Update the p1k only when the iv16 in the packet wraps around, this | 182 | /* Update the p1k only when the iv16 in the packet wraps around, this |
183 | * might occur after the wrap around of iv16 in the key in case of | 183 | * might occur after the wrap around of iv16 in the key in case of |
@@ -205,7 +205,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | |||
205 | { | 205 | { |
206 | u8 rc4key[16]; | 206 | u8 rc4key[16]; |
207 | struct tkip_ctx *ctx = &key->u.tkip.tx; | 207 | struct tkip_ctx *ctx = &key->u.tkip.tx; |
208 | const u8 *tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; | 208 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
209 | 209 | ||
210 | /* Calculate per-packet key */ | 210 | /* Calculate per-packet key */ |
211 | if (ctx->iv16 == 0 || !ctx->initialized) | 211 | if (ctx->iv16 == 0 || !ctx->initialized) |
@@ -231,7 +231,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
231 | u32 iv16; | 231 | u32 iv16; |
232 | u8 rc4key[16], keyid, *pos = payload; | 232 | u8 rc4key[16], keyid, *pos = payload; |
233 | int res; | 233 | int res; |
234 | const u8 *tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; | 234 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
235 | 235 | ||
236 | if (payload_len < 12) | 236 | if (payload_len < 12) |
237 | return -1; | 237 | return -1; |
@@ -240,7 +240,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
240 | keyid = pos[3]; | 240 | keyid = pos[3]; |
241 | iv32 = get_unaligned_le32(pos + 4); | 241 | iv32 = get_unaligned_le32(pos + 4); |
242 | pos += 8; | 242 | pos += 8; |
243 | #ifdef CONFIG_TKIP_DEBUG | 243 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
244 | { | 244 | { |
245 | int i; | 245 | int i; |
246 | printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len); | 246 | printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len); |
@@ -250,7 +250,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
250 | printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n", | 250 | printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n", |
251 | iv16, iv32); | 251 | iv16, iv32); |
252 | } | 252 | } |
253 | #endif /* CONFIG_TKIP_DEBUG */ | 253 | #endif |
254 | 254 | ||
255 | if (!(keyid & (1 << 5))) | 255 | if (!(keyid & (1 << 5))) |
256 | return TKIP_DECRYPT_NO_EXT_IV; | 256 | return TKIP_DECRYPT_NO_EXT_IV; |
@@ -262,14 +262,14 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
262 | (iv32 < key->u.tkip.rx[queue].iv32 || | 262 | (iv32 < key->u.tkip.rx[queue].iv32 || |
263 | (iv32 == key->u.tkip.rx[queue].iv32 && | 263 | (iv32 == key->u.tkip.rx[queue].iv32 && |
264 | iv16 <= key->u.tkip.rx[queue].iv16))) { | 264 | iv16 <= key->u.tkip.rx[queue].iv16))) { |
265 | #ifdef CONFIG_TKIP_DEBUG | 265 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
266 | DECLARE_MAC_BUF(mac); | 266 | DECLARE_MAC_BUF(mac); |
267 | printk(KERN_DEBUG "TKIP replay detected for RX frame from " | 267 | printk(KERN_DEBUG "TKIP replay detected for RX frame from " |
268 | "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", | 268 | "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", |
269 | print_mac(mac, ta), | 269 | print_mac(mac, ta), |
270 | iv32, iv16, key->u.tkip.rx[queue].iv32, | 270 | iv32, iv16, key->u.tkip.rx[queue].iv32, |
271 | key->u.tkip.rx[queue].iv16); | 271 | key->u.tkip.rx[queue].iv16); |
272 | #endif /* CONFIG_TKIP_DEBUG */ | 272 | #endif |
273 | return TKIP_DECRYPT_REPLAY; | 273 | return TKIP_DECRYPT_REPLAY; |
274 | } | 274 | } |
275 | 275 | ||
@@ -283,23 +283,23 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
283 | key->u.tkip.rx[queue].iv32 != iv32) { | 283 | key->u.tkip.rx[queue].iv32 != iv32) { |
284 | /* IV16 wrapped around - perform TKIP phase 1 */ | 284 | /* IV16 wrapped around - perform TKIP phase 1 */ |
285 | tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); | 285 | tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); |
286 | #ifdef CONFIG_TKIP_DEBUG | 286 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
287 | { | 287 | { |
288 | int i; | 288 | int i; |
289 | u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY; | ||
289 | DECLARE_MAC_BUF(mac); | 290 | DECLARE_MAC_BUF(mac); |
290 | printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%s" | 291 | printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%s" |
291 | " TK=", print_mac(mac, ta)); | 292 | " TK=", print_mac(mac, ta)); |
292 | for (i = 0; i < 16; i++) | 293 | for (i = 0; i < 16; i++) |
293 | printk("%02x ", | 294 | printk("%02x ", |
294 | key->conf.key[ | 295 | key->conf.key[key_offset + i]); |
295 | ALG_TKIP_TEMP_ENCR_KEY + i]); | ||
296 | printk("\n"); | 296 | printk("\n"); |
297 | printk(KERN_DEBUG "TKIP decrypt: P1K="); | 297 | printk(KERN_DEBUG "TKIP decrypt: P1K="); |
298 | for (i = 0; i < 5; i++) | 298 | for (i = 0; i < 5; i++) |
299 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); | 299 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); |
300 | printk("\n"); | 300 | printk("\n"); |
301 | } | 301 | } |
302 | #endif /* CONFIG_TKIP_DEBUG */ | 302 | #endif |
303 | if (key->local->ops->update_tkip_key && | 303 | if (key->local->ops->update_tkip_key && |
304 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 304 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
305 | u8 bcast[ETH_ALEN] = | 305 | u8 bcast[ETH_ALEN] = |
@@ -316,7 +316,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
316 | } | 316 | } |
317 | 317 | ||
318 | tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); | 318 | tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); |
319 | #ifdef CONFIG_TKIP_DEBUG | 319 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
320 | { | 320 | { |
321 | int i; | 321 | int i; |
322 | printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key="); | 322 | printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key="); |
@@ -324,7 +324,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
324 | printk("%02x ", rc4key[i]); | 324 | printk("%02x ", rc4key[i]); |
325 | printk("\n"); | 325 | printk("\n"); |
326 | } | 326 | } |
327 | #endif /* CONFIG_TKIP_DEBUG */ | 327 | #endif |
328 | 328 | ||
329 | res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12); | 329 | res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12); |
330 | done: | 330 | done: |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ce06e791bf43..52ab85c4341b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -52,9 +52,8 @@ static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdat | |||
52 | static void ieee80211_dump_frame(const char *ifname, const char *title, | 52 | static void ieee80211_dump_frame(const char *ifname, const char *title, |
53 | const struct sk_buff *skb) | 53 | const struct sk_buff *skb) |
54 | { | 54 | { |
55 | const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 55 | const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
56 | u16 fc; | 56 | unsigned int hdrlen; |
57 | int hdrlen; | ||
58 | DECLARE_MAC_BUF(mac); | 57 | DECLARE_MAC_BUF(mac); |
59 | 58 | ||
60 | printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); | 59 | printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); |
@@ -63,13 +62,12 @@ static void ieee80211_dump_frame(const char *ifname, const char *title, | |||
63 | return; | 62 | return; |
64 | } | 63 | } |
65 | 64 | ||
66 | fc = le16_to_cpu(hdr->frame_control); | 65 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
67 | hdrlen = ieee80211_get_hdrlen(fc); | ||
68 | if (hdrlen > skb->len) | 66 | if (hdrlen > skb->len) |
69 | hdrlen = skb->len; | 67 | hdrlen = skb->len; |
70 | if (hdrlen >= 4) | 68 | if (hdrlen >= 4) |
71 | printk(" FC=0x%04x DUR=0x%04x", | 69 | printk(" FC=0x%04x DUR=0x%04x", |
72 | fc, le16_to_cpu(hdr->duration_id)); | 70 | le16_to_cpu(hdr->frame_control), le16_to_cpu(hdr->duration_id)); |
73 | if (hdrlen >= 10) | 71 | if (hdrlen >= 10) |
74 | printk(" A1=%s", print_mac(mac, hdr->addr1)); | 72 | printk(" A1=%s", print_mac(mac, hdr->addr1)); |
75 | if (hdrlen >= 16) | 73 | if (hdrlen >= 16) |
@@ -87,8 +85,8 @@ static inline void ieee80211_dump_frame(const char *ifname, const char *title, | |||
87 | } | 85 | } |
88 | #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ | 86 | #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ |
89 | 87 | ||
90 | static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | 88 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, |
91 | int next_frag_len) | 89 | int next_frag_len) |
92 | { | 90 | { |
93 | int rate, mrate, erp, dur, i; | 91 | int rate, mrate, erp, dur, i; |
94 | struct ieee80211_rate *txrate; | 92 | struct ieee80211_rate *txrate; |
@@ -140,7 +138,7 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
140 | 138 | ||
141 | /* data/mgmt */ | 139 | /* data/mgmt */ |
142 | if (0 /* FIX: data/mgmt during CFP */) | 140 | if (0 /* FIX: data/mgmt during CFP */) |
143 | return 32768; | 141 | return cpu_to_le16(32768); |
144 | 142 | ||
145 | if (group_addr) /* Group address as the destination - no ACK */ | 143 | if (group_addr) /* Group address as the destination - no ACK */ |
146 | return 0; | 144 | return 0; |
@@ -210,7 +208,7 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
210 | tx->sdata->bss_conf.use_short_preamble); | 208 | tx->sdata->bss_conf.use_short_preamble); |
211 | } | 209 | } |
212 | 210 | ||
213 | return dur; | 211 | return cpu_to_le16(dur); |
214 | } | 212 | } |
215 | 213 | ||
216 | static int inline is_ieee80211_device(struct net_device *dev, | 214 | static int inline is_ieee80211_device(struct net_device *dev, |
@@ -281,7 +279,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
281 | { | 279 | { |
282 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 280 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
283 | 281 | ||
284 | if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24) | 282 | if (ieee80211_hdrlen(hdr->frame_control) >= 24) |
285 | ieee80211_include_sequence(tx->sdata, hdr); | 283 | ieee80211_include_sequence(tx->sdata, hdr); |
286 | 284 | ||
287 | return TX_CONTINUE; | 285 | return TX_CONTINUE; |
@@ -542,9 +540,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
542 | static ieee80211_tx_result | 540 | static ieee80211_tx_result |
543 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | 541 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) |
544 | { | 542 | { |
545 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | 543 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
546 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
547 | u16 dur; | ||
548 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 544 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
549 | struct ieee80211_supported_band *sband; | 545 | struct ieee80211_supported_band *sband; |
550 | 546 | ||
@@ -595,21 +591,13 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
595 | /* Transmit data frames using short preambles if the driver supports | 591 | /* Transmit data frames using short preambles if the driver supports |
596 | * short preambles at the selected rate and short preambles are | 592 | * short preambles at the selected rate and short preambles are |
597 | * available on the network at the current point in time. */ | 593 | * available on the network at the current point in time. */ |
598 | if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | 594 | if (ieee80211_is_data(hdr->frame_control) && |
599 | (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && | 595 | (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && |
600 | tx->sdata->bss_conf.use_short_preamble && | 596 | tx->sdata->bss_conf.use_short_preamble && |
601 | (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { | 597 | (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { |
602 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | 598 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; |
603 | } | 599 | } |
604 | 600 | ||
605 | /* Setup duration field for the first fragment of the frame. Duration | ||
606 | * for remaining fragments will be updated when they are being sent | ||
607 | * to low-level driver in ieee80211_tx(). */ | ||
608 | dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1), | ||
609 | (tx->flags & IEEE80211_TX_FRAGMENTED) ? | ||
610 | tx->extra_frag[0]->len : 0); | ||
611 | hdr->duration_id = cpu_to_le16(dur); | ||
612 | |||
613 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || | 601 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || |
614 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { | 602 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { |
615 | struct ieee80211_rate *rate; | 603 | struct ieee80211_rate *rate; |
@@ -647,7 +635,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
647 | static ieee80211_tx_result | 635 | static ieee80211_tx_result |
648 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | 636 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) |
649 | { | 637 | { |
650 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | 638 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
651 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; | 639 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; |
652 | struct sk_buff **frags, *first, *frag; | 640 | struct sk_buff **frags, *first, *frag; |
653 | int i; | 641 | int i; |
@@ -670,7 +658,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
670 | 658 | ||
671 | first = tx->skb; | 659 | first = tx->skb; |
672 | 660 | ||
673 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 661 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
674 | payload_len = first->len - hdrlen; | 662 | payload_len = first->len - hdrlen; |
675 | per_fragm = frag_threshold - hdrlen - FCS_LEN; | 663 | per_fragm = frag_threshold - hdrlen - FCS_LEN; |
676 | num_fragm = DIV_ROUND_UP(payload_len, per_fragm); | 664 | num_fragm = DIV_ROUND_UP(payload_len, per_fragm); |
@@ -711,6 +699,8 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
711 | fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); | 699 | fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); |
712 | copylen = left > per_fragm ? per_fragm : left; | 700 | copylen = left > per_fragm ? per_fragm : left; |
713 | memcpy(skb_put(frag, copylen), pos, copylen); | 701 | memcpy(skb_put(frag, copylen), pos, copylen); |
702 | memcpy(frag->cb, first->cb, sizeof(frag->cb)); | ||
703 | skb_copy_queue_mapping(frag, first); | ||
714 | 704 | ||
715 | pos += copylen; | 705 | pos += copylen; |
716 | left -= copylen; | 706 | left -= copylen; |
@@ -755,6 +745,36 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | |||
755 | } | 745 | } |
756 | 746 | ||
757 | static ieee80211_tx_result | 747 | static ieee80211_tx_result |
748 | ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | ||
749 | { | ||
750 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
751 | int next_len, i; | ||
752 | int group_addr = is_multicast_ether_addr(hdr->addr1); | ||
753 | |||
754 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) { | ||
755 | hdr->duration_id = ieee80211_duration(tx, group_addr, 0); | ||
756 | return TX_CONTINUE; | ||
757 | } | ||
758 | |||
759 | hdr->duration_id = ieee80211_duration(tx, group_addr, | ||
760 | tx->extra_frag[0]->len); | ||
761 | |||
762 | for (i = 0; i < tx->num_extra_frag; i++) { | ||
763 | if (i + 1 < tx->num_extra_frag) { | ||
764 | next_len = tx->extra_frag[i + 1]->len; | ||
765 | } else { | ||
766 | next_len = 0; | ||
767 | tx->rate_idx = tx->last_frag_rate_idx; | ||
768 | } | ||
769 | |||
770 | hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; | ||
771 | hdr->duration_id = ieee80211_duration(tx, 0, next_len); | ||
772 | } | ||
773 | |||
774 | return TX_CONTINUE; | ||
775 | } | ||
776 | |||
777 | static ieee80211_tx_result | ||
758 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | 778 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
759 | { | 779 | { |
760 | int i; | 780 | int i; |
@@ -788,6 +808,7 @@ static ieee80211_tx_handler ieee80211_tx_handlers[] = | |||
788 | ieee80211_tx_h_fragment, | 808 | ieee80211_tx_h_fragment, |
789 | /* handlers after fragment must be aware of tx info fragmentation! */ | 809 | /* handlers after fragment must be aware of tx info fragmentation! */ |
790 | ieee80211_tx_h_encrypt, | 810 | ieee80211_tx_h_encrypt, |
811 | ieee80211_tx_h_calculate_duration, | ||
791 | ieee80211_tx_h_stats, | 812 | ieee80211_tx_h_stats, |
792 | NULL | 813 | NULL |
793 | }; | 814 | }; |
@@ -1083,13 +1104,46 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1083 | return IEEE80211_TX_OK; | 1104 | return IEEE80211_TX_OK; |
1084 | } | 1105 | } |
1085 | 1106 | ||
1107 | /* | ||
1108 | * Invoke TX handlers, return 0 on success and non-zero if the | ||
1109 | * frame was dropped or queued. | ||
1110 | */ | ||
1111 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | ||
1112 | { | ||
1113 | struct ieee80211_local *local = tx->local; | ||
1114 | struct sk_buff *skb = tx->skb; | ||
1115 | ieee80211_tx_handler *handler; | ||
1116 | ieee80211_tx_result res = TX_DROP; | ||
1117 | int i; | ||
1118 | |||
1119 | for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { | ||
1120 | res = (*handler)(tx); | ||
1121 | if (res != TX_CONTINUE) | ||
1122 | break; | ||
1123 | } | ||
1124 | |||
1125 | if (unlikely(res == TX_DROP)) { | ||
1126 | I802_DEBUG_INC(local->tx_handlers_drop); | ||
1127 | dev_kfree_skb(skb); | ||
1128 | for (i = 0; i < tx->num_extra_frag; i++) | ||
1129 | if (tx->extra_frag[i]) | ||
1130 | dev_kfree_skb(tx->extra_frag[i]); | ||
1131 | kfree(tx->extra_frag); | ||
1132 | return -1; | ||
1133 | } else if (unlikely(res == TX_QUEUED)) { | ||
1134 | I802_DEBUG_INC(local->tx_handlers_queued); | ||
1135 | return -1; | ||
1136 | } | ||
1137 | |||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1086 | static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | 1141 | static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) |
1087 | { | 1142 | { |
1088 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1143 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1089 | struct sta_info *sta; | 1144 | struct sta_info *sta; |
1090 | ieee80211_tx_handler *handler; | ||
1091 | struct ieee80211_tx_data tx; | 1145 | struct ieee80211_tx_data tx; |
1092 | ieee80211_tx_result res = TX_DROP, res_prepare; | 1146 | ieee80211_tx_result res_prepare; |
1093 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1147 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1094 | int ret, i; | 1148 | int ret, i; |
1095 | u16 queue; | 1149 | u16 queue; |
@@ -1118,44 +1172,8 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
1118 | tx.channel = local->hw.conf.channel; | 1172 | tx.channel = local->hw.conf.channel; |
1119 | info->band = tx.channel->band; | 1173 | info->band = tx.channel->band; |
1120 | 1174 | ||
1121 | for (handler = ieee80211_tx_handlers; *handler != NULL; | 1175 | if (invoke_tx_handlers(&tx)) |
1122 | handler++) { | 1176 | goto out; |
1123 | res = (*handler)(&tx); | ||
1124 | if (res != TX_CONTINUE) | ||
1125 | break; | ||
1126 | } | ||
1127 | |||
1128 | if (WARN_ON(tx.skb != skb)) | ||
1129 | goto drop; | ||
1130 | |||
1131 | if (unlikely(res == TX_DROP)) { | ||
1132 | I802_DEBUG_INC(local->tx_handlers_drop); | ||
1133 | goto drop; | ||
1134 | } | ||
1135 | |||
1136 | if (unlikely(res == TX_QUEUED)) { | ||
1137 | I802_DEBUG_INC(local->tx_handlers_queued); | ||
1138 | rcu_read_unlock(); | ||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1142 | if (tx.extra_frag) { | ||
1143 | for (i = 0; i < tx.num_extra_frag; i++) { | ||
1144 | int next_len, dur; | ||
1145 | struct ieee80211_hdr *hdr = | ||
1146 | (struct ieee80211_hdr *) | ||
1147 | tx.extra_frag[i]->data; | ||
1148 | |||
1149 | if (i + 1 < tx.num_extra_frag) { | ||
1150 | next_len = tx.extra_frag[i + 1]->len; | ||
1151 | } else { | ||
1152 | next_len = 0; | ||
1153 | tx.rate_idx = tx.last_frag_rate_idx; | ||
1154 | } | ||
1155 | dur = ieee80211_duration(&tx, 0, next_len); | ||
1156 | hdr->duration_id = cpu_to_le16(dur); | ||
1157 | } | ||
1158 | } | ||
1159 | 1177 | ||
1160 | retry: | 1178 | retry: |
1161 | ret = __ieee80211_tx(local, skb, &tx); | 1179 | ret = __ieee80211_tx(local, skb, &tx); |
@@ -1198,6 +1216,7 @@ retry: | |||
1198 | store->last_frag_rate_ctrl_probe = | 1216 | store->last_frag_rate_ctrl_probe = |
1199 | !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); | 1217 | !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); |
1200 | } | 1218 | } |
1219 | out: | ||
1201 | rcu_read_unlock(); | 1220 | rcu_read_unlock(); |
1202 | return 0; | 1221 | return 0; |
1203 | 1222 | ||
@@ -1379,7 +1398,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1379 | struct ieee80211_tx_info *info; | 1398 | struct ieee80211_tx_info *info; |
1380 | struct ieee80211_sub_if_data *sdata; | 1399 | struct ieee80211_sub_if_data *sdata; |
1381 | int ret = 1, head_need; | 1400 | int ret = 1, head_need; |
1382 | u16 ethertype, hdrlen, meshhdrlen = 0, fc; | 1401 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1402 | __le16 fc; | ||
1383 | struct ieee80211_hdr hdr; | 1403 | struct ieee80211_hdr hdr; |
1384 | struct ieee80211s_hdr mesh_hdr; | 1404 | struct ieee80211s_hdr mesh_hdr; |
1385 | const u8 *encaps_data; | 1405 | const u8 *encaps_data; |
@@ -1402,12 +1422,12 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1402 | /* convert Ethernet header to proper 802.11 header (based on | 1422 | /* convert Ethernet header to proper 802.11 header (based on |
1403 | * operation mode) */ | 1423 | * operation mode) */ |
1404 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1424 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
1405 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; | 1425 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); |
1406 | 1426 | ||
1407 | switch (sdata->vif.type) { | 1427 | switch (sdata->vif.type) { |
1408 | case IEEE80211_IF_TYPE_AP: | 1428 | case IEEE80211_IF_TYPE_AP: |
1409 | case IEEE80211_IF_TYPE_VLAN: | 1429 | case IEEE80211_IF_TYPE_VLAN: |
1410 | fc |= IEEE80211_FCTL_FROMDS; | 1430 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1411 | /* DA BSSID SA */ | 1431 | /* DA BSSID SA */ |
1412 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1432 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1413 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1433 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
@@ -1415,7 +1435,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1415 | hdrlen = 24; | 1435 | hdrlen = 24; |
1416 | break; | 1436 | break; |
1417 | case IEEE80211_IF_TYPE_WDS: | 1437 | case IEEE80211_IF_TYPE_WDS: |
1418 | fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; | 1438 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1419 | /* RA TA DA SA */ | 1439 | /* RA TA DA SA */ |
1420 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); | 1440 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); |
1421 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1441 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
@@ -1425,7 +1445,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1425 | break; | 1445 | break; |
1426 | #ifdef CONFIG_MAC80211_MESH | 1446 | #ifdef CONFIG_MAC80211_MESH |
1427 | case IEEE80211_IF_TYPE_MESH_POINT: | 1447 | case IEEE80211_IF_TYPE_MESH_POINT: |
1428 | fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; | 1448 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1429 | /* RA TA DA SA */ | 1449 | /* RA TA DA SA */ |
1430 | if (is_multicast_ether_addr(skb->data)) | 1450 | if (is_multicast_ether_addr(skb->data)) |
1431 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1451 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -1455,7 +1475,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1455 | break; | 1475 | break; |
1456 | #endif | 1476 | #endif |
1457 | case IEEE80211_IF_TYPE_STA: | 1477 | case IEEE80211_IF_TYPE_STA: |
1458 | fc |= IEEE80211_FCTL_TODS; | 1478 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
1459 | /* BSSID SA DA */ | 1479 | /* BSSID SA DA */ |
1460 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); | 1480 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); |
1461 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1481 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
@@ -1490,7 +1510,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1490 | /* receiver and we are QoS enabled, use a QoS type frame */ | 1510 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1491 | if (sta_flags & WLAN_STA_WME && | 1511 | if (sta_flags & WLAN_STA_WME && |
1492 | ieee80211_num_regular_queues(&local->hw) >= 4) { | 1512 | ieee80211_num_regular_queues(&local->hw) >= 4) { |
1493 | fc |= IEEE80211_STYPE_QOS_DATA; | 1513 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1494 | hdrlen += 2; | 1514 | hdrlen += 2; |
1495 | } | 1515 | } |
1496 | 1516 | ||
@@ -1518,7 +1538,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1518 | goto fail; | 1538 | goto fail; |
1519 | } | 1539 | } |
1520 | 1540 | ||
1521 | hdr.frame_control = cpu_to_le16(fc); | 1541 | hdr.frame_control = fc; |
1522 | hdr.duration_id = 0; | 1542 | hdr.duration_id = 0; |
1523 | hdr.seq_ctrl = 0; | 1543 | hdr.seq_ctrl = 0; |
1524 | 1544 | ||
@@ -1587,7 +1607,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1587 | h_pos += meshhdrlen; | 1607 | h_pos += meshhdrlen; |
1588 | } | 1608 | } |
1589 | 1609 | ||
1590 | if (fc & IEEE80211_STYPE_QOS_DATA) { | 1610 | if (ieee80211_is_data_qos(fc)) { |
1591 | __le16 *qos_control; | 1611 | __le16 *qos_control; |
1592 | 1612 | ||
1593 | qos_control = (__le16*) skb_push(skb, 2); | 1613 | qos_control = (__le16*) skb_push(skb, 2); |
@@ -1845,8 +1865,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1845 | mgmt = (struct ieee80211_mgmt *) | 1865 | mgmt = (struct ieee80211_mgmt *) |
1846 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 1866 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
1847 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 1867 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
1848 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 1868 | mgmt->frame_control = |
1849 | IEEE80211_STYPE_BEACON); | 1869 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
1850 | memset(mgmt->da, 0xff, ETH_ALEN); | 1870 | memset(mgmt->da, 0xff, ETH_ALEN); |
1851 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 1871 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
1852 | /* BSSID is left zeroed, wildcard value */ | 1872 | /* BSSID is left zeroed, wildcard value */ |
@@ -1914,10 +1934,9 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1914 | struct ieee80211_rts *rts) | 1934 | struct ieee80211_rts *rts) |
1915 | { | 1935 | { |
1916 | const struct ieee80211_hdr *hdr = frame; | 1936 | const struct ieee80211_hdr *hdr = frame; |
1917 | u16 fctl; | ||
1918 | 1937 | ||
1919 | fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS; | 1938 | rts->frame_control = |
1920 | rts->frame_control = cpu_to_le16(fctl); | 1939 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); |
1921 | rts->duration = ieee80211_rts_duration(hw, vif, frame_len, | 1940 | rts->duration = ieee80211_rts_duration(hw, vif, frame_len, |
1922 | frame_txctl); | 1941 | frame_txctl); |
1923 | memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); | 1942 | memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); |
@@ -1931,10 +1950,9 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1931 | struct ieee80211_cts *cts) | 1950 | struct ieee80211_cts *cts) |
1932 | { | 1951 | { |
1933 | const struct ieee80211_hdr *hdr = frame; | 1952 | const struct ieee80211_hdr *hdr = frame; |
1934 | u16 fctl; | ||
1935 | 1953 | ||
1936 | fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS; | 1954 | cts->frame_control = |
1937 | cts->frame_control = cpu_to_le16(fctl); | 1955 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); |
1938 | cts->duration = ieee80211_ctstoself_duration(hw, vif, | 1956 | cts->duration = ieee80211_ctstoself_duration(hw, vif, |
1939 | frame_len, frame_txctl); | 1957 | frame_len, frame_txctl); |
1940 | memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); | 1958 | memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); |
@@ -1948,9 +1966,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
1948 | struct ieee80211_local *local = hw_to_local(hw); | 1966 | struct ieee80211_local *local = hw_to_local(hw); |
1949 | struct sk_buff *skb = NULL; | 1967 | struct sk_buff *skb = NULL; |
1950 | struct sta_info *sta; | 1968 | struct sta_info *sta; |
1951 | ieee80211_tx_handler *handler; | ||
1952 | struct ieee80211_tx_data tx; | 1969 | struct ieee80211_tx_data tx; |
1953 | ieee80211_tx_result res = TX_DROP; | ||
1954 | struct net_device *bdev; | 1970 | struct net_device *bdev; |
1955 | struct ieee80211_sub_if_data *sdata; | 1971 | struct ieee80211_sub_if_data *sdata; |
1956 | struct ieee80211_if_ap *bss = NULL; | 1972 | struct ieee80211_if_ap *bss = NULL; |
@@ -2001,25 +2017,9 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2001 | tx.channel = local->hw.conf.channel; | 2017 | tx.channel = local->hw.conf.channel; |
2002 | info->band = tx.channel->band; | 2018 | info->band = tx.channel->band; |
2003 | 2019 | ||
2004 | for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { | 2020 | if (invoke_tx_handlers(&tx)) |
2005 | res = (*handler)(&tx); | ||
2006 | if (res == TX_DROP || res == TX_QUEUED) | ||
2007 | break; | ||
2008 | } | ||
2009 | |||
2010 | if (WARN_ON(tx.skb != skb)) | ||
2011 | res = TX_DROP; | ||
2012 | |||
2013 | if (res == TX_DROP) { | ||
2014 | I802_DEBUG_INC(local->tx_handlers_drop); | ||
2015 | dev_kfree_skb(skb); | ||
2016 | skb = NULL; | 2021 | skb = NULL; |
2017 | } else if (res == TX_QUEUED) { | 2022 | out: |
2018 | I802_DEBUG_INC(local->tx_handlers_queued); | ||
2019 | skb = NULL; | ||
2020 | } | ||
2021 | |||
2022 | out: | ||
2023 | rcu_read_unlock(); | 2023 | rcu_read_unlock(); |
2024 | 2024 | ||
2025 | return skb; | 2025 | return skb; |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index e7b6344c900a..35b664d00e23 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -84,20 +84,17 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, | |||
84 | struct sk_buff *skb, | 84 | struct sk_buff *skb, |
85 | struct ieee80211_key *key) | 85 | struct ieee80211_key *key) |
86 | { | 86 | { |
87 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 87 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
88 | u16 fc; | 88 | unsigned int hdrlen; |
89 | int hdrlen; | ||
90 | u8 *newhdr; | 89 | u8 *newhdr; |
91 | 90 | ||
92 | fc = le16_to_cpu(hdr->frame_control); | 91 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
93 | fc |= IEEE80211_FCTL_PROTECTED; | ||
94 | hdr->frame_control = cpu_to_le16(fc); | ||
95 | 92 | ||
96 | if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || | 93 | if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || |
97 | skb_headroom(skb) < WEP_IV_LEN)) | 94 | skb_headroom(skb) < WEP_IV_LEN)) |
98 | return NULL; | 95 | return NULL; |
99 | 96 | ||
100 | hdrlen = ieee80211_get_hdrlen(fc); | 97 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
101 | newhdr = skb_push(skb, WEP_IV_LEN); | 98 | newhdr = skb_push(skb, WEP_IV_LEN); |
102 | memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); | 99 | memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); |
103 | ieee80211_wep_get_iv(local, key, newhdr + hdrlen); | 100 | ieee80211_wep_get_iv(local, key, newhdr + hdrlen); |
@@ -109,12 +106,10 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, | |||
109 | struct sk_buff *skb, | 106 | struct sk_buff *skb, |
110 | struct ieee80211_key *key) | 107 | struct ieee80211_key *key) |
111 | { | 108 | { |
112 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 109 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
113 | u16 fc; | 110 | unsigned int hdrlen; |
114 | int hdrlen; | ||
115 | 111 | ||
116 | fc = le16_to_cpu(hdr->frame_control); | 112 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
117 | hdrlen = ieee80211_get_hdrlen(fc); | ||
118 | memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); | 113 | memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); |
119 | skb_pull(skb, WEP_IV_LEN); | 114 | skb_pull(skb, WEP_IV_LEN); |
120 | } | 115 | } |
@@ -224,17 +219,15 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, | |||
224 | u32 klen; | 219 | u32 klen; |
225 | u8 *rc4key; | 220 | u8 *rc4key; |
226 | u8 keyidx; | 221 | u8 keyidx; |
227 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 222 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
228 | u16 fc; | 223 | unsigned int hdrlen; |
229 | int hdrlen; | ||
230 | size_t len; | 224 | size_t len; |
231 | int ret = 0; | 225 | int ret = 0; |
232 | 226 | ||
233 | fc = le16_to_cpu(hdr->frame_control); | 227 | if (!ieee80211_has_protected(hdr->frame_control)) |
234 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
235 | return -1; | 228 | return -1; |
236 | 229 | ||
237 | hdrlen = ieee80211_get_hdrlen(fc); | 230 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
238 | 231 | ||
239 | if (skb->len < 8 + hdrlen) | 232 | if (skb->len < 8 + hdrlen) |
240 | return -1; | 233 | return -1; |
@@ -281,17 +274,15 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, | |||
281 | 274 | ||
282 | u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) | 275 | u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) |
283 | { | 276 | { |
284 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 277 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
285 | u16 fc; | 278 | unsigned int hdrlen; |
286 | int hdrlen; | ||
287 | u8 *ivpos; | 279 | u8 *ivpos; |
288 | u32 iv; | 280 | u32 iv; |
289 | 281 | ||
290 | fc = le16_to_cpu(hdr->frame_control); | 282 | if (!ieee80211_has_protected(hdr->frame_control)) |
291 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
292 | return NULL; | 283 | return NULL; |
293 | 284 | ||
294 | hdrlen = ieee80211_get_hdrlen(fc); | 285 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
295 | ivpos = skb->data + hdrlen; | 286 | ivpos = skb->data + hdrlen; |
296 | iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; | 287 | iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; |
297 | 288 | ||
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 5af3862e7191..df0531c28141 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -135,7 +135,39 @@ static int ieee80211_ioctl_giwname(struct net_device *dev, | |||
135 | struct iw_request_info *info, | 135 | struct iw_request_info *info, |
136 | char *name, char *extra) | 136 | char *name, char *extra) |
137 | { | 137 | { |
138 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
139 | struct ieee80211_supported_band *sband; | ||
140 | u8 is_ht = 0, is_a = 0, is_b = 0, is_g = 0; | ||
141 | |||
142 | |||
143 | sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ]; | ||
144 | if (sband) { | ||
145 | is_a = 1; | ||
146 | is_ht |= sband->ht_info.ht_supported; | ||
147 | } | ||
148 | |||
149 | sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
150 | if (sband) { | ||
151 | int i; | ||
152 | /* Check for mandatory rates */ | ||
153 | for (i = 0; i < sband->n_bitrates; i++) { | ||
154 | if (sband->bitrates[i].bitrate == 10) | ||
155 | is_b = 1; | ||
156 | if (sband->bitrates[i].bitrate == 60) | ||
157 | is_g = 1; | ||
158 | } | ||
159 | is_ht |= sband->ht_info.ht_supported; | ||
160 | } | ||
161 | |||
138 | strcpy(name, "IEEE 802.11"); | 162 | strcpy(name, "IEEE 802.11"); |
163 | if (is_a) | ||
164 | strcat(name, "a"); | ||
165 | if (is_b) | ||
166 | strcat(name, "b"); | ||
167 | if (is_g) | ||
168 | strcat(name, "g"); | ||
169 | if (is_ht) | ||
170 | strcat(name, "n"); | ||
139 | 171 | ||
140 | return 0; | 172 | return 0; |
141 | } | 173 | } |
@@ -567,7 +599,7 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, | |||
567 | if (local->sta_sw_scanning || local->sta_hw_scanning) | 599 | if (local->sta_sw_scanning || local->sta_hw_scanning) |
568 | return -EAGAIN; | 600 | return -EAGAIN; |
569 | 601 | ||
570 | res = ieee80211_sta_scan_results(dev, extra, data->length); | 602 | res = ieee80211_sta_scan_results(dev, info, extra, data->length); |
571 | if (res >= 0) { | 603 | if (res >= 0) { |
572 | data->length = res; | 604 | data->length = res; |
573 | return 0; | 605 | return 0; |
@@ -721,6 +753,9 @@ static int ieee80211_ioctl_siwrts(struct net_device *dev, | |||
721 | 753 | ||
722 | if (rts->disabled) | 754 | if (rts->disabled) |
723 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 755 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
756 | else if (!rts->fixed) | ||
757 | /* if the rts value is not fixed, then take default */ | ||
758 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | ||
724 | else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) | 759 | else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) |
725 | return -EINVAL; | 760 | return -EINVAL; |
726 | else | 761 | else |
@@ -949,6 +984,19 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, | |||
949 | erq->length = sdata->keys[idx]->conf.keylen; | 984 | erq->length = sdata->keys[idx]->conf.keylen; |
950 | erq->flags |= IW_ENCODE_ENABLED; | 985 | erq->flags |= IW_ENCODE_ENABLED; |
951 | 986 | ||
987 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | ||
988 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
989 | switch (ifsta->auth_alg) { | ||
990 | case WLAN_AUTH_OPEN: | ||
991 | case WLAN_AUTH_LEAP: | ||
992 | erq->flags |= IW_ENCODE_OPEN; | ||
993 | break; | ||
994 | case WLAN_AUTH_SHARED_KEY: | ||
995 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
996 | break; | ||
997 | } | ||
998 | } | ||
999 | |||
952 | return 0; | 1000 | return 0; |
953 | } | 1001 | } |
954 | 1002 | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 345e10e9b313..f809761fbfb5 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -49,7 +49,7 @@ static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, | |||
49 | ieee80211_tx_result | 49 | ieee80211_tx_result |
50 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | 50 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) |
51 | { | 51 | { |
52 | u8 *data, *sa, *da, *key, *mic, qos_tid; | 52 | u8 *data, *sa, *da, *key, *mic, qos_tid, key_offset; |
53 | size_t data_len; | 53 | size_t data_len; |
54 | u16 fc; | 54 | u16 fc; |
55 | struct sk_buff *skb = tx->skb; | 55 | struct sk_buff *skb = tx->skb; |
@@ -88,8 +88,12 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
88 | #else | 88 | #else |
89 | authenticator = 1; | 89 | authenticator = 1; |
90 | #endif | 90 | #endif |
91 | key = &tx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY : | 91 | /* At this point we know we're using ALG_TKIP. To get the MIC key |
92 | ALG_TKIP_TEMP_AUTH_RX_MIC_KEY]; | 92 | * we now will rely on the offset from the ieee80211_key_conf::key */ |
93 | key_offset = authenticator ? | ||
94 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY : | ||
95 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
96 | key = &tx->key->conf.key[key_offset]; | ||
93 | mic = skb_put(skb, MICHAEL_MIC_LEN); | 97 | mic = skb_put(skb, MICHAEL_MIC_LEN); |
94 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); | 98 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); |
95 | 99 | ||
@@ -100,7 +104,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
100 | ieee80211_rx_result | 104 | ieee80211_rx_result |
101 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | 105 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) |
102 | { | 106 | { |
103 | u8 *data, *sa, *da, *key = NULL, qos_tid; | 107 | u8 *data, *sa, *da, *key = NULL, qos_tid, key_offset; |
104 | size_t data_len; | 108 | size_t data_len; |
105 | u16 fc; | 109 | u16 fc; |
106 | u8 mic[MICHAEL_MIC_LEN]; | 110 | u8 mic[MICHAEL_MIC_LEN]; |
@@ -131,8 +135,12 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
131 | #else | 135 | #else |
132 | authenticator = 1; | 136 | authenticator = 1; |
133 | #endif | 137 | #endif |
134 | key = &rx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY : | 138 | /* At this point we know we're using ALG_TKIP. To get the MIC key |
135 | ALG_TKIP_TEMP_AUTH_TX_MIC_KEY]; | 139 | * we now will rely on the offset from the ieee80211_key_conf::key */ |
140 | key_offset = authenticator ? | ||
141 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : | ||
142 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
143 | key = &rx->key->conf.key[key_offset]; | ||
136 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); | 144 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); |
137 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { | 145 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { |
138 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 146 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index e4b051dbed61..8aa822730145 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c | |||
@@ -30,39 +30,62 @@ struct rfkill_task { | |||
30 | spinlock_t lock; /* for accessing last and desired state */ | 30 | spinlock_t lock; /* for accessing last and desired state */ |
31 | unsigned long last; /* last schedule */ | 31 | unsigned long last; /* last schedule */ |
32 | enum rfkill_state desired_state; /* on/off */ | 32 | enum rfkill_state desired_state; /* on/off */ |
33 | enum rfkill_state current_state; /* on/off */ | ||
34 | }; | 33 | }; |
35 | 34 | ||
36 | static void rfkill_task_handler(struct work_struct *work) | 35 | static void rfkill_task_handler(struct work_struct *work) |
37 | { | 36 | { |
38 | struct rfkill_task *task = container_of(work, struct rfkill_task, work); | 37 | struct rfkill_task *task = container_of(work, struct rfkill_task, work); |
39 | enum rfkill_state state; | ||
40 | 38 | ||
41 | mutex_lock(&task->mutex); | 39 | mutex_lock(&task->mutex); |
42 | 40 | ||
43 | /* | 41 | rfkill_switch_all(task->type, task->desired_state); |
44 | * Use temp variable to fetch desired state to keep it | ||
45 | * consistent even if rfkill_schedule_toggle() runs in | ||
46 | * another thread or interrupts us. | ||
47 | */ | ||
48 | state = task->desired_state; | ||
49 | 42 | ||
50 | if (state != task->current_state) { | 43 | mutex_unlock(&task->mutex); |
51 | rfkill_switch_all(task->type, state); | 44 | } |
52 | task->current_state = state; | 45 | |
46 | static void rfkill_task_epo_handler(struct work_struct *work) | ||
47 | { | ||
48 | rfkill_epo(); | ||
49 | } | ||
50 | |||
51 | static DECLARE_WORK(epo_work, rfkill_task_epo_handler); | ||
52 | |||
53 | static void rfkill_schedule_epo(void) | ||
54 | { | ||
55 | schedule_work(&epo_work); | ||
56 | } | ||
57 | |||
58 | static void rfkill_schedule_set(struct rfkill_task *task, | ||
59 | enum rfkill_state desired_state) | ||
60 | { | ||
61 | unsigned long flags; | ||
62 | |||
63 | if (unlikely(work_pending(&epo_work))) | ||
64 | return; | ||
65 | |||
66 | spin_lock_irqsave(&task->lock, flags); | ||
67 | |||
68 | if (time_after(jiffies, task->last + msecs_to_jiffies(200))) { | ||
69 | task->desired_state = desired_state; | ||
70 | task->last = jiffies; | ||
71 | schedule_work(&task->work); | ||
53 | } | 72 | } |
54 | 73 | ||
55 | mutex_unlock(&task->mutex); | 74 | spin_unlock_irqrestore(&task->lock, flags); |
56 | } | 75 | } |
57 | 76 | ||
58 | static void rfkill_schedule_toggle(struct rfkill_task *task) | 77 | static void rfkill_schedule_toggle(struct rfkill_task *task) |
59 | { | 78 | { |
60 | unsigned long flags; | 79 | unsigned long flags; |
61 | 80 | ||
81 | if (unlikely(work_pending(&epo_work))) | ||
82 | return; | ||
83 | |||
62 | spin_lock_irqsave(&task->lock, flags); | 84 | spin_lock_irqsave(&task->lock, flags); |
63 | 85 | ||
64 | if (time_after(jiffies, task->last + msecs_to_jiffies(200))) { | 86 | if (time_after(jiffies, task->last + msecs_to_jiffies(200))) { |
65 | task->desired_state = !task->desired_state; | 87 | task->desired_state = |
88 | rfkill_state_complement(task->desired_state); | ||
66 | task->last = jiffies; | 89 | task->last = jiffies; |
67 | schedule_work(&task->work); | 90 | schedule_work(&task->work); |
68 | } | 91 | } |
@@ -70,26 +93,26 @@ static void rfkill_schedule_toggle(struct rfkill_task *task) | |||
70 | spin_unlock_irqrestore(&task->lock, flags); | 93 | spin_unlock_irqrestore(&task->lock, flags); |
71 | } | 94 | } |
72 | 95 | ||
73 | #define DEFINE_RFKILL_TASK(n, t) \ | 96 | #define DEFINE_RFKILL_TASK(n, t) \ |
74 | struct rfkill_task n = { \ | 97 | struct rfkill_task n = { \ |
75 | .work = __WORK_INITIALIZER(n.work, \ | 98 | .work = __WORK_INITIALIZER(n.work, \ |
76 | rfkill_task_handler), \ | 99 | rfkill_task_handler), \ |
77 | .type = t, \ | 100 | .type = t, \ |
78 | .mutex = __MUTEX_INITIALIZER(n.mutex), \ | 101 | .mutex = __MUTEX_INITIALIZER(n.mutex), \ |
79 | .lock = __SPIN_LOCK_UNLOCKED(n.lock), \ | 102 | .lock = __SPIN_LOCK_UNLOCKED(n.lock), \ |
80 | .desired_state = RFKILL_STATE_ON, \ | 103 | .desired_state = RFKILL_STATE_UNBLOCKED, \ |
81 | .current_state = RFKILL_STATE_ON, \ | ||
82 | } | 104 | } |
83 | 105 | ||
84 | static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN); | 106 | static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN); |
85 | static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH); | 107 | static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH); |
86 | static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); | 108 | static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); |
87 | static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); | 109 | static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); |
110 | static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); | ||
88 | 111 | ||
89 | static void rfkill_event(struct input_handle *handle, unsigned int type, | 112 | static void rfkill_event(struct input_handle *handle, unsigned int type, |
90 | unsigned int code, int down) | 113 | unsigned int code, int data) |
91 | { | 114 | { |
92 | if (type == EV_KEY && down == 1) { | 115 | if (type == EV_KEY && data == 1) { |
93 | switch (code) { | 116 | switch (code) { |
94 | case KEY_WLAN: | 117 | case KEY_WLAN: |
95 | rfkill_schedule_toggle(&rfkill_wlan); | 118 | rfkill_schedule_toggle(&rfkill_wlan); |
@@ -106,6 +129,28 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, | |||
106 | default: | 129 | default: |
107 | break; | 130 | break; |
108 | } | 131 | } |
132 | } else if (type == EV_SW) { | ||
133 | switch (code) { | ||
134 | case SW_RFKILL_ALL: | ||
135 | /* EVERY radio type. data != 0 means radios ON */ | ||
136 | /* handle EPO (emergency power off) through shortcut */ | ||
137 | if (data) { | ||
138 | rfkill_schedule_set(&rfkill_wwan, | ||
139 | RFKILL_STATE_UNBLOCKED); | ||
140 | rfkill_schedule_set(&rfkill_wimax, | ||
141 | RFKILL_STATE_UNBLOCKED); | ||
142 | rfkill_schedule_set(&rfkill_uwb, | ||
143 | RFKILL_STATE_UNBLOCKED); | ||
144 | rfkill_schedule_set(&rfkill_bt, | ||
145 | RFKILL_STATE_UNBLOCKED); | ||
146 | rfkill_schedule_set(&rfkill_wlan, | ||
147 | RFKILL_STATE_UNBLOCKED); | ||
148 | } else | ||
149 | rfkill_schedule_epo(); | ||
150 | break; | ||
151 | default: | ||
152 | break; | ||
153 | } | ||
109 | } | 154 | } |
110 | } | 155 | } |
111 | 156 | ||
@@ -168,6 +213,11 @@ static const struct input_device_id rfkill_ids[] = { | |||
168 | .evbit = { BIT_MASK(EV_KEY) }, | 213 | .evbit = { BIT_MASK(EV_KEY) }, |
169 | .keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) }, | 214 | .keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) }, |
170 | }, | 215 | }, |
216 | { | ||
217 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT, | ||
218 | .evbit = { BIT(EV_SW) }, | ||
219 | .swbit = { [BIT_WORD(SW_RFKILL_ALL)] = BIT_MASK(SW_RFKILL_ALL) }, | ||
220 | }, | ||
171 | { } | 221 | { } |
172 | }; | 222 | }; |
173 | 223 | ||
diff --git a/net/rfkill/rfkill-input.h b/net/rfkill/rfkill-input.h index 4dae5006fc77..f63d05045685 100644 --- a/net/rfkill/rfkill-input.h +++ b/net/rfkill/rfkill-input.h | |||
@@ -12,5 +12,6 @@ | |||
12 | #define __RFKILL_INPUT_H | 12 | #define __RFKILL_INPUT_H |
13 | 13 | ||
14 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state); | 14 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state); |
15 | void rfkill_epo(void); | ||
15 | 16 | ||
16 | #endif /* __RFKILL_INPUT_H */ | 17 | #endif /* __RFKILL_INPUT_H */ |
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 4e10a95de832..ce0e23148cdd 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -39,8 +39,56 @@ MODULE_LICENSE("GPL"); | |||
39 | static LIST_HEAD(rfkill_list); /* list of registered rf switches */ | 39 | static LIST_HEAD(rfkill_list); /* list of registered rf switches */ |
40 | static DEFINE_MUTEX(rfkill_mutex); | 40 | static DEFINE_MUTEX(rfkill_mutex); |
41 | 41 | ||
42 | static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED; | ||
43 | module_param_named(default_state, rfkill_default_state, uint, 0444); | ||
44 | MODULE_PARM_DESC(default_state, | ||
45 | "Default initial state for all radio types, 0 = radio off"); | ||
46 | |||
42 | static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX]; | 47 | static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX]; |
43 | 48 | ||
49 | static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list); | ||
50 | |||
51 | |||
52 | /** | ||
53 | * register_rfkill_notifier - Add notifier to rfkill notifier chain | ||
54 | * @nb: pointer to the new entry to add to the chain | ||
55 | * | ||
56 | * See blocking_notifier_chain_register() for return value and further | ||
57 | * observations. | ||
58 | * | ||
59 | * Adds a notifier to the rfkill notifier chain. The chain will be | ||
60 | * called with a pointer to the relevant rfkill structure as a parameter, | ||
61 | * refer to include/linux/rfkill.h for the possible events. | ||
62 | * | ||
63 | * Notifiers added to this chain are to always return NOTIFY_DONE. This | ||
64 | * chain is a blocking notifier chain: notifiers can sleep. | ||
65 | * | ||
66 | * Calls to this chain may have been done through a workqueue. One must | ||
67 | * assume unordered asynchronous behaviour, there is no way to know if | ||
68 | * actions related to the event that generated the notification have been | ||
69 | * carried out already. | ||
70 | */ | ||
71 | int register_rfkill_notifier(struct notifier_block *nb) | ||
72 | { | ||
73 | return blocking_notifier_chain_register(&rfkill_notifier_list, nb); | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(register_rfkill_notifier); | ||
76 | |||
77 | /** | ||
78 | * unregister_rfkill_notifier - remove notifier from rfkill notifier chain | ||
79 | * @nb: pointer to the entry to remove from the chain | ||
80 | * | ||
81 | * See blocking_notifier_chain_unregister() for return value and further | ||
82 | * observations. | ||
83 | * | ||
84 | * Removes a notifier from the rfkill notifier chain. | ||
85 | */ | ||
86 | int unregister_rfkill_notifier(struct notifier_block *nb) | ||
87 | { | ||
88 | return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb); | ||
89 | } | ||
90 | EXPORT_SYMBOL_GPL(unregister_rfkill_notifier); | ||
91 | |||
44 | 92 | ||
45 | static void rfkill_led_trigger(struct rfkill *rfkill, | 93 | static void rfkill_led_trigger(struct rfkill *rfkill, |
46 | enum rfkill_state state) | 94 | enum rfkill_state state) |
@@ -50,24 +98,99 @@ static void rfkill_led_trigger(struct rfkill *rfkill, | |||
50 | 98 | ||
51 | if (!led->name) | 99 | if (!led->name) |
52 | return; | 100 | return; |
53 | if (state == RFKILL_STATE_OFF) | 101 | if (state != RFKILL_STATE_UNBLOCKED) |
54 | led_trigger_event(led, LED_OFF); | 102 | led_trigger_event(led, LED_OFF); |
55 | else | 103 | else |
56 | led_trigger_event(led, LED_FULL); | 104 | led_trigger_event(led, LED_FULL); |
57 | #endif /* CONFIG_RFKILL_LEDS */ | 105 | #endif /* CONFIG_RFKILL_LEDS */ |
58 | } | 106 | } |
59 | 107 | ||
108 | static void notify_rfkill_state_change(struct rfkill *rfkill) | ||
109 | { | ||
110 | blocking_notifier_call_chain(&rfkill_notifier_list, | ||
111 | RFKILL_STATE_CHANGED, | ||
112 | rfkill); | ||
113 | } | ||
114 | |||
115 | static void update_rfkill_state(struct rfkill *rfkill) | ||
116 | { | ||
117 | enum rfkill_state newstate, oldstate; | ||
118 | |||
119 | if (rfkill->get_state) { | ||
120 | mutex_lock(&rfkill->mutex); | ||
121 | if (!rfkill->get_state(rfkill->data, &newstate)) { | ||
122 | oldstate = rfkill->state; | ||
123 | rfkill->state = newstate; | ||
124 | if (oldstate != newstate) | ||
125 | notify_rfkill_state_change(rfkill); | ||
126 | } | ||
127 | mutex_unlock(&rfkill->mutex); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * rfkill_toggle_radio - wrapper for toggle_radio hook | ||
133 | * calls toggle_radio taking into account a lot of "small" | ||
134 | * details. | ||
135 | * @rfkill: the rfkill struct to use | ||
136 | * @force: calls toggle_radio even if cache says it is not needed, | ||
137 | * and also makes sure notifications of the state will be | ||
138 | * sent even if it didn't change | ||
139 | * @state: the new state to call toggle_radio() with | ||
140 | * | ||
141 | * This wrappen protects and enforces the API for toggle_radio | ||
142 | * calls. Note that @force cannot override a (possibly cached) | ||
143 | * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of | ||
144 | * RFKILL_STATE_HARD_BLOCKED implements either get_state() or | ||
145 | * rfkill_force_state(), so the cache either is bypassed or valid. | ||
146 | * | ||
147 | * Note that we do call toggle_radio for RFKILL_STATE_SOFT_BLOCKED | ||
148 | * even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to | ||
149 | * give the driver a hint that it should double-BLOCK the transmitter. | ||
150 | * | ||
151 | * Caller must have aquired rfkill_mutex. | ||
152 | */ | ||
60 | static int rfkill_toggle_radio(struct rfkill *rfkill, | 153 | static int rfkill_toggle_radio(struct rfkill *rfkill, |
61 | enum rfkill_state state) | 154 | enum rfkill_state state, |
155 | int force) | ||
62 | { | 156 | { |
63 | int retval = 0; | 157 | int retval = 0; |
158 | enum rfkill_state oldstate, newstate; | ||
159 | |||
160 | oldstate = rfkill->state; | ||
64 | 161 | ||
65 | if (state != rfkill->state) { | 162 | if (rfkill->get_state && !force && |
163 | !rfkill->get_state(rfkill->data, &newstate)) | ||
164 | rfkill->state = newstate; | ||
165 | |||
166 | switch (state) { | ||
167 | case RFKILL_STATE_HARD_BLOCKED: | ||
168 | /* typically happens when refreshing hardware state, | ||
169 | * such as on resume */ | ||
170 | state = RFKILL_STATE_SOFT_BLOCKED; | ||
171 | break; | ||
172 | case RFKILL_STATE_UNBLOCKED: | ||
173 | /* force can't override this, only rfkill_force_state() can */ | ||
174 | if (rfkill->state == RFKILL_STATE_HARD_BLOCKED) | ||
175 | return -EPERM; | ||
176 | break; | ||
177 | case RFKILL_STATE_SOFT_BLOCKED: | ||
178 | /* nothing to do, we want to give drivers the hint to double | ||
179 | * BLOCK even a transmitter that is already in state | ||
180 | * RFKILL_STATE_HARD_BLOCKED */ | ||
181 | break; | ||
182 | } | ||
183 | |||
184 | if (force || state != rfkill->state) { | ||
66 | retval = rfkill->toggle_radio(rfkill->data, state); | 185 | retval = rfkill->toggle_radio(rfkill->data, state); |
67 | if (!retval) { | 186 | /* never allow a HARD->SOFT downgrade! */ |
187 | if (!retval && rfkill->state != RFKILL_STATE_HARD_BLOCKED) | ||
68 | rfkill->state = state; | 188 | rfkill->state = state; |
69 | rfkill_led_trigger(rfkill, state); | 189 | } |
70 | } | 190 | |
191 | if (force || rfkill->state != oldstate) { | ||
192 | rfkill_led_trigger(rfkill, rfkill->state); | ||
193 | notify_rfkill_state_change(rfkill); | ||
71 | } | 194 | } |
72 | 195 | ||
73 | return retval; | 196 | return retval; |
@@ -82,7 +205,6 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, | |||
82 | * a specific switch is claimed by userspace in which case it is | 205 | * a specific switch is claimed by userspace in which case it is |
83 | * left alone. | 206 | * left alone. |
84 | */ | 207 | */ |
85 | |||
86 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) | 208 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) |
87 | { | 209 | { |
88 | struct rfkill *rfkill; | 210 | struct rfkill *rfkill; |
@@ -93,13 +215,66 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) | |||
93 | 215 | ||
94 | list_for_each_entry(rfkill, &rfkill_list, node) { | 216 | list_for_each_entry(rfkill, &rfkill_list, node) { |
95 | if ((!rfkill->user_claim) && (rfkill->type == type)) | 217 | if ((!rfkill->user_claim) && (rfkill->type == type)) |
96 | rfkill_toggle_radio(rfkill, state); | 218 | rfkill_toggle_radio(rfkill, state, 0); |
97 | } | 219 | } |
98 | 220 | ||
99 | mutex_unlock(&rfkill_mutex); | 221 | mutex_unlock(&rfkill_mutex); |
100 | } | 222 | } |
101 | EXPORT_SYMBOL(rfkill_switch_all); | 223 | EXPORT_SYMBOL(rfkill_switch_all); |
102 | 224 | ||
225 | /** | ||
226 | * rfkill_epo - emergency power off all transmitters | ||
227 | * | ||
228 | * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring | ||
229 | * everything in its path but rfkill_mutex. | ||
230 | */ | ||
231 | void rfkill_epo(void) | ||
232 | { | ||
233 | struct rfkill *rfkill; | ||
234 | |||
235 | mutex_lock(&rfkill_mutex); | ||
236 | list_for_each_entry(rfkill, &rfkill_list, node) { | ||
237 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | ||
238 | } | ||
239 | mutex_unlock(&rfkill_mutex); | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(rfkill_epo); | ||
242 | |||
243 | /** | ||
244 | * rfkill_force_state - Force the internal rfkill radio state | ||
245 | * @rfkill: pointer to the rfkill class to modify. | ||
246 | * @state: the current radio state the class should be forced to. | ||
247 | * | ||
248 | * This function updates the internal state of the radio cached | ||
249 | * by the rfkill class. It should be used when the driver gets | ||
250 | * a notification by the firmware/hardware of the current *real* | ||
251 | * state of the radio rfkill switch. | ||
252 | * | ||
253 | * It may not be called from an atomic context. | ||
254 | */ | ||
255 | int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) | ||
256 | { | ||
257 | enum rfkill_state oldstate; | ||
258 | |||
259 | if (state != RFKILL_STATE_SOFT_BLOCKED && | ||
260 | state != RFKILL_STATE_UNBLOCKED && | ||
261 | state != RFKILL_STATE_HARD_BLOCKED) | ||
262 | return -EINVAL; | ||
263 | |||
264 | mutex_lock(&rfkill->mutex); | ||
265 | |||
266 | oldstate = rfkill->state; | ||
267 | rfkill->state = state; | ||
268 | |||
269 | if (state != oldstate) | ||
270 | notify_rfkill_state_change(rfkill); | ||
271 | |||
272 | mutex_unlock(&rfkill->mutex); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | EXPORT_SYMBOL(rfkill_force_state); | ||
277 | |||
103 | static ssize_t rfkill_name_show(struct device *dev, | 278 | static ssize_t rfkill_name_show(struct device *dev, |
104 | struct device_attribute *attr, | 279 | struct device_attribute *attr, |
105 | char *buf) | 280 | char *buf) |
@@ -109,31 +284,31 @@ static ssize_t rfkill_name_show(struct device *dev, | |||
109 | return sprintf(buf, "%s\n", rfkill->name); | 284 | return sprintf(buf, "%s\n", rfkill->name); |
110 | } | 285 | } |
111 | 286 | ||
112 | static ssize_t rfkill_type_show(struct device *dev, | 287 | static const char *rfkill_get_type_str(enum rfkill_type type) |
113 | struct device_attribute *attr, | ||
114 | char *buf) | ||
115 | { | 288 | { |
116 | struct rfkill *rfkill = to_rfkill(dev); | 289 | switch (type) { |
117 | const char *type; | ||
118 | |||
119 | switch (rfkill->type) { | ||
120 | case RFKILL_TYPE_WLAN: | 290 | case RFKILL_TYPE_WLAN: |
121 | type = "wlan"; | 291 | return "wlan"; |
122 | break; | ||
123 | case RFKILL_TYPE_BLUETOOTH: | 292 | case RFKILL_TYPE_BLUETOOTH: |
124 | type = "bluetooth"; | 293 | return "bluetooth"; |
125 | break; | ||
126 | case RFKILL_TYPE_UWB: | 294 | case RFKILL_TYPE_UWB: |
127 | type = "ultrawideband"; | 295 | return "ultrawideband"; |
128 | break; | ||
129 | case RFKILL_TYPE_WIMAX: | 296 | case RFKILL_TYPE_WIMAX: |
130 | type = "wimax"; | 297 | return "wimax"; |
131 | break; | 298 | case RFKILL_TYPE_WWAN: |
299 | return "wwan"; | ||
132 | default: | 300 | default: |
133 | BUG(); | 301 | BUG(); |
134 | } | 302 | } |
303 | } | ||
304 | |||
305 | static ssize_t rfkill_type_show(struct device *dev, | ||
306 | struct device_attribute *attr, | ||
307 | char *buf) | ||
308 | { | ||
309 | struct rfkill *rfkill = to_rfkill(dev); | ||
135 | 310 | ||
136 | return sprintf(buf, "%s\n", type); | 311 | return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type)); |
137 | } | 312 | } |
138 | 313 | ||
139 | static ssize_t rfkill_state_show(struct device *dev, | 314 | static ssize_t rfkill_state_show(struct device *dev, |
@@ -142,6 +317,7 @@ static ssize_t rfkill_state_show(struct device *dev, | |||
142 | { | 317 | { |
143 | struct rfkill *rfkill = to_rfkill(dev); | 318 | struct rfkill *rfkill = to_rfkill(dev); |
144 | 319 | ||
320 | update_rfkill_state(rfkill); | ||
145 | return sprintf(buf, "%d\n", rfkill->state); | 321 | return sprintf(buf, "%d\n", rfkill->state); |
146 | } | 322 | } |
147 | 323 | ||
@@ -156,10 +332,14 @@ static ssize_t rfkill_state_store(struct device *dev, | |||
156 | if (!capable(CAP_NET_ADMIN)) | 332 | if (!capable(CAP_NET_ADMIN)) |
157 | return -EPERM; | 333 | return -EPERM; |
158 | 334 | ||
335 | /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ | ||
336 | if (state != RFKILL_STATE_UNBLOCKED && | ||
337 | state != RFKILL_STATE_SOFT_BLOCKED) | ||
338 | return -EINVAL; | ||
339 | |||
159 | if (mutex_lock_interruptible(&rfkill->mutex)) | 340 | if (mutex_lock_interruptible(&rfkill->mutex)) |
160 | return -ERESTARTSYS; | 341 | return -ERESTARTSYS; |
161 | error = rfkill_toggle_radio(rfkill, | 342 | error = rfkill_toggle_radio(rfkill, state, 0); |
162 | state ? RFKILL_STATE_ON : RFKILL_STATE_OFF); | ||
163 | mutex_unlock(&rfkill->mutex); | 343 | mutex_unlock(&rfkill->mutex); |
164 | 344 | ||
165 | return error ? error : count; | 345 | return error ? error : count; |
@@ -200,7 +380,8 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
200 | if (rfkill->user_claim != claim) { | 380 | if (rfkill->user_claim != claim) { |
201 | if (!claim) | 381 | if (!claim) |
202 | rfkill_toggle_radio(rfkill, | 382 | rfkill_toggle_radio(rfkill, |
203 | rfkill_states[rfkill->type]); | 383 | rfkill_states[rfkill->type], |
384 | 0); | ||
204 | rfkill->user_claim = claim; | 385 | rfkill->user_claim = claim; |
205 | } | 386 | } |
206 | 387 | ||
@@ -233,12 +414,12 @@ static int rfkill_suspend(struct device *dev, pm_message_t state) | |||
233 | 414 | ||
234 | if (dev->power.power_state.event != state.event) { | 415 | if (dev->power.power_state.event != state.event) { |
235 | if (state.event & PM_EVENT_SLEEP) { | 416 | if (state.event & PM_EVENT_SLEEP) { |
236 | mutex_lock(&rfkill->mutex); | 417 | /* Stop transmitter, keep state, no notifies */ |
237 | 418 | update_rfkill_state(rfkill); | |
238 | if (rfkill->state == RFKILL_STATE_ON) | ||
239 | rfkill->toggle_radio(rfkill->data, | ||
240 | RFKILL_STATE_OFF); | ||
241 | 419 | ||
420 | mutex_lock(&rfkill->mutex); | ||
421 | rfkill->toggle_radio(rfkill->data, | ||
422 | RFKILL_STATE_SOFT_BLOCKED); | ||
242 | mutex_unlock(&rfkill->mutex); | 423 | mutex_unlock(&rfkill->mutex); |
243 | } | 424 | } |
244 | 425 | ||
@@ -255,8 +436,8 @@ static int rfkill_resume(struct device *dev) | |||
255 | if (dev->power.power_state.event != PM_EVENT_ON) { | 436 | if (dev->power.power_state.event != PM_EVENT_ON) { |
256 | mutex_lock(&rfkill->mutex); | 437 | mutex_lock(&rfkill->mutex); |
257 | 438 | ||
258 | if (rfkill->state == RFKILL_STATE_ON) | 439 | /* restore radio state AND notify everybody */ |
259 | rfkill->toggle_radio(rfkill->data, RFKILL_STATE_ON); | 440 | rfkill_toggle_radio(rfkill, rfkill->state, 1); |
260 | 441 | ||
261 | mutex_unlock(&rfkill->mutex); | 442 | mutex_unlock(&rfkill->mutex); |
262 | } | 443 | } |
@@ -269,12 +450,51 @@ static int rfkill_resume(struct device *dev) | |||
269 | #define rfkill_resume NULL | 450 | #define rfkill_resume NULL |
270 | #endif | 451 | #endif |
271 | 452 | ||
453 | static int rfkill_blocking_uevent_notifier(struct notifier_block *nb, | ||
454 | unsigned long eventid, | ||
455 | void *data) | ||
456 | { | ||
457 | struct rfkill *rfkill = (struct rfkill *)data; | ||
458 | |||
459 | switch (eventid) { | ||
460 | case RFKILL_STATE_CHANGED: | ||
461 | kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); | ||
462 | break; | ||
463 | default: | ||
464 | break; | ||
465 | } | ||
466 | |||
467 | return NOTIFY_DONE; | ||
468 | } | ||
469 | |||
470 | static struct notifier_block rfkill_blocking_uevent_nb = { | ||
471 | .notifier_call = rfkill_blocking_uevent_notifier, | ||
472 | .priority = 0, | ||
473 | }; | ||
474 | |||
475 | static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
476 | { | ||
477 | struct rfkill *rfkill = to_rfkill(dev); | ||
478 | int error; | ||
479 | |||
480 | error = add_uevent_var(env, "RFKILL_NAME=%s", rfkill->name); | ||
481 | if (error) | ||
482 | return error; | ||
483 | error = add_uevent_var(env, "RFKILL_TYPE=%s", | ||
484 | rfkill_get_type_str(rfkill->type)); | ||
485 | if (error) | ||
486 | return error; | ||
487 | error = add_uevent_var(env, "RFKILL_STATE=%d", rfkill->state); | ||
488 | return error; | ||
489 | } | ||
490 | |||
272 | static struct class rfkill_class = { | 491 | static struct class rfkill_class = { |
273 | .name = "rfkill", | 492 | .name = "rfkill", |
274 | .dev_release = rfkill_release, | 493 | .dev_release = rfkill_release, |
275 | .dev_attrs = rfkill_dev_attrs, | 494 | .dev_attrs = rfkill_dev_attrs, |
276 | .suspend = rfkill_suspend, | 495 | .suspend = rfkill_suspend, |
277 | .resume = rfkill_resume, | 496 | .resume = rfkill_resume, |
497 | .dev_uevent = rfkill_dev_uevent, | ||
278 | }; | 498 | }; |
279 | 499 | ||
280 | static int rfkill_add_switch(struct rfkill *rfkill) | 500 | static int rfkill_add_switch(struct rfkill *rfkill) |
@@ -283,7 +503,7 @@ static int rfkill_add_switch(struct rfkill *rfkill) | |||
283 | 503 | ||
284 | mutex_lock(&rfkill_mutex); | 504 | mutex_lock(&rfkill_mutex); |
285 | 505 | ||
286 | error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]); | 506 | error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); |
287 | if (!error) | 507 | if (!error) |
288 | list_add_tail(&rfkill->node, &rfkill_list); | 508 | list_add_tail(&rfkill->node, &rfkill_list); |
289 | 509 | ||
@@ -296,7 +516,7 @@ static void rfkill_remove_switch(struct rfkill *rfkill) | |||
296 | { | 516 | { |
297 | mutex_lock(&rfkill_mutex); | 517 | mutex_lock(&rfkill_mutex); |
298 | list_del_init(&rfkill->node); | 518 | list_del_init(&rfkill->node); |
299 | rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF); | 519 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); |
300 | mutex_unlock(&rfkill_mutex); | 520 | mutex_unlock(&rfkill_mutex); |
301 | } | 521 | } |
302 | 522 | ||
@@ -412,7 +632,7 @@ int rfkill_register(struct rfkill *rfkill) | |||
412 | EXPORT_SYMBOL(rfkill_register); | 632 | EXPORT_SYMBOL(rfkill_register); |
413 | 633 | ||
414 | /** | 634 | /** |
415 | * rfkill_unregister - Uegister a rfkill structure. | 635 | * rfkill_unregister - Unregister a rfkill structure. |
416 | * @rfkill: rfkill structure to be unregistered | 636 | * @rfkill: rfkill structure to be unregistered |
417 | * | 637 | * |
418 | * This function should be called by the network driver during device | 638 | * This function should be called by the network driver during device |
@@ -436,8 +656,13 @@ static int __init rfkill_init(void) | |||
436 | int error; | 656 | int error; |
437 | int i; | 657 | int i; |
438 | 658 | ||
659 | /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ | ||
660 | if (rfkill_default_state != RFKILL_STATE_SOFT_BLOCKED && | ||
661 | rfkill_default_state != RFKILL_STATE_UNBLOCKED) | ||
662 | return -EINVAL; | ||
663 | |||
439 | for (i = 0; i < ARRAY_SIZE(rfkill_states); i++) | 664 | for (i = 0; i < ARRAY_SIZE(rfkill_states); i++) |
440 | rfkill_states[i] = RFKILL_STATE_ON; | 665 | rfkill_states[i] = rfkill_default_state; |
441 | 666 | ||
442 | error = class_register(&rfkill_class); | 667 | error = class_register(&rfkill_class); |
443 | if (error) { | 668 | if (error) { |
@@ -445,11 +670,14 @@ static int __init rfkill_init(void) | |||
445 | return error; | 670 | return error; |
446 | } | 671 | } |
447 | 672 | ||
673 | register_rfkill_notifier(&rfkill_blocking_uevent_nb); | ||
674 | |||
448 | return 0; | 675 | return 0; |
449 | } | 676 | } |
450 | 677 | ||
451 | static void __exit rfkill_exit(void) | 678 | static void __exit rfkill_exit(void) |
452 | { | 679 | { |
680 | unregister_rfkill_notifier(&rfkill_blocking_uevent_nb); | ||
453 | class_unregister(&rfkill_class); | 681 | class_unregister(&rfkill_class); |
454 | } | 682 | } |
455 | 683 | ||
diff --git a/net/socket.c b/net/socket.c index 66c4a8cf6db9..81fe82513046 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -90,6 +90,7 @@ | |||
90 | #include <asm/unistd.h> | 90 | #include <asm/unistd.h> |
91 | 91 | ||
92 | #include <net/compat.h> | 92 | #include <net/compat.h> |
93 | #include <net/wext.h> | ||
93 | 94 | ||
94 | #include <net/sock.h> | 95 | #include <net/sock.h> |
95 | #include <linux/netfilter.h> | 96 | #include <linux/netfilter.h> |
@@ -2210,10 +2211,19 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd, | |||
2210 | { | 2211 | { |
2211 | struct socket *sock = file->private_data; | 2212 | struct socket *sock = file->private_data; |
2212 | int ret = -ENOIOCTLCMD; | 2213 | int ret = -ENOIOCTLCMD; |
2214 | struct sock *sk; | ||
2215 | struct net *net; | ||
2216 | |||
2217 | sk = sock->sk; | ||
2218 | net = sock_net(sk); | ||
2213 | 2219 | ||
2214 | if (sock->ops->compat_ioctl) | 2220 | if (sock->ops->compat_ioctl) |
2215 | ret = sock->ops->compat_ioctl(sock, cmd, arg); | 2221 | ret = sock->ops->compat_ioctl(sock, cmd, arg); |
2216 | 2222 | ||
2223 | if (ret == -ENOIOCTLCMD && | ||
2224 | (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) | ||
2225 | ret = compat_wext_handle_ioctl(net, cmd, arg); | ||
2226 | |||
2217 | return ret; | 2227 | return ret; |
2218 | } | 2228 | } |
2219 | #endif | 2229 | #endif |
diff --git a/net/wireless/wext.c b/net/wireless/wext.c index 947188a5b937..273a84359998 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c | |||
@@ -500,7 +500,7 @@ static int call_commit_handler(struct net_device *dev) | |||
500 | /* | 500 | /* |
501 | * Calculate size of private arguments | 501 | * Calculate size of private arguments |
502 | */ | 502 | */ |
503 | static inline int get_priv_size(__u16 args) | 503 | static int get_priv_size(__u16 args) |
504 | { | 504 | { |
505 | int num = args & IW_PRIV_SIZE_MASK; | 505 | int num = args & IW_PRIV_SIZE_MASK; |
506 | int type = (args & IW_PRIV_TYPE_MASK) >> 12; | 506 | int type = (args & IW_PRIV_TYPE_MASK) >> 12; |
@@ -512,10 +512,9 @@ static inline int get_priv_size(__u16 args) | |||
512 | /* | 512 | /* |
513 | * Re-calculate the size of private arguments | 513 | * Re-calculate the size of private arguments |
514 | */ | 514 | */ |
515 | static inline int adjust_priv_size(__u16 args, | 515 | static int adjust_priv_size(__u16 args, struct iw_point *iwp) |
516 | union iwreq_data * wrqu) | ||
517 | { | 516 | { |
518 | int num = wrqu->data.length; | 517 | int num = iwp->length; |
519 | int max = args & IW_PRIV_SIZE_MASK; | 518 | int max = args & IW_PRIV_SIZE_MASK; |
520 | int type = (args & IW_PRIV_TYPE_MASK) >> 12; | 519 | int type = (args & IW_PRIV_TYPE_MASK) >> 12; |
521 | 520 | ||
@@ -695,19 +694,150 @@ void wext_proc_exit(struct net *net) | |||
695 | */ | 694 | */ |
696 | 695 | ||
697 | /* ---------------------------------------------------------------- */ | 696 | /* ---------------------------------------------------------------- */ |
697 | static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, | ||
698 | const struct iw_ioctl_description *descr, | ||
699 | iw_handler handler, struct net_device *dev, | ||
700 | struct iw_request_info *info) | ||
701 | { | ||
702 | int err, extra_size, user_length = 0, essid_compat = 0; | ||
703 | char *extra; | ||
704 | |||
705 | /* Calculate space needed by arguments. Always allocate | ||
706 | * for max space. | ||
707 | */ | ||
708 | extra_size = descr->max_tokens * descr->token_size; | ||
709 | |||
710 | /* Check need for ESSID compatibility for WE < 21 */ | ||
711 | switch (cmd) { | ||
712 | case SIOCSIWESSID: | ||
713 | case SIOCGIWESSID: | ||
714 | case SIOCSIWNICKN: | ||
715 | case SIOCGIWNICKN: | ||
716 | if (iwp->length == descr->max_tokens + 1) | ||
717 | essid_compat = 1; | ||
718 | else if (IW_IS_SET(cmd) && (iwp->length != 0)) { | ||
719 | char essid[IW_ESSID_MAX_SIZE + 1]; | ||
720 | |||
721 | err = copy_from_user(essid, iwp->pointer, | ||
722 | iwp->length * | ||
723 | descr->token_size); | ||
724 | if (err) | ||
725 | return -EFAULT; | ||
726 | |||
727 | if (essid[iwp->length - 1] == '\0') | ||
728 | essid_compat = 1; | ||
729 | } | ||
730 | break; | ||
731 | default: | ||
732 | break; | ||
733 | } | ||
734 | |||
735 | iwp->length -= essid_compat; | ||
736 | |||
737 | /* Check what user space is giving us */ | ||
738 | if (IW_IS_SET(cmd)) { | ||
739 | /* Check NULL pointer */ | ||
740 | if (!iwp->pointer && iwp->length != 0) | ||
741 | return -EFAULT; | ||
742 | /* Check if number of token fits within bounds */ | ||
743 | if (iwp->length > descr->max_tokens) | ||
744 | return -E2BIG; | ||
745 | if (iwp->length < descr->min_tokens) | ||
746 | return -EINVAL; | ||
747 | } else { | ||
748 | /* Check NULL pointer */ | ||
749 | if (!iwp->pointer) | ||
750 | return -EFAULT; | ||
751 | /* Save user space buffer size for checking */ | ||
752 | user_length = iwp->length; | ||
753 | |||
754 | /* Don't check if user_length > max to allow forward | ||
755 | * compatibility. The test user_length < min is | ||
756 | * implied by the test at the end. | ||
757 | */ | ||
758 | |||
759 | /* Support for very large requests */ | ||
760 | if ((descr->flags & IW_DESCR_FLAG_NOMAX) && | ||
761 | (user_length > descr->max_tokens)) { | ||
762 | /* Allow userspace to GET more than max so | ||
763 | * we can support any size GET requests. | ||
764 | * There is still a limit : -ENOMEM. | ||
765 | */ | ||
766 | extra_size = user_length * descr->token_size; | ||
767 | |||
768 | /* Note : user_length is originally a __u16, | ||
769 | * and token_size is controlled by us, | ||
770 | * so extra_size won't get negative and | ||
771 | * won't overflow... | ||
772 | */ | ||
773 | } | ||
774 | } | ||
775 | |||
776 | /* kzalloc() ensures NULL-termination for essid_compat. */ | ||
777 | extra = kzalloc(extra_size, GFP_KERNEL); | ||
778 | if (!extra) | ||
779 | return -ENOMEM; | ||
780 | |||
781 | /* If it is a SET, get all the extra data in here */ | ||
782 | if (IW_IS_SET(cmd) && (iwp->length != 0)) { | ||
783 | if (copy_from_user(extra, iwp->pointer, | ||
784 | iwp->length * | ||
785 | descr->token_size)) { | ||
786 | err = -EFAULT; | ||
787 | goto out; | ||
788 | } | ||
789 | } | ||
790 | |||
791 | err = handler(dev, info, (union iwreq_data *) iwp, extra); | ||
792 | |||
793 | iwp->length += essid_compat; | ||
794 | |||
795 | /* If we have something to return to the user */ | ||
796 | if (!err && IW_IS_GET(cmd)) { | ||
797 | /* Check if there is enough buffer up there */ | ||
798 | if (user_length < iwp->length) { | ||
799 | err = -E2BIG; | ||
800 | goto out; | ||
801 | } | ||
802 | |||
803 | if (copy_to_user(iwp->pointer, extra, | ||
804 | iwp->length * | ||
805 | descr->token_size)) { | ||
806 | err = -EFAULT; | ||
807 | goto out; | ||
808 | } | ||
809 | } | ||
810 | |||
811 | /* Generate an event to notify listeners of the change */ | ||
812 | if ((descr->flags & IW_DESCR_FLAG_EVENT) && err == -EIWCOMMIT) { | ||
813 | union iwreq_data *data = (union iwreq_data *) iwp; | ||
814 | |||
815 | if (descr->flags & IW_DESCR_FLAG_RESTRICT) | ||
816 | /* If the event is restricted, don't | ||
817 | * export the payload. | ||
818 | */ | ||
819 | wireless_send_event(dev, cmd, data, NULL); | ||
820 | else | ||
821 | wireless_send_event(dev, cmd, data, extra); | ||
822 | } | ||
823 | |||
824 | out: | ||
825 | kfree(extra); | ||
826 | return err; | ||
827 | } | ||
828 | |||
698 | /* | 829 | /* |
699 | * Wrapper to call a standard Wireless Extension handler. | 830 | * Wrapper to call a standard Wireless Extension handler. |
700 | * We do various checks and also take care of moving data between | 831 | * We do various checks and also take care of moving data between |
701 | * user space and kernel space. | 832 | * user space and kernel space. |
702 | */ | 833 | */ |
703 | static int ioctl_standard_call(struct net_device * dev, | 834 | static int ioctl_standard_call(struct net_device * dev, |
704 | struct ifreq * ifr, | 835 | struct iwreq *iwr, |
705 | unsigned int cmd, | 836 | unsigned int cmd, |
837 | struct iw_request_info *info, | ||
706 | iw_handler handler) | 838 | iw_handler handler) |
707 | { | 839 | { |
708 | struct iwreq * iwr = (struct iwreq *) ifr; | ||
709 | const struct iw_ioctl_description * descr; | 840 | const struct iw_ioctl_description * descr; |
710 | struct iw_request_info info; | ||
711 | int ret = -EINVAL; | 841 | int ret = -EINVAL; |
712 | 842 | ||
713 | /* Get the description of the IOCTL */ | 843 | /* Get the description of the IOCTL */ |
@@ -715,145 +845,19 @@ static int ioctl_standard_call(struct net_device * dev, | |||
715 | return -EOPNOTSUPP; | 845 | return -EOPNOTSUPP; |
716 | descr = &(standard_ioctl[cmd - SIOCIWFIRST]); | 846 | descr = &(standard_ioctl[cmd - SIOCIWFIRST]); |
717 | 847 | ||
718 | /* Prepare the call */ | ||
719 | info.cmd = cmd; | ||
720 | info.flags = 0; | ||
721 | |||
722 | /* Check if we have a pointer to user space data or not */ | 848 | /* Check if we have a pointer to user space data or not */ |
723 | if (descr->header_type != IW_HEADER_TYPE_POINT) { | 849 | if (descr->header_type != IW_HEADER_TYPE_POINT) { |
724 | 850 | ||
725 | /* No extra arguments. Trivial to handle */ | 851 | /* No extra arguments. Trivial to handle */ |
726 | ret = handler(dev, &info, &(iwr->u), NULL); | 852 | ret = handler(dev, info, &(iwr->u), NULL); |
727 | 853 | ||
728 | /* Generate an event to notify listeners of the change */ | 854 | /* Generate an event to notify listeners of the change */ |
729 | if ((descr->flags & IW_DESCR_FLAG_EVENT) && | 855 | if ((descr->flags & IW_DESCR_FLAG_EVENT) && |
730 | ((ret == 0) || (ret == -EIWCOMMIT))) | 856 | ((ret == 0) || (ret == -EIWCOMMIT))) |
731 | wireless_send_event(dev, cmd, &(iwr->u), NULL); | 857 | wireless_send_event(dev, cmd, &(iwr->u), NULL); |
732 | } else { | 858 | } else { |
733 | char * extra; | 859 | ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr, |
734 | int extra_size; | 860 | handler, dev, info); |
735 | int user_length = 0; | ||
736 | int err; | ||
737 | int essid_compat = 0; | ||
738 | |||
739 | /* Calculate space needed by arguments. Always allocate | ||
740 | * for max space. Easier, and won't last long... */ | ||
741 | extra_size = descr->max_tokens * descr->token_size; | ||
742 | |||
743 | /* Check need for ESSID compatibility for WE < 21 */ | ||
744 | switch (cmd) { | ||
745 | case SIOCSIWESSID: | ||
746 | case SIOCGIWESSID: | ||
747 | case SIOCSIWNICKN: | ||
748 | case SIOCGIWNICKN: | ||
749 | if (iwr->u.data.length == descr->max_tokens + 1) | ||
750 | essid_compat = 1; | ||
751 | else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { | ||
752 | char essid[IW_ESSID_MAX_SIZE + 1]; | ||
753 | |||
754 | err = copy_from_user(essid, iwr->u.data.pointer, | ||
755 | iwr->u.data.length * | ||
756 | descr->token_size); | ||
757 | if (err) | ||
758 | return -EFAULT; | ||
759 | |||
760 | if (essid[iwr->u.data.length - 1] == '\0') | ||
761 | essid_compat = 1; | ||
762 | } | ||
763 | break; | ||
764 | default: | ||
765 | break; | ||
766 | } | ||
767 | |||
768 | iwr->u.data.length -= essid_compat; | ||
769 | |||
770 | /* Check what user space is giving us */ | ||
771 | if (IW_IS_SET(cmd)) { | ||
772 | /* Check NULL pointer */ | ||
773 | if ((iwr->u.data.pointer == NULL) && | ||
774 | (iwr->u.data.length != 0)) | ||
775 | return -EFAULT; | ||
776 | /* Check if number of token fits within bounds */ | ||
777 | if (iwr->u.data.length > descr->max_tokens) | ||
778 | return -E2BIG; | ||
779 | if (iwr->u.data.length < descr->min_tokens) | ||
780 | return -EINVAL; | ||
781 | } else { | ||
782 | /* Check NULL pointer */ | ||
783 | if (iwr->u.data.pointer == NULL) | ||
784 | return -EFAULT; | ||
785 | /* Save user space buffer size for checking */ | ||
786 | user_length = iwr->u.data.length; | ||
787 | |||
788 | /* Don't check if user_length > max to allow forward | ||
789 | * compatibility. The test user_length < min is | ||
790 | * implied by the test at the end. */ | ||
791 | |||
792 | /* Support for very large requests */ | ||
793 | if ((descr->flags & IW_DESCR_FLAG_NOMAX) && | ||
794 | (user_length > descr->max_tokens)) { | ||
795 | /* Allow userspace to GET more than max so | ||
796 | * we can support any size GET requests. | ||
797 | * There is still a limit : -ENOMEM. */ | ||
798 | extra_size = user_length * descr->token_size; | ||
799 | /* Note : user_length is originally a __u16, | ||
800 | * and token_size is controlled by us, | ||
801 | * so extra_size won't get negative and | ||
802 | * won't overflow... */ | ||
803 | } | ||
804 | } | ||
805 | |||
806 | /* Create the kernel buffer */ | ||
807 | /* kzalloc ensures NULL-termination for essid_compat */ | ||
808 | extra = kzalloc(extra_size, GFP_KERNEL); | ||
809 | if (extra == NULL) | ||
810 | return -ENOMEM; | ||
811 | |||
812 | /* If it is a SET, get all the extra data in here */ | ||
813 | if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { | ||
814 | err = copy_from_user(extra, iwr->u.data.pointer, | ||
815 | iwr->u.data.length * | ||
816 | descr->token_size); | ||
817 | if (err) { | ||
818 | kfree(extra); | ||
819 | return -EFAULT; | ||
820 | } | ||
821 | } | ||
822 | |||
823 | /* Call the handler */ | ||
824 | ret = handler(dev, &info, &(iwr->u), extra); | ||
825 | |||
826 | iwr->u.data.length += essid_compat; | ||
827 | |||
828 | /* If we have something to return to the user */ | ||
829 | if (!ret && IW_IS_GET(cmd)) { | ||
830 | /* Check if there is enough buffer up there */ | ||
831 | if (user_length < iwr->u.data.length) { | ||
832 | kfree(extra); | ||
833 | return -E2BIG; | ||
834 | } | ||
835 | |||
836 | err = copy_to_user(iwr->u.data.pointer, extra, | ||
837 | iwr->u.data.length * | ||
838 | descr->token_size); | ||
839 | if (err) | ||
840 | ret = -EFAULT; | ||
841 | } | ||
842 | |||
843 | /* Generate an event to notify listeners of the change */ | ||
844 | if ((descr->flags & IW_DESCR_FLAG_EVENT) && | ||
845 | ((ret == 0) || (ret == -EIWCOMMIT))) { | ||
846 | if (descr->flags & IW_DESCR_FLAG_RESTRICT) | ||
847 | /* If the event is restricted, don't | ||
848 | * export the payload */ | ||
849 | wireless_send_event(dev, cmd, &(iwr->u), NULL); | ||
850 | else | ||
851 | wireless_send_event(dev, cmd, &(iwr->u), | ||
852 | extra); | ||
853 | } | ||
854 | |||
855 | /* Cleanup - I told you it wasn't that long ;-) */ | ||
856 | kfree(extra); | ||
857 | } | 861 | } |
858 | 862 | ||
859 | /* Call commit handler if needed and defined */ | 863 | /* Call commit handler if needed and defined */ |
@@ -881,25 +885,22 @@ static int ioctl_standard_call(struct net_device * dev, | |||
881 | * a iw_handler but process it in your ioctl handler (i.e. use the | 885 | * a iw_handler but process it in your ioctl handler (i.e. use the |
882 | * old driver API). | 886 | * old driver API). |
883 | */ | 887 | */ |
884 | static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, | 888 | static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, |
885 | unsigned int cmd, iw_handler handler) | 889 | const struct iw_priv_args **descrp) |
886 | { | 890 | { |
887 | struct iwreq * iwr = (struct iwreq *) ifr; | 891 | const struct iw_priv_args *descr; |
888 | const struct iw_priv_args * descr = NULL; | 892 | int i, extra_size; |
889 | struct iw_request_info info; | ||
890 | int extra_size = 0; | ||
891 | int i; | ||
892 | int ret = -EINVAL; | ||
893 | 893 | ||
894 | /* Get the description of the IOCTL */ | 894 | descr = NULL; |
895 | for (i = 0; i < dev->wireless_handlers->num_private_args; i++) | 895 | for (i = 0; i < dev->wireless_handlers->num_private_args; i++) { |
896 | if (cmd == dev->wireless_handlers->private_args[i].cmd) { | 896 | if (cmd == dev->wireless_handlers->private_args[i].cmd) { |
897 | descr = &(dev->wireless_handlers->private_args[i]); | 897 | descr = &dev->wireless_handlers->private_args[i]; |
898 | break; | 898 | break; |
899 | } | 899 | } |
900 | } | ||
900 | 901 | ||
901 | /* Compute the size of the set/get arguments */ | 902 | extra_size = 0; |
902 | if (descr != NULL) { | 903 | if (descr) { |
903 | if (IW_IS_SET(cmd)) { | 904 | if (IW_IS_SET(cmd)) { |
904 | int offset = 0; /* For sub-ioctls */ | 905 | int offset = 0; /* For sub-ioctls */ |
905 | /* Check for sub-ioctl handler */ | 906 | /* Check for sub-ioctl handler */ |
@@ -924,72 +925,77 @@ static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, | |||
924 | extra_size = 0; | 925 | extra_size = 0; |
925 | } | 926 | } |
926 | } | 927 | } |
928 | *descrp = descr; | ||
929 | return extra_size; | ||
930 | } | ||
927 | 931 | ||
928 | /* Prepare the call */ | 932 | static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, |
929 | info.cmd = cmd; | 933 | const struct iw_priv_args *descr, |
930 | info.flags = 0; | 934 | iw_handler handler, struct net_device *dev, |
935 | struct iw_request_info *info, int extra_size) | ||
936 | { | ||
937 | char *extra; | ||
938 | int err; | ||
931 | 939 | ||
932 | /* Check if we have a pointer to user space data or not. */ | 940 | /* Check what user space is giving us */ |
933 | if (extra_size == 0) { | 941 | if (IW_IS_SET(cmd)) { |
934 | /* No extra arguments. Trivial to handle */ | 942 | if (!iwp->pointer && iwp->length != 0) |
935 | ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); | 943 | return -EFAULT; |
936 | } else { | ||
937 | char * extra; | ||
938 | int err; | ||
939 | 944 | ||
940 | /* Check what user space is giving us */ | 945 | if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK)) |
941 | if (IW_IS_SET(cmd)) { | 946 | return -E2BIG; |
942 | /* Check NULL pointer */ | 947 | } else if (!iwp->pointer) |
943 | if ((iwr->u.data.pointer == NULL) && | 948 | return -EFAULT; |
944 | (iwr->u.data.length != 0)) | ||
945 | return -EFAULT; | ||
946 | 949 | ||
947 | /* Does it fits within bounds ? */ | 950 | extra = kmalloc(extra_size, GFP_KERNEL); |
948 | if (iwr->u.data.length > (descr->set_args & | 951 | if (!extra) |
949 | IW_PRIV_SIZE_MASK)) | 952 | return -ENOMEM; |
950 | return -E2BIG; | ||
951 | } else if (iwr->u.data.pointer == NULL) | ||
952 | return -EFAULT; | ||
953 | 953 | ||
954 | /* Always allocate for max space. Easier, and won't last | 954 | /* If it is a SET, get all the extra data in here */ |
955 | * long... */ | 955 | if (IW_IS_SET(cmd) && (iwp->length != 0)) { |
956 | extra = kmalloc(extra_size, GFP_KERNEL); | 956 | if (copy_from_user(extra, iwp->pointer, extra_size)) { |
957 | if (extra == NULL) | 957 | err = -EFAULT; |
958 | return -ENOMEM; | 958 | goto out; |
959 | |||
960 | /* If it is a SET, get all the extra data in here */ | ||
961 | if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { | ||
962 | err = copy_from_user(extra, iwr->u.data.pointer, | ||
963 | extra_size); | ||
964 | if (err) { | ||
965 | kfree(extra); | ||
966 | return -EFAULT; | ||
967 | } | ||
968 | } | 959 | } |
960 | } | ||
969 | 961 | ||
970 | /* Call the handler */ | 962 | /* Call the handler */ |
971 | ret = handler(dev, &info, &(iwr->u), extra); | 963 | err = handler(dev, info, (union iwreq_data *) iwp, extra); |
972 | 964 | ||
973 | /* If we have something to return to the user */ | 965 | /* If we have something to return to the user */ |
974 | if (!ret && IW_IS_GET(cmd)) { | 966 | if (!err && IW_IS_GET(cmd)) { |
967 | /* Adjust for the actual length if it's variable, | ||
968 | * avoid leaking kernel bits outside. | ||
969 | */ | ||
970 | if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) | ||
971 | extra_size = adjust_priv_size(descr->get_args, iwp); | ||
975 | 972 | ||
976 | /* Adjust for the actual length if it's variable, | 973 | if (copy_to_user(iwp->pointer, extra, extra_size)) |
977 | * avoid leaking kernel bits outside. */ | 974 | err = -EFAULT; |
978 | if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) { | 975 | } |
979 | extra_size = adjust_priv_size(descr->get_args, | ||
980 | &(iwr->u)); | ||
981 | } | ||
982 | 976 | ||
983 | err = copy_to_user(iwr->u.data.pointer, extra, | 977 | out: |
984 | extra_size); | 978 | kfree(extra); |
985 | if (err) | 979 | return err; |
986 | ret = -EFAULT; | 980 | } |
987 | } | ||
988 | 981 | ||
989 | /* Cleanup - I told you it wasn't that long ;-) */ | 982 | static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, |
990 | kfree(extra); | 983 | unsigned int cmd, struct iw_request_info *info, |
991 | } | 984 | iw_handler handler) |
985 | { | ||
986 | int extra_size = 0, ret = -EINVAL; | ||
987 | const struct iw_priv_args *descr; | ||
992 | 988 | ||
989 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | ||
990 | |||
991 | /* Check if we have a pointer to user space data or not. */ | ||
992 | if (extra_size == 0) { | ||
993 | /* No extra arguments. Trivial to handle */ | ||
994 | ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); | ||
995 | } else { | ||
996 | ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, | ||
997 | handler, dev, info, extra_size); | ||
998 | } | ||
993 | 999 | ||
994 | /* Call commit handler if needed and defined */ | 1000 | /* Call commit handler if needed and defined */ |
995 | if (ret == -EIWCOMMIT) | 1001 | if (ret == -EIWCOMMIT) |
@@ -999,12 +1005,21 @@ static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, | |||
999 | } | 1005 | } |
1000 | 1006 | ||
1001 | /* ---------------------------------------------------------------- */ | 1007 | /* ---------------------------------------------------------------- */ |
1008 | typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, | ||
1009 | unsigned int, struct iw_request_info *, | ||
1010 | iw_handler); | ||
1011 | |||
1002 | /* | 1012 | /* |
1003 | * Main IOCTl dispatcher. | 1013 | * Main IOCTl dispatcher. |
1004 | * Check the type of IOCTL and call the appropriate wrapper... | 1014 | * Check the type of IOCTL and call the appropriate wrapper... |
1005 | */ | 1015 | */ |
1006 | static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd) | 1016 | static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, |
1017 | unsigned int cmd, | ||
1018 | struct iw_request_info *info, | ||
1019 | wext_ioctl_func standard, | ||
1020 | wext_ioctl_func private) | ||
1007 | { | 1021 | { |
1022 | struct iwreq *iwr = (struct iwreq *) ifr; | ||
1008 | struct net_device *dev; | 1023 | struct net_device *dev; |
1009 | iw_handler handler; | 1024 | iw_handler handler; |
1010 | 1025 | ||
@@ -1019,12 +1034,12 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned i | |||
1019 | * Note that 'cmd' is already filtered in dev_ioctl() with | 1034 | * Note that 'cmd' is already filtered in dev_ioctl() with |
1020 | * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ | 1035 | * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ |
1021 | if (cmd == SIOCGIWSTATS) | 1036 | if (cmd == SIOCGIWSTATS) |
1022 | return ioctl_standard_call(dev, ifr, cmd, | 1037 | return standard(dev, iwr, cmd, info, |
1023 | &iw_handler_get_iwstats); | 1038 | &iw_handler_get_iwstats); |
1024 | 1039 | ||
1025 | if (cmd == SIOCGIWPRIV && dev->wireless_handlers) | 1040 | if (cmd == SIOCGIWPRIV && dev->wireless_handlers) |
1026 | return ioctl_standard_call(dev, ifr, cmd, | 1041 | return standard(dev, iwr, cmd, info, |
1027 | &iw_handler_get_private); | 1042 | &iw_handler_get_private); |
1028 | 1043 | ||
1029 | /* Basic check */ | 1044 | /* Basic check */ |
1030 | if (!netif_device_present(dev)) | 1045 | if (!netif_device_present(dev)) |
@@ -1035,9 +1050,9 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned i | |||
1035 | if (handler) { | 1050 | if (handler) { |
1036 | /* Standard and private are not the same */ | 1051 | /* Standard and private are not the same */ |
1037 | if (cmd < SIOCIWFIRSTPRIV) | 1052 | if (cmd < SIOCIWFIRSTPRIV) |
1038 | return ioctl_standard_call(dev, ifr, cmd, handler); | 1053 | return standard(dev, iwr, cmd, info, handler); |
1039 | else | 1054 | else |
1040 | return ioctl_private_call(dev, ifr, cmd, handler); | 1055 | return private(dev, iwr, cmd, info, handler); |
1041 | } | 1056 | } |
1042 | /* Old driver API : call driver ioctl handler */ | 1057 | /* Old driver API : call driver ioctl handler */ |
1043 | if (dev->do_ioctl) | 1058 | if (dev->do_ioctl) |
@@ -1045,27 +1060,154 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned i | |||
1045 | return -EOPNOTSUPP; | 1060 | return -EOPNOTSUPP; |
1046 | } | 1061 | } |
1047 | 1062 | ||
1048 | /* entry point from dev ioctl */ | 1063 | /* If command is `set a parameter', or `get the encoding parameters', |
1049 | int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | 1064 | * check if the user has the right to do it. |
1050 | void __user *arg) | 1065 | */ |
1066 | static int wext_permission_check(unsigned int cmd) | ||
1051 | { | 1067 | { |
1052 | int ret; | ||
1053 | |||
1054 | /* If command is `set a parameter', or | ||
1055 | * `get the encoding parameters', check if | ||
1056 | * the user has the right to do it */ | ||
1057 | if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE || cmd == SIOCGIWENCODEEXT) | 1068 | if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE || cmd == SIOCGIWENCODEEXT) |
1058 | && !capable(CAP_NET_ADMIN)) | 1069 | && !capable(CAP_NET_ADMIN)) |
1059 | return -EPERM; | 1070 | return -EPERM; |
1060 | 1071 | ||
1072 | return 0; | ||
1073 | } | ||
1074 | |||
1075 | /* entry point from dev ioctl */ | ||
1076 | static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, | ||
1077 | unsigned int cmd, struct iw_request_info *info, | ||
1078 | wext_ioctl_func standard, | ||
1079 | wext_ioctl_func private) | ||
1080 | { | ||
1081 | int ret = wext_permission_check(cmd); | ||
1082 | |||
1083 | if (ret) | ||
1084 | return ret; | ||
1085 | |||
1061 | dev_load(net, ifr->ifr_name); | 1086 | dev_load(net, ifr->ifr_name); |
1062 | rtnl_lock(); | 1087 | rtnl_lock(); |
1063 | ret = wireless_process_ioctl(net, ifr, cmd); | 1088 | ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private); |
1064 | rtnl_unlock(); | 1089 | rtnl_unlock(); |
1065 | if (IW_IS_GET(cmd) && copy_to_user(arg, ifr, sizeof(struct iwreq))) | 1090 | |
1091 | return ret; | ||
1092 | } | ||
1093 | |||
1094 | int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | ||
1095 | void __user *arg) | ||
1096 | { | ||
1097 | struct iw_request_info info = { .cmd = cmd, .flags = 0 }; | ||
1098 | int ret; | ||
1099 | |||
1100 | ret = wext_ioctl_dispatch(net, ifr, cmd, &info, | ||
1101 | ioctl_standard_call, | ||
1102 | ioctl_private_call); | ||
1103 | if (ret >= 0 && | ||
1104 | IW_IS_GET(cmd) && | ||
1105 | copy_to_user(arg, ifr, sizeof(struct iwreq))) | ||
1106 | return -EFAULT; | ||
1107 | |||
1108 | return ret; | ||
1109 | } | ||
1110 | |||
1111 | #ifdef CONFIG_COMPAT | ||
1112 | static int compat_standard_call(struct net_device *dev, | ||
1113 | struct iwreq *iwr, | ||
1114 | unsigned int cmd, | ||
1115 | struct iw_request_info *info, | ||
1116 | iw_handler handler) | ||
1117 | { | ||
1118 | const struct iw_ioctl_description *descr; | ||
1119 | struct compat_iw_point *iwp_compat; | ||
1120 | struct iw_point iwp; | ||
1121 | int err; | ||
1122 | |||
1123 | descr = standard_ioctl + (cmd - SIOCIWFIRST); | ||
1124 | |||
1125 | if (descr->header_type != IW_HEADER_TYPE_POINT) | ||
1126 | return ioctl_standard_call(dev, iwr, cmd, info, handler); | ||
1127 | |||
1128 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | ||
1129 | iwp.pointer = compat_ptr(iwp_compat->pointer); | ||
1130 | iwp.length = iwp_compat->length; | ||
1131 | iwp.flags = iwp_compat->flags; | ||
1132 | |||
1133 | err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info); | ||
1134 | |||
1135 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | ||
1136 | iwp_compat->length = iwp.length; | ||
1137 | iwp_compat->flags = iwp.flags; | ||
1138 | |||
1139 | return err; | ||
1140 | } | ||
1141 | |||
1142 | static int compat_private_call(struct net_device *dev, struct iwreq *iwr, | ||
1143 | unsigned int cmd, struct iw_request_info *info, | ||
1144 | iw_handler handler) | ||
1145 | { | ||
1146 | const struct iw_priv_args *descr; | ||
1147 | int ret, extra_size; | ||
1148 | |||
1149 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | ||
1150 | |||
1151 | /* Check if we have a pointer to user space data or not. */ | ||
1152 | if (extra_size == 0) { | ||
1153 | /* No extra arguments. Trivial to handle */ | ||
1154 | ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); | ||
1155 | } else { | ||
1156 | struct compat_iw_point *iwp_compat; | ||
1157 | struct iw_point iwp; | ||
1158 | |||
1159 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | ||
1160 | iwp.pointer = compat_ptr(iwp_compat->pointer); | ||
1161 | iwp.length = iwp_compat->length; | ||
1162 | iwp.flags = iwp_compat->flags; | ||
1163 | |||
1164 | ret = ioctl_private_iw_point(&iwp, cmd, descr, | ||
1165 | handler, dev, info, extra_size); | ||
1166 | |||
1167 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | ||
1168 | iwp_compat->length = iwp.length; | ||
1169 | iwp_compat->flags = iwp.flags; | ||
1170 | } | ||
1171 | |||
1172 | /* Call commit handler if needed and defined */ | ||
1173 | if (ret == -EIWCOMMIT) | ||
1174 | ret = call_commit_handler(dev); | ||
1175 | |||
1176 | return ret; | ||
1177 | } | ||
1178 | |||
1179 | int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | ||
1180 | unsigned long arg) | ||
1181 | { | ||
1182 | void __user *argp = (void __user *)arg; | ||
1183 | struct iw_request_info info; | ||
1184 | struct iwreq iwr; | ||
1185 | char *colon; | ||
1186 | int ret; | ||
1187 | |||
1188 | if (copy_from_user(&iwr, argp, sizeof(struct iwreq))) | ||
1189 | return -EFAULT; | ||
1190 | |||
1191 | iwr.ifr_name[IFNAMSIZ-1] = 0; | ||
1192 | colon = strchr(iwr.ifr_name, ':'); | ||
1193 | if (colon) | ||
1194 | *colon = 0; | ||
1195 | |||
1196 | info.cmd = cmd; | ||
1197 | info.flags = IW_REQUEST_FLAG_COMPAT; | ||
1198 | |||
1199 | ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, &info, | ||
1200 | compat_standard_call, | ||
1201 | compat_private_call); | ||
1202 | |||
1203 | if (ret >= 0 && | ||
1204 | IW_IS_GET(cmd) && | ||
1205 | copy_to_user(argp, &iwr, sizeof(struct iwreq))) | ||
1066 | return -EFAULT; | 1206 | return -EFAULT; |
1207 | |||
1067 | return ret; | 1208 | return ret; |
1068 | } | 1209 | } |
1210 | #endif | ||
1069 | 1211 | ||
1070 | /************************* EVENT PROCESSING *************************/ | 1212 | /************************* EVENT PROCESSING *************************/ |
1071 | /* | 1213 | /* |