maybe_print_eds (controller, "donehead",
ohci_readl (controller, ®s->donehead), next, size);
-
- /* broken fminterval means traffic won't flow! */
- ohci_dbg (controller, "fminterval %08x\n",
- ohci_readl (controller, ®s->fminterval));
}
#define dbg_port_sw(hc,num,value,next,size) \
ohci_vdbg (ohci, "resume detect\n");
ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus);
if (hcd->state != HC_STATE_QUIESCING)
- schedule_work(&ohci->rh_resume);
+ usb_hcd_resume_root_hub(hcd);
}
if (ints & OHCI_INTR_WDH) {
ohci_dbg (ohci, "suspend root hub\n");
/* First stop any processing */
- hcd->state = HC_STATE_QUIESCING;
if (ohci->hc_control & OHCI_SCHED_ENABLES) {
int limit;
else
ohci->hc_control &= ~OHCI_CTRL_RWE;
- /* Suspend hub */
+ /* Suspend hub ... this is the "global (to this bus) suspend" mode,
+ * which doesn't imply ports will first be individually suspended.
+ */
ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_SUSPEND;
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
ohci->next_statechange = jiffies + msecs_to_jiffies (5);
done:
+ /* external suspend vs self autosuspend ... same effect */
if (status == 0)
- hcd->state = HC_STATE_SUSPENDED;
+ usb_hcd_suspend_root_hub(hcd);
spin_unlock_irqrestore (&ohci->lock, flags);
return status;
}
ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
- /* this can happen after suspend-to-disk */
+ /* this can happen after resuming a swsusp snapshot */
if (hcd->state == HC_STATE_RESUMING) {
ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
ohci->hc_control);
ohci_info (ohci, "wakeup\n");
break;
case OHCI_USB_OPER:
- ohci_dbg (ohci, "already resumed\n");
- status = 0;
+ /* this can happen after resuming a swsusp snapshot */
+ ohci_dbg (ohci, "snapshot resume? reinit\n");
+ status = -EBUSY;
break;
default: /* RESET, we lost power */
- ohci_dbg (ohci, "root hub hardware reset\n");
+ ohci_dbg (ohci, "lost power\n");
status = -EBUSY;
}
spin_unlock_irq (&ohci->lock);
}
/* Some controllers (lucent erratum) need extra-long delays */
- hcd->state = HC_STATE_RESUMING;
- mdelay (20 /* usb 11.5.1.10 */ + 15);
+ msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
temp = ohci_readl (ohci, &ohci->regs->control);
temp &= OHCI_CTRL_HCFS;
(void) ohci_readl (ohci, &ohci->regs->control);
}
- hcd->state = HC_STATE_RUNNING;
return 0;
}
-static void ohci_rh_resume (void *_hcd)
-{
- struct usb_hcd *hcd = _hcd;
-
- usb_lock_device (hcd->self.root_hub);
- (void) ohci_hub_resume (hcd);
- usb_unlock_device (hcd->self.root_hub);
-}
-
-#else
-
-static void ohci_rh_resume (void *_hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci (_hcd);
- ohci_dbg(ohci, "rh_resume ??\n");
-}
-
#endif /* CONFIG_PM */
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_PM
/* save power by suspending idle root hubs;
* INTR_RD wakes us when there's work
- * NOTE: if we can do this, we don't need a root hub timer!
*/
if (can_suspend
&& !changed
) {
ohci_vdbg (ohci, "autosuspend\n");
(void) ohci_hub_suspend (hcd);
- hcd->state = HC_STATE_RUNNING;
usb_unlock_device (hcd->self.root_hub);
}
#endif
temp = RH_PS_POCI;
if ((ohci->hc_control & OHCI_CTRL_HCFS)
!= OHCI_USB_OPER)
- schedule_work (&ohci->rh_resume);
+ usb_hcd_resume_root_hub(hcd);
break;
case USB_PORT_FEAT_C_SUSPEND:
temp = RH_PS_PSSC;
ohci->next_statechange = jiffies;
spin_lock_init (&ohci->lock);
INIT_LIST_HEAD (&ohci->pending);
- INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci));
ohci->reboot_notifier.notifier_call = ohci_reboot;
}
static int ohci_omap_suspend(struct device *dev, pm_message_t message)
{
struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
- int status = -EINVAL;
-
- down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
- status = ohci_hub_suspend(ohci_to_hcd(ohci));
- if (status == 0) {
- omap_ohci_clock_power(0);
- ohci_to_hcd(ohci)->self.root_hub->state =
- USB_STATE_SUSPENDED;
- ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
- dev->power.power_state = PMSG_SUSPEND;
- }
- up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
- return status;
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ omap_ohci_clock_power(0);
+ ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+ dev->power.power_state = PMSG_SUSPEND;
+ return 0;
}
static int ohci_omap_resume(struct device *dev)
{
struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
- int status = 0;
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
+
omap_ohci_clock_power(1);
-#ifdef CONFIG_USB_SUSPEND
- /* get extra cleanup even if remote wakeup isn't in use */
- status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
-#else
- down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
- status = ohci_hub_resume(ohci_to_hcd(ohci));
- up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-#endif
- if (status == 0)
- dev->power.power_state = PMSG_ON;
- return status;
+ dev->power.power_state = PMSG_ON;
+ usb_hcd_resume_root_hub(dev_get_drvdata(dev));
+ return 0;
}
#endif
static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-
- /* suspend root hub, hoping it keeps power during suspend */
- if (time_before (jiffies, ohci->next_statechange))
- msleep (100);
-
-#ifdef CONFIG_USB_SUSPEND
- (void) usb_suspend_device (hcd->self.root_hub);
-#else
- usb_lock_device (hcd->self.root_hub);
- (void) ohci_hub_suspend (hcd);
- usb_unlock_device (hcd->self.root_hub);
-#endif
+ /* root hub was already suspended */
- /* let things settle down a bit */
- msleep (100);
-
+ /* FIXME these PMAC things get called in the wrong places. ASIC
+ * clocks should be turned off AFTER entering D3, and on BEFORE
+ * trying to enter D0. Evidently the PCI layer doesn't currently
+ * provide the right sort of platform hooks for this ...
+ */
#ifdef CONFIG_PPC_PMAC
if (_machine == _MACH_Pmac) {
struct device_node *of_node;
static int ohci_pci_resume (struct usb_hcd *hcd)
{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int retval = 0;
-
#ifdef CONFIG_PPC_PMAC
if (_machine == _MACH_Pmac) {
struct device_node *of_node;
}
#endif /* CONFIG_PPC_PMAC */
- /* resume root hub */
- if (time_before (jiffies, ohci->next_statechange))
- msleep (100);
-#ifdef CONFIG_USB_SUSPEND
- /* get extra cleanup even if remote wakeup isn't in use */
- retval = usb_resume_device (hcd->self.root_hub);
-#else
- usb_lock_device (hcd->self.root_hub);
- retval = ohci_hub_resume (hcd);
- usb_unlock_device (hcd->self.root_hub);
-#endif
-
- return retval;
+ usb_hcd_resume_root_hub(hcd);
+ return 0;
}
#endif /* CONFIG_PM */
unsigned long next_statechange; /* suspend/resume */
u32 fminterval; /* saved register */
- struct work_struct rh_resume;
struct notifier_block reboot_notifier;
unsigned long flags; /* for HC bugs */