From owner-p4-projects@FreeBSD.ORG Wed Aug 2 17:56:22 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 9389816A4E2; Wed, 2 Aug 2006 17:56:22 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6EDFF16A4DF for ; Wed, 2 Aug 2006 17:56:22 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id E133643D72 for ; Wed, 2 Aug 2006 17:56:19 +0000 (GMT) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k72HuJ36083707 for ; Wed, 2 Aug 2006 17:56:19 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k72HuJNA083704 for perforce@freebsd.org; Wed, 2 Aug 2006 17:56:19 GMT (envelope-from hselasky@FreeBSD.org) Date: Wed, 2 Aug 2006 17:56:19 GMT Message-Id: <200608021756.k72HuJNA083704@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 103047 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Aug 2006 17:56:22 -0000 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; }