On Monday 27 April 2009, Alan Stern wrote: > This patch (as1237) changes the way the PCI host controller drivers > avoid retaining bogus hardware states during resume-from-hibernation. > Previously we had reset the hardware as part of preparing to reinstate > the memory image. But we can do better now with the new PM framework, > since we know exactly which resume operations are from hibernation. > > The pci_resume method is changed to accept a flag indicating whether > the system is resuming from hibernation. When this flag is set, the > drivers will reset the hardware to get rid of any existing state. > > Similarly, the pci_suspend method is changed to remove the > pm_message_t argument. It's no longer needed, since no special action > has to be taken when preparing to reinstate the memory image. > > Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> This one looks good too. Acked-by: Rafael J. Wysocki <rjw@xxxxxxx> > --- > > Index: usb-2.6/drivers/usb/core/hcd.h > =================================================================== > --- usb-2.6.orig/drivers/usb/core/hcd.h > +++ usb-2.6/drivers/usb/core/hcd.h > @@ -182,10 +182,10 @@ struct hc_driver { > * a whole, not just the root hub; they're for PCI bus glue. > */ > /* called after suspending the hub, before entering D3 etc */ > - int (*pci_suspend) (struct usb_hcd *hcd, pm_message_t message); > + int (*pci_suspend)(struct usb_hcd *hcd); > > /* called after entering D0 (etc), before resuming the hub */ > - int (*pci_resume) (struct usb_hcd *hcd); > + int (*pci_resume)(struct usb_hcd *hcd, bool hibernated); > > /* cleanly make HCD stop writing memory and doing I/O */ > void (*stop) (struct usb_hcd *hcd); > Index: usb-2.6/drivers/usb/core/hcd-pci.c > =================================================================== > --- usb-2.6.orig/drivers/usb/core/hcd-pci.c > +++ usb-2.6/drivers/usb/core/hcd-pci.c > @@ -237,7 +237,7 @@ static int hcd_pci_suspend(struct device > return retval; > > if (hcd->driver->pci_suspend) { > - retval = hcd->driver->pci_suspend(hcd, PMSG_SUSPEND); > + retval = hcd->driver->pci_suspend(hcd); > suspend_report_result(hcd->driver->pci_suspend, retval); > if (retval) > return retval; > @@ -344,7 +344,7 @@ static int resume_common(struct device * > clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); > > if (hcd->driver->pci_resume) { > - retval = hcd->driver->pci_resume(hcd); > + retval = hcd->driver->pci_resume(hcd, hibernated); > if (retval) { > dev_err(dev, "PCI post-resume error %d!\n", retval); > usb_hc_died(hcd); > Index: usb-2.6/drivers/usb/host/ehci-pci.c > =================================================================== > --- usb-2.6.orig/drivers/usb/host/ehci-pci.c > +++ usb-2.6/drivers/usb/host/ehci-pci.c > @@ -268,7 +268,7 @@ done: > * Also they depend on separate root hub suspend/resume. > */ > > -static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) > +static int ehci_pci_suspend(struct usb_hcd *hcd) > { > struct ehci_hcd *ehci = hcd_to_ehci(hcd); > unsigned long flags; > @@ -293,12 +293,6 @@ static int ehci_pci_suspend(struct usb_h > ehci_writel(ehci, 0, &ehci->regs->intr_enable); > (void)ehci_readl(ehci, &ehci->regs->intr_enable); > > - /* make sure snapshot being resumed re-enumerates everything */ > - if (message.event == PM_EVENT_PRETHAW) { > - ehci_halt(ehci); > - ehci_reset(ehci); > - } > - > clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); > bail: > spin_unlock_irqrestore (&ehci->lock, flags); > @@ -309,7 +303,7 @@ static int ehci_pci_suspend(struct usb_h > return rc; > } > > -static int ehci_pci_resume(struct usb_hcd *hcd) > +static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) > { > struct ehci_hcd *ehci = hcd_to_ehci(hcd); > struct pci_dev *pdev = to_pci_dev(hcd->self.controller); > @@ -322,10 +316,12 @@ static int ehci_pci_resume(struct usb_hc > /* Mark hardware accessible again as we are out of D3 state by now */ > set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); > > - /* If CF is still set, we maintained PCI Vaux power. > + /* If CF is still set and we aren't resuming from hibernation > + * then we maintained PCI Vaux power. > * Just undo the effect of ehci_pci_suspend(). > */ > - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { > + if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && > + !hibernated) { > int mask = INTR_MASK; > > if (!hcd->self.root_hub->do_remote_wakeup) > @@ -335,7 +331,6 @@ static int ehci_pci_resume(struct usb_hc > return 0; > } > > - ehci_dbg(ehci, "lost power, restarting\n"); > usb_root_hub_lost_power(hcd->self.root_hub); > > /* Else reset, to cope with power loss or flush-to-storage > Index: usb-2.6/drivers/usb/host/ohci-pci.c > =================================================================== > --- usb-2.6.orig/drivers/usb/host/ohci-pci.c > +++ usb-2.6/drivers/usb/host/ohci-pci.c > @@ -372,7 +372,7 @@ static int __devinit ohci_pci_start (str > > #ifdef CONFIG_PM > > -static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) > +static int ohci_pci_suspend(struct usb_hcd *hcd) > { > struct ohci_hcd *ohci = hcd_to_ohci (hcd); > unsigned long flags; > @@ -394,10 +394,6 @@ static int ohci_pci_suspend (struct usb_ > ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); > (void)ohci_readl(ohci, &ohci->regs->intrdisable); > > - /* make sure snapshot being resumed re-enumerates everything */ > - if (message.event == PM_EVENT_PRETHAW) > - ohci_usb_reset(ohci); > - > clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); > bail: > spin_unlock_irqrestore (&ohci->lock, flags); > @@ -406,9 +402,14 @@ static int ohci_pci_suspend (struct usb_ > } > > > -static int ohci_pci_resume (struct usb_hcd *hcd) > +static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated) > { > set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); > + > + /* Make sure resume from hibernation re-enumerates everything */ > + if (hibernated) > + ohci_usb_reset(hcd_to_ohci(hcd)); > + > ohci_finish_controller_resume(hcd); > return 0; > } > Index: usb-2.6/drivers/usb/host/uhci-hcd.c > =================================================================== > --- usb-2.6.orig/drivers/usb/host/uhci-hcd.c > +++ usb-2.6/drivers/usb/host/uhci-hcd.c > @@ -769,7 +769,7 @@ static int uhci_rh_resume(struct usb_hcd > return rc; > } > > -static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) > +static int uhci_pci_suspend(struct usb_hcd *hcd) > { > struct uhci_hcd *uhci = hcd_to_uhci(hcd); > int rc = 0; > @@ -795,10 +795,6 @@ static int uhci_pci_suspend(struct usb_h > > /* FIXME: Enable non-PME# remote wakeup? */ > > - /* make sure snapshot being resumed re-enumerates everything */ > - if (message.event == PM_EVENT_PRETHAW) > - uhci_hc_died(uhci); > - > done_okay: > clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); > done: > @@ -806,7 +802,7 @@ done: > return rc; > } > > -static int uhci_pci_resume(struct usb_hcd *hcd) > +static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) > { > struct uhci_hcd *uhci = hcd_to_uhci(hcd); > > @@ -820,6 +816,10 @@ static int uhci_pci_resume(struct usb_hc > > spin_lock_irq(&uhci->lock); > > + /* Make sure resume from hibernation re-enumerates everything */ > + if (hibernated) > + uhci_hc_died(uhci); > + > /* FIXME: Disable non-PME# remote wakeup? */ > > /* The firmware or a boot kernel may have changed the controller > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html