Commit 56b4783d authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: misc ohci tweaks

Various minor OHCI tweaks;

    - Fix osdl bugid=2503 by:
	* Change needlessly-scarey message (WARN_ON dumps stack)
	* Tries cleaning up, as if it's just IRQ lossage.

    - Force IRQs off when shutting down a controller that was
      already stopped ... just in case.

    - Allow suspending OHCI during driver initialization, to
      support more aggressive power management.

    - Fix some misleading/wrong debug messages.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 18d898df
...@@ -340,6 +340,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) ...@@ -340,6 +340,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
goto done; goto done;
if (!HCD_IS_RUNNING (ohci->hcd.state)) { if (!HCD_IS_RUNNING (ohci->hcd.state)) {
sanitize:
ed->state = ED_IDLE; ed->state = ED_IDLE;
finish_unlinks (ohci, 0, NULL); finish_unlinks (ohci, 0, NULL);
} }
...@@ -347,7 +348,10 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) ...@@ -347,7 +348,10 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
switch (ed->state) { switch (ed->state) {
case ED_UNLINK: /* wait for hw to finish? */ case ED_UNLINK: /* wait for hw to finish? */
/* major IRQ delivery trouble loses INTR_SF too... */ /* major IRQ delivery trouble loses INTR_SF too... */
WARN_ON (limit-- == 0); if (limit-- == 0) {
ohci_warn (ohci, "IRQ INTR_SF lossage\n");
goto sanitize;
}
spin_unlock_irqrestore (&ohci->lock, flags); spin_unlock_irqrestore (&ohci->lock, flags);
set_current_state (TASK_UNINTERRUPTIBLE); set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (1); schedule_timeout (1);
...@@ -671,6 +675,8 @@ static void ohci_stop (struct usb_hcd *hcd) ...@@ -671,6 +675,8 @@ static void ohci_stop (struct usb_hcd *hcd)
flush_scheduled_work(); flush_scheduled_work();
if (HCD_IS_RUNNING(ohci->hcd.state)) if (HCD_IS_RUNNING(ohci->hcd.state))
hc_reset (ohci); hc_reset (ohci);
else
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
remove_debug_files (ohci); remove_debug_files (ohci);
ohci_mem_cleanup (ohci); ohci_mem_cleanup (ohci);
......
...@@ -190,7 +190,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -190,7 +190,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
break; break;
case OHCI_USB_RESUME: case OHCI_USB_RESUME:
/* HCFS changes sometime after INTR_RD */ /* HCFS changes sometime after INTR_RD */
ohci_info (ohci, "remote wakeup\n"); ohci_info (ohci, "wakeup\n");
break; break;
case OHCI_USB_OPER: case OHCI_USB_OPER:
ohci_dbg (ohci, "odd resume\n"); ohci_dbg (ohci, "odd resume\n");
...@@ -515,7 +515,7 @@ static int ohci_hub_control ( ...@@ -515,7 +515,7 @@ static int ohci_hub_control (
#ifndef OHCI_VERBOSE_DEBUG #ifndef OHCI_VERBOSE_DEBUG
if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
#endif #endif
dbg_port (ohci, "GetStatus", wIndex + 1, temp); dbg_port (ohci, "GetStatus", wIndex, temp);
break; break;
case SetHubFeature: case SetHubFeature:
switch (wValue) { switch (wValue) {
......
...@@ -31,6 +31,7 @@ static struct usb_hcd *ohci_hcd_alloc (void) ...@@ -31,6 +31,7 @@ static struct usb_hcd *ohci_hcd_alloc (void)
if (ohci != 0) { if (ohci != 0) {
memset (ohci, 0, sizeof (struct ohci_hcd)); memset (ohci, 0, sizeof (struct ohci_hcd));
ohci->hcd.product_desc = "OHCI Host Controller"; ohci->hcd.product_desc = "OHCI Host Controller";
ohci->next_statechange = jiffies;
spin_lock_init (&ohci->lock); spin_lock_init (&ohci->lock);
INIT_LIST_HEAD (&ohci->pending); INIT_LIST_HEAD (&ohci->pending);
INIT_WORK (&ohci->rh_resume, ohci_rh_resume, &ohci->hcd); INIT_WORK (&ohci->rh_resume, ohci_rh_resume, &ohci->hcd);
......
...@@ -924,7 +924,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) ...@@ -924,7 +924,7 @@ finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
/* only take off EDs that the HC isn't using, accounting for /* only take off EDs that the HC isn't using, accounting for
* frame counter wraps and EDs with partially retired TDs * frame counter wraps and EDs with partially retired TDs
*/ */
if (likely (HCD_IS_RUNNING(ohci->hcd.state))) { if (likely (regs && HCD_IS_RUNNING(ohci->hcd.state))) {
if (tick_before (tick, ed->tick)) { if (tick_before (tick, ed->tick)) {
skip_ed: skip_ed:
last = &ed->ed_next; last = &ed->ed_next;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment