Re: [PATCH 3/3] USB: new flag for resume-from-hibernation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux