Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Nov 2005 03:47:23 +0000
From:      Ian Dowse <iedowse@iedowse.com>
To:        freebsd-usb@freebsd.org
Subject:   ohci patch
Message-ID:  <200511200347.aa87008@nowhere.iedowse.com>

next in thread | raw e-mail | index | archive | help

There's a patch at

	http://people.freebsd.org/~iedowse/ohci_td.diff

that attempts to fix a number of incorrect assumptions and bad
behaviours in the OHCI host controller driver. If you've seen
problems that are specific to the ohci controller (i.e. things work
fine with uhci or ehci), then there is a possibility that this may
help.

A more detailed description is below.

Ian


The ohci driver's processing of completed transfer descriptors
appeared to rely on all kinds of non-guaranteed behaviours: the
transfer abort code assumed that TDs with no interrupt timeout
configured would end up on the done queue within 20ms, the done
queue processing assumed that all TDs from a transfer would appear
at the same time, and there were access-after-free bugs triggered
on failed transfers.

Attempt to fix these problems by the following changes:
 - Use a maximum (6-frame) interrupt delay instead of no interrupt
   delay to ensure that the 20ms wait in ohci_abort_xfer() is enough
   for the TDs to have been taken off the hardware done queue.
 - Defer cancellation of timeouts and freeing of TDs until we either
   hit an error or reach the final TD.
 - Remove TDs from the done queue before freeing them so that it
   is safe to continue traversing the done queue.

This appears to fix a hang that was reproducable with revision 1.67
or 1.68 of ulpt.c (earlier revisions had a different transfer
pattern). With certain HP printers, the command "true > /dev/ulpt0"
would cause ohci_add_done() to spin because the done queue had a
loop. The list corruption was caused by a 3-TD transfer where the
first TD completed but remained on the internal host controller
done queue because it had no interrupt timeout. When the transfer
timed out, the TD got freed and reused, so it caused a loop in the
done queue when it was inserted a second time from a different
transfer.






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200511200347.aa87008>