ChangeSet 1.1587.3.51, 2004/05/11 15:57:21-07:00, david-b@pacbell.net [PATCH] USB: OHCI cleanups This splits out a few obvious fixes, to help shrink a PM patch: - when the HC is quiescing, don't schedule any more EDs or re-activate any after unlink completion. - when the HC is suspended, don't access registers through sysfs either. - simplify locking and call for donelist processing drivers/usb/host/ohci-dbg.c | 14 ++++++++++++-- drivers/usb/host/ohci-hcd.c | 6 ++++-- drivers/usb/host/ohci-pci.c | 8 +++++--- drivers/usb/host/ohci-q.c | 17 ++++++++--------- 4 files changed, 29 insertions(+), 16 deletions(-) diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c --- a/drivers/usb/host/ohci-dbg.c Fri May 14 15:28:37 2004 +++ b/drivers/usb/host/ohci-dbg.c Fri May 14 15:28:37 2004 @@ -617,7 +617,17 @@ /* dump driver info, then registers in spec order */ ohci_dbg_sw (ohci, &next, &size, - "%s version " DRIVER_VERSION "\n", hcd_name); + "bus %s, device %s\n" + "%s version " DRIVER_VERSION "\n", + hcd->self.controller->bus->name, + hcd->self.controller->bus_id, + hcd_name); + + if (bus->controller->power.power_state) { + size -= scnprintf (next, size, + "SUSPENDED (no register access)\n"); + goto done; + } ohci_dump_status(ohci, &next, &size); @@ -657,8 +667,8 @@ /* roothub */ ohci_dump_roothub (ohci, 1, &next, &size); +done: spin_unlock_irqrestore (&ohci->lock, flags); - return PAGE_SIZE - size; } static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c Fri May 14 15:28:37 2004 +++ b/drivers/usb/host/ohci-hcd.c Fri May 14 15:28:37 2004 @@ -611,11 +611,13 @@ ohci_dump (ohci, 1); hc_reset (ohci); } - + if (ints & OHCI_INTR_WDH) { if (HCD_IS_RUNNING(hcd->state)) writel (OHCI_INTR_WDH, ®s->intrdisable); - dl_done_list (ohci, dl_reverse_done_list (ohci), ptregs); + spin_lock (&ohci->lock); + dl_done_list (ohci, ptregs); + spin_unlock (&ohci->lock); if (HCD_IS_RUNNING(hcd->state)) writel (OHCI_INTR_WDH, ®s->intrenable); } diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- a/drivers/usb/host/ohci-pci.c Fri May 14 15:28:37 2004 +++ b/drivers/usb/host/ohci-pci.c Fri May 14 15:28:37 2004 @@ -281,6 +281,11 @@ writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); (void) readl (&ohci->regs->intrdisable); + + /* Check for a pending done list */ + if (ohci->hcca->done_head) + dl_done_list (ohci, NULL); + spin_unlock_irq (&ohci->lock); #ifdef CONFIG_PMAC_PBOOK @@ -288,9 +293,6 @@ enable_irq (to_pci_dev(hcd->self.controller)->irq); #endif - /* Check for a pending done list */ - if (ohci->hcca->done_head) - dl_done_list (ohci, dl_reverse_done_list (ohci), NULL); writel (OHCI_INTR_WDH, &ohci->regs->intrenable); /* assume there are TDs on the bulk and control lists */ diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c Fri May 14 15:28:37 2004 +++ b/drivers/usb/host/ohci-q.c Fri May 14 15:28:37 2004 @@ -170,6 +170,9 @@ { int branch; + if (ohci->hcd.state == USB_STATE_QUIESCING) + return -EAGAIN; + ed->state = ED_OPER; ed->ed_prev = 0; ed->ed_next = 0; @@ -867,9 +870,6 @@ u32 td_dma; struct td *td_rev = NULL; struct td *td = NULL; - unsigned long flags; - - spin_lock_irqsave (&ohci->lock, flags); td_dma = le32_to_cpup (&ohci->hcca->done_head); ohci->hcca->done_head = 0; @@ -901,7 +901,6 @@ td_rev = td; td_dma = le32_to_cpup (&td->hwNextTD); } - spin_unlock_irqrestore (&ohci->lock, flags); return td_rev; } @@ -1015,7 +1014,9 @@ } /* maybe reenable control and bulk lists */ - if (HCD_IS_RUNNING(ohci->hcd.state) && !ohci->ed_rm_list) { + if (HCD_IS_RUNNING(ohci->hcd.state) + && ohci->hcd.state != USB_STATE_QUIESCING + && !ohci->ed_rm_list) { u32 command = 0, control = 0; if (ohci->ed_controltail) { @@ -1055,11 +1056,10 @@ * scanning the (re-reversed) donelist as this does. */ static void -dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *regs) +dl_done_list (struct ohci_hcd *ohci, struct pt_regs *regs) { - unsigned long flags; + struct td *td = dl_reverse_done_list (ohci); - spin_lock_irqsave (&ohci->lock, flags); while (td) { struct td *td_next = td->next_dl_td; struct urb *urb = td->urb; @@ -1100,5 +1100,4 @@ td = td_next; } - spin_unlock_irqrestore (&ohci->lock, flags); }