Date: Wed, 2 Aug 2006 17:56:19 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 103047 for review Message-ID: <200608021756.k72HuJNA083704@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=103047 Change 103047 by hselasky@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; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608021756.k72HuJNA083704>