On Sat, 8 Dec 2007, Dr. Peer Griebel wrote: > Dear USB developers > > some time ago (3/4 year) I already reported my problem with the EHCI > driver. There was no response to it. I would like to tell you that my > problem still persists. I just tried it today using the current Gentoo > kernel 2.6.23-gentoo-r3. > > There don't seem to be many people with this problem and it is not very > urgent for me to get it resolved. But I do think that this problem > should be resolved. It is not very easy to find out that there are > "lost IAA" messages since only the debug version of the driver shows the > message. The average user doesn't know about the debug version. The > everage user only sees that his web cam does not work. > > I'm a software developer myself. But I don't know very much about USB. > I would be very glad if I can help you in any way to resolve my problem.
On Sat, 8 Dec 2007, Christian Hoffmann wrote: > Hi, > I am running into a similar crash with a dvb t receiver in end_async_unlink as > reported some month ago on this ML. > > PID: 0 TASK: ffffffff804b7870 CPU: 0 COMMAND: "swapper" > #0 [ffffffff80624b10] machine_kexec at ffffffff8021c00d > #1 [ffffffff80624bc0] crash_kexec at ffffffff80255dbe > #2 [ffffffff80624c80] do_page_fault at ffffffff803fde21 > #3 [ffffffff80624d90] error_exit at ffffffff803fc0fd > [exception RIP: end_unlink_async+34] > RIP: ffffffff8811d20a RSP: ffffffff80624e48 RFLAGS: 00010202 > RAX: 0000000000010029 RBX: ffff81007e098178 RCX: 0000000000000000 > RDX: 0000000000008028 RSI: ffffffff8811fe7e RDI: 0000000000000080 > RBP: 0000000000000000 R8: 0000000000000000 R9: ffffffff8047dc64 > R10: ffff8100022ffc48 R11: 0000000000000246 R12: 0000000000000000 > R13: ffff81007e098178 R14: ffff81007e098000 R15: 0000000000000000 > ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 > #4 [ffffffff80624e60] ehci_work at ffffffff8811d78b > #5 [ffffffff80624ed0] ehci_irq at ffffffff88120d0f > #6 [ffffffff80624f20] usb_hcd_irq at ffffffff880ded82 > #7 [ffffffff80624f30] handle_IRQ_event at ffffffff802603e8 > #8 [ffffffff80624f60] handle_fasteoi_irq at ffffffff802618b6 > #9 [ffffffff80624f90] do_IRQ at ffffffff8020c136 > --- <IRQ stack> --- > #10 [ffffffff805c7e88] ret_from_intr at ffffffff8020a141 > [exception RIP: acpi_safe_halt+40] > RIP: ffffffff88003dc6 RSP: ffffffff805c7f30 RFLAGS: 00000246 > RAX: 0000000000000000 RBX: ffff81007e6760a8 RCX: ffffffff8047dde4 > RDX: 0000000000000007 RSI: 00000000000001c6 RDI: 0000000004000000 > RBP: 0000000000000000 R8: 0000000000000002 R9: ffffffff8047dc64 > R10: ffff8100022ffc48 R11: 0000000000000246 R12: ffffffff805c7f14 > R13: 0000000000001001 R14: ffffffff80332334 R15: 0000000000000000 > ORIG_RAX: ffffffffffffff86 CS: 0010 SS: 0018 > #11 [ffffffff805c7f30] acpi_processor_idle at ffffffff88003ff9 > #12 [ffffffff805c7f70] cpu_idle at ffffffff80208daf > crash> > I use 2.6.22.13-0.3-default on an Acer Laptop. ATI chipset. Anything > else I can provide? For both of you, here is a somewhat experimental patch you can try. It probably won't fix the problem, but it might make the problem easier to diagnose. Along with this patch you should enable CONFIG_USB_DEBUG. If a problem occurs, the contents of the files in /sys/class/usb_host/usb_hostN (where N is the bus number of the EHCI controller in question) will be of interest, especially the "async" and "registers" files. This patch is for 2.6.24-rc4, but it ought to apply with little difficulty to all recent kernels. Alan Stern Index: 2.6.24-rc4/drivers/usb/host/ehci-dbg.c =================================================================== --- 2.6.24-rc4.orig/drivers/usb/host/ehci-dbg.c +++ 2.6.24-rc4/drivers/usb/host/ehci-dbg.c @@ -763,9 +763,7 @@ show_registers (struct class_device *cla } if (ehci->reclaim) { - temp = scnprintf (next, size, "reclaim qh %p%s\n", - ehci->reclaim, - ehci->reclaim_ready ? " ready" : ""); + temp = scnprintf(next, size, "reclaim qh %p\n", ehci->reclaim); size -= temp; next += temp; } Index: 2.6.24-rc4/drivers/usb/host/ehci-hcd.c =================================================================== --- 2.6.24-rc4.orig/drivers/usb/host/ehci-hcd.c +++ 2.6.24-rc4/drivers/usb/host/ehci-hcd.c @@ -109,7 +109,7 @@ static const char hcd_name [] = "ehci_hc #define EHCI_TUNE_MULT_TT 1 #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ -#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_IAA_MSECS 10 /* arbitrary */ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ @@ -266,6 +266,7 @@ static void ehci_quiesce (struct ehci_hc /*-------------------------------------------------------------------------*/ +static void end_unlink_async(struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); #include "ehci-hub.c" @@ -275,25 +276,41 @@ static void ehci_work(struct ehci_hcd *e /*-------------------------------------------------------------------------*/ -static void ehci_watchdog (unsigned long param) +static void ehci_iaa_watchdog(unsigned long param) { struct ehci_hcd *ehci = (struct ehci_hcd *) param; unsigned long flags; + u32 status, cmd; spin_lock_irqsave (&ehci->lock, flags); + WARN_ON(!ehci->reclaim); - /* lost IAA irqs wedge things badly; seen with a vt8235 */ + status = ehci_readl(ehci, &ehci->regs->status); + cmd = ehci_readl(ehci, &ehci->regs->command); + ehci_info(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); + + /* lost IAA irqs wedge things badly; seen first with a vt8235 */ if (ehci->reclaim) { - u32 status = ehci_readl(ehci, &ehci->regs->status); if (status & STS_IAA) { ehci_vdbg (ehci, "lost IAA\n"); COUNT (ehci->stats.lost_iaa); ehci_writel(ehci, STS_IAA, &ehci->regs->status); - ehci->reclaim_ready = 1; } + ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command); + end_unlink_async(ehci); } - /* stop async processing after it's idled a bit */ + spin_unlock_irqrestore(&ehci->lock, flags); +} + +static void ehci_watchdog(unsigned long param) +{ + struct ehci_hcd *ehci = (struct ehci_hcd *) param; + unsigned long flags; + + spin_lock_irqsave(&ehci->lock, flags); + + /* stop async processing after it's idled a bit */ if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) start_unlink_async (ehci, ehci->async); @@ -363,8 +380,6 @@ static void ehci_port_power (struct ehci static void ehci_work (struct ehci_hcd *ehci) { timer_action_done (ehci, TIMER_IO_WATCHDOG); - if (ehci->reclaim_ready) - end_unlink_async (ehci); /* another CPU may drop ehci->lock during a schedule scan while * it reports urb completions. this flag guards against bogus @@ -399,6 +414,7 @@ static void ehci_stop (struct usb_hcd *h /* no more interrupts ... */ del_timer_sync (&ehci->watchdog); + del_timer_sync(&ehci->iaa_watchdog); spin_lock_irq(&ehci->lock); if (HC_IS_RUNNING (hcd->state)) @@ -447,6 +463,10 @@ static int ehci_init(struct usb_hcd *hcd ehci->watchdog.function = ehci_watchdog; ehci->watchdog.data = (unsigned long) ehci; + init_timer(&ehci->iaa_watchdog); + ehci->iaa_watchdog.function = ehci_iaa_watchdog; + ehci->iaa_watchdog.data = (unsigned long) ehci; + /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. @@ -463,7 +483,6 @@ static int ehci_init(struct usb_hcd *hcd ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); ehci->reclaim = NULL; - ehci->reclaim_ready = 0; ehci->next_uframe = -1; /* @@ -654,8 +673,7 @@ static irqreturn_t ehci_irq (struct usb_ /* complete the unlinking of some qh [4.15.2.3] */ if (status & STS_IAA) { COUNT (ehci->stats.reclaim); - ehci->reclaim_ready = 1; - bh = 1; + end_unlink_async(ehci); } /* remote wakeup [4.3.1] */ @@ -761,10 +779,16 @@ static int ehci_urb_enqueue ( static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) { - /* if we need to use IAA and it's busy, defer */ - if (qh->qh_state == QH_STATE_LINKED - && ehci->reclaim - && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { + /* failfast */ + if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) + end_unlink_async(ehci); + + /* if it's not linked then there's nothing to do */ + if (qh->qh_state != QH_STATE_LINKED) + ; + + /* defer till later if busy */ + else if (ehci->reclaim) { struct ehci_qh *last; for (last = ehci->reclaim; @@ -774,12 +798,8 @@ static void unlink_async (struct ehci_hc qh->qh_state = QH_STATE_UNLINK_WAIT; last->reclaim = qh; - /* bypass IAA if the hc can't care */ - } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) - end_unlink_async (ehci); - - /* something else might have unlinked the qh by now */ - if (qh->qh_state == QH_STATE_LINKED) + /* start IAA cycle */ + } else start_unlink_async (ehci, qh); } @@ -806,7 +826,19 @@ static int ehci_urb_dequeue(struct usb_h qh = (struct ehci_qh *) urb->hcpriv; if (!qh) break; - unlink_async (ehci, qh); + switch (qh->qh_state) { + case QH_STATE_LINKED: + case QH_STATE_COMPLETING: + unlink_async(ehci, qh); + break; + case QH_STATE_UNLINK: + case QH_STATE_UNLINK_WAIT: + /* already started */ + break; + case QH_STATE_IDLE: + WARN_ON(1); + break; + } break; case PIPE_INTERRUPT: @@ -898,6 +930,7 @@ rescan: unlink_async (ehci, qh); /* FALL THROUGH */ case QH_STATE_UNLINK: /* wait for hw to finish? */ + case QH_STATE_UNLINK_WAIT: idle_timeout: spin_unlock_irqrestore (&ehci->lock, flags); schedule_timeout_uninterruptible(1); Index: 2.6.24-rc4/drivers/usb/host/ehci-hub.c =================================================================== --- 2.6.24-rc4.orig/drivers/usb/host/ehci-hub.c +++ 2.6.24-rc4/drivers/usb/host/ehci-hub.c @@ -134,7 +134,7 @@ static int ehci_bus_suspend (struct usb_ } ehci->command = ehci_readl(ehci, &ehci->regs->command); if (ehci->reclaim) - ehci->reclaim_ready = 1; + end_unlink_async(ehci); ehci_work(ehci); /* Unlike other USB host controller types, EHCI doesn't have Index: 2.6.24-rc4/drivers/usb/host/ehci-pci.c =================================================================== --- 2.6.24-rc4.orig/drivers/usb/host/ehci-pci.c +++ 2.6.24-rc4/drivers/usb/host/ehci-pci.c @@ -305,7 +305,7 @@ static int ehci_pci_resume(struct usb_hc /* emptying the schedule aborts any urbs */ spin_lock_irq(&ehci->lock); if (ehci->reclaim) - ehci->reclaim_ready = 1; + end_unlink_async(ehci); ehci_work(ehci); spin_unlock_irq(&ehci->lock); Index: 2.6.24-rc4/drivers/usb/host/ehci-q.c =================================================================== --- 2.6.24-rc4.orig/drivers/usb/host/ehci-q.c +++ 2.6.24-rc4/drivers/usb/host/ehci-q.c @@ -973,7 +973,7 @@ static void end_unlink_async (struct ehc struct ehci_qh *qh = ehci->reclaim; struct ehci_qh *next; - timer_action_done (ehci, TIMER_IAA_WATCHDOG); + iaa_watchdog_done(ehci); // qh->hw_next = cpu_to_hc32(qh->qh_dma); qh->qh_state = QH_STATE_IDLE; @@ -983,7 +983,6 @@ static void end_unlink_async (struct ehc /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ next = qh->reclaim; ehci->reclaim = next; - ehci->reclaim_ready = 0; qh->reclaim = NULL; qh_completions (ehci, qh); @@ -1059,11 +1058,10 @@ static void start_unlink_async (struct e return; } - ehci->reclaim_ready = 0; cmd |= CMD_IAAD; ehci_writel(ehci, cmd, &ehci->regs->command); (void)ehci_readl(ehci, &ehci->regs->command); - timer_action (ehci, TIMER_IAA_WATCHDOG); + iaa_watchdog_start(ehci); } /*-------------------------------------------------------------------------*/ Index: 2.6.24-rc4/drivers/usb/host/ehci.h =================================================================== --- 2.6.24-rc4.orig/drivers/usb/host/ehci.h +++ 2.6.24-rc4/drivers/usb/host/ehci.h @@ -74,7 +74,6 @@ struct ehci_hcd { /* one per controlle /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; - unsigned reclaim_ready : 1; unsigned scanning : 1; /* periodic schedule support */ @@ -105,6 +104,7 @@ struct ehci_hcd { /* one per controlle struct dma_pool *itd_pool; /* itd per iso urb */ struct dma_pool *sitd_pool; /* sitd per split iso urb */ + struct timer_list iaa_watchdog; struct timer_list watchdog; unsigned long actions; unsigned stamp; @@ -140,9 +140,21 @@ static inline struct usb_hcd *ehci_to_hc } +static inline void +iaa_watchdog_start(struct ehci_hcd *ehci) +{ + WARN_ON(timer_pending(&ehci->iaa_watchdog)); + mod_timer(&ehci->iaa_watchdog, + jiffies + msecs_to_jiffies(EHCI_IAA_MSECS)); +} + +static inline void iaa_watchdog_done(struct ehci_hcd *ehci) +{ + del_timer(&ehci->iaa_watchdog); +} + enum ehci_timer_action { TIMER_IO_WATCHDOG, - TIMER_IAA_WATCHDOG, TIMER_ASYNC_SHRINK, TIMER_ASYNC_OFF, }; @@ -160,9 +172,6 @@ timer_action (struct ehci_hcd *ehci, enu unsigned long t; switch (action) { - case TIMER_IAA_WATCHDOG: - t = EHCI_IAA_JIFFIES; - break; case TIMER_IO_WATCHDOG: t = EHCI_IO_JIFFIES; break; @@ -179,8 +188,7 @@ timer_action (struct ehci_hcd *ehci, enu // async queue SHRINK often precedes IAA. while it's ready // to go OFF neither can matter, and afterwards the IO // watchdog stops unless there's still periodic traffic. - if (action != TIMER_IAA_WATCHDOG - && t > ehci->watchdog.expires + if (time_before_eq(t, ehci->watchdog.expires) && timer_pending (&ehci->watchdog)) return; mod_timer (&ehci->watchdog, t); - To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html