This patch has some updates to the hcd pci power management glue:

- removes now-obsolete comments (driver model now exists)

 - better state transitions:
     * suspending "dead" controllers needn't oops
     * multi-resume case (pm bug) simplified
     * multi-suspend case likewise (not always a bug)
     * should handle transitions other than D0->D3{hot,cold}

 - prepares for usb remote wake up support, which will be
   wanting the driver model suspend/resume code to be ready.

Please merge to test4.

- Dave

--- 1.19/drivers/usb/core/hcd-pci.c     Wed Aug  6 04:52:20 2003
+++ edited/drivers/usb/core/hcd-pci.c   Tue Aug 12 16:19:01 2003
@@ -257,33 +257,6 @@
 
 #ifdef CONFIG_PM
 
-/*
- * Some "sleep" power levels imply updating struct usb_driver
- * to include a callback asking hcds to do their bit by checking
- * if all the drivers can suspend.  Gets involved with remote wakeup.
- *
- * If there are pending urbs, then HCs will need to access memory,
- * causing extra power drain.  New sleep()/wakeup() PM calls might
- * be needed, beyond PCI suspend()/resume().  The root hub timer
- * still be accessing memory though ...
- *
- * FIXME:  USB should have some power budgeting support working with
- * all kinds of hubs.
- *
- * FIXME:  This assumes only D0->D3 suspend and D3->D0 resume.
- * D1 and D2 states should do something, yes?
- *
- * FIXME:  Should provide generic enable_wake(), calling pci_enable_wake()
- * for all supported states, so that USB remote wakeup can work for any
- * devices that support it (and are connected via powered hubs).
- *
- * FIXME:  resume doesn't seem to work right any more...
- */
-
-
-// 2.4 kernels have issued concurrent resumes (w/APM)
-// we defend against that error; PCI doesn't yet.
-
 /**
  * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
  * @dev: USB Host Controller being suspended
@@ -294,20 +267,29 @@
 int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
 {
        struct usb_hcd          *hcd;
-       int                     retval;
+       int                     retval = 0;
 
        hcd = pci_get_drvdata(dev);
-       dev_info (hcd->controller, "suspend to state %d\n", state);
-
-       pci_save_state (dev, hcd->pci_state);
-
-       // FIXME for all connected devices, leaf-to-root:
-       // driver->suspend()
-       // proposed "new 2.5 driver model" will automate that
-
-       /* driver may want to disable DMA etc */
-       retval = hcd->driver->suspend (hcd, state);
-       hcd->state = USB_STATE_SUSPENDED;
+       switch (hcd->state) {
+       case USB_STATE_HALT:
+               dev_dbg (hcd->controller, "halted; hcd not suspended\n");
+               break;
+       case USB_STATE_SUSPENDED:
+               dev_dbg (hcd->controller, "suspend D%d --> D%d\n",
+                               dev->current_state, state);
+               break;
+       default:
+               dev_dbg (hcd->controller, "suspend to state %d\n", state);
+
+               /* remote wakeup needs hub->suspend() cooperation */
+               // pci_enable_wake (dev, 3, 1);
+
+               pci_save_state (dev, hcd->pci_state);
+
+               /* driver may want to disable DMA etc */
+               retval = hcd->driver->suspend (hcd, state);
+               hcd->state = USB_STATE_SUSPENDED;
+       }
 
        pci_set_power_state (dev, state);
        return retval;
@@ -326,39 +308,24 @@
        int                     retval;
 
        hcd = pci_get_drvdata(dev);
-       dev_info (hcd->controller, "resume\n");
-
-       /* guard against multiple resumes (APM bug?) */
-       atomic_inc (&hcd->resume_count);
-       if (atomic_read (&hcd->resume_count) != 1) {
-               dev_err (hcd->controller, "concurrent PCI resumes\n");
-               retval = 0;
-               goto done;
-       }
-
-       retval = -EBUSY;
        if (hcd->state != USB_STATE_SUSPENDED) {
                dev_dbg (hcd->controller, "can't resume, not suspended!\n");
-               goto done;
+               return -EL3HLT;
        }
        hcd->state = USB_STATE_RESUMING;
 
        pci_set_power_state (dev, 0);
        pci_restore_state (dev, hcd->pci_state);
 
+       /* remote wakeup needs hub->suspend() cooperation */
+       // pci_enable_wake (dev, 3, 0);
+
        retval = hcd->driver->resume (hcd);
        if (!HCD_IS_RUNNING (hcd->state)) {
                dev_dbg (hcd->controller, "resume fail, retval %d\n", retval);
                usb_hc_died (hcd);
-// FIXME:  recover, reset etc.
-       } else {
-               // FIXME for all connected devices, root-to-leaf:
-               // driver->resume ();
-               // proposed "new 2.5 driver model" will automate that
        }
 
-done:
-       atomic_dec (&hcd->resume_count);
        return retval;
 }
 EXPORT_SYMBOL (usb_hcd_pci_resume);
--- 1.32/drivers/usb/core/hcd.h Fri Aug  1 05:03:12 2003
+++ edited/drivers/usb/core/hcd.h       Tue Aug 12 16:13:35 2003
@@ -82,7 +82,6 @@
 #ifdef CONFIG_PCI
        int                     region;         /* pci region for regs */
        u32                     pci_state [16]; /* for PM state save */
-       atomic_t                resume_count;   /* multiple resumes issue */
 #endif
 
 #define HCD_BUFFER_POOLS       4
@@ -220,11 +219,8 @@
 extern void usb_hcd_pci_remove (struct pci_dev *dev);
 
 #ifdef CONFIG_PM
-// FIXME:  see Documentation/power/pci.txt (2.4.6 and later?)
-// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
 extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
 extern int usb_hcd_pci_resume (struct pci_dev *dev);
-// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
 #endif /* CONFIG_PM */
 
 #endif /* CONFIG_PCI */

Reply via email to