]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/zd1211rw/zd_usb.c
[PATCH] zd1211rw: Add ID for ZyXEL AG-220
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / zd1211rw / zd_usb.c
index aa782e88754b3d777722eb3e41fd66c7ee669291..e04cffc8adf305240d6f7f5923af55550f91262d 100644 (file)
@@ -52,12 +52,21 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
        /* ZD1211B */
        { USB_DEVICE(0x0ace, 0x1215), .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, 0x4505), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0b05, 0x171b), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
        /* "Driverless" devices that need ejecting */
        { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
        {}
@@ -73,96 +82,6 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
 #define FW_ZD1211_PREFIX       "zd1211/zd1211_"
 #define FW_ZD1211B_PREFIX      "zd1211/zd1211b_"
 
-/* register address handling */
-
-#ifdef DEBUG
-static int check_addr(struct zd_usb *usb, zd_addr_t addr)
-{
-       u32 base = ZD_ADDR_BASE(addr);
-       u32 offset = ZD_OFFSET(addr);
-
-       if ((u32)addr & ADDR_ZERO_MASK)
-               goto invalid_address;
-       switch (base) {
-       case USB_BASE:
-               break;
-       case CR_BASE:
-               if (offset > CR_MAX_OFFSET) {
-                       dev_dbg(zd_usb_dev(usb),
-                               "CR offset %#010x larger than"
-                               " CR_MAX_OFFSET %#10x\n",
-                               offset, CR_MAX_OFFSET);
-                       goto invalid_address;
-               }
-               if (offset & 1) {
-                       dev_dbg(zd_usb_dev(usb),
-                               "CR offset %#010x is not a multiple of 2\n",
-                               offset);
-                       goto invalid_address;
-               }
-               break;
-       case E2P_BASE:
-               if (offset > E2P_MAX_OFFSET) {
-                       dev_dbg(zd_usb_dev(usb),
-                               "E2P offset %#010x larger than"
-                               " E2P_MAX_OFFSET %#010x\n",
-                               offset, E2P_MAX_OFFSET);
-                       goto invalid_address;
-               }
-               break;
-       case FW_BASE:
-               if (!usb->fw_base_offset) {
-                       dev_dbg(zd_usb_dev(usb),
-                              "ERROR: fw base offset has not been set\n");
-                       return -EAGAIN;
-               }
-               if (offset > FW_MAX_OFFSET) {
-                       dev_dbg(zd_usb_dev(usb),
-                               "FW offset %#10x is larger than"
-                               " FW_MAX_OFFSET %#010x\n",
-                               offset, FW_MAX_OFFSET);
-                       goto invalid_address;
-               }
-               break;
-       default:
-               dev_dbg(zd_usb_dev(usb),
-                       "address has unsupported base %#010x\n", addr);
-               goto invalid_address;
-       }
-
-       return 0;
-invalid_address:
-       dev_dbg(zd_usb_dev(usb),
-               "ERROR: invalid address: %#010x\n", addr);
-       return -EINVAL;
-}
-#endif /* DEBUG */
-
-static u16 usb_addr(struct zd_usb *usb, zd_addr_t addr)
-{
-       u32 base;
-       u16 offset;
-
-       base = ZD_ADDR_BASE(addr);
-       offset = ZD_OFFSET(addr);
-
-       ZD_ASSERT(check_addr(usb, addr) == 0);
-
-       switch (base) {
-       case CR_BASE:
-               offset += CR_BASE_OFFSET;
-               break;
-       case E2P_BASE:
-               offset += E2P_BASE_OFFSET;
-               break;
-       case FW_BASE:
-               offset += usb->fw_base_offset;
-               break;
-       }
-
-       return offset;
-}
-
 /* USB device initialization */
 
 static int request_fw_file(
@@ -295,14 +214,13 @@ static int handle_version_mismatch(struct usb_device *udev, u8 device_type,
        if (r)
                goto error;
 
-       r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START_OFFSET,
-               REBOOT);
+       r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START, REBOOT);
        if (r)
                goto error;
 
-       offset = ((EEPROM_REGS_OFFSET + EEPROM_REGS_SIZE) * sizeof(u16));
+       offset = (E2P_BOOT_CODE_OFFSET * sizeof(u16));
        r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset,
-               E2P_BASE_OFFSET + EEPROM_REGS_SIZE, REBOOT);
+               E2P_START + E2P_BOOT_CODE_OFFSET, REBOOT);
 
        /* At this point, the vendor driver downloads the whole firmware
         * image, hacks around with version IDs, and uploads it again,
@@ -331,7 +249,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
        if (r)
                goto error;
 
-       fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET);
+       fw_bcdDevice = get_word(ub_fw->data, E2P_DATA_OFFSET);
 
        if (fw_bcdDevice != bcdDevice) {
                dev_info(&udev->dev,
@@ -357,8 +275,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
        if (r)
                goto error;
 
-       r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START_OFFSET,
-                       REBOOT);
+       r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START, REBOOT);
        if (r) {
                dev_err(&udev->dev,
                        "Could not upload firmware code uph. Error number %d\n",
@@ -401,6 +318,12 @@ out:
 
 static inline void handle_retry_failed_int(struct urb *urb)
 {
+       struct zd_usb *usb = urb->context;
+       struct zd_mac *mac = zd_usb_to_mac(usb);
+       struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+       ieee->stats.tx_errors++;
+       ieee->ieee_stats.tx_retry_limit_exceeded++;
        dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
 }
 
@@ -494,7 +417,7 @@ int zd_usb_enable_int(struct zd_usb *usb)
 
        dev_dbg_f(zd_usb_dev(usb), "\n");
 
-       urb = usb_alloc_urb(0, GFP_NOFS);
+       urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb) {
                r = -ENOMEM;
                goto out;
@@ -512,7 +435,7 @@ int zd_usb_enable_int(struct zd_usb *usb)
 
        /* TODO: make it a DMA buffer */
        r = -ENOMEM;
-       transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_NOFS);
+       transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_KERNEL);
        if (!transfer_buffer) {
                dev_dbg_f(zd_usb_dev(usb),
                        "couldn't allocate transfer_buffer\n");
@@ -526,7 +449,7 @@ int zd_usb_enable_int(struct zd_usb *usb)
                         intr->interval);
 
        dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb);
-       r = usb_submit_urb(urb, GFP_NOFS);
+       r = usb_submit_urb(urb, GFP_KERNEL);
        if (r) {
                dev_dbg_f(zd_usb_dev(usb),
                         "Couldn't submit urb. Error number %d\n", r);
@@ -575,6 +498,9 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
 
        if (length < sizeof(struct rx_length_info)) {
                /* It's not a complete packet anyhow. */
+               struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+               ieee->stats.rx_errors++;
+               ieee->stats.rx_length_errors++;
                return;
        }
        length_info = (struct rx_length_info *)
@@ -598,13 +524,13 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
                        n = l+k;
                        if (n > length)
                                return;
-                       zd_mac_rx(mac, buffer+l, k);
+                       zd_mac_rx_irq(mac, buffer+l, k);
                        if (i >= 2)
                                return;
                        l = (n+3) & ~3;
                }
        } else {
-               zd_mac_rx(mac, buffer, length);
+               zd_mac_rx_irq(mac, buffer, length);
        }
 }
 
@@ -672,10 +598,10 @@ static struct urb *alloc_urb(struct zd_usb *usb)
        struct urb *urb;
        void *buffer;
 
-       urb = usb_alloc_urb(0, GFP_NOFS);
+       urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb)
                return NULL;
-       buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_NOFS,
+       buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
                                  &urb->transfer_dma);
        if (!buffer) {
                usb_free_urb(urb);
@@ -708,7 +634,7 @@ int zd_usb_enable_rx(struct zd_usb *usb)
        dev_dbg_f(zd_usb_dev(usb), "\n");
 
        r = -ENOMEM;
-       urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_NOFS);
+       urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_KERNEL);
        if (!urbs)
                goto error;
        for (i = 0; i < URBS_COUNT; i++) {
@@ -729,7 +655,7 @@ int zd_usb_enable_rx(struct zd_usb *usb)
        spin_unlock_irq(&rx->lock);
 
        for (i = 0; i < URBS_COUNT; i++) {
-               r = usb_submit_urb(urbs[i], GFP_NOFS);
+               r = usb_submit_urb(urbs[i], GFP_KERNEL);
                if (r)
                        goto error_submit;
        }
@@ -858,7 +784,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb)
        spin_lock_init(&intr->lock);
        intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
        init_completion(&intr->read_regs.completion);
-       intr->read_regs.cr_int_addr = cpu_to_le16(usb_addr(usb, CR_INTERRUPT));
+       intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
 }
 
 static inline void init_usb_rx(struct zd_usb *usb)
@@ -890,22 +816,6 @@ void zd_usb_init(struct zd_usb *usb, struct net_device *netdev,
        init_usb_rx(usb);
 }
 
-int zd_usb_init_hw(struct zd_usb *usb)
-{
-       int r;
-       struct zd_chip *chip = zd_usb_to_chip(usb);
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_ioread16_locked(chip, &usb->fw_base_offset,
-                       USB_REG((u16)FW_BASE_ADDR_OFFSET));
-       if (r)
-               return r;
-       dev_dbg_f(zd_usb_dev(usb), "fw_base_offset: %#06hx\n",
-                usb->fw_base_offset);
-
-       return 0;
-}
-
 void zd_usb_clear(struct zd_usb *usb)
 {
        usb_set_intfdata(usb->intf, NULL);
@@ -1027,6 +937,8 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
                goto error;
        }
 
+       usb_reset_device(interface_to_usbdev(intf));
+
        netdev = zd_netdev_alloc(intf);
        if (netdev == NULL) {
                r = -ENOMEM;
@@ -1128,6 +1040,7 @@ static int __init usb_init(void)
 
        r = usb_register(&driver);
        if (r) {
+               destroy_workqueue(zd_workqueue);
                printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
                       driver.name, r);
                return r;
@@ -1248,12 +1161,12 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
        }
 
        req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);
-       req = kmalloc(req_len, GFP_NOFS);
+       req = kmalloc(req_len, GFP_KERNEL);
        if (!req)
                return -ENOMEM;
        req->id = cpu_to_le16(USB_REQ_READ_REGS);
        for (i = 0; i < count; i++)
-               req->addr[i] = cpu_to_le16(usb_addr(usb, addresses[i]));
+               req->addr[i] = cpu_to_le16((u16)addresses[i]);
 
        udev = zd_usb_to_usbdev(usb);
        prepare_read_regs_int(usb);
@@ -1311,14 +1224,14 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
 
        req_len = sizeof(struct usb_req_write_regs) +
                  count * sizeof(struct reg_data);
-       req = kmalloc(req_len, GFP_NOFS);
+       req = kmalloc(req_len, GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
        req->id = cpu_to_le16(USB_REQ_WRITE_REGS);
        for (i = 0; i < count; i++) {
                struct reg_data *rw  = &req->reg_writes[i];
-               rw->addr = cpu_to_le16(usb_addr(usb, ioreqs[i].addr));
+               rw->addr = cpu_to_le16((u16)ioreqs[i].addr);
                rw->value = cpu_to_le16(ioreqs[i].value);
        }
 
@@ -1391,7 +1304,7 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
        bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);
 
        req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);
-       req = kmalloc(req_len, GFP_NOFS);
+       req = kmalloc(req_len, GFP_KERNEL);
        if (!req)
                return -ENOMEM;