Re: soft lockup in 2.6.26-rc1+git, on Fire V100 - USB again

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 21 Aug 2008, Meelis Roos wrote:

> > But please turn this thing off and see if that clears everything
> > up.
> 
> Well, it cleared the strange hang up and got to USB problem again.
> Now I can see the looping in usb startup. Note that there really is a 
> 'getting stuck' mesasage somewhere down in the messages.

> usb_hcd_poll_rh_status start
> usb_hcd_poll_rh_status: uses_new_polling=1, status_urb=fffff8006e0f18c0 
> usb_hcd_poll_rh_status before hub_status_data
> ohci_hub_status_data before spin_lock_irqsave
> ohci_hub_status_data after spin_lock_irqsave
> ohci_hub_status_data return
> usb_hcd_poll_rh_status after hub_status_data
> hub 1-0:1.0: state 7 ports 2 chg 0000 evt 0000

> ...
> (and so on)

Okay.  My theory is that your OHCI controller hardware is defective and
is failing to turn off one of the interrupt-enable bits when it should.  
Thus your CPU gets caught in a permanent interrupt loop.

That is, in ohci-hcd.c:ohci_irq(), this code is running over and over:

	if (ints & OHCI_INTR_RHSC) {
		ohci_vdbg(ohci, "rhsc\n");
		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
		ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
				&regs->intrstatus);

		/* NOTE: Vendors didn't always make the same implementation
		 * choices for RHSC.  Many followed the spec; RHSC triggers
		 * on an edge, like setting and maybe clearing a port status
		 * change bit.  With others it's level-triggered, active
		 * until khubd clears all the port status change bits.  We'll
		 * always disable it here and rely on polling until khubd
		 * re-enables it.
		 */
		ohci_writel(ohci, OHCI_INTR_RHSC, &regs->intrdisable);
		usb_hcd_poll_rh_status(hcd);
	}

You can verify this easily enough.  If I'm right, it explains why 
usb_hcd_poll_rh_status() keeps being called constantly.

The ohci_writel call near the end is supposed to clear the RHSC
interrupt-enable bit.  You can tell whether it worked by printing out
the value of

	ohci_readl(ohci, &regs->intrenable) & OHCI_INTR_RHSC

immediately afterward.

The earlier ohci_writel call is supposed to clear the RHSC
interrupt-status bit.  You can test whether that worked by printing out

	ohci_readl(ohci, &regs->intrstatus) & OHCI_INTR_RHSC

In addition, you should take a look at ohci_rhsc_enable() in
ohci-hub.c.  That's the place where RHSC interrupts get re-enabled, so
make sure it isn't getting called by mistake.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Development]     [DCCP]     [Linux ARM Development]     [Linux]     [Photo]     [Yosemite Help]     [Linux ARM Kernel]     [Linux SCSI]     [Linux x86_64]     [Linux Hams]

  Powered by Linux