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