]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/wireless/ath/carl9170/usb.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / net / wireless / ath / carl9170 / usb.c
index 7504ed14c72575a7befb91b0c0d9dd2684660af9..f82c400be28864d58edd9a5d38bd10f8a8c73f9d 100644 (file)
@@ -118,6 +118,8 @@ static struct usb_device_id carl9170_usb_ids[] = {
        { USB_DEVICE(0x057c, 0x8402) },
        /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */
        { USB_DEVICE(0x1668, 0x1200) },
+       /* Airlive X.USB a/b/g/n */
+       { USB_DEVICE(0x1b75, 0x9170) },
 
        /* terminate */
        {}
@@ -160,8 +162,7 @@ err_acc:
 
 static void carl9170_usb_tx_data_complete(struct urb *urb)
 {
-       struct ar9170 *ar = (struct ar9170 *)
-             usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+       struct ar9170 *ar = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 
        if (WARN_ON_ONCE(!ar)) {
                dev_kfree_skb_irq(urb->context);
@@ -433,7 +434,7 @@ static void carl9170_usb_rx_complete(struct urb *urb)
                         * device.
                         */
 
-                       carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
+                       ieee80211_queue_work(ar->hw, &ar->ping_work);
                }
        } else {
                /*
@@ -835,7 +836,7 @@ static int carl9170_usb_load_firmware(struct ar9170 *ar)
        if (err)
                goto err_out;
 
-       /* firmware restarts cmd counter */
+       /* now, start the command response counter */
        ar->cmd_seq = -1;
 
        return 0;
@@ -852,7 +853,12 @@ int carl9170_usb_restart(struct ar9170 *ar)
        if (ar->intf->condition != USB_INTERFACE_BOUND)
                return 0;
 
-       /* Disable command response sequence counter. */
+       /*
+        * Disable the command response sequence counter check.
+        * We already know that the device/firmware is in a bad state.
+        * So, no extra points are awarded to anyone who reminds the
+        * driver about that.
+        */
        ar->cmd_seq = -2;
 
        err = carl9170_reboot(ar);
@@ -904,6 +910,15 @@ static int carl9170_usb_init_device(struct ar9170 *ar)
 {
        int err;
 
+       /*
+        * The carl9170 firmware let's the driver know when it's
+        * ready for action. But we have to be prepared to gracefully
+        * handle all spurious [flushed] messages after each (re-)boot.
+        * Thus the command response counter remains disabled until it
+        * can be safely synchronized.
+        */
+       ar->cmd_seq = -2;
+
        err = carl9170_usb_send_rx_irq_urb(ar);
        if (err)
                goto err_out;
@@ -912,14 +927,21 @@ static int carl9170_usb_init_device(struct ar9170 *ar)
        if (err)
                goto err_unrx;
 
+       err = carl9170_usb_open(ar);
+       if (err)
+               goto err_unrx;
+
        mutex_lock(&ar->mutex);
        err = carl9170_usb_load_firmware(ar);
        mutex_unlock(&ar->mutex);
        if (err)
-               goto err_unrx;
+               goto err_stop;
 
        return 0;
 
+err_stop:
+       carl9170_usb_stop(ar);
+
 err_unrx:
        carl9170_usb_cancel_urbs(ar);
 
@@ -965,10 +987,6 @@ static void carl9170_usb_firmware_finish(struct ar9170 *ar)
        if (err)
                goto err_freefw;
 
-       err = carl9170_usb_open(ar);
-       if (err)
-               goto err_unrx;
-
        err = carl9170_register(ar);
 
        carl9170_usb_stop(ar);
@@ -1044,7 +1062,6 @@ static int carl9170_usb_probe(struct usb_interface *intf,
        atomic_set(&ar->rx_work_urbs, 0);
        atomic_set(&ar->rx_anch_urbs, 0);
        atomic_set(&ar->rx_pool_urbs, 0);
-       ar->cmd_seq = -2;
 
        usb_get_dev(ar->udev);
 
@@ -1091,10 +1108,6 @@ static int carl9170_usb_suspend(struct usb_interface *intf,
 
        carl9170_usb_cancel_urbs(ar);
 
-       /*
-        * firmware automatically reboots for usb suspend.
-        */
-
        return 0;
 }
 
@@ -1107,12 +1120,20 @@ static int carl9170_usb_resume(struct usb_interface *intf)
                return -ENODEV;
 
        usb_unpoison_anchored_urbs(&ar->rx_anch);
+       carl9170_set_state(ar, CARL9170_STOPPED);
 
-       err = carl9170_usb_init_device(ar);
-       if (err)
-               goto err_unrx;
+       /*
+        * The USB documentation demands that [for suspend] all traffic
+        * to and from the device has to stop. This would be fine, but
+        * there's a catch: the device[usb phy] does not come back.
+        *
+        * Upon resume the firmware will "kill" itself and the
+        * boot-code sorts out the magic voodoo.
+        * Not very nice, but there's not much what could go wrong.
+        */
+       msleep(1100);
 
-       err = carl9170_usb_open(ar);
+       err = carl9170_usb_init_device(ar);
        if (err)
                goto err_unrx;
 
@@ -1134,6 +1155,7 @@ static struct usb_driver carl9170_driver = {
 #ifdef CONFIG_PM
        .suspend = carl9170_usb_suspend,
        .resume = carl9170_usb_resume,
+       .reset_resume = carl9170_usb_resume,
 #endif /* CONFIG_PM */
 };