]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/wireless/p54/p54usb.c
drivers/net: Remove unnecessary returns from void function()s
[net-next-2.6.git] / drivers / net / wireless / p54 / p54usb.c
CommitLineData
eff1a59c
MW
1
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>
5a0e3ad6 18#include <linux/slab.h>
eff1a59c
MW
19#include <linux/firmware.h>
20#include <linux/etherdevice.h>
21#include <linux/delay.h>
22#include <linux/crc32.h>
23#include <net/mac80211.h>
24
25#include "p54.h"
d8c92107 26#include "lmac.h"
eff1a59c
MW
27#include "p54usb.h"
28
29MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
30MODULE_DESCRIPTION("Prism54 USB wireless driver");
31MODULE_LICENSE("GPL");
32MODULE_ALIAS("prism54usb");
9a8675d7
CL
33MODULE_FIRMWARE("isl3886usb");
34MODULE_FIRMWARE("isl3887usb");
eff1a59c
MW
35
36static struct usb_device_id p54u_table[] __devinitdata = {
37 /* Version 1 devices (pci chip + net2280) */
38 {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
05a9a161 39 {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */
eff1a59c 40 {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
15a69a81 41 {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */
eff1a59c
MW
42 {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
43 {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
1a17582e 44 {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
eff1a59c
MW
45 {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
46 {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
47 {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
ec366eba 48 {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
eff1a59c
MW
49 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
50 {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
51 {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
52 {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
53 {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
54 {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
55 {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
56 {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
57
58 /* Version 2 devices (3887) */
4546002c 59 {USB_DEVICE(0x0471, 0x1230)}, /* Philips CPWUA054/00 */
eff1a59c
MW
60 {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
61 {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
62 {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
878e6a43 63 {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
eff1a59c
MW
64 {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
65 {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
5b9a919a 66 {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */
eff1a59c
MW
67 {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
68 {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
69 {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
70 {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
71 {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
72 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
73 {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
f7f71173 74 {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */
eff1a59c 75 {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
43557e15 76 {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
ec366eba 77 {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */
387e100a 78 {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
c1098103 79 {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
e3062403 80 {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */
eff1a59c
MW
81 {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
82 {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
83 {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
84 {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
85 {}
86};
87
88MODULE_DEVICE_TABLE(usb, p54u_table);
89
1ca5f2e9
CL
90static const struct {
91 u32 intf;
92 enum p54u_hw_type type;
328d84fb
SO
93 const char *fw;
94 const char *fw_legacy;
1ca5f2e9
CL
95 char hw[20];
96} p54u_fwlist[__NUM_P54U_HWTYPES] = {
97 {
98 .type = P54U_NET2280,
99 .intf = FW_LM86,
100 .fw = "isl3886usb",
101 .fw_legacy = "isl3890usb",
102 .hw = "ISL3886 + net2280",
103 },
104 {
105 .type = P54U_3887,
106 .intf = FW_LM87,
107 .fw = "isl3887usb",
108 .fw_legacy = "isl3887usb_bare",
109 .hw = "ISL3887",
110 },
111};
112
eff1a59c
MW
113static void p54u_rx_cb(struct urb *urb)
114{
115 struct sk_buff *skb = (struct sk_buff *) urb->context;
116 struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
117 struct ieee80211_hw *dev = info->dev;
118 struct p54u_priv *priv = dev->priv;
119
dd397dc9
CL
120 skb_unlink(skb, &priv->rx_queue);
121
eff1a59c 122 if (unlikely(urb->status)) {
dd397dc9 123 dev_kfree_skb_irq(skb);
eff1a59c
MW
124 return;
125 }
126
eff1a59c 127 skb_put(skb, urb->actual_length);
2b80848e
CL
128
129 if (priv->hw_type == P54U_NET2280)
130 skb_pull(skb, priv->common.tx_hdr_len);
131 if (priv->common.fw_interface == FW_LM87) {
132 skb_pull(skb, 4);
133 skb_put(skb, 4);
134 }
eff1a59c
MW
135
136 if (p54_rx(dev, skb)) {
4e416a6f 137 skb = dev_alloc_skb(priv->common.rx_mtu + 32);
eff1a59c 138 if (unlikely(!skb)) {
eff1a59c
MW
139 /* TODO check rx queue length and refill *somewhere* */
140 return;
141 }
142
143 info = (struct p54u_rx_info *) skb->cb;
144 info->urb = urb;
145 info->dev = dev;
146 urb->transfer_buffer = skb_tail_pointer(skb);
147 urb->context = skb;
eff1a59c 148 } else {
2b80848e
CL
149 if (priv->hw_type == P54U_NET2280)
150 skb_push(skb, priv->common.tx_hdr_len);
151 if (priv->common.fw_interface == FW_LM87) {
152 skb_push(skb, 4);
153 skb_put(skb, 4);
154 }
d47c3ceb 155 skb_reset_tail_pointer(skb);
eff1a59c 156 skb_trim(skb, 0);
1ca5f2e9 157 urb->transfer_buffer = skb_tail_pointer(skb);
eff1a59c 158 }
dd397dc9
CL
159 skb_queue_tail(&priv->rx_queue, skb);
160 usb_anchor_urb(urb, &priv->submitted);
161 if (usb_submit_urb(urb, GFP_ATOMIC)) {
162 skb_unlink(skb, &priv->rx_queue);
163 usb_unanchor_urb(urb);
164 dev_kfree_skb_irq(skb);
165 }
eff1a59c
MW
166}
167
0a5ec96a 168static void p54u_tx_cb(struct urb *urb)
b92f30d6
CL
169{
170 struct sk_buff *skb = urb->context;
171 struct ieee80211_hw *dev = (struct ieee80211_hw *)
172 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
173
e2fe154e 174 p54_free_skb(dev, skb);
dd397dc9
CL
175}
176
177static void p54u_tx_dummy_cb(struct urb *urb) { }
178
179static void p54u_free_urbs(struct ieee80211_hw *dev)
180{
181 struct p54u_priv *priv = dev->priv;
182 usb_kill_anchored_urbs(&priv->submitted);
b92f30d6
CL
183}
184
eff1a59c
MW
185static int p54u_init_urbs(struct ieee80211_hw *dev)
186{
187 struct p54u_priv *priv = dev->priv;
dd397dc9 188 struct urb *entry = NULL;
eff1a59c
MW
189 struct sk_buff *skb;
190 struct p54u_rx_info *info;
dd397dc9 191 int ret = 0;
eff1a59c
MW
192
193 while (skb_queue_len(&priv->rx_queue) < 32) {
4e416a6f 194 skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
dd397dc9
CL
195 if (!skb) {
196 ret = -ENOMEM;
197 goto err;
198 }
eff1a59c
MW
199 entry = usb_alloc_urb(0, GFP_KERNEL);
200 if (!entry) {
dd397dc9
CL
201 ret = -ENOMEM;
202 goto err;
eff1a59c 203 }
dd397dc9 204
4e416a6f
CL
205 usb_fill_bulk_urb(entry, priv->udev,
206 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
207 skb_tail_pointer(skb),
208 priv->common.rx_mtu + 32, p54u_rx_cb, skb);
eff1a59c
MW
209 info = (struct p54u_rx_info *) skb->cb;
210 info->urb = entry;
211 info->dev = dev;
212 skb_queue_tail(&priv->rx_queue, skb);
dd397dc9
CL
213
214 usb_anchor_urb(entry, &priv->submitted);
215 ret = usb_submit_urb(entry, GFP_KERNEL);
216 if (ret) {
217 skb_unlink(skb, &priv->rx_queue);
218 usb_unanchor_urb(entry);
219 goto err;
220 }
221 usb_free_urb(entry);
222 entry = NULL;
eff1a59c
MW
223 }
224
225 return 0;
eff1a59c 226
dd397dc9
CL
227 err:
228 usb_free_urb(entry);
229 kfree_skb(skb);
230 p54u_free_urbs(dev);
231 return ret;
eff1a59c
MW
232}
233
c9127659 234static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
2b80848e 235{
1f1c0e33 236 u32 chk = 0;
2b80848e
CL
237
238 length >>= 2;
239 while (length--) {
c9127659 240 chk ^= le32_to_cpu(*data++);
2b80848e
CL
241 chk = (chk >> 5) ^ (chk << 3);
242 }
243
1f1c0e33 244 return cpu_to_le32(chk);
2b80848e
CL
245}
246
0a5ec96a 247static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
2b80848e
CL
248{
249 struct p54u_priv *priv = dev->priv;
250 struct urb *data_urb;
e2fe154e 251 struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
2b80848e
CL
252
253 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
6d541a68
CL
254 if (!data_urb) {
255 p54_free_skb(dev, skb);
2b80848e 256 return;
6d541a68 257 }
2b80848e 258
e2fe154e
CL
259 hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
260 hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
2b80848e
CL
261
262 usb_fill_bulk_urb(data_urb, priv->udev,
b92f30d6 263 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
e2fe154e
CL
264 hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
265 p54u_tx_cb : p54u_tx_dummy_cb, skb);
00627f22 266 data_urb->transfer_flags |= URB_ZERO_PACKET;
2b80848e 267
dd397dc9
CL
268 usb_anchor_urb(data_urb, &priv->submitted);
269 if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
270 usb_unanchor_urb(data_urb);
dd397dc9
CL
271 p54_free_skb(dev, skb);
272 }
273 usb_free_urb(data_urb);
2b80848e
CL
274}
275
0a5ec96a 276static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
eff1a59c
MW
277{
278 struct p54u_priv *priv = dev->priv;
6d541a68 279 struct urb *int_urb = NULL, *data_urb = NULL;
e2fe154e 280 struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
6d541a68
CL
281 struct net2280_reg_write *reg = NULL;
282 int err = -ENOMEM;
eff1a59c
MW
283
284 reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
285 if (!reg)
6d541a68 286 goto out;
eff1a59c
MW
287
288 int_urb = usb_alloc_urb(0, GFP_ATOMIC);
6d541a68
CL
289 if (!int_urb)
290 goto out;
eff1a59c
MW
291
292 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
6d541a68
CL
293 if (!data_urb)
294 goto out;
eff1a59c
MW
295
296 reg->port = cpu_to_le16(NET2280_DEV_U32);
297 reg->addr = cpu_to_le32(P54U_DEV_BASE);
298 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
299
eff1a59c 300 memset(hdr, 0, sizeof(*hdr));
e2fe154e
CL
301 hdr->len = cpu_to_le16(skb->len);
302 hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id;
eff1a59c
MW
303
304 usb_fill_bulk_urb(int_urb, priv->udev,
305 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
dd397dc9
CL
306 p54u_tx_dummy_cb, dev);
307
308 /*
6d541a68
CL
309 * URB_FREE_BUFFER triggers a code path in the USB subsystem that will
310 * free what is inside the transfer_buffer after the last reference to
311 * the int_urb is dropped.
dd397dc9 312 */
b4068a80 313 int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET;
6d541a68 314 reg = NULL;
eff1a59c
MW
315
316 usb_fill_bulk_urb(data_urb, priv->udev,
b92f30d6 317 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
e2fe154e
CL
318 hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
319 p54u_tx_cb : p54u_tx_dummy_cb, skb);
b4068a80 320 data_urb->transfer_flags |= URB_ZERO_PACKET;
dd397dc9
CL
321
322 usb_anchor_urb(int_urb, &priv->submitted);
323 err = usb_submit_urb(int_urb, GFP_ATOMIC);
324 if (err) {
325 usb_unanchor_urb(int_urb);
326 goto out;
327 }
328
329 usb_anchor_urb(data_urb, &priv->submitted);
330 err = usb_submit_urb(data_urb, GFP_ATOMIC);
331 if (err) {
332 usb_unanchor_urb(data_urb);
333 goto out;
334 }
6d541a68 335out:
dd397dc9
CL
336 usb_free_urb(int_urb);
337 usb_free_urb(data_urb);
338
339 if (err) {
6d541a68 340 kfree(reg);
dd397dc9
CL
341 p54_free_skb(dev, skb);
342 }
eff1a59c
MW
343}
344
345static int p54u_write(struct p54u_priv *priv,
346 struct net2280_reg_write *buf,
347 enum net2280_op_type type,
348 __le32 addr, __le32 val)
349{
350 unsigned int ep;
351 int alen;
352
353 if (type & 0x0800)
354 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
355 else
356 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
357
358 buf->port = cpu_to_le16(type);
359 buf->addr = addr;
360 buf->val = val;
361
362 return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
363}
364
365static int p54u_read(struct p54u_priv *priv, void *buf,
366 enum net2280_op_type type,
367 __le32 addr, __le32 *val)
368{
369 struct net2280_reg_read *read = buf;
370 __le32 *reg = buf;
371 unsigned int ep;
372 int alen, err;
373
374 if (type & 0x0800)
375 ep = P54U_PIPE_DEV;
376 else
377 ep = P54U_PIPE_BRG;
378
379 read->port = cpu_to_le16(type);
380 read->addr = addr;
381
382 err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
383 read, sizeof(*read), &alen, 1000);
384 if (err)
385 return err;
386
387 err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
388 reg, sizeof(*reg), &alen, 1000);
389 if (err)
390 return err;
391
392 *val = *reg;
393 return 0;
394}
395
396static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
397 void *data, size_t len)
398{
399 int alen;
400 return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
401 data, len, &alen, 2000);
402}
403
1ca5f2e9 404static int p54u_device_reset(struct ieee80211_hw *dev)
6982869d
CL
405{
406 struct p54u_priv *priv = dev->priv;
c88a768d 407 int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);
6982869d 408
c88a768d
CL
409 if (lock) {
410 ret = usb_lock_device_for_reset(priv->udev, priv->intf);
411 if (ret < 0) {
412 dev_err(&priv->udev->dev, "(p54usb) unable to lock "
1ca5f2e9 413 "device for reset (%d)!\n", ret);
c88a768d
CL
414 return ret;
415 }
6982869d
CL
416 }
417
418 ret = usb_reset_device(priv->udev);
419 if (lock)
420 usb_unlock_device(priv->udev);
421
1ca5f2e9 422 if (ret)
6982869d 423 dev_err(&priv->udev->dev, "(p54usb) unable to reset "
1ca5f2e9
CL
424 "device (%d)!\n", ret);
425
426 return ret;
427}
428
429static const char p54u_romboot_3887[] = "~~~~";
430static int p54u_firmware_reset_3887(struct ieee80211_hw *dev)
431{
432 struct p54u_priv *priv = dev->priv;
21d6c270 433 u8 *buf;
1ca5f2e9 434 int ret;
6982869d 435
21d6c270
LF
436 buf = kmalloc(4, GFP_KERNEL);
437 if (!buf)
438 return -ENOMEM;
439 memcpy(buf, p54u_romboot_3887, 4);
6982869d 440 ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
21d6c270
LF
441 buf, 4);
442 kfree(buf);
6982869d
CL
443 if (ret)
444 dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
1ca5f2e9 445 "boot ROM (%d)!\n", ret);
6982869d
CL
446
447 return ret;
448}
449
1ca5f2e9 450static const char p54u_firmware_upload_3887[] = "<\r";
eff1a59c
MW
451static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
452{
eff1a59c 453 struct p54u_priv *priv = dev->priv;
eff1a59c
MW
454 int err, alen;
455 u8 carry = 0;
8b72eb43
DW
456 u8 *buf, *tmp;
457 const u8 *data;
eff1a59c
MW
458 unsigned int left, remains, block_size;
459 struct x2_header *hdr;
460 unsigned long timeout;
461
1ca5f2e9
CL
462 err = p54u_firmware_reset_3887(dev);
463 if (err)
464 return err;
465
eff1a59c
MW
466 tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
467 if (!buf) {
02e37ba1
CL
468 dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
469 "upload buffer!\n");
1ca5f2e9 470 return -ENOMEM;
e365f160
CL
471 }
472
1ca5f2e9 473 left = block_size = min((size_t)P54U_FW_BLOCK, priv->fw->size);
6982869d
CL
474 strcpy(buf, p54u_firmware_upload_3887);
475 left -= strlen(p54u_firmware_upload_3887);
476 tmp += strlen(p54u_firmware_upload_3887);
eff1a59c 477
1ca5f2e9
CL
478 data = priv->fw->data;
479 remains = priv->fw->size;
eff1a59c 480
6982869d 481 hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
eff1a59c
MW
482 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
483 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
1ca5f2e9 484 hdr->fw_length = cpu_to_le32(priv->fw->size);
eff1a59c
MW
485 hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
486 sizeof(u32)*2));
487 left -= sizeof(*hdr);
488 tmp += sizeof(*hdr);
489
490 while (remains) {
491 while (left--) {
492 if (carry) {
493 *tmp++ = carry;
494 carry = 0;
495 remains--;
496 continue;
497 }
498 switch (*data) {
499 case '~':
500 *tmp++ = '}';
501 carry = '^';
502 break;
503 case '}':
504 *tmp++ = '}';
505 carry = ']';
506 break;
507 default:
508 *tmp++ = *data;
509 remains--;
510 break;
511 }
512 data++;
513 }
514
515 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
516 if (err) {
02e37ba1
CL
517 dev_err(&priv->udev->dev, "(p54usb) firmware "
518 "upload failed!\n");
eff1a59c
MW
519 goto err_upload_failed;
520 }
521
522 tmp = buf;
523 left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
524 }
525
1ca5f2e9
CL
526 *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data,
527 priv->fw->size));
eff1a59c
MW
528 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
529 if (err) {
02e37ba1 530 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
eff1a59c
MW
531 goto err_upload_failed;
532 }
eff1a59c
MW
533 timeout = jiffies + msecs_to_jiffies(1000);
534 while (!(err = usb_bulk_msg(priv->udev,
535 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
536 if (alen > 2 && !memcmp(buf, "OK", 2))
537 break;
538
539 if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
eff1a59c
MW
540 err = -EINVAL;
541 break;
542 }
543
544 if (time_after(jiffies, timeout)) {
02e37ba1
CL
545 dev_err(&priv->udev->dev, "(p54usb) firmware boot "
546 "timed out!\n");
eff1a59c
MW
547 err = -ETIMEDOUT;
548 break;
549 }
550 }
02e37ba1
CL
551 if (err) {
552 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
eff1a59c 553 goto err_upload_failed;
02e37ba1 554 }
eff1a59c
MW
555
556 buf[0] = 'g';
557 buf[1] = '\r';
558 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
559 if (err) {
02e37ba1 560 dev_err(&priv->udev->dev, "(p54usb) firmware boot failed!\n");
eff1a59c
MW
561 goto err_upload_failed;
562 }
563
564 timeout = jiffies + msecs_to_jiffies(1000);
565 while (!(err = usb_bulk_msg(priv->udev,
566 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
567 if (alen > 0 && buf[0] == 'g')
568 break;
569
570 if (time_after(jiffies, timeout)) {
571 err = -ETIMEDOUT;
572 break;
573 }
574 }
575 if (err)
576 goto err_upload_failed;
577
1ca5f2e9 578err_upload_failed:
eff1a59c 579 kfree(buf);
eff1a59c
MW
580 return err;
581}
582
583static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
584{
585 struct p54u_priv *priv = dev->priv;
eff1a59c
MW
586 const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
587 int err, alen;
588 void *buf;
589 __le32 reg;
590 unsigned int remains, offset;
8b72eb43 591 const u8 *data;
eff1a59c
MW
592
593 buf = kmalloc(512, GFP_KERNEL);
594 if (!buf) {
02e37ba1
CL
595 dev_err(&priv->udev->dev, "(p54usb) firmware buffer "
596 "alloc failed!\n");
eff1a59c
MW
597 return -ENOMEM;
598 }
599
eff1a59c
MW
600#define P54U_WRITE(type, addr, data) \
601 do {\
602 err = p54u_write(priv, buf, type,\
603 cpu_to_le32((u32)(unsigned long)addr), data);\
604 if (err) \
605 goto fail;\
606 } while (0)
607
608#define P54U_READ(type, addr) \
609 do {\
610 err = p54u_read(priv, buf, type,\
611 cpu_to_le32((u32)(unsigned long)addr), &reg);\
612 if (err)\
613 goto fail;\
614 } while (0)
615
616 /* power down net2280 bridge */
617 P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
618 reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
619 reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
620 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
621
622 mdelay(100);
623
624 /* power up bridge */
625 reg |= cpu_to_le32(P54U_BRG_POWER_UP);
626 reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
627 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
628
629 mdelay(100);
630
631 P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
632 cpu_to_le32(NET2280_CLK_30Mhz |
633 NET2280_PCI_ENABLE |
634 NET2280_PCI_SOFT_RESET));
635
636 mdelay(20);
637
638 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
639 cpu_to_le32(PCI_COMMAND_MEMORY |
640 PCI_COMMAND_MASTER));
641
642 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
643 cpu_to_le32(NET2280_BASE));
644
645 P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
646 reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
647 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
648
649 // TODO: we really need this?
650 P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
651
652 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
653 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
654 P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
655 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
656
657 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
658 cpu_to_le32(NET2280_BASE2));
659
660 /* finally done setting up the bridge */
661
662 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
663 cpu_to_le32(PCI_COMMAND_MEMORY |
664 PCI_COMMAND_MASTER));
665
666 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
667 P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
668 cpu_to_le32(P54U_DEV_BASE));
669
670 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
671 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
672 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
673
674 /* do romboot */
675 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
676
677 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
678 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
679 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
680 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
681 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
682
683 mdelay(20);
684
685 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
686 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
687
688 mdelay(20);
689
690 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
691 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
692
693 mdelay(100);
694
695 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
696 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
697
698 /* finally, we can upload firmware now! */
1ca5f2e9
CL
699 remains = priv->fw->size;
700 data = priv->fw->data;
eff1a59c
MW
701 offset = ISL38XX_DEV_FIRMWARE_ADDR;
702
703 while (remains) {
704 unsigned int block_len = min(remains, (unsigned int)512);
705 memcpy(buf, data, block_len);
706
707 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
708 if (err) {
02e37ba1
CL
709 dev_err(&priv->udev->dev, "(p54usb) firmware block "
710 "upload failed\n");
eff1a59c
MW
711 goto fail;
712 }
713
714 P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
715 cpu_to_le32(0xc0000f00));
716
717 P54U_WRITE(NET2280_DEV_U32,
718 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
719 P54U_WRITE(NET2280_DEV_U32,
720 0x0020 | (unsigned long)&devreg->direct_mem_win,
721 cpu_to_le32(1));
722
723 P54U_WRITE(NET2280_DEV_U32,
724 0x0024 | (unsigned long)&devreg->direct_mem_win,
725 cpu_to_le32(block_len));
726 P54U_WRITE(NET2280_DEV_U32,
727 0x0028 | (unsigned long)&devreg->direct_mem_win,
728 cpu_to_le32(offset));
729
730 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
731 cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
732 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
733 cpu_to_le32(block_len >> 2));
734 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
735 cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
736
737 mdelay(10);
738
739 P54U_READ(NET2280_DEV_U32,
740 0x002C | (unsigned long)&devreg->direct_mem_win);
741 if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
742 !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
02e37ba1
CL
743 dev_err(&priv->udev->dev, "(p54usb) firmware DMA "
744 "transfer failed\n");
eff1a59c
MW
745 goto fail;
746 }
747
748 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
749 cpu_to_le32(NET2280_FIFO_FLUSH));
750
751 remains -= block_len;
752 data += block_len;
753 offset += block_len;
754 }
755
756 /* do ramboot */
757 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
758 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
759 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
760 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
761 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
762
763 mdelay(20);
764
765 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
766 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
767
768 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
769 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
770
771 mdelay(100);
772
773 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
774 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
775
776 /* start up the firmware */
777 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
778 cpu_to_le32(ISL38XX_INT_IDENT_INIT));
779
780 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
781 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
782
783 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
784 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
785 NET2280_USB_INTERRUPT_ENABLE));
786
787 P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
788 cpu_to_le32(ISL38XX_DEV_INT_RESET));
789
790 err = usb_interrupt_msg(priv->udev,
791 usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
792 buf, sizeof(__le32), &alen, 1000);
793 if (err || alen != sizeof(__le32))
794 goto fail;
795
796 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
797 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
798
799 if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
800 err = -EINVAL;
801
802 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
803 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
804 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
805
806#undef P54U_WRITE
807#undef P54U_READ
808
1ca5f2e9 809fail:
eff1a59c
MW
810 kfree(buf);
811 return err;
812}
813
1ca5f2e9
CL
814static int p54u_load_firmware(struct ieee80211_hw *dev)
815{
816 struct p54u_priv *priv = dev->priv;
817 int err, i;
818
819 BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES);
820
821 for (i = 0; i < __NUM_P54U_HWTYPES; i++)
822 if (p54u_fwlist[i].type == priv->hw_type)
823 break;
824
825 if (i == __NUM_P54U_HWTYPES)
826 return -EOPNOTSUPP;
827
828 err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev);
829 if (err) {
830 dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
831 "(%d)!\n", p54u_fwlist[i].fw, err);
832
833 err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy,
834 &priv->udev->dev);
835 if (err)
836 return err;
837 }
838
839 err = p54_parse_firmware(dev, priv->fw);
840 if (err)
841 goto out;
842
843 if (priv->common.fw_interface != p54u_fwlist[i].intf) {
844 dev_err(&priv->udev->dev, "wrong firmware, please get "
845 "a firmware for \"%s\" and try again.\n",
846 p54u_fwlist[i].hw);
847 err = -EINVAL;
848 }
849
850out:
851 if (err)
852 release_firmware(priv->fw);
853
854 return err;
855}
856
eff1a59c
MW
857static int p54u_open(struct ieee80211_hw *dev)
858{
859 struct p54u_priv *priv = dev->priv;
860 int err;
861
862 err = p54u_init_urbs(dev);
863 if (err) {
864 return err;
865 }
866
867 priv->common.open = p54u_init_urbs;
868
869 return 0;
870}
871
872static void p54u_stop(struct ieee80211_hw *dev)
873{
874 /* TODO: figure out how to reliably stop the 3887 and net2280 so
875 the hardware is still usable next time we want to start it.
876 until then, we just stop listening to the hardware.. */
877 p54u_free_urbs(dev);
eff1a59c
MW
878}
879
880static int __devinit p54u_probe(struct usb_interface *intf,
881 const struct usb_device_id *id)
882{
883 struct usb_device *udev = interface_to_usbdev(intf);
884 struct ieee80211_hw *dev;
885 struct p54u_priv *priv;
886 int err;
887 unsigned int i, recognized_pipes;
eff1a59c
MW
888
889 dev = p54_init_common(sizeof(*priv));
02e37ba1 890
eff1a59c 891 if (!dev) {
02e37ba1 892 dev_err(&udev->dev, "(p54usb) ieee80211 alloc failed\n");
eff1a59c
MW
893 return -ENOMEM;
894 }
895
896 priv = dev->priv;
1ca5f2e9 897 priv->hw_type = P54U_INVALID_HW;
eff1a59c
MW
898
899 SET_IEEE80211_DEV(dev, &intf->dev);
900 usb_set_intfdata(intf, dev);
901 priv->udev = udev;
6982869d
CL
902 priv->intf = intf;
903 skb_queue_head_init(&priv->rx_queue);
904 init_usb_anchor(&priv->submitted);
eff1a59c
MW
905
906 usb_get_dev(udev);
907
908 /* really lazy and simple way of figuring out if we're a 3887 */
909 /* TODO: should just stick the identification in the device table */
910 i = intf->altsetting->desc.bNumEndpoints;
911 recognized_pipes = 0;
912 while (i--) {
913 switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
914 case P54U_PIPE_DATA:
915 case P54U_PIPE_MGMT:
916 case P54U_PIPE_BRG:
917 case P54U_PIPE_DEV:
918 case P54U_PIPE_DATA | USB_DIR_IN:
919 case P54U_PIPE_MGMT | USB_DIR_IN:
920 case P54U_PIPE_BRG | USB_DIR_IN:
921 case P54U_PIPE_DEV | USB_DIR_IN:
922 case P54U_PIPE_INT | USB_DIR_IN:
923 recognized_pipes++;
924 }
925 }
926 priv->common.open = p54u_open;
2b80848e 927 priv->common.stop = p54u_stop;
eff1a59c 928 if (recognized_pipes < P54U_PIPE_NUMBER) {
13792578 929#ifdef CONFIG_PM
1ca5f2e9
CL
930 /* ISL3887 needs a full reset on resume */
931 udev->reset_resume = 1;
932 err = p54u_device_reset(dev);
13792578 933#endif
1ca5f2e9 934
eff1a59c 935 priv->hw_type = P54U_3887;
a406ac0d
CL
936 dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
937 priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
938 priv->common.tx = p54u_tx_lm87;
1ca5f2e9 939 priv->upload_fw = p54u_upload_firmware_3887;
eff1a59c 940 } else {
2b80848e 941 priv->hw_type = P54U_NET2280;
eff1a59c
MW
942 dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
943 priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
944 priv->common.tx = p54u_tx_net2280;
1ca5f2e9 945 priv->upload_fw = p54u_upload_firmware_net2280;
2b80848e 946 }
1ca5f2e9 947 err = p54u_load_firmware(dev);
eff1a59c
MW
948 if (err)
949 goto err_free_dev;
950
1ca5f2e9
CL
951 err = priv->upload_fw(dev);
952 if (err)
953 goto err_free_fw;
954
7cb77072
CL
955 p54u_open(dev);
956 err = p54_read_eeprom(dev);
957 p54u_stop(dev);
eff1a59c 958 if (err)
1ca5f2e9 959 goto err_free_fw;
eff1a59c 960
2ac71072
CL
961 err = p54_register_common(dev, &udev->dev);
962 if (err)
1ca5f2e9 963 goto err_free_fw;
eff1a59c 964
eff1a59c
MW
965 return 0;
966
1ca5f2e9
CL
967err_free_fw:
968 release_firmware(priv->fw);
969
970err_free_dev:
d8c92107 971 p54_free_common(dev);
eff1a59c
MW
972 usb_set_intfdata(intf, NULL);
973 usb_put_dev(udev);
974 return err;
975}
976
977static void __devexit p54u_disconnect(struct usb_interface *intf)
978{
979 struct ieee80211_hw *dev = usb_get_intfdata(intf);
980 struct p54u_priv *priv;
981
982 if (!dev)
983 return;
984
d8c92107 985 p54_unregister_common(dev);
eff1a59c
MW
986
987 priv = dev->priv;
988 usb_put_dev(interface_to_usbdev(intf));
1ca5f2e9 989 release_firmware(priv->fw);
eff1a59c 990 p54_free_common(dev);
eff1a59c
MW
991}
992
6982869d
CL
993static int p54u_pre_reset(struct usb_interface *intf)
994{
1ca5f2e9
CL
995 struct ieee80211_hw *dev = usb_get_intfdata(intf);
996
997 if (!dev)
998 return -ENODEV;
999
1000 p54u_stop(dev);
6982869d
CL
1001 return 0;
1002}
1003
1ca5f2e9
CL
1004static int p54u_resume(struct usb_interface *intf)
1005{
1006 struct ieee80211_hw *dev = usb_get_intfdata(intf);
1007 struct p54u_priv *priv;
1008
1009 if (!dev)
1010 return -ENODEV;
1011
1012 priv = dev->priv;
1013 if (unlikely(!(priv->upload_fw && priv->fw)))
1014 return 0;
1015
1016 return priv->upload_fw(dev);
1017}
1018
6982869d
CL
1019static int p54u_post_reset(struct usb_interface *intf)
1020{
1ca5f2e9
CL
1021 struct ieee80211_hw *dev = usb_get_intfdata(intf);
1022 struct p54u_priv *priv;
1023 int err;
1024
1025 err = p54u_resume(intf);
1026 if (err)
1027 return err;
1028
1029 /* reinitialize old device state */
1030 priv = dev->priv;
1031 if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED)
1032 ieee80211_restart_hw(dev);
1033
6982869d
CL
1034 return 0;
1035}
1036
1ca5f2e9
CL
1037#ifdef CONFIG_PM
1038
1039static int p54u_suspend(struct usb_interface *intf, pm_message_t message)
1040{
1041 return p54u_pre_reset(intf);
1042}
1043
1044#endif /* CONFIG_PM */
1045
eff1a59c 1046static struct usb_driver p54u_driver = {
32ddf071 1047 .name = "p54usb",
eff1a59c
MW
1048 .id_table = p54u_table,
1049 .probe = p54u_probe,
1050 .disconnect = p54u_disconnect,
6982869d
CL
1051 .pre_reset = p54u_pre_reset,
1052 .post_reset = p54u_post_reset,
1ca5f2e9
CL
1053#ifdef CONFIG_PM
1054 .suspend = p54u_suspend,
1055 .resume = p54u_resume,
1056 .reset_resume = p54u_resume,
1057#endif /* CONFIG_PM */
fbf95296 1058 .soft_unbind = 1,
eff1a59c
MW
1059};
1060
1061static int __init p54u_init(void)
1062{
1063 return usb_register(&p54u_driver);
1064}
1065
1066static void __exit p54u_exit(void)
1067{
1068 usb_deregister(&p54u_driver);
1069}
1070
1071module_init(p54u_init);
1072module_exit(p54u_exit);