blob: c2789e53b9845629f8d9b5eaef9e2f37febdda13 [file] [log] [blame]
Michael Wueff1a592007-09-25 18:11:01 -07001
2/*
3 * Linux device driver for USB based Prism54
4 *
5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
6 *
7 * Based on the islsm (softmac prism54) driver, which is:
8 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/usb.h>
17#include <linux/pci.h>
18#include <linux/firmware.h>
19#include <linux/etherdevice.h>
20#include <linux/delay.h>
21#include <linux/crc32.h>
22#include <net/mac80211.h>
23
24#include "p54.h"
25#include "p54usb.h"
26
27MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
28MODULE_DESCRIPTION("Prism54 USB wireless driver");
29MODULE_LICENSE("GPL");
30MODULE_ALIAS("prism54usb");
Christian Lamparter9a8675d2008-10-18 23:04:15 +020031MODULE_FIRMWARE("isl3886usb");
32MODULE_FIRMWARE("isl3887usb");
Michael Wueff1a592007-09-25 18:11:01 -070033
34static struct usb_device_id p54u_table[] __devinitdata = {
35 /* Version 1 devices (pci chip + net2280) */
36 {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
37 {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
38 {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
39 {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
Ivo Couckuyt1a175822008-02-20 14:58:00 -050040 {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
Michael Wueff1a592007-09-25 18:11:01 -070041 {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
42 {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
43 {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
Christian Lamparterec366eb2008-10-13 23:41:53 +020044 {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
Michael Wueff1a592007-09-25 18:11:01 -070045 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
46 {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
47 {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
48 {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
49 {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
50 {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
51 {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
52 {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
53
54 /* Version 2 devices (3887) */
Felix Homann45460022008-05-29 00:36:45 -070055 {USB_DEVICE(0x0471, 0x1230)}, /* Philips CPWUA054/00 */
Michael Wueff1a592007-09-25 18:11:01 -070056 {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
57 {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
58 {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
59 {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
60 {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
61 {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
62 {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
63 {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
64 {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
65 {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
66 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
67 {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
68 {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
Jan Slupski43557e12008-03-10 22:41:18 -070069 {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
Christian Lamparterec366eb2008-10-13 23:41:53 +020070 {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */
John W. Linville387e1002008-02-20 15:06:02 -050071 {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
Martti Huttunenc1098102007-10-04 00:06:00 -040072 {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
Michael Wueff1a592007-09-25 18:11:01 -070073 {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
74 {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
75 {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
76 {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
77 {}
78};
79
80MODULE_DEVICE_TABLE(usb, p54u_table);
81
82static void p54u_rx_cb(struct urb *urb)
83{
84 struct sk_buff *skb = (struct sk_buff *) urb->context;
85 struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
86 struct ieee80211_hw *dev = info->dev;
87 struct p54u_priv *priv = dev->priv;
88
Christian Lamparterdd397dc2008-12-09 15:14:37 +010089 skb_unlink(skb, &priv->rx_queue);
90
Michael Wueff1a592007-09-25 18:11:01 -070091 if (unlikely(urb->status)) {
Christian Lamparterdd397dc2008-12-09 15:14:37 +010092 dev_kfree_skb_irq(skb);
Michael Wueff1a592007-09-25 18:11:01 -070093 return;
94 }
95
Michael Wueff1a592007-09-25 18:11:01 -070096 skb_put(skb, urb->actual_length);
Christian Lamparter2b808482008-09-04 12:29:38 +020097
98 if (priv->hw_type == P54U_NET2280)
99 skb_pull(skb, priv->common.tx_hdr_len);
100 if (priv->common.fw_interface == FW_LM87) {
101 skb_pull(skb, 4);
102 skb_put(skb, 4);
103 }
Michael Wueff1a592007-09-25 18:11:01 -0700104
105 if (p54_rx(dev, skb)) {
Christian Lamparter4e416a62008-09-01 22:48:41 +0200106 skb = dev_alloc_skb(priv->common.rx_mtu + 32);
Michael Wueff1a592007-09-25 18:11:01 -0700107 if (unlikely(!skb)) {
Michael Wueff1a592007-09-25 18:11:01 -0700108 /* TODO check rx queue length and refill *somewhere* */
109 return;
110 }
111
112 info = (struct p54u_rx_info *) skb->cb;
113 info->urb = urb;
114 info->dev = dev;
115 urb->transfer_buffer = skb_tail_pointer(skb);
116 urb->context = skb;
Michael Wueff1a592007-09-25 18:11:01 -0700117 } else {
Christian Lamparter2b808482008-09-04 12:29:38 +0200118 if (priv->hw_type == P54U_NET2280)
119 skb_push(skb, priv->common.tx_hdr_len);
120 if (priv->common.fw_interface == FW_LM87) {
121 skb_push(skb, 4);
122 skb_put(skb, 4);
123 }
Christian Lamparterd47c3ce2008-08-13 23:41:48 +0200124 skb_reset_tail_pointer(skb);
Michael Wueff1a592007-09-25 18:11:01 -0700125 skb_trim(skb, 0);
Christian Lamparterd47c3ce2008-08-13 23:41:48 +0200126 if (urb->transfer_buffer != skb_tail_pointer(skb)) {
127 /* this should not happen */
128 WARN_ON(1);
129 urb->transfer_buffer = skb_tail_pointer(skb);
130 }
Michael Wueff1a592007-09-25 18:11:01 -0700131 }
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100132 skb_queue_tail(&priv->rx_queue, skb);
133 usb_anchor_urb(urb, &priv->submitted);
134 if (usb_submit_urb(urb, GFP_ATOMIC)) {
135 skb_unlink(skb, &priv->rx_queue);
136 usb_unanchor_urb(urb);
137 dev_kfree_skb_irq(skb);
138 }
Michael Wueff1a592007-09-25 18:11:01 -0700139}
140
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200141static void p54u_tx_reuse_skb_cb(struct urb *urb)
142{
143 struct sk_buff *skb = urb->context;
144 struct p54u_priv *priv = (struct p54u_priv *)((struct ieee80211_hw *)
145 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv;
146
147 skb_pull(skb, priv->common.tx_hdr_len);
Michael Wueff1a592007-09-25 18:11:01 -0700148}
149
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200150static void p54u_tx_free_skb_cb(struct urb *urb)
151{
152 struct sk_buff *skb = urb->context;
153 struct ieee80211_hw *dev = (struct ieee80211_hw *)
154 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
155
156 p54_free_skb(dev, skb);
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100157}
158
159static void p54u_tx_dummy_cb(struct urb *urb) { }
160
161static void p54u_free_urbs(struct ieee80211_hw *dev)
162{
163 struct p54u_priv *priv = dev->priv;
164 usb_kill_anchored_urbs(&priv->submitted);
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200165}
166
Michael Wueff1a592007-09-25 18:11:01 -0700167static int p54u_init_urbs(struct ieee80211_hw *dev)
168{
169 struct p54u_priv *priv = dev->priv;
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100170 struct urb *entry = NULL;
Michael Wueff1a592007-09-25 18:11:01 -0700171 struct sk_buff *skb;
172 struct p54u_rx_info *info;
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100173 int ret = 0;
Michael Wueff1a592007-09-25 18:11:01 -0700174
175 while (skb_queue_len(&priv->rx_queue) < 32) {
Christian Lamparter4e416a62008-09-01 22:48:41 +0200176 skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100177 if (!skb) {
178 ret = -ENOMEM;
179 goto err;
180 }
Michael Wueff1a592007-09-25 18:11:01 -0700181 entry = usb_alloc_urb(0, GFP_KERNEL);
182 if (!entry) {
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100183 ret = -ENOMEM;
184 goto err;
Michael Wueff1a592007-09-25 18:11:01 -0700185 }
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100186
Christian Lamparter4e416a62008-09-01 22:48:41 +0200187 usb_fill_bulk_urb(entry, priv->udev,
188 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
189 skb_tail_pointer(skb),
190 priv->common.rx_mtu + 32, p54u_rx_cb, skb);
Michael Wueff1a592007-09-25 18:11:01 -0700191 info = (struct p54u_rx_info *) skb->cb;
192 info->urb = entry;
193 info->dev = dev;
194 skb_queue_tail(&priv->rx_queue, skb);
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100195
196 usb_anchor_urb(entry, &priv->submitted);
197 ret = usb_submit_urb(entry, GFP_KERNEL);
198 if (ret) {
199 skb_unlink(skb, &priv->rx_queue);
200 usb_unanchor_urb(entry);
201 goto err;
202 }
203 usb_free_urb(entry);
204 entry = NULL;
Michael Wueff1a592007-09-25 18:11:01 -0700205 }
206
207 return 0;
Michael Wueff1a592007-09-25 18:11:01 -0700208
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100209 err:
210 usb_free_urb(entry);
211 kfree_skb(skb);
212 p54u_free_urbs(dev);
213 return ret;
Michael Wueff1a592007-09-25 18:11:01 -0700214}
215
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200216static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
217 int free_on_tx)
Michael Wueff1a592007-09-25 18:11:01 -0700218{
219 struct p54u_priv *priv = dev->priv;
220 struct urb *addr_urb, *data_urb;
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100221 int err = 0;
Michael Wueff1a592007-09-25 18:11:01 -0700222
223 addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
224 if (!addr_urb)
225 return;
226
227 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
228 if (!data_urb) {
229 usb_free_urb(addr_urb);
230 return;
231 }
232
233 usb_fill_bulk_urb(addr_urb, priv->udev,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200234 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
John W. Linville27df6052008-10-22 16:41:55 -0400235 &((struct p54_hdr *)skb->data)->req_id, 4,
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100236 p54u_tx_dummy_cb, dev);
Michael Wueff1a592007-09-25 18:11:01 -0700237 usb_fill_bulk_urb(data_urb, priv->udev,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200238 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
239 skb->data, skb->len,
240 free_on_tx ? p54u_tx_free_skb_cb :
241 p54u_tx_reuse_skb_cb, skb);
Michael Wueff1a592007-09-25 18:11:01 -0700242
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100243 usb_anchor_urb(addr_urb, &priv->submitted);
244 err = usb_submit_urb(addr_urb, GFP_ATOMIC);
245 if (err) {
246 usb_unanchor_urb(addr_urb);
247 goto out;
248 }
249
250 usb_anchor_urb(addr_urb, &priv->submitted);
251 err = usb_submit_urb(data_urb, GFP_ATOMIC);
252 if (err)
253 usb_unanchor_urb(data_urb);
254
255 out:
256 usb_free_urb(addr_urb);
257 usb_free_urb(data_urb);
258
259 if (err)
260 p54_free_skb(dev, skb);
Michael Wueff1a592007-09-25 18:11:01 -0700261}
262
Johannes Bergc9127652008-12-01 18:19:36 +0100263static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
Christian Lamparter2b808482008-09-04 12:29:38 +0200264{
Larry Finger1f1c0e32008-09-25 14:54:28 -0500265 u32 chk = 0;
Christian Lamparter2b808482008-09-04 12:29:38 +0200266
267 length >>= 2;
268 while (length--) {
Johannes Bergc9127652008-12-01 18:19:36 +0100269 chk ^= le32_to_cpu(*data++);
Christian Lamparter2b808482008-09-04 12:29:38 +0200270 chk = (chk >> 5) ^ (chk << 3);
271 }
272
Larry Finger1f1c0e32008-09-25 14:54:28 -0500273 return cpu_to_le32(chk);
Christian Lamparter2b808482008-09-04 12:29:38 +0200274}
275
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200276static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb,
277 int free_on_tx)
Christian Lamparter2b808482008-09-04 12:29:38 +0200278{
279 struct p54u_priv *priv = dev->priv;
280 struct urb *data_urb;
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200281 struct lm87_tx_hdr *hdr;
282 __le32 checksum;
John W. Linville27df6052008-10-22 16:41:55 -0400283 __le32 addr = ((struct p54_hdr *)skb->data)->req_id;
Christian Lamparter2b808482008-09-04 12:29:38 +0200284
285 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
286 if (!data_urb)
287 return;
288
Johannes Bergc9127652008-12-01 18:19:36 +0100289 checksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200290 hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr));
291 hdr->chksum = checksum;
292 hdr->device_addr = addr;
Christian Lamparter2b808482008-09-04 12:29:38 +0200293
294 usb_fill_bulk_urb(data_urb, priv->udev,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200295 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
296 skb->data, skb->len,
297 free_on_tx ? p54u_tx_free_skb_cb :
298 p54u_tx_reuse_skb_cb, skb);
Christian Lamparter2b808482008-09-04 12:29:38 +0200299
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100300 usb_anchor_urb(data_urb, &priv->submitted);
301 if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
302 usb_unanchor_urb(data_urb);
303 skb_pull(skb, sizeof(*hdr));
304 p54_free_skb(dev, skb);
305 }
306 usb_free_urb(data_urb);
Christian Lamparter2b808482008-09-04 12:29:38 +0200307}
308
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200309static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
310 int free_on_tx)
Michael Wueff1a592007-09-25 18:11:01 -0700311{
312 struct p54u_priv *priv = dev->priv;
313 struct urb *int_urb, *data_urb;
314 struct net2280_tx_hdr *hdr;
315 struct net2280_reg_write *reg;
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100316 int err = 0;
Michael Wueff1a592007-09-25 18:11:01 -0700317
318 reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
319 if (!reg)
320 return;
321
322 int_urb = usb_alloc_urb(0, GFP_ATOMIC);
323 if (!int_urb) {
324 kfree(reg);
325 return;
326 }
327
328 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
329 if (!data_urb) {
330 kfree(reg);
331 usb_free_urb(int_urb);
332 return;
333 }
334
335 reg->port = cpu_to_le16(NET2280_DEV_U32);
336 reg->addr = cpu_to_le32(P54U_DEV_BASE);
337 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
338
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200339 hdr = (void *)skb_push(skb, sizeof(*hdr));
Michael Wueff1a592007-09-25 18:11:01 -0700340 memset(hdr, 0, sizeof(*hdr));
John W. Linville27df6052008-10-22 16:41:55 -0400341 hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
342 hdr->len = cpu_to_le16(skb->len + sizeof(struct p54_hdr));
Michael Wueff1a592007-09-25 18:11:01 -0700343
344 usb_fill_bulk_urb(int_urb, priv->udev,
345 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100346 p54u_tx_dummy_cb, dev);
347
348 /*
349 * This flag triggers a code path in the USB subsystem that will
350 * free what's inside the transfer_buffer after the callback routine
351 * has completed.
352 */
353 int_urb->transfer_flags |= URB_FREE_BUFFER;
Michael Wueff1a592007-09-25 18:11:01 -0700354
355 usb_fill_bulk_urb(data_urb, priv->udev,
Christian Lamparterb92f30d2008-10-15 04:07:16 +0200356 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
357 skb->data, skb->len,
358 free_on_tx ? p54u_tx_free_skb_cb :
359 p54u_tx_reuse_skb_cb, skb);
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100360
361 usb_anchor_urb(int_urb, &priv->submitted);
362 err = usb_submit_urb(int_urb, GFP_ATOMIC);
363 if (err) {
364 usb_unanchor_urb(int_urb);
365 goto out;
366 }
367
368 usb_anchor_urb(data_urb, &priv->submitted);
369 err = usb_submit_urb(data_urb, GFP_ATOMIC);
370 if (err) {
371 usb_unanchor_urb(data_urb);
372 goto out;
373 }
374 out:
375 usb_free_urb(int_urb);
376 usb_free_urb(data_urb);
377
378 if (err) {
379 skb_pull(skb, sizeof(*hdr));
380 p54_free_skb(dev, skb);
381 }
Michael Wueff1a592007-09-25 18:11:01 -0700382}
383
384static int p54u_write(struct p54u_priv *priv,
385 struct net2280_reg_write *buf,
386 enum net2280_op_type type,
387 __le32 addr, __le32 val)
388{
389 unsigned int ep;
390 int alen;
391
392 if (type & 0x0800)
393 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
394 else
395 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
396
397 buf->port = cpu_to_le16(type);
398 buf->addr = addr;
399 buf->val = val;
400
401 return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
402}
403
404static int p54u_read(struct p54u_priv *priv, void *buf,
405 enum net2280_op_type type,
406 __le32 addr, __le32 *val)
407{
408 struct net2280_reg_read *read = buf;
409 __le32 *reg = buf;
410 unsigned int ep;
411 int alen, err;
412
413 if (type & 0x0800)
414 ep = P54U_PIPE_DEV;
415 else
416 ep = P54U_PIPE_BRG;
417
418 read->port = cpu_to_le16(type);
419 read->addr = addr;
420
421 err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
422 read, sizeof(*read), &alen, 1000);
423 if (err)
424 return err;
425
426 err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
427 reg, sizeof(*reg), &alen, 1000);
428 if (err)
429 return err;
430
431 *val = *reg;
432 return 0;
433}
434
435static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
436 void *data, size_t len)
437{
438 int alen;
439 return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
440 data, len, &alen, 2000);
441}
442
Michael Wueff1a592007-09-25 18:11:01 -0700443static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
444{
445 static char start_string[] = "~~~~<\r";
446 struct p54u_priv *priv = dev->priv;
447 const struct firmware *fw_entry = NULL;
448 int err, alen;
449 u8 carry = 0;
David Woodhouse8b72eb42008-05-24 00:08:55 +0100450 u8 *buf, *tmp;
451 const u8 *data;
Michael Wueff1a592007-09-25 18:11:01 -0700452 unsigned int left, remains, block_size;
453 struct x2_header *hdr;
454 unsigned long timeout;
455
456 tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
457 if (!buf) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100458 dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
459 "upload buffer!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700460 err = -ENOMEM;
461 goto err_bufalloc;
462 }
463
464 memcpy(buf, start_string, 4);
465 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
466 if (err) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100467 dev_err(&priv->udev->dev, "(p54usb) reset failed! (%d)\n", err);
Michael Wueff1a592007-09-25 18:11:01 -0700468 goto err_reset;
469 }
470
Christian Lamparter9a8675d2008-10-18 23:04:15 +0200471 err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
Michael Wueff1a592007-09-25 18:11:01 -0700472 if (err) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100473 dev_err(&priv->udev->dev, "p54usb: cannot find firmware "
474 "(isl3887usb)\n");
Christian Lamparter9a8675d2008-10-18 23:04:15 +0200475 err = request_firmware(&fw_entry, "isl3887usb_bare",
476 &priv->udev->dev);
477 if (err)
478 goto err_req_fw_failed;
Michael Wueff1a592007-09-25 18:11:01 -0700479 }
480
Christian Lamparter4e416a62008-09-01 22:48:41 +0200481 err = p54_parse_firmware(dev, fw_entry);
482 if (err)
483 goto err_upload_failed;
Michael Wueff1a592007-09-25 18:11:01 -0700484
485 left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
486 strcpy(buf, start_string);
487 left -= strlen(start_string);
488 tmp += strlen(start_string);
489
490 data = fw_entry->data;
491 remains = fw_entry->size;
492
493 hdr = (struct x2_header *)(buf + strlen(start_string));
494 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
495 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
496 hdr->fw_length = cpu_to_le32(fw_entry->size);
497 hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
498 sizeof(u32)*2));
499 left -= sizeof(*hdr);
500 tmp += sizeof(*hdr);
501
502 while (remains) {
503 while (left--) {
504 if (carry) {
505 *tmp++ = carry;
506 carry = 0;
507 remains--;
508 continue;
509 }
510 switch (*data) {
511 case '~':
512 *tmp++ = '}';
513 carry = '^';
514 break;
515 case '}':
516 *tmp++ = '}';
517 carry = ']';
518 break;
519 default:
520 *tmp++ = *data;
521 remains--;
522 break;
523 }
524 data++;
525 }
526
527 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
528 if (err) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100529 dev_err(&priv->udev->dev, "(p54usb) firmware "
530 "upload failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700531 goto err_upload_failed;
532 }
533
534 tmp = buf;
535 left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
536 }
537
538 *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
539 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
540 if (err) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100541 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700542 goto err_upload_failed;
543 }
Michael Wueff1a592007-09-25 18:11:01 -0700544 timeout = jiffies + msecs_to_jiffies(1000);
545 while (!(err = usb_bulk_msg(priv->udev,
546 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
547 if (alen > 2 && !memcmp(buf, "OK", 2))
548 break;
549
550 if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
Michael Wueff1a592007-09-25 18:11:01 -0700551 err = -EINVAL;
552 break;
553 }
554
555 if (time_after(jiffies, timeout)) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100556 dev_err(&priv->udev->dev, "(p54usb) firmware boot "
557 "timed out!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700558 err = -ETIMEDOUT;
559 break;
560 }
561 }
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100562 if (err) {
563 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700564 goto err_upload_failed;
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100565 }
Michael Wueff1a592007-09-25 18:11:01 -0700566
567 buf[0] = 'g';
568 buf[1] = '\r';
569 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
570 if (err) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100571 dev_err(&priv->udev->dev, "(p54usb) firmware boot failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700572 goto err_upload_failed;
573 }
574
575 timeout = jiffies + msecs_to_jiffies(1000);
576 while (!(err = usb_bulk_msg(priv->udev,
577 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
578 if (alen > 0 && buf[0] == 'g')
579 break;
580
581 if (time_after(jiffies, timeout)) {
582 err = -ETIMEDOUT;
583 break;
584 }
585 }
586 if (err)
587 goto err_upload_failed;
588
589 err_upload_failed:
590 release_firmware(fw_entry);
591 err_req_fw_failed:
592 err_reset:
593 kfree(buf);
594 err_bufalloc:
595 return err;
596}
597
598static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
599{
600 struct p54u_priv *priv = dev->priv;
601 const struct firmware *fw_entry = NULL;
602 const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
603 int err, alen;
604 void *buf;
605 __le32 reg;
606 unsigned int remains, offset;
David Woodhouse8b72eb42008-05-24 00:08:55 +0100607 const u8 *data;
Michael Wueff1a592007-09-25 18:11:01 -0700608
609 buf = kmalloc(512, GFP_KERNEL);
610 if (!buf) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100611 dev_err(&priv->udev->dev, "(p54usb) firmware buffer "
612 "alloc failed!\n");
Michael Wueff1a592007-09-25 18:11:01 -0700613 return -ENOMEM;
614 }
615
Christian Lamparter9a8675d2008-10-18 23:04:15 +0200616 err = request_firmware(&fw_entry, "isl3886usb", &priv->udev->dev);
Michael Wueff1a592007-09-25 18:11:01 -0700617 if (err) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100618 dev_err(&priv->udev->dev, "(p54usb) cannot find firmware "
619 "(isl3886usb)\n");
Christian Lamparter9a8675d2008-10-18 23:04:15 +0200620 err = request_firmware(&fw_entry, "isl3890usb",
621 &priv->udev->dev);
622 if (err) {
623 kfree(buf);
624 return err;
625 }
Michael Wueff1a592007-09-25 18:11:01 -0700626 }
627
Christian Lamparter4e416a62008-09-01 22:48:41 +0200628 err = p54_parse_firmware(dev, fw_entry);
629 if (err) {
630 kfree(buf);
631 release_firmware(fw_entry);
632 return err;
633 }
Michael Wueff1a592007-09-25 18:11:01 -0700634
635#define P54U_WRITE(type, addr, data) \
636 do {\
637 err = p54u_write(priv, buf, type,\
638 cpu_to_le32((u32)(unsigned long)addr), data);\
639 if (err) \
640 goto fail;\
641 } while (0)
642
643#define P54U_READ(type, addr) \
644 do {\
645 err = p54u_read(priv, buf, type,\
646 cpu_to_le32((u32)(unsigned long)addr), &reg);\
647 if (err)\
648 goto fail;\
649 } while (0)
650
651 /* power down net2280 bridge */
652 P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
653 reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
654 reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
655 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
656
657 mdelay(100);
658
659 /* power up bridge */
660 reg |= cpu_to_le32(P54U_BRG_POWER_UP);
661 reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
662 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
663
664 mdelay(100);
665
666 P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
667 cpu_to_le32(NET2280_CLK_30Mhz |
668 NET2280_PCI_ENABLE |
669 NET2280_PCI_SOFT_RESET));
670
671 mdelay(20);
672
673 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
674 cpu_to_le32(PCI_COMMAND_MEMORY |
675 PCI_COMMAND_MASTER));
676
677 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
678 cpu_to_le32(NET2280_BASE));
679
680 P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
681 reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
682 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
683
684 // TODO: we really need this?
685 P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
686
687 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
688 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
689 P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
690 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
691
692 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
693 cpu_to_le32(NET2280_BASE2));
694
695 /* finally done setting up the bridge */
696
697 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
698 cpu_to_le32(PCI_COMMAND_MEMORY |
699 PCI_COMMAND_MASTER));
700
701 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
702 P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
703 cpu_to_le32(P54U_DEV_BASE));
704
705 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
706 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
707 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
708
709 /* do romboot */
710 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
711
712 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
713 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
714 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
715 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
716 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
717
718 mdelay(20);
719
720 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
721 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
722
723 mdelay(20);
724
725 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
726 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
727
728 mdelay(100);
729
730 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
731 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
732
733 /* finally, we can upload firmware now! */
734 remains = fw_entry->size;
735 data = fw_entry->data;
736 offset = ISL38XX_DEV_FIRMWARE_ADDR;
737
738 while (remains) {
739 unsigned int block_len = min(remains, (unsigned int)512);
740 memcpy(buf, data, block_len);
741
742 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
743 if (err) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100744 dev_err(&priv->udev->dev, "(p54usb) firmware block "
745 "upload failed\n");
Michael Wueff1a592007-09-25 18:11:01 -0700746 goto fail;
747 }
748
749 P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
750 cpu_to_le32(0xc0000f00));
751
752 P54U_WRITE(NET2280_DEV_U32,
753 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
754 P54U_WRITE(NET2280_DEV_U32,
755 0x0020 | (unsigned long)&devreg->direct_mem_win,
756 cpu_to_le32(1));
757
758 P54U_WRITE(NET2280_DEV_U32,
759 0x0024 | (unsigned long)&devreg->direct_mem_win,
760 cpu_to_le32(block_len));
761 P54U_WRITE(NET2280_DEV_U32,
762 0x0028 | (unsigned long)&devreg->direct_mem_win,
763 cpu_to_le32(offset));
764
765 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
766 cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
767 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
768 cpu_to_le32(block_len >> 2));
769 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
770 cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
771
772 mdelay(10);
773
774 P54U_READ(NET2280_DEV_U32,
775 0x002C | (unsigned long)&devreg->direct_mem_win);
776 if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
777 !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100778 dev_err(&priv->udev->dev, "(p54usb) firmware DMA "
779 "transfer failed\n");
Michael Wueff1a592007-09-25 18:11:01 -0700780 goto fail;
781 }
782
783 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
784 cpu_to_le32(NET2280_FIFO_FLUSH));
785
786 remains -= block_len;
787 data += block_len;
788 offset += block_len;
789 }
790
791 /* do ramboot */
792 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
793 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
794 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
795 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
796 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
797
798 mdelay(20);
799
800 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
801 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
802
803 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
804 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
805
806 mdelay(100);
807
808 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
809 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
810
811 /* start up the firmware */
812 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
813 cpu_to_le32(ISL38XX_INT_IDENT_INIT));
814
815 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
816 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
817
818 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
819 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
820 NET2280_USB_INTERRUPT_ENABLE));
821
822 P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
823 cpu_to_le32(ISL38XX_DEV_INT_RESET));
824
825 err = usb_interrupt_msg(priv->udev,
826 usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
827 buf, sizeof(__le32), &alen, 1000);
828 if (err || alen != sizeof(__le32))
829 goto fail;
830
831 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
832 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
833
834 if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
835 err = -EINVAL;
836
837 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
838 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
839 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
840
841#undef P54U_WRITE
842#undef P54U_READ
843
844 fail:
845 release_firmware(fw_entry);
846 kfree(buf);
847 return err;
848}
849
850static int p54u_open(struct ieee80211_hw *dev)
851{
852 struct p54u_priv *priv = dev->priv;
853 int err;
854
855 err = p54u_init_urbs(dev);
856 if (err) {
857 return err;
858 }
859
860 priv->common.open = p54u_init_urbs;
861
862 return 0;
863}
864
865static void p54u_stop(struct ieee80211_hw *dev)
866{
867 /* TODO: figure out how to reliably stop the 3887 and net2280 so
868 the hardware is still usable next time we want to start it.
869 until then, we just stop listening to the hardware.. */
870 p54u_free_urbs(dev);
871 return;
872}
873
874static int __devinit p54u_probe(struct usb_interface *intf,
875 const struct usb_device_id *id)
876{
877 struct usb_device *udev = interface_to_usbdev(intf);
878 struct ieee80211_hw *dev;
879 struct p54u_priv *priv;
880 int err;
881 unsigned int i, recognized_pipes;
Michael Wueff1a592007-09-25 18:11:01 -0700882
883 dev = p54_init_common(sizeof(*priv));
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100884
Michael Wueff1a592007-09-25 18:11:01 -0700885 if (!dev) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100886 dev_err(&udev->dev, "(p54usb) ieee80211 alloc failed\n");
Michael Wueff1a592007-09-25 18:11:01 -0700887 return -ENOMEM;
888 }
889
890 priv = dev->priv;
891
892 SET_IEEE80211_DEV(dev, &intf->dev);
893 usb_set_intfdata(intf, dev);
894 priv->udev = udev;
895
896 usb_get_dev(udev);
897
898 /* really lazy and simple way of figuring out if we're a 3887 */
899 /* TODO: should just stick the identification in the device table */
900 i = intf->altsetting->desc.bNumEndpoints;
901 recognized_pipes = 0;
902 while (i--) {
903 switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
904 case P54U_PIPE_DATA:
905 case P54U_PIPE_MGMT:
906 case P54U_PIPE_BRG:
907 case P54U_PIPE_DEV:
908 case P54U_PIPE_DATA | USB_DIR_IN:
909 case P54U_PIPE_MGMT | USB_DIR_IN:
910 case P54U_PIPE_BRG | USB_DIR_IN:
911 case P54U_PIPE_DEV | USB_DIR_IN:
912 case P54U_PIPE_INT | USB_DIR_IN:
913 recognized_pipes++;
914 }
915 }
916 priv->common.open = p54u_open;
Christian Lamparter2b808482008-09-04 12:29:38 +0200917 priv->common.stop = p54u_stop;
Michael Wueff1a592007-09-25 18:11:01 -0700918 if (recognized_pipes < P54U_PIPE_NUMBER) {
919 priv->hw_type = P54U_3887;
Christian Lamparter2b808482008-09-04 12:29:38 +0200920 err = p54u_upload_firmware_3887(dev);
921 if (priv->common.fw_interface == FW_LM87) {
922 dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
923 priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
924 priv->common.tx = p54u_tx_lm87;
925 } else
926 priv->common.tx = p54u_tx_3887;
Michael Wueff1a592007-09-25 18:11:01 -0700927 } else {
Christian Lamparter2b808482008-09-04 12:29:38 +0200928 priv->hw_type = P54U_NET2280;
Michael Wueff1a592007-09-25 18:11:01 -0700929 dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
930 priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
931 priv->common.tx = p54u_tx_net2280;
Michael Wueff1a592007-09-25 18:11:01 -0700932 err = p54u_upload_firmware_net2280(dev);
Christian Lamparter2b808482008-09-04 12:29:38 +0200933 }
Michael Wueff1a592007-09-25 18:11:01 -0700934 if (err)
935 goto err_free_dev;
936
Christian Lamparter7cb77072008-09-01 22:48:51 +0200937 skb_queue_head_init(&priv->rx_queue);
Christian Lamparterdd397dc2008-12-09 15:14:37 +0100938 init_usb_anchor(&priv->submitted);
Christian Lamparter7cb77072008-09-01 22:48:51 +0200939
940 p54u_open(dev);
941 err = p54_read_eeprom(dev);
942 p54u_stop(dev);
Michael Wueff1a592007-09-25 18:11:01 -0700943 if (err)
944 goto err_free_dev;
945
Michael Wueff1a592007-09-25 18:11:01 -0700946 err = ieee80211_register_hw(dev);
947 if (err) {
Christian Lamparter02e37ba2008-11-29 22:39:08 +0100948 dev_err(&udev->dev, "(p54usb) Cannot register netdevice\n");
Michael Wueff1a592007-09-25 18:11:01 -0700949 goto err_free_dev;
950 }
951
Michael Wueff1a592007-09-25 18:11:01 -0700952 return 0;
953
954 err_free_dev:
955 ieee80211_free_hw(dev);
956 usb_set_intfdata(intf, NULL);
957 usb_put_dev(udev);
958 return err;
959}
960
961static void __devexit p54u_disconnect(struct usb_interface *intf)
962{
963 struct ieee80211_hw *dev = usb_get_intfdata(intf);
964 struct p54u_priv *priv;
965
966 if (!dev)
967 return;
968
969 ieee80211_unregister_hw(dev);
970
971 priv = dev->priv;
972 usb_put_dev(interface_to_usbdev(intf));
973 p54_free_common(dev);
974 ieee80211_free_hw(dev);
975}
976
977static struct usb_driver p54u_driver = {
Christian Lamparter32ddf072008-08-08 21:17:37 +0200978 .name = "p54usb",
Michael Wueff1a592007-09-25 18:11:01 -0700979 .id_table = p54u_table,
980 .probe = p54u_probe,
981 .disconnect = p54u_disconnect,
982};
983
984static int __init p54u_init(void)
985{
986 return usb_register(&p54u_driver);
987}
988
989static void __exit p54u_exit(void)
990{
991 usb_deregister(&p54u_driver);
992}
993
994module_init(p54u_init);
995module_exit(p54u_exit);