VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / usb / host / uhci-hcd.c
index afe0320..bf8ab3c 100644 (file)
@@ -103,8 +103,8 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
 static void hc_state_transitions(struct uhci_hcd *uhci);
 
 /* If a transfer is still active after this much time, turn off FSBR */
-#define IDLE_TIMEOUT   (HZ / 20)       /* 50 ms */
-#define FSBR_DELAY     (HZ / 20)       /* 50 ms */
+#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 TD's */
@@ -862,7 +862,7 @@ static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
        urbp->short_control_packet = 1;
 
        td = list_entry(urbp->td_list.prev, struct uhci_td, list);
-       urbp->qh->element = td->dma_handle;
+       urbp->qh->element = cpu_to_le32(td->dma_handle);
 
        return -EINPROGRESS;
 }
@@ -1611,6 +1611,7 @@ static void stall_callback(unsigned long ptr)
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        struct list_head list, *tmp, *head;
        unsigned long flags;
+       int called_uhci_finish_completion = 0;
 
        INIT_LIST_HEAD(&list);
 
@@ -1619,6 +1620,7 @@ static void stall_callback(unsigned long ptr)
            uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) {
                uhci_remove_pending_urbps(uhci);
                uhci_finish_completion(hcd, NULL);
+               called_uhci_finish_completion = 1;
        }
 
        head = &uhci->urb_list;
@@ -1646,6 +1648,10 @@ static void stall_callback(unsigned long ptr)
        }
        spin_unlock_irqrestore(&uhci->schedule_lock, flags);
 
+       /* Wake up anyone waiting for an URB to complete */
+       if (called_uhci_finish_completion)
+               wake_up_all(&uhci->waitqh);
+
        head = &list;
        tmp = head->next;
        while (tmp != head) {
@@ -1676,7 +1682,7 @@ static int init_stall_timer(struct usb_hcd *hcd)
        init_timer(&uhci->stall_timer);
        uhci->stall_timer.function = stall_callback;
        uhci->stall_timer.data = (unsigned long)hcd;
-       uhci->stall_timer.expires = jiffies + (HZ / 10);
+       uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100);
        add_timer(&uhci->stall_timer);
 
        return 0;
@@ -1756,7 +1762,7 @@ static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-       unsigned int io_addr = uhci->io_addr;
+       unsigned long io_addr = uhci->io_addr;
        unsigned short status;
        struct list_head *tmp, *head;
        unsigned int age;
@@ -1829,24 +1835,28 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 
 static void reset_hc(struct uhci_hcd *uhci)
 {
-       unsigned int io_addr = uhci->io_addr;
+       unsigned long io_addr = uhci->io_addr;
+
+       /* Turn off PIRQ, SMI, and all interrupts.  This also turns off
+        * the BIOS's USB Legacy Support.
+        */
+       pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
+       outw(0, uhci->io_addr + USBINTR);
 
        /* Global reset for 50ms */
        uhci->state = UHCI_RESET;
        outw(USBCMD_GRESET, io_addr + USBCMD);
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout((HZ*50+999) / 1000);
+       msleep(50);
        outw(0, io_addr + USBCMD);
 
        /* Another 10ms delay */
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout((HZ*10+999) / 1000);
+       msleep(10);
        uhci->resume_detect = 0;
 }
 
 static void suspend_hc(struct uhci_hcd *uhci)
 {
-       unsigned int io_addr = uhci->io_addr;
+       unsigned long io_addr = uhci->io_addr;
 
        dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
        uhci->state = UHCI_SUSPENDED;
@@ -1856,7 +1866,7 @@ static void suspend_hc(struct uhci_hcd *uhci)
 
 static void wakeup_hc(struct uhci_hcd *uhci)
 {
-       unsigned int io_addr = uhci->io_addr;
+       unsigned long io_addr = uhci->io_addr;
 
        switch (uhci->state) {
                case UHCI_SUSPENDED:            /* Start the resume */
@@ -1865,7 +1875,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
                        /* Global resume for >= 20ms */
                        outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD);
                        uhci->state = UHCI_RESUMING_1;
-                       uhci->state_end = jiffies + (20*HZ+999) / 1000;
+                       uhci->state_end = jiffies + msecs_to_jiffies(20);
                        break;
 
                case UHCI_RESUMING_1:           /* End global resume */
@@ -1896,7 +1906,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
 
 static int ports_active(struct uhci_hcd *uhci)
 {
-       unsigned int io_addr = uhci->io_addr;
+       unsigned long io_addr = uhci->io_addr;
        int connection = 0;
        int i;
 
@@ -1908,7 +1918,7 @@ static int ports_active(struct uhci_hcd *uhci)
 
 static int suspend_allowed(struct uhci_hcd *uhci)
 {
-       unsigned int io_addr = uhci->io_addr;
+       unsigned long io_addr = uhci->io_addr;
        int i;
 
        if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
@@ -1973,7 +1983,7 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
 
 static void start_hc(struct uhci_hcd *uhci)
 {
-       unsigned int io_addr = uhci->io_addr;
+       unsigned long io_addr = uhci->io_addr;
        int timeout = 1000;
 
        /*
@@ -1990,7 +2000,9 @@ static void start_hc(struct uhci_hcd *uhci)
                }
        }
 
-       /* Turn on all interrupts */
+       /* Turn on PIRQ and all interrupts */
+       pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+                       USBLEGSUP_DEFAULT);
        outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
                io_addr + USBINTR);
 
@@ -2054,15 +2066,10 @@ static int uhci_reset(struct usb_hcd *hcd)
 
        uhci->io_addr = (unsigned long) hcd->regs;
 
-       /* Turn off all interrupts */
-       outw(0, uhci->io_addr + USBINTR);
-
-       /* Maybe kick BIOS off this hardware.  Then reset, so we won't get
+       /* Kick BIOS off this hardware and reset, so we won't get
         * interrupts from any previous setup.
         */
        reset_hc(uhci);
-       pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
-                       USBLEGSUP_DEFAULT);
        return 0;
 }
 
@@ -2178,7 +2185,7 @@ static int uhci_start(struct usb_hcd *hcd)
 
        uhci->rh_numports = port;
 
-       hcd->self.root_hub = udev = usb_alloc_dev(NULL, &hcd->self, 0);
+       udev = usb_alloc_dev(NULL, &hcd->self, 0);
        if (!udev) {
                dev_err(uhci_dev(uhci), "unable to allocate root hub\n");
                goto err_alloc_root_hub;
@@ -2254,13 +2261,18 @@ static int uhci_start(struct usb_hcd *hcd)
                uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[irq]->dma_handle);
        }
 
+       /*
+        * Some architectures require a full mb() to enforce completion of
+        * the memory writes above before the I/O transfers in start_hc().
+        */
+       mb();
        start_hc(uhci);
 
        init_stall_timer(hcd);
 
        udev->speed = USB_SPEED_FULL;
 
-       if (usb_register_root_hub(udev, uhci_dev(uhci)) != 0) {
+       if (hcd_register_root(udev, &uhci->hcd) != 0) {
                dev_err(uhci_dev(uhci), "unable to start root hub\n");
                retval = -ENOMEM;
                goto err_start_root_hub;
@@ -2288,7 +2300,6 @@ err_alloc_skelqh:
 
 err_alloc_term_td:
        usb_put_dev(udev);
-       hcd->self.root_hub = NULL;
 
 err_alloc_root_hub:
        dma_pool_destroy(uhci->qh_pool);
@@ -2369,14 +2380,18 @@ static int uhci_resume(struct usb_hcd *hcd)
                /*
                 * Some systems don't maintain the UHCI register values
                 * during a PM suspend/resume cycle, so reinitialize
-                * the Frame Number, the Framelist Base Address, and the
-                * Interrupt Enable registers.
+                * the Frame Number, Framelist Base Address, Interrupt
+                * Enable, and Legacy Support registers.
                 */
+               pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+                               0);
                outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM);
                outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
                outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
                                USBINTR_SP, uhci->io_addr + USBINTR);
                uhci->resume_detect = 1;
+               pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
+                               USBLEGSUP_DEFAULT);
        } else {
                reset_hc(uhci);
                start_hc(uhci);
@@ -2518,7 +2533,7 @@ static int __init uhci_hcd_init(void)
        }
 
 #ifdef CONFIG_PROC_FS
-       uhci_proc_root = create_proc_entry("driver/uhci", S_IFDIR, 0);
+       uhci_proc_root = create_proc_entry("driver/uhci", S_IFDIR, NULL);
        if (!uhci_proc_root)
                goto proc_failed;
 #endif
@@ -2541,7 +2556,7 @@ init_failed:
 up_failed:
 
 #ifdef CONFIG_PROC_FS
-       remove_proc_entry("driver/uhci", 0);
+       remove_proc_entry("driver/uhci", NULL);
 
 proc_failed:
 #endif
@@ -2561,7 +2576,7 @@ static void __exit uhci_hcd_cleanup(void)
                warn("not all urb_priv's were freed!");
 
 #ifdef CONFIG_PROC_FS
-       remove_proc_entry("driver/uhci", 0);
+       remove_proc_entry("driver/uhci", NULL);
 #endif
 
        if (errbuf)