ath9k: Use new scan notifiers from mac80211
[safe/jmp/linux-2.6] / drivers / net / wireless / zd1211rw / zd_usb.c
index 3429576..f0e5e94 100644 (file)
@@ -1,4 +1,8 @@
-/* zd_usb.c
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -33,6 +37,7 @@
 static struct usb_device_id usb_ids[] = {
        /* ZD1211 */
        { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
@@ -53,12 +58,16 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
        /* ZD1211B */
        { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
@@ -75,6 +84,8 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B },
        /* "Driverless" devices that need ejecting */
        { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
        { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
@@ -92,6 +103,7 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
 #define FW_ZD1211B_PREFIX      "zd1211/zd1211b_"
 
 /* USB device initialization */
+static void int_urb_complete(struct urb *urb);
 
 static int request_fw_file(
        const struct firmware **fw, const char *name, struct device *device)
@@ -163,10 +175,11 @@ static int upload_code(struct usb_device *udev,
        if (flags & REBOOT) {
                u8 ret;
 
+               /* Use "DMA-aware" buffer. */
                r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                        USB_REQ_FIRMWARE_CONFIRM,
                        USB_DIR_IN | USB_TYPE_VENDOR,
-                       0, 0, &ret, sizeof(ret), 5000 /* ms */);
+                       0, 0, p, sizeof(ret), 5000 /* ms */);
                if (r != sizeof(ret)) {
                        dev_err(&udev->dev,
                                "control request firmeware confirmation failed."
@@ -175,6 +188,7 @@ static int upload_code(struct usb_device *udev,
                                r = -ENODEV;
                        goto error;
                }
+               ret = p[0];
                if (ret & 0x80) {
                        dev_err(&udev->dev,
                                "Internal error while downloading."
@@ -306,22 +320,31 @@ int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
 {
        int r;
        struct usb_device *udev = zd_usb_to_usbdev(usb);
+       u8 *buf;
 
+       /* Use "DMA-aware" buffer. */
+       buf = kmalloc(len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
        r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0,
-               data, len, 5000);
+               buf, len, 5000);
        if (r < 0) {
                dev_err(&udev->dev,
                        "read over firmware interface failed: %d\n", r);
-               return r;
+               goto exit;
        } else if (r != len) {
                dev_err(&udev->dev,
                        "incomplete read over firmware interface: %d/%d\n",
                        r, len);
-               return -EIO;
+               r = -EIO;
+               goto exit;
        }
-
-       return 0;
+       r = 0;
+       memcpy(data, buf, len);
+exit:
+       kfree(buf);
+       return r;
 }
 
 #define urb_dev(urb) (&(urb)->dev->dev)
@@ -331,11 +354,18 @@ static inline void handle_regs_int(struct urb *urb)
        struct zd_usb *usb = urb->context;
        struct zd_usb_interrupt *intr = &usb->intr;
        int len;
+       u16 int_num;
 
        ZD_ASSERT(in_interrupt());
        spin_lock(&intr->lock);
 
-       if (intr->read_regs_enabled) {
+       int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2));
+       if (int_num == CR_INTERRUPT) {
+               struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
+               memcpy(&mac->intr_buffer, urb->transfer_buffer,
+                               USB_MAX_EP_INT_BUFFER);
+               schedule_work(&mac->process_intr);
+       } else if (intr->read_regs_enabled) {
                intr->read_regs.length = len = urb->actual_length;
 
                if (len > sizeof(intr->read_regs.buffer))
@@ -346,7 +376,6 @@ static inline void handle_regs_int(struct urb *urb)
                goto out;
        }
 
-       dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n");
 out:
        spin_unlock(&intr->lock);
 }
@@ -533,11 +562,11 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
         * be padded. Unaligned access might also happen if the length_info
         * structure is not present.
         */
-       if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG))
+       if (get_unaligned_le16(&length_info->tag) == RX_LENGTH_INFO_TAG)
        {
                unsigned int l, k, n;
                for (i = 0, l = 0;; i++) {
-                       k = le16_to_cpu(get_unaligned(&length_info->length[i]));
+                       k = get_unaligned_le16(&length_info->length[i]);
                        if (k == 0)
                                return;
                        n = l+k;
@@ -857,7 +886,7 @@ static void tx_urb_complete(struct urb *urb)
 {
        int r;
        struct sk_buff *skb;
-       struct zd_tx_skb_control_block *cb;
+       struct ieee80211_tx_info *info;
        struct zd_usb *usb;
 
        switch (urb->status) {
@@ -877,9 +906,13 @@ static void tx_urb_complete(struct urb *urb)
        }
 free_urb:
        skb = (struct sk_buff *)urb->context;
+       /*
+        * grab 'usb' pointer before handing off the skb (since
+        * it might be freed by zd_mac_tx_to_dev or mac80211)
+        */
+       info = IEEE80211_SKB_CB(skb);
+       usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
        zd_mac_tx_to_dev(skb, urb->status);
-       cb = (struct zd_tx_skb_control_block *)skb->cb;
-       usb = &zd_hw_mac(cb->hw)->chip.usb;
        free_tx_urb(usb, urb);
        tx_dec_submitted_urbs(usb);
        return;
@@ -1034,8 +1067,7 @@ static int eject_installer(struct usb_interface *intf)
        /* Find bulk out endpoint */
        endpoint = &iface_desc->endpoint[1].desc;
        if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT &&
-           (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-           USB_ENDPOINT_XFER_BULK) {
+           usb_endpoint_xfer_bulk(endpoint)) {
                bulk_out_ep = endpoint->bEndpointAddress;
        } else {
                dev_err(&udev->dev,