Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 316996
b: refs/heads/master
c: c5cf921
h: refs/heads/master
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Jul 9, 2012
1 parent 3cd1de2 commit 378af3a
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 349 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 336c5c310e8f0d5baba7973765339eaf5d989fe1
refs/heads/master: c5cf9212a368d88fe1e25797699b167f6daa64a5
73 changes: 4 additions & 69 deletions trunk/drivers/usb/host/ehci-au1xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,28 +158,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned long flags;
int rc = 0;

if (time_before(jiffies, ehci->next_statechange))
msleep(10);

/* Root hub was already suspended. Disable irq emission and
* mark HW unaccessible. The PM and USB cores make sure that
* the root hub is either suspended or stopped.
*/
ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
spin_lock_irqsave(&ehci->lock, flags);
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
(void)ehci_readl(ehci, &ehci->regs->intr_enable);

clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
spin_unlock_irqrestore(&ehci->lock, flags);

// could save FLADJ in case of Vaux power loss
// ... we'd only use it to handle clock skew
bool do_wakeup = device_may_wakeup(dev);
int rc;

rc = ehci_suspend(hcd, do_wakeup);
alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);

return rc;
Expand All @@ -188,56 +170,9 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);

alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);

// maybe restore FLADJ

if (time_before(jiffies, ehci->next_statechange))
msleep(100);

/* 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.
* Just undo the effect of ehci_pci_suspend().
*/
if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
int mask = INTR_MASK;

ehci_prepare_ports_for_controller_resume(ehci);
if (!hcd->self.root_hub->do_remote_wakeup)
mask &= ~STS_PCD;
ehci_writel(ehci, mask, &ehci->regs->intr_enable);
ehci_readl(ehci, &ehci->regs->intr_enable);
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
* style "resume" having let BIOS kick in during reboot.
*/
(void) ehci_halt(ehci);
(void) ehci_reset(ehci);

/* emptying the schedule aborts any urbs */
spin_lock_irq(&ehci->lock);
if (ehci->reclaim)
end_unlink_async(ehci);
ehci_work(ehci);
spin_unlock_irq(&ehci->lock);

ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */

/* here we "know" root ports should always stay powered */
ehci_port_power(ehci, 1);

ehci->rh_state = EHCI_RH_SUSPENDED;
ehci_resume(hcd, false);

return 0;
}
Expand Down
89 changes: 89 additions & 0 deletions trunk/drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,95 @@ static int ehci_get_frame (struct usb_hcd *hcd)
}

/*-------------------------------------------------------------------------*/

#ifdef CONFIG_PM

/* suspend/resume, section 4.3 */

/* These routines handle the generic parts of controller suspend/resume */

static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);

if (time_before(jiffies, ehci->next_statechange))
msleep(10);

/*
* Root hub was already suspended. Disable IRQ emission and
* mark HW unaccessible. The PM and USB cores make sure that
* the root hub is either suspended or stopped.
*/
ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);

spin_lock_irq(&ehci->lock);
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
(void) ehci_readl(ehci, &ehci->regs->intr_enable);

clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
spin_unlock_irq(&ehci->lock);

return 0;
}

/* Returns 0 if power was preserved, 1 if power was lost */
static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);

if (time_before(jiffies, ehci->next_statechange))
msleep(100);

/* Mark hardware accessible again as we are back to full power by now */
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

/*
* If CF is still set and we aren't resuming from hibernation
* then we maintained suspend power.
* Just undo the effect of ehci_suspend().
*/
if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
!hibernated) {
int mask = INTR_MASK;

ehci_prepare_ports_for_controller_resume(ehci);
if (!hcd->self.root_hub->do_remote_wakeup)
mask &= ~STS_PCD;
ehci_writel(ehci, mask, &ehci->regs->intr_enable);
ehci_readl(ehci, &ehci->regs->intr_enable);
return 0;
}

/*
* Else reset, to cope with power loss or resume from hibernation
* having let the firmware kick in during reboot.
*/
usb_root_hub_lost_power(hcd->self.root_hub);
(void) ehci_halt(ehci);
(void) ehci_reset(ehci);

/* emptying the schedule aborts any urbs */
spin_lock_irq(&ehci->lock);
if (ehci->reclaim)
end_unlink_async(ehci);
ehci_work(ehci);
spin_unlock_irq(&ehci->lock);

ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */

/* here we "know" root ports should always stay powered */
ehci_port_power(ehci, 1);

ehci->rh_state = EHCI_RH_SUSPENDED;
return 1;
}

#endif

/*-------------------------------------------------------------------------*/

/*
* The EHCI in ChipIdea HDRC cannot be a separate module or device,
* because its registers (and irq) are shared between host/gadget/otg
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/usb/host/ehci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
ehci->owned_ports = 0;
}

static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
static int ehci_port_change(struct ehci_hcd *ehci)
{
int i = HCS_N_PORTS(ehci->hcs_params);

Expand All @@ -128,7 +128,7 @@ static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
return 0;
}

static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
bool suspending, bool do_wakeup)
{
int port;
Expand Down
19 changes: 3 additions & 16 deletions trunk/drivers/usb/host/ehci-msm.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,32 +198,19 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
static int ehci_msm_pm_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
bool wakeup = device_may_wakeup(dev);
bool do_wakeup = device_may_wakeup(dev);

dev_dbg(dev, "ehci-msm PM suspend\n");

/*
* EHCI helper function has also the same check before manipulating
* port wakeup flags. We do check here the same condition before
* calling the same helper function to avoid bringing hardware
* from Low power mode when there is no need for adjusting port
* wakeup flags.
*/
if (hcd->self.root_hub->do_remote_wakeup && !wakeup) {
pm_runtime_resume(dev);
ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
wakeup);
}

return 0;
return ehci_suspend(hcd, do_wakeup);
}

static int ehci_msm_pm_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);

dev_dbg(dev, "ehci-msm PM resume\n");
ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
ehci_resume(hcd, false);

return 0;
}
Expand Down
74 changes: 3 additions & 71 deletions trunk/drivers/usb/host/ehci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,29 +331,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)

static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned long flags;
int rc = 0;

if (time_before(jiffies, ehci->next_statechange))
msleep(10);

/* Root hub was already suspended. Disable irq emission and
* mark HW unaccessible. The PM and USB cores make sure that
* the root hub is either suspended or stopped.
*/
ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
spin_lock_irqsave (&ehci->lock, flags);
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
(void)ehci_readl(ehci, &ehci->regs->intr_enable);

clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
spin_unlock_irqrestore (&ehci->lock, flags);

// could save FLADJ in case of Vaux power loss
// ... we'd only use it to handle clock skew

return rc;
return ehci_suspend(hcd, do_wakeup);
}

static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
Expand Down Expand Up @@ -402,54 +380,8 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
if (usb_is_intel_switchable_ehci(pdev))
ehci_enable_xhci_companion();

// maybe restore FLADJ

if (time_before(jiffies, ehci->next_statechange))
msleep(100);

/* 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 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 &&
!hibernated) {
int mask = INTR_MASK;

ehci_prepare_ports_for_controller_resume(ehci);
if (!hcd->self.root_hub->do_remote_wakeup)
mask &= ~STS_PCD;
ehci_writel(ehci, mask, &ehci->regs->intr_enable);
ehci_readl(ehci, &ehci->regs->intr_enable);
return 0;
}

usb_root_hub_lost_power(hcd->self.root_hub);

/* Else reset, to cope with power loss or flush-to-storage
* style "resume" having let BIOS kick in during reboot.
*/
(void) ehci_halt(ehci);
(void) ehci_reset(ehci);
(void) ehci_pci_reinit(ehci, pdev);

/* emptying the schedule aborts any urbs */
spin_lock_irq(&ehci->lock);
if (ehci->reclaim)
end_unlink_async(ehci);
ehci_work(ehci);
spin_unlock_irq(&ehci->lock);

ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */

/* here we "know" root ports should always stay powered */
ehci_port_power(ehci, 1);

ehci->rh_state = EHCI_RH_SUSPENDED;
if (ehci_resume(hcd, hibernated) != 0)
(void) ehci_pci_reinit(ehci, pdev);
return 0;
}
#endif
Expand Down
7 changes: 3 additions & 4 deletions trunk/drivers/usb/host/ehci-platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,16 @@ static int __devexit ehci_platform_remove(struct platform_device *dev)
static int ehci_platform_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
bool wakeup = device_may_wakeup(dev);
bool do_wakeup = device_may_wakeup(dev);

ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup);
return 0;
return ehci_suspend(hcd, do_wakeup);
}

static int ehci_platform_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);

ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
ehci_resume(hcd, false);
return 0;
}

Expand Down
Loading

0 comments on commit 378af3a

Please sign in to comment.