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