]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/staging-at76_usb-wireless-driver.patch
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / staging-at76_usb-wireless-driver.patch
1 From: Pavel Roskin <proski@gnu.org>
2 Subject: staging: at76_usb wireless driver
3 Patch-mainline: 2.6.28
4
5
6 Add the at76_usb wireless driver to the staging tree while the
7 other kernel driver (out of tree) gets rewritten to use the internal
8 wireless stack.
9
10 This patch comes directly from the Fedora kernel tree, with only the
11 directory placement of the files changed.
12
13 Signed-off-by: Pavel Roskin <proski@gnu.org>
14 Signed-off-by: John W. Linville <linville@tuxdriver.com>
15 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
16
17 ---
18 drivers/staging/Kconfig | 2
19 drivers/staging/Makefile | 1
20 drivers/staging/at76_usb/Kconfig | 8
21 drivers/staging/at76_usb/Makefile | 1
22 drivers/staging/at76_usb/TODO | 2
23 drivers/staging/at76_usb/at76_usb.c | 5559 ++++++++++++++++++++++++++++++++++++
24 drivers/staging/at76_usb/at76_usb.h | 619 ++++
25 7 files changed, 6192 insertions(+)
26
27 --- /dev/null
28 +++ b/drivers/staging/at76_usb/at76_usb.c
29 @@ -0,0 +1,5559 @@
30 +/*
31 + * at76c503/at76c505 USB driver
32 + *
33 + * Copyright (c) 2002 - 2003 Oliver Kurth
34 + * Copyright (c) 2004 Joerg Albert <joerg.albert@gmx.de>
35 + * Copyright (c) 2004 Nick Jones
36 + * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com>
37 + * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org>
38 + *
39 + * This program is free software; you can redistribute it and/or
40 + * modify it under the terms of the GNU General Public License as
41 + * published by the Free Software Foundation; either version 2 of
42 + * the License, or (at your option) any later version.
43 + *
44 + * This file is part of the Berlios driver for WLAN USB devices based on the
45 + * Atmel AT76C503A/505/505A.
46 + *
47 + * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed
48 + */
49 +
50 +#include <linux/init.h>
51 +#include <linux/kernel.h>
52 +#include <linux/sched.h>
53 +#include <linux/errno.h>
54 +#include <linux/slab.h>
55 +#include <linux/module.h>
56 +#include <linux/spinlock.h>
57 +#include <linux/list.h>
58 +#include <linux/usb.h>
59 +#include <linux/netdevice.h>
60 +#include <linux/if_arp.h>
61 +#include <linux/etherdevice.h>
62 +#include <linux/ethtool.h>
63 +#include <linux/wireless.h>
64 +#include <net/iw_handler.h>
65 +#include <net/ieee80211_radiotap.h>
66 +#include <linux/firmware.h>
67 +#include <linux/leds.h>
68 +#include <net/ieee80211.h>
69 +
70 +#include "at76_usb.h"
71 +
72 +/* Version information */
73 +#define DRIVER_NAME "at76_usb"
74 +#define DRIVER_VERSION "0.17"
75 +#define DRIVER_DESC "Atmel at76x USB Wireless LAN Driver"
76 +
77 +/* at76_debug bits */
78 +#define DBG_PROGRESS 0x00000001 /* authentication/accociation */
79 +#define DBG_BSS_TABLE 0x00000002 /* show BSS table after scans */
80 +#define DBG_IOCTL 0x00000004 /* ioctl calls / settings */
81 +#define DBG_MAC_STATE 0x00000008 /* MAC state transitions */
82 +#define DBG_TX_DATA 0x00000010 /* tx header */
83 +#define DBG_TX_DATA_CONTENT 0x00000020 /* tx content */
84 +#define DBG_TX_MGMT 0x00000040 /* tx management */
85 +#define DBG_RX_DATA 0x00000080 /* rx data header */
86 +#define DBG_RX_DATA_CONTENT 0x00000100 /* rx data content */
87 +#define DBG_RX_MGMT 0x00000200 /* rx mgmt frame headers */
88 +#define DBG_RX_BEACON 0x00000400 /* rx beacon */
89 +#define DBG_RX_CTRL 0x00000800 /* rx control */
90 +#define DBG_RX_MGMT_CONTENT 0x00001000 /* rx mgmt content */
91 +#define DBG_RX_FRAGS 0x00002000 /* rx data fragment handling */
92 +#define DBG_DEVSTART 0x00004000 /* fw download, device start */
93 +#define DBG_URB 0x00008000 /* rx urb status, ... */
94 +#define DBG_RX_ATMEL_HDR 0x00010000 /* Atmel-specific Rx headers */
95 +#define DBG_PROC_ENTRY 0x00020000 /* procedure entries/exits */
96 +#define DBG_PM 0x00040000 /* power management settings */
97 +#define DBG_BSS_MATCH 0x00080000 /* BSS match failures */
98 +#define DBG_PARAMS 0x00100000 /* show configured parameters */
99 +#define DBG_WAIT_COMPLETE 0x00200000 /* command completion */
100 +#define DBG_RX_FRAGS_SKB 0x00400000 /* skb header of Rx fragments */
101 +#define DBG_BSS_TABLE_RM 0x00800000 /* purging bss table entries */
102 +#define DBG_MONITOR_MODE 0x01000000 /* monitor mode */
103 +#define DBG_MIB 0x02000000 /* dump all MIBs on startup */
104 +#define DBG_MGMT_TIMER 0x04000000 /* dump mgmt_timer ops */
105 +#define DBG_WE_EVENTS 0x08000000 /* dump wireless events */
106 +#define DBG_FW 0x10000000 /* firmware download */
107 +#define DBG_DFU 0x20000000 /* device firmware upgrade */
108 +
109 +#define DBG_DEFAULTS 0
110 +
111 +/* Use our own dbg macro */
112 +#define at76_dbg(bits, format, arg...) \
113 + do { \
114 + if (at76_debug & (bits)) \
115 + printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , ## arg); \
116 + } while (0)
117 +
118 +static int at76_debug = DBG_DEFAULTS;
119 +
120 +/* Protect against concurrent firmware loading and parsing */
121 +static struct mutex fw_mutex;
122 +
123 +static struct fwentry firmwares[] = {
124 + [0] = {""},
125 + [BOARD_503_ISL3861] = {"atmel_at76c503-i3861.bin"},
126 + [BOARD_503_ISL3863] = {"atmel_at76c503-i3863.bin"},
127 + [BOARD_503] = {"atmel_at76c503-rfmd.bin"},
128 + [BOARD_503_ACC] = {"atmel_at76c503-rfmd-acc.bin"},
129 + [BOARD_505] = {"atmel_at76c505-rfmd.bin"},
130 + [BOARD_505_2958] = {"atmel_at76c505-rfmd2958.bin"},
131 + [BOARD_505A] = {"atmel_at76c505a-rfmd2958.bin"},
132 + [BOARD_505AMX] = {"atmel_at76c505amx-rfmd.bin"},
133 +};
134 +
135 +#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops)
136 +
137 +static struct usb_device_id dev_table[] = {
138 + /*
139 + * at76c503-i3861
140 + */
141 + /* Generic AT76C503/3861 device */
142 + {USB_DEVICE(0x03eb, 0x7603), USB_DEVICE_DATA(BOARD_503_ISL3861)},
143 + /* Linksys WUSB11 v2.1/v2.6 */
144 + {USB_DEVICE(0x066b, 0x2211), USB_DEVICE_DATA(BOARD_503_ISL3861)},
145 + /* Netgear MA101 rev. A */
146 + {USB_DEVICE(0x0864, 0x4100), USB_DEVICE_DATA(BOARD_503_ISL3861)},
147 + /* Tekram U300C / Allnet ALL0193 */
148 + {USB_DEVICE(0x0b3b, 0x1612), USB_DEVICE_DATA(BOARD_503_ISL3861)},
149 + /* HP HN210W J7801A */
150 + {USB_DEVICE(0x03f0, 0x011c), USB_DEVICE_DATA(BOARD_503_ISL3861)},
151 + /* Sitecom/Z-Com/Zyxel M4Y-750 */
152 + {USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861)},
153 + /* Dynalink/Askey WLL013 (intersil) */
154 + {USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861)},
155 + /* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */
156 + {USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861)},
157 + /* BenQ AWL300 */
158 + {USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861)},
159 + /* Addtron AWU-120, Compex WLU11 */
160 + {USB_DEVICE(0x05dd, 0xff31), USB_DEVICE_DATA(BOARD_503_ISL3861)},
161 + /* Intel AP310 AnyPoint II USB */
162 + {USB_DEVICE(0x8086, 0x0200), USB_DEVICE_DATA(BOARD_503_ISL3861)},
163 + /* Dynalink L11U */
164 + {USB_DEVICE(0x0d8e, 0x7100), USB_DEVICE_DATA(BOARD_503_ISL3861)},
165 + /* Arescom WL-210, FCC id 07J-GL2411USB */
166 + {USB_DEVICE(0x0d8e, 0x7110), USB_DEVICE_DATA(BOARD_503_ISL3861)},
167 + /* I-O DATA WN-B11/USB */
168 + {USB_DEVICE(0x04bb, 0x0919), USB_DEVICE_DATA(BOARD_503_ISL3861)},
169 + /* BT Voyager 1010 */
170 + {USB_DEVICE(0x069a, 0x0821), USB_DEVICE_DATA(BOARD_503_ISL3861)},
171 + /*
172 + * at76c503-i3863
173 + */
174 + /* Generic AT76C503/3863 device */
175 + {USB_DEVICE(0x03eb, 0x7604), USB_DEVICE_DATA(BOARD_503_ISL3863)},
176 + /* Samsung SWL-2100U */
177 + {USB_DEVICE(0x055d, 0xa000), USB_DEVICE_DATA(BOARD_503_ISL3863)},
178 + /*
179 + * at76c503-rfmd
180 + */
181 + /* Generic AT76C503/RFMD device */
182 + {USB_DEVICE(0x03eb, 0x7605), USB_DEVICE_DATA(BOARD_503)},
183 + /* Dynalink/Askey WLL013 (rfmd) */
184 + {USB_DEVICE(0x069a, 0x0321), USB_DEVICE_DATA(BOARD_503)},
185 + /* Linksys WUSB11 v2.6 */
186 + {USB_DEVICE(0x077b, 0x2219), USB_DEVICE_DATA(BOARD_503)},
187 + /* Network Everywhere NWU11B */
188 + {USB_DEVICE(0x077b, 0x2227), USB_DEVICE_DATA(BOARD_503)},
189 + /* Netgear MA101 rev. B */
190 + {USB_DEVICE(0x0864, 0x4102), USB_DEVICE_DATA(BOARD_503)},
191 + /* D-Link DWL-120 rev. E */
192 + {USB_DEVICE(0x2001, 0x3200), USB_DEVICE_DATA(BOARD_503)},
193 + /* Actiontec 802UAT1, HWU01150-01UK */
194 + {USB_DEVICE(0x1668, 0x7605), USB_DEVICE_DATA(BOARD_503)},
195 + /* AirVast W-Buddie WN210 */
196 + {USB_DEVICE(0x03eb, 0x4102), USB_DEVICE_DATA(BOARD_503)},
197 + /* Dick Smith Electronics XH1153 802.11b USB adapter */
198 + {USB_DEVICE(0x1371, 0x5743), USB_DEVICE_DATA(BOARD_503)},
199 + /* CNet CNUSB611 */
200 + {USB_DEVICE(0x1371, 0x0001), USB_DEVICE_DATA(BOARD_503)},
201 + /* FiberLine FL-WL200U */
202 + {USB_DEVICE(0x1371, 0x0002), USB_DEVICE_DATA(BOARD_503)},
203 + /* BenQ AWL400 USB stick */
204 + {USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503)},
205 + /* 3Com 3CRSHEW696 */
206 + {USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503)},
207 + /* Siemens Santis ADSL WLAN USB adapter WLL 013 */
208 + {USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503)},
209 + /* Belkin F5D6050, version 2 */
210 + {USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503)},
211 + /* iBlitzz, BWU613 (not *B or *SB) */
212 + {USB_DEVICE(0x07b8, 0xb000), USB_DEVICE_DATA(BOARD_503)},
213 + /* Gigabyte GN-WLBM101 */
214 + {USB_DEVICE(0x1044, 0x8003), USB_DEVICE_DATA(BOARD_503)},
215 + /* Planex GW-US11S */
216 + {USB_DEVICE(0x2019, 0x3220), USB_DEVICE_DATA(BOARD_503)},
217 + /* Internal WLAN adapter in h5[4,5]xx series iPAQs */
218 + {USB_DEVICE(0x049f, 0x0032), USB_DEVICE_DATA(BOARD_503)},
219 + /* Corega Wireless LAN USB-11 mini */
220 + {USB_DEVICE(0x07aa, 0x0011), USB_DEVICE_DATA(BOARD_503)},
221 + /* Corega Wireless LAN USB-11 mini2 */
222 + {USB_DEVICE(0x07aa, 0x0018), USB_DEVICE_DATA(BOARD_503)},
223 + /* Uniden PCW100 */
224 + {USB_DEVICE(0x05dd, 0xff35), USB_DEVICE_DATA(BOARD_503)},
225 + /*
226 + * at76c503-rfmd-acc
227 + */
228 + /* SMC2664W */
229 + {USB_DEVICE(0x083a, 0x3501), USB_DEVICE_DATA(BOARD_503_ACC)},
230 + /* Belkin F5D6050, SMC2662W v2, SMC2662W-AR */
231 + {USB_DEVICE(0x0d5c, 0xa002), USB_DEVICE_DATA(BOARD_503_ACC)},
232 + /*
233 + * at76c505-rfmd
234 + */
235 + /* Generic AT76C505/RFMD */
236 + {USB_DEVICE(0x03eb, 0x7606), USB_DEVICE_DATA(BOARD_505)},
237 + /*
238 + * at76c505-rfmd2958
239 + */
240 + /* Generic AT76C505/RFMD, OvisLink WL-1130USB */
241 + {USB_DEVICE(0x03eb, 0x7613), USB_DEVICE_DATA(BOARD_505_2958)},
242 + /* Fiberline FL-WL240U */
243 + {USB_DEVICE(0x1371, 0x0014), USB_DEVICE_DATA(BOARD_505_2958)},
244 + /* CNet CNUSB-611G */
245 + {USB_DEVICE(0x1371, 0x0013), USB_DEVICE_DATA(BOARD_505_2958)},
246 + /* Linksys WUSB11 v2.8 */
247 + {USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958)},
248 + /* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */
249 + {USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958)},
250 + /* Corega WLAN USB Stick 11 */
251 + {USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958)},
252 + /* Microstar MSI Box MS6978 */
253 + {USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958)},
254 + /*
255 + * at76c505a-rfmd2958
256 + */
257 + /* Generic AT76C505A device */
258 + {USB_DEVICE(0x03eb, 0x7614), USB_DEVICE_DATA(BOARD_505A)},
259 + /* Generic AT76C505AS device */
260 + {USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A)},
261 + /* Siemens Gigaset USB WLAN Adapter 11 */
262 + {USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A)},
263 + /*
264 + * at76c505amx-rfmd
265 + */
266 + /* Generic AT76C505AMX device */
267 + {USB_DEVICE(0x03eb, 0x7615), USB_DEVICE_DATA(BOARD_505AMX)},
268 + {}
269 +};
270 +
271 +MODULE_DEVICE_TABLE(usb, dev_table);
272 +
273 +/* Supported rates of this hardware, bit 7 marks basic rates */
274 +static const u8 hw_rates[] = { 0x82, 0x84, 0x0b, 0x16 };
275 +
276 +/* Frequency of each channel in MHz */
277 +static const long channel_frequency[] = {
278 + 2412, 2417, 2422, 2427, 2432, 2437, 2442,
279 + 2447, 2452, 2457, 2462, 2467, 2472, 2484
280 +};
281 +
282 +#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
283 +
284 +static const char *const preambles[] = { "long", "short", "auto" };
285 +
286 +static const char *const mac_states[] = {
287 + [MAC_INIT] = "INIT",
288 + [MAC_SCANNING] = "SCANNING",
289 + [MAC_AUTH] = "AUTH",
290 + [MAC_ASSOC] = "ASSOC",
291 + [MAC_JOINING] = "JOINING",
292 + [MAC_CONNECTED] = "CONNECTED",
293 + [MAC_OWN_IBSS] = "OWN_IBSS"
294 +};
295 +
296 +/* Firmware download */
297 +/* DFU states */
298 +#define STATE_IDLE 0x00
299 +#define STATE_DETACH 0x01
300 +#define STATE_DFU_IDLE 0x02
301 +#define STATE_DFU_DOWNLOAD_SYNC 0x03
302 +#define STATE_DFU_DOWNLOAD_BUSY 0x04
303 +#define STATE_DFU_DOWNLOAD_IDLE 0x05
304 +#define STATE_DFU_MANIFEST_SYNC 0x06
305 +#define STATE_DFU_MANIFEST 0x07
306 +#define STATE_DFU_MANIFEST_WAIT_RESET 0x08
307 +#define STATE_DFU_UPLOAD_IDLE 0x09
308 +#define STATE_DFU_ERROR 0x0a
309 +
310 +/* DFU commands */
311 +#define DFU_DETACH 0
312 +#define DFU_DNLOAD 1
313 +#define DFU_UPLOAD 2
314 +#define DFU_GETSTATUS 3
315 +#define DFU_CLRSTATUS 4
316 +#define DFU_GETSTATE 5
317 +#define DFU_ABORT 6
318 +
319 +#define FW_BLOCK_SIZE 1024
320 +
321 +struct dfu_status {
322 + unsigned char status;
323 + unsigned char poll_timeout[3];
324 + unsigned char state;
325 + unsigned char string;
326 +} __attribute__((packed));
327 +
328 +static inline int at76_is_intersil(enum board_type board)
329 +{
330 + return (board == BOARD_503_ISL3861 || board == BOARD_503_ISL3863);
331 +}
332 +
333 +static inline int at76_is_503rfmd(enum board_type board)
334 +{
335 + return (board == BOARD_503 || board == BOARD_503_ACC);
336 +}
337 +
338 +static inline int at76_is_505a(enum board_type board)
339 +{
340 + return (board == BOARD_505A || board == BOARD_505AMX);
341 +}
342 +
343 +/* Load a block of the first (internal) part of the firmware */
344 +static int at76_load_int_fw_block(struct usb_device *udev, int blockno,
345 + void *block, int size)
346 +{
347 + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), DFU_DNLOAD,
348 + USB_TYPE_CLASS | USB_DIR_OUT |
349 + USB_RECIP_INTERFACE, blockno, 0, block, size,
350 + USB_CTRL_GET_TIMEOUT);
351 +}
352 +
353 +static int at76_dfu_get_status(struct usb_device *udev,
354 + struct dfu_status *status)
355 +{
356 + int ret;
357 +
358 + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), DFU_GETSTATUS,
359 + USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
360 + 0, 0, status, sizeof(struct dfu_status),
361 + USB_CTRL_GET_TIMEOUT);
362 + return ret;
363 +}
364 +
365 +static u8 at76_dfu_get_state(struct usb_device *udev, u8 *state)
366 +{
367 + int ret;
368 +
369 + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), DFU_GETSTATE,
370 + USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
371 + 0, 0, state, 1, USB_CTRL_GET_TIMEOUT);
372 + return ret;
373 +}
374 +
375 +/* Convert timeout from the DFU status to jiffies */
376 +static inline unsigned long at76_get_timeout(struct dfu_status *s)
377 +{
378 + return msecs_to_jiffies((s->poll_timeout[2] << 16)
379 + | (s->poll_timeout[1] << 8)
380 + | (s->poll_timeout[0]));
381 +}
382 +
383 +/* Load internal firmware from the buffer. If manifest_sync_timeout > 0, use
384 + * its value in jiffies in the MANIFEST_SYNC state. */
385 +static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
386 + int manifest_sync_timeout)
387 +{
388 + u8 *block;
389 + struct dfu_status dfu_stat_buf;
390 + int ret = 0;
391 + int need_dfu_state = 1;
392 + int is_done = 0;
393 + u8 dfu_state = 0;
394 + u32 dfu_timeout = 0;
395 + int bsize = 0;
396 + int blockno = 0;
397 +
398 + at76_dbg(DBG_DFU, "%s( %p, %u, %d)", __func__, buf, size,
399 + manifest_sync_timeout);
400 +
401 + if (!size) {
402 + dev_printk(KERN_ERR, &udev->dev, "FW buffer length invalid!\n");
403 + return -EINVAL;
404 + }
405 +
406 + block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL);
407 + if (!block)
408 + return -ENOMEM;
409 +
410 + do {
411 + if (need_dfu_state) {
412 + ret = at76_dfu_get_state(udev, &dfu_state);
413 + if (ret < 0) {
414 + dev_printk(KERN_ERR, &udev->dev,
415 + "cannot get DFU state: %d\n", ret);
416 + goto exit;
417 + }
418 + need_dfu_state = 0;
419 + }
420 +
421 + switch (dfu_state) {
422 + case STATE_DFU_DOWNLOAD_SYNC:
423 + at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_SYNC");
424 + ret = at76_dfu_get_status(udev, &dfu_stat_buf);
425 + if (ret >= 0) {
426 + dfu_state = dfu_stat_buf.state;
427 + dfu_timeout = at76_get_timeout(&dfu_stat_buf);
428 + need_dfu_state = 0;
429 + } else
430 + dev_printk(KERN_ERR, &udev->dev,
431 + "at76_dfu_get_status returned %d\n",
432 + ret);
433 + break;
434 +
435 + case STATE_DFU_DOWNLOAD_BUSY:
436 + at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_BUSY");
437 + need_dfu_state = 1;
438 +
439 + at76_dbg(DBG_DFU, "DFU: Resetting device");
440 + schedule_timeout_interruptible(dfu_timeout);
441 + break;
442 +
443 + case STATE_DFU_DOWNLOAD_IDLE:
444 + at76_dbg(DBG_DFU, "DOWNLOAD...");
445 + /* fall through */
446 + case STATE_DFU_IDLE:
447 + at76_dbg(DBG_DFU, "DFU IDLE");
448 +
449 + bsize = min_t(int, size, FW_BLOCK_SIZE);
450 + memcpy(block, buf, bsize);
451 + at76_dbg(DBG_DFU, "int fw, size left = %5d, "
452 + "bsize = %4d, blockno = %2d", size, bsize,
453 + blockno);
454 + ret =
455 + at76_load_int_fw_block(udev, blockno, block, bsize);
456 + buf += bsize;
457 + size -= bsize;
458 + blockno++;
459 +
460 + if (ret != bsize)
461 + dev_printk(KERN_ERR, &udev->dev,
462 + "at76_load_int_fw_block "
463 + "returned %d\n", ret);
464 + need_dfu_state = 1;
465 + break;
466 +
467 + case STATE_DFU_MANIFEST_SYNC:
468 + at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_SYNC");
469 +
470 + ret = at76_dfu_get_status(udev, &dfu_stat_buf);
471 + if (ret < 0)
472 + break;
473 +
474 + dfu_state = dfu_stat_buf.state;
475 + dfu_timeout = at76_get_timeout(&dfu_stat_buf);
476 + need_dfu_state = 0;
477 +
478 + /* override the timeout from the status response,
479 + needed for AT76C505A */
480 + if (manifest_sync_timeout > 0)
481 + dfu_timeout = manifest_sync_timeout;
482 +
483 + at76_dbg(DBG_DFU, "DFU: Waiting for manifest phase");
484 + schedule_timeout_interruptible(dfu_timeout);
485 + break;
486 +
487 + case STATE_DFU_MANIFEST:
488 + at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST");
489 + is_done = 1;
490 + break;
491 +
492 + case STATE_DFU_MANIFEST_WAIT_RESET:
493 + at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_WAIT_RESET");
494 + is_done = 1;
495 + break;
496 +
497 + case STATE_DFU_UPLOAD_IDLE:
498 + at76_dbg(DBG_DFU, "STATE_DFU_UPLOAD_IDLE");
499 + break;
500 +
501 + case STATE_DFU_ERROR:
502 + at76_dbg(DBG_DFU, "STATE_DFU_ERROR");
503 + ret = -EPIPE;
504 + break;
505 +
506 + default:
507 + at76_dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", dfu_state);
508 + ret = -EINVAL;
509 + break;
510 + }
511 + } while (!is_done && (ret >= 0));
512 +
513 +exit:
514 + kfree(block);
515 + if (ret >= 0)
516 + ret = 0;
517 +
518 + return ret;
519 +}
520 +
521 +/* Report that the scan results are ready */
522 +static inline void at76_iwevent_scan_complete(struct net_device *netdev)
523 +{
524 + union iwreq_data wrqu;
525 + wrqu.data.length = 0;
526 + wrqu.data.flags = 0;
527 + wireless_send_event(netdev, SIOCGIWSCAN, &wrqu, NULL);
528 + at76_dbg(DBG_WE_EVENTS, "%s: SIOCGIWSCAN sent", netdev->name);
529 +}
530 +
531 +static inline void at76_iwevent_bss_connect(struct net_device *netdev,
532 + u8 *bssid)
533 +{
534 + union iwreq_data wrqu;
535 + wrqu.data.length = 0;
536 + wrqu.data.flags = 0;
537 + memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
538 + wrqu.ap_addr.sa_family = ARPHRD_ETHER;
539 + wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL);
540 + at76_dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", netdev->name,
541 + __func__);
542 +}
543 +
544 +static inline void at76_iwevent_bss_disconnect(struct net_device *netdev)
545 +{
546 + union iwreq_data wrqu;
547 + wrqu.data.length = 0;
548 + wrqu.data.flags = 0;
549 + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
550 + wrqu.ap_addr.sa_family = ARPHRD_ETHER;
551 + wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL);
552 + at76_dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", netdev->name,
553 + __func__);
554 +}
555 +
556 +#define HEX2STR_BUFFERS 4
557 +#define HEX2STR_MAX_LEN 64
558 +#define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10)
559 +
560 +/* Convert binary data into hex string */
561 +static char *hex2str(void *buf, int len)
562 +{
563 + static atomic_t a = ATOMIC_INIT(0);
564 + static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1];
565 + char *ret = bufs[atomic_inc_return(&a) & (HEX2STR_BUFFERS - 1)];
566 + char *obuf = ret;
567 + u8 *ibuf = buf;
568 +
569 + if (len > HEX2STR_MAX_LEN)
570 + len = HEX2STR_MAX_LEN;
571 +
572 + if (len <= 0) {
573 + ret[0] = '\0';
574 + return ret;
575 + }
576 +
577 + while (len--) {
578 + *obuf++ = BIN2HEX(*ibuf >> 4);
579 + *obuf++ = BIN2HEX(*ibuf & 0xf);
580 + *obuf++ = '-';
581 + ibuf++;
582 + }
583 + *(--obuf) = '\0';
584 +
585 + return ret;
586 +}
587 +
588 +#define MAC2STR_BUFFERS 4
589 +
590 +static inline char *mac2str(u8 *mac)
591 +{
592 + static atomic_t a = ATOMIC_INIT(0);
593 + static char bufs[MAC2STR_BUFFERS][6 * 3];
594 + char *str;
595 +
596 + str = bufs[atomic_inc_return(&a) & (MAC2STR_BUFFERS - 1)];
597 + sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
598 + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
599 + return str;
600 +}
601 +
602 +/* LED trigger */
603 +static int tx_activity;
604 +static void at76_ledtrig_tx_timerfunc(unsigned long data);
605 +static DEFINE_TIMER(ledtrig_tx_timer, at76_ledtrig_tx_timerfunc, 0, 0);
606 +DEFINE_LED_TRIGGER(ledtrig_tx);
607 +
608 +static void at76_ledtrig_tx_timerfunc(unsigned long data)
609 +{
610 + static int tx_lastactivity;
611 +
612 + if (tx_lastactivity != tx_activity) {
613 + tx_lastactivity = tx_activity;
614 + led_trigger_event(ledtrig_tx, LED_FULL);
615 + mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4);
616 + } else
617 + led_trigger_event(ledtrig_tx, LED_OFF);
618 +}
619 +
620 +static void at76_ledtrig_tx_activity(void)
621 +{
622 + tx_activity++;
623 + if (!timer_pending(&ledtrig_tx_timer))
624 + mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4);
625 +}
626 +
627 +/* Check if the given ssid is hidden */
628 +static inline int at76_is_hidden_ssid(u8 *ssid, int length)
629 +{
630 + static const u8 zeros[32];
631 +
632 + if (length == 0)
633 + return 1;
634 +
635 + if (length == 1 && ssid[0] == ' ')
636 + return 1;
637 +
638 + return (memcmp(ssid, zeros, length) == 0);
639 +}
640 +
641 +static inline void at76_free_bss_list(struct at76_priv *priv)
642 +{
643 + struct list_head *next, *ptr;
644 + unsigned long flags;
645 +
646 + spin_lock_irqsave(&priv->bss_list_spinlock, flags);
647 +
648 + priv->curr_bss = NULL;
649 +
650 + list_for_each_safe(ptr, next, &priv->bss_list) {
651 + list_del(ptr);
652 + kfree(list_entry(ptr, struct bss_info, list));
653 + }
654 +
655 + spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
656 +}
657 +
658 +static int at76_remap(struct usb_device *udev)
659 +{
660 + int ret;
661 + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0a,
662 + USB_TYPE_VENDOR | USB_DIR_OUT |
663 + USB_RECIP_INTERFACE, 0, 0, NULL, 0,
664 + USB_CTRL_GET_TIMEOUT);
665 + if (ret < 0)
666 + return ret;
667 + return 0;
668 +}
669 +
670 +static int at76_get_op_mode(struct usb_device *udev)
671 +{
672 + int ret;
673 + u8 op_mode;
674 +
675 + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
676 + USB_TYPE_VENDOR | USB_DIR_IN |
677 + USB_RECIP_INTERFACE, 0x01, 0, &op_mode, 1,
678 + USB_CTRL_GET_TIMEOUT);
679 + if (ret < 0)
680 + return ret;
681 + else if (ret < 1)
682 + return -EIO;
683 + else
684 + return op_mode;
685 +}
686 +
687 +/* Load a block of the second ("external") part of the firmware */
688 +static inline int at76_load_ext_fw_block(struct usb_device *udev, int blockno,
689 + void *block, int size)
690 +{
691 + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e,
692 + USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
693 + 0x0802, blockno, block, size,
694 + USB_CTRL_GET_TIMEOUT);
695 +}
696 +
697 +static inline int at76_get_hw_cfg(struct usb_device *udev,
698 + union at76_hwcfg *buf, int buf_size)
699 +{
700 + return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
701 + USB_TYPE_VENDOR | USB_DIR_IN |
702 + USB_RECIP_INTERFACE, 0x0a02, 0,
703 + buf, buf_size, USB_CTRL_GET_TIMEOUT);
704 +}
705 +
706 +/* Intersil boards use a different "value" for GetHWConfig requests */
707 +static inline int at76_get_hw_cfg_intersil(struct usb_device *udev,
708 + union at76_hwcfg *buf, int buf_size)
709 +{
710 + return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
711 + USB_TYPE_VENDOR | USB_DIR_IN |
712 + USB_RECIP_INTERFACE, 0x0902, 0,
713 + buf, buf_size, USB_CTRL_GET_TIMEOUT);
714 +}
715 +
716 +/* Get the hardware configuration for the adapter and put it to the appropriate
717 + * fields of 'priv' (the GetHWConfig request and interpretation of the result
718 + * depends on the board type) */
719 +static int at76_get_hw_config(struct at76_priv *priv)
720 +{
721 + int ret;
722 + union at76_hwcfg *hwcfg = kmalloc(sizeof(*hwcfg), GFP_KERNEL);
723 +
724 + if (!hwcfg)
725 + return -ENOMEM;
726 +
727 + if (at76_is_intersil(priv->board_type)) {
728 + ret = at76_get_hw_cfg_intersil(priv->udev, hwcfg,
729 + sizeof(hwcfg->i));
730 + if (ret < 0)
731 + goto exit;
732 + memcpy(priv->mac_addr, hwcfg->i.mac_addr, ETH_ALEN);
733 + priv->regulatory_domain = hwcfg->i.regulatory_domain;
734 + } else if (at76_is_503rfmd(priv->board_type)) {
735 + ret = at76_get_hw_cfg(priv->udev, hwcfg, sizeof(hwcfg->r3));
736 + if (ret < 0)
737 + goto exit;
738 + memcpy(priv->mac_addr, hwcfg->r3.mac_addr, ETH_ALEN);
739 + priv->regulatory_domain = hwcfg->r3.regulatory_domain;
740 + } else {
741 + ret = at76_get_hw_cfg(priv->udev, hwcfg, sizeof(hwcfg->r5));
742 + if (ret < 0)
743 + goto exit;
744 + memcpy(priv->mac_addr, hwcfg->r5.mac_addr, ETH_ALEN);
745 + priv->regulatory_domain = hwcfg->r5.regulatory_domain;
746 + }
747 +
748 +exit:
749 + kfree(hwcfg);
750 + if (ret < 0)
751 + printk(KERN_ERR "%s: cannot get HW Config (error %d)\n",
752 + priv->netdev->name, ret);
753 +
754 + return ret;
755 +}
756 +
757 +static struct reg_domain const *at76_get_reg_domain(u16 code)
758 +{
759 + int i;
760 + static struct reg_domain const fd_tab[] = {
761 + {0x10, "FCC (USA)", 0x7ff}, /* ch 1-11 */
762 + {0x20, "IC (Canada)", 0x7ff}, /* ch 1-11 */
763 + {0x30, "ETSI (most of Europe)", 0x1fff}, /* ch 1-13 */
764 + {0x31, "Spain", 0x600}, /* ch 10-11 */
765 + {0x32, "France", 0x1e00}, /* ch 10-13 */
766 + {0x40, "MKK (Japan)", 0x2000}, /* ch 14 */
767 + {0x41, "MKK1 (Japan)", 0x3fff}, /* ch 1-14 */
768 + {0x50, "Israel", 0x3fc}, /* ch 3-9 */
769 + {0x00, "<unknown>", 0xffffffff} /* ch 1-32 */
770 + };
771 +
772 + /* Last entry is fallback for unknown domain code */
773 + for (i = 0; i < ARRAY_SIZE(fd_tab) - 1; i++)
774 + if (code == fd_tab[i].code)
775 + break;
776 +
777 + return &fd_tab[i];
778 +}
779 +
780 +static inline int at76_get_mib(struct usb_device *udev, u16 mib, void *buf,
781 + int buf_size)
782 +{
783 + int ret;
784 +
785 + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
786 + USB_TYPE_VENDOR | USB_DIR_IN |
787 + USB_RECIP_INTERFACE, mib << 8, 0, buf, buf_size,
788 + USB_CTRL_GET_TIMEOUT);
789 + if (ret >= 0 && ret != buf_size)
790 + return -EIO;
791 + return ret;
792 +}
793 +
794 +/* Return positive number for status, negative for an error */
795 +static inline int at76_get_cmd_status(struct usb_device *udev, u8 cmd)
796 +{
797 + u8 stat_buf[40];
798 + int ret;
799 +
800 + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x22,
801 + USB_TYPE_VENDOR | USB_DIR_IN |
802 + USB_RECIP_INTERFACE, cmd, 0, stat_buf,
803 + sizeof(stat_buf), USB_CTRL_GET_TIMEOUT);
804 + if (ret < 0)
805 + return ret;
806 +
807 + return stat_buf[5];
808 +}
809 +
810 +static int at76_set_card_command(struct usb_device *udev, int cmd, void *buf,
811 + int buf_size)
812 +{
813 + int ret;
814 + struct at76_command *cmd_buf = kmalloc(sizeof(struct at76_command) +
815 + buf_size, GFP_KERNEL);
816 +
817 + if (!cmd_buf)
818 + return -ENOMEM;
819 +
820 + cmd_buf->cmd = cmd;
821 + cmd_buf->reserved = 0;
822 + cmd_buf->size = cpu_to_le16(buf_size);
823 + memcpy(cmd_buf->data, buf, buf_size);
824 +
825 + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e,
826 + USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
827 + 0, 0, cmd_buf,
828 + sizeof(struct at76_command) + buf_size,
829 + USB_CTRL_GET_TIMEOUT);
830 + kfree(cmd_buf);
831 + return ret;
832 +}
833 +
834 +#define MAKE_CMD_STATUS_CASE(c) case (c): return #c
835 +static const char *at76_get_cmd_status_string(u8 cmd_status)
836 +{
837 + switch (cmd_status) {
838 + MAKE_CMD_STATUS_CASE(CMD_STATUS_IDLE);
839 + MAKE_CMD_STATUS_CASE(CMD_STATUS_COMPLETE);
840 + MAKE_CMD_STATUS_CASE(CMD_STATUS_UNKNOWN);
841 + MAKE_CMD_STATUS_CASE(CMD_STATUS_INVALID_PARAMETER);
842 + MAKE_CMD_STATUS_CASE(CMD_STATUS_FUNCTION_NOT_SUPPORTED);
843 + MAKE_CMD_STATUS_CASE(CMD_STATUS_TIME_OUT);
844 + MAKE_CMD_STATUS_CASE(CMD_STATUS_IN_PROGRESS);
845 + MAKE_CMD_STATUS_CASE(CMD_STATUS_HOST_FAILURE);
846 + MAKE_CMD_STATUS_CASE(CMD_STATUS_SCAN_FAILED);
847 + }
848 +
849 + return "UNKNOWN";
850 +}
851 +
852 +/* Wait until the command is completed */
853 +static int at76_wait_completion(struct at76_priv *priv, int cmd)
854 +{
855 + int status = 0;
856 + unsigned long timeout = jiffies + CMD_COMPLETION_TIMEOUT;
857 +
858 + do {
859 + status = at76_get_cmd_status(priv->udev, cmd);
860 + if (status < 0) {
861 + printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n",
862 + priv->netdev->name, status);
863 + break;
864 + }
865 +
866 + at76_dbg(DBG_WAIT_COMPLETE,
867 + "%s: Waiting on cmd %d, status = %d (%s)",
868 + priv->netdev->name, cmd, status,
869 + at76_get_cmd_status_string(status));
870 +
871 + if (status != CMD_STATUS_IN_PROGRESS
872 + && status != CMD_STATUS_IDLE)
873 + break;
874 +
875 + schedule_timeout_interruptible(HZ / 10); /* 100 ms */
876 + if (time_after(jiffies, timeout)) {
877 + printk(KERN_ERR
878 + "%s: completion timeout for command %d\n",
879 + priv->netdev->name, cmd);
880 + status = -ETIMEDOUT;
881 + break;
882 + }
883 + } while (1);
884 +
885 + return status;
886 +}
887 +
888 +static int at76_set_mib(struct at76_priv *priv, struct set_mib_buffer *buf)
889 +{
890 + int ret;
891 +
892 + ret = at76_set_card_command(priv->udev, CMD_SET_MIB, buf,
893 + offsetof(struct set_mib_buffer,
894 + data) + buf->size);
895 + if (ret < 0)
896 + return ret;
897 +
898 + ret = at76_wait_completion(priv, CMD_SET_MIB);
899 + if (ret != CMD_STATUS_COMPLETE) {
900 + printk(KERN_INFO
901 + "%s: set_mib: at76_wait_completion failed "
902 + "with %d\n", priv->netdev->name, ret);
903 + ret = -EIO;
904 + }
905 +
906 + return ret;
907 +}
908 +
909 +/* Return < 0 on error, == 0 if no command sent, == 1 if cmd sent */
910 +static int at76_set_radio(struct at76_priv *priv, int enable)
911 +{
912 + int ret;
913 + int cmd;
914 +
915 + if (priv->radio_on == enable)
916 + return 0;
917 +
918 + cmd = enable ? CMD_RADIO_ON : CMD_RADIO_OFF;
919 +
920 + ret = at76_set_card_command(priv->udev, cmd, NULL, 0);
921 + if (ret < 0)
922 + printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n",
923 + priv->netdev->name, cmd, ret);
924 + else
925 + ret = 1;
926 +
927 + priv->radio_on = enable;
928 + return ret;
929 +}
930 +
931 +/* Set current power save mode (AT76_PM_OFF/AT76_PM_ON/AT76_PM_SMART) */
932 +static int at76_set_pm_mode(struct at76_priv *priv)
933 +{
934 + int ret = 0;
935 +
936 + priv->mib_buf.type = MIB_MAC_MGMT;
937 + priv->mib_buf.size = 1;
938 + priv->mib_buf.index = offsetof(struct mib_mac_mgmt, power_mgmt_mode);
939 + priv->mib_buf.data.byte = priv->pm_mode;
940 +
941 + ret = at76_set_mib(priv, &priv->mib_buf);
942 + if (ret < 0)
943 + printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n",
944 + priv->netdev->name, ret);
945 +
946 + return ret;
947 +}
948 +
949 +/* Set the association id for power save mode */
950 +static int at76_set_associd(struct at76_priv *priv, u16 id)
951 +{
952 + int ret = 0;
953 +
954 + priv->mib_buf.type = MIB_MAC_MGMT;
955 + priv->mib_buf.size = 2;
956 + priv->mib_buf.index = offsetof(struct mib_mac_mgmt, station_id);
957 + priv->mib_buf.data.word = cpu_to_le16(id);
958 +
959 + ret = at76_set_mib(priv, &priv->mib_buf);
960 + if (ret < 0)
961 + printk(KERN_ERR "%s: set_mib (associd) failed: %d\n",
962 + priv->netdev->name, ret);
963 +
964 + return ret;
965 +}
966 +
967 +/* Set the listen interval for power save mode */
968 +static int at76_set_listen_interval(struct at76_priv *priv, u16 interval)
969 +{
970 + int ret = 0;
971 +
972 + priv->mib_buf.type = MIB_MAC;
973 + priv->mib_buf.size = 2;
974 + priv->mib_buf.index = offsetof(struct mib_mac, listen_interval);
975 + priv->mib_buf.data.word = cpu_to_le16(interval);
976 +
977 + ret = at76_set_mib(priv, &priv->mib_buf);
978 + if (ret < 0)
979 + printk(KERN_ERR
980 + "%s: set_mib (listen_interval) failed: %d\n",
981 + priv->netdev->name, ret);
982 +
983 + return ret;
984 +}
985 +
986 +static int at76_set_preamble(struct at76_priv *priv, u8 type)
987 +{
988 + int ret = 0;
989 +
990 + priv->mib_buf.type = MIB_LOCAL;
991 + priv->mib_buf.size = 1;
992 + priv->mib_buf.index = offsetof(struct mib_local, preamble_type);
993 + priv->mib_buf.data.byte = type;
994 +
995 + ret = at76_set_mib(priv, &priv->mib_buf);
996 + if (ret < 0)
997 + printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n",
998 + priv->netdev->name, ret);
999 +
1000 + return ret;
1001 +}
1002 +
1003 +static int at76_set_frag(struct at76_priv *priv, u16 size)
1004 +{
1005 + int ret = 0;
1006 +
1007 + priv->mib_buf.type = MIB_MAC;
1008 + priv->mib_buf.size = 2;
1009 + priv->mib_buf.index = offsetof(struct mib_mac, frag_threshold);
1010 + priv->mib_buf.data.word = cpu_to_le16(size);
1011 +
1012 + ret = at76_set_mib(priv, &priv->mib_buf);
1013 + if (ret < 0)
1014 + printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n",
1015 + priv->netdev->name, ret);
1016 +
1017 + return ret;
1018 +}
1019 +
1020 +static int at76_set_rts(struct at76_priv *priv, u16 size)
1021 +{
1022 + int ret = 0;
1023 +
1024 + priv->mib_buf.type = MIB_MAC;
1025 + priv->mib_buf.size = 2;
1026 + priv->mib_buf.index = offsetof(struct mib_mac, rts_threshold);
1027 + priv->mib_buf.data.word = cpu_to_le16(size);
1028 +
1029 + ret = at76_set_mib(priv, &priv->mib_buf);
1030 + if (ret < 0)
1031 + printk(KERN_ERR "%s: set_mib (rts) failed: %d\n",
1032 + priv->netdev->name, ret);
1033 +
1034 + return ret;
1035 +}
1036 +
1037 +static int at76_set_autorate_fallback(struct at76_priv *priv, int onoff)
1038 +{
1039 + int ret = 0;
1040 +
1041 + priv->mib_buf.type = MIB_LOCAL;
1042 + priv->mib_buf.size = 1;
1043 + priv->mib_buf.index = offsetof(struct mib_local, txautorate_fallback);
1044 + priv->mib_buf.data.byte = onoff;
1045 +
1046 + ret = at76_set_mib(priv, &priv->mib_buf);
1047 + if (ret < 0)
1048 + printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n",
1049 + priv->netdev->name, ret);
1050 +
1051 + return ret;
1052 +}
1053 +
1054 +static int at76_add_mac_address(struct at76_priv *priv, void *addr)
1055 +{
1056 + int ret = 0;
1057 +
1058 + priv->mib_buf.type = MIB_MAC_ADDR;
1059 + priv->mib_buf.size = ETH_ALEN;
1060 + priv->mib_buf.index = offsetof(struct mib_mac_addr, mac_addr);
1061 + memcpy(priv->mib_buf.data.addr, addr, ETH_ALEN);
1062 +
1063 + ret = at76_set_mib(priv, &priv->mib_buf);
1064 + if (ret < 0)
1065 + printk(KERN_ERR "%s: set_mib (MAC_ADDR, mac_addr) failed: %d\n",
1066 + priv->netdev->name, ret);
1067 +
1068 + return ret;
1069 +}
1070 +
1071 +static void at76_dump_mib_mac_addr(struct at76_priv *priv)
1072 +{
1073 + int i;
1074 + int ret;
1075 + struct mib_mac_addr *m = kmalloc(sizeof(struct mib_mac_addr),
1076 + GFP_KERNEL);
1077 +
1078 + if (!m)
1079 + return;
1080 +
1081 + ret = at76_get_mib(priv->udev, MIB_MAC_ADDR, m,
1082 + sizeof(struct mib_mac_addr));
1083 + if (ret < 0) {
1084 + printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n",
1085 + priv->netdev->name, ret);
1086 + goto exit;
1087 + }
1088 +
1089 + at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x",
1090 + priv->netdev->name,
1091 + mac2str(m->mac_addr), m->res[0], m->res[1]);
1092 + for (i = 0; i < ARRAY_SIZE(m->group_addr); i++)
1093 + at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %s, "
1094 + "status %d", priv->netdev->name, i,
1095 + mac2str(m->group_addr[i]), m->group_addr_status[i]);
1096 +exit:
1097 + kfree(m);
1098 +}
1099 +
1100 +static void at76_dump_mib_mac_wep(struct at76_priv *priv)
1101 +{
1102 + int i;
1103 + int ret;
1104 + int key_len;
1105 + struct mib_mac_wep *m = kmalloc(sizeof(struct mib_mac_wep), GFP_KERNEL);
1106 +
1107 + if (!m)
1108 + return;
1109 +
1110 + ret = at76_get_mib(priv->udev, MIB_MAC_WEP, m,
1111 + sizeof(struct mib_mac_wep));
1112 + if (ret < 0) {
1113 + printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n",
1114 + priv->netdev->name, ret);
1115 + goto exit;
1116 + }
1117 +
1118 + at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: priv_invoked %u def_key_id %u "
1119 + "key_len %u excl_unencr %u wep_icv_err %u wep_excluded %u "
1120 + "encr_level %u key %d", priv->netdev->name,
1121 + m->privacy_invoked, m->wep_default_key_id,
1122 + m->wep_key_mapping_len, m->exclude_unencrypted,
1123 + le32_to_cpu(m->wep_icv_error_count),
1124 + le32_to_cpu(m->wep_excluded_count), m->encryption_level,
1125 + m->wep_default_key_id);
1126 +
1127 + key_len = (m->encryption_level == 1) ?
1128 + WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
1129 +
1130 + for (i = 0; i < WEP_KEYS; i++)
1131 + at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %s",
1132 + priv->netdev->name, i,
1133 + hex2str(m->wep_default_keyvalue[i], key_len));
1134 +exit:
1135 + kfree(m);
1136 +}
1137 +
1138 +static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
1139 +{
1140 + int ret;
1141 + struct mib_mac_mgmt *m = kmalloc(sizeof(struct mib_mac_mgmt),
1142 + GFP_KERNEL);
1143 +
1144 + if (!m)
1145 + return;
1146 +
1147 + ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, m,
1148 + sizeof(struct mib_mac_mgmt));
1149 + if (ret < 0) {
1150 + printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n",
1151 + priv->netdev->name, ret);
1152 + goto exit;
1153 + }
1154 +
1155 + at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration "
1156 + "%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d "
1157 + "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d "
1158 + "current_bssid %s current_essid %s current_bss_type %d "
1159 + "pm_mode %d ibss_change %d res %d "
1160 + "multi_domain_capability_implemented %d "
1161 + "international_roaming %d country_string %.3s",
1162 + priv->netdev->name, le16_to_cpu(m->beacon_period),
1163 + le16_to_cpu(m->CFP_max_duration),
1164 + le16_to_cpu(m->medium_occupancy_limit),
1165 + le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window),
1166 + m->CFP_mode, m->privacy_option_implemented, m->DTIM_period,
1167 + m->CFP_period, mac2str(m->current_bssid),
1168 + hex2str(m->current_essid, IW_ESSID_MAX_SIZE),
1169 + m->current_bss_type, m->power_mgmt_mode, m->ibss_change,
1170 + m->res, m->multi_domain_capability_implemented,
1171 + m->multi_domain_capability_enabled, m->country_string);
1172 +exit:
1173 + kfree(m);
1174 +}
1175 +
1176 +static void at76_dump_mib_mac(struct at76_priv *priv)
1177 +{
1178 + int ret;
1179 + struct mib_mac *m = kmalloc(sizeof(struct mib_mac), GFP_KERNEL);
1180 +
1181 + if (!m)
1182 + return;
1183 +
1184 + ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac));
1185 + if (ret < 0) {
1186 + printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n",
1187 + priv->netdev->name, ret);
1188 + goto exit;
1189 + }
1190 +
1191 + at76_dbg(DBG_MIB, "%s: MIB MAC: max_tx_msdu_lifetime %d "
1192 + "max_rx_lifetime %d frag_threshold %d rts_threshold %d "
1193 + "cwmin %d cwmax %d short_retry_time %d long_retry_time %d "
1194 + "scan_type %d scan_channel %d probe_delay %u "
1195 + "min_channel_time %d max_channel_time %d listen_int %d "
1196 + "desired_ssid %s desired_bssid %s desired_bsstype %d",
1197 + priv->netdev->name, le32_to_cpu(m->max_tx_msdu_lifetime),
1198 + le32_to_cpu(m->max_rx_lifetime),
1199 + le16_to_cpu(m->frag_threshold), le16_to_cpu(m->rts_threshold),
1200 + le16_to_cpu(m->cwmin), le16_to_cpu(m->cwmax),
1201 + m->short_retry_time, m->long_retry_time, m->scan_type,
1202 + m->scan_channel, le16_to_cpu(m->probe_delay),
1203 + le16_to_cpu(m->min_channel_time),
1204 + le16_to_cpu(m->max_channel_time),
1205 + le16_to_cpu(m->listen_interval),
1206 + hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE),
1207 + mac2str(m->desired_bssid), m->desired_bsstype);
1208 +exit:
1209 + kfree(m);
1210 +}
1211 +
1212 +static void at76_dump_mib_phy(struct at76_priv *priv)
1213 +{
1214 + int ret;
1215 + struct mib_phy *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
1216 +
1217 + if (!m)
1218 + return;
1219 +
1220 + ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy));
1221 + if (ret < 0) {
1222 + printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n",
1223 + priv->netdev->name, ret);
1224 + goto exit;
1225 + }
1226 +
1227 + at76_dbg(DBG_MIB, "%s: MIB PHY: ed_threshold %d slot_time %d "
1228 + "sifs_time %d preamble_length %d plcp_header_length %d "
1229 + "mpdu_max_length %d cca_mode_supported %d operation_rate_set "
1230 + "0x%x 0x%x 0x%x 0x%x channel_id %d current_cca_mode %d "
1231 + "phy_type %d current_reg_domain %d",
1232 + priv->netdev->name, le32_to_cpu(m->ed_threshold),
1233 + le16_to_cpu(m->slot_time), le16_to_cpu(m->sifs_time),
1234 + le16_to_cpu(m->preamble_length),
1235 + le16_to_cpu(m->plcp_header_length),
1236 + le16_to_cpu(m->mpdu_max_length),
1237 + le16_to_cpu(m->cca_mode_supported), m->operation_rate_set[0],
1238 + m->operation_rate_set[1], m->operation_rate_set[2],
1239 + m->operation_rate_set[3], m->channel_id, m->current_cca_mode,
1240 + m->phy_type, m->current_reg_domain);
1241 +exit:
1242 + kfree(m);
1243 +}
1244 +
1245 +static void at76_dump_mib_local(struct at76_priv *priv)
1246 +{
1247 + int ret;
1248 + struct mib_local *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
1249 +
1250 + if (!m)
1251 + return;
1252 +
1253 + ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local));
1254 + if (ret < 0) {
1255 + printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n",
1256 + priv->netdev->name, ret);
1257 + goto exit;
1258 + }
1259 +
1260 + at76_dbg(DBG_MIB, "%s: MIB LOCAL: beacon_enable %d "
1261 + "txautorate_fallback %d ssid_size %d promiscuous_mode %d "
1262 + "preamble_type %d", priv->netdev->name, m->beacon_enable,
1263 + m->txautorate_fallback, m->ssid_size, m->promiscuous_mode,
1264 + m->preamble_type);
1265 +exit:
1266 + kfree(m);
1267 +}
1268 +
1269 +static void at76_dump_mib_mdomain(struct at76_priv *priv)
1270 +{
1271 + int ret;
1272 + struct mib_mdomain *m = kmalloc(sizeof(struct mib_mdomain), GFP_KERNEL);
1273 +
1274 + if (!m)
1275 + return;
1276 +
1277 + ret = at76_get_mib(priv->udev, MIB_MDOMAIN, m,
1278 + sizeof(struct mib_mdomain));
1279 + if (ret < 0) {
1280 + printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n",
1281 + priv->netdev->name, ret);
1282 + goto exit;
1283 + }
1284 +
1285 + at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s",
1286 + priv->netdev->name,
1287 + hex2str(m->channel_list, sizeof(m->channel_list)));
1288 +
1289 + at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %s",
1290 + priv->netdev->name,
1291 + hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel)));
1292 +exit:
1293 + kfree(m);
1294 +}
1295 +
1296 +static int at76_get_current_bssid(struct at76_priv *priv)
1297 +{
1298 + int ret = 0;
1299 + struct mib_mac_mgmt *mac_mgmt =
1300 + kmalloc(sizeof(struct mib_mac_mgmt), GFP_KERNEL);
1301 +
1302 + if (!mac_mgmt) {
1303 + ret = -ENOMEM;
1304 + goto exit;
1305 + }
1306 +
1307 + ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, mac_mgmt,
1308 + sizeof(struct mib_mac_mgmt));
1309 + if (ret < 0) {
1310 + printk(KERN_ERR "%s: at76_get_mib failed: %d\n",
1311 + priv->netdev->name, ret);
1312 + goto error;
1313 + }
1314 + memcpy(priv->bssid, mac_mgmt->current_bssid, ETH_ALEN);
1315 + printk(KERN_INFO "%s: using BSSID %s\n", priv->netdev->name,
1316 + mac2str(priv->bssid));
1317 +error:
1318 + kfree(mac_mgmt);
1319 +exit:
1320 + return ret;
1321 +}
1322 +
1323 +static int at76_get_current_channel(struct at76_priv *priv)
1324 +{
1325 + int ret = 0;
1326 + struct mib_phy *phy = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
1327 +
1328 + if (!phy) {
1329 + ret = -ENOMEM;
1330 + goto exit;
1331 + }
1332 + ret = at76_get_mib(priv->udev, MIB_PHY, phy, sizeof(struct mib_phy));
1333 + if (ret < 0) {
1334 + printk(KERN_ERR "%s: at76_get_mib(MIB_PHY) failed: %d\n",
1335 + priv->netdev->name, ret);
1336 + goto error;
1337 + }
1338 + priv->channel = phy->channel_id;
1339 +error:
1340 + kfree(phy);
1341 +exit:
1342 + return ret;
1343 +}
1344 +
1345 +/**
1346 + * at76_start_scan - start a scan
1347 + *
1348 + * @use_essid - use the configured ESSID in non passive mode
1349 + */
1350 +static int at76_start_scan(struct at76_priv *priv, int use_essid)
1351 +{
1352 + struct at76_req_scan scan;
1353 +
1354 + memset(&scan, 0, sizeof(struct at76_req_scan));
1355 + memset(scan.bssid, 0xff, ETH_ALEN);
1356 +
1357 + if (use_essid) {
1358 + memcpy(scan.essid, priv->essid, IW_ESSID_MAX_SIZE);
1359 + scan.essid_size = priv->essid_size;
1360 + } else
1361 + scan.essid_size = 0;
1362 +
1363 + /* jal: why should we start at a certain channel? we do scan the whole
1364 + range allowed by reg domain. */
1365 + scan.channel = priv->channel;
1366 +
1367 + /* atmelwlandriver differs between scan type 0 and 1 (active/passive)
1368 + For ad-hoc mode, it uses type 0 only. */
1369 + scan.scan_type = priv->scan_mode;
1370 +
1371 + /* INFO: For probe_delay, not multiplying by 1024 as this will be
1372 + slightly less than min_channel_time
1373 + (per spec: probe delay < min. channel time) */
1374 + scan.min_channel_time = cpu_to_le16(priv->scan_min_time);
1375 + scan.max_channel_time = cpu_to_le16(priv->scan_max_time);
1376 + scan.probe_delay = cpu_to_le16(priv->scan_min_time * 1000);
1377 + scan.international_scan = 0;
1378 +
1379 + /* other values are set to 0 for type 0 */
1380 +
1381 + at76_dbg(DBG_PROGRESS, "%s: start_scan (use_essid = %d, intl = %d, "
1382 + "channel = %d, probe_delay = %d, scan_min_time = %d, "
1383 + "scan_max_time = %d)",
1384 + priv->netdev->name, use_essid,
1385 + scan.international_scan, scan.channel,
1386 + le16_to_cpu(scan.probe_delay),
1387 + le16_to_cpu(scan.min_channel_time),
1388 + le16_to_cpu(scan.max_channel_time));
1389 +
1390 + return at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
1391 +}
1392 +
1393 +/* Enable monitor mode */
1394 +static int at76_start_monitor(struct at76_priv *priv)
1395 +{
1396 + struct at76_req_scan scan;
1397 + int ret;
1398 +
1399 + memset(&scan, 0, sizeof(struct at76_req_scan));
1400 + memset(scan.bssid, 0xff, ETH_ALEN);
1401 +
1402 + scan.channel = priv->channel;
1403 + scan.scan_type = SCAN_TYPE_PASSIVE;
1404 + scan.international_scan = 0;
1405 +
1406 + ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
1407 + if (ret >= 0)
1408 + ret = at76_get_cmd_status(priv->udev, CMD_SCAN);
1409 +
1410 + return ret;
1411 +}
1412 +
1413 +static int at76_start_ibss(struct at76_priv *priv)
1414 +{
1415 + struct at76_req_ibss bss;
1416 + int ret;
1417 +
1418 + WARN_ON(priv->mac_state != MAC_OWN_IBSS);
1419 + if (priv->mac_state != MAC_OWN_IBSS)
1420 + return -EBUSY;
1421 +
1422 + memset(&bss, 0, sizeof(struct at76_req_ibss));
1423 + memset(bss.bssid, 0xff, ETH_ALEN);
1424 + memcpy(bss.essid, priv->essid, IW_ESSID_MAX_SIZE);
1425 + bss.essid_size = priv->essid_size;
1426 + bss.bss_type = ADHOC_MODE;
1427 + bss.channel = priv->channel;
1428 +
1429 + ret = at76_set_card_command(priv->udev, CMD_START_IBSS, &bss,
1430 + sizeof(struct at76_req_ibss));
1431 + if (ret < 0) {
1432 + printk(KERN_ERR "%s: start_ibss failed: %d\n",
1433 + priv->netdev->name, ret);
1434 + return ret;
1435 + }
1436 +
1437 + ret = at76_wait_completion(priv, CMD_START_IBSS);
1438 + if (ret != CMD_STATUS_COMPLETE) {
1439 + printk(KERN_ERR "%s: start_ibss failed to complete, %d\n",
1440 + priv->netdev->name, ret);
1441 + return ret;
1442 + }
1443 +
1444 + ret = at76_get_current_bssid(priv);
1445 + if (ret < 0)
1446 + return ret;
1447 +
1448 + ret = at76_get_current_channel(priv);
1449 + if (ret < 0)
1450 + return ret;
1451 +
1452 + /* not sure what this is good for ??? */
1453 + priv->mib_buf.type = MIB_MAC_MGMT;
1454 + priv->mib_buf.size = 1;
1455 + priv->mib_buf.index = offsetof(struct mib_mac_mgmt, ibss_change);
1456 + priv->mib_buf.data.byte = 0;
1457 +
1458 + ret = at76_set_mib(priv, &priv->mib_buf);
1459 + if (ret < 0) {
1460 + printk(KERN_ERR "%s: set_mib (ibss change ok) failed: %d\n",
1461 + priv->netdev->name, ret);
1462 + return ret;
1463 + }
1464 +
1465 + netif_carrier_on(priv->netdev);
1466 + netif_start_queue(priv->netdev);
1467 + return 0;
1468 +}
1469 +
1470 +/* Request card to join BSS in managed or ad-hoc mode */
1471 +static int at76_join_bss(struct at76_priv *priv, struct bss_info *ptr)
1472 +{
1473 + struct at76_req_join join;
1474 +
1475 + BUG_ON(!ptr);
1476 +
1477 + memset(&join, 0, sizeof(struct at76_req_join));
1478 + memcpy(join.bssid, ptr->bssid, ETH_ALEN);
1479 + memcpy(join.essid, ptr->ssid, ptr->ssid_len);
1480 + join.essid_size = ptr->ssid_len;
1481 + join.bss_type = (priv->iw_mode == IW_MODE_ADHOC ? 1 : 2);
1482 + join.channel = ptr->channel;
1483 + join.timeout = cpu_to_le16(2000);
1484 +
1485 + at76_dbg(DBG_PROGRESS,
1486 + "%s join addr %s ssid %s type %d ch %d timeout %d",
1487 + priv->netdev->name, mac2str(join.bssid), join.essid,
1488 + join.bss_type, join.channel, le16_to_cpu(join.timeout));
1489 + return at76_set_card_command(priv->udev, CMD_JOIN, &join,
1490 + sizeof(struct at76_req_join));
1491 +}
1492 +
1493 +/* Calculate padding from txbuf->wlength (which excludes the USB TX header),
1494 + likely to compensate a flaw in the AT76C503A USB part ... */
1495 +static inline int at76_calc_padding(int wlen)
1496 +{
1497 + /* add the USB TX header */
1498 + wlen += AT76_TX_HDRLEN;
1499 +
1500 + wlen = wlen % 64;
1501 +
1502 + if (wlen < 50)
1503 + return 50 - wlen;
1504 +
1505 + if (wlen >= 61)
1506 + return 64 + 50 - wlen;
1507 +
1508 + return 0;
1509 +}
1510 +
1511 +/* We are doing a lot of things here in an interrupt. Need
1512 + a bh handler (Watching TV with a TV card is probably
1513 + a good test: if you see flickers, we are doing too much.
1514 + Currently I do see flickers... even with our tasklet :-( )
1515 + Maybe because the bttv driver and usb-uhci use the same interrupt
1516 +*/
1517 +/* Or maybe because our BH handler is preempting bttv's BH handler.. BHs don't
1518 + * solve everything.. (alex) */
1519 +static void at76_rx_callback(struct urb *urb)
1520 +{
1521 + struct at76_priv *priv = urb->context;
1522 +
1523 + priv->rx_tasklet.data = (unsigned long)urb;
1524 + tasklet_schedule(&priv->rx_tasklet);
1525 + return;
1526 +}
1527 +
1528 +static void at76_tx_callback(struct urb *urb)
1529 +{
1530 + struct at76_priv *priv = urb->context;
1531 + struct net_device_stats *stats = &priv->stats;
1532 + unsigned long flags;
1533 + struct at76_tx_buffer *mgmt_buf;
1534 + int ret;
1535 +
1536 + switch (urb->status) {
1537 + case 0:
1538 + stats->tx_packets++;
1539 + break;
1540 + case -ENOENT:
1541 + case -ECONNRESET:
1542 + /* urb has been unlinked */
1543 + return;
1544 + default:
1545 + at76_dbg(DBG_URB, "%s - nonzero tx status received: %d",
1546 + __func__, urb->status);
1547 + stats->tx_errors++;
1548 + break;
1549 + }
1550 +
1551 + spin_lock_irqsave(&priv->mgmt_spinlock, flags);
1552 + mgmt_buf = priv->next_mgmt_bulk;
1553 + priv->next_mgmt_bulk = NULL;
1554 + spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
1555 +
1556 + if (!mgmt_buf) {
1557 + netif_wake_queue(priv->netdev);
1558 + return;
1559 + }
1560 +
1561 + /* we don't copy the padding bytes, but add them
1562 + to the length */
1563 + memcpy(priv->bulk_out_buffer, mgmt_buf,
1564 + le16_to_cpu(mgmt_buf->wlength) + AT76_TX_HDRLEN);
1565 + usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe,
1566 + priv->bulk_out_buffer,
1567 + le16_to_cpu(mgmt_buf->wlength) + mgmt_buf->padding +
1568 + AT76_TX_HDRLEN, at76_tx_callback, priv);
1569 + ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
1570 + if (ret)
1571 + printk(KERN_ERR "%s: error in tx submit urb: %d\n",
1572 + priv->netdev->name, ret);
1573 +
1574 + kfree(mgmt_buf);
1575 +}
1576 +
1577 +/* Send a management frame on bulk-out. txbuf->wlength must be set */
1578 +static int at76_tx_mgmt(struct at76_priv *priv, struct at76_tx_buffer *txbuf)
1579 +{
1580 + unsigned long flags;
1581 + int ret;
1582 + int urb_status;
1583 + void *oldbuf = NULL;
1584 +
1585 + netif_carrier_off(priv->netdev); /* stop netdev watchdog */
1586 + netif_stop_queue(priv->netdev); /* stop tx data packets */
1587 +
1588 + spin_lock_irqsave(&priv->mgmt_spinlock, flags);
1589 +
1590 + urb_status = priv->tx_urb->status;
1591 + if (urb_status == -EINPROGRESS) {
1592 + /* cannot transmit now, put in the queue */
1593 + oldbuf = priv->next_mgmt_bulk;
1594 + priv->next_mgmt_bulk = txbuf;
1595 + }
1596 + spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
1597 +
1598 + if (oldbuf) {
1599 + /* a data/mgmt tx is already pending in the URB -
1600 + if this is no error in some situations we must
1601 + implement a queue or silently modify the old msg */
1602 + printk(KERN_ERR "%s: removed pending mgmt buffer %s\n",
1603 + priv->netdev->name, hex2str(oldbuf, 64));
1604 + kfree(oldbuf);
1605 + return 0;
1606 + }
1607 +
1608 + txbuf->tx_rate = TX_RATE_1MBIT;
1609 + txbuf->padding = at76_calc_padding(le16_to_cpu(txbuf->wlength));
1610 + memset(txbuf->reserved, 0, sizeof(txbuf->reserved));
1611 +
1612 + if (priv->next_mgmt_bulk)
1613 + printk(KERN_ERR "%s: URB status %d, but mgmt is pending\n",
1614 + priv->netdev->name, urb_status);
1615 +
1616 + at76_dbg(DBG_TX_MGMT,
1617 + "%s: tx mgmt: wlen %d tx_rate %d pad %d %s",
1618 + priv->netdev->name, le16_to_cpu(txbuf->wlength),
1619 + txbuf->tx_rate, txbuf->padding,
1620 + hex2str(txbuf->packet, le16_to_cpu(txbuf->wlength)));
1621 +
1622 + /* txbuf was not consumed above -> send mgmt msg immediately */
1623 + memcpy(priv->bulk_out_buffer, txbuf,
1624 + le16_to_cpu(txbuf->wlength) + AT76_TX_HDRLEN);
1625 + usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe,
1626 + priv->bulk_out_buffer,
1627 + le16_to_cpu(txbuf->wlength) + txbuf->padding +
1628 + AT76_TX_HDRLEN, at76_tx_callback, priv);
1629 + ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
1630 + if (ret)
1631 + printk(KERN_ERR "%s: error in tx submit urb: %d\n",
1632 + priv->netdev->name, ret);
1633 +
1634 + kfree(txbuf);
1635 +
1636 + return ret;
1637 +}
1638 +
1639 +/* Go to the next information element */
1640 +static inline void next_ie(struct ieee80211_info_element **ie)
1641 +{
1642 + *ie = (struct ieee80211_info_element *)(&(*ie)->data[(*ie)->len]);
1643 +}
1644 +
1645 +/* Challenge is the challenge string (in TLV format)
1646 + we got with seq_nr 2 for shared secret authentication only and
1647 + send in seq_nr 3 WEP encrypted to prove we have the correct WEP key;
1648 + otherwise it is NULL */
1649 +static int at76_auth_req(struct at76_priv *priv, struct bss_info *bss,
1650 + int seq_nr, struct ieee80211_info_element *challenge)
1651 +{
1652 + struct at76_tx_buffer *tx_buffer;
1653 + struct ieee80211_hdr_3addr *mgmt;
1654 + struct ieee80211_auth *req;
1655 + int buf_len = (seq_nr != 3 ? AUTH_FRAME_SIZE :
1656 + AUTH_FRAME_SIZE + 1 + 1 + challenge->len);
1657 +
1658 + BUG_ON(!bss);
1659 + BUG_ON(seq_nr == 3 && !challenge);
1660 + tx_buffer = kmalloc(buf_len + MAX_PADDING_SIZE, GFP_ATOMIC);
1661 + if (!tx_buffer)
1662 + return -ENOMEM;
1663 +
1664 + req = (struct ieee80211_auth *)tx_buffer->packet;
1665 + mgmt = &req->header;
1666 +
1667 + /* make wireless header */
1668 + /* first auth msg is not encrypted, only the second (seq_nr == 3) */
1669 + mgmt->frame_ctl =
1670 + cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH |
1671 + (seq_nr == 3 ? IEEE80211_FCTL_PROTECTED : 0));
1672 +
1673 + mgmt->duration_id = cpu_to_le16(0x8000);
1674 + memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);
1675 + memcpy(mgmt->addr2, priv->netdev->dev_addr, ETH_ALEN);
1676 + memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);
1677 + mgmt->seq_ctl = cpu_to_le16(0);
1678 +
1679 + req->algorithm = cpu_to_le16(priv->auth_mode);
1680 + req->transaction = cpu_to_le16(seq_nr);
1681 + req->status = cpu_to_le16(0);
1682 +
1683 + if (seq_nr == 3)
1684 + memcpy(req->info_element, challenge, 1 + 1 + challenge->len);
1685 +
1686 + /* init. at76_priv tx header */
1687 + tx_buffer->wlength = cpu_to_le16(buf_len - AT76_TX_HDRLEN);
1688 + at76_dbg(DBG_TX_MGMT, "%s: AuthReq bssid %s alg %d seq_nr %d",
1689 + priv->netdev->name, mac2str(mgmt->addr3),
1690 + le16_to_cpu(req->algorithm), le16_to_cpu(req->transaction));
1691 + if (seq_nr == 3)
1692 + at76_dbg(DBG_TX_MGMT, "%s: AuthReq challenge: %s ...",
1693 + priv->netdev->name, hex2str(req->info_element, 18));
1694 +
1695 + /* either send immediately (if no data tx is pending
1696 + or put it in pending list */
1697 + return at76_tx_mgmt(priv, tx_buffer);
1698 +}
1699 +
1700 +static int at76_assoc_req(struct at76_priv *priv, struct bss_info *bss)
1701 +{
1702 + struct at76_tx_buffer *tx_buffer;
1703 + struct ieee80211_hdr_3addr *mgmt;
1704 + struct ieee80211_assoc_request *req;
1705 + struct ieee80211_info_element *ie;
1706 + char *essid;
1707 + int essid_len;
1708 + u16 capa;
1709 +
1710 + BUG_ON(!bss);
1711 +
1712 + tx_buffer = kmalloc(ASSOCREQ_MAX_SIZE + MAX_PADDING_SIZE, GFP_ATOMIC);
1713 + if (!tx_buffer)
1714 + return -ENOMEM;
1715 +
1716 + req = (struct ieee80211_assoc_request *)tx_buffer->packet;
1717 + mgmt = &req->header;
1718 + ie = req->info_element;
1719 +
1720 + /* make wireless header */
1721 + mgmt->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
1722 + IEEE80211_STYPE_ASSOC_REQ);
1723 +
1724 + mgmt->duration_id = cpu_to_le16(0x8000);
1725 + memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);
1726 + memcpy(mgmt->addr2, priv->netdev->dev_addr, ETH_ALEN);
1727 + memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);
1728 + mgmt->seq_ctl = cpu_to_le16(0);
1729 +
1730 + /* we must set the Privacy bit in the capabilities to assure an
1731 + Agere-based AP with optional WEP transmits encrypted frames
1732 + to us. AP only set the Privacy bit in their capabilities
1733 + if WEP is mandatory in the BSS! */
1734 + capa = bss->capa;
1735 + if (priv->wep_enabled)
1736 + capa |= WLAN_CAPABILITY_PRIVACY;
1737 + if (priv->preamble_type != PREAMBLE_TYPE_LONG)
1738 + capa |= WLAN_CAPABILITY_SHORT_PREAMBLE;
1739 + req->capability = cpu_to_le16(capa);
1740 +
1741 + req->listen_interval = cpu_to_le16(2 * bss->beacon_interval);
1742 +
1743 + /* write TLV data elements */
1744 +
1745 + ie->id = MFIE_TYPE_SSID;
1746 + ie->len = bss->ssid_len;
1747 + memcpy(ie->data, bss->ssid, bss->ssid_len);
1748 + next_ie(&ie);
1749 +
1750 + ie->id = MFIE_TYPE_RATES;
1751 + ie->len = sizeof(hw_rates);
1752 + memcpy(ie->data, hw_rates, sizeof(hw_rates));
1753 + next_ie(&ie); /* ie points behind the supp_rates field */
1754 +
1755 + /* init. at76_priv tx header */
1756 + tx_buffer->wlength = cpu_to_le16((u8 *)ie - (u8 *)mgmt);
1757 +
1758 + ie = req->info_element;
1759 + essid = ie->data;
1760 + essid_len = min_t(int, IW_ESSID_MAX_SIZE, ie->len);
1761 +
1762 + next_ie(&ie); /* points to IE of rates now */
1763 + at76_dbg(DBG_TX_MGMT,
1764 + "%s: AssocReq bssid %s capa 0x%04x ssid %.*s rates %s",
1765 + priv->netdev->name, mac2str(mgmt->addr3),
1766 + le16_to_cpu(req->capability), essid_len, essid,
1767 + hex2str(ie->data, ie->len));
1768 +
1769 + /* either send immediately (if no data tx is pending
1770 + or put it in pending list */
1771 + return at76_tx_mgmt(priv, tx_buffer);
1772 +}
1773 +
1774 +/* We got to check the bss_list for old entries */
1775 +static void at76_bss_list_timeout(unsigned long par)
1776 +{
1777 + struct at76_priv *priv = (struct at76_priv *)par;
1778 + unsigned long flags;
1779 + struct list_head *lptr, *nptr;
1780 + struct bss_info *ptr;
1781 +
1782 + spin_lock_irqsave(&priv->bss_list_spinlock, flags);
1783 +
1784 + list_for_each_safe(lptr, nptr, &priv->bss_list) {
1785 +
1786 + ptr = list_entry(lptr, struct bss_info, list);
1787 +
1788 + if (ptr != priv->curr_bss
1789 + && time_after(jiffies, ptr->last_rx + BSS_LIST_TIMEOUT)) {
1790 + at76_dbg(DBG_BSS_TABLE_RM,
1791 + "%s: bss_list: removing old BSS %s ch %d",
1792 + priv->netdev->name, mac2str(ptr->bssid),
1793 + ptr->channel);
1794 + list_del(&ptr->list);
1795 + kfree(ptr);
1796 + }
1797 + }
1798 + spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
1799 + /* restart the timer */
1800 + mod_timer(&priv->bss_list_timer, jiffies + BSS_LIST_TIMEOUT);
1801 +}
1802 +
1803 +static inline void at76_set_mac_state(struct at76_priv *priv,
1804 + enum mac_state mac_state)
1805 +{
1806 + at76_dbg(DBG_MAC_STATE, "%s state: %s", priv->netdev->name,
1807 + mac_states[mac_state]);
1808 + priv->mac_state = mac_state;
1809 +}
1810 +
1811 +static void at76_dump_bss_table(struct at76_priv *priv)
1812 +{
1813 + struct bss_info *ptr;
1814 + unsigned long flags;
1815 + struct list_head *lptr;
1816 +
1817 + spin_lock_irqsave(&priv->bss_list_spinlock, flags);
1818 +
1819 + at76_dbg(DBG_BSS_TABLE, "%s BSS table (curr=%p):", priv->netdev->name,
1820 + priv->curr_bss);
1821 +
1822 + list_for_each(lptr, &priv->bss_list) {
1823 + ptr = list_entry(lptr, struct bss_info, list);
1824 + at76_dbg(DBG_BSS_TABLE, "0x%p: bssid %s channel %d ssid %.*s "
1825 + "(%s) capa 0x%04x rates %s rssi %d link %d noise %d",
1826 + ptr, mac2str(ptr->bssid), ptr->channel, ptr->ssid_len,
1827 + ptr->ssid, hex2str(ptr->ssid, ptr->ssid_len),
1828 + ptr->capa, hex2str(ptr->rates, ptr->rates_len),
1829 + ptr->rssi, ptr->link_qual, ptr->noise_level);
1830 + }
1831 + spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
1832 +}
1833 +
1834 +/* Called upon successful association to mark interface as connected */
1835 +static void at76_work_assoc_done(struct work_struct *work)
1836 +{
1837 + struct at76_priv *priv = container_of(work, struct at76_priv,
1838 + work_assoc_done);
1839 +
1840 + mutex_lock(&priv->mtx);
1841 +
1842 + WARN_ON(priv->mac_state != MAC_ASSOC);
1843 + WARN_ON(!priv->curr_bss);
1844 + if (priv->mac_state != MAC_ASSOC || !priv->curr_bss)
1845 + goto exit;
1846 +
1847 + if (priv->iw_mode == IW_MODE_INFRA) {
1848 + if (priv->pm_mode != AT76_PM_OFF) {
1849 + /* calculate the listen interval in units of
1850 + beacon intervals of the curr_bss */
1851 + u32 pm_period_beacon = (priv->pm_period >> 10) /
1852 + priv->curr_bss->beacon_interval;
1853 +
1854 + pm_period_beacon = max(pm_period_beacon, 2u);
1855 + pm_period_beacon = min(pm_period_beacon, 0xffffu);
1856 +
1857 + at76_dbg(DBG_PM,
1858 + "%s: pm_mode %d assoc id 0x%x listen int %d",
1859 + priv->netdev->name, priv->pm_mode,
1860 + priv->assoc_id, pm_period_beacon);
1861 +
1862 + at76_set_associd(priv, priv->assoc_id);
1863 + at76_set_listen_interval(priv, (u16)pm_period_beacon);
1864 + }
1865 + schedule_delayed_work(&priv->dwork_beacon, BEACON_TIMEOUT);
1866 + }
1867 + at76_set_pm_mode(priv);
1868 +
1869 + netif_carrier_on(priv->netdev);
1870 + netif_wake_queue(priv->netdev);
1871 + at76_set_mac_state(priv, MAC_CONNECTED);
1872 + at76_iwevent_bss_connect(priv->netdev, priv->curr_bss->bssid);
1873 + at76_dbg(DBG_PROGRESS, "%s: connected to BSSID %s",
1874 + priv->netdev->name, mac2str(priv->curr_bss->bssid));
1875 +
1876 +exit:
1877 + mutex_unlock(&priv->mtx);
1878 +}
1879 +
1880 +/* We only store the new mac address in netdev struct,
1881 + it gets set when the netdev is opened. */
1882 +static int at76_set_mac_address(struct net_device *netdev, void *addr)
1883 +{
1884 + struct sockaddr *mac = addr;
1885 + memcpy(netdev->dev_addr, mac->sa_data, ETH_ALEN);
1886 + return 1;
1887 +}
1888 +
1889 +static struct net_device_stats *at76_get_stats(struct net_device *netdev)
1890 +{
1891 + struct at76_priv *priv = netdev_priv(netdev);
1892 + return &priv->stats;
1893 +}
1894 +
1895 +static struct iw_statistics *at76_get_wireless_stats(struct net_device *netdev)
1896 +{
1897 + struct at76_priv *priv = netdev_priv(netdev);
1898 +
1899 + at76_dbg(DBG_IOCTL, "RETURN qual %d level %d noise %d updated %d",
1900 + priv->wstats.qual.qual, priv->wstats.qual.level,
1901 + priv->wstats.qual.noise, priv->wstats.qual.updated);
1902 +
1903 + return &priv->wstats;
1904 +}
1905 +
1906 +static void at76_set_multicast(struct net_device *netdev)
1907 +{
1908 + struct at76_priv *priv = netdev_priv(netdev);
1909 + int promisc;
1910 +
1911 + promisc = ((netdev->flags & IFF_PROMISC) != 0);
1912 + if (promisc != priv->promisc) {
1913 + /* This gets called in interrupt, must reschedule */
1914 + priv->promisc = promisc;
1915 + schedule_work(&priv->work_set_promisc);
1916 + }
1917 +}
1918 +
1919 +/* Stop all network activity, flush all pending tasks */
1920 +static void at76_quiesce(struct at76_priv *priv)
1921 +{
1922 + unsigned long flags;
1923 +
1924 + netif_stop_queue(priv->netdev);
1925 + netif_carrier_off(priv->netdev);
1926 +
1927 + at76_set_mac_state(priv, MAC_INIT);
1928 +
1929 + cancel_delayed_work(&priv->dwork_get_scan);
1930 + cancel_delayed_work(&priv->dwork_beacon);
1931 + cancel_delayed_work(&priv->dwork_auth);
1932 + cancel_delayed_work(&priv->dwork_assoc);
1933 + cancel_delayed_work(&priv->dwork_restart);
1934 +
1935 + spin_lock_irqsave(&priv->mgmt_spinlock, flags);
1936 + kfree(priv->next_mgmt_bulk);
1937 + priv->next_mgmt_bulk = NULL;
1938 + spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
1939 +}
1940 +
1941 +/*******************************************************************************
1942 + * at76_priv implementations of iw_handler functions:
1943 + */
1944 +static int at76_iw_handler_commit(struct net_device *netdev,
1945 + struct iw_request_info *info,
1946 + void *null, char *extra)
1947 +{
1948 + struct at76_priv *priv = netdev_priv(netdev);
1949 +
1950 + at76_dbg(DBG_IOCTL, "%s %s: restarting the device", netdev->name,
1951 + __func__);
1952 +
1953 + if (priv->mac_state != MAC_INIT)
1954 + at76_quiesce(priv);
1955 +
1956 + /* Wait half second before the restart to process subsequent
1957 + * requests from the same iwconfig in a single restart */
1958 + schedule_delayed_work(&priv->dwork_restart, HZ / 2);
1959 +
1960 + return 0;
1961 +}
1962 +
1963 +static int at76_iw_handler_get_name(struct net_device *netdev,
1964 + struct iw_request_info *info,
1965 + char *name, char *extra)
1966 +{
1967 + strcpy(name, "IEEE 802.11b");
1968 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWNAME - name %s", netdev->name, name);
1969 + return 0;
1970 +}
1971 +
1972 +static int at76_iw_handler_set_freq(struct net_device *netdev,
1973 + struct iw_request_info *info,
1974 + struct iw_freq *freq, char *extra)
1975 +{
1976 + struct at76_priv *priv = netdev_priv(netdev);
1977 + int chan = -1;
1978 + int ret = -EIWCOMMIT;
1979 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWFREQ - freq.m %d freq.e %d",
1980 + netdev->name, freq->m, freq->e);
1981 +
1982 + if ((freq->e == 0) && (freq->m <= 1000))
1983 + /* Setting by channel number */
1984 + chan = freq->m;
1985 + else {
1986 + /* Setting by frequency - search the table */
1987 + int mult = 1;
1988 + int i;
1989 +
1990 + for (i = 0; i < (6 - freq->e); i++)
1991 + mult *= 10;
1992 +
1993 + for (i = 0; i < NUM_CHANNELS; i++) {
1994 + if (freq->m == (channel_frequency[i] * mult))
1995 + chan = i + 1;
1996 + }
1997 + }
1998 +
1999 + if (chan < 1 || !priv->domain)
2000 + /* non-positive channels are invalid
2001 + * we need a domain info to set the channel
2002 + * either that or an invalid frequency was
2003 + * provided by the user */
2004 + ret = -EINVAL;
2005 + else if (!(priv->domain->channel_map & (1 << (chan - 1)))) {
2006 + printk(KERN_INFO "%s: channel %d not allowed for domain %s\n",
2007 + priv->netdev->name, chan, priv->domain->name);
2008 + ret = -EINVAL;
2009 + }
2010 +
2011 + if (ret == -EIWCOMMIT) {
2012 + priv->channel = chan;
2013 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWFREQ - ch %d", netdev->name,
2014 + chan);
2015 + }
2016 +
2017 + return ret;
2018 +}
2019 +
2020 +static int at76_iw_handler_get_freq(struct net_device *netdev,
2021 + struct iw_request_info *info,
2022 + struct iw_freq *freq, char *extra)
2023 +{
2024 + struct at76_priv *priv = netdev_priv(netdev);
2025 +
2026 + freq->m = priv->channel;
2027 + freq->e = 0;
2028 +
2029 + if (priv->channel)
2030 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWFREQ - freq %ld x 10e%d",
2031 + netdev->name, channel_frequency[priv->channel - 1], 6);
2032 +
2033 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWFREQ - ch %d", netdev->name,
2034 + priv->channel);
2035 +
2036 + return 0;
2037 +}
2038 +
2039 +static int at76_iw_handler_set_mode(struct net_device *netdev,
2040 + struct iw_request_info *info,
2041 + __u32 *mode, char *extra)
2042 +{
2043 + struct at76_priv *priv = netdev_priv(netdev);
2044 +
2045 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWMODE - %d", netdev->name, *mode);
2046 +
2047 + if ((*mode != IW_MODE_ADHOC) && (*mode != IW_MODE_INFRA) &&
2048 + (*mode != IW_MODE_MONITOR))
2049 + return -EINVAL;
2050 +
2051 + priv->iw_mode = *mode;
2052 + if (priv->iw_mode != IW_MODE_INFRA)
2053 + priv->pm_mode = AT76_PM_OFF;
2054 +
2055 + return -EIWCOMMIT;
2056 +}
2057 +
2058 +static int at76_iw_handler_get_mode(struct net_device *netdev,
2059 + struct iw_request_info *info,
2060 + __u32 *mode, char *extra)
2061 +{
2062 + struct at76_priv *priv = netdev_priv(netdev);
2063 +
2064 + *mode = priv->iw_mode;
2065 +
2066 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWMODE - %d", netdev->name, *mode);
2067 +
2068 + return 0;
2069 +}
2070 +
2071 +static int at76_iw_handler_get_range(struct net_device *netdev,
2072 + struct iw_request_info *info,
2073 + struct iw_point *data, char *extra)
2074 +{
2075 + /* inspired by atmel.c */
2076 + struct at76_priv *priv = netdev_priv(netdev);
2077 + struct iw_range *range = (struct iw_range *)extra;
2078 + int i;
2079 +
2080 + data->length = sizeof(struct iw_range);
2081 + memset(range, 0, sizeof(struct iw_range));
2082 +
2083 + /* TODO: range->throughput = xxxxxx; */
2084 +
2085 + range->min_nwid = 0x0000;
2086 + range->max_nwid = 0x0000;
2087 +
2088 + /* this driver doesn't maintain sensitivity information */
2089 + range->sensitivity = 0;
2090 +
2091 + range->max_qual.qual = 100;
2092 + range->max_qual.level = 100;
2093 + range->max_qual.noise = 0;
2094 + range->max_qual.updated = IW_QUAL_NOISE_INVALID;
2095 +
2096 + range->avg_qual.qual = 50;
2097 + range->avg_qual.level = 50;
2098 + range->avg_qual.noise = 0;
2099 + range->avg_qual.updated = IW_QUAL_NOISE_INVALID;
2100 +
2101 + range->bitrate[0] = 1000000;
2102 + range->bitrate[1] = 2000000;
2103 + range->bitrate[2] = 5500000;
2104 + range->bitrate[3] = 11000000;
2105 + range->num_bitrates = 4;
2106 +
2107 + range->min_rts = 0;
2108 + range->max_rts = MAX_RTS_THRESHOLD;
2109 +
2110 + range->min_frag = MIN_FRAG_THRESHOLD;
2111 + range->max_frag = MAX_FRAG_THRESHOLD;
2112 +
2113 + range->pmp_flags = IW_POWER_PERIOD;
2114 + range->pmt_flags = IW_POWER_ON;
2115 + range->pm_capa = IW_POWER_PERIOD | IW_POWER_ALL_R;
2116 +
2117 + range->encoding_size[0] = WEP_SMALL_KEY_LEN;
2118 + range->encoding_size[1] = WEP_LARGE_KEY_LEN;
2119 + range->num_encoding_sizes = 2;
2120 + range->max_encoding_tokens = WEP_KEYS;
2121 +
2122 + /* both WL-240U and Linksys WUSB11 v2.6 specify 15 dBm as output power
2123 + - take this for all (ignore antenna gains) */
2124 + range->txpower[0] = 15;
2125 + range->num_txpower = 1;
2126 + range->txpower_capa = IW_TXPOW_DBM;
2127 +
2128 + range->we_version_source = WIRELESS_EXT;
2129 + range->we_version_compiled = WIRELESS_EXT;
2130 +
2131 + /* same as the values used in atmel.c */
2132 + range->retry_capa = IW_RETRY_LIMIT;
2133 + range->retry_flags = IW_RETRY_LIMIT;
2134 + range->r_time_flags = 0;
2135 + range->min_retry = 1;
2136 + range->max_retry = 255;
2137 +
2138 + range->num_channels = NUM_CHANNELS;
2139 + range->num_frequency = 0;
2140 +
2141 + for (i = 0; i < NUM_CHANNELS; i++) {
2142 + /* test if channel map bit is raised */
2143 + if (priv->domain->channel_map & (0x1 << i)) {
2144 + range->num_frequency += 1;
2145 +
2146 + range->freq[i].i = i + 1;
2147 + range->freq[i].m = channel_frequency[i] * 100000;
2148 + range->freq[i].e = 1; /* freq * 10^1 */
2149 + }
2150 + }
2151 +
2152 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWRANGE", netdev->name);
2153 +
2154 + return 0;
2155 +}
2156 +
2157 +static int at76_iw_handler_set_spy(struct net_device *netdev,
2158 + struct iw_request_info *info,
2159 + struct iw_point *data, char *extra)
2160 +{
2161 + struct at76_priv *priv = netdev_priv(netdev);
2162 + int ret = 0;
2163 +
2164 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWSPY - number of addresses %d",
2165 + netdev->name, data->length);
2166 +
2167 + spin_lock_bh(&priv->spy_spinlock);
2168 + ret = iw_handler_set_spy(priv->netdev, info, (union iwreq_data *)data,
2169 + extra);
2170 + spin_unlock_bh(&priv->spy_spinlock);
2171 +
2172 + return ret;
2173 +}
2174 +
2175 +static int at76_iw_handler_get_spy(struct net_device *netdev,
2176 + struct iw_request_info *info,
2177 + struct iw_point *data, char *extra)
2178 +{
2179 +
2180 + struct at76_priv *priv = netdev_priv(netdev);
2181 + int ret = 0;
2182 +
2183 + spin_lock_bh(&priv->spy_spinlock);
2184 + ret = iw_handler_get_spy(priv->netdev, info,
2185 + (union iwreq_data *)data, extra);
2186 + spin_unlock_bh(&priv->spy_spinlock);
2187 +
2188 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWSPY - number of addresses %d",
2189 + netdev->name, data->length);
2190 +
2191 + return ret;
2192 +}
2193 +
2194 +static int at76_iw_handler_set_thrspy(struct net_device *netdev,
2195 + struct iw_request_info *info,
2196 + struct iw_point *data, char *extra)
2197 +{
2198 + struct at76_priv *priv = netdev_priv(netdev);
2199 + int ret;
2200 +
2201 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWTHRSPY - number of addresses %d)",
2202 + netdev->name, data->length);
2203 +
2204 + spin_lock_bh(&priv->spy_spinlock);
2205 + ret = iw_handler_set_thrspy(netdev, info, (union iwreq_data *)data,
2206 + extra);
2207 + spin_unlock_bh(&priv->spy_spinlock);
2208 +
2209 + return ret;
2210 +}
2211 +
2212 +static int at76_iw_handler_get_thrspy(struct net_device *netdev,
2213 + struct iw_request_info *info,
2214 + struct iw_point *data, char *extra)
2215 +{
2216 + struct at76_priv *priv = netdev_priv(netdev);
2217 + int ret;
2218 +
2219 + spin_lock_bh(&priv->spy_spinlock);
2220 + ret = iw_handler_get_thrspy(netdev, info, (union iwreq_data *)data,
2221 + extra);
2222 + spin_unlock_bh(&priv->spy_spinlock);
2223 +
2224 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWTHRSPY - number of addresses %d)",
2225 + netdev->name, data->length);
2226 +
2227 + return ret;
2228 +}
2229 +
2230 +static int at76_iw_handler_set_wap(struct net_device *netdev,
2231 + struct iw_request_info *info,
2232 + struct sockaddr *ap_addr, char *extra)
2233 +{
2234 + struct at76_priv *priv = netdev_priv(netdev);
2235 +
2236 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWAP - wap/bssid %s", netdev->name,
2237 + mac2str(ap_addr->sa_data));
2238 +
2239 + /* if the incoming address == ff:ff:ff:ff:ff:ff, the user has
2240 + chosen any or auto AP preference */
2241 + if (is_broadcast_ether_addr(ap_addr->sa_data)
2242 + || is_zero_ether_addr(ap_addr->sa_data))
2243 + priv->wanted_bssid_valid = 0;
2244 + else {
2245 + /* user wants to set a preferred AP address */
2246 + priv->wanted_bssid_valid = 1;
2247 + memcpy(priv->wanted_bssid, ap_addr->sa_data, ETH_ALEN);
2248 + }
2249 +
2250 + return -EIWCOMMIT;
2251 +}
2252 +
2253 +static int at76_iw_handler_get_wap(struct net_device *netdev,
2254 + struct iw_request_info *info,
2255 + struct sockaddr *ap_addr, char *extra)
2256 +{
2257 + struct at76_priv *priv = netdev_priv(netdev);
2258 +
2259 + ap_addr->sa_family = ARPHRD_ETHER;
2260 + memcpy(ap_addr->sa_data, priv->bssid, ETH_ALEN);
2261 +
2262 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWAP - wap/bssid %s", netdev->name,
2263 + mac2str(ap_addr->sa_data));
2264 +
2265 + return 0;
2266 +}
2267 +
2268 +static int at76_iw_handler_set_scan(struct net_device *netdev,
2269 + struct iw_request_info *info,
2270 + union iwreq_data *wrqu, char *extra)
2271 +{
2272 + struct at76_priv *priv = netdev_priv(netdev);
2273 + int ret = 0;
2274 +
2275 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWSCAN", netdev->name);
2276 +
2277 + if (mutex_lock_interruptible(&priv->mtx))
2278 + return -EINTR;
2279 +
2280 + if (!netif_running(netdev)) {
2281 + ret = -ENETDOWN;
2282 + goto exit;
2283 + }
2284 +
2285 + /* jal: we don't allow "iwlist ethX scan" while we are
2286 + in monitor mode */
2287 + if (priv->iw_mode == IW_MODE_MONITOR) {
2288 + ret = -EBUSY;
2289 + goto exit;
2290 + }
2291 +
2292 + /* Discard old scan results */
2293 + if ((jiffies - priv->last_scan) > (20 * HZ))
2294 + priv->scan_state = SCAN_IDLE;
2295 + priv->last_scan = jiffies;
2296 +
2297 + /* Initiate a scan command */
2298 + if (priv->scan_state == SCAN_IN_PROGRESS) {
2299 + ret = -EBUSY;
2300 + goto exit;
2301 + }
2302 +
2303 + priv->scan_state = SCAN_IN_PROGRESS;
2304 +
2305 + at76_quiesce(priv);
2306 +
2307 + /* Try to do passive or active scan if WE asks as. */
2308 + if (wrqu->data.length
2309 + && wrqu->data.length == sizeof(struct iw_scan_req)) {
2310 + struct iw_scan_req *req = (struct iw_scan_req *)extra;
2311 +
2312 + if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
2313 + priv->scan_mode = SCAN_TYPE_PASSIVE;
2314 + else if (req->scan_type == IW_SCAN_TYPE_ACTIVE)
2315 + priv->scan_mode = SCAN_TYPE_ACTIVE;
2316 +
2317 + /* Sanity check values? */
2318 + if (req->min_channel_time > 0)
2319 + priv->scan_min_time = req->min_channel_time;
2320 +
2321 + if (req->max_channel_time > 0)
2322 + priv->scan_max_time = req->max_channel_time;
2323 + }
2324 +
2325 + /* change to scanning state */
2326 + at76_set_mac_state(priv, MAC_SCANNING);
2327 + schedule_work(&priv->work_start_scan);
2328 +
2329 +exit:
2330 + mutex_unlock(&priv->mtx);
2331 + return ret;
2332 +}
2333 +
2334 +static int at76_iw_handler_get_scan(struct net_device *netdev,
2335 + struct iw_request_info *info,
2336 + struct iw_point *data, char *extra)
2337 +{
2338 + struct at76_priv *priv = netdev_priv(netdev);
2339 + unsigned long flags;
2340 + struct list_head *lptr, *nptr;
2341 + struct bss_info *curr_bss;
2342 + struct iw_event *iwe = kmalloc(sizeof(struct iw_event), GFP_KERNEL);
2343 + char *curr_val, *curr_pos = extra;
2344 + int i;
2345 +
2346 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWSCAN", netdev->name);
2347 +
2348 + if (!iwe)
2349 + return -ENOMEM;
2350 +
2351 + if (priv->scan_state != SCAN_COMPLETED)
2352 + /* scan not yet finished */
2353 + return -EAGAIN;
2354 +
2355 + spin_lock_irqsave(&priv->bss_list_spinlock, flags);
2356 +
2357 + list_for_each_safe(lptr, nptr, &priv->bss_list) {
2358 + curr_bss = list_entry(lptr, struct bss_info, list);
2359 +
2360 + iwe->cmd = SIOCGIWAP;
2361 + iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
2362 + memcpy(iwe->u.ap_addr.sa_data, curr_bss->bssid, 6);
2363 + curr_pos = iwe_stream_add_event(info, curr_pos,
2364 + extra + IW_SCAN_MAX_DATA, iwe,
2365 + IW_EV_ADDR_LEN);
2366 +
2367 + iwe->u.data.length = curr_bss->ssid_len;
2368 + iwe->cmd = SIOCGIWESSID;
2369 + iwe->u.data.flags = 1;
2370 +
2371 + curr_pos = iwe_stream_add_point(info, curr_pos,
2372 + extra + IW_SCAN_MAX_DATA, iwe,
2373 + curr_bss->ssid);
2374 +
2375 + iwe->cmd = SIOCGIWMODE;
2376 + iwe->u.mode = (curr_bss->capa & WLAN_CAPABILITY_IBSS) ?
2377 + IW_MODE_ADHOC :
2378 + (curr_bss->capa & WLAN_CAPABILITY_ESS) ?
2379 + IW_MODE_MASTER : IW_MODE_AUTO;
2380 + /* IW_MODE_AUTO = 0 which I thought is
2381 + * the most logical value to return in this case */
2382 + curr_pos = iwe_stream_add_event(info, curr_pos,
2383 + extra + IW_SCAN_MAX_DATA, iwe,
2384 + IW_EV_UINT_LEN);
2385 +
2386 + iwe->cmd = SIOCGIWFREQ;
2387 + iwe->u.freq.m = curr_bss->channel;
2388 + iwe->u.freq.e = 0;
2389 + curr_pos = iwe_stream_add_event(info, curr_pos,
2390 + extra + IW_SCAN_MAX_DATA, iwe,
2391 + IW_EV_FREQ_LEN);
2392 +
2393 + iwe->cmd = SIOCGIWENCODE;
2394 + if (curr_bss->capa & WLAN_CAPABILITY_PRIVACY)
2395 + iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
2396 + else
2397 + iwe->u.data.flags = IW_ENCODE_DISABLED;
2398 +
2399 + iwe->u.data.length = 0;
2400 + curr_pos = iwe_stream_add_point(info, curr_pos,
2401 + extra + IW_SCAN_MAX_DATA, iwe,
2402 + NULL);
2403 +
2404 + /* Add quality statistics */
2405 + iwe->cmd = IWEVQUAL;
2406 + iwe->u.qual.noise = 0;
2407 + iwe->u.qual.updated =
2408 + IW_QUAL_NOISE_INVALID | IW_QUAL_LEVEL_UPDATED;
2409 + iwe->u.qual.level = (curr_bss->rssi * 100 / 42);
2410 + if (iwe->u.qual.level > 100)
2411 + iwe->u.qual.level = 100;
2412 + if (at76_is_intersil(priv->board_type))
2413 + iwe->u.qual.qual = curr_bss->link_qual;
2414 + else {
2415 + iwe->u.qual.qual = 0;
2416 + iwe->u.qual.updated |= IW_QUAL_QUAL_INVALID;
2417 + }
2418 + /* Add new value to event */
2419 + curr_pos = iwe_stream_add_event(info, curr_pos,
2420 + extra + IW_SCAN_MAX_DATA, iwe,
2421 + IW_EV_QUAL_LEN);
2422 +
2423 + /* Rate: stuffing multiple values in a single event requires
2424 + * a bit more of magic - Jean II */
2425 + curr_val = curr_pos + IW_EV_LCP_LEN;
2426 +
2427 + iwe->cmd = SIOCGIWRATE;
2428 + /* Those two flags are ignored... */
2429 + iwe->u.bitrate.fixed = 0;
2430 + iwe->u.bitrate.disabled = 0;
2431 + /* Max 8 values */
2432 + for (i = 0; i < curr_bss->rates_len; i++) {
2433 + /* Bit rate given in 500 kb/s units (+ 0x80) */
2434 + iwe->u.bitrate.value =
2435 + ((curr_bss->rates[i] & 0x7f) * 500000);
2436 + /* Add new value to event */
2437 + curr_val = iwe_stream_add_value(info, curr_pos,
2438 + curr_val,
2439 + extra +
2440 + IW_SCAN_MAX_DATA, iwe,
2441 + IW_EV_PARAM_LEN);
2442 + }
2443 +
2444 + /* Check if we added any event */
2445 + if ((curr_val - curr_pos) > IW_EV_LCP_LEN)
2446 + curr_pos = curr_val;
2447 +
2448 + /* more information may be sent back using IWECUSTOM */
2449 +
2450 + }
2451 +
2452 + spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
2453 +
2454 + data->length = (curr_pos - extra);
2455 + data->flags = 0;
2456 +
2457 + kfree(iwe);
2458 + return 0;
2459 +}
2460 +
2461 +static int at76_iw_handler_set_essid(struct net_device *netdev,
2462 + struct iw_request_info *info,
2463 + struct iw_point *data, char *extra)
2464 +{
2465 + struct at76_priv *priv = netdev_priv(netdev);
2466 +
2467 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWESSID - %s", netdev->name, extra);
2468 +
2469 + if (data->flags) {
2470 + memcpy(priv->essid, extra, data->length);
2471 + priv->essid_size = data->length;
2472 + } else
2473 + priv->essid_size = 0; /* Use any SSID */
2474 +
2475 + return -EIWCOMMIT;
2476 +}
2477 +
2478 +static int at76_iw_handler_get_essid(struct net_device *netdev,
2479 + struct iw_request_info *info,
2480 + struct iw_point *data, char *extra)
2481 +{
2482 + struct at76_priv *priv = netdev_priv(netdev);
2483 +
2484 + if (priv->essid_size) {
2485 + /* not the ANY ssid in priv->essid */
2486 + data->flags = 1;
2487 + data->length = priv->essid_size;
2488 + memcpy(extra, priv->essid, data->length);
2489 + } else {
2490 + /* the ANY ssid was specified */
2491 + if (priv->mac_state == MAC_CONNECTED && priv->curr_bss) {
2492 + /* report the SSID we have found */
2493 + data->flags = 1;
2494 + data->length = priv->curr_bss->ssid_len;
2495 + memcpy(extra, priv->curr_bss->ssid, data->length);
2496 + } else {
2497 + /* report ANY back */
2498 + data->flags = 0;
2499 + data->length = 0;
2500 + }
2501 + }
2502 +
2503 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWESSID - %.*s", netdev->name,
2504 + data->length, extra);
2505 +
2506 + return 0;
2507 +}
2508 +
2509 +static int at76_iw_handler_set_rate(struct net_device *netdev,
2510 + struct iw_request_info *info,
2511 + struct iw_param *bitrate, char *extra)
2512 +{
2513 + struct at76_priv *priv = netdev_priv(netdev);
2514 + int ret = -EIWCOMMIT;
2515 +
2516 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWRATE - %d", netdev->name,
2517 + bitrate->value);
2518 +
2519 + switch (bitrate->value) {
2520 + case -1:
2521 + priv->txrate = TX_RATE_AUTO;
2522 + break; /* auto rate */
2523 + case 1000000:
2524 + priv->txrate = TX_RATE_1MBIT;
2525 + break;
2526 + case 2000000:
2527 + priv->txrate = TX_RATE_2MBIT;
2528 + break;
2529 + case 5500000:
2530 + priv->txrate = TX_RATE_5_5MBIT;
2531 + break;
2532 + case 11000000:
2533 + priv->txrate = TX_RATE_11MBIT;
2534 + break;
2535 + default:
2536 + ret = -EINVAL;
2537 + }
2538 +
2539 + return ret;
2540 +}
2541 +
2542 +static int at76_iw_handler_get_rate(struct net_device *netdev,
2543 + struct iw_request_info *info,
2544 + struct iw_param *bitrate, char *extra)
2545 +{
2546 + struct at76_priv *priv = netdev_priv(netdev);
2547 + int ret = 0;
2548 +
2549 + switch (priv->txrate) {
2550 + /* return max rate if RATE_AUTO */
2551 + case TX_RATE_AUTO:
2552 + bitrate->value = 11000000;
2553 + break;
2554 + case TX_RATE_1MBIT:
2555 + bitrate->value = 1000000;
2556 + break;
2557 + case TX_RATE_2MBIT:
2558 + bitrate->value = 2000000;
2559 + break;
2560 + case TX_RATE_5_5MBIT:
2561 + bitrate->value = 5500000;
2562 + break;
2563 + case TX_RATE_11MBIT:
2564 + bitrate->value = 11000000;
2565 + break;
2566 + default:
2567 + ret = -EINVAL;
2568 + }
2569 +
2570 + bitrate->fixed = (priv->txrate != TX_RATE_AUTO);
2571 + bitrate->disabled = 0;
2572 +
2573 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWRATE - %d", netdev->name,
2574 + bitrate->value);
2575 +
2576 + return ret;
2577 +}
2578 +
2579 +static int at76_iw_handler_set_rts(struct net_device *netdev,
2580 + struct iw_request_info *info,
2581 + struct iw_param *rts, char *extra)
2582 +{
2583 + struct at76_priv *priv = netdev_priv(netdev);
2584 + int ret = -EIWCOMMIT;
2585 + int rthr = rts->value;
2586 +
2587 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWRTS - value %d disabled %s",
2588 + netdev->name, rts->value, (rts->disabled) ? "true" : "false");
2589 +
2590 + if (rts->disabled)
2591 + rthr = MAX_RTS_THRESHOLD;
2592 +
2593 + if ((rthr < 0) || (rthr > MAX_RTS_THRESHOLD))
2594 + ret = -EINVAL;
2595 + else
2596 + priv->rts_threshold = rthr;
2597 +
2598 + return ret;
2599 +}
2600 +
2601 +static int at76_iw_handler_get_rts(struct net_device *netdev,
2602 + struct iw_request_info *info,
2603 + struct iw_param *rts, char *extra)
2604 +{
2605 + struct at76_priv *priv = netdev_priv(netdev);
2606 +
2607 + rts->value = priv->rts_threshold;
2608 + rts->disabled = (rts->value >= MAX_RTS_THRESHOLD);
2609 + rts->fixed = 1;
2610 +
2611 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWRTS - value %d disabled %s",
2612 + netdev->name, rts->value, (rts->disabled) ? "true" : "false");
2613 +
2614 + return 0;
2615 +}
2616 +
2617 +static int at76_iw_handler_set_frag(struct net_device *netdev,
2618 + struct iw_request_info *info,
2619 + struct iw_param *frag, char *extra)
2620 +{
2621 + struct at76_priv *priv = netdev_priv(netdev);
2622 + int ret = -EIWCOMMIT;
2623 + int fthr = frag->value;
2624 +
2625 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWFRAG - value %d, disabled %s",
2626 + netdev->name, frag->value,
2627 + (frag->disabled) ? "true" : "false");
2628 +
2629 + if (frag->disabled)
2630 + fthr = MAX_FRAG_THRESHOLD;
2631 +
2632 + if ((fthr < MIN_FRAG_THRESHOLD) || (fthr > MAX_FRAG_THRESHOLD))
2633 + ret = -EINVAL;
2634 + else
2635 + priv->frag_threshold = fthr & ~0x1; /* get an even value */
2636 +
2637 + return ret;
2638 +}
2639 +
2640 +static int at76_iw_handler_get_frag(struct net_device *netdev,
2641 + struct iw_request_info *info,
2642 + struct iw_param *frag, char *extra)
2643 +{
2644 + struct at76_priv *priv = netdev_priv(netdev);
2645 +
2646 + frag->value = priv->frag_threshold;
2647 + frag->disabled = (frag->value >= MAX_FRAG_THRESHOLD);
2648 + frag->fixed = 1;
2649 +
2650 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWFRAG - value %d, disabled %s",
2651 + netdev->name, frag->value,
2652 + (frag->disabled) ? "true" : "false");
2653 +
2654 + return 0;
2655 +}
2656 +
2657 +static int at76_iw_handler_get_txpow(struct net_device *netdev,
2658 + struct iw_request_info *info,
2659 + struct iw_param *power, char *extra)
2660 +{
2661 + power->value = 15;
2662 + power->fixed = 1; /* No power control */
2663 + power->disabled = 0;
2664 + power->flags = IW_TXPOW_DBM;
2665 +
2666 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWTXPOW - txpow %d dBm", netdev->name,
2667 + power->value);
2668 +
2669 + return 0;
2670 +}
2671 +
2672 +/* jal: short retry is handled by the firmware (at least 0.90.x),
2673 + while long retry is not (?) */
2674 +static int at76_iw_handler_set_retry(struct net_device *netdev,
2675 + struct iw_request_info *info,
2676 + struct iw_param *retry, char *extra)
2677 +{
2678 + struct at76_priv *priv = netdev_priv(netdev);
2679 + int ret = -EIWCOMMIT;
2680 +
2681 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWRETRY disabled %d flags 0x%x val %d",
2682 + netdev->name, retry->disabled, retry->flags, retry->value);
2683 +
2684 + if (!retry->disabled && (retry->flags & IW_RETRY_LIMIT)) {
2685 + if ((retry->flags & IW_RETRY_MIN) ||
2686 + !(retry->flags & IW_RETRY_MAX))
2687 + priv->short_retry_limit = retry->value;
2688 + else
2689 + ret = -EINVAL;
2690 + } else
2691 + ret = -EINVAL;
2692 +
2693 + return ret;
2694 +}
2695 +
2696 +/* Adapted (ripped) from atmel.c */
2697 +static int at76_iw_handler_get_retry(struct net_device *netdev,
2698 + struct iw_request_info *info,
2699 + struct iw_param *retry, char *extra)
2700 +{
2701 + struct at76_priv *priv = netdev_priv(netdev);
2702 +
2703 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWRETRY", netdev->name);
2704 +
2705 + retry->disabled = 0; /* Can't be disabled */
2706 + retry->flags = IW_RETRY_LIMIT;
2707 + retry->value = priv->short_retry_limit;
2708 +
2709 + return 0;
2710 +}
2711 +
2712 +static int at76_iw_handler_set_encode(struct net_device *netdev,
2713 + struct iw_request_info *info,
2714 + struct iw_point *encoding, char *extra)
2715 +{
2716 + struct at76_priv *priv = netdev_priv(netdev);
2717 + int index = (encoding->flags & IW_ENCODE_INDEX) - 1;
2718 + int len = encoding->length;
2719 +
2720 + at76_dbg(DBG_IOCTL, "%s: SIOCSIWENCODE - enc.flags %08x "
2721 + "pointer %p len %d", netdev->name, encoding->flags,
2722 + encoding->pointer, encoding->length);
2723 + at76_dbg(DBG_IOCTL,
2724 + "%s: SIOCSIWENCODE - old wepstate: enabled %s key_id %d "
2725 + "auth_mode %s", netdev->name,
2726 + (priv->wep_enabled) ? "true" : "false", priv->wep_key_id,
2727 + (priv->auth_mode ==
2728 + WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
2729 +
2730 + /* take the old default key if index is invalid */
2731 + if ((index < 0) || (index >= WEP_KEYS))
2732 + index = priv->wep_key_id;
2733 +
2734 + if (len > 0) {
2735 + if (len > WEP_LARGE_KEY_LEN)
2736 + len = WEP_LARGE_KEY_LEN;
2737 +
2738 + memset(priv->wep_keys[index], 0, WEP_KEY_LEN);
2739 + memcpy(priv->wep_keys[index], extra, len);
2740 + priv->wep_keys_len[index] = (len <= WEP_SMALL_KEY_LEN) ?
2741 + WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
2742 + priv->wep_enabled = 1;
2743 + }
2744 +
2745 + priv->wep_key_id = index;
2746 + priv->wep_enabled = ((encoding->flags & IW_ENCODE_DISABLED) == 0);
2747 +
2748 + if (encoding->flags & IW_ENCODE_RESTRICTED)
2749 + priv->auth_mode = WLAN_AUTH_SHARED_KEY;
2750 + if (encoding->flags & IW_ENCODE_OPEN)
2751 + priv->auth_mode = WLAN_AUTH_OPEN;
2752 +
2753 + at76_dbg(DBG_IOCTL,
2754 + "%s: SIOCSIWENCODE - new wepstate: enabled %s key_id %d "
2755 + "key_len %d auth_mode %s", netdev->name,
2756 + (priv->wep_enabled) ? "true" : "false", priv->wep_key_id + 1,
2757 + priv->wep_keys_len[priv->wep_key_id],
2758 + (priv->auth_mode ==
2759 + WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
2760 +
2761 + return -EIWCOMMIT;
2762 +}
2763 +
2764 +static int at76_iw_handler_get_encode(struct net_device *netdev,
2765 + struct iw_request_info *info,
2766 + struct iw_point *encoding, char *extra)
2767 +{
2768 + struct at76_priv *priv = netdev_priv(netdev);
2769 + int index = (encoding->flags & IW_ENCODE_INDEX) - 1;
2770 +
2771 + if ((index < 0) || (index >= WEP_KEYS))
2772 + index = priv->wep_key_id;
2773 +
2774 + encoding->flags =
2775 + (priv->auth_mode == WLAN_AUTH_SHARED_KEY) ?
2776 + IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
2777 +
2778 + if (!priv->wep_enabled)
2779 + encoding->flags |= IW_ENCODE_DISABLED;
2780 +
2781 + if (encoding->pointer) {
2782 + encoding->length = priv->wep_keys_len[index];
2783 +
2784 + memcpy(extra, priv->wep_keys[index], priv->wep_keys_len[index]);
2785 +
2786 + encoding->flags |= (index + 1);
2787 + }
2788 +
2789 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWENCODE - enc.flags %08x "
2790 + "pointer %p len %d", netdev->name, encoding->flags,
2791 + encoding->pointer, encoding->length);
2792 + at76_dbg(DBG_IOCTL,
2793 + "%s: SIOCGIWENCODE - wepstate: enabled %s key_id %d "
2794 + "key_len %d auth_mode %s", netdev->name,
2795 + (priv->wep_enabled) ? "true" : "false", priv->wep_key_id + 1,
2796 + priv->wep_keys_len[priv->wep_key_id],
2797 + (priv->auth_mode ==
2798 + WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
2799 +
2800 + return 0;
2801 +}
2802 +
2803 +static int at76_iw_handler_set_power(struct net_device *netdev,
2804 + struct iw_request_info *info,
2805 + struct iw_param *prq, char *extra)
2806 +{
2807 + int err = -EIWCOMMIT;
2808 + struct at76_priv *priv = netdev_priv(netdev);
2809 +
2810 + at76_dbg(DBG_IOCTL,
2811 + "%s: SIOCSIWPOWER - disabled %s flags 0x%x value 0x%x",
2812 + netdev->name, (prq->disabled) ? "true" : "false", prq->flags,
2813 + prq->value);
2814 +
2815 + if (prq->disabled)
2816 + priv->pm_mode = AT76_PM_OFF;
2817 + else {
2818 + switch (prq->flags & IW_POWER_MODE) {
2819 + case IW_POWER_ALL_R:
2820 + case IW_POWER_ON:
2821 + break;
2822 + default:
2823 + err = -EINVAL;
2824 + goto exit;
2825 + }
2826 + if (prq->flags & IW_POWER_PERIOD)
2827 + priv->pm_period = prq->value;
2828 +
2829 + if (prq->flags & IW_POWER_TIMEOUT) {
2830 + err = -EINVAL;
2831 + goto exit;
2832 + }
2833 + priv->pm_mode = AT76_PM_ON;
2834 + }
2835 +exit:
2836 + return err;
2837 +}
2838 +
2839 +static int at76_iw_handler_get_power(struct net_device *netdev,
2840 + struct iw_request_info *info,
2841 + struct iw_param *power, char *extra)
2842 +{
2843 + struct at76_priv *priv = netdev_priv(netdev);
2844 +
2845 + power->disabled = (priv->pm_mode == AT76_PM_OFF);
2846 + if (!power->disabled) {
2847 + power->flags = IW_POWER_PERIOD | IW_POWER_ALL_R;
2848 + power->value = priv->pm_period;
2849 + }
2850 +
2851 + at76_dbg(DBG_IOCTL, "%s: SIOCGIWPOWER - %s flags 0x%x value 0x%x",
2852 + netdev->name, power->disabled ? "disabled" : "enabled",
2853 + power->flags, power->value);
2854 +
2855 + return 0;
2856 +}
2857 +
2858 +/*******************************************************************************
2859 + * Private IOCTLS
2860 + */
2861 +static int at76_iw_set_short_preamble(struct net_device *netdev,
2862 + struct iw_request_info *info, char *name,
2863 + char *extra)
2864 +{
2865 + struct at76_priv *priv = netdev_priv(netdev);
2866 + int val = *((int *)name);
2867 + int ret = -EIWCOMMIT;
2868 +
2869 + at76_dbg(DBG_IOCTL, "%s: AT76_SET_SHORT_PREAMBLE, %d",
2870 + netdev->name, val);
2871 +
2872 + if (val < PREAMBLE_TYPE_LONG || val > PREAMBLE_TYPE_AUTO)
2873 + ret = -EINVAL;
2874 + else
2875 + priv->preamble_type = val;
2876 +
2877 + return ret;
2878 +}
2879 +
2880 +static int at76_iw_get_short_preamble(struct net_device *netdev,
2881 + struct iw_request_info *info,
2882 + union iwreq_data *wrqu, char *extra)
2883 +{
2884 + struct at76_priv *priv = netdev_priv(netdev);
2885 +
2886 + snprintf(wrqu->name, sizeof(wrqu->name), "%s (%d)",
2887 + preambles[priv->preamble_type], priv->preamble_type);
2888 + return 0;
2889 +}
2890 +
2891 +static int at76_iw_set_debug(struct net_device *netdev,
2892 + struct iw_request_info *info,
2893 + struct iw_point *data, char *extra)
2894 +{
2895 + char *ptr;
2896 + u32 val;
2897 +
2898 + if (data->length > 0) {
2899 + val = simple_strtol(extra, &ptr, 0);
2900 +
2901 + if (ptr == extra)
2902 + val = DBG_DEFAULTS;
2903 +
2904 + at76_dbg(DBG_IOCTL, "%s: AT76_SET_DEBUG input %d: %s -> 0x%x",
2905 + netdev->name, data->length, extra, val);
2906 + } else
2907 + val = DBG_DEFAULTS;
2908 +
2909 + at76_dbg(DBG_IOCTL, "%s: AT76_SET_DEBUG, old 0x%x, new 0x%x",
2910 + netdev->name, at76_debug, val);
2911 +
2912 + /* jal: some more output to pin down lockups */
2913 + at76_dbg(DBG_IOCTL, "%s: netif running %d queue_stopped %d "
2914 + "carrier_ok %d", netdev->name, netif_running(netdev),
2915 + netif_queue_stopped(netdev), netif_carrier_ok(netdev));
2916 +
2917 + at76_debug = val;
2918 +
2919 + return 0;
2920 +}
2921 +
2922 +static int at76_iw_get_debug(struct net_device *netdev,
2923 + struct iw_request_info *info,
2924 + union iwreq_data *wrqu, char *extra)
2925 +{
2926 + snprintf(wrqu->name, sizeof(wrqu->name), "0x%08x", at76_debug);
2927 + return 0;
2928 +}
2929 +
2930 +static int at76_iw_set_powersave_mode(struct net_device *netdev,
2931 + struct iw_request_info *info, char *name,
2932 + char *extra)
2933 +{
2934 + struct at76_priv *priv = netdev_priv(netdev);
2935 + int val = *((int *)name);
2936 + int ret = -EIWCOMMIT;
2937 +
2938 + at76_dbg(DBG_IOCTL, "%s: AT76_SET_POWERSAVE_MODE, %d (%s)",
2939 + netdev->name, val,
2940 + val == AT76_PM_OFF ? "active" : val == AT76_PM_ON ? "save" :
2941 + val == AT76_PM_SMART ? "smart save" : "<invalid>");
2942 + if (val < AT76_PM_OFF || val > AT76_PM_SMART)
2943 + ret = -EINVAL;
2944 + else
2945 + priv->pm_mode = val;
2946 +
2947 + return ret;
2948 +}
2949 +
2950 +static int at76_iw_get_powersave_mode(struct net_device *netdev,
2951 + struct iw_request_info *info,
2952 + union iwreq_data *wrqu, char *extra)
2953 +{
2954 + struct at76_priv *priv = netdev_priv(netdev);
2955 + int *param = (int *)extra;
2956 +
2957 + param[0] = priv->pm_mode;
2958 + return 0;
2959 +}
2960 +
2961 +static int at76_iw_set_scan_times(struct net_device *netdev,
2962 + struct iw_request_info *info, char *name,
2963 + char *extra)
2964 +{
2965 + struct at76_priv *priv = netdev_priv(netdev);
2966 + int mint = *((int *)name);
2967 + int maxt = *((int *)name + 1);
2968 + int ret = -EIWCOMMIT;
2969 +
2970 + at76_dbg(DBG_IOCTL, "%s: AT76_SET_SCAN_TIMES - min %d max %d",
2971 + netdev->name, mint, maxt);
2972 + if (mint <= 0 || maxt <= 0 || mint > maxt)
2973 + ret = -EINVAL;
2974 + else {
2975 + priv->scan_min_time = mint;
2976 + priv->scan_max_time = maxt;
2977 + }
2978 +
2979 + return ret;
2980 +}
2981 +
2982 +static int at76_iw_get_scan_times(struct net_device *netdev,
2983 + struct iw_request_info *info,
2984 + union iwreq_data *wrqu, char *extra)
2985 +{
2986 + struct at76_priv *priv = netdev_priv(netdev);
2987 + int *param = (int *)extra;
2988 +
2989 + param[0] = priv->scan_min_time;
2990 + param[1] = priv->scan_max_time;
2991 + return 0;
2992 +}
2993 +
2994 +static int at76_iw_set_scan_mode(struct net_device *netdev,
2995 + struct iw_request_info *info, char *name,
2996 + char *extra)
2997 +{
2998 + struct at76_priv *priv = netdev_priv(netdev);
2999 + int val = *((int *)name);
3000 + int ret = -EIWCOMMIT;
3001 +
3002 + at76_dbg(DBG_IOCTL, "%s: AT76_SET_SCAN_MODE - mode %s",
3003 + netdev->name, (val = SCAN_TYPE_ACTIVE) ? "active" :
3004 + (val = SCAN_TYPE_PASSIVE) ? "passive" : "<invalid>");
3005 +
3006 + if (val != SCAN_TYPE_ACTIVE && val != SCAN_TYPE_PASSIVE)
3007 + ret = -EINVAL;
3008 + else
3009 + priv->scan_mode = val;
3010 +
3011 + return ret;
3012 +}
3013 +
3014 +static int at76_iw_get_scan_mode(struct net_device *netdev,
3015 + struct iw_request_info *info,
3016 + union iwreq_data *wrqu, char *extra)
3017 +{
3018 + struct at76_priv *priv = netdev_priv(netdev);
3019 + int *param = (int *)extra;
3020 +
3021 + param[0] = priv->scan_mode;
3022 + return 0;
3023 +}
3024 +
3025 +#define AT76_SET_HANDLER(h, f) [h - SIOCIWFIRST] = (iw_handler) f
3026 +
3027 +/* Standard wireless handlers */
3028 +static const iw_handler at76_handlers[] = {
3029 + AT76_SET_HANDLER(SIOCSIWCOMMIT, at76_iw_handler_commit),
3030 + AT76_SET_HANDLER(SIOCGIWNAME, at76_iw_handler_get_name),
3031 + AT76_SET_HANDLER(SIOCSIWFREQ, at76_iw_handler_set_freq),
3032 + AT76_SET_HANDLER(SIOCGIWFREQ, at76_iw_handler_get_freq),
3033 + AT76_SET_HANDLER(SIOCSIWMODE, at76_iw_handler_set_mode),
3034 + AT76_SET_HANDLER(SIOCGIWMODE, at76_iw_handler_get_mode),
3035 + AT76_SET_HANDLER(SIOCGIWRANGE, at76_iw_handler_get_range),
3036 + AT76_SET_HANDLER(SIOCSIWSPY, at76_iw_handler_set_spy),
3037 + AT76_SET_HANDLER(SIOCGIWSPY, at76_iw_handler_get_spy),
3038 + AT76_SET_HANDLER(SIOCSIWTHRSPY, at76_iw_handler_set_thrspy),
3039 + AT76_SET_HANDLER(SIOCGIWTHRSPY, at76_iw_handler_get_thrspy),
3040 + AT76_SET_HANDLER(SIOCSIWAP, at76_iw_handler_set_wap),
3041 + AT76_SET_HANDLER(SIOCGIWAP, at76_iw_handler_get_wap),
3042 + AT76_SET_HANDLER(SIOCSIWSCAN, at76_iw_handler_set_scan),
3043 + AT76_SET_HANDLER(SIOCGIWSCAN, at76_iw_handler_get_scan),
3044 + AT76_SET_HANDLER(SIOCSIWESSID, at76_iw_handler_set_essid),
3045 + AT76_SET_HANDLER(SIOCGIWESSID, at76_iw_handler_get_essid),
3046 + AT76_SET_HANDLER(SIOCSIWRATE, at76_iw_handler_set_rate),
3047 + AT76_SET_HANDLER(SIOCGIWRATE, at76_iw_handler_get_rate),
3048 + AT76_SET_HANDLER(SIOCSIWRTS, at76_iw_handler_set_rts),
3049 + AT76_SET_HANDLER(SIOCGIWRTS, at76_iw_handler_get_rts),
3050 + AT76_SET_HANDLER(SIOCSIWFRAG, at76_iw_handler_set_frag),
3051 + AT76_SET_HANDLER(SIOCGIWFRAG, at76_iw_handler_get_frag),
3052 + AT76_SET_HANDLER(SIOCGIWTXPOW, at76_iw_handler_get_txpow),
3053 + AT76_SET_HANDLER(SIOCSIWRETRY, at76_iw_handler_set_retry),
3054 + AT76_SET_HANDLER(SIOCGIWRETRY, at76_iw_handler_get_retry),
3055 + AT76_SET_HANDLER(SIOCSIWENCODE, at76_iw_handler_set_encode),
3056 + AT76_SET_HANDLER(SIOCGIWENCODE, at76_iw_handler_get_encode),
3057 + AT76_SET_HANDLER(SIOCSIWPOWER, at76_iw_handler_set_power),
3058 + AT76_SET_HANDLER(SIOCGIWPOWER, at76_iw_handler_get_power)
3059 +};
3060 +
3061 +#define AT76_SET_PRIV(h, f) [h - SIOCIWFIRSTPRIV] = (iw_handler) f
3062 +
3063 +/* Private wireless handlers */
3064 +static const iw_handler at76_priv_handlers[] = {
3065 + AT76_SET_PRIV(AT76_SET_SHORT_PREAMBLE, at76_iw_set_short_preamble),
3066 + AT76_SET_PRIV(AT76_GET_SHORT_PREAMBLE, at76_iw_get_short_preamble),
3067 + AT76_SET_PRIV(AT76_SET_DEBUG, at76_iw_set_debug),
3068 + AT76_SET_PRIV(AT76_GET_DEBUG, at76_iw_get_debug),
3069 + AT76_SET_PRIV(AT76_SET_POWERSAVE_MODE, at76_iw_set_powersave_mode),
3070 + AT76_SET_PRIV(AT76_GET_POWERSAVE_MODE, at76_iw_get_powersave_mode),
3071 + AT76_SET_PRIV(AT76_SET_SCAN_TIMES, at76_iw_set_scan_times),
3072 + AT76_SET_PRIV(AT76_GET_SCAN_TIMES, at76_iw_get_scan_times),
3073 + AT76_SET_PRIV(AT76_SET_SCAN_MODE, at76_iw_set_scan_mode),
3074 + AT76_SET_PRIV(AT76_GET_SCAN_MODE, at76_iw_get_scan_mode),
3075 +};
3076 +
3077 +/* Names and arguments of private wireless handlers */
3078 +static const struct iw_priv_args at76_priv_args[] = {
3079 + /* 0 - long, 1 - short */
3080 + {AT76_SET_SHORT_PREAMBLE,
3081 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble"},
3082 +
3083 + {AT76_GET_SHORT_PREAMBLE,
3084 + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 10, "get_preamble"},
3085 +
3086 + /* we must pass the new debug mask as a string, because iwpriv cannot
3087 + * parse hex numbers starting with 0x :-( */
3088 + {AT76_SET_DEBUG,
3089 + IW_PRIV_TYPE_CHAR | 10, 0, "set_debug"},
3090 +
3091 + {AT76_GET_DEBUG,
3092 + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 10, "get_debug"},
3093 +
3094 + /* 1 - active, 2 - power save, 3 - smart power save */
3095 + {AT76_SET_POWERSAVE_MODE,
3096 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_powersave"},
3097 +
3098 + {AT76_GET_POWERSAVE_MODE,
3099 + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_powersave"},
3100 +
3101 + /* min_channel_time, max_channel_time */
3102 + {AT76_SET_SCAN_TIMES,
3103 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_scan_times"},
3104 +
3105 + {AT76_GET_SCAN_TIMES,
3106 + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, "get_scan_times"},
3107 +
3108 + /* 0 - active, 1 - passive scan */
3109 + {AT76_SET_SCAN_MODE,
3110 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_scan_mode"},
3111 +
3112 + {AT76_GET_SCAN_MODE,
3113 + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_scan_mode"},
3114 +};
3115 +
3116 +static const struct iw_handler_def at76_handler_def = {
3117 + .num_standard = ARRAY_SIZE(at76_handlers),
3118 + .num_private = ARRAY_SIZE(at76_priv_handlers),
3119 + .num_private_args = ARRAY_SIZE(at76_priv_args),
3120 + .standard = at76_handlers,
3121 + .private = at76_priv_handlers,
3122 + .private_args = at76_priv_args,
3123 + .get_wireless_stats = at76_get_wireless_stats,
3124 +};
3125 +
3126 +static const u8 snapsig[] = { 0xaa, 0xaa, 0x03 };
3127 +
3128 +/* RFC 1042 encapsulates Ethernet frames in 802.2 SNAP (0xaa, 0xaa, 0x03) with
3129 + * a SNAP OID of 0 (0x00, 0x00, 0x00) */
3130 +static const u8 rfc1042sig[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
3131 +
3132 +static int at76_tx(struct sk_buff *skb, struct net_device *netdev)
3133 +{
3134 + struct at76_priv *priv = netdev_priv(netdev);
3135 + struct net_device_stats *stats = &priv->stats;
3136 + int ret = 0;
3137 + int wlen;
3138 + int submit_len;
3139 + struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
3140 + struct ieee80211_hdr_3addr *i802_11_hdr =
3141 + (struct ieee80211_hdr_3addr *)tx_buffer->packet;
3142 + u8 *payload = i802_11_hdr->payload;
3143 + struct ethhdr *eh = (struct ethhdr *)skb->data;
3144 +
3145 + if (netif_queue_stopped(netdev)) {
3146 + printk(KERN_ERR "%s: %s called while netdev is stopped\n",
3147 + netdev->name, __func__);
3148 + /* skip this packet */
3149 + dev_kfree_skb(skb);
3150 + return 0;
3151 + }
3152 +
3153 + if (priv->tx_urb->status == -EINPROGRESS) {
3154 + printk(KERN_ERR "%s: %s called while tx urb is pending\n",
3155 + netdev->name, __func__);
3156 + /* skip this packet */
3157 + dev_kfree_skb(skb);
3158 + return 0;
3159 + }
3160 +
3161 + if (skb->len < ETH_HLEN) {
3162 + printk(KERN_ERR "%s: %s: skb too short (%d)\n",
3163 + netdev->name, __func__, skb->len);
3164 + dev_kfree_skb(skb);
3165 + return 0;
3166 + }
3167 +
3168 + at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */
3169 +
3170 + /* we can get rid of memcpy if we set netdev->hard_header_len to
3171 + reserve enough space, but we would need to keep the skb around */
3172 +
3173 + if (ntohs(eh->h_proto) <= ETH_DATA_LEN) {
3174 + /* this is a 802.3 packet */
3175 + if (skb->len >= ETH_HLEN + sizeof(rfc1042sig)
3176 + && skb->data[ETH_HLEN] == rfc1042sig[0]
3177 + && skb->data[ETH_HLEN + 1] == rfc1042sig[1]) {
3178 + /* higher layer delivered SNAP header - keep it */
3179 + memcpy(payload, skb->data + ETH_HLEN,
3180 + skb->len - ETH_HLEN);
3181 + wlen = IEEE80211_3ADDR_LEN + skb->len - ETH_HLEN;
3182 + } else {
3183 + printk(KERN_ERR "%s: dropping non-SNAP 802.2 packet "
3184 + "(DSAP 0x%02x SSAP 0x%02x cntrl 0x%02x)\n",
3185 + priv->netdev->name, skb->data[ETH_HLEN],
3186 + skb->data[ETH_HLEN + 1],
3187 + skb->data[ETH_HLEN + 2]);
3188 + dev_kfree_skb(skb);
3189 + return 0;
3190 + }
3191 + } else {
3192 + /* add RFC 1042 header in front */
3193 + memcpy(payload, rfc1042sig, sizeof(rfc1042sig));
3194 + memcpy(payload + sizeof(rfc1042sig), &eh->h_proto,
3195 + skb->len - offsetof(struct ethhdr, h_proto));
3196 + wlen = IEEE80211_3ADDR_LEN + sizeof(rfc1042sig) + skb->len -
3197 + offsetof(struct ethhdr, h_proto);
3198 + }
3199 +
3200 + /* make wireless header */
3201 + i802_11_hdr->frame_ctl =
3202 + cpu_to_le16(IEEE80211_FTYPE_DATA |
3203 + (priv->wep_enabled ? IEEE80211_FCTL_PROTECTED : 0) |
3204 + (priv->iw_mode ==
3205 + IW_MODE_INFRA ? IEEE80211_FCTL_TODS : 0));
3206 +
3207 + if (priv->iw_mode == IW_MODE_ADHOC) {
3208 + memcpy(i802_11_hdr->addr1, eh->h_dest, ETH_ALEN);
3209 + memcpy(i802_11_hdr->addr2, eh->h_source, ETH_ALEN);
3210 + memcpy(i802_11_hdr->addr3, priv->bssid, ETH_ALEN);
3211 + } else if (priv->iw_mode == IW_MODE_INFRA) {
3212 + memcpy(i802_11_hdr->addr1, priv->bssid, ETH_ALEN);
3213 + memcpy(i802_11_hdr->addr2, eh->h_source, ETH_ALEN);
3214 + memcpy(i802_11_hdr->addr3, eh->h_dest, ETH_ALEN);
3215 + }
3216 +
3217 + i802_11_hdr->duration_id = cpu_to_le16(0);
3218 + i802_11_hdr->seq_ctl = cpu_to_le16(0);
3219 +
3220 + /* setup 'Atmel' header */
3221 + tx_buffer->wlength = cpu_to_le16(wlen);
3222 + tx_buffer->tx_rate = priv->txrate;
3223 + /* for broadcast destination addresses, the firmware 0.100.x
3224 + seems to choose the highest rate set with CMD_STARTUP in
3225 + basic_rate_set replacing this value */
3226 +
3227 + memset(tx_buffer->reserved, 0, sizeof(tx_buffer->reserved));
3228 +
3229 + tx_buffer->padding = at76_calc_padding(wlen);
3230 + submit_len = wlen + AT76_TX_HDRLEN + tx_buffer->padding;
3231 +
3232 + at76_dbg(DBG_TX_DATA_CONTENT, "%s skb->data %s", priv->netdev->name,
3233 + hex2str(skb->data, 32));
3234 + at76_dbg(DBG_TX_DATA, "%s tx: wlen 0x%x pad 0x%x rate %d hdr %s",
3235 + priv->netdev->name,
3236 + le16_to_cpu(tx_buffer->wlength),
3237 + tx_buffer->padding, tx_buffer->tx_rate,
3238 + hex2str(i802_11_hdr, sizeof(*i802_11_hdr)));
3239 + at76_dbg(DBG_TX_DATA_CONTENT, "%s payload %s", priv->netdev->name,
3240 + hex2str(payload, 48));
3241 +
3242 + /* send stuff */
3243 + netif_stop_queue(netdev);
3244 + netdev->trans_start = jiffies;
3245 +
3246 + usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe, tx_buffer,
3247 + submit_len, at76_tx_callback, priv);
3248 + ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
3249 + if (ret) {
3250 + stats->tx_errors++;
3251 + printk(KERN_ERR "%s: error in tx submit urb: %d\n",
3252 + netdev->name, ret);
3253 + if (ret == -EINVAL)
3254 + printk(KERN_ERR
3255 + "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n",
3256 + priv->netdev->name, priv->tx_urb,
3257 + priv->tx_urb->hcpriv, priv->tx_urb->complete);
3258 + } else {
3259 + stats->tx_bytes += skb->len;
3260 + dev_kfree_skb(skb);
3261 + }
3262 +
3263 + return ret;
3264 +}
3265 +
3266 +static void at76_tx_timeout(struct net_device *netdev)
3267 +{
3268 + struct at76_priv *priv = netdev_priv(netdev);
3269 +
3270 + if (!priv)
3271 + return;
3272 + dev_warn(&netdev->dev, "tx timeout.");
3273 +
3274 + usb_unlink_urb(priv->tx_urb);
3275 + priv->stats.tx_errors++;
3276 +}
3277 +
3278 +static int at76_submit_rx_urb(struct at76_priv *priv)
3279 +{
3280 + int ret;
3281 + int size;
3282 + struct sk_buff *skb = priv->rx_skb;
3283 +
3284 + if (!priv->rx_urb) {
3285 + printk(KERN_ERR "%s: %s: priv->rx_urb is NULL\n",
3286 + priv->netdev->name, __func__);
3287 + return -EFAULT;
3288 + }
3289 +
3290 + if (!skb) {
3291 + skb = dev_alloc_skb(sizeof(struct at76_rx_buffer));
3292 + if (!skb) {
3293 + printk(KERN_ERR "%s: cannot allocate rx skbuff\n",
3294 + priv->netdev->name);
3295 + ret = -ENOMEM;
3296 + goto exit;
3297 + }
3298 + priv->rx_skb = skb;
3299 + } else {
3300 + skb_push(skb, skb_headroom(skb));
3301 + skb_trim(skb, 0);
3302 + }
3303 +
3304 + size = skb_tailroom(skb);
3305 + usb_fill_bulk_urb(priv->rx_urb, priv->udev, priv->rx_pipe,
3306 + skb_put(skb, size), size, at76_rx_callback, priv);
3307 + ret = usb_submit_urb(priv->rx_urb, GFP_ATOMIC);
3308 + if (ret < 0) {
3309 + if (ret == -ENODEV)
3310 + at76_dbg(DBG_DEVSTART,
3311 + "usb_submit_urb returned -ENODEV");
3312 + else
3313 + printk(KERN_ERR "%s: rx, usb_submit_urb failed: %d\n",
3314 + priv->netdev->name, ret);
3315 + }
3316 +
3317 +exit:
3318 + if (ret < 0 && ret != -ENODEV)
3319 + printk(KERN_ERR "%s: cannot submit rx urb - please unload the "
3320 + "driver and/or power cycle the device\n",
3321 + priv->netdev->name);
3322 +
3323 + return ret;
3324 +}
3325 +
3326 +static int at76_open(struct net_device *netdev)
3327 +{
3328 + struct at76_priv *priv = netdev_priv(netdev);
3329 + int ret = 0;
3330 +
3331 + at76_dbg(DBG_PROC_ENTRY, "%s(): entry", __func__);
3332 +
3333 + if (mutex_lock_interruptible(&priv->mtx))
3334 + return -EINTR;
3335 +
3336 + /* if netdev->dev_addr != priv->mac_addr we must
3337 + set the mac address in the device ! */
3338 + if (compare_ether_addr(netdev->dev_addr, priv->mac_addr)) {
3339 + if (at76_add_mac_address(priv, netdev->dev_addr) >= 0)
3340 + at76_dbg(DBG_PROGRESS, "%s: set new MAC addr %s",
3341 + netdev->name, mac2str(netdev->dev_addr));
3342 + }
3343 +
3344 + priv->scan_state = SCAN_IDLE;
3345 + priv->last_scan = jiffies;
3346 +
3347 + ret = at76_submit_rx_urb(priv);
3348 + if (ret < 0) {
3349 + printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n",
3350 + netdev->name, ret);
3351 + goto error;
3352 + }
3353 +
3354 + schedule_delayed_work(&priv->dwork_restart, 0);
3355 +
3356 + at76_dbg(DBG_PROC_ENTRY, "%s(): end", __func__);
3357 +error:
3358 + mutex_unlock(&priv->mtx);
3359 + return ret < 0 ? ret : 0;
3360 +}
3361 +
3362 +static int at76_stop(struct net_device *netdev)
3363 +{
3364 + struct at76_priv *priv = netdev_priv(netdev);
3365 +
3366 + at76_dbg(DBG_DEVSTART, "%s: ENTER", __func__);
3367 +
3368 + if (mutex_lock_interruptible(&priv->mtx))
3369 + return -EINTR;
3370 +
3371 + at76_quiesce(priv);
3372 +
3373 + if (!priv->device_unplugged) {
3374 + /* We are called by "ifconfig ethX down", not because the
3375 + * device is not available anymore. */
3376 + at76_set_radio(priv, 0);
3377 +
3378 + /* We unlink rx_urb because at76_open() re-submits it.
3379 + * If unplugged, at76_delete_device() takes care of it. */
3380 + usb_kill_urb(priv->rx_urb);
3381 + }
3382 +
3383 + /* free the bss_list */
3384 + at76_free_bss_list(priv);
3385 +
3386 + mutex_unlock(&priv->mtx);
3387 + at76_dbg(DBG_DEVSTART, "%s: EXIT", __func__);
3388 +
3389 + return 0;
3390 +}
3391 +
3392 +static void at76_ethtool_get_drvinfo(struct net_device *netdev,
3393 + struct ethtool_drvinfo *info)
3394 +{
3395 + struct at76_priv *priv = netdev_priv(netdev);
3396 +
3397 + strncpy(info->driver, DRIVER_NAME, sizeof(info->driver));
3398 + strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
3399 +
3400 + usb_make_path(priv->udev, info->bus_info, sizeof(info->bus_info));
3401 +
3402 + snprintf(info->fw_version, sizeof(info->fw_version), "%d.%d.%d-%d",
3403 + priv->fw_version.major, priv->fw_version.minor,
3404 + priv->fw_version.patch, priv->fw_version.build);
3405 +}
3406 +
3407 +static u32 at76_ethtool_get_link(struct net_device *netdev)
3408 +{
3409 + struct at76_priv *priv = netdev_priv(netdev);
3410 + return priv->mac_state == MAC_CONNECTED;
3411 +}
3412 +
3413 +static struct ethtool_ops at76_ethtool_ops = {
3414 + .get_drvinfo = at76_ethtool_get_drvinfo,
3415 + .get_link = at76_ethtool_get_link,
3416 +};
3417 +
3418 +/* Download external firmware */
3419 +static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
3420 +{
3421 + int ret;
3422 + int op_mode;
3423 + int blockno = 0;
3424 + int bsize;
3425 + u8 *block;
3426 + u8 *buf = fwe->extfw;
3427 + int size = fwe->extfw_size;
3428 +
3429 + if (!buf || !size)
3430 + return -ENOENT;
3431 +
3432 + op_mode = at76_get_op_mode(udev);
3433 + at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
3434 +
3435 + if (op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
3436 + dev_printk(KERN_ERR, &udev->dev, "unexpected opmode %d\n",
3437 + op_mode);
3438 + return -EINVAL;
3439 + }
3440 +
3441 + block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL);
3442 + if (!block)
3443 + return -ENOMEM;
3444 +
3445 + at76_dbg(DBG_DEVSTART, "downloading external firmware");
3446 +
3447 + /* for fw >= 0.100, the device needs an extra empty block */
3448 + do {
3449 + bsize = min_t(int, size, FW_BLOCK_SIZE);
3450 + memcpy(block, buf, bsize);
3451 + at76_dbg(DBG_DEVSTART,
3452 + "ext fw, size left = %5d, bsize = %4d, blockno = %2d",
3453 + size, bsize, blockno);
3454 + ret = at76_load_ext_fw_block(udev, blockno, block, bsize);
3455 + if (ret != bsize) {
3456 + dev_printk(KERN_ERR, &udev->dev,
3457 + "loading %dth firmware block failed: %d\n",
3458 + blockno, ret);
3459 + goto exit;
3460 + }
3461 + buf += bsize;
3462 + size -= bsize;
3463 + blockno++;
3464 + } while (bsize > 0);
3465 +
3466 + if (at76_is_505a(fwe->board_type)) {
3467 + at76_dbg(DBG_DEVSTART, "200 ms delay for 505a");
3468 + schedule_timeout_interruptible(HZ / 5 + 1);
3469 + }
3470 +
3471 +exit:
3472 + kfree(block);
3473 + if (ret < 0)
3474 + dev_printk(KERN_ERR, &udev->dev,
3475 + "downloading external firmware failed: %d\n", ret);
3476 + return ret;
3477 +}
3478 +
3479 +/* Download internal firmware */
3480 +static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
3481 +{
3482 + int ret;
3483 + int need_remap = !at76_is_505a(fwe->board_type);
3484 +
3485 + ret = at76_usbdfu_download(udev, fwe->intfw, fwe->intfw_size,
3486 + need_remap ? 0 : 2 * HZ);
3487 +
3488 + if (ret < 0) {
3489 + dev_printk(KERN_ERR, &udev->dev,
3490 + "downloading internal fw failed with %d\n", ret);
3491 + goto exit;
3492 + }
3493 +
3494 + at76_dbg(DBG_DEVSTART, "sending REMAP");
3495 +
3496 + /* no REMAP for 505A (see SF driver) */
3497 + if (need_remap) {
3498 + ret = at76_remap(udev);
3499 + if (ret < 0) {
3500 + dev_printk(KERN_ERR, &udev->dev,
3501 + "sending REMAP failed with %d\n", ret);
3502 + goto exit;
3503 + }
3504 + }
3505 +
3506 + at76_dbg(DBG_DEVSTART, "sleeping for 2 seconds");
3507 + schedule_timeout_interruptible(2 * HZ + 1);
3508 + usb_reset_device(udev);
3509 +
3510 +exit:
3511 + return ret;
3512 +}
3513 +
3514 +static int at76_match_essid(struct at76_priv *priv, struct bss_info *ptr)
3515 +{
3516 + /* common criteria for both modi */
3517 +
3518 + int ret = (priv->essid_size == 0 /* ANY ssid */ ||
3519 + (priv->essid_size == ptr->ssid_len &&
3520 + !memcmp(priv->essid, ptr->ssid, ptr->ssid_len)));
3521 + if (!ret)
3522 + at76_dbg(DBG_BSS_MATCH,
3523 + "%s bss table entry %p: essid didn't match",
3524 + priv->netdev->name, ptr);
3525 + return ret;
3526 +}
3527 +
3528 +static inline int at76_match_mode(struct at76_priv *priv, struct bss_info *ptr)
3529 +{
3530 + int ret;
3531 +
3532 + if (priv->iw_mode == IW_MODE_ADHOC)
3533 + ret = ptr->capa & WLAN_CAPABILITY_IBSS;
3534 + else
3535 + ret = ptr->capa & WLAN_CAPABILITY_ESS;
3536 + if (!ret)
3537 + at76_dbg(DBG_BSS_MATCH,
3538 + "%s bss table entry %p: mode didn't match",
3539 + priv->netdev->name, ptr);
3540 + return ret;
3541 +}
3542 +
3543 +static int at76_match_rates(struct at76_priv *priv, struct bss_info *ptr)
3544 +{
3545 + int i;
3546 +
3547 + for (i = 0; i < ptr->rates_len; i++) {
3548 + u8 rate = ptr->rates[i];
3549 +
3550 + if (!(rate & 0x80))
3551 + continue;
3552 +
3553 + /* this is a basic rate we have to support
3554 + (see IEEE802.11, ch. 7.3.2.2) */
3555 + if (rate != (0x80 | hw_rates[0])
3556 + && rate != (0x80 | hw_rates[1])
3557 + && rate != (0x80 | hw_rates[2])
3558 + && rate != (0x80 | hw_rates[3])) {
3559 + at76_dbg(DBG_BSS_MATCH,
3560 + "%s: bss table entry %p: basic rate %02x not "
3561 + "supported", priv->netdev->name, ptr, rate);
3562 + return 0;
3563 + }
3564 + }
3565 +
3566 + /* if we use short preamble, the bss must support it */
3567 + if (priv->preamble_type == PREAMBLE_TYPE_SHORT &&
3568 + !(ptr->capa & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
3569 + at76_dbg(DBG_BSS_MATCH,
3570 + "%s: %p does not support short preamble",
3571 + priv->netdev->name, ptr);
3572 + return 0;
3573 + } else
3574 + return 1;
3575 +}
3576 +
3577 +static inline int at76_match_wep(struct at76_priv *priv, struct bss_info *ptr)
3578 +{
3579 + if (!priv->wep_enabled && ptr->capa & WLAN_CAPABILITY_PRIVACY) {
3580 + /* we have disabled WEP, but the BSS signals privacy */
3581 + at76_dbg(DBG_BSS_MATCH,
3582 + "%s: bss table entry %p: requires encryption",
3583 + priv->netdev->name, ptr);
3584 + return 0;
3585 + }
3586 + /* otherwise if the BSS does not signal privacy it may well
3587 + accept encrypted packets from us ... */
3588 + return 1;
3589 +}
3590 +
3591 +static inline int at76_match_bssid(struct at76_priv *priv, struct bss_info *ptr)
3592 +{
3593 + if (!priv->wanted_bssid_valid ||
3594 + !compare_ether_addr(ptr->bssid, priv->wanted_bssid))
3595 + return 1;
3596 +
3597 + at76_dbg(DBG_BSS_MATCH,
3598 + "%s: requested bssid - %s does not match",
3599 + priv->netdev->name, mac2str(priv->wanted_bssid));
3600 + at76_dbg(DBG_BSS_MATCH,
3601 + " AP bssid - %s of bss table entry %p",
3602 + mac2str(ptr->bssid), ptr);
3603 + return 0;
3604 +}
3605 +
3606 +/**
3607 + * at76_match_bss - try to find a matching bss in priv->bss
3608 + *
3609 + * last - last bss tried
3610 + *
3611 + * last == NULL signals a new round starting with priv->bss_list.next
3612 + * this function must be called inside an acquired priv->bss_list_spinlock
3613 + * otherwise the timeout on bss may remove the newly chosen entry
3614 + */
3615 +static struct bss_info *at76_match_bss(struct at76_priv *priv,
3616 + struct bss_info *last)
3617 +{
3618 + struct bss_info *ptr = NULL;
3619 + struct list_head *curr;
3620 +
3621 + curr = last ? last->list.next : priv->bss_list.next;
3622 + while (curr != &priv->bss_list) {
3623 + ptr = list_entry(curr, struct bss_info, list);
3624 + if (at76_match_essid(priv, ptr) && at76_match_mode(priv, ptr)
3625 + && at76_match_wep(priv, ptr) && at76_match_rates(priv, ptr)
3626 + && at76_match_bssid(priv, ptr))
3627 + break;
3628 + curr = curr->next;
3629 + }
3630 +
3631 + if (curr == &priv->bss_list)
3632 + ptr = NULL;
3633 + /* otherwise ptr points to the struct bss_info we have chosen */
3634 +
3635 + at76_dbg(DBG_BSS_TABLE, "%s %s: returned %p", priv->netdev->name,
3636 + __func__, ptr);
3637 + return ptr;
3638 +}
3639 +
3640 +/* Start joining a matching BSS, or create own IBSS */
3641 +static void at76_work_join(struct work_struct *work)
3642 +{
3643 + struct at76_priv *priv = container_of(work, struct at76_priv,
3644 + work_join);
3645 + int ret;
3646 + unsigned long flags;
3647 +
3648 + mutex_lock(&priv->mtx);
3649 +
3650 + WARN_ON(priv->mac_state != MAC_JOINING);
3651 + if (priv->mac_state != MAC_JOINING)
3652 + goto exit;
3653 +
3654 + /* secure the access to priv->curr_bss ! */
3655 + spin_lock_irqsave(&priv->bss_list_spinlock, flags);
3656 + priv->curr_bss = at76_match_bss(priv, priv->curr_bss);
3657 + spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
3658 +
3659 + if (!priv->curr_bss) {
3660 + /* here we haven't found a matching (i)bss ... */
3661 + if (priv->iw_mode == IW_MODE_ADHOC) {
3662 + at76_set_mac_state(priv, MAC_OWN_IBSS);
3663 + at76_start_ibss(priv);
3664 + goto exit;
3665 + }
3666 + /* haven't found a matching BSS in infra mode - try again */
3667 + at76_set_mac_state(priv, MAC_SCANNING);
3668 + schedule_work(&priv->work_start_scan);
3669 + goto exit;
3670 + }
3671 +
3672 + ret = at76_join_bss(priv, priv->curr_bss);
3673 + if (ret < 0) {
3674 + printk(KERN_ERR "%s: join_bss failed with %d\n",
3675 + priv->netdev->name, ret);
3676 + goto exit;
3677 + }
3678 +
3679 + ret = at76_wait_completion(priv, CMD_JOIN);
3680 + if (ret != CMD_STATUS_COMPLETE) {
3681 + if (ret != CMD_STATUS_TIME_OUT)
3682 + printk(KERN_ERR "%s: join_bss completed with %d\n",
3683 + priv->netdev->name, ret);
3684 + else
3685 + printk(KERN_INFO "%s: join_bss ssid %s timed out\n",
3686 + priv->netdev->name,
3687 + mac2str(priv->curr_bss->bssid));
3688 +
3689 + /* retry next BSS immediately */
3690 + schedule_work(&priv->work_join);
3691 + goto exit;
3692 + }
3693 +
3694 + /* here we have joined the (I)BSS */
3695 + if (priv->iw_mode == IW_MODE_ADHOC) {
3696 + struct bss_info *bptr = priv->curr_bss;
3697 + at76_set_mac_state(priv, MAC_CONNECTED);
3698 + /* get ESSID, BSSID and channel for priv->curr_bss */
3699 + priv->essid_size = bptr->ssid_len;
3700 + memcpy(priv->essid, bptr->ssid, bptr->ssid_len);
3701 + memcpy(priv->bssid, bptr->bssid, ETH_ALEN);
3702 + priv->channel = bptr->channel;
3703 + at76_iwevent_bss_connect(priv->netdev, bptr->bssid);
3704 + netif_carrier_on(priv->netdev);
3705 + netif_start_queue(priv->netdev);
3706 + /* just to be sure */
3707 + cancel_delayed_work(&priv->dwork_get_scan);
3708 + cancel_delayed_work(&priv->dwork_auth);
3709 + cancel_delayed_work(&priv->dwork_assoc);
3710 + } else {
3711 + /* send auth req */
3712 + priv->retries = AUTH_RETRIES;
3713 + at76_set_mac_state(priv, MAC_AUTH);
3714 + at76_auth_req(priv, priv->curr_bss, 1, NULL);
3715 + at76_dbg(DBG_MGMT_TIMER,
3716 + "%s:%d: starting mgmt_timer + HZ", __func__, __LINE__);
3717 + schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
3718 + }
3719 +
3720 +exit:
3721 + mutex_unlock(&priv->mtx);
3722 +}
3723 +
3724 +/* Reap scan results */
3725 +static void at76_dwork_get_scan(struct work_struct *work)
3726 +{
3727 + int status;
3728 + int ret;
3729 + struct at76_priv *priv = container_of(work, struct at76_priv,
3730 + dwork_get_scan.work);
3731 +
3732 + mutex_lock(&priv->mtx);
3733 + WARN_ON(priv->mac_state != MAC_SCANNING);
3734 + if (priv->mac_state != MAC_SCANNING)
3735 + goto exit;
3736 +
3737 + status = at76_get_cmd_status(priv->udev, CMD_SCAN);
3738 + if (status < 0) {
3739 + printk(KERN_ERR "%s: %s: at76_get_cmd_status failed with %d\n",
3740 + priv->netdev->name, __func__, status);
3741 + status = CMD_STATUS_IN_PROGRESS;
3742 + /* INFO: Hope it was a one off error - if not, scanning
3743 + further down the line and stop this cycle */
3744 + }
3745 + at76_dbg(DBG_PROGRESS,
3746 + "%s %s: got cmd_status %d (state %s, need_any %d)",
3747 + priv->netdev->name, __func__, status,
3748 + mac_states[priv->mac_state], priv->scan_need_any);
3749 +
3750 + if (status != CMD_STATUS_COMPLETE) {
3751 + if ((status != CMD_STATUS_IN_PROGRESS) &&
3752 + (status != CMD_STATUS_IDLE))
3753 + printk(KERN_ERR "%s: %s: Bad scan status: %s\n",
3754 + priv->netdev->name, __func__,
3755 + at76_get_cmd_status_string(status));
3756 +
3757 + /* the first cmd status after scan start is always a IDLE ->
3758 + start the timer to poll again until COMPLETED */
3759 + at76_dbg(DBG_MGMT_TIMER,
3760 + "%s:%d: starting mgmt_timer for %d ticks",
3761 + __func__, __LINE__, SCAN_POLL_INTERVAL);
3762 + schedule_delayed_work(&priv->dwork_get_scan,
3763 + SCAN_POLL_INTERVAL);
3764 + goto exit;
3765 + }
3766 +
3767 + if (at76_debug & DBG_BSS_TABLE)
3768 + at76_dump_bss_table(priv);
3769 +
3770 + if (priv->scan_need_any) {
3771 + ret = at76_start_scan(priv, 0);
3772 + if (ret < 0)
3773 + printk(KERN_ERR
3774 + "%s: %s: start_scan (ANY) failed with %d\n",
3775 + priv->netdev->name, __func__, ret);
3776 + at76_dbg(DBG_MGMT_TIMER,
3777 + "%s:%d: starting mgmt_timer for %d ticks", __func__,
3778 + __LINE__, SCAN_POLL_INTERVAL);
3779 + schedule_delayed_work(&priv->dwork_get_scan,
3780 + SCAN_POLL_INTERVAL);
3781 + priv->scan_need_any = 0;
3782 + } else {
3783 + priv->scan_state = SCAN_COMPLETED;
3784 + /* report the end of scan to user space */
3785 + at76_iwevent_scan_complete(priv->netdev);
3786 + at76_set_mac_state(priv, MAC_JOINING);
3787 + schedule_work(&priv->work_join);
3788 + }
3789 +
3790 +exit:
3791 + mutex_unlock(&priv->mtx);
3792 +}
3793 +
3794 +/* Handle loss of beacons from the AP */
3795 +static void at76_dwork_beacon(struct work_struct *work)
3796 +{
3797 + struct at76_priv *priv = container_of(work, struct at76_priv,
3798 + dwork_beacon.work);
3799 +
3800 + mutex_lock(&priv->mtx);
3801 + if (priv->mac_state != MAC_CONNECTED || priv->iw_mode != IW_MODE_INFRA)
3802 + goto exit;
3803 +
3804 + /* We haven't received any beacons from out AP for BEACON_TIMEOUT */
3805 + printk(KERN_INFO "%s: lost beacon bssid %s\n",
3806 + priv->netdev->name, mac2str(priv->curr_bss->bssid));
3807 +
3808 + netif_carrier_off(priv->netdev);
3809 + netif_stop_queue(priv->netdev);
3810 + at76_iwevent_bss_disconnect(priv->netdev);
3811 + at76_set_mac_state(priv, MAC_SCANNING);
3812 + schedule_work(&priv->work_start_scan);
3813 +
3814 +exit:
3815 + mutex_unlock(&priv->mtx);
3816 +}
3817 +
3818 +/* Handle authentication response timeout */
3819 +static void at76_dwork_auth(struct work_struct *work)
3820 +{
3821 + struct at76_priv *priv = container_of(work, struct at76_priv,
3822 + dwork_auth.work);
3823 +
3824 + mutex_lock(&priv->mtx);
3825 + WARN_ON(priv->mac_state != MAC_AUTH);
3826 + if (priv->mac_state != MAC_AUTH)
3827 + goto exit;
3828 +
3829 + at76_dbg(DBG_PROGRESS, "%s: authentication response timeout",
3830 + priv->netdev->name);
3831 +
3832 + if (priv->retries-- >= 0) {
3833 + at76_auth_req(priv, priv->curr_bss, 1, NULL);
3834 + at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ",
3835 + __func__, __LINE__);
3836 + schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
3837 + } else {
3838 + /* try to get next matching BSS */
3839 + at76_set_mac_state(priv, MAC_JOINING);
3840 + schedule_work(&priv->work_join);
3841 + }
3842 +
3843 +exit:
3844 + mutex_unlock(&priv->mtx);
3845 +}
3846 +
3847 +/* Handle association response timeout */
3848 +static void at76_dwork_assoc(struct work_struct *work)
3849 +{
3850 + struct at76_priv *priv = container_of(work, struct at76_priv,
3851 + dwork_assoc.work);
3852 +
3853 + mutex_lock(&priv->mtx);
3854 + WARN_ON(priv->mac_state != MAC_ASSOC);
3855 + if (priv->mac_state != MAC_ASSOC)
3856 + goto exit;
3857 +
3858 + at76_dbg(DBG_PROGRESS, "%s: association response timeout",
3859 + priv->netdev->name);
3860 +
3861 + if (priv->retries-- >= 0) {
3862 + at76_assoc_req(priv, priv->curr_bss);
3863 + at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ",
3864 + __func__, __LINE__);
3865 + schedule_delayed_work(&priv->dwork_assoc, ASSOC_TIMEOUT);
3866 + } else {
3867 + /* try to get next matching BSS */
3868 + at76_set_mac_state(priv, MAC_JOINING);
3869 + schedule_work(&priv->work_join);
3870 + }
3871 +
3872 +exit:
3873 + mutex_unlock(&priv->mtx);
3874 +}
3875 +
3876 +/* Read new bssid in ad-hoc mode */
3877 +static void at76_work_new_bss(struct work_struct *work)
3878 +{
3879 + struct at76_priv *priv = container_of(work, struct at76_priv,
3880 + work_new_bss);
3881 + int ret;
3882 + struct mib_mac_mgmt mac_mgmt;
3883 +
3884 + mutex_lock(&priv->mtx);
3885 +
3886 + ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, &mac_mgmt,
3887 + sizeof(struct mib_mac_mgmt));
3888 + if (ret < 0) {
3889 + printk(KERN_ERR "%s: at76_get_mib failed: %d\n",
3890 + priv->netdev->name, ret);
3891 + goto exit;
3892 + }
3893 +
3894 + at76_dbg(DBG_PROGRESS, "ibss_change = 0x%2x", mac_mgmt.ibss_change);
3895 + memcpy(priv->bssid, mac_mgmt.current_bssid, ETH_ALEN);
3896 + at76_dbg(DBG_PROGRESS, "using BSSID %s", mac2str(priv->bssid));
3897 +
3898 + at76_iwevent_bss_connect(priv->netdev, priv->bssid);
3899 +
3900 + priv->mib_buf.type = MIB_MAC_MGMT;
3901 + priv->mib_buf.size = 1;
3902 + priv->mib_buf.index = offsetof(struct mib_mac_mgmt, ibss_change);
3903 + priv->mib_buf.data.byte = 0;
3904 +
3905 + ret = at76_set_mib(priv, &priv->mib_buf);
3906 + if (ret < 0)
3907 + printk(KERN_ERR "%s: set_mib (ibss change ok) failed: %d\n",
3908 + priv->netdev->name, ret);
3909 +
3910 +exit:
3911 + mutex_unlock(&priv->mtx);
3912 +}
3913 +
3914 +static int at76_startup_device(struct at76_priv *priv)
3915 +{
3916 + struct at76_card_config *ccfg = &priv->card_config;
3917 + int ret;
3918 +
3919 + at76_dbg(DBG_PARAMS,
3920 + "%s param: ssid %.*s (%s) mode %s ch %d wep %s key %d "
3921 + "keylen %d", priv->netdev->name, priv->essid_size, priv->essid,
3922 + hex2str(priv->essid, IW_ESSID_MAX_SIZE),
3923 + priv->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra",
3924 + priv->channel, priv->wep_enabled ? "enabled" : "disabled",
3925 + priv->wep_key_id, priv->wep_keys_len[priv->wep_key_id]);
3926 + at76_dbg(DBG_PARAMS,
3927 + "%s param: preamble %s rts %d retry %d frag %d "
3928 + "txrate %s auth_mode %d", priv->netdev->name,
3929 + preambles[priv->preamble_type], priv->rts_threshold,
3930 + priv->short_retry_limit, priv->frag_threshold,
3931 + priv->txrate == TX_RATE_1MBIT ? "1MBit" : priv->txrate ==
3932 + TX_RATE_2MBIT ? "2MBit" : priv->txrate ==
3933 + TX_RATE_5_5MBIT ? "5.5MBit" : priv->txrate ==
3934 + TX_RATE_11MBIT ? "11MBit" : priv->txrate ==
3935 + TX_RATE_AUTO ? "auto" : "<invalid>", priv->auth_mode);
3936 + at76_dbg(DBG_PARAMS,
3937 + "%s param: pm_mode %d pm_period %d auth_mode %s "
3938 + "scan_times %d %d scan_mode %s",
3939 + priv->netdev->name, priv->pm_mode, priv->pm_period,
3940 + priv->auth_mode == WLAN_AUTH_OPEN ? "open" : "shared_secret",
3941 + priv->scan_min_time, priv->scan_max_time,
3942 + priv->scan_mode == SCAN_TYPE_ACTIVE ? "active" : "passive");
3943 +
3944 + memset(ccfg, 0, sizeof(struct at76_card_config));
3945 + ccfg->promiscuous_mode = 0;
3946 + ccfg->short_retry_limit = priv->short_retry_limit;
3947 +
3948 + if (priv->wep_enabled) {
3949 + if (priv->wep_keys_len[priv->wep_key_id] > WEP_SMALL_KEY_LEN)
3950 + ccfg->encryption_type = 2;
3951 + else
3952 + ccfg->encryption_type = 1;
3953 +
3954 + /* jal: always exclude unencrypted if WEP is active */
3955 + ccfg->exclude_unencrypted = 1;
3956 + } else {
3957 + ccfg->exclude_unencrypted = 0;
3958 + ccfg->encryption_type = 0;
3959 + }
3960 +
3961 + ccfg->rts_threshold = cpu_to_le16(priv->rts_threshold);
3962 + ccfg->fragmentation_threshold = cpu_to_le16(priv->frag_threshold);
3963 +
3964 + memcpy(ccfg->basic_rate_set, hw_rates, 4);
3965 + /* jal: really needed, we do a set_mib for autorate later ??? */
3966 + ccfg->auto_rate_fallback = (priv->txrate == TX_RATE_AUTO ? 1 : 0);
3967 + ccfg->channel = priv->channel;
3968 + ccfg->privacy_invoked = priv->wep_enabled;
3969 + memcpy(ccfg->current_ssid, priv->essid, IW_ESSID_MAX_SIZE);
3970 + ccfg->ssid_len = priv->essid_size;
3971 +
3972 + ccfg->wep_default_key_id = priv->wep_key_id;
3973 + memcpy(ccfg->wep_default_key_value, priv->wep_keys, 4 * WEP_KEY_LEN);
3974 +
3975 + ccfg->short_preamble = priv->preamble_type;
3976 + ccfg->beacon_period = cpu_to_le16(priv->beacon_period);
3977 +
3978 + ret = at76_set_card_command(priv->udev, CMD_STARTUP, &priv->card_config,
3979 + sizeof(struct at76_card_config));
3980 + if (ret < 0) {
3981 + printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
3982 + priv->netdev->name, ret);
3983 + return ret;
3984 + }
3985 +
3986 + at76_wait_completion(priv, CMD_STARTUP);
3987 +
3988 + /* remove BSSID from previous run */
3989 + memset(priv->bssid, 0, ETH_ALEN);
3990 +
3991 + if (at76_set_radio(priv, 1) == 1)
3992 + at76_wait_completion(priv, CMD_RADIO_ON);
3993 +
3994 + ret = at76_set_preamble(priv, priv->preamble_type);
3995 + if (ret < 0)
3996 + return ret;
3997 +
3998 + ret = at76_set_frag(priv, priv->frag_threshold);
3999 + if (ret < 0)
4000 + return ret;
4001 +
4002 + ret = at76_set_rts(priv, priv->rts_threshold);
4003 + if (ret < 0)
4004 + return ret;
4005 +
4006 + ret = at76_set_autorate_fallback(priv,
4007 + priv->txrate == TX_RATE_AUTO ? 1 : 0);
4008 + if (ret < 0)
4009 + return ret;
4010 +
4011 + ret = at76_set_pm_mode(priv);
4012 + if (ret < 0)
4013 + return ret;
4014 +
4015 + if (at76_debug & DBG_MIB) {
4016 + at76_dump_mib_mac(priv);
4017 + at76_dump_mib_mac_addr(priv);
4018 + at76_dump_mib_mac_mgmt(priv);
4019 + at76_dump_mib_mac_wep(priv);
4020 + at76_dump_mib_mdomain(priv);
4021 + at76_dump_mib_phy(priv);
4022 + at76_dump_mib_local(priv);
4023 + }
4024 +
4025 + return 0;
4026 +}
4027 +
4028 +/* Restart the interface */
4029 +static void at76_dwork_restart(struct work_struct *work)
4030 +{
4031 + struct at76_priv *priv = container_of(work, struct at76_priv,
4032 + dwork_restart.work);
4033 +
4034 + mutex_lock(&priv->mtx);
4035 +
4036 + netif_carrier_off(priv->netdev); /* stop netdev watchdog */
4037 + netif_stop_queue(priv->netdev); /* stop tx data packets */
4038 +
4039 + at76_startup_device(priv);
4040 +
4041 + if (priv->iw_mode != IW_MODE_MONITOR) {
4042 + priv->netdev->type = ARPHRD_ETHER;
4043 + at76_set_mac_state(priv, MAC_SCANNING);
4044 + schedule_work(&priv->work_start_scan);
4045 + } else {
4046 + priv->netdev->type = ARPHRD_IEEE80211_RADIOTAP;
4047 + at76_start_monitor(priv);
4048 + }
4049 +
4050 + mutex_unlock(&priv->mtx);
4051 +}
4052 +
4053 +/* Initiate scanning */
4054 +static void at76_work_start_scan(struct work_struct *work)
4055 +{
4056 + struct at76_priv *priv = container_of(work, struct at76_priv,
4057 + work_start_scan);
4058 + int ret;
4059 +
4060 + mutex_lock(&priv->mtx);
4061 +
4062 + WARN_ON(priv->mac_state != MAC_SCANNING);
4063 + if (priv->mac_state != MAC_SCANNING)
4064 + goto exit;
4065 +
4066 + /* only clear the bss list when a scan is actively initiated,
4067 + * otherwise simply rely on at76_bss_list_timeout */
4068 + if (priv->scan_state == SCAN_IN_PROGRESS) {
4069 + at76_free_bss_list(priv);
4070 + priv->scan_need_any = 1;
4071 + } else
4072 + priv->scan_need_any = 0;
4073 +
4074 + ret = at76_start_scan(priv, 1);
4075 +
4076 + if (ret < 0)
4077 + printk(KERN_ERR "%s: %s: start_scan failed with %d\n",
4078 + priv->netdev->name, __func__, ret);
4079 + else {
4080 + at76_dbg(DBG_MGMT_TIMER,
4081 + "%s:%d: starting mgmt_timer for %d ticks",
4082 + __func__, __LINE__, SCAN_POLL_INTERVAL);
4083 + schedule_delayed_work(&priv->dwork_get_scan,
4084 + SCAN_POLL_INTERVAL);
4085 + }
4086 +
4087 +exit:
4088 + mutex_unlock(&priv->mtx);
4089 +}
4090 +
4091 +/* Enable or disable promiscuous mode */
4092 +static void at76_work_set_promisc(struct work_struct *work)
4093 +{
4094 + struct at76_priv *priv = container_of(work, struct at76_priv,
4095 + work_set_promisc);
4096 + int ret = 0;
4097 +
4098 + mutex_lock(&priv->mtx);
4099 +
4100 + priv->mib_buf.type = MIB_LOCAL;
4101 + priv->mib_buf.size = 1;
4102 + priv->mib_buf.index = offsetof(struct mib_local, promiscuous_mode);
4103 + priv->mib_buf.data.byte = priv->promisc ? 1 : 0;
4104 +
4105 + ret = at76_set_mib(priv, &priv->mib_buf);
4106 + if (ret < 0)
4107 + printk(KERN_ERR "%s: set_mib (promiscuous_mode) failed: %d\n",
4108 + priv->netdev->name, ret);
4109 +
4110 + mutex_unlock(&priv->mtx);
4111 +}
4112 +
4113 +/* Submit Rx urb back to the device */
4114 +static void at76_work_submit_rx(struct work_struct *work)
4115 +{
4116 + struct at76_priv *priv = container_of(work, struct at76_priv,
4117 + work_submit_rx);
4118 +
4119 + mutex_lock(&priv->mtx);
4120 + at76_submit_rx_urb(priv);
4121 + mutex_unlock(&priv->mtx);
4122 +}
4123 +
4124 +/* We got an association response */
4125 +static void at76_rx_mgmt_assoc(struct at76_priv *priv,
4126 + struct at76_rx_buffer *buf)
4127 +{
4128 + struct ieee80211_assoc_response *resp =
4129 + (struct ieee80211_assoc_response *)buf->packet;
4130 + u16 assoc_id = le16_to_cpu(resp->aid);
4131 + u16 status = le16_to_cpu(resp->status);
4132 +
4133 + at76_dbg(DBG_RX_MGMT, "%s: rx AssocResp bssid %s capa 0x%04x status "
4134 + "0x%04x assoc_id 0x%04x rates %s", priv->netdev->name,
4135 + mac2str(resp->header.addr3), le16_to_cpu(resp->capability),
4136 + status, assoc_id, hex2str(resp->info_element->data,
4137 + resp->info_element->len));
4138 +
4139 + if (priv->mac_state != MAC_ASSOC) {
4140 + printk(KERN_INFO "%s: AssocResp in state %s ignored\n",
4141 + priv->netdev->name, mac_states[priv->mac_state]);
4142 + return;
4143 + }
4144 +
4145 + BUG_ON(!priv->curr_bss);
4146 +
4147 + cancel_delayed_work(&priv->dwork_assoc);
4148 + if (status == WLAN_STATUS_SUCCESS) {
4149 + struct bss_info *ptr = priv->curr_bss;
4150 + priv->assoc_id = assoc_id & 0x3fff;
4151 + /* update iwconfig params */
4152 + memcpy(priv->bssid, ptr->bssid, ETH_ALEN);
4153 + memcpy(priv->essid, ptr->ssid, ptr->ssid_len);
4154 + priv->essid_size = ptr->ssid_len;
4155 + priv->channel = ptr->channel;
4156 + schedule_work(&priv->work_assoc_done);
4157 + } else {
4158 + at76_set_mac_state(priv, MAC_JOINING);
4159 + schedule_work(&priv->work_join);
4160 + }
4161 +}
4162 +
4163 +/* Process disassociation request from the AP */
4164 +static void at76_rx_mgmt_disassoc(struct at76_priv *priv,
4165 + struct at76_rx_buffer *buf)
4166 +{
4167 + struct ieee80211_disassoc *resp =
4168 + (struct ieee80211_disassoc *)buf->packet;
4169 + struct ieee80211_hdr_3addr *mgmt = &resp->header;
4170 +
4171 + at76_dbg(DBG_RX_MGMT,
4172 + "%s: rx DisAssoc bssid %s reason 0x%04x destination %s",
4173 + priv->netdev->name, mac2str(mgmt->addr3),
4174 + le16_to_cpu(resp->reason), mac2str(mgmt->addr1));
4175 +
4176 + /* We are not connected, ignore */
4177 + if (priv->mac_state == MAC_SCANNING || priv->mac_state == MAC_INIT
4178 + || !priv->curr_bss)
4179 + return;
4180 +
4181 + /* Not our BSSID, ignore */
4182 + if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid))
4183 + return;
4184 +
4185 + /* Not for our STA and not broadcast, ignore */
4186 + if (compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)
4187 + && !is_broadcast_ether_addr(mgmt->addr1))
4188 + return;
4189 +
4190 + if (priv->mac_state != MAC_ASSOC && priv->mac_state != MAC_CONNECTED
4191 + && priv->mac_state != MAC_JOINING) {
4192 + printk(KERN_INFO "%s: DisAssoc in state %s ignored\n",
4193 + priv->netdev->name, mac_states[priv->mac_state]);
4194 + return;
4195 + }
4196 +
4197 + if (priv->mac_state == MAC_CONNECTED) {
4198 + netif_carrier_off(priv->netdev);
4199 + netif_stop_queue(priv->netdev);
4200 + at76_iwevent_bss_disconnect(priv->netdev);
4201 + }
4202 + cancel_delayed_work(&priv->dwork_get_scan);
4203 + cancel_delayed_work(&priv->dwork_beacon);
4204 + cancel_delayed_work(&priv->dwork_auth);
4205 + cancel_delayed_work(&priv->dwork_assoc);
4206 + at76_set_mac_state(priv, MAC_JOINING);
4207 + schedule_work(&priv->work_join);
4208 +}
4209 +
4210 +static void at76_rx_mgmt_auth(struct at76_priv *priv,
4211 + struct at76_rx_buffer *buf)
4212 +{
4213 + struct ieee80211_auth *resp = (struct ieee80211_auth *)buf->packet;
4214 + struct ieee80211_hdr_3addr *mgmt = &resp->header;
4215 + int seq_nr = le16_to_cpu(resp->transaction);
4216 + int alg = le16_to_cpu(resp->algorithm);
4217 + int status = le16_to_cpu(resp->status);
4218 +
4219 + at76_dbg(DBG_RX_MGMT,
4220 + "%s: rx AuthFrame bssid %s alg %d seq_nr %d status %d "
4221 + "destination %s", priv->netdev->name, mac2str(mgmt->addr3),
4222 + alg, seq_nr, status, mac2str(mgmt->addr1));
4223 +
4224 + if (alg == WLAN_AUTH_SHARED_KEY && seq_nr == 2)
4225 + at76_dbg(DBG_RX_MGMT, "%s: AuthFrame challenge %s ...",
4226 + priv->netdev->name, hex2str(resp->info_element, 18));
4227 +
4228 + if (priv->mac_state != MAC_AUTH) {
4229 + printk(KERN_INFO "%s: ignored AuthFrame in state %s\n",
4230 + priv->netdev->name, mac_states[priv->mac_state]);
4231 + return;
4232 + }
4233 + if (priv->auth_mode != alg) {
4234 + printk(KERN_INFO "%s: ignored AuthFrame for alg %d\n",
4235 + priv->netdev->name, alg);
4236 + return;
4237 + }
4238 +
4239 + BUG_ON(!priv->curr_bss);
4240 +
4241 + /* Not our BSSID or not for our STA, ignore */
4242 + if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid)
4243 + || compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1))
4244 + return;
4245 +
4246 + cancel_delayed_work(&priv->dwork_auth);
4247 + if (status != WLAN_STATUS_SUCCESS) {
4248 + /* try to join next bss */
4249 + at76_set_mac_state(priv, MAC_JOINING);
4250 + schedule_work(&priv->work_join);
4251 + return;
4252 + }
4253 +
4254 + if (priv->auth_mode == WLAN_AUTH_OPEN || seq_nr == 4) {
4255 + priv->retries = ASSOC_RETRIES;
4256 + at76_set_mac_state(priv, MAC_ASSOC);
4257 + at76_assoc_req(priv, priv->curr_bss);
4258 + at76_dbg(DBG_MGMT_TIMER,
4259 + "%s:%d: starting mgmt_timer + HZ", __func__, __LINE__);
4260 + schedule_delayed_work(&priv->dwork_assoc, ASSOC_TIMEOUT);
4261 + return;
4262 + }
4263 +
4264 + WARN_ON(seq_nr != 2);
4265 + at76_auth_req(priv, priv->curr_bss, seq_nr + 1, resp->info_element);
4266 + at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", __func__,
4267 + __LINE__);
4268 + schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
4269 +}
4270 +
4271 +static void at76_rx_mgmt_deauth(struct at76_priv *priv,
4272 + struct at76_rx_buffer *buf)
4273 +{
4274 + struct ieee80211_disassoc *resp =
4275 + (struct ieee80211_disassoc *)buf->packet;
4276 + struct ieee80211_hdr_3addr *mgmt = &resp->header;
4277 +
4278 + at76_dbg(DBG_RX_MGMT | DBG_PROGRESS,
4279 + "%s: rx DeAuth bssid %s reason 0x%04x destination %s",
4280 + priv->netdev->name, mac2str(mgmt->addr3),
4281 + le16_to_cpu(resp->reason), mac2str(mgmt->addr1));
4282 +
4283 + if (priv->mac_state != MAC_AUTH && priv->mac_state != MAC_ASSOC
4284 + && priv->mac_state != MAC_CONNECTED) {
4285 + printk(KERN_INFO "%s: DeAuth in state %s ignored\n",
4286 + priv->netdev->name, mac_states[priv->mac_state]);
4287 + return;
4288 + }
4289 +
4290 + BUG_ON(!priv->curr_bss);
4291 +
4292 + /* Not our BSSID, ignore */
4293 + if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid))
4294 + return;
4295 +
4296 + /* Not for our STA and not broadcast, ignore */
4297 + if (compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)
4298 + && !is_broadcast_ether_addr(mgmt->addr1))
4299 + return;
4300 +
4301 + if (priv->mac_state == MAC_CONNECTED)
4302 + at76_iwevent_bss_disconnect(priv->netdev);
4303 +
4304 + at76_set_mac_state(priv, MAC_JOINING);
4305 + schedule_work(&priv->work_join);
4306 + cancel_delayed_work(&priv->dwork_get_scan);
4307 + cancel_delayed_work(&priv->dwork_beacon);
4308 + cancel_delayed_work(&priv->dwork_auth);
4309 + cancel_delayed_work(&priv->dwork_assoc);
4310 +}
4311 +
4312 +static void at76_rx_mgmt_beacon(struct at76_priv *priv,
4313 + struct at76_rx_buffer *buf)
4314 +{
4315 + int varpar_len;
4316 + /* beacon content */
4317 + struct ieee80211_beacon *bdata = (struct ieee80211_beacon *)buf->packet;
4318 + struct ieee80211_hdr_3addr *mgmt = &bdata->header;
4319 +
4320 + struct list_head *lptr;
4321 + struct bss_info *match; /* entry matching addr3 with its bssid */
4322 + int new_entry = 0;
4323 + int len;
4324 + struct ieee80211_info_element *ie;
4325 + int have_ssid = 0;
4326 + int have_rates = 0;
4327 + int have_channel = 0;
4328 + int keep_going = 1;
4329 + unsigned long flags;
4330 +
4331 + spin_lock_irqsave(&priv->bss_list_spinlock, flags);
4332 + if (priv->mac_state == MAC_CONNECTED) {
4333 + /* in state MAC_CONNECTED we use the mgmt_timer to control
4334 + the beacon of the BSS */
4335 + BUG_ON(!priv->curr_bss);
4336 +
4337 + if (!compare_ether_addr(priv->curr_bss->bssid, mgmt->addr3)) {
4338 + /* We got our AP's beacon, defer the timeout handler.
4339 + Kill pending work first, as schedule_delayed_work()
4340 + won't do it. */
4341 + cancel_delayed_work(&priv->dwork_beacon);
4342 + schedule_delayed_work(&priv->dwork_beacon,
4343 + BEACON_TIMEOUT);
4344 + priv->curr_bss->rssi = buf->rssi;
4345 + priv->beacons_received++;
4346 + goto exit;
4347 + }
4348 + }
4349 +
4350 + /* look if we have this BSS already in the list */
4351 + match = NULL;
4352 +
4353 + if (!list_empty(&priv->bss_list)) {
4354 + list_for_each(lptr, &priv->bss_list) {
4355 + struct bss_info *bss_ptr =
4356 + list_entry(lptr, struct bss_info, list);
4357 + if (!compare_ether_addr(bss_ptr->bssid, mgmt->addr3)) {
4358 + match = bss_ptr;
4359 + break;
4360 + }
4361 + }
4362 + }
4363 +
4364 + if (!match) {
4365 + /* BSS not in the list - append it */
4366 + match = kzalloc(sizeof(struct bss_info), GFP_ATOMIC);
4367 + if (!match) {
4368 + at76_dbg(DBG_BSS_TABLE,
4369 + "%s: cannot kmalloc new bss info (%zd byte)",
4370 + priv->netdev->name, sizeof(struct bss_info));
4371 + goto exit;
4372 + }
4373 + new_entry = 1;
4374 + list_add_tail(&match->list, &priv->bss_list);
4375 + }
4376 +
4377 + match->capa = le16_to_cpu(bdata->capability);
4378 + match->beacon_interval = le16_to_cpu(bdata->beacon_interval);
4379 + match->rssi = buf->rssi;
4380 + match->link_qual = buf->link_quality;
4381 + match->noise_level = buf->noise_level;
4382 + memcpy(match->bssid, mgmt->addr3, ETH_ALEN);
4383 + at76_dbg(DBG_RX_BEACON, "%s: bssid %s", priv->netdev->name,
4384 + mac2str(match->bssid));
4385 +
4386 + ie = bdata->info_element;
4387 +
4388 + /* length of var length beacon parameters */
4389 + varpar_len = min_t(int, le16_to_cpu(buf->wlength) -
4390 + sizeof(struct ieee80211_beacon),
4391 + BEACON_MAX_DATA_LENGTH);
4392 +
4393 + /* This routine steps through the bdata->data array to get
4394 + * some useful information about the access point.
4395 + * Currently, this implementation supports receipt of: SSID,
4396 + * supported transfer rates and channel, in any order, with some
4397 + * tolerance for intermittent unknown codes (although this
4398 + * functionality may not be necessary as the useful information will
4399 + * usually arrive in consecutively, but there have been some
4400 + * reports of some of the useful information fields arriving in a
4401 + * different order).
4402 + * It does not support any more IE types although MFIE_TYPE_TIM may
4403 + * be supported (on my AP at least).
4404 + * The bdata->data array is about 1500 bytes long but only ~36 of those
4405 + * bytes are useful, hence the have_ssid etc optimizations. */
4406 +
4407 + while (keep_going &&
4408 + ((&ie->data[ie->len] - (u8 *)bdata->info_element) <=
4409 + varpar_len)) {
4410 +
4411 + switch (ie->id) {
4412 +
4413 + case MFIE_TYPE_SSID:
4414 + if (have_ssid)
4415 + break;
4416 +
4417 + len = min_t(int, IW_ESSID_MAX_SIZE, ie->len);
4418 +
4419 + /* we copy only if this is a new entry,
4420 + or the incoming SSID is not a hidden SSID. This
4421 + will protect us from overwriting a real SSID read
4422 + in a ProbeResponse with a hidden one from a
4423 + following beacon. */
4424 + if (!new_entry && at76_is_hidden_ssid(ie->data, len)) {
4425 + have_ssid = 1;
4426 + break;
4427 + }
4428 +
4429 + match->ssid_len = len;
4430 + memcpy(match->ssid, ie->data, len);
4431 + at76_dbg(DBG_RX_BEACON, "%s: SSID - %.*s",
4432 + priv->netdev->name, len, match->ssid);
4433 + have_ssid = 1;
4434 + break;
4435 +
4436 + case MFIE_TYPE_RATES:
4437 + if (have_rates)
4438 + break;
4439 +
4440 + match->rates_len =
4441 + min_t(int, sizeof(match->rates), ie->len);
4442 + memcpy(match->rates, ie->data, match->rates_len);
4443 + have_rates = 1;
4444 + at76_dbg(DBG_RX_BEACON, "%s: SUPPORTED RATES %s",
4445 + priv->netdev->name,
4446 + hex2str(ie->data, ie->len));
4447 + break;
4448 +
4449 + case MFIE_TYPE_DS_SET:
4450 + if (have_channel)
4451 + break;
4452 +
4453 + match->channel = ie->data[0];
4454 + have_channel = 1;
4455 + at76_dbg(DBG_RX_BEACON, "%s: CHANNEL - %d",
4456 + priv->netdev->name, match->channel);
4457 + break;
4458 +
4459 + case MFIE_TYPE_CF_SET:
4460 + case MFIE_TYPE_TIM:
4461 + case MFIE_TYPE_IBSS_SET:
4462 + default:
4463 + at76_dbg(DBG_RX_BEACON, "%s: beacon IE id %d len %d %s",
4464 + priv->netdev->name, ie->id, ie->len,
4465 + hex2str(ie->data, ie->len));
4466 + break;
4467 + }
4468 +
4469 + /* advance to the next informational element */
4470 + next_ie(&ie);
4471 +
4472 + /* Optimization: after all, the bdata->data array is
4473 + * varpar_len bytes long, whereas we get all of the useful
4474 + * information after only ~36 bytes, this saves us a lot of
4475 + * time (and trouble as the remaining portion of the array
4476 + * could be full of junk)
4477 + * Comment this out if you want to see what other information
4478 + * comes from the AP - although little of it may be useful */
4479 + }
4480 +
4481 + at76_dbg(DBG_RX_BEACON, "%s: Finished processing beacon data",
4482 + priv->netdev->name);
4483 +
4484 + match->last_rx = jiffies; /* record last rx of beacon */
4485 +
4486 +exit:
4487 + spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
4488 +}
4489 +
4490 +/* Calculate the link level from a given rx_buffer */
4491 +static void at76_calc_level(struct at76_priv *priv, struct at76_rx_buffer *buf,
4492 + struct iw_quality *qual)
4493 +{
4494 + /* just a guess for now, might be different for other chips */
4495 + int max_rssi = 42;
4496 +
4497 + qual->level = (buf->rssi * 100 / max_rssi);
4498 + if (qual->level > 100)
4499 + qual->level = 100;
4500 + qual->updated |= IW_QUAL_LEVEL_UPDATED;
4501 +}
4502 +
4503 +/* Calculate the link quality from a given rx_buffer */
4504 +static void at76_calc_qual(struct at76_priv *priv, struct at76_rx_buffer *buf,
4505 + struct iw_quality *qual)
4506 +{
4507 + if (at76_is_intersil(priv->board_type))
4508 + qual->qual = buf->link_quality;
4509 + else {
4510 + unsigned long elapsed;
4511 +
4512 + /* Update qual at most once a second */
4513 + elapsed = jiffies - priv->beacons_last_qual;
4514 + if (elapsed < 1 * HZ)
4515 + return;
4516 +
4517 + qual->qual = qual->level * priv->beacons_received *
4518 + msecs_to_jiffies(priv->beacon_period) / elapsed;
4519 +
4520 + priv->beacons_last_qual = jiffies;
4521 + priv->beacons_received = 0;
4522 + }
4523 + qual->qual = (qual->qual > 100) ? 100 : qual->qual;
4524 + qual->updated |= IW_QUAL_QUAL_UPDATED;
4525 +}
4526 +
4527 +/* Calculate the noise quality from a given rx_buffer */
4528 +static void at76_calc_noise(struct at76_priv *priv, struct at76_rx_buffer *buf,
4529 + struct iw_quality *qual)
4530 +{
4531 + qual->noise = 0;
4532 + qual->updated |= IW_QUAL_NOISE_INVALID;
4533 +}
4534 +
4535 +static void at76_update_wstats(struct at76_priv *priv,
4536 + struct at76_rx_buffer *buf)
4537 +{
4538 + struct iw_quality *qual = &priv->wstats.qual;
4539 +
4540 + if (buf->rssi && priv->mac_state == MAC_CONNECTED) {
4541 + qual->updated = 0;
4542 + at76_calc_level(priv, buf, qual);
4543 + at76_calc_qual(priv, buf, qual);
4544 + at76_calc_noise(priv, buf, qual);
4545 + } else {
4546 + qual->qual = 0;
4547 + qual->level = 0;
4548 + qual->noise = 0;
4549 + qual->updated = IW_QUAL_ALL_INVALID;
4550 + }
4551 +}
4552 +
4553 +static void at76_rx_mgmt(struct at76_priv *priv, struct at76_rx_buffer *buf)
4554 +{
4555 + struct ieee80211_hdr_3addr *mgmt =
4556 + (struct ieee80211_hdr_3addr *)buf->packet;
4557 + u16 framectl = le16_to_cpu(mgmt->frame_ctl);
4558 +
4559 + /* update wstats */
4560 + if (priv->mac_state != MAC_INIT && priv->mac_state != MAC_SCANNING) {
4561 + /* jal: this is a dirty hack needed by Tim in ad-hoc mode */
4562 + /* Data packets always seem to have a 0 link level, so we
4563 + only read link quality info from management packets.
4564 + Atmel driver actually averages the present, and previous
4565 + values, we just present the raw value at the moment - TJS */
4566 + if (priv->iw_mode == IW_MODE_ADHOC
4567 + || (priv->curr_bss
4568 + && !compare_ether_addr(mgmt->addr3,
4569 + priv->curr_bss->bssid)))
4570 + at76_update_wstats(priv, buf);
4571 + }
4572 +
4573 + at76_dbg(DBG_RX_MGMT_CONTENT, "%s rx mgmt framectl 0x%x %s",
4574 + priv->netdev->name, framectl,
4575 + hex2str(mgmt, le16_to_cpu(buf->wlength)));
4576 +
4577 + switch (framectl & IEEE80211_FCTL_STYPE) {
4578 + case IEEE80211_STYPE_BEACON:
4579 + case IEEE80211_STYPE_PROBE_RESP:
4580 + at76_rx_mgmt_beacon(priv, buf);
4581 + break;
4582 +
4583 + case IEEE80211_STYPE_ASSOC_RESP:
4584 + at76_rx_mgmt_assoc(priv, buf);
4585 + break;
4586 +
4587 + case IEEE80211_STYPE_DISASSOC:
4588 + at76_rx_mgmt_disassoc(priv, buf);
4589 + break;
4590 +
4591 + case IEEE80211_STYPE_AUTH:
4592 + at76_rx_mgmt_auth(priv, buf);
4593 + break;
4594 +
4595 + case IEEE80211_STYPE_DEAUTH:
4596 + at76_rx_mgmt_deauth(priv, buf);
4597 + break;
4598 +
4599 + default:
4600 + printk(KERN_DEBUG "%s: ignoring frame with framectl 0x%04x\n",
4601 + priv->netdev->name, framectl);
4602 + }
4603 +
4604 + return;
4605 +}
4606 +
4607 +/* Convert the 802.11 header into an ethernet-style header, make skb
4608 + * ready for consumption by netif_rx() */
4609 +static void at76_ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
4610 +{
4611 + struct ieee80211_hdr_3addr *i802_11_hdr;
4612 + struct ethhdr *eth_hdr_p;
4613 + u8 *src_addr;
4614 + u8 *dest_addr;
4615 +
4616 + i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data;
4617 +
4618 + /* That would be the ethernet header if the hardware converted
4619 + * the frame for us. Make sure the source and the destination
4620 + * match the 802.11 header. Which hardware does it? */
4621 + eth_hdr_p = (struct ethhdr *)skb_pull(skb, IEEE80211_3ADDR_LEN);
4622 +
4623 + dest_addr = i802_11_hdr->addr1;
4624 + if (iw_mode == IW_MODE_ADHOC)
4625 + src_addr = i802_11_hdr->addr2;
4626 + else
4627 + src_addr = i802_11_hdr->addr3;
4628 +
4629 + if (!compare_ether_addr(eth_hdr_p->h_source, src_addr) &&
4630 + !compare_ether_addr(eth_hdr_p->h_dest, dest_addr))
4631 + /* Yes, we already have an ethernet header */
4632 + skb_reset_mac_header(skb);
4633 + else {
4634 + u16 len;
4635 +
4636 + /* Need to build an ethernet header */
4637 + if (!memcmp(skb->data, snapsig, sizeof(snapsig))) {
4638 + /* SNAP frame - decapsulate, keep proto */
4639 + skb_push(skb, offsetof(struct ethhdr, h_proto) -
4640 + sizeof(rfc1042sig));
4641 + len = 0;
4642 + } else {
4643 + /* 802.3 frame, proto is length */
4644 + len = skb->len;
4645 + skb_push(skb, ETH_HLEN);
4646 + }
4647 +
4648 + skb_reset_mac_header(skb);
4649 + eth_hdr_p = eth_hdr(skb);
4650 + /* This needs to be done in this order (eth_hdr_p->h_dest may
4651 + * overlap src_addr) */
4652 + memcpy(eth_hdr_p->h_source, src_addr, ETH_ALEN);
4653 + memcpy(eth_hdr_p->h_dest, dest_addr, ETH_ALEN);
4654 + if (len)
4655 + eth_hdr_p->h_proto = htons(len);
4656 + }
4657 +
4658 + skb->protocol = eth_type_trans(skb, skb->dev);
4659 +}
4660 +
4661 +/* Check for fragmented data in priv->rx_skb. If the packet was no fragment
4662 + or it was the last of a fragment set a skb containing the whole packet
4663 + is returned for further processing. Otherwise we get NULL and are
4664 + done and the packet is either stored inside the fragment buffer
4665 + or thrown away. Every returned skb starts with the ieee802_11 header
4666 + and contains _no_ FCS at the end */
4667 +static struct sk_buff *at76_check_for_rx_frags(struct at76_priv *priv)
4668 +{
4669 + struct sk_buff *skb = priv->rx_skb;
4670 + struct at76_rx_buffer *buf = (struct at76_rx_buffer *)skb->data;
4671 + struct ieee80211_hdr_3addr *i802_11_hdr =
4672 + (struct ieee80211_hdr_3addr *)buf->packet;
4673 + /* seq_ctrl, fragment_number, sequence number of new packet */
4674 + u16 sctl = le16_to_cpu(i802_11_hdr->seq_ctl);
4675 + u16 fragnr = sctl & 0xf;
4676 + u16 seqnr = sctl >> 4;
4677 + u16 frame_ctl = le16_to_cpu(i802_11_hdr->frame_ctl);
4678 +
4679 + /* Length including the IEEE802.11 header, but without the trailing
4680 + * FCS and without the Atmel Rx header */
4681 + int length = le16_to_cpu(buf->wlength) - IEEE80211_FCS_LEN;
4682 +
4683 + /* where does the data payload start in skb->data ? */
4684 + u8 *data = i802_11_hdr->payload;
4685 +
4686 + /* length of payload, excl. the trailing FCS */
4687 + int data_len = length - IEEE80211_3ADDR_LEN;
4688 +
4689 + int i;
4690 + struct rx_data_buf *bptr, *optr;
4691 + unsigned long oldest = ~0UL;
4692 +
4693 + at76_dbg(DBG_RX_FRAGS,
4694 + "%s: rx data frame_ctl %04x addr2 %s seq/frag %d/%d "
4695 + "length %d data %d: %s ...", priv->netdev->name, frame_ctl,
4696 + mac2str(i802_11_hdr->addr2), seqnr, fragnr, length, data_len,
4697 + hex2str(data, 32));
4698 +
4699 + at76_dbg(DBG_RX_FRAGS_SKB, "%s: incoming skb: head %p data %p "
4700 + "tail %p end %p len %d", priv->netdev->name, skb->head,
4701 + skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
4702 + skb->len);
4703 +
4704 + if (data_len < 0) {
4705 + /* make sure data starts in the buffer */
4706 + printk(KERN_INFO "%s: data frame too short\n",
4707 + priv->netdev->name);
4708 + return NULL;
4709 + }
4710 +
4711 + WARN_ON(length <= AT76_RX_HDRLEN);
4712 + if (length <= AT76_RX_HDRLEN)
4713 + return NULL;
4714 +
4715 + /* remove the at76_rx_buffer header - we don't need it anymore */
4716 + /* we need the IEEE802.11 header (for the addresses) if this packet
4717 + is the first of a chain */
4718 + skb_pull(skb, AT76_RX_HDRLEN);
4719 +
4720 + /* remove FCS at end */
4721 + skb_trim(skb, length);
4722 +
4723 + at76_dbg(DBG_RX_FRAGS_SKB, "%s: trimmed skb: head %p data %p tail %p "
4724 + "end %p len %d data %p data_len %d", priv->netdev->name,
4725 + skb->head, skb->data, skb_tail_pointer(skb),
4726 + skb_end_pointer(skb), skb->len, data, data_len);
4727 +
4728 + if (fragnr == 0 && !(frame_ctl & IEEE80211_FCTL_MOREFRAGS)) {
4729 + /* unfragmented packet received */
4730 + /* Use a new skb for the next receive */
4731 + priv->rx_skb = NULL;
4732 + at76_dbg(DBG_RX_FRAGS, "%s: unfragmented", priv->netdev->name);
4733 + return skb;
4734 + }
4735 +
4736 + /* look if we've got a chain for the sender address.
4737 + afterwards optr points to first free or the oldest entry,
4738 + or, if i < NR_RX_DATA_BUF, bptr points to the entry for the
4739 + sender address */
4740 + /* determining the oldest entry doesn't cope with jiffies wrapping
4741 + but I don't care to delete a young entry at these rare moments ... */
4742 +
4743 + bptr = priv->rx_data;
4744 + optr = NULL;
4745 + for (i = 0; i < NR_RX_DATA_BUF; i++, bptr++) {
4746 + if (!bptr->skb) {
4747 + optr = bptr;
4748 + oldest = 0UL;
4749 + continue;
4750 + }
4751 +
4752 + if (!compare_ether_addr(i802_11_hdr->addr2, bptr->sender))
4753 + break;
4754 +
4755 + if (!optr) {
4756 + optr = bptr;
4757 + oldest = bptr->last_rx;
4758 + } else if (bptr->last_rx < oldest)
4759 + optr = bptr;
4760 + }
4761 +
4762 + if (i < NR_RX_DATA_BUF) {
4763 +
4764 + at76_dbg(DBG_RX_FRAGS, "%s: %d. cacheentry (seq/frag = %d/%d) "
4765 + "matched sender addr",
4766 + priv->netdev->name, i, bptr->seqnr, bptr->fragnr);
4767 +
4768 + /* bptr points to an entry for the sender address */
4769 + if (bptr->seqnr == seqnr) {
4770 + int left;
4771 + /* the fragment has the current sequence number */
4772 + if (((bptr->fragnr + 1) & 0xf) != fragnr) {
4773 + /* wrong fragment number -> ignore it */
4774 + /* is & 0xf necessary above ??? */
4775 + at76_dbg(DBG_RX_FRAGS,
4776 + "%s: frag nr mismatch: %d + 1 != %d",
4777 + priv->netdev->name, bptr->fragnr,
4778 + fragnr);
4779 + return NULL;
4780 + }
4781 + bptr->last_rx = jiffies;
4782 + /* the next following fragment number ->
4783 + add the data at the end */
4784 +
4785 + /* for test only ??? */
4786 + left = skb_tailroom(bptr->skb);
4787 + if (left < data_len)
4788 + printk(KERN_INFO
4789 + "%s: only %d byte free (need %d)\n",
4790 + priv->netdev->name, left, data_len);
4791 + else
4792 + memcpy(skb_put(bptr->skb, data_len), data,
4793 + data_len);
4794 +
4795 + bptr->fragnr = fragnr;
4796 + if (frame_ctl & IEEE80211_FCTL_MOREFRAGS)
4797 + return NULL;
4798 +
4799 + /* this was the last fragment - send it */
4800 + skb = bptr->skb;
4801 + bptr->skb = NULL; /* free the entry */
4802 + at76_dbg(DBG_RX_FRAGS, "%s: last frag of seq %d",
4803 + priv->netdev->name, seqnr);
4804 + return skb;
4805 + }
4806 +
4807 + /* got another sequence number */
4808 + if (fragnr == 0) {
4809 + /* it's the start of a new chain - replace the
4810 + old one by this */
4811 + /* bptr->sender has the correct value already */
4812 + at76_dbg(DBG_RX_FRAGS,
4813 + "%s: start of new seq %d, removing old seq %d",
4814 + priv->netdev->name, seqnr, bptr->seqnr);
4815 + bptr->seqnr = seqnr;
4816 + bptr->fragnr = 0;
4817 + bptr->last_rx = jiffies;
4818 + /* swap bptr->skb and priv->rx_skb */
4819 + skb = bptr->skb;
4820 + bptr->skb = priv->rx_skb;
4821 + priv->rx_skb = skb;
4822 + } else {
4823 + /* it from the middle of a new chain ->
4824 + delete the old entry and skip the new one */
4825 + at76_dbg(DBG_RX_FRAGS,
4826 + "%s: middle of new seq %d (%d) "
4827 + "removing old seq %d",
4828 + priv->netdev->name, seqnr, fragnr,
4829 + bptr->seqnr);
4830 + dev_kfree_skb(bptr->skb);
4831 + bptr->skb = NULL;
4832 + }
4833 + return NULL;
4834 + }
4835 +
4836 + /* if we didn't find a chain for the sender address, optr
4837 + points either to the first free or the oldest entry */
4838 +
4839 + if (fragnr != 0) {
4840 + /* this is not the begin of a fragment chain ... */
4841 + at76_dbg(DBG_RX_FRAGS,
4842 + "%s: no chain for non-first fragment (%d)",
4843 + priv->netdev->name, fragnr);
4844 + return NULL;
4845 + }
4846 +
4847 + BUG_ON(!optr);
4848 + if (optr->skb) {
4849 + /* swap the skb's */
4850 + skb = optr->skb;
4851 + optr->skb = priv->rx_skb;
4852 + priv->rx_skb = skb;
4853 +
4854 + at76_dbg(DBG_RX_FRAGS,
4855 + "%s: free old contents: sender %s seq/frag %d/%d",
4856 + priv->netdev->name, mac2str(optr->sender),
4857 + optr->seqnr, optr->fragnr);
4858 +
4859 + } else {
4860 + /* take the skb from priv->rx_skb */
4861 + optr->skb = priv->rx_skb;
4862 + /* let at76_submit_rx_urb() allocate a new skb */
4863 + priv->rx_skb = NULL;
4864 +
4865 + at76_dbg(DBG_RX_FRAGS, "%s: use a free entry",
4866 + priv->netdev->name);
4867 + }
4868 + memcpy(optr->sender, i802_11_hdr->addr2, ETH_ALEN);
4869 + optr->seqnr = seqnr;
4870 + optr->fragnr = 0;
4871 + optr->last_rx = jiffies;
4872 +
4873 + return NULL;
4874 +}
4875 +
4876 +/* Rx interrupt: we expect the complete data buffer in priv->rx_skb */
4877 +static void at76_rx_data(struct at76_priv *priv)
4878 +{
4879 + struct net_device *netdev = priv->netdev;
4880 + struct net_device_stats *stats = &priv->stats;
4881 + struct sk_buff *skb = priv->rx_skb;
4882 + struct at76_rx_buffer *buf = (struct at76_rx_buffer *)skb->data;
4883 + struct ieee80211_hdr_3addr *i802_11_hdr;
4884 + int length = le16_to_cpu(buf->wlength);
4885 +
4886 + at76_dbg(DBG_RX_DATA, "%s received data packet: %s", netdev->name,
4887 + hex2str(skb->data, AT76_RX_HDRLEN));
4888 +
4889 + at76_dbg(DBG_RX_DATA_CONTENT, "rx packet: %s",
4890 + hex2str(skb->data + AT76_RX_HDRLEN, length));
4891 +
4892 + skb = at76_check_for_rx_frags(priv);
4893 + if (!skb)
4894 + return;
4895 +
4896 + /* Atmel header and the FCS are already removed */
4897 + i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data;
4898 +
4899 + skb->dev = netdev;
4900 + skb->ip_summed = CHECKSUM_NONE; /* TODO: should check CRC */
4901 +
4902 + if (is_broadcast_ether_addr(i802_11_hdr->addr1)) {
4903 + if (!compare_ether_addr(i802_11_hdr->addr1, netdev->broadcast))
4904 + skb->pkt_type = PACKET_BROADCAST;
4905 + else
4906 + skb->pkt_type = PACKET_MULTICAST;
4907 + } else if (compare_ether_addr(i802_11_hdr->addr1, netdev->dev_addr))
4908 + skb->pkt_type = PACKET_OTHERHOST;
4909 +
4910 + at76_ieee80211_to_eth(skb, priv->iw_mode);
4911 +
4912 + netdev->last_rx = jiffies;
4913 + netif_rx(skb);
4914 + stats->rx_packets++;
4915 + stats->rx_bytes += length;
4916 +
4917 + return;
4918 +}
4919 +
4920 +static void at76_rx_monitor_mode(struct at76_priv *priv)
4921 +{
4922 + struct at76_rx_radiotap *rt;
4923 + u8 *payload;
4924 + int skblen;
4925 + struct net_device *netdev = priv->netdev;
4926 + struct at76_rx_buffer *buf =
4927 + (struct at76_rx_buffer *)priv->rx_skb->data;
4928 + /* length including the IEEE802.11 header and the trailing FCS,
4929 + but not at76_rx_buffer */
4930 + int length = le16_to_cpu(buf->wlength);
4931 + struct sk_buff *skb = priv->rx_skb;
4932 + struct net_device_stats *stats = &priv->stats;
4933 +
4934 + if (length < IEEE80211_FCS_LEN) {
4935 + /* buffer contains no data */
4936 + at76_dbg(DBG_MONITOR_MODE,
4937 + "%s: MONITOR MODE: rx skb without data",
4938 + priv->netdev->name);
4939 + return;
4940 + }
4941 +
4942 + skblen = sizeof(struct at76_rx_radiotap) + length;
4943 +
4944 + skb = dev_alloc_skb(skblen);
4945 + if (!skb) {
4946 + printk(KERN_ERR "%s: MONITOR MODE: dev_alloc_skb for radiotap "
4947 + "header returned NULL\n", priv->netdev->name);
4948 + return;
4949 + }
4950 +
4951 + skb_put(skb, skblen);
4952 +
4953 + rt = (struct at76_rx_radiotap *)skb->data;
4954 + payload = skb->data + sizeof(struct at76_rx_radiotap);
4955 +
4956 + rt->rt_hdr.it_version = 0;
4957 + rt->rt_hdr.it_pad = 0;
4958 + rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct at76_rx_radiotap));
4959 + rt->rt_hdr.it_present = cpu_to_le32(AT76_RX_RADIOTAP_PRESENT);
4960 +
4961 + rt->rt_tsft = cpu_to_le64(le32_to_cpu(buf->rx_time));
4962 + rt->rt_rate = hw_rates[buf->rx_rate] & (~0x80);
4963 + rt->rt_signal = buf->rssi;
4964 + rt->rt_noise = buf->noise_level;
4965 + rt->rt_flags = IEEE80211_RADIOTAP_F_FCS;
4966 + if (buf->fragmentation)
4967 + rt->rt_flags |= IEEE80211_RADIOTAP_F_FRAG;
4968 +
4969 + memcpy(payload, buf->packet, length);
4970 + skb->dev = netdev;
4971 + skb->ip_summed = CHECKSUM_NONE;
4972 + skb_reset_mac_header(skb);
4973 + skb->pkt_type = PACKET_OTHERHOST;
4974 + skb->protocol = htons(ETH_P_802_2);
4975 +
4976 + netdev->last_rx = jiffies;
4977 + netif_rx(skb);
4978 + stats->rx_packets++;
4979 + stats->rx_bytes += length;
4980 +}
4981 +
4982 +/* Check if we spy on the sender address in buf and update stats */
4983 +static void at76_iwspy_update(struct at76_priv *priv,
4984 + struct at76_rx_buffer *buf)
4985 +{
4986 + struct ieee80211_hdr_3addr *hdr =
4987 + (struct ieee80211_hdr_3addr *)buf->packet;
4988 + struct iw_quality qual;
4989 +
4990 + /* We can only set the level here */
4991 + qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID;
4992 + qual.level = 0;
4993 + qual.noise = 0;
4994 + at76_calc_level(priv, buf, &qual);
4995 +
4996 + spin_lock_bh(&priv->spy_spinlock);
4997 +
4998 + if (priv->spy_data.spy_number > 0)
4999 + wireless_spy_update(priv->netdev, hdr->addr2, &qual);
5000 +
5001 + spin_unlock_bh(&priv->spy_spinlock);
5002 +}
5003 +
5004 +static void at76_rx_tasklet(unsigned long param)
5005 +{
5006 + struct urb *urb = (struct urb *)param;
5007 + struct at76_priv *priv = urb->context;
5008 + struct net_device *netdev = priv->netdev;
5009 + struct at76_rx_buffer *buf;
5010 + struct ieee80211_hdr_3addr *i802_11_hdr;
5011 + u16 frame_ctl;
5012 +
5013 + if (priv->device_unplugged) {
5014 + at76_dbg(DBG_DEVSTART, "device unplugged");
5015 + if (urb)
5016 + at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
5017 + return;
5018 + }
5019 +
5020 + if (!priv->rx_skb || !netdev || !priv->rx_skb->data)
5021 + return;
5022 +
5023 + buf = (struct at76_rx_buffer *)priv->rx_skb->data;
5024 +
5025 + i802_11_hdr = (struct ieee80211_hdr_3addr *)buf->packet;
5026 +
5027 + frame_ctl = le16_to_cpu(i802_11_hdr->frame_ctl);
5028 +
5029 + if (urb->status != 0) {
5030 + if (urb->status != -ENOENT && urb->status != -ECONNRESET)
5031 + at76_dbg(DBG_URB,
5032 + "%s %s: - nonzero Rx bulk status received: %d",
5033 + __func__, netdev->name, urb->status);
5034 + return;
5035 + }
5036 +
5037 + at76_dbg(DBG_RX_ATMEL_HDR,
5038 + "%s: rx frame: rate %d rssi %d noise %d link %d %s",
5039 + priv->netdev->name, buf->rx_rate, buf->rssi, buf->noise_level,
5040 + buf->link_quality, hex2str(i802_11_hdr, 48));
5041 + if (priv->iw_mode == IW_MODE_MONITOR) {
5042 + at76_rx_monitor_mode(priv);
5043 + goto exit;
5044 + }
5045 +
5046 + /* there is a new bssid around, accept it: */
5047 + if (buf->newbss && priv->iw_mode == IW_MODE_ADHOC) {
5048 + at76_dbg(DBG_PROGRESS, "%s: rx newbss", netdev->name);
5049 + schedule_work(&priv->work_new_bss);
5050 + }
5051 +
5052 + switch (frame_ctl & IEEE80211_FCTL_FTYPE) {
5053 + case IEEE80211_FTYPE_DATA:
5054 + at76_rx_data(priv);
5055 + break;
5056 +
5057 + case IEEE80211_FTYPE_MGMT:
5058 + /* jal: TODO: find out if we can update iwspy also on
5059 + other frames than management (might depend on the
5060 + radio chip / firmware version !) */
5061 +
5062 + at76_iwspy_update(priv, buf);
5063 +
5064 + at76_rx_mgmt(priv, buf);
5065 + break;
5066 +
5067 + case IEEE80211_FTYPE_CTL:
5068 + at76_dbg(DBG_RX_CTRL, "%s: ignored ctrl frame: %04x",
5069 + priv->netdev->name, frame_ctl);
5070 + break;
5071 +
5072 + default:
5073 + printk(KERN_DEBUG "%s: ignoring frame with framectl 0x%04x\n",
5074 + priv->netdev->name, frame_ctl);
5075 + }
5076 +exit:
5077 + at76_submit_rx_urb(priv);
5078 +}
5079 +
5080 +/* Load firmware into kernel memory and parse it */
5081 +static struct fwentry *at76_load_firmware(struct usb_device *udev,
5082 + enum board_type board_type)
5083 +{
5084 + int ret;
5085 + char *str;
5086 + struct at76_fw_header *fwh;
5087 + struct fwentry *fwe = &firmwares[board_type];
5088 +
5089 + mutex_lock(&fw_mutex);
5090 +
5091 + if (fwe->loaded) {
5092 + at76_dbg(DBG_FW, "re-using previously loaded fw");
5093 + goto exit;
5094 + }
5095 +
5096 + at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
5097 + ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
5098 + if (ret < 0) {
5099 + dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n",
5100 + fwe->fwname);
5101 + dev_printk(KERN_ERR, &udev->dev,
5102 + "you may need to download the firmware from "
5103 + "http://developer.berlios.de/projects/at76c503a/");
5104 + goto exit;
5105 + }
5106 +
5107 + at76_dbg(DBG_FW, "got it.");
5108 + fwh = (struct at76_fw_header *)(fwe->fw->data);
5109 +
5110 + if (fwe->fw->size <= sizeof(*fwh)) {
5111 + dev_printk(KERN_ERR, &udev->dev,
5112 + "firmware is too short (0x%zx)\n", fwe->fw->size);
5113 + goto exit;
5114 + }
5115 +
5116 + /* CRC currently not checked */
5117 + fwe->board_type = le32_to_cpu(fwh->board_type);
5118 + if (fwe->board_type != board_type) {
5119 + dev_printk(KERN_ERR, &udev->dev,
5120 + "board type mismatch, requested %u, got %u\n",
5121 + board_type, fwe->board_type);
5122 + goto exit;
5123 + }
5124 +
5125 + fwe->fw_version.major = fwh->major;
5126 + fwe->fw_version.minor = fwh->minor;
5127 + fwe->fw_version.patch = fwh->patch;
5128 + fwe->fw_version.build = fwh->build;
5129 +
5130 + str = (char *)fwh + le32_to_cpu(fwh->str_offset);
5131 + fwe->intfw = (u8 *)fwh + le32_to_cpu(fwh->int_fw_offset);
5132 + fwe->intfw_size = le32_to_cpu(fwh->int_fw_len);
5133 + fwe->extfw = (u8 *)fwh + le32_to_cpu(fwh->ext_fw_offset);
5134 + fwe->extfw_size = le32_to_cpu(fwh->ext_fw_len);
5135 +
5136 + fwe->loaded = 1;
5137 +
5138 + dev_printk(KERN_DEBUG, &udev->dev,
5139 + "using firmware %s (version %d.%d.%d-%d)\n",
5140 + fwe->fwname, fwh->major, fwh->minor, fwh->patch, fwh->build);
5141 +
5142 + at76_dbg(DBG_DEVSTART, "board %u, int %d:%d, ext %d:%d", board_type,
5143 + le32_to_cpu(fwh->int_fw_offset), le32_to_cpu(fwh->int_fw_len),
5144 + le32_to_cpu(fwh->ext_fw_offset), le32_to_cpu(fwh->ext_fw_len));
5145 + at76_dbg(DBG_DEVSTART, "firmware id %s", str);
5146 +
5147 +exit:
5148 + mutex_unlock(&fw_mutex);
5149 +
5150 + if (fwe->loaded)
5151 + return fwe;
5152 + else
5153 + return NULL;
5154 +}
5155 +
5156 +/* Allocate network device and initialize private data */
5157 +static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
5158 +{
5159 + struct net_device *netdev;
5160 + struct at76_priv *priv;
5161 + int i;
5162 +
5163 + /* allocate memory for our device state and initialize it */
5164 + netdev = alloc_etherdev(sizeof(struct at76_priv));
5165 + if (!netdev) {
5166 + dev_printk(KERN_ERR, &udev->dev, "out of memory\n");
5167 + return NULL;
5168 + }
5169 +
5170 + priv = netdev_priv(netdev);
5171 +
5172 + priv->udev = udev;
5173 + priv->netdev = netdev;
5174 +
5175 + mutex_init(&priv->mtx);
5176 + INIT_WORK(&priv->work_assoc_done, at76_work_assoc_done);
5177 + INIT_WORK(&priv->work_join, at76_work_join);
5178 + INIT_WORK(&priv->work_new_bss, at76_work_new_bss);
5179 + INIT_WORK(&priv->work_start_scan, at76_work_start_scan);
5180 + INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc);
5181 + INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx);
5182 + INIT_DELAYED_WORK(&priv->dwork_restart, at76_dwork_restart);
5183 + INIT_DELAYED_WORK(&priv->dwork_get_scan, at76_dwork_get_scan);
5184 + INIT_DELAYED_WORK(&priv->dwork_beacon, at76_dwork_beacon);
5185 + INIT_DELAYED_WORK(&priv->dwork_auth, at76_dwork_auth);
5186 + INIT_DELAYED_WORK(&priv->dwork_assoc, at76_dwork_assoc);
5187 +
5188 + spin_lock_init(&priv->mgmt_spinlock);
5189 + priv->next_mgmt_bulk = NULL;
5190 + priv->mac_state = MAC_INIT;
5191 +
5192 + /* initialize empty BSS list */
5193 + priv->curr_bss = NULL;
5194 + INIT_LIST_HEAD(&priv->bss_list);
5195 + spin_lock_init(&priv->bss_list_spinlock);
5196 +
5197 + init_timer(&priv->bss_list_timer);
5198 + priv->bss_list_timer.data = (unsigned long)priv;
5199 + priv->bss_list_timer.function = at76_bss_list_timeout;
5200 +
5201 + spin_lock_init(&priv->spy_spinlock);
5202 +
5203 + /* mark all rx data entries as unused */
5204 + for (i = 0; i < NR_RX_DATA_BUF; i++)
5205 + priv->rx_data[i].skb = NULL;
5206 +
5207 + priv->rx_tasklet.func = at76_rx_tasklet;
5208 + priv->rx_tasklet.data = 0;
5209 +
5210 + priv->pm_mode = AT76_PM_OFF;
5211 + priv->pm_period = 0;
5212 +
5213 + return priv;
5214 +}
5215 +
5216 +static int at76_alloc_urbs(struct at76_priv *priv,
5217 + struct usb_interface *interface)
5218 +{
5219 + struct usb_endpoint_descriptor *endpoint, *ep_in, *ep_out;
5220 + int i;
5221 + int buffer_size;
5222 + struct usb_host_interface *iface_desc;
5223 +
5224 + at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__);
5225 +
5226 + at76_dbg(DBG_URB, "%s: NumEndpoints %d ", __func__,
5227 + interface->altsetting[0].desc.bNumEndpoints);
5228 +
5229 + ep_in = NULL;
5230 + ep_out = NULL;
5231 + iface_desc = interface->cur_altsetting;
5232 + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
5233 + endpoint = &iface_desc->endpoint[i].desc;
5234 +
5235 + at76_dbg(DBG_URB, "%s: %d. endpoint: addr 0x%x attr 0x%x",
5236 + __func__, i, endpoint->bEndpointAddress,
5237 + endpoint->bmAttributes);
5238 +
5239 + if (!ep_in && usb_endpoint_is_bulk_in(endpoint))
5240 + ep_in = endpoint;
5241 +
5242 + if (!ep_out && usb_endpoint_is_bulk_out(endpoint))
5243 + ep_out = endpoint;
5244 + }
5245 +
5246 + if (!ep_in || !ep_out) {
5247 + dev_printk(KERN_ERR, &interface->dev,
5248 + "bulk endpoints missing\n");
5249 + return -ENXIO;
5250 + }
5251 +
5252 + priv->rx_pipe = usb_rcvbulkpipe(priv->udev, ep_in->bEndpointAddress);
5253 + priv->tx_pipe = usb_sndbulkpipe(priv->udev, ep_out->bEndpointAddress);
5254 +
5255 + priv->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
5256 + priv->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
5257 + if (!priv->rx_urb || !priv->tx_urb) {
5258 + dev_printk(KERN_ERR, &interface->dev, "cannot allocate URB\n");
5259 + return -ENOMEM;
5260 + }
5261 +
5262 + buffer_size = sizeof(struct at76_tx_buffer) + MAX_PADDING_SIZE;
5263 + priv->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
5264 + if (!priv->bulk_out_buffer) {
5265 + dev_printk(KERN_ERR, &interface->dev,
5266 + "cannot allocate output buffer\n");
5267 + return -ENOMEM;
5268 + }
5269 +
5270 + at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__);
5271 +
5272 + return 0;
5273 +}
5274 +
5275 +/* Register network device and initialize the hardware */
5276 +static int at76_init_new_device(struct at76_priv *priv,
5277 + struct usb_interface *interface)
5278 +{
5279 + struct net_device *netdev = priv->netdev;
5280 + int ret;
5281 +
5282 + /* set up the endpoint information */
5283 + /* check out the endpoints */
5284 +
5285 + at76_dbg(DBG_DEVSTART, "USB interface: %d endpoints",
5286 + interface->cur_altsetting->desc.bNumEndpoints);
5287 +
5288 + ret = at76_alloc_urbs(priv, interface);
5289 + if (ret < 0)
5290 + goto exit;
5291 +
5292 + /* MAC address */
5293 + ret = at76_get_hw_config(priv);
5294 + if (ret < 0) {
5295 + dev_printk(KERN_ERR, &interface->dev,
5296 + "cannot get MAC address\n");
5297 + goto exit;
5298 + }
5299 +
5300 + priv->domain = at76_get_reg_domain(priv->regulatory_domain);
5301 + /* init. netdev->dev_addr */
5302 + memcpy(netdev->dev_addr, priv->mac_addr, ETH_ALEN);
5303 +
5304 + priv->channel = DEF_CHANNEL;
5305 + priv->iw_mode = IW_MODE_INFRA;
5306 + priv->rts_threshold = DEF_RTS_THRESHOLD;
5307 + priv->frag_threshold = DEF_FRAG_THRESHOLD;
5308 + priv->short_retry_limit = DEF_SHORT_RETRY_LIMIT;
5309 + priv->txrate = TX_RATE_AUTO;
5310 + priv->preamble_type = PREAMBLE_TYPE_LONG;
5311 + priv->beacon_period = 100;
5312 + priv->beacons_last_qual = jiffies;
5313 + priv->auth_mode = WLAN_AUTH_OPEN;
5314 + priv->scan_min_time = DEF_SCAN_MIN_TIME;
5315 + priv->scan_max_time = DEF_SCAN_MAX_TIME;
5316 + priv->scan_mode = SCAN_TYPE_ACTIVE;
5317 +
5318 + netdev->flags &= ~IFF_MULTICAST; /* not yet or never */
5319 + netdev->open = at76_open;
5320 + netdev->stop = at76_stop;
5321 + netdev->get_stats = at76_get_stats;
5322 + netdev->ethtool_ops = &at76_ethtool_ops;
5323 +
5324 + /* Add pointers to enable iwspy support. */
5325 + priv->wireless_data.spy_data = &priv->spy_data;
5326 + netdev->wireless_data = &priv->wireless_data;
5327 +
5328 + netdev->hard_start_xmit = at76_tx;
5329 + netdev->tx_timeout = at76_tx_timeout;
5330 + netdev->watchdog_timeo = 2 * HZ;
5331 + netdev->wireless_handlers = &at76_handler_def;
5332 + netdev->set_multicast_list = at76_set_multicast;
5333 + netdev->set_mac_address = at76_set_mac_address;
5334 + dev_alloc_name(netdev, "wlan%d");
5335 +
5336 + ret = register_netdev(priv->netdev);
5337 + if (ret) {
5338 + dev_printk(KERN_ERR, &interface->dev,
5339 + "cannot register netdevice (status %d)!\n", ret);
5340 + goto exit;
5341 + }
5342 + priv->netdev_registered = 1;
5343 +
5344 + printk(KERN_INFO "%s: USB %s, MAC %s, firmware %d.%d.%d-%d\n",
5345 + netdev->name, interface->dev.bus_id, mac2str(priv->mac_addr),
5346 + priv->fw_version.major, priv->fw_version.minor,
5347 + priv->fw_version.patch, priv->fw_version.build);
5348 + printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n", netdev->name,
5349 + priv->regulatory_domain, priv->domain->name);
5350 +
5351 + /* we let this timer run the whole time this driver instance lives */
5352 + mod_timer(&priv->bss_list_timer, jiffies + BSS_LIST_TIMEOUT);
5353 +
5354 +exit:
5355 + return ret;
5356 +}
5357 +
5358 +static void at76_delete_device(struct at76_priv *priv)
5359 +{
5360 + int i;
5361 +
5362 + at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__);
5363 +
5364 + /* The device is gone, don't bother turning it off */
5365 + priv->device_unplugged = 1;
5366 +
5367 + if (priv->netdev_registered)
5368 + unregister_netdev(priv->netdev);
5369 +
5370 + /* assuming we used keventd, it must quiesce too */
5371 + flush_scheduled_work();
5372 +
5373 + kfree(priv->bulk_out_buffer);
5374 +
5375 + if (priv->tx_urb) {
5376 + usb_kill_urb(priv->tx_urb);
5377 + usb_free_urb(priv->tx_urb);
5378 + }
5379 + if (priv->rx_urb) {
5380 + usb_kill_urb(priv->rx_urb);
5381 + usb_free_urb(priv->rx_urb);
5382 + }
5383 +
5384 + at76_dbg(DBG_PROC_ENTRY, "%s: unlinked urbs", __func__);
5385 +
5386 + if (priv->rx_skb)
5387 + kfree_skb(priv->rx_skb);
5388 +
5389 + at76_free_bss_list(priv);
5390 + del_timer_sync(&priv->bss_list_timer);
5391 + cancel_delayed_work(&priv->dwork_get_scan);
5392 + cancel_delayed_work(&priv->dwork_beacon);
5393 + cancel_delayed_work(&priv->dwork_auth);
5394 + cancel_delayed_work(&priv->dwork_assoc);
5395 +
5396 + if (priv->mac_state == MAC_CONNECTED)
5397 + at76_iwevent_bss_disconnect(priv->netdev);
5398 +
5399 + for (i = 0; i < NR_RX_DATA_BUF; i++)
5400 + if (priv->rx_data[i].skb) {
5401 + dev_kfree_skb(priv->rx_data[i].skb);
5402 + priv->rx_data[i].skb = NULL;
5403 + }
5404 + usb_put_dev(priv->udev);
5405 +
5406 + at76_dbg(DBG_PROC_ENTRY, "%s: before freeing priv/netdev", __func__);
5407 + free_netdev(priv->netdev); /* priv is in netdev */
5408 +
5409 + at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__);
5410 +}
5411 +
5412 +static int at76_probe(struct usb_interface *interface,
5413 + const struct usb_device_id *id)
5414 +{
5415 + int ret;
5416 + struct at76_priv *priv;
5417 + struct fwentry *fwe;
5418 + struct usb_device *udev;
5419 + int op_mode;
5420 + int need_ext_fw = 0;
5421 + struct mib_fw_version fwv;
5422 + int board_type = (int)id->driver_info;
5423 +
5424 + udev = usb_get_dev(interface_to_usbdev(interface));
5425 +
5426 + /* Load firmware into kernel memory */
5427 + fwe = at76_load_firmware(udev, board_type);
5428 + if (!fwe) {
5429 + ret = -ENOENT;
5430 + goto error;
5431 + }
5432 +
5433 + op_mode = at76_get_op_mode(udev);
5434 +
5435 + at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
5436 +
5437 + /* we get OPMODE_NONE with 2.4.23, SMC2662W-AR ???
5438 + we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */
5439 +
5440 + if (op_mode == OPMODE_HW_CONFIG_MODE) {
5441 + dev_printk(KERN_ERR, &interface->dev,
5442 + "cannot handle a device in HW_CONFIG_MODE\n");
5443 + ret = -EBUSY;
5444 + goto error;
5445 + }
5446 +
5447 + if (op_mode != OPMODE_NORMAL_NIC_WITH_FLASH
5448 + && op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
5449 + /* download internal firmware part */
5450 + dev_printk(KERN_DEBUG, &interface->dev,
5451 + "downloading internal firmware\n");
5452 + ret = at76_load_internal_fw(udev, fwe);
5453 + if (ret < 0) {
5454 + dev_printk(KERN_ERR, &interface->dev,
5455 + "error %d downloading internal firmware\n",
5456 + ret);
5457 + goto error;
5458 + }
5459 + usb_put_dev(udev);
5460 + return ret;
5461 + }
5462 +
5463 + /* Internal firmware already inside the device. Get firmware
5464 + * version to test if external firmware is loaded.
5465 + * This works only for newer firmware, e.g. the Intersil 0.90.x
5466 + * says "control timeout on ep0in" and subsequent
5467 + * at76_get_op_mode() fail too :-( */
5468 +
5469 + /* if version >= 0.100.x.y or device with built-in flash we can
5470 + * query the device for the fw version */
5471 + if ((fwe->fw_version.major > 0 || fwe->fw_version.minor >= 100)
5472 + || (op_mode == OPMODE_NORMAL_NIC_WITH_FLASH)) {
5473 + ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
5474 + if (ret < 0 || (fwv.major | fwv.minor) == 0)
5475 + need_ext_fw = 1;
5476 + } else
5477 + /* No way to check firmware version, reload to be sure */
5478 + need_ext_fw = 1;
5479 +
5480 + if (need_ext_fw) {
5481 + dev_printk(KERN_DEBUG, &interface->dev,
5482 + "downloading external firmware\n");
5483 +
5484 + ret = at76_load_external_fw(udev, fwe);
5485 + if (ret)
5486 + goto error;
5487 +
5488 + /* Re-check firmware version */
5489 + ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
5490 + if (ret < 0) {
5491 + dev_printk(KERN_ERR, &interface->dev,
5492 + "error %d getting firmware version\n", ret);
5493 + goto error;
5494 + }
5495 + }
5496 +
5497 + priv = at76_alloc_new_device(udev);
5498 + if (!priv) {
5499 + ret = -ENOMEM;
5500 + goto error;
5501 + }
5502 +
5503 + SET_NETDEV_DEV(priv->netdev, &interface->dev);
5504 + usb_set_intfdata(interface, priv);
5505 +
5506 + memcpy(&priv->fw_version, &fwv, sizeof(struct mib_fw_version));
5507 + priv->board_type = board_type;
5508 +
5509 + ret = at76_init_new_device(priv, interface);
5510 + if (ret < 0)
5511 + at76_delete_device(priv);
5512 +
5513 + return ret;
5514 +
5515 +error:
5516 + usb_put_dev(udev);
5517 + return ret;
5518 +}
5519 +
5520 +static void at76_disconnect(struct usb_interface *interface)
5521 +{
5522 + struct at76_priv *priv;
5523 +
5524 + priv = usb_get_intfdata(interface);
5525 + usb_set_intfdata(interface, NULL);
5526 +
5527 + /* Disconnect after loading internal firmware */
5528 + if (!priv)
5529 + return;
5530 +
5531 + printk(KERN_INFO "%s: disconnecting\n", priv->netdev->name);
5532 + at76_delete_device(priv);
5533 + dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
5534 +}
5535 +
5536 +/* Structure for registering this driver with the USB subsystem */
5537 +static struct usb_driver at76_driver = {
5538 + .name = DRIVER_NAME,
5539 + .probe = at76_probe,
5540 + .disconnect = at76_disconnect,
5541 + .id_table = dev_table,
5542 +};
5543 +
5544 +static int __init at76_mod_init(void)
5545 +{
5546 + int result;
5547 +
5548 + printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " loading\n");
5549 +
5550 + mutex_init(&fw_mutex);
5551 +
5552 + /* register this driver with the USB subsystem */
5553 + result = usb_register(&at76_driver);
5554 + if (result < 0)
5555 + printk(KERN_ERR DRIVER_NAME
5556 + ": usb_register failed (status %d)\n", result);
5557 +
5558 + led_trigger_register_simple("at76_usb-tx", &ledtrig_tx);
5559 + return result;
5560 +}
5561 +
5562 +static void __exit at76_mod_exit(void)
5563 +{
5564 + int i;
5565 +
5566 + printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " unloading\n");
5567 + usb_deregister(&at76_driver);
5568 + for (i = 0; i < ARRAY_SIZE(firmwares); i++) {
5569 + if (firmwares[i].fw)
5570 + release_firmware(firmwares[i].fw);
5571 + }
5572 + led_trigger_unregister_simple(ledtrig_tx);
5573 +}
5574 +
5575 +module_param_named(debug, at76_debug, int, 0600);
5576 +MODULE_PARM_DESC(debug, "Debugging level");
5577 +
5578 +module_init(at76_mod_init);
5579 +module_exit(at76_mod_exit);
5580 +
5581 +MODULE_AUTHOR("Oliver Kurth <oku@masqmail.cx>");
5582 +MODULE_AUTHOR("Joerg Albert <joerg.albert@gmx.de>");
5583 +MODULE_AUTHOR("Alex <alex@foogod.com>");
5584 +MODULE_AUTHOR("Nick Jones");
5585 +MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>");
5586 +MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
5587 +MODULE_DESCRIPTION(DRIVER_DESC);
5588 +MODULE_LICENSE("GPL");
5589 --- /dev/null
5590 +++ b/drivers/staging/at76_usb/at76_usb.h
5591 @@ -0,0 +1,619 @@
5592 +/*
5593 + * Copyright (c) 2002,2003 Oliver Kurth
5594 + * (c) 2003,2004 Joerg Albert <joerg.albert@gmx.de>
5595 + * (c) 2007 Guido Guenther <agx@sigxcpu.org>
5596 + *
5597 + * This program is free software; you can redistribute it and/or
5598 + * modify it under the terms of the GNU General Public License as
5599 + * published by the Free Software Foundation; either version 2 of
5600 + * the License, or (at your option) any later version.
5601 + *
5602 + * This driver was based on information from the Sourceforge driver
5603 + * released and maintained by Atmel:
5604 + *
5605 + * http://sourceforge.net/projects/atmelwlandriver/
5606 + *
5607 + * Although the code was completely re-written,
5608 + * it would have been impossible without Atmel's decision to
5609 + * release an Open Source driver (unfortunately the firmware was
5610 + * kept binary only). Thanks for that decision to Atmel!
5611 + */
5612 +
5613 +#ifndef _AT76_USB_H
5614 +#define _AT76_USB_H
5615 +
5616 +/* Board types */
5617 +enum board_type {
5618 + BOARD_503_ISL3861 = 1,
5619 + BOARD_503_ISL3863 = 2,
5620 + BOARD_503 = 3,
5621 + BOARD_503_ACC = 4,
5622 + BOARD_505 = 5,
5623 + BOARD_505_2958 = 6,
5624 + BOARD_505A = 7,
5625 + BOARD_505AMX = 8
5626 +};
5627 +
5628 +/* our private ioctl's */
5629 +/* preamble length (0 - long, 1 - short, 2 - auto) */
5630 +#define AT76_SET_SHORT_PREAMBLE (SIOCIWFIRSTPRIV + 0)
5631 +#define AT76_GET_SHORT_PREAMBLE (SIOCIWFIRSTPRIV + 1)
5632 +/* which debug channels are enabled */
5633 +#define AT76_SET_DEBUG (SIOCIWFIRSTPRIV + 2)
5634 +#define AT76_GET_DEBUG (SIOCIWFIRSTPRIV + 3)
5635 +/* power save mode (incl. the Atmel proprietary smart save mode) */
5636 +#define AT76_SET_POWERSAVE_MODE (SIOCIWFIRSTPRIV + 4)
5637 +#define AT76_GET_POWERSAVE_MODE (SIOCIWFIRSTPRIV + 5)
5638 +/* min and max channel times for scan */
5639 +#define AT76_SET_SCAN_TIMES (SIOCIWFIRSTPRIV + 6)
5640 +#define AT76_GET_SCAN_TIMES (SIOCIWFIRSTPRIV + 7)
5641 +/* scan mode (0 - active, 1 - passive) */
5642 +#define AT76_SET_SCAN_MODE (SIOCIWFIRSTPRIV + 8)
5643 +#define AT76_GET_SCAN_MODE (SIOCIWFIRSTPRIV + 9)
5644 +
5645 +#define CMD_STATUS_IDLE 0x00
5646 +#define CMD_STATUS_COMPLETE 0x01
5647 +#define CMD_STATUS_UNKNOWN 0x02
5648 +#define CMD_STATUS_INVALID_PARAMETER 0x03
5649 +#define CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04
5650 +#define CMD_STATUS_TIME_OUT 0x07
5651 +#define CMD_STATUS_IN_PROGRESS 0x08
5652 +#define CMD_STATUS_HOST_FAILURE 0xff
5653 +#define CMD_STATUS_SCAN_FAILED 0xf0
5654 +
5655 +/* answers to get op mode */
5656 +#define OPMODE_NONE 0x00
5657 +#define OPMODE_NORMAL_NIC_WITH_FLASH 0x01
5658 +#define OPMODE_HW_CONFIG_MODE 0x02
5659 +#define OPMODE_DFU_MODE_WITH_FLASH 0x03
5660 +#define OPMODE_NORMAL_NIC_WITHOUT_FLASH 0x04
5661 +
5662 +#define CMD_SET_MIB 0x01
5663 +#define CMD_GET_MIB 0x02
5664 +#define CMD_SCAN 0x03
5665 +#define CMD_JOIN 0x04
5666 +#define CMD_START_IBSS 0x05
5667 +#define CMD_RADIO_ON 0x06
5668 +#define CMD_RADIO_OFF 0x07
5669 +#define CMD_STARTUP 0x0B
5670 +
5671 +#define MIB_LOCAL 0x01
5672 +#define MIB_MAC_ADDR 0x02
5673 +#define MIB_MAC 0x03
5674 +#define MIB_MAC_MGMT 0x05
5675 +#define MIB_MAC_WEP 0x06
5676 +#define MIB_PHY 0x07
5677 +#define MIB_FW_VERSION 0x08
5678 +#define MIB_MDOMAIN 0x09
5679 +
5680 +#define ADHOC_MODE 1
5681 +#define INFRASTRUCTURE_MODE 2
5682 +
5683 +/* values for struct mib_local, field preamble_type */
5684 +#define PREAMBLE_TYPE_LONG 0
5685 +#define PREAMBLE_TYPE_SHORT 1
5686 +#define PREAMBLE_TYPE_AUTO 2
5687 +
5688 +/* values for tx_rate */
5689 +#define TX_RATE_1MBIT 0
5690 +#define TX_RATE_2MBIT 1
5691 +#define TX_RATE_5_5MBIT 2
5692 +#define TX_RATE_11MBIT 3
5693 +#define TX_RATE_AUTO 4
5694 +
5695 +/* power management modes */
5696 +#define AT76_PM_OFF 1
5697 +#define AT76_PM_ON 2
5698 +#define AT76_PM_SMART 3
5699 +
5700 +struct hwcfg_r505 {
5701 + u8 cr39_values[14];
5702 + u8 reserved1[14];
5703 + u8 bb_cr[14];
5704 + u8 pidvid[4];
5705 + u8 mac_addr[ETH_ALEN];
5706 + u8 regulatory_domain;
5707 + u8 reserved2[14];
5708 + u8 cr15_values[14];
5709 + u8 reserved3[3];
5710 +} __attribute__((packed));
5711 +
5712 +struct hwcfg_rfmd {
5713 + u8 cr20_values[14];
5714 + u8 cr21_values[14];
5715 + u8 bb_cr[14];
5716 + u8 pidvid[4];
5717 + u8 mac_addr[ETH_ALEN];
5718 + u8 regulatory_domain;
5719 + u8 low_power_values[14];
5720 + u8 normal_power_values[14];
5721 + u8 reserved1[3];
5722 +} __attribute__((packed));
5723 +
5724 +struct hwcfg_intersil {
5725 + u8 mac_addr[ETH_ALEN];
5726 + u8 cr31_values[14];
5727 + u8 cr58_values[14];
5728 + u8 pidvid[4];
5729 + u8 regulatory_domain;
5730 + u8 reserved[1];
5731 +} __attribute__((packed));
5732 +
5733 +union at76_hwcfg {
5734 + struct hwcfg_intersil i;
5735 + struct hwcfg_rfmd r3;
5736 + struct hwcfg_r505 r5;
5737 +};
5738 +
5739 +#define WEP_SMALL_KEY_LEN (40 / 8)
5740 +#define WEP_LARGE_KEY_LEN (104 / 8)
5741 +
5742 +struct at76_card_config {
5743 + u8 exclude_unencrypted;
5744 + u8 promiscuous_mode;
5745 + u8 short_retry_limit;
5746 + u8 encryption_type;
5747 + __le16 rts_threshold;
5748 + __le16 fragmentation_threshold; /* 256..2346 */
5749 + u8 basic_rate_set[4];
5750 + u8 auto_rate_fallback; /* 0,1 */
5751 + u8 channel;
5752 + u8 privacy_invoked;
5753 + u8 wep_default_key_id; /* 0..3 */
5754 + u8 current_ssid[32];
5755 + u8 wep_default_key_value[4][WEP_KEY_LEN];
5756 + u8 ssid_len;
5757 + u8 short_preamble;
5758 + __le16 beacon_period;
5759 +} __attribute__((packed));
5760 +
5761 +struct at76_command {
5762 + u8 cmd;
5763 + u8 reserved;
5764 + __le16 size;
5765 + u8 data[0];
5766 +} __attribute__((packed));
5767 +
5768 +/* Length of Atmel-specific Rx header before 802.11 frame */
5769 +#define AT76_RX_HDRLEN offsetof(struct at76_rx_buffer, packet)
5770 +
5771 +struct at76_rx_buffer {
5772 + __le16 wlength;
5773 + u8 rx_rate;
5774 + u8 newbss;
5775 + u8 fragmentation;
5776 + u8 rssi;
5777 + u8 link_quality;
5778 + u8 noise_level;
5779 + __le32 rx_time;
5780 + u8 packet[IEEE80211_FRAME_LEN + IEEE80211_FCS_LEN];
5781 +} __attribute__((packed));
5782 +
5783 +/* Length of Atmel-specific Tx header before 802.11 frame */
5784 +#define AT76_TX_HDRLEN offsetof(struct at76_tx_buffer, packet)
5785 +
5786 +struct at76_tx_buffer {
5787 + __le16 wlength;
5788 + u8 tx_rate;
5789 + u8 padding;
5790 + u8 reserved[4];
5791 + u8 packet[IEEE80211_FRAME_LEN + IEEE80211_FCS_LEN];
5792 +} __attribute__((packed));
5793 +
5794 +/* defines for scan_type below */
5795 +#define SCAN_TYPE_ACTIVE 0
5796 +#define SCAN_TYPE_PASSIVE 1
5797 +
5798 +struct at76_req_scan {
5799 + u8 bssid[ETH_ALEN];
5800 + u8 essid[32];
5801 + u8 scan_type;
5802 + u8 channel;
5803 + __le16 probe_delay;
5804 + __le16 min_channel_time;
5805 + __le16 max_channel_time;
5806 + u8 essid_size;
5807 + u8 international_scan;
5808 +} __attribute__((packed));
5809 +
5810 +struct at76_req_ibss {
5811 + u8 bssid[ETH_ALEN];
5812 + u8 essid[32];
5813 + u8 bss_type;
5814 + u8 channel;
5815 + u8 essid_size;
5816 + u8 reserved[3];
5817 +} __attribute__((packed));
5818 +
5819 +struct at76_req_join {
5820 + u8 bssid[ETH_ALEN];
5821 + u8 essid[32];
5822 + u8 bss_type;
5823 + u8 channel;
5824 + __le16 timeout;
5825 + u8 essid_size;
5826 + u8 reserved;
5827 +} __attribute__((packed));
5828 +
5829 +struct set_mib_buffer {
5830 + u8 type;
5831 + u8 size;
5832 + u8 index;
5833 + u8 reserved;
5834 + union {
5835 + u8 byte;
5836 + __le16 word;
5837 + u8 addr[ETH_ALEN];
5838 + } data;
5839 +} __attribute__((packed));
5840 +
5841 +struct mib_local {
5842 + u16 reserved0;
5843 + u8 beacon_enable;
5844 + u8 txautorate_fallback;
5845 + u8 reserved1;
5846 + u8 ssid_size;
5847 + u8 promiscuous_mode;
5848 + u16 reserved2;
5849 + u8 preamble_type;
5850 + u16 reserved3;
5851 +} __attribute__((packed));
5852 +
5853 +struct mib_mac_addr {
5854 + u8 mac_addr[ETH_ALEN];
5855 + u8 res[2]; /* ??? */
5856 + u8 group_addr[4][ETH_ALEN];
5857 + u8 group_addr_status[4];
5858 +} __attribute__((packed));
5859 +
5860 +struct mib_mac {
5861 + __le32 max_tx_msdu_lifetime;
5862 + __le32 max_rx_lifetime;
5863 + __le16 frag_threshold;
5864 + __le16 rts_threshold;
5865 + __le16 cwmin;
5866 + __le16 cwmax;
5867 + u8 short_retry_time;
5868 + u8 long_retry_time;
5869 + u8 scan_type; /* active or passive */
5870 + u8 scan_channel;
5871 + __le16 probe_delay; /* delay before ProbeReq in active scan, RO */
5872 + __le16 min_channel_time;
5873 + __le16 max_channel_time;
5874 + __le16 listen_interval;
5875 + u8 desired_ssid[32];
5876 + u8 desired_bssid[ETH_ALEN];
5877 + u8 desired_bsstype; /* ad-hoc or infrastructure */
5878 + u8 reserved2;
5879 +} __attribute__((packed));
5880 +
5881 +struct mib_mac_mgmt {
5882 + __le16 beacon_period;
5883 + __le16 CFP_max_duration;
5884 + __le16 medium_occupancy_limit;
5885 + __le16 station_id; /* assoc id */
5886 + __le16 ATIM_window;
5887 + u8 CFP_mode;
5888 + u8 privacy_option_implemented;
5889 + u8 DTIM_period;
5890 + u8 CFP_period;
5891 + u8 current_bssid[ETH_ALEN];
5892 + u8 current_essid[32];
5893 + u8 current_bss_type;
5894 + u8 power_mgmt_mode;
5895 + /* rfmd and 505 */
5896 + u8 ibss_change;
5897 + u8 res;
5898 + u8 multi_domain_capability_implemented;
5899 + u8 multi_domain_capability_enabled;
5900 + u8 country_string[3];
5901 + u8 reserved[3];
5902 +} __attribute__((packed));
5903 +
5904 +struct mib_mac_wep {
5905 + u8 privacy_invoked; /* 0 disable encr., 1 enable encr */
5906 + u8 wep_default_key_id;
5907 + u8 wep_key_mapping_len;
5908 + u8 exclude_unencrypted;
5909 + __le32 wep_icv_error_count;
5910 + __le32 wep_excluded_count;
5911 + u8 wep_default_keyvalue[WEP_KEYS][WEP_KEY_LEN];
5912 + u8 encryption_level; /* 1 for 40bit, 2 for 104bit encryption */
5913 +} __attribute__((packed));
5914 +
5915 +struct mib_phy {
5916 + __le32 ed_threshold;
5917 +
5918 + __le16 slot_time;
5919 + __le16 sifs_time;
5920 + __le16 preamble_length;
5921 + __le16 plcp_header_length;
5922 + __le16 mpdu_max_length;
5923 + __le16 cca_mode_supported;
5924 +
5925 + u8 operation_rate_set[4];
5926 + u8 channel_id;
5927 + u8 current_cca_mode;
5928 + u8 phy_type;
5929 + u8 current_reg_domain;
5930 +} __attribute__((packed));
5931 +
5932 +struct mib_fw_version {
5933 + u8 major;
5934 + u8 minor;
5935 + u8 patch;
5936 + u8 build;
5937 +} __attribute__((packed));
5938 +
5939 +struct mib_mdomain {
5940 + u8 tx_powerlevel[14];
5941 + u8 channel_list[14]; /* 0 for invalid channels */
5942 +} __attribute__((packed));
5943 +
5944 +struct at76_fw_header {
5945 + __le32 crc; /* CRC32 of the whole image */
5946 + __le32 board_type; /* firmware compatibility code */
5947 + u8 build; /* firmware build number */
5948 + u8 patch; /* firmware patch level */
5949 + u8 minor; /* firmware minor version */
5950 + u8 major; /* firmware major version */
5951 + __le32 str_offset; /* offset of the copyright string */
5952 + __le32 int_fw_offset; /* internal firmware image offset */
5953 + __le32 int_fw_len; /* internal firmware image length */
5954 + __le32 ext_fw_offset; /* external firmware image offset */
5955 + __le32 ext_fw_len; /* external firmware image length */
5956 +} __attribute__((packed));
5957 +
5958 +enum mac_state {
5959 + MAC_INIT,
5960 + MAC_SCANNING,
5961 + MAC_AUTH,
5962 + MAC_ASSOC,
5963 + MAC_JOINING,
5964 + MAC_CONNECTED,
5965 + MAC_OWN_IBSS
5966 +};
5967 +
5968 +/* a description of a regulatory domain and the allowed channels */
5969 +struct reg_domain {
5970 + u16 code;
5971 + char const *name;
5972 + u32 channel_map; /* if bit N is set, channel (N+1) is allowed */
5973 +};
5974 +
5975 +/* how long do we keep a (I)BSS in the bss_list in jiffies
5976 + this should be long enough for the user to retrieve the table
5977 + (by iwlist ?) after the device started, because all entries from
5978 + other channels than the one the device locks on get removed, too */
5979 +#define BSS_LIST_TIMEOUT (120 * HZ)
5980 +/* struct to store BSS info found during scan */
5981 +#define BSS_LIST_MAX_RATE_LEN 32 /* 32 rates should be enough ... */
5982 +
5983 +struct bss_info {
5984 + struct list_head list;
5985 +
5986 + u8 bssid[ETH_ALEN]; /* bssid */
5987 + u8 ssid[IW_ESSID_MAX_SIZE]; /* essid */
5988 + u8 ssid_len; /* length of ssid above */
5989 + u8 channel;
5990 + u16 capa; /* BSS capabilities */
5991 + u16 beacon_interval; /* beacon interval, Kus (1024 microseconds) */
5992 + u8 rates[BSS_LIST_MAX_RATE_LEN]; /* supported rates in units of
5993 + 500 kbps, ORed with 0x80 for
5994 + basic rates */
5995 + u8 rates_len;
5996 +
5997 + /* quality of received beacon */
5998 + u8 rssi;
5999 + u8 link_qual;
6000 + u8 noise_level;
6001 +
6002 + unsigned long last_rx; /* time (jiffies) of last beacon received */
6003 +};
6004 +
6005 +/* a rx data buffer to collect rx fragments */
6006 +struct rx_data_buf {
6007 + u8 sender[ETH_ALEN]; /* sender address */
6008 + u16 seqnr; /* sequence number */
6009 + u16 fragnr; /* last fragment received */
6010 + unsigned long last_rx; /* jiffies of last rx */
6011 + struct sk_buff *skb; /* == NULL if entry is free */
6012 +};
6013 +
6014 +#define NR_RX_DATA_BUF 8
6015 +
6016 +/* Data for one loaded firmware file */
6017 +struct fwentry {
6018 + const char *const fwname;
6019 + const struct firmware *fw;
6020 + int extfw_size;
6021 + int intfw_size;
6022 + /* pointer to loaded firmware, no need to free */
6023 + u8 *extfw; /* external firmware, extfw_size bytes long */
6024 + u8 *intfw; /* internal firmware, intfw_size bytes long */
6025 + enum board_type board_type; /* board type */
6026 + struct mib_fw_version fw_version;
6027 + int loaded; /* Loaded and parsed successfully */
6028 +};
6029 +
6030 +struct at76_priv {
6031 + struct usb_device *udev; /* USB device pointer */
6032 + struct net_device *netdev; /* net device pointer */
6033 + struct net_device_stats stats; /* net device stats */
6034 + struct iw_statistics wstats; /* wireless stats */
6035 +
6036 + struct sk_buff *rx_skb; /* skbuff for receiving data */
6037 + void *bulk_out_buffer; /* buffer for sending data */
6038 +
6039 + struct urb *tx_urb; /* URB for sending data */
6040 + struct urb *rx_urb; /* URB for receiving data */
6041 +
6042 + unsigned int tx_pipe; /* bulk out pipe */
6043 + unsigned int rx_pipe; /* bulk in pipe */
6044 +
6045 + struct mutex mtx; /* locks this structure */
6046 +
6047 + /* work queues */
6048 + struct work_struct work_assoc_done;
6049 + struct work_struct work_join;
6050 + struct work_struct work_new_bss;
6051 + struct work_struct work_start_scan;
6052 + struct work_struct work_set_promisc;
6053 + struct work_struct work_submit_rx;
6054 + struct delayed_work dwork_restart;
6055 + struct delayed_work dwork_get_scan;
6056 + struct delayed_work dwork_beacon;
6057 + struct delayed_work dwork_auth;
6058 + struct delayed_work dwork_assoc;
6059 +
6060 + struct tasklet_struct rx_tasklet;
6061 +
6062 + /* the WEP stuff */
6063 + int wep_enabled; /* 1 if WEP is enabled */
6064 + int wep_key_id; /* key id to be used */
6065 + u8 wep_keys[WEP_KEYS][WEP_KEY_LEN]; /* the four WEP keys,
6066 + 5 or 13 bytes are used */
6067 + u8 wep_keys_len[WEP_KEYS]; /* the length of the above keys */
6068 +
6069 + int channel;
6070 + int iw_mode;
6071 + u8 bssid[ETH_ALEN];
6072 + u8 essid[IW_ESSID_MAX_SIZE];
6073 + int essid_size;
6074 + int radio_on;
6075 + int promisc;
6076 +
6077 + int preamble_type; /* 0 - long, 1 - short, 2 - auto */
6078 + int auth_mode; /* authentication type: 0 open, 1 shared key */
6079 + int txrate; /* 0,1,2,3 = 1,2,5.5,11 Mbps, 4 is auto */
6080 + int frag_threshold; /* threshold for fragmentation of tx packets */
6081 + int rts_threshold; /* threshold for RTS mechanism */
6082 + int short_retry_limit;
6083 +
6084 + int scan_min_time; /* scan min channel time */
6085 + int scan_max_time; /* scan max channel time */
6086 + int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
6087 + int scan_need_any; /* if set, need to scan for any ESSID */
6088 +
6089 + /* the list we got from scanning */
6090 + spinlock_t bss_list_spinlock; /* protects bss_list operations */
6091 + struct list_head bss_list; /* list of BSS we got beacons from */
6092 + struct timer_list bss_list_timer; /* timer to purge old entries
6093 + from bss_list */
6094 + struct bss_info *curr_bss; /* current BSS */
6095 + u16 assoc_id; /* current association ID, if associated */
6096 +
6097 + u8 wanted_bssid[ETH_ALEN];
6098 + int wanted_bssid_valid; /* != 0 if wanted_bssid is to be used */
6099 +
6100 + /* some data for infrastructure mode only */
6101 + spinlock_t mgmt_spinlock; /* this spinlock protects access to
6102 + next_mgmt_bulk */
6103 +
6104 + struct at76_tx_buffer *next_mgmt_bulk; /* pending management msg to
6105 + send via bulk out */
6106 + enum mac_state mac_state;
6107 + enum {
6108 + SCAN_IDLE,
6109 + SCAN_IN_PROGRESS,
6110 + SCAN_COMPLETED
6111 + } scan_state;
6112 + time_t last_scan;
6113 +
6114 + int retries; /* remaining retries in case of timeout when
6115 + * sending AuthReq or AssocReq */
6116 + u8 pm_mode; /* power management mode */
6117 + u32 pm_period; /* power management period in microseconds */
6118 +
6119 + struct reg_domain const *domain; /* reg domain description */
6120 +
6121 + /* iwspy support */
6122 + spinlock_t spy_spinlock;
6123 + struct iw_spy_data spy_data;
6124 +
6125 + struct iw_public_data wireless_data;
6126 +
6127 + /* These fields contain HW config provided by the device (not all of
6128 + * these fields are used by all board types) */
6129 + u8 mac_addr[ETH_ALEN];
6130 + u8 regulatory_domain;
6131 +
6132 + struct at76_card_config card_config;
6133 +
6134 + /* store rx fragments until complete */
6135 + struct rx_data_buf rx_data[NR_RX_DATA_BUF];
6136 +
6137 + enum board_type board_type;
6138 + struct mib_fw_version fw_version;
6139 +
6140 + unsigned int device_unplugged:1;
6141 + unsigned int netdev_registered:1;
6142 + struct set_mib_buffer mib_buf; /* global buffer for set_mib calls */
6143 +
6144 + /* beacon counting */
6145 + int beacon_period; /* period of mgmt beacons, Kus */
6146 + int beacons_received;
6147 + unsigned long beacons_last_qual; /* time we restarted counting
6148 + beacons */
6149 +};
6150 +
6151 +struct at76_rx_radiotap {
6152 + struct ieee80211_radiotap_header rt_hdr;
6153 + __le64 rt_tsft;
6154 + u8 rt_flags;
6155 + u8 rt_rate;
6156 + s8 rt_signal;
6157 + s8 rt_noise;
6158 +};
6159 +
6160 +#define AT76_RX_RADIOTAP_PRESENT \
6161 + ((1 << IEEE80211_RADIOTAP_TSFT) | \
6162 + (1 << IEEE80211_RADIOTAP_FLAGS) | \
6163 + (1 << IEEE80211_RADIOTAP_RATE) | \
6164 + (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
6165 + (1 << IEEE80211_RADIOTAP_DB_ANTNOISE))
6166 +
6167 +#define BEACON_MAX_DATA_LENGTH 1500
6168 +
6169 +/* the maximum size of an AssocReq packet */
6170 +#define ASSOCREQ_MAX_SIZE \
6171 + (AT76_TX_HDRLEN + sizeof(struct ieee80211_assoc_request) + \
6172 + 1 + 1 + IW_ESSID_MAX_SIZE + 1 + 1 + 4)
6173 +
6174 +/* for shared secret auth, add the challenge text size */
6175 +#define AUTH_FRAME_SIZE (AT76_TX_HDRLEN + sizeof(struct ieee80211_auth))
6176 +
6177 +/* Maximal number of AuthReq retries */
6178 +#define AUTH_RETRIES 3
6179 +
6180 +/* Maximal number of AssocReq retries */
6181 +#define ASSOC_RETRIES 3
6182 +
6183 +/* Beacon timeout in managed mode when we are connected */
6184 +#define BEACON_TIMEOUT (10 * HZ)
6185 +
6186 +/* Timeout for authentication response */
6187 +#define AUTH_TIMEOUT (1 * HZ)
6188 +
6189 +/* Timeout for association response */
6190 +#define ASSOC_TIMEOUT (1 * HZ)
6191 +
6192 +/* Polling interval when scan is running */
6193 +#define SCAN_POLL_INTERVAL (HZ / 4)
6194 +
6195 +/* Command completion timeout */
6196 +#define CMD_COMPLETION_TIMEOUT (5 * HZ)
6197 +
6198 +#define DEF_RTS_THRESHOLD 1536
6199 +#define DEF_FRAG_THRESHOLD 1536
6200 +#define DEF_SHORT_RETRY_LIMIT 8
6201 +#define DEF_CHANNEL 10
6202 +#define DEF_SCAN_MIN_TIME 10
6203 +#define DEF_SCAN_MAX_TIME 120
6204 +
6205 +#define MAX_RTS_THRESHOLD (MAX_FRAG_THRESHOLD + 1)
6206 +
6207 +/* the max padding size for tx in bytes (see calc_padding) */
6208 +#define MAX_PADDING_SIZE 53
6209 +
6210 +#endif /* _AT76_USB_H */
6211 --- /dev/null
6212 +++ b/drivers/staging/at76_usb/Kconfig
6213 @@ -0,0 +1,8 @@
6214 +config USB_ATMEL
6215 + tristate "Atmel at76c503/at76c505/at76c505a USB cards"
6216 + depends on WLAN_80211 && USB
6217 + default N
6218 + select FW_LOADER
6219 + ---help---
6220 + Enable support for USB Wireless devices using Atmel at76c503,
6221 + at76c505 or at76c505a chips.
6222 --- /dev/null
6223 +++ b/drivers/staging/at76_usb/Makefile
6224 @@ -0,0 +1 @@
6225 +obj-$(CONFIG_USB_ATMEL) += at76_usb.o
6226 --- /dev/null
6227 +++ b/drivers/staging/at76_usb/TODO
6228 @@ -0,0 +1,2 @@
6229 +rewrite the driver to use the proper in-kernel wireless stack
6230 +instead of using its own.
6231 --- a/drivers/staging/Kconfig
6232 +++ b/drivers/staging/Kconfig
6233 @@ -41,4 +41,6 @@ source "drivers/staging/wlan-ng/Kconfig"
6234
6235 source "drivers/staging/echo/Kconfig"
6236
6237 +source "drivers/staging/at76_usb/Kconfig"
6238 +
6239 endif # STAGING
6240 --- a/drivers/staging/Makefile
6241 +++ b/drivers/staging/Makefile
6242 @@ -12,3 +12,4 @@ obj-$(CONFIG_USB_IP_COMMON) += usbip/
6243 obj-$(CONFIG_W35UND) += winbond/
6244 obj-$(CONFIG_PRISM2_USB) += wlan-ng/
6245 obj-$(CONFIG_ECHO) += echo/
6246 +obj-$(CONFIG_USB_ATMEL) += at76_usb/