USB: rename usb_buffer_alloc() and usb_buffer_free() users
[linux-2.6.git] / drivers / net / wireless / ath / ar9170 / usb.c
index 71579e4..a1f5444 100644 (file)
@@ -38,6 +38,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
@@ -64,10 +65,14 @@ static struct usb_device_id ar9170_usb_ids[] = {
        { USB_DEVICE(0x0cf3, 0x9170) },
        /* Atheros TG121N */
        { USB_DEVICE(0x0cf3, 0x1001) },
+       /* TP-Link TL-WN821N v2 */
+       { USB_DEVICE(0x0cf3, 0x1002) },
        /* Cace Airpcap NX */
        { USB_DEVICE(0xcace, 0x0300) },
-       /* D-Link DWA 160A */
+       /* D-Link DWA 160 A1 */
        { USB_DEVICE(0x07d1, 0x3c10) },
+       /* D-Link DWA 160 A2 */
+       { USB_DEVICE(0x07d1, 0x3a09) },
        /* Netgear WNDA3100 */
        { USB_DEVICE(0x0846, 0x9010) },
        /* Netgear WN111 v2 */
@@ -80,6 +85,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
        { USB_DEVICE(0x0cde, 0x0023) },
        /* Z-Com UB82 ABG */
        { USB_DEVICE(0x0cde, 0x0026) },
+       /* Sphairon Homelink 1202 */
+       { USB_DEVICE(0x0cde, 0x0027) },
        /* Arcadyan WN7512 */
        { USB_DEVICE(0x083a, 0xf522) },
        /* Planex GWUS300 */
@@ -88,6 +95,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
        { USB_DEVICE(0x04bb, 0x093f) },
        /* AVM FRITZ!WLAN USB Stick N */
        { USB_DEVICE(0x057C, 0x8401) },
+       /* NEC WL300NU-G */
+       { USB_DEVICE(0x0409, 0x0249) },
        /* AVM FRITZ!WLAN USB Stick N 2.4 */
        { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY },
 
@@ -96,19 +105,64 @@ static struct usb_device_id ar9170_usb_ids[] = {
 };
 MODULE_DEVICE_TABLE(usb, ar9170_usb_ids);
 
-static void ar9170_usb_tx_urb_complete_free(struct urb *urb)
+static void ar9170_usb_submit_urb(struct ar9170_usb *aru)
+{
+       struct urb *urb;
+       unsigned long flags;
+       int err;
+
+       if (unlikely(!IS_STARTED(&aru->common)))
+               return ;
+
+       spin_lock_irqsave(&aru->tx_urb_lock, flags);
+       if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) {
+               spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
+               return ;
+       }
+       atomic_inc(&aru->tx_submitted_urbs);
+
+       urb = usb_get_from_anchor(&aru->tx_pending);
+       if (!urb) {
+               atomic_dec(&aru->tx_submitted_urbs);
+               spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
+
+               return ;
+       }
+       spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
+
+       aru->tx_pending_urbs--;
+       usb_anchor_urb(urb, &aru->tx_submitted);
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (unlikely(err)) {
+               if (ar9170_nag_limiter(&aru->common))
+                       dev_err(&aru->udev->dev, "submit_urb failed (%d).\n",
+                               err);
+
+               usb_unanchor_urb(urb);
+               atomic_dec(&aru->tx_submitted_urbs);
+               ar9170_tx_callback(&aru->common, urb->context);
+       }
+
+       usb_free_urb(urb);
+}
+
+static void ar9170_usb_tx_urb_complete_frame(struct urb *urb)
 {
        struct sk_buff *skb = urb->context;
        struct ar9170_usb *aru = (struct ar9170_usb *)
              usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 
-       if (!aru) {
+       if (unlikely(!aru)) {
                dev_kfree_skb_irq(skb);
                return ;
        }
 
-       ar9170_handle_tx_status(&aru->common, skb, false,
-                               AR9170_TX_STATUS_COMPLETE);
+       atomic_dec(&aru->tx_submitted_urbs);
+
+       ar9170_tx_callback(&aru->common, skb);
+
+       ar9170_usb_submit_urb(aru);
 }
 
 static void ar9170_usb_tx_urb_complete(struct urb *urb)
@@ -135,8 +189,8 @@ static void ar9170_usb_irq_completed(struct urb *urb)
                goto resubmit;
        }
 
-       print_hex_dump_bytes("ar9170 irq: ", DUMP_PREFIX_OFFSET,
-                            urb->transfer_buffer, urb->actual_length);
+       ar9170_handle_command_response(&aru->common, urb->transfer_buffer,
+                                      urb->actual_length);
 
 resubmit:
        usb_anchor_urb(urb, &aru->rx_submitted);
@@ -148,7 +202,7 @@ resubmit:
        return;
 
 free:
-       usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
+       usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
 }
 
 static void ar9170_usb_rx_completed(struct urb *urb)
@@ -186,16 +240,15 @@ resubmit:
 
        usb_anchor_urb(urb, &aru->rx_submitted);
        err = usb_submit_urb(urb, GFP_ATOMIC);
-       if (err) {
+       if (unlikely(err)) {
                usb_unanchor_urb(urb);
-               dev_kfree_skb_irq(skb);
+               goto free;
        }
 
        return ;
 
 free:
        dev_kfree_skb_irq(skb);
-       return;
 }
 
 static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru,
@@ -230,7 +283,7 @@ static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
        if (!urb)
                goto out;
 
-       ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
+       ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
        if (!ibuf)
                goto out;
 
@@ -243,8 +296,8 @@ static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
        err = usb_submit_urb(urb, GFP_KERNEL);
        if (err) {
                usb_unanchor_urb(urb);
-               usb_buffer_free(aru->udev, 64, urb->transfer_buffer,
-                               urb->transfer_dma);
+               usb_free_coherent(aru->udev, 64, urb->transfer_buffer,
+                                 urb->transfer_dma);
        }
 
 out:
@@ -291,21 +344,47 @@ err_out:
        return err;
 }
 
-static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru)
+static int ar9170_usb_flush(struct ar9170 *ar)
 {
-       int ret;
+       struct ar9170_usb *aru = (void *) ar;
+       struct urb *urb;
+       int ret, err = 0;
 
-       aru->common.state = AR9170_UNKNOWN_STATE;
+       if (IS_STARTED(ar))
+               aru->common.state = AR9170_IDLE;
 
-       usb_unlink_anchored_urbs(&aru->tx_submitted);
+       usb_wait_anchor_empty_timeout(&aru->tx_pending,
+                                           msecs_to_jiffies(800));
+       while ((urb = usb_get_from_anchor(&aru->tx_pending))) {
+               ar9170_tx_callback(&aru->common, (void *) urb->context);
+               usb_free_urb(urb);
+       }
 
-       /* give the LED OFF command and the deauth frame a chance to air. */
+       /* lets wait a while until the tx - queues are dried out */
        ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
                                            msecs_to_jiffies(100));
        if (ret == 0)
-               dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
-       usb_poison_anchored_urbs(&aru->tx_submitted);
+               err = -ETIMEDOUT;
+
+       usb_kill_anchored_urbs(&aru->tx_submitted);
+
+       if (IS_ACCEPTING_CMD(ar))
+               aru->common.state = AR9170_STARTED;
+
+       return err;
+}
 
+static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru)
+{
+       int err;
+
+       aru->common.state = AR9170_UNKNOWN_STATE;
+
+       err = ar9170_usb_flush(&aru->common);
+       if (err)
+               dev_err(&aru->udev->dev, "stuck tx urbs!\n");
+
+       usb_poison_anchored_urbs(&aru->tx_submitted);
        usb_poison_anchored_urbs(&aru->rx_submitted);
 }
 
@@ -340,13 +419,13 @@ static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd,
        spin_unlock_irqrestore(&aru->common.cmdlock, flags);
 
        usb_fill_int_urb(urb, aru->udev,
-                        usb_sndbulkpipe(aru->udev, AR9170_EP_CMD),
+                        usb_sndintpipe(aru->udev, AR9170_EP_CMD),
                         aru->common.cmdbuf, plen + 4,
                         ar9170_usb_tx_urb_complete, NULL, 1);
 
        usb_anchor_urb(urb, &aru->tx_submitted);
        err = usb_submit_urb(urb, GFP_ATOMIC);
-       if (err) {
+       if (unlikely(err)) {
                usb_unanchor_urb(urb);
                usb_free_urb(urb);
                goto err_unbuf;
@@ -389,12 +468,10 @@ err_free:
        return err;
 }
 
-static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb,
-                        bool txstatus_needed, unsigned int extra_len)
+static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb)
 {
        struct ar9170_usb *aru = (struct ar9170_usb *) ar;
        struct urb *urb;
-       int err;
 
        if (unlikely(!IS_STARTED(ar))) {
                /* Seriously, what were you drink... err... thinking!? */
@@ -407,18 +484,17 @@ static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb,
 
        usb_fill_bulk_urb(urb, aru->udev,
                          usb_sndbulkpipe(aru->udev, AR9170_EP_TX),
-                         skb->data, skb->len + extra_len, (txstatus_needed ?
-                         ar9170_usb_tx_urb_complete :
-                         ar9170_usb_tx_urb_complete_free), skb);
+                         skb->data, skb->len,
+                         ar9170_usb_tx_urb_complete_frame, skb);
        urb->transfer_flags |= URB_ZERO_PACKET;
 
-       usb_anchor_urb(urb, &aru->tx_submitted);
-       err = usb_submit_urb(urb, GFP_ATOMIC);
-       if (unlikely(err))
-               usb_unanchor_urb(urb);
+       usb_anchor_urb(urb, &aru->tx_pending);
+       aru->tx_pending_urbs++;
 
        usb_free_urb(urb);
-       return err;
+
+       ar9170_usb_submit_urb(aru);
+       return 0;
 }
 
 static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer)
@@ -427,7 +503,7 @@ static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer)
        unsigned long flags;
        u32 in, out;
 
-       if (!buffer)
+       if (unlikely(!buffer))
                return ;
 
        in = le32_to_cpup((__le32 *)buffer);
@@ -509,39 +585,6 @@ static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data,
        return 0;
 }
 
-static int ar9170_usb_request_firmware(struct ar9170_usb *aru)
-{
-       int err = 0;
-
-       err = request_firmware(&aru->firmware, "ar9170.fw",
-                              &aru->udev->dev);
-       if (!err) {
-               aru->init_values = NULL;
-               return 0;
-       }
-
-       if (aru->req_one_stage_fw) {
-               dev_err(&aru->udev->dev, "ar9170.fw firmware file "
-                       "not found and is required for this device\n");
-               return -EINVAL;
-       }
-
-       dev_err(&aru->udev->dev, "ar9170.fw firmware file "
-               "not found, trying old firmware...\n");
-
-       err = request_firmware(&aru->init_values, "ar9170-1.fw",
-                              &aru->udev->dev);
-
-       err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev);
-       if (err) {
-               release_firmware(aru->init_values);
-               dev_err(&aru->udev->dev, "file with init values not found.\n");
-               return err;
-       }
-
-       return err;
-}
-
 static int ar9170_usb_reset(struct ar9170_usb *aru)
 {
        int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING);
@@ -618,10 +661,8 @@ static void ar9170_usb_stop(struct ar9170 *ar)
        if (IS_ACCEPTING_CMD(ar))
                aru->common.state = AR9170_STOPPED;
 
-       /* lets wait a while until the tx - queues are dried out */
-       ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
-                                           msecs_to_jiffies(1000));
-       if (ret == 0)
+       ret = ar9170_usb_flush(ar);
+       if (ret)
                dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
 
        usb_poison_anchored_urbs(&aru->tx_submitted);
@@ -682,6 +723,109 @@ err_out:
        return err;
 }
 
+static void ar9170_usb_firmware_failed(struct ar9170_usb *aru)
+{
+       struct device *parent = aru->udev->dev.parent;
+
+       complete(&aru->firmware_loading_complete);
+
+       /* unbind anything failed */
+       if (parent)
+               down(&parent->sem);
+       device_release_driver(&aru->udev->dev);
+       if (parent)
+               up(&parent->sem);
+
+       usb_put_dev(aru->udev);
+}
+
+static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context)
+{
+       struct ar9170_usb *aru = context;
+       int err;
+
+       aru->firmware = fw;
+
+       if (!fw) {
+               dev_err(&aru->udev->dev, "firmware file not found.\n");
+               goto err_freefw;
+       }
+
+       err = ar9170_usb_init_device(aru);
+       if (err)
+               goto err_freefw;
+
+       err = ar9170_usb_open(&aru->common);
+       if (err)
+               goto err_unrx;
+
+       err = ar9170_register(&aru->common, &aru->udev->dev);
+
+       ar9170_usb_stop(&aru->common);
+       if (err)
+               goto err_unrx;
+
+       complete(&aru->firmware_loading_complete);
+       usb_put_dev(aru->udev);
+       return;
+
+ err_unrx:
+       ar9170_usb_cancel_urbs(aru);
+
+ err_freefw:
+       ar9170_usb_firmware_failed(aru);
+}
+
+static void ar9170_usb_firmware_inits(const struct firmware *fw,
+                                     void *context)
+{
+       struct ar9170_usb *aru = context;
+       int err;
+
+       if (!fw) {
+               dev_err(&aru->udev->dev, "file with init values not found.\n");
+               ar9170_usb_firmware_failed(aru);
+               return;
+       }
+
+       aru->init_values = fw;
+
+       /* ok so we have the init values -- get code for two-stage */
+
+       err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw",
+                                     &aru->udev->dev, GFP_KERNEL, aru,
+                                     ar9170_usb_firmware_finish);
+       if (err)
+               ar9170_usb_firmware_failed(aru);
+}
+
+static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context)
+{
+       struct ar9170_usb *aru = context;
+       int err;
+
+       if (fw) {
+               ar9170_usb_firmware_finish(fw, context);
+               return;
+       }
+
+       if (aru->req_one_stage_fw) {
+               dev_err(&aru->udev->dev, "ar9170.fw firmware file "
+                       "not found and is required for this device\n");
+               ar9170_usb_firmware_failed(aru);
+               return;
+       }
+
+       dev_err(&aru->udev->dev, "ar9170.fw firmware file "
+               "not found, trying old firmware...\n");
+
+       err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw",
+                                     &aru->udev->dev, GFP_KERNEL, aru,
+                                     ar9170_usb_firmware_inits);
+       if (err)
+               ar9170_usb_firmware_failed(aru);
+}
+
 static bool ar9170_requires_one_stage(const struct usb_device_id *id)
 {
        if (!id->driver_info)
@@ -714,13 +858,20 @@ static int ar9170_usb_probe(struct usb_interface *intf,
        aru->req_one_stage_fw = ar9170_requires_one_stage(id);
 
        usb_set_intfdata(intf, aru);
-       SET_IEEE80211_DEV(ar->hw, &udev->dev);
+       SET_IEEE80211_DEV(ar->hw, &intf->dev);
 
        init_usb_anchor(&aru->rx_submitted);
+       init_usb_anchor(&aru->tx_pending);
        init_usb_anchor(&aru->tx_submitted);
        init_completion(&aru->cmd_wait);
+       init_completion(&aru->firmware_loading_complete);
+       spin_lock_init(&aru->tx_urb_lock);
+
+       aru->tx_pending_urbs = 0;
+       atomic_set(&aru->tx_submitted_urbs, 0);
 
        aru->common.stop = ar9170_usb_stop;
+       aru->common.flush = ar9170_usb_flush;
        aru->common.open = ar9170_usb_open;
        aru->common.tx = ar9170_usb_tx;
        aru->common.exec_cmd = ar9170_usb_exec_cmd;
@@ -728,38 +879,15 @@ static int ar9170_usb_probe(struct usb_interface *intf,
 
 #ifdef CONFIG_PM
        udev->reset_resume = 1;
-#endif
+#endif /* CONFIG_PM */
        err = ar9170_usb_reset(aru);
        if (err)
                goto err_freehw;
 
-       err = ar9170_usb_request_firmware(aru);
-       if (err)
-               goto err_freehw;
-
-       err = ar9170_usb_init_device(aru);
-       if (err)
-               goto err_freefw;
-
-       err = ar9170_usb_open(ar);
-       if (err)
-               goto err_unrx;
-
-       err = ar9170_register(ar, &udev->dev);
-
-       ar9170_usb_stop(ar);
-       if (err)
-               goto err_unrx;
-
-       return 0;
-
-err_unrx:
-       ar9170_usb_cancel_urbs(aru);
-
-err_freefw:
-       release_firmware(aru->init_values);
-       release_firmware(aru->firmware);
-
+       usb_get_dev(aru->udev);
+       return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw",
+                                      &aru->udev->dev, GFP_KERNEL, aru,
+                                      ar9170_usb_firmware_step2);
 err_freehw:
        usb_set_intfdata(intf, NULL);
        usb_put_dev(udev);
@@ -776,15 +904,18 @@ static void ar9170_usb_disconnect(struct usb_interface *intf)
                return;
 
        aru->common.state = AR9170_IDLE;
+
+       wait_for_completion(&aru->firmware_loading_complete);
+
        ar9170_unregister(&aru->common);
        ar9170_usb_cancel_urbs(aru);
 
-       release_firmware(aru->init_values);
-       release_firmware(aru->firmware);
-
        usb_put_dev(aru->udev);
        usb_set_intfdata(intf, NULL);
        ieee80211_free_hw(aru->common.hw);
+
+       release_firmware(aru->init_values);
+       release_firmware(aru->firmware);
 }
 
 #ifdef CONFIG_PM
@@ -813,11 +944,6 @@ static int ar9170_resume(struct usb_interface *intf)
        usb_unpoison_anchored_urbs(&aru->rx_submitted);
        usb_unpoison_anchored_urbs(&aru->tx_submitted);
 
-       /*
-        * FIXME: firmware upload will fail on resume.
-        * but this is better than a hang!
-        */
-
        err = ar9170_usb_init_device(aru);
        if (err)
                goto err_unrx;