|
@@ -36,6 +36,18 @@
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
+/* hcd->hub_irq_enable() */
|
|
|
+static void ohci_rhsc_enable (struct usb_hcd *hcd)
|
|
|
+{
|
|
|
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
|
|
+
|
|
|
+ spin_lock_irq(&ohci->lock);
|
|
|
+ if (!ohci->autostop)
|
|
|
+ del_timer(&hcd->rh_timer); /* Prevent next poll */
|
|
|
+ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
|
|
|
+ spin_unlock_irq(&ohci->lock);
|
|
|
+}
|
|
|
+
|
|
|
#define OHCI_SCHED_ENABLES \
|
|
|
(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
|
|
|
|
|
@@ -362,28 +374,18 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
|
|
|
int any_connected)
|
|
|
{
|
|
|
int poll_rh = 1;
|
|
|
- int rhsc;
|
|
|
|
|
|
- rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
|
|
|
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
|
|
|
|
|
|
case OHCI_USB_OPER:
|
|
|
- /* If no status changes are pending, enable status-change
|
|
|
- * interrupts.
|
|
|
- */
|
|
|
- if (!rhsc && !changed) {
|
|
|
- rhsc = OHCI_INTR_RHSC;
|
|
|
- ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
|
|
|
- }
|
|
|
-
|
|
|
- /* Keep on polling until we know a device is connected
|
|
|
- * and RHSC is enabled, or until we autostop.
|
|
|
- */
|
|
|
+ /* keep on polling until we know a device is connected
|
|
|
+ * and RHSC is enabled */
|
|
|
if (!ohci->autostop) {
|
|
|
if (any_connected ||
|
|
|
!device_may_wakeup(&ohci_to_hcd(ohci)
|
|
|
->self.root_hub->dev)) {
|
|
|
- if (rhsc)
|
|
|
+ if (ohci_readl(ohci, &ohci->regs->intrenable) &
|
|
|
+ OHCI_INTR_RHSC)
|
|
|
poll_rh = 0;
|
|
|
} else {
|
|
|
ohci->autostop = 1;
|
|
@@ -396,13 +398,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
|
|
|
ohci->autostop = 0;
|
|
|
ohci->next_statechange = jiffies +
|
|
|
STATECHANGE_DELAY;
|
|
|
- } else if (rhsc && time_after_eq(jiffies,
|
|
|
+ } else if (time_after_eq(jiffies,
|
|
|
ohci->next_statechange)
|
|
|
&& !ohci->ed_rm_list
|
|
|
&& !(ohci->hc_control &
|
|
|
OHCI_SCHED_ENABLES)) {
|
|
|
ohci_rh_suspend(ohci, 1);
|
|
|
- poll_rh = 0;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
@@ -416,12 +417,6 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
|
|
|
else
|
|
|
usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
|
|
|
} else {
|
|
|
- if (!rhsc && (ohci->autostop ||
|
|
|
- ohci_to_hcd(ohci)->self.root_hub->
|
|
|
- do_remote_wakeup))
|
|
|
- ohci_writel(ohci, OHCI_INTR_RHSC,
|
|
|
- &ohci->regs->intrenable);
|
|
|
-
|
|
|
/* everything is idle, no need for polling */
|
|
|
poll_rh = 0;
|
|
|
}
|
|
@@ -443,16 +438,12 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
|
|
|
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
|
|
|
int any_connected)
|
|
|
{
|
|
|
- /* If RHSC is enabled, don't poll */
|
|
|
- if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
|
|
|
- return 0;
|
|
|
+ int poll_rh = 1;
|
|
|
|
|
|
- /* If no status changes are pending, enable status-change interrupts */
|
|
|
- if (!changed) {
|
|
|
- ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- return 1;
|
|
|
+ /* keep on polling until RHSC is enabled */
|
|
|
+ if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
|
|
|
+ poll_rh = 0;
|
|
|
+ return poll_rh;
|
|
|
}
|
|
|
|
|
|
#endif /* CONFIG_PM */
|