]> err.no Git - linux-2.6/blobdiff - drivers/usb/host/uhci-hcd.c
[PATCH] USB: Rename hcd->hub_suspend to hcd->bus_suspend
[linux-2.6] / drivers / usb / host / uhci-hcd.c
index 25a718eb1d0fffd07f100079ac5239e4629b5e41..72cd1576d20cc00ca5db57b0c43b903b40bea606 100644 (file)
@@ -97,43 +97,26 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 /* to make sure it doesn't hog all of the bandwidth */
 #define DEPTH_INTERVAL 5
 
-static inline void restart_timer(struct uhci_hcd *uhci)
-{
-       mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
-}
-
-#include "uhci-hub.c"
 #include "uhci-debug.c"
 #include "uhci-q.c"
+#include "uhci-hub.c"
+
+extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
 
 /*
- * Make sure the controller is completely inactive, unable to
- * generate interrupts or do DMA.
+ * Finish up a host controller reset and update the recorded state.
  */
-static void reset_hc(struct uhci_hcd *uhci)
+static void finish_reset(struct uhci_hcd *uhci)
 {
-       /* 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.
-        */
-       pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
-                       USBLEGSUP_RWC);
-
-       /* Reset the HC - this will force us to get a
-        * new notification of any already connected
-        * ports due to the virtual disconnect that it
-        * implies.
-        */
-       outw(USBCMD_HCRESET, uhci->io_addr + USBCMD);
-       mb();
-       udelay(5);
-       if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET)
-               dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n");
+       int port;
 
-       /* Just to be safe, disable interrupt requests and
-        * make sure the controller is stopped.
+       /* 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.
         */
-       outw(0, uhci->io_addr + USBINTR);
-       outw(0, uhci->io_addr + USBCMD);
+       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;
@@ -145,12 +128,13 @@ static void reset_hc(struct uhci_hcd *uhci)
 
 /*
  * 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_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
+       finish_reset(uhci);
        uhci->hc_inaccessible = 1;
-       del_timer(&uhci->stall_timer);
 }
 
 /*
@@ -159,44 +143,8 @@ static void hc_died(struct uhci_hcd *uhci)
  */
 static void check_and_reset_hc(struct uhci_hcd *uhci)
 {
-       u16 legsup;
-       unsigned int cmd, intr;
-
-       /*
-        * 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;
-        *      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) {
-               dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
-                               __FUNCTION__, legsup);
-               goto reset_needed;
-       }
-
-       cmd = inw(uhci->io_addr + USBCMD);
-       if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) {
-               dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n",
-                               __FUNCTION__, cmd);
-               goto reset_needed;
-       }
-
-       intr = inw(uhci->io_addr + USBINTR);
-       if (intr & (~USBINTR_RESUME)) {
-               dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n",
-                               __FUNCTION__, intr);
-               goto reset_needed;
-       }
-       return;
-
-reset_needed:
-       dev_dbg(uhci_dev(uhci), "Performing full reset\n");
-       reset_hc(uhci);
+       if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr))
+               finish_reset(uhci);
 }
 
 /*
@@ -208,7 +156,7 @@ static void configure_hc(struct uhci_hcd *uhci)
        outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
 
        /* Store the frame list base address */
-       outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
+       outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
 
        /* Set the current frame number */
        outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
@@ -277,8 +225,11 @@ __acquires(uhci->lock)
        /* Enable resume-detect interrupts if they work.
         * Then enter Global Suspend mode, still configured.
         */
-       int_enable = (resume_detect_interrupts_are_broken(uhci) ?
-                       0 : USBINTR_RESUME);
+       uhci->working_RD = 1;
+       int_enable = USBINTR_RESUME;
+       if (resume_detect_interrupts_are_broken(uhci)) {
+               uhci->working_RD = int_enable = 0;
+       }
        outw(int_enable, uhci->io_addr + USBINTR);
        outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
        mb();
@@ -305,7 +256,6 @@ __acquires(uhci->lock)
 
        uhci->rh_state = new_state;
        uhci->is_stopped = UHCI_IS_STOPPED;
-       del_timer(&uhci->stall_timer);
        uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
        uhci_scan_schedule(uhci, NULL);
@@ -325,7 +275,6 @@ static void start_rh(struct uhci_hcd *uhci)
        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)
@@ -364,20 +313,6 @@ __acquires(uhci->lock)
        mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
 }
 
-static void stall_callback(unsigned long _uhci)
-{
-       struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
-       unsigned long flags;
-
-       spin_lock_irqsave(&uhci->lock, flags);
-       uhci_scan_schedule(uhci, NULL);
-       check_fsbr(uhci);
-
-       if (!uhci->is_stopped)
-               restart_timer(uhci);
-       spin_unlock_irqrestore(&uhci->lock, flags);
-}
-
 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -408,8 +343,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
                                        "host controller halted, "
                                        "very bad!\n");
                                hc_died(uhci);
-                               spin_unlock_irqrestore(&uhci->lock, flags);
-                               return IRQ_HANDLED;
+
+                               /* Force a callback in case there are
+                                * pending unlinks */
+                               mod_timer(&hcd->rh_timer, jiffies);
                        }
                        spin_unlock_irqrestore(&uhci->lock, flags);
                }
@@ -417,10 +354,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 
        if (status & USBSTS_RD)
                usb_hcd_poll_rh_status(hcd);
-
-       spin_lock_irqsave(&uhci->lock, flags);
-       uhci_scan_schedule(uhci, regs);
-       spin_unlock_irqrestore(&uhci->lock, flags);
+       else {
+               spin_lock_irqsave(&uhci->lock, flags);
+               uhci_scan_schedule(uhci, regs);
+               spin_unlock_irqrestore(&uhci->lock, flags);
+       }
 
        return IRQ_HANDLED;
 }
@@ -443,44 +381,57 @@ static void release_uhci(struct uhci_hcd *uhci)
        int i;
 
        for (i = 0; i < UHCI_NUM_SKELQH; i++)
-               if (uhci->skelqh[i]) {
-                       uhci_free_qh(uhci, uhci->skelqh[i]);
-                       uhci->skelqh[i] = NULL;
-               }
+               uhci_free_qh(uhci, uhci->skelqh[i]);
 
-       if (uhci->term_td) {
-               uhci_free_td(uhci, uhci->term_td);
-               uhci->term_td = NULL;
-       }
+       uhci_free_td(uhci, uhci->term_td);
 
-       if (uhci->qh_pool) {
-               dma_pool_destroy(uhci->qh_pool);
-               uhci->qh_pool = NULL;
-       }
+       dma_pool_destroy(uhci->qh_pool);
 
-       if (uhci->td_pool) {
-               dma_pool_destroy(uhci->td_pool);
-               uhci->td_pool = NULL;
-       }
+       dma_pool_destroy(uhci->td_pool);
 
-       if (uhci->fl) {
-               dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                               uhci->fl, uhci->fl->dma_handle);
-               uhci->fl = NULL;
-       }
+       kfree(uhci->frame_cpu);
 
-       if (uhci->dentry) {
-               debugfs_remove(uhci->dentry);
-               uhci->dentry = NULL;
-       }
+       dma_free_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       uhci->frame, uhci->frame_dma_handle);
+
+       debugfs_remove(uhci->dentry);
 }
 
 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.
         */
@@ -488,6 +439,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
  *
@@ -508,13 +473,9 @@ 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;
-       dma_addr_t dma_handle;
-       struct usb_device *udev;
+       int i;
        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# */
@@ -546,21 +507,23 @@ static int uhci_start(struct usb_hcd *hcd)
 
        init_waitqueue_head(&uhci->waitqh);
 
-       init_timer(&uhci->stall_timer);
-       uhci->stall_timer.function = stall_callback;
-       uhci->stall_timer.data = (unsigned long) uhci;
-
-       uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                       &dma_handle, 0);
-       if (!uhci->fl) {
+       uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       &uhci->frame_dma_handle, 0);
+       if (!uhci->frame) {
                dev_err(uhci_dev(uhci), "unable to allocate "
                                "consistent memory for frame list\n");
-               goto err_alloc_fl;
+               goto err_alloc_frame;
        }
+       memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
 
-       memset((void *)uhci->fl, 0, sizeof(*uhci->fl));
-
-       uhci->fl->dma_handle = dma_handle;
+       uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
+                       GFP_KERNEL);
+       if (!uhci->frame_cpu) {
+               dev_err(uhci_dev(uhci), "unable to allocate "
+                               "memory for frame pointers\n");
+               goto err_alloc_frame_cpu;
+       }
 
        uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
                        sizeof(struct uhci_td), 16, 0);
@@ -576,46 +539,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;
@@ -675,7 +606,7 @@ static int uhci_start(struct usb_hcd *hcd)
                        irq = 7;
 
                /* Only place we don't use the frame list routines */
-               uhci->fl->frame[i] = UHCI_PTR_QH |
+               uhci->frame[i] = UHCI_PTR_QH |
                                cpu_to_le32(uhci->skelqh[irq]->dma_handle);
        }
 
@@ -687,53 +618,35 @@ static int uhci_start(struct usb_hcd *hcd)
 
        configure_hc(uhci);
        start_rh(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:
-       reset_hc(uhci);
-       del_timer_sync(&uhci->stall_timer);
-
 err_alloc_skelqh:
-       for (i = 0; i < UHCI_NUM_SKELQH; i++)
-               if (uhci->skelqh[i]) {
+       for (i = 0; i < UHCI_NUM_SKELQH; i++) {
+               if (uhci->skelqh[i])
                        uhci_free_qh(uhci, uhci->skelqh[i]);
-                       uhci->skelqh[i] = NULL;
-               }
+       }
 
        uhci_free_td(uhci, uhci->term_td);
-       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;
 
 err_create_qh_pool:
        dma_pool_destroy(uhci->td_pool);
-       uhci->td_pool = NULL;
 
 err_create_td_pool:
-       dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                       uhci->fl, uhci->fl->dma_handle);
-       uhci->fl = NULL;
+       kfree(uhci->frame_cpu);
+
+err_alloc_frame_cpu:
+       dma_free_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       uhci->frame, uhci->frame_dma_handle);
 
-err_alloc_fl:
+err_alloc_frame:
        debugfs_remove(uhci->dentry);
-       uhci->dentry = NULL;
 
 err_create_debug_entry:
        return retval;
@@ -744,11 +657,11 @@ static void uhci_stop(struct usb_hcd *hcd)
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
        spin_lock_irq(&uhci->lock);
-       reset_hc(uhci);
+       if (!uhci->hc_inaccessible)
+               hc_died(uhci);
        uhci_scan_schedule(uhci, NULL);
        spin_unlock_irq(&uhci->lock);
 
-       del_timer_sync(&uhci->stall_timer);
        release_uhci(uhci);
 }
 
@@ -793,11 +706,6 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
        if (uhci->hc_inaccessible)      /* Dead or already suspended */
                goto done;
 
-#ifndef CONFIG_USB_SUSPEND
-       /* Otherwise this would never happen */
-       suspend_rh(uhci, UHCI_RH_SUSPENDED);
-#endif
-
        if (uhci->rh_state > UHCI_RH_SUSPENDED) {
                dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
                hcd->state = HC_STATE_RUNNING;
@@ -810,13 +718,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);
        uhci->hc_inaccessible = 1;
+       hcd->poll_rh = 0;
 
        /* FIXME: Enable non-PME# remote wakeup? */
 
 done:
        spin_unlock_irq(&uhci->lock);
-       if (rc == 0)
-               del_timer_sync(&hcd->rh_timer);
        return rc;
 }
 
@@ -840,17 +747,16 @@ static int uhci_resume(struct usb_hcd *hcd)
        check_and_reset_hc(uhci);
        configure_hc(uhci);
 
-#ifndef CONFIG_USB_SUSPEND
-       /* Otherwise this would never happen */
-       wakeup_rh(uhci);
-#endif
        if (uhci->rh_state == UHCI_RH_RESET)
                suspend_rh(uhci, UHCI_RH_SUSPENDED);
 
        spin_unlock_irq(&uhci->lock);
 
-       if (hcd->poll_rh)
+       if (!uhci->working_RD) {
+               /* Suspended root hub needs to be polled */
+               hcd->poll_rh = 1;
                usb_hcd_poll_rh_status(hcd);
+       }
        return 0;
 }
 #endif
@@ -898,8 +804,8 @@ static const struct hc_driver uhci_driver = {
 #ifdef CONFIG_PM
        .suspend =              uhci_suspend,
        .resume =               uhci_resume,
-       .hub_suspend =          uhci_rh_suspend,
-       .hub_resume =           uhci_rh_resume,
+       .bus_suspend =          uhci_rh_suspend,
+       .bus_resume =           uhci_rh_resume,
 #endif
        .stop =                 uhci_stop,
 
@@ -928,6 +834,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,