]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - drivers/usb/host/uhci-hcd.c
Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev
[mirror_ubuntu-zesty-kernel.git] / drivers / usb / host / uhci-hcd.c
index 82e608a4bbd026f8b6e2bb4e23b37cbd581f0993..0d5d2545bf07ba151a40e617e52583a2a096f62b 100644 (file)
@@ -84,6 +84,8 @@ static char *errbuf;
 
 static kmem_cache_t *uhci_up_cachep;   /* urb_priv */
 
+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 */
@@ -110,6 +112,8 @@ static inline void restart_timer(struct uhci_hcd *uhci)
  */
 static void reset_hc(struct uhci_hcd *uhci)
 {
+       int port;
+
        /* Turn off PIRQ enable and SMI enable.  (This also turns off the
         * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
         */
@@ -133,21 +137,30 @@ static void reset_hc(struct uhci_hcd *uhci)
        outw(0, uhci->io_addr + USBINTR);
        outw(0, uhci->io_addr + USBCMD);
 
-       uhci->resume_detect = 0;
+       /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect
+        * bits in the port status and control registers.
+        * We have to clear them by hand.
+        */
+       for (port = 0; port < uhci->rh_numports; ++port)
+               outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));
+
        uhci->port_c_suspend = uhci->suspended_ports =
                        uhci->resuming_ports = 0;
        uhci->rh_state = UHCI_RH_RESET;
        uhci->is_stopped = UHCI_IS_STOPPED;
        uhci_to_hcd(uhci)->state = HC_STATE_HALT;
+       uhci_to_hcd(uhci)->poll_rh = 0;
 }
 
 /*
  * Last rites for a defunct/nonfunctional controller
+ * or one we don't want to use any more.
  */
 static void hc_died(struct uhci_hcd *uhci)
 {
        reset_hc(uhci);
        uhci->hc_inaccessible = 1;
+       del_timer(&uhci->stall_timer);
 }
 
 /*
@@ -163,14 +176,14 @@ static void check_and_reset_hc(struct uhci_hcd *uhci)
         * When restarting a suspended controller, we expect all the
         * settings to be the same as we left them:
         *
-        *      PIRQ and SMI disabled, no R/WC bits set in USBLEGSUP;
+        *      PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
         *      Controller is stopped and configured with EGSM set;
         *      No interrupts enabled except possibly Resume Detect.
         *
         * If any of these conditions are violated we do a complete reset.
         */
        pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);
-       if (legsup & ~USBLEGSUP_RO) {
+       if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) {
                dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
                                __FUNCTION__, legsup);
                goto reset_needed;
@@ -302,14 +315,14 @@ __acquires(uhci->lock)
 
        uhci->rh_state = new_state;
        uhci->is_stopped = UHCI_IS_STOPPED;
-       uhci->resume_detect = 0;
+       del_timer(&uhci->stall_timer);
+       uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
        uhci_scan_schedule(uhci, NULL);
 }
 
 static void start_rh(struct uhci_hcd *uhci)
 {
-       uhci->rh_state = UHCI_RH_RUNNING;
        uhci->is_stopped = 0;
        smp_wmb();
 
@@ -320,6 +333,9 @@ static void start_rh(struct uhci_hcd *uhci)
        outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
                        uhci->io_addr + USBINTR);
        mb();
+       uhci->rh_state = UHCI_RH_RUNNING;
+       uhci_to_hcd(uhci)->poll_rh = 1;
+       restart_timer(uhci);
 }
 
 static void wakeup_rh(struct uhci_hcd *uhci)
@@ -353,36 +369,9 @@ __acquires(uhci->lock)
        }
 
        start_rh(uhci);
-}
-
-static void rh_state_transitions(struct uhci_hcd *uhci)
-{
-       switch (uhci->rh_state) {
-           case UHCI_RH_RUNNING:
-               /* are any devices attached? */
-               if (!any_ports_active(uhci)) {
-                       uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
-                       uhci->auto_stop_time = jiffies + HZ;
-               }
-               break;
-
-           case UHCI_RH_RUNNING_NODEVS:
-               /* auto-stop if nothing connected for 1 second */
-               if (any_ports_active(uhci))
-                       uhci->rh_state = UHCI_RH_RUNNING;
-               else if (time_after_eq(jiffies, uhci->auto_stop_time))
-                       suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
-               break;
-
-           case UHCI_RH_AUTO_STOPPED:
-               /* wakeup if requested by a device */
-               if (uhci->resume_detect)
-                       wakeup_rh(uhci);
-               break;
 
-           default:
-               break;
-       }
+       /* Restart root hub polling */
+       mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
 }
 
 static void stall_callback(unsigned long _uhci)
@@ -394,14 +383,8 @@ static void stall_callback(unsigned long _uhci)
        uhci_scan_schedule(uhci, NULL);
        check_fsbr(uhci);
 
-       /* Poll for and perform state transitions */
-       if (!uhci->hc_inaccessible) {
-               rh_state_transitions(uhci);
-               if (uhci->suspended_ports)
-                       uhci_check_ports(uhci);
-       }
-
-       restart_timer(uhci);
+       if (!uhci->is_stopped)
+               restart_timer(uhci);
        spin_unlock_irqrestore(&uhci->lock, flags);
 }
 
@@ -443,7 +426,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
        }
 
        if (status & USBSTS_RD)
-               uhci->resume_detect = 1;
+               usb_hcd_poll_rh_status(hcd);
 
        spin_lock_irqsave(&uhci->lock, flags);
        uhci_scan_schedule(uhci, regs);
@@ -505,9 +488,37 @@ static void release_uhci(struct uhci_hcd *uhci)
 static int uhci_reset(struct usb_hcd *hcd)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+       unsigned io_size = (unsigned) hcd->rsrc_len;
+       int port;
 
        uhci->io_addr = (unsigned long) hcd->rsrc_start;
 
+       /* The UHCI spec says devices must have 2 ports, and goes on to say
+        * they may have more but gives no way to determine how many there
+        * are.  However according to the UHCI spec, Bit 7 of the port
+        * status and control register is always set to 1.  So we try to
+        * use this to our advantage.  Another common failure mode when
+        * a nonexistent register is addressed is to return all ones, so
+        * we test for that also.
+        */
+       for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) {
+               unsigned int portstatus;
+
+               portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2));
+               if (!(portstatus & 0x0080) || portstatus == 0xffff)
+                       break;
+       }
+       if (debug)
+               dev_info(uhci_dev(uhci), "detected %d ports\n", port);
+
+       /* Anything greater than 7 is weird so we'll ignore it. */
+       if (port > UHCI_RH_MAXCHILD) {
+               dev_info(uhci_dev(uhci), "port count misdetected? "
+                               "forcing to 2 ports\n");
+               port = 2;
+       }
+       uhci->rh_numports = port;
+
        /* Kick BIOS off this hardware and reset if the controller
         * isn't already safely quiescent.
         */
@@ -515,6 +526,20 @@ static int uhci_reset(struct usb_hcd *hcd)
        return 0;
 }
 
+/* Make sure the controller is quiescent and that we're not using it
+ * any more.  This is mainly for the benefit of programs which, like kexec,
+ * expect the hardware to be idle: not doing DMA or generating IRQs.
+ *
+ * This routine may be called in a damaged or failing kernel.  Hence we
+ * do not acquire the spinlock before shutting down the controller.
+ */
+static void uhci_shutdown(struct pci_dev *pdev)
+{
+       struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
+
+       hc_died(hcd_to_uhci(hcd));
+}
+
 /*
  * Allocate a frame list, and then setup the skeleton
  *
@@ -535,13 +560,11 @@ static int uhci_start(struct usb_hcd *hcd)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        int retval = -EBUSY;
-       int i, port;
-       unsigned io_size;
+       int i;
        dma_addr_t dma_handle;
-       struct usb_device *udev;
        struct dentry *dentry;
 
-       io_size = (unsigned) hcd->rsrc_len;
+       hcd->uses_new_polling = 1;
        if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
                hcd->can_wakeup = 1;            /* Assume it supports PME# */
 
@@ -602,46 +625,14 @@ static int uhci_start(struct usb_hcd *hcd)
                goto err_create_qh_pool;
        }
 
-       /* Initialize the root hub */
-
-       /* UHCI specs says devices must have 2 ports, but goes on to say */
-       /*  they may have more but give no way to determine how many they */
-       /*  have. However, according to the UHCI spec, Bit 7 is always set */
-       /*  to 1. So we try to use this to our advantage */
-       for (port = 0; port < (io_size - 0x10) / 2; port++) {
-               unsigned int portstatus;
-
-               portstatus = inw(uhci->io_addr + 0x10 + (port * 2));
-               if (!(portstatus & 0x0080))
-                       break;
-       }
-       if (debug)
-               dev_info(uhci_dev(uhci), "detected %d ports\n", port);
-
-       /* This is experimental so anything less than 2 or greater than 8 is */
-       /*  something weird and we'll ignore it */
-       if (port < 2 || port > UHCI_RH_MAXCHILD) {
-               dev_info(uhci_dev(uhci), "port count misdetected? "
-                               "forcing to 2 ports\n");
-               port = 2;
-       }
-
-       uhci->rh_numports = port;
-
-       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;
-       }
-
-       uhci->term_td = uhci_alloc_td(uhci, udev);
+       uhci->term_td = uhci_alloc_td(uhci);
        if (!uhci->term_td) {
                dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n");
                goto err_alloc_term_td;
        }
 
        for (i = 0; i < UHCI_NUM_SKELQH; i++) {
-               uhci->skelqh[i] = uhci_alloc_qh(uhci, udev);
+               uhci->skelqh[i] = uhci_alloc_qh(uhci);
                if (!uhci->skelqh[i]) {
                        dev_err(uhci_dev(uhci), "unable to allocate QH\n");
                        goto err_alloc_skelqh;
@@ -713,26 +704,11 @@ static int uhci_start(struct usb_hcd *hcd)
 
        configure_hc(uhci);
        start_rh(uhci);
-
-       restart_timer(uhci);
-
-       udev->speed = USB_SPEED_FULL;
-
-       if (usb_hcd_register_root_hub(udev, hcd) != 0) {
-               dev_err(uhci_dev(uhci), "unable to start root hub\n");
-               retval = -ENOMEM;
-               goto err_start_root_hub;
-       }
-
        return 0;
 
 /*
  * error exits:
  */
-err_start_root_hub:
-       del_timer_sync(&uhci->stall_timer);
-       reset_hc(uhci);
-
 err_alloc_skelqh:
        for (i = 0; i < UHCI_NUM_SKELQH; i++)
                if (uhci->skelqh[i]) {
@@ -744,9 +720,6 @@ err_alloc_skelqh:
        uhci->term_td = NULL;
 
 err_alloc_term_td:
-       usb_put_dev(udev);
-
-err_alloc_root_hub:
        dma_pool_destroy(uhci->qh_pool);
        uhci->qh_pool = NULL;
 
@@ -771,13 +744,12 @@ static void uhci_stop(struct usb_hcd *hcd)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
-       del_timer_sync(&uhci->stall_timer);
-
        spin_lock_irq(&uhci->lock);
        reset_hc(uhci);
        uhci_scan_schedule(uhci, NULL);
        spin_unlock_irq(&uhci->lock);
-       
+
+       del_timer_sync(&uhci->stall_timer);
        release_uhci(uhci);
 }
 
@@ -844,6 +816,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
 
 done:
        spin_unlock_irq(&uhci->lock);
+       if (rc == 0)
+               del_timer_sync(&hcd->rh_timer);
        return rc;
 }
 
@@ -875,6 +849,9 @@ static int uhci_resume(struct usb_hcd *hcd)
                suspend_rh(uhci, UHCI_RH_SUSPENDED);
 
        spin_unlock_irq(&uhci->lock);
+
+       if (hcd->poll_rh)
+               usb_hcd_poll_rh_status(hcd);
        return 0;
 }
 #endif
@@ -952,6 +929,7 @@ static struct pci_driver uhci_pci_driver = {
 
        .probe =        usb_hcd_pci_probe,
        .remove =       usb_hcd_pci_remove,
+       .shutdown =     uhci_shutdown,
 
 #ifdef CONFIG_PM
        .suspend =      usb_hcd_pci_suspend,