PERFORCE change 103047 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Aug 2 17:56:22 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=103047
Change 103047 by hselasky at hselasky_mini_itx on 2006/08/02 17:55:20
Improve support for polling USB transfers:
1) Make sure that the polling thread does not
read USB host controller status registers,
blocking host controller interrupts.
2) Make sure that the polling thread handles
poll transfers only, and the interrupt thread
interrupt transfers only, and simplify the check.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/ehci.c#8 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.c#8 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.c#8 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/ehci.c#8 (text+ko) ====
@@ -1059,19 +1059,16 @@
* and callback must be called else zero
*/
static u_int8_t
-ehci_check_transfer(struct usbd_xfer *xfer)
+ehci_check_transfer(struct usbd_xfer *xfer, struct thread *ctd)
{
DPRINTFN(15, ("xfer=%p\n", xfer));
- if(xfer->usb_thread)
+ if(xfer->usb_thread != ctd)
{
- if(xfer->usb_thread != curthread)
- {
- /* cannot call this transfer
- * back due to locking !
- */
- goto done;
- }
+ /* cannot call this transfer
+ * back due to locking !
+ */
+ goto done;
}
if(xfer->pipe->methods == &ehci_device_isoc_fs_methods)
@@ -1205,8 +1202,8 @@
return;
}
-void
-ehci_interrupt(ehci_softc_t *sc)
+static void
+ehci_interrupt_td(ehci_softc_t *sc, struct thread *ctd)
{
enum { FINISH_LIST_MAX = 16 };
@@ -1232,6 +1229,15 @@
goto done;
}
+ if(ctd)
+ {
+ /* the poll thread should not read
+ * any status registers that will
+ * clear interrupts!
+ */
+ goto repeat;
+ }
+
sc->sc_bus.no_intrs++;
DPRINTFN(15,("%s: real interrupt\n",
@@ -1322,7 +1328,7 @@
/* check if transfer is
* transferred
*/
- if(ehci_check_transfer(xfer))
+ if(ehci_check_transfer(xfer, ctd))
{
/* queue callback */
ptr->xfer = xfer;
@@ -1358,6 +1364,13 @@
return;
}
+void
+ehci_interrupt(ehci_softc_t *sc)
+{
+ ehci_interrupt_td(sc, NULL);
+ return;
+}
+
/*
* called when a request does not complete
*/
@@ -1390,7 +1403,7 @@
static void
ehci_do_poll(struct usbd_bus *bus)
{
- ehci_interrupt(EHCI_BUS2SC(bus));
+ ehci_interrupt_td(EHCI_BUS2SC(bus), curthread);
return;
}
==== //depot/projects/usb/src/sys/dev/usb/ohci.c#8 (text+ko) ====
@@ -839,21 +839,18 @@
* and callback must be called; else zero
*/
static u_int8_t
-ohci_check_transfer(struct usbd_xfer *xfer)
+ohci_check_transfer(struct usbd_xfer *xfer, struct thread *ctd)
{
ohci_ed_t *ed = xfer->qh_start;
DPRINTFN(15, ("xfer=%p\n", xfer));
- if(xfer->usb_thread)
+ if(xfer->usb_thread != ctd)
{
- if(xfer->usb_thread != curthread)
- {
- /* cannot call this transfer
- * back due to locking !
- */
- return 0;
- }
+ /* cannot call this transfer
+ * back due to locking !
+ */
+ return 0;
}
if((ed->ed_flags & htole32(OHCI_ED_SKIP)) ||
@@ -928,8 +925,8 @@
return;
}
-void
-ohci_interrupt(ohci_softc_t *sc)
+static void
+ohci_interrupt_td(ohci_softc_t *sc, struct thread *ctd)
{
enum { FINISH_LIST_MAX = 16 };
@@ -948,6 +945,15 @@
goto done;
}
+ if(ctd)
+ {
+ /* the poll thread should not read
+ * any status registers that will
+ * clear interrupts!
+ */
+ goto repeat;
+ }
+
sc->sc_bus.no_intrs++;
DPRINTFN(15,("%s: real interrupt\n",
@@ -1074,7 +1080,7 @@
/* check if transfer is
* transferred
*/
- if(ohci_check_transfer(xfer))
+ if(ohci_check_transfer(xfer, ctd))
{
/* queue callback */
ptr->xfer = xfer;
@@ -1110,6 +1116,13 @@
return;
}
+void
+ohci_interrupt(ohci_softc_t *sc)
+{
+ ohci_interrupt_td(sc, NULL);
+ return;
+}
+
/*
* called when a request does not complete
*/
@@ -1142,7 +1155,7 @@
static void
ohci_do_poll(struct usbd_bus *bus)
{
- ohci_interrupt(OHCI_BUS2SC(bus));
+ ohci_interrupt_td(OHCI_BUS2SC(bus), curthread);
return;
}
==== //depot/projects/usb/src/sys/dev/usb/uhci.c#8 (text+ko) ====
@@ -927,21 +927,18 @@
* and callback must be called; else zero
*/
static u_int8_t
-uhci_check_transfer(struct usbd_xfer *xfer)
+uhci_check_transfer(struct usbd_xfer *xfer, struct thread *ctd)
{
uhci_td_t *td;
DPRINTFN(15, ("xfer=%p\n", xfer));
- if(xfer->usb_thread)
+ if(xfer->usb_thread != ctd)
{
- if(xfer->usb_thread != curthread)
- {
- /* cannot call this transfer
- * back due to locking !
- */
- return 0;
- }
+ /* cannot call this transfer
+ * back due to locking !
+ */
+ goto done;
}
td = xfer->td_transfer_last;
@@ -1021,8 +1018,8 @@
return 1;
}
-void
-uhci_interrupt(uhci_softc_t *sc)
+static void
+uhci_interrupt_td(uhci_softc_t *sc, struct thread *ctd)
{
enum { FINISH_LIST_MAX = 16 };
@@ -1053,6 +1050,15 @@
goto done;
}
+ if(ctd)
+ {
+ /* the poll thread should not read
+ * any status registers that will
+ * clear interrupts!
+ */
+ goto repeat;
+ }
+
sc->sc_bus.no_intrs++;
DPRINTFN(15,("%s: real interrupt\n",
@@ -1128,7 +1134,7 @@
/* check if transfer is
* transferred
*/
- if(uhci_check_transfer(xfer))
+ if(uhci_check_transfer(xfer, ctd))
{
/* queue callback */
ptr->xfer = xfer;
@@ -1164,6 +1170,13 @@
return;
}
+void
+uhci_interrupt(uhci_softc_t *sc)
+{
+ uhci_interrupt_td(sc, NULL);
+ return;
+}
+
/*
* called when a request does not complete
*/
@@ -1196,7 +1209,7 @@
static void
uhci_do_poll(struct usbd_bus *bus)
{
- uhci_interrupt(UHCI_BUS2SC(bus));
+ uhci_interrupt_td(UHCI_BUS2SC(bus), curthread);
return;
}
More information about the p4-projects
mailing list