On Wed, Feb 22, 2012 at 06:59:38PM +0100, Nils wrote:
Op dinsdag 21-02-2012 om 19:31 uur [tijdzone -0500], schreef Kevin O'Connor:
Well, that's not good. I was assuming that the earlier problems were due to a sloppy free, but it looks like something else is confusing the controller. The previous and current errors are probably related. It's odd that control messages seem to be handled properly while the frame_no and interrupt lists aren't. To fix this, more debugging is needed to see what's going wrong at what point. You can start with the patch below.
See attachment for the corresponding log.
[...]
OHCI init on dev 00:0f.4 (regs=0xfe00e000) pmm_malloc zone=0x1f7bfec4 handle=ffffffff size=256 align=100 ret=0x1f7cff00 (detail=0x1f7b7000) pmm_malloc zone=0x1f7bfec4 handle=ffffffff size=16 align=10 ret=0x1f7cfef0 (detail=0x1f7b6fd0) ohci init: c=97 h=0x1f7cff00 h=1f7cff00 f=0
[...]
ohci wait: c=87 h=0x1f7cff00 f=236 WARNING - Timeout at ohci_waittick:134!
That's odd. It looks like the controller was running for 236ms and then freezes. The only thing I can think of to track this down is to sprinkle dprintf() statements through the code until we find what caused the controller to stop.
As an example of more debugging, see the patch below. I think you'll likely need to keep adding statements until finding the place where the counter stops.
Another thing to check is to see if the Linux code has any quirks for this particular controller.
-Kevin
--- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -123,6 +123,8 @@ ohci_waittick(struct usb_ohci_s *cntl) { barrier(); struct ohci_hcca *hcca = (void*)cntl->regs->hcca; + dprintf(1, "ohci wait: c=%x h=%p f=%d s=%x\n" + , cntl->regs->control, hcca, hcca->frame_no, cntl->regs->intrstatus); u32 startframe = hcca->frame_no; u64 end = calc_future_tsc(1000 * 5); for (;;) { @@ -130,6 +132,8 @@ ohci_waittick(struct usb_ohci_s *cntl) break; if (check_tsc(end)) { warn_timeout(); + dprintf(1, "ohci to: c=%x h=%p f=%d s=%x\n" + , cntl->regs->control, hcca, hcca->frame_no, cntl->regs->intrstatus); return; } yield(); @@ -141,11 +145,16 @@ ohci_free_pipes(struct usb_ohci_s *cntl) { dprintf(7, "ohci_free_pipes %p\n", cntl);
+ struct ohci_hcca *hcca = (void*)cntl->regs->hcca; + dprintf(1, "ohci fp: c=%x h=%p f=%d s=%x\n" + , cntl->regs->control, hcca, hcca->frame_no, cntl->regs->intrstatus); u32 creg = readl(&cntl->regs->control); if (creg & (OHCI_CTRL_CLE|OHCI_CTRL_BLE)) { writel(&cntl->regs->control, creg & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE)); ohci_waittick(cntl); } + dprintf(1, "ohci fp2: c=%x h=%p f=%d s=%x\n" + , cntl->regs->control, hcca, hcca->frame_no, cntl->regs->intrstatus);
u32 *pos = &cntl->regs->ed_controlhead; for (;;) { @@ -214,6 +223,9 @@ start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca) | OHCI_USB_OPER | oldrwc)); readl(&cntl->regs->control); // flush writes
+ dprintf(1, "ohci init: c=%x h=%p f=%d s=%x\n" + , cntl->regs->control, hcca, hcca->frame_no, cntl->regs->intrstatus); + return 0; }