use a pool instead of a linked list to avoid synchronization problems.
This commit is contained in:
parent
2d523d359a
commit
b9fd652795
@ -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 child)
|
||||
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 flags)
|
||||
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_xfer_handle xfer)
|
||||
printf("ehci_freex: !isdone\n");
|
||||
}
|
||||
#endif
|
||||
SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
|
||||
pool_cache_put(sc->sc_xferpool, xfer);
|
||||
}
|
||||
|
||||
Static void
|
||||
|
@ -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_ */
|
||||
|
@ -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 flags)
|
||||
|
||||
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,18 +948,7 @@ 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));
|
||||
#ifdef DIAGNOSTIC
|
||||
@ -984,7 +970,7 @@ ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
|
||||
}
|
||||
xfer->busy_free = XFER_FREE;
|
||||
#endif
|
||||
SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
|
||||
pool_cache_put(sc->sc_xferpool, xfer);
|
||||
}
|
||||
|
||||
Static void
|
||||
|
@ -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_ */
|
||||
|
@ -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 child)
|
||||
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 flags)
|
||||
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;
|
||||
#ifdef DIAGNOSTIC
|
||||
UXFER(xfer)->iinfo.isdone = 1;
|
||||
xfer->busy_free = XFER_BUSY;
|
||||
@ -692,7 +673,7 @@ uhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
|
||||
printf("uhci_freex: !isdone\n");
|
||||
}
|
||||
#endif
|
||||
SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
|
||||
pool_cache_put(sc->sc_xferpool, xfer);
|
||||
}
|
||||
|
||||
Static void
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user