Module Name: src Committed By: christos Date: Tue Jan 29 00:00:16 UTC 2013
Modified Files: src/sys/dev/usb: ehci.c ehcivar.h ohci.c ohcivar.h uhci.c uhcivar.h Log Message: use a pool instead of a linked list to avoid synchronization problems. To generate a diff of this commit: cvs rdiff -u -r1.203 -r1.204 src/sys/dev/usb/ehci.c cvs rdiff -u -r1.40 -r1.41 src/sys/dev/usb/ehcivar.h cvs rdiff -u -r1.231 -r1.232 src/sys/dev/usb/ohci.c cvs rdiff -u -r1.53 -r1.54 src/sys/dev/usb/ohcivar.h cvs rdiff -u -r1.252 -r1.253 src/sys/dev/usb/uhci.c cvs rdiff -u -r1.51 -r1.52 src/sys/dev/usb/uhcivar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/ehci.c diff -u src/sys/dev/usb/ehci.c:1.203 src/sys/dev/usb/ehci.c:1.204 --- src/sys/dev/usb/ehci.c:1.203 Tue Jan 22 07:40:42 2013 +++ src/sys/dev/usb/ehci.c Mon Jan 28 19:00:15 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.203 2013/01/22 12:40:42 jmcneill Exp $ */ +/* $NetBSD: ehci.c,v 1.204 2013/01/29 00:00:15 christos Exp $ */ /* * Copyright (c) 2004-2012 The NetBSD Foundation, Inc. @@ -53,7 +53,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.203 2013/01/22 12:40:42 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.204 2013/01/29 00:00:15 christos Exp $"); #include "ohci.h" #include "uhci.h" @@ -353,6 +353,9 @@ ehci_init(ehci_softc_t *sc) cv_init(&sc->sc_softwake_cv, "ehciab"); cv_init(&sc->sc_doorbell, "ehcidi"); + sc->sc_xferpool = pool_cache_init(sizeof(struct ehci_xfer), 0, 0, 0, + "ehcixfer", NULL, IPL_USB, NULL, NULL, NULL); + sc->sc_doorbell_si = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, ehci_doorbell, sc); sc->sc_pcd_si = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, @@ -1143,7 +1146,6 @@ ehci_childdet(device_t self, device_t ch int ehci_detach(struct ehci_softc *sc, int flags) { - usbd_xfer_handle xfer; int rv = 0; if (sc->sc_child != NULL) @@ -1172,10 +1174,7 @@ ehci_detach(struct ehci_softc *sc, int f mutex_destroy(&sc->sc_intr_lock); #endif - while ((xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers)) != NULL) { - SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); - kmem_free(xfer, sizeof(struct ehci_xfer)); - } + pool_cache_destroy(sc->sc_xferpool); EOWRITE4(sc, EHCI_CONFIGFLAG, 0); @@ -1369,18 +1368,7 @@ ehci_allocx(struct usbd_bus *bus) struct ehci_softc *sc = bus->hci_private; usbd_xfer_handle xfer; - xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - printf("ehci_allocx: xfer=%p not free, 0x%08x\n", xfer, - xfer->busy_free); - } -#endif - } else { - xfer = kmem_alloc(sizeof(struct ehci_xfer), KM_SLEEP); - } + xfer = pool_cache_get(sc->sc_xferpool, PR_NOWAIT); if (xfer != NULL) { memset(xfer, 0, sizeof(struct ehci_xfer)); #ifdef DIAGNOSTIC @@ -1406,7 +1394,7 @@ ehci_freex(struct usbd_bus *bus, usbd_xf printf("ehci_freex: !isdone\n"); } #endif - SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); + pool_cache_put(sc->sc_xferpool, xfer); } Static void Index: src/sys/dev/usb/ehcivar.h diff -u src/sys/dev/usb/ehcivar.h:1.40 src/sys/dev/usb/ehcivar.h:1.41 --- src/sys/dev/usb/ehcivar.h:1.40 Sun Jun 10 02:15:53 2012 +++ src/sys/dev/usb/ehcivar.h Mon Jan 28 19:00:15 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: ehcivar.h,v 1.40 2012/06/10 06:15:53 mrg Exp $ */ +/* $NetBSD: ehcivar.h,v 1.41 2013/01/29 00:00:15 christos Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -29,6 +29,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef _EHCIVAR_H_ +#define _EHCIVAR_H_ + +#include <sys/pool.h> + typedef struct ehci_soft_qtd { ehci_qtd_t qtd; struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */ @@ -162,7 +167,7 @@ typedef struct ehci_softc { u_int32_t sc_eintrs; ehci_soft_qh_t *sc_async_head; - SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ + pool_cache_t sc_xferpool; /* free xfer pool */ struct callout sc_tmo_intrlist; @@ -195,3 +200,5 @@ void ehci_childdet(device_t, device_t); bool ehci_suspend(device_t, const pmf_qual_t *); bool ehci_resume(device_t, const pmf_qual_t *); bool ehci_shutdown(device_t, int); + +#endif /* _EHCIVAR_H_ */ Index: src/sys/dev/usb/ohci.c diff -u src/sys/dev/usb/ohci.c:1.231 src/sys/dev/usb/ohci.c:1.232 --- src/sys/dev/usb/ohci.c:1.231 Tue Jan 22 07:40:43 2013 +++ src/sys/dev/usb/ohci.c Mon Jan 28 19:00:15 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.231 2013/01/22 12:40:43 jmcneill Exp $ */ +/* $NetBSD: ohci.c,v 1.232 2013/01/29 00:00:15 christos Exp $ */ /* * Copyright (c) 1998, 2004, 2005, 2012 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.231 2013/01/22 12:40:43 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.232 2013/01/29 00:00:15 christos Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -359,7 +359,6 @@ int ohci_detach(struct ohci_softc *sc, int flags) { int rv = 0; - usbd_xfer_handle xfer; if (sc->sc_child != NULL) rv = config_detach(sc->sc_child, flags); @@ -381,10 +380,7 @@ ohci_detach(struct ohci_softc *sc, int f if (sc->sc_hcca != NULL) usb_freemem(&sc->sc_bus, &sc->sc_hccadma); - while((xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers)) != NULL) { - SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); - kmem_free(xfer, sizeof(struct ohci_xfer)); - } + pool_cache_destroy(sc->sc_xferpool); return (rv); } @@ -672,7 +668,8 @@ ohci_init(ohci_softc_t *sc) for (i = 0; i < OHCI_HASH_SIZE; i++) LIST_INIT(&sc->sc_hash_itds[i]); - SIMPLEQ_INIT(&sc->sc_free_xfers); + sc->sc_xferpool = pool_cache_init(sizeof(struct ohci_xfer), 0, 0, 0, + "ohcixfer", NULL, IPL_USB, NULL, NULL, NULL); rev = OREAD4(sc, OHCI_REVISION); aprint_normal("OHCI version %d.%d%s\n", @@ -951,20 +948,9 @@ ohci_allocx(struct usbd_bus *bus) struct ohci_softc *sc = bus->hci_private; usbd_xfer_handle xfer; - xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - printf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer, - xfer->busy_free); - } -#endif - } else { - xfer = kmem_alloc(sizeof(struct ohci_xfer), KM_SLEEP); - } + xfer = pool_cache_get(sc->sc_xferpool, PR_NOWAIT); if (xfer != NULL) { - memset(xfer, 0, sizeof (struct ohci_xfer)); + memset(xfer, 0, sizeof(struct ohci_xfer)); #ifdef DIAGNOSTIC xfer->busy_free = XFER_BUSY; #endif @@ -984,7 +970,7 @@ ohci_freex(struct usbd_bus *bus, usbd_xf } xfer->busy_free = XFER_FREE; #endif - SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); + pool_cache_put(sc->sc_xferpool, xfer); } Static void Index: src/sys/dev/usb/ohcivar.h diff -u src/sys/dev/usb/ohcivar.h:1.53 src/sys/dev/usb/ohcivar.h:1.54 --- src/sys/dev/usb/ohcivar.h:1.53 Sun Jun 10 02:15:53 2012 +++ src/sys/dev/usb/ohcivar.h Mon Jan 28 19:00:15 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: ohcivar.h,v 1.53 2012/06/10 06:15:53 mrg Exp $ */ +/* $NetBSD: ohcivar.h,v 1.54 2013/01/29 00:00:15 christos Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -30,6 +30,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef _OHCIVAR_H_ +#define _OHCIVAR_H_ + +#include <sys/pool.h> + typedef struct ohci_soft_ed { ohci_ed_t ed; struct ohci_soft_ed *next; @@ -119,7 +124,7 @@ typedef struct ohci_softc { ohci_soft_td_t *sc_freetds; ohci_soft_itd_t *sc_freeitds; - SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ + pool_cache_t sc_xferpool; /* free xfer pool */ usbd_xfer_handle sc_intrxfer; @@ -151,3 +156,5 @@ void ohci_childdet(device_t, device_t); int ohci_activate(device_t, enum devact); bool ohci_resume(device_t, const pmf_qual_t *); bool ohci_suspend(device_t, const pmf_qual_t *); + +#endif /* _OHCIVAR_H_ */ Index: src/sys/dev/usb/uhci.c diff -u src/sys/dev/usb/uhci.c:1.252 src/sys/dev/usb/uhci.c:1.253 --- src/sys/dev/usb/uhci.c:1.252 Tue Jan 22 07:40:43 2013 +++ src/sys/dev/usb/uhci.c Mon Jan 28 19:00:15 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.252 2013/01/22 12:40:43 jmcneill Exp $ */ +/* $NetBSD: uhci.c,v 1.253 2013/01/29 00:00:15 christos Exp $ */ /* * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.252 2013/01/22 12:40:43 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.253 2013/01/29 00:00:15 christos Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -521,7 +521,8 @@ uhci_init(uhci_softc_t *sc) LIST_INIT(&sc->sc_intrhead); - SIMPLEQ_INIT(&sc->sc_free_xfers); + sc->sc_xferpool = pool_cache_init(sizeof(struct uhci_xfer), 0, 0, 0, + "uhcixfer", NULL, IPL_USB, NULL, NULL, NULL); callout_init(&sc->sc_poll_handle, CALLOUT_MPSAFE); @@ -569,7 +570,6 @@ uhci_childdet(device_t self, device_t ch int uhci_detach(struct uhci_softc *sc, int flags) { - usbd_xfer_handle xfer; int rv = 0; if (sc->sc_child != NULL) @@ -578,14 +578,7 @@ uhci_detach(struct uhci_softc *sc, int f if (rv != 0) return (rv); - /* Free all xfers associated with this HC. */ - for (;;) { - xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); - if (xfer == NULL) - break; - SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); - kmem_free(xfer, sizeof(struct uhci_xfer)); - } + pool_cache_destroy(sc->sc_xferpool); callout_halt(&sc->sc_poll_handle, NULL); callout_destroy(&sc->sc_poll_handle); @@ -654,21 +647,9 @@ uhci_allocx(struct usbd_bus *bus) struct uhci_softc *sc = bus->hci_private; usbd_xfer_handle xfer; - xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - printf("uhci_allocx: xfer=%p not free, 0x%08x\n", xfer, - xfer->busy_free); - } -#endif - } else { - xfer = kmem_alloc(sizeof(struct uhci_xfer), KM_SLEEP); - } + xfer = pool_cache_get(sc->sc_xferpool, PR_NOWAIT); if (xfer != NULL) { - memset(xfer, 0, sizeof (struct uhci_xfer)); - UXFER(xfer)->iinfo.sc = sc; + memset(xfer, 0, sizeof(struct uhci_xfer)); #ifdef DIAGNOSTIC UXFER(xfer)->iinfo.isdone = 1; xfer->busy_free = XFER_BUSY; @@ -692,7 +673,7 @@ uhci_freex(struct usbd_bus *bus, usbd_xf printf("uhci_freex: !isdone\n"); } #endif - SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); + pool_cache_put(sc->sc_xferpool, xfer); } Static void Index: src/sys/dev/usb/uhcivar.h diff -u src/sys/dev/usb/uhcivar.h:1.51 src/sys/dev/usb/uhcivar.h:1.52 --- src/sys/dev/usb/uhcivar.h:1.51 Sun Jun 10 02:15:54 2012 +++ src/sys/dev/usb/uhcivar.h Mon Jan 28 19:00:15 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: uhcivar.h,v 1.51 2012/06/10 06:15:54 mrg Exp $ */ +/* $NetBSD: uhcivar.h,v 1.52 2013/01/29 00:00:15 christos Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -30,6 +30,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef _UHCIVAR_H_ +#define _UHCIVAR_H_ + +#include <sys/pool.h> + /* * To avoid having 1024 TDs for each isochronous transfer we introduce * a virtual frame list. Every UHCI_VFRAMELIST_COUNT entries in the real @@ -152,7 +157,7 @@ typedef struct uhci_softc { uhci_soft_td_t *sc_freetds; /* TD free list */ uhci_soft_qh_t *sc_freeqhs; /* QH free list */ - SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ + pool_cache_t sc_xferpool; /* free xfer pool */ u_int8_t sc_addr; /* device address */ u_int8_t sc_conf; /* device configuration */ @@ -187,3 +192,5 @@ void uhci_childdet(device_t, device_t); int uhci_activate(device_t, enum devact); bool uhci_resume(device_t, const pmf_qual_t *); bool uhci_suspend(device_t, const pmf_qual_t *); + +#endif /* _UHCIVAR_H_ */