Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / drivers / usb / host / uhci-hcd.c
index 4151f61..d225e11 100644 (file)
@@ -13,7 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
  *
  * Intel documents this fairly well, and as far as I know there
  * are no royalties or anything like that, but even so there are
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -30,6 +31,7 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
 #include <linux/interrupt.h>
@@ -86,6 +88,15 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
 static void wakeup_rh(struct uhci_hcd *uhci);
 static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 
+/* If a transfer is still active after this much time, turn off FSBR */
+#define IDLE_TIMEOUT   msecs_to_jiffies(50)
+#define FSBR_DELAY     msecs_to_jiffies(50)
+
+/* When we timeout an idle transfer for FSBR, we'll switch it over to */
+/* depth first traversal. We'll do it in groups of this number of TDs */
+/* to make sure it doesn't hog all of the bandwidth */
+#define DEPTH_INTERVAL 5
+
 #include "uhci-debug.c"
 #include "uhci-q.c"
 #include "uhci-hub.c"
@@ -109,29 +120,22 @@ static void finish_reset(struct uhci_hcd *uhci)
        uhci->is_stopped = UHCI_IS_STOPPED;
        uhci_to_hcd(uhci)->state = HC_STATE_HALT;
        uhci_to_hcd(uhci)->poll_rh = 0;
-
-       uhci->dead = 0;         /* Full reset resurrects the controller */
 }
 
 /*
  * Last rites for a defunct/nonfunctional controller
  * or one we don't want to use any more.
  */
-static void uhci_hc_died(struct uhci_hcd *uhci)
+static void hc_died(struct uhci_hcd *uhci)
 {
-       uhci_get_current_frame_number(uhci);
        uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
        finish_reset(uhci);
-       uhci->dead = 1;
-
-       /* The current frame may already be partway finished */
-       ++uhci->frame_number;
+       uhci->hc_inaccessible = 1;
 }
 
 /*
- * Initialize a controller that was newly discovered or has lost power
- * or otherwise been reset while it was suspended.  In none of these cases
- * can we be sure of its previous state.
+ * Initialize a controller that was newly discovered or has just been
+ * resumed.  In either case we can't be sure of its previous state.
  */
 static void check_and_reset_hc(struct uhci_hcd *uhci)
 {
@@ -151,8 +155,7 @@ static void configure_hc(struct uhci_hcd *uhci)
        outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
 
        /* Set the current frame number */
-       outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER,
-                       uhci->io_addr + USBFRNUM);
+       outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
 
        /* Mark controller as not halted before we enable interrupts */
        uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
@@ -204,8 +207,7 @@ __acquires(uhci->lock)
        int int_enable;
 
        auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
-       dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
-                       "%s%s\n", __FUNCTION__,
+       dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,
                        (auto_stop ? " (auto-stop)" : ""));
 
        /* If we get a suspend request when we're already auto-stopped
@@ -239,27 +241,27 @@ __acquires(uhci->lock)
                spin_unlock_irq(&uhci->lock);
                msleep(1);
                spin_lock_irq(&uhci->lock);
-               if (uhci->dead)
+               if (uhci->hc_inaccessible)      /* Died */
                        return;
        }
        if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
-               dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev,
-                       "Controller not stopped yet!\n");
+               dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
 
        uhci_get_current_frame_number(uhci);
+       smp_wmb();
 
        uhci->rh_state = new_state;
        uhci->is_stopped = UHCI_IS_STOPPED;
        uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
        uhci_scan_schedule(uhci, NULL);
-       uhci_fsbr_off(uhci);
 }
 
 static void start_rh(struct uhci_hcd *uhci)
 {
        uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
        uhci->is_stopped = 0;
+       smp_wmb();
 
        /* Mark it configured and running with a 64-byte max packet.
         * All interrupts are enabled, even though RESUME won't do anything.
@@ -276,8 +278,7 @@ static void wakeup_rh(struct uhci_hcd *uhci)
 __releases(uhci->lock)
 __acquires(uhci->lock)
 {
-       dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
-                       "%s%s\n", __FUNCTION__,
+       dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,
                        uhci->rh_state == UHCI_RH_AUTO_STOPPED ?
                                " (auto-start)" : "");
 
@@ -292,7 +293,7 @@ __acquires(uhci->lock)
                spin_unlock_irq(&uhci->lock);
                msleep(20);
                spin_lock_irq(&uhci->lock);
-               if (uhci->dead)
+               if (uhci->hc_inaccessible)      /* Died */
                        return;
 
                /* End Global Resume and wait for EOP to be sent */
@@ -344,7 +345,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
                                                        errbuf, ERRBUF_LEN);
                                        lprintk(errbuf);
                                }
-                               uhci_hc_died(uhci);
+                               hc_died(uhci);
 
                                /* Force a callback in case there are
                                 * pending unlinks */
@@ -367,21 +368,12 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 
 /*
  * Store the current frame number in uhci->frame_number if the controller
- * is runnning.  Expand from 11 bits (of which we use only 10) to a
- * full-sized integer.
- *
- * Like many other parts of the driver, this code relies on being polled
- * more than once per second as long as the controller is running.
+ * is runnning
  */
 static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
 {
-       if (!uhci->is_stopped) {
-               unsigned delta;
-
-               delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) &
-                               (UHCI_NUMFRAMES - 1);
-               uhci->frame_number += delta;
-       }
+       if (!uhci->is_stopped)
+               uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
 }
 
 /*
@@ -415,7 +407,7 @@ static void release_uhci(struct uhci_hcd *uhci)
                        uhci->frame, uhci->frame_dma_handle);
 }
 
-static int uhci_init(struct usb_hcd *hcd)
+static int uhci_reset(struct usb_hcd *hcd)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        unsigned io_size = (unsigned) hcd->rsrc_len;
@@ -467,7 +459,7 @@ static void uhci_shutdown(struct pci_dev *pdev)
 {
        struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
 
-       uhci_hc_died(hcd_to_uhci(hcd));
+       hc_died(hcd_to_uhci(hcd));
 }
 
 /*
@@ -495,10 +487,14 @@ static int uhci_start(struct usb_hcd *hcd)
 
        hcd->uses_new_polling = 1;
 
+       uhci->fsbr = 0;
+       uhci->fsbrtimeout = 0;
+
        spin_lock_init(&uhci->lock);
-       setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,
-                       (unsigned long) uhci);
+
+       INIT_LIST_HEAD(&uhci->td_remove_list);
        INIT_LIST_HEAD(&uhci->idle_qh_list);
+
        init_waitqueue_head(&uhci->waitqh);
 
        if (DEBUG_CONFIGURED) {
@@ -669,12 +665,11 @@ static void uhci_stop(struct usb_hcd *hcd)
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
        spin_lock_irq(&uhci->lock);
-       if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
-               uhci_hc_died(uhci);
+       if (!uhci->hc_inaccessible)
+               hc_died(uhci);
        uhci_scan_schedule(uhci, NULL);
        spin_unlock_irq(&uhci->lock);
 
-       del_timer_sync(&uhci->fsbr_timer);
        release_uhci(uhci);
 }
 
@@ -682,15 +677,12 @@ static void uhci_stop(struct usb_hcd *hcd)
 static int uhci_rh_suspend(struct usb_hcd *hcd)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-       int rc = 0;
 
        spin_lock_irq(&uhci->lock);
-       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
-               rc = -ESHUTDOWN;
-       else if (!uhci->dead)
+       if (!uhci->hc_inaccessible)             /* Not dead */
                suspend_rh(uhci, UHCI_RH_SUSPENDED);
        spin_unlock_irq(&uhci->lock);
-       return rc;
+       return 0;
 }
 
 static int uhci_rh_resume(struct usb_hcd *hcd)
@@ -699,10 +691,13 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
        int rc = 0;
 
        spin_lock_irq(&uhci->lock);
-       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
-               dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
-               rc = -ESHUTDOWN;
-       } else if (!uhci->dead)
+       if (uhci->hc_inaccessible) {
+               if (uhci->rh_state == UHCI_RH_SUSPENDED) {
+                       dev_warn(uhci_dev(uhci), "HC isn't running!\n");
+                       rc = -ENODEV;
+               }
+               /* Otherwise the HC is dead */
+       } else
                wakeup_rh(uhci);
        spin_unlock_irq(&uhci->lock);
        return rc;
@@ -716,8 +711,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
        dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
 
        spin_lock_irq(&uhci->lock);
-       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
-               goto done_okay;         /* Already suspended or dead */
+       if (uhci->hc_inaccessible)      /* Dead or already suspended */
+               goto done;
 
        if (uhci->rh_state > UHCI_RH_SUSPENDED) {
                dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
@@ -730,12 +725,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
         */
        pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
        mb();
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       uhci->hc_inaccessible = 1;
        hcd->poll_rh = 0;
 
        /* FIXME: Enable non-PME# remote wakeup? */
 
-done_okay:
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 done:
        spin_unlock_irq(&uhci->lock);
        return rc;
@@ -748,22 +743,24 @@ static int uhci_resume(struct usb_hcd *hcd)
        dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
 
        /* Since we aren't in D3 any more, it's safe to set this flag
-        * even if the controller was dead.
+        * even if the controller was dead.  It might not even be dead
+        * any more, if the firmware or quirks code has reset it.
         */
        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
        mb();
 
+       if (uhci->rh_state == UHCI_RH_RESET)    /* Dead */
+               return 0;
        spin_lock_irq(&uhci->lock);
 
        /* FIXME: Disable non-PME# remote wakeup? */
 
-       /* The firmware or a boot kernel may have changed the controller
-        * settings during a system wakeup.  Check it and reconfigure
-        * to avoid problems.
+       uhci->hc_inaccessible = 0;
+
+       /* The BIOS may have changed the controller settings during a
+        * system wakeup.  Check it and reconfigure to avoid problems.
         */
        check_and_reset_hc(uhci);
-
-       /* If the controller was dead before, it's back alive now */
        configure_hc(uhci);
 
        if (uhci->rh_state == UHCI_RH_RESET) {
@@ -813,15 +810,18 @@ done:
 static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-       unsigned frame_number;
-       unsigned delta;
+       unsigned long flags;
+       int is_stopped;
+       int frame_number;
 
        /* Minimize latency by avoiding the spinlock */
-       frame_number = uhci->frame_number;
-       barrier();
-       delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) &
-                       (UHCI_NUMFRAMES - 1);
-       return frame_number + delta;
+       local_irq_save(flags);
+       is_stopped = uhci->is_stopped;
+       smp_rmb();
+       frame_number = (is_stopped ? uhci->frame_number :
+                       inw(uhci->io_addr + USBFRNUM));
+       local_irq_restore(flags);
+       return frame_number;
 }
 
 static const char hcd_name[] = "uhci_hcd";
@@ -836,7 +836,7 @@ static const struct hc_driver uhci_driver = {
        .flags =                HCD_USB11,
 
        /* Basic lifecycle operations */
-       .reset =                uhci_init,
+       .reset =                uhci_reset,
        .start =                uhci_start,
 #ifdef CONFIG_PM
        .suspend =              uhci_suspend,