diff options
| author | thorpej <thorpej@NetBSD.org> | 2003-09-23 23:50:04 +0000 |
|---|---|---|
| committer | thorpej <thorpej@NetBSD.org> | 2003-09-23 23:50:04 +0000 |
| commit | 544359b9a2028eab2daff7d7d3c86c78e4aeea49 (patch) | |
| tree | eb5cab3c06aaf23a4f47de17ffc235d10bb1234c /sys/dev | |
| parent | 08b458c6719057f1c332d0bd62974ec245e95341 (diff) | |
- Make CCB allocation slightly more efficient by changing how the
CCB is returned to the caller.
- Make code paths that can use twe_ccb_alloc_wait() use it, and assert
that a CCB is always returned from that function.
- Assert that a CCB is always returned when allocating the reserved CCB
for an AEN fetch.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/pci/ld_twe.c | 8 | ||||
| -rw-r--r-- | sys/dev/pci/twe.c | 96 | ||||
| -rw-r--r-- | sys/dev/pci/twevar.h | 6 |
3 files changed, 74 insertions, 36 deletions
diff --git a/sys/dev/pci/ld_twe.c b/sys/dev/pci/ld_twe.c index bc11e553220..3eb345e4f7b 100644 --- a/sys/dev/pci/ld_twe.c +++ b/sys/dev/pci/ld_twe.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_twe.c,v 1.16 2003/09/22 18:31:10 thorpej Exp $ */ +/* $NetBSD: ld_twe.c,v 1.17 2003/09/23 23:50:04 thorpej Exp $ */ /*- * Copyright (c) 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld_twe.c,v 1.16 2003/09/22 18:31:10 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_twe.c,v 1.17 2003/09/23 23:50:04 thorpej Exp $"); #include "rnd.h" @@ -188,8 +188,8 @@ ld_twe_dobio(struct ld_twe_softc *sc, void *data, int datasize, int blkno, twe = (struct twe_softc *)sc->sc_ld.sc_dv.dv_parent; flags = (dowrite ? TWE_CCB_DATA_OUT : TWE_CCB_DATA_IN); - if ((rv = twe_ccb_alloc(twe, &ccb, flags)) != 0) - return (rv); + if ((ccb = twe_ccb_alloc(twe, flags)) == NULL) + return (EAGAIN); ccb->ccb_data = data; ccb->ccb_datasize = datasize; diff --git a/sys/dev/pci/twe.c b/sys/dev/pci/twe.c index 3d56d9320f6..47fe569a04b 100644 --- a/sys/dev/pci/twe.c +++ b/sys/dev/pci/twe.c @@ -1,4 +1,4 @@ -/* $NetBSD: twe.c,v 1.48 2003/09/23 23:10:53 thorpej Exp $ */ +/* $NetBSD: twe.c,v 1.49 2003/09/23 23:50:05 thorpej Exp $ */ /*- * Copyright (c) 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: twe.c,v 1.48 2003/09/23 23:10:53 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: twe.c,v 1.49 2003/09/23 23:50:05 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -834,10 +834,9 @@ twe_aen_get(struct twe_softc *sc, uint16_t *aenp) if (tp == NULL) return (ENOMEM); - rv = twe_ccb_alloc(sc, &ccb, + ccb = twe_ccb_alloc(sc, TWE_CCB_AEN | TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT); - if (rv != 0) - goto done; + KASSERT(ccb != NULL); ccb->ccb_data = tp; ccb->ccb_datasize = TWE_SECTOR_SIZE; @@ -1054,6 +1053,8 @@ twe_param_get_4(struct twe_softc *sc, int table_id, int param_id, * and a pointer to a buffer containing the data returned. * * The caller or callback is responsible for freeing the buffer. + * + * NOTE: We assume we can sleep here to wait for a CCB to become available. */ int twe_param_get(struct twe_softc *sc, int table_id, int param_id, size_t size, @@ -1068,9 +1069,8 @@ twe_param_get(struct twe_softc *sc, int table_id, int param_id, size_t size, if (tp == NULL) return ENOMEM; - rv = twe_ccb_alloc(sc, &ccb, TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT); - if (rv != 0) - goto done; + ccb = twe_ccb_alloc_wait(sc, TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT); + KASSERT(ccb != NULL); ccb->ccb_data = tp; ccb->ccb_datasize = TWE_SECTOR_SIZE; @@ -1121,6 +1121,8 @@ done: /* * Execute a TWE_OP_SET_PARAM command. + * + * NOTE: We assume we can sleep here to wait for a CCB to become available. */ static int twe_param_set(struct twe_softc *sc, int table_id, int param_id, size_t size, @@ -1135,9 +1137,8 @@ twe_param_set(struct twe_softc *sc, int table_id, int param_id, size_t size, if (tp == NULL) return ENOMEM; - rv = twe_ccb_alloc(sc, &ccb, TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT); - if (rv != 0) - goto done; + ccb = twe_ccb_alloc_wait(sc, TWE_CCB_DATA_IN | TWE_CCB_DATA_OUT); + KASSERT(ccb != NULL); ccb->ccb_data = tp; ccb->ccb_datasize = TWE_SECTOR_SIZE; @@ -1187,8 +1188,8 @@ twe_init_connection(struct twe_softc *sc) struct twe_cmd *tc; int rv; - if ((rv = twe_ccb_alloc(sc, &ccb, 0)) != 0) - return (rv); + if ((ccb = twe_ccb_alloc(sc, 0)) == NULL) + return (EAGAIN); /* Build the command. */ tc = ccb->ccb_cmd; @@ -1301,24 +1302,36 @@ twe_status_check(struct twe_softc *sc, u_int status) /* * Allocate and initialise a CCB. */ -int -twe_ccb_alloc(struct twe_softc *sc, struct twe_ccb **ccbp, int flags) +static __inline void +twe_ccb_init(struct twe_softc *sc, struct twe_ccb *ccb, int flags) { struct twe_cmd *tc; + + ccb->ccb_tx.tx_handler = NULL; + ccb->ccb_flags = flags; + tc = ccb->ccb_cmd; + tc->tc_status = 0; + tc->tc_flags = 0; + tc->tc_cmdid = ccb->ccb_cmdid; +} + +struct twe_ccb * +twe_ccb_alloc(struct twe_softc *sc, int flags) +{ struct twe_ccb *ccb; int s; s = splbio(); - if ((flags & TWE_CCB_AEN) != 0) { + if (__predict_false((flags & TWE_CCB_AEN) != 0)) { /* Use the reserved CCB. */ ccb = sc->sc_ccbs; } else { /* Allocate a CCB and command block. */ - if (SLIST_FIRST(&sc->sc_ccb_freelist) == NULL) { + if (__predict_false((ccb = + SLIST_FIRST(&sc->sc_ccb_freelist)) == NULL)) { splx(s); - return (EAGAIN); + return (NULL); } - ccb = SLIST_FIRST(&sc->sc_ccb_freelist); SLIST_REMOVE_HEAD(&sc->sc_ccb_freelist, ccb_chain.slist); } #ifdef DIAGNOSTIC @@ -1328,16 +1341,34 @@ twe_ccb_alloc(struct twe_softc *sc, struct twe_ccb **ccbp, int flags) #endif splx(s); - /* Initialise some fields and return. */ - ccb->ccb_tx.tx_handler = NULL; - ccb->ccb_flags = flags; - tc = ccb->ccb_cmd; - tc->tc_status = 0; - tc->tc_flags = 0; - tc->tc_cmdid = ccb->ccb_cmdid; - *ccbp = ccb; + twe_ccb_init(sc, ccb, flags); + return (ccb); +} - return (0); +struct twe_ccb * +twe_ccb_alloc_wait(struct twe_softc *sc, int flags) +{ + struct twe_ccb *ccb; + int s; + + KASSERT((flags & TWE_CCB_AEN) == 0); + + s = splbio(); + while (__predict_false((ccb = + SLIST_FIRST(&sc->sc_ccb_freelist)) == NULL)) { + sc->sc_flags |= TWEF_WAIT_CCB; + (void) tsleep(&sc->sc_ccb_freelist, PRIBIO, "tweccb", 0); + } + SLIST_REMOVE_HEAD(&sc->sc_ccb_freelist, ccb_chain.slist); +#ifdef DIAGNOSTIC + if ((ccb->ccb_flags & TWE_CCB_ALLOCED) != 0) + panic("twe_ccb_alloc_wait: CCB already allocated"); + flags |= TWE_CCB_ALLOCED; +#endif + splx(s); + + twe_ccb_init(sc, ccb, flags); + return (ccb); } /* @@ -1349,9 +1380,14 @@ twe_ccb_free(struct twe_softc *sc, struct twe_ccb *ccb) int s; s = splbio(); - if ((ccb->ccb_flags & TWE_CCB_AEN) == 0) - SLIST_INSERT_HEAD(&sc->sc_ccb_freelist, ccb, ccb_chain.slist); ccb->ccb_flags = 0; + if ((ccb->ccb_flags & TWE_CCB_AEN) == 0) { + SLIST_INSERT_HEAD(&sc->sc_ccb_freelist, ccb, ccb_chain.slist); + if (__predict_false((sc->sc_flags & TWEF_WAIT_CCB) != 0)) { + sc->sc_flags &= ~TWEF_WAIT_CCB; + wakeup(&sc->sc_ccb_freelist); + } + } splx(s); } diff --git a/sys/dev/pci/twevar.h b/sys/dev/pci/twevar.h index ac2dd606fd3..b7bb3b0b3bc 100644 --- a/sys/dev/pci/twevar.h +++ b/sys/dev/pci/twevar.h @@ -1,4 +1,4 @@ -/* $NetBSD: twevar.h,v 1.19 2003/09/23 23:08:54 thorpej Exp $ */ +/* $NetBSD: twevar.h,v 1.20 2003/09/23 23:50:05 thorpej Exp $ */ /*- * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc. @@ -86,6 +86,7 @@ struct twe_softc { #define TWEF_OPEN 0x01 /* control device is opened */ #define TWEF_AENQ_WAIT 0x02 /* someone waiting for AENs */ #define TWEF_AEN 0x04 /* AEN fetch in progress */ +#define TWEF_WAIT_CCB 0x08 /* someone waiting for a CCB */ /* Optional per-command context. */ struct twe_context { @@ -122,7 +123,8 @@ struct twe_attach_args { #define tweacf_unit cf_loc[TWECF_UNIT] -int twe_ccb_alloc(struct twe_softc *, struct twe_ccb **, int); +struct twe_ccb *twe_ccb_alloc(struct twe_softc *, int); +struct twe_ccb *twe_ccb_alloc_wait(struct twe_softc *, int); void twe_ccb_enqueue(struct twe_softc *sc, struct twe_ccb *ccb); void twe_ccb_free(struct twe_softc *sc, struct twe_ccb *); int twe_ccb_map(struct twe_softc *, struct twe_ccb *); |
