diff options
| author | ad <ad@NetBSD.org> | 2007-02-09 21:55:00 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2007-02-09 21:55:00 +0000 |
| commit | b07ec3fc388a5aeae51e8871aa89eefea3ce1e53 (patch) | |
| tree | c93d3b23a29f98ac0e26c9d43afb509219d0ea42 /sys/dev/ic | |
| parent | 5c1aad3ad0b9d2403784bd52128e8e8399e22254 (diff) | |
Merge newlock2 to head.
Diffstat (limited to 'sys/dev/ic')
| -rw-r--r-- | sys/dev/ic/cac.c | 79 | ||||
| -rw-r--r-- | sys/dev/ic/cacvar.h | 7 | ||||
| -rw-r--r-- | sys/dev/ic/ld_cac.c | 16 |
3 files changed, 66 insertions, 36 deletions
diff --git a/sys/dev/ic/cac.c b/sys/dev/ic/cac.c index 6eeae583569..fac89bd5336 100644 --- a/sys/dev/ic/cac.c +++ b/sys/dev/ic/cac.c @@ -1,7 +1,7 @@ -/* $NetBSD: cac.c,v 1.38 2006/12/29 14:07:08 ad Exp $ */ +/* $NetBSD: cac.c,v 1.39 2007/02/09 21:55:27 ad Exp $ */ /*- - * Copyright (c) 2000, 2006 The NetBSD Foundation, Inc. + * Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.38 2006/12/29 14:07:08 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cac.c,v 1.39 2007/02/09 21:55:27 ad Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -108,6 +108,8 @@ cac_init(struct cac_softc *sc, const char *intrstr, int startfw) SIMPLEQ_INIT(&sc->sc_ccb_free); SIMPLEQ_INIT(&sc->sc_ccb_queue); + mutex_init(&sc->sc_mutex, MUTEX_DRIVER, IPL_BIO); + cv_init(&sc->sc_ccb_cv, "cacccb"); size = sizeof(struct cac_ccb) * CAC_MAX_CCBS; @@ -197,7 +199,10 @@ cac_init(struct cac_softc *sc, const char *intrstr, int startfw) if (cac_sdh == NULL) cac_sdh = shutdownhook_establish(cac_shutdown, NULL); + mutex_enter(&sc->sc_mutex); (*sc->sc_cl.cl_intr_enable)(sc, CAC_INTR_ENABLE); + mutex_exit(&sc->sc_mutex); + return (0); } @@ -247,22 +252,24 @@ cac_intr(void *cookie) { struct cac_softc *sc; struct cac_ccb *ccb; + int rv; sc = (struct cac_softc *)cookie; - if (!(*sc->sc_cl.cl_intr_pending)(sc)) { -#ifdef DEBUG - printf("%s: spurious intr\n", sc->sc_dv.dv_xname); -#endif - return (0); - } + mutex_enter(&sc->sc_mutex); - while ((ccb = (*sc->sc_cl.cl_completed)(sc)) != NULL) { - cac_ccb_done(sc, ccb); - cac_ccb_start(sc, NULL); - } + if ((*sc->sc_cl.cl_intr_pending)(sc)) { + while ((ccb = (*sc->sc_cl.cl_completed)(sc)) != NULL) { + cac_ccb_done(sc, ccb); + cac_ccb_start(sc, NULL); + } + rv = 1; + } else + rv = 0; + + mutex_exit(&sc->sc_mutex); - return (1); + return (rv); } /* @@ -274,7 +281,7 @@ cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, { struct cac_ccb *ccb; struct cac_sgb *sgb; - int s, i, rv, size, nsegs; + int i, rv, size, nsegs; size = 0; @@ -324,9 +331,10 @@ cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, ccb->ccb_flags = flags; ccb->ccb_datasize = size; + mutex_enter(&sc->sc_mutex); + if (context == NULL) { memset(&ccb->ccb_context, 0, sizeof(struct cac_context)); - s = splbio(); /* Synchronous commands musn't wait. */ if ((*sc->sc_cl.cl_fifo_full)(sc)) { @@ -342,23 +350,24 @@ cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, } } else { memcpy(&ccb->ccb_context, context, sizeof(struct cac_context)); - s = splbio(); (void)cac_ccb_start(sc, ccb); rv = 0; } - splx(s); + mutex_exit(&sc->sc_mutex); return (rv); } /* - * Wait for the specified CCB to complete. Must be called at splbio. + * Wait for the specified CCB to complete. */ static int cac_ccb_poll(struct cac_softc *sc, struct cac_ccb *wantccb, int timo) { struct cac_ccb *ccb; + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); + timo *= 1000; do { @@ -381,12 +390,14 @@ cac_ccb_poll(struct cac_softc *sc, struct cac_ccb *wantccb, int timo) /* * Enqueue the specified command (if any) and attempt to start all enqueued - * commands. Must be called at splbio. + * commands. */ static int cac_ccb_start(struct cac_softc *sc, struct cac_ccb *ccb) { + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); + if (ccb != NULL) SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ccb, ccb_chain); @@ -415,6 +426,8 @@ cac_ccb_done(struct cac_softc *sc, struct cac_ccb *ccb) error = 0; + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); + #ifdef DIAGNOSTIC if ((ccb->ccb_flags & CAC_CCB_ACTIVE) == 0) panic("cac_ccb_done: CCB not active"); @@ -454,9 +467,8 @@ static struct cac_ccb * cac_ccb_alloc(struct cac_softc *sc, int nosleep) { struct cac_ccb *ccb; - int s; - s = splbio(); + mutex_enter(&sc->sc_mutex); for (;;) { if ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) != NULL) { @@ -467,10 +479,10 @@ cac_ccb_alloc(struct cac_softc *sc, int nosleep) ccb = NULL; break; } - tsleep(&sc->sc_ccb_free, PRIBIO, "cacccb", 0); + cv_wait(&sc->sc_ccb_cv, &sc->sc_mutex); } - splx(s); + mutex_exit(&sc->sc_mutex); return (ccb); } @@ -480,14 +492,13 @@ cac_ccb_alloc(struct cac_softc *sc, int nosleep) static void cac_ccb_free(struct cac_softc *sc, struct cac_ccb *ccb) { - int s; + + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); ccb->ccb_flags = 0; - s = splbio(); + if (SIMPLEQ_EMPTY(&sc->sc_ccb_free)) + cv_signal(&sc->sc_ccb_cv); SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain); - if (SIMPLEQ_NEXT(ccb, ccb_chain) == NULL) - wakeup_one(&sc->sc_ccb_free); - splx(s); } /* @@ -498,6 +509,8 @@ static int cac_l0_fifo_full(struct cac_softc *sc) { + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); + return (cac_inl(sc, CAC_REG_CMD_FIFO) == 0); } @@ -505,6 +518,8 @@ static void cac_l0_submit(struct cac_softc *sc, struct cac_ccb *ccb) { + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); + bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, (caddr_t)ccb - sc->sc_ccbs, sizeof(struct cac_ccb), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); cac_outl(sc, CAC_REG_CMD_FIFO, ccb->ccb_paddr); @@ -516,6 +531,8 @@ cac_l0_completed(struct cac_softc *sc) struct cac_ccb *ccb; paddr_t off; + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); + if ((off = cac_inl(sc, CAC_REG_DONE_FIFO)) == 0) return (NULL); @@ -539,6 +556,8 @@ static int cac_l0_intr_pending(struct cac_softc *sc) { + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); + return (cac_inl(sc, CAC_REG_INTR_PENDING) & CAC_INTR_ENABLE); } @@ -546,6 +565,8 @@ static void cac_l0_intr_enable(struct cac_softc *sc, int state) { + LOCK_ASSERT(mutex_owned(&sc->sc_mutex)); + cac_outl(sc, CAC_REG_INTR_MASK, state ? CAC_INTR_ENABLE : CAC_INTR_DISABLE); } diff --git a/sys/dev/ic/cacvar.h b/sys/dev/ic/cacvar.h index a5d48e71ee3..d6f9a7a9aef 100644 --- a/sys/dev/ic/cacvar.h +++ b/sys/dev/ic/cacvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: cacvar.h,v 1.13 2006/12/28 19:17:12 ad Exp $ */ +/* $NetBSD: cacvar.h,v 1.14 2007/02/09 21:55:27 ad Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -39,6 +39,9 @@ #ifndef _IC_CACVAR_H_ #define _IC_CACVAR_H_ +#include <sys/mutex.h> +#include <sys/condvar.h> + #define CAC_MAX_CCBS 256 #define CAC_MAX_XFER (0xffff * 512) #define CAC_SG_SIZE 32 @@ -106,6 +109,7 @@ struct cac_linkage { struct cac_softc { struct device sc_dv; + kmutex_t sc_mutex; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; bus_dma_tag_t sc_dmat; @@ -116,6 +120,7 @@ struct cac_softc { paddr_t sc_ccbs_paddr; SIMPLEQ_HEAD(, cac_ccb) sc_ccb_free; SIMPLEQ_HEAD(, cac_ccb) sc_ccb_queue; + kcondvar_t sc_ccb_cv; struct cac_linkage sc_cl; }; diff --git a/sys/dev/ic/ld_cac.c b/sys/dev/ic/ld_cac.c index 6059ffe58cc..a4876e44f02 100644 --- a/sys/dev/ic/ld_cac.c +++ b/sys/dev/ic/ld_cac.c @@ -1,7 +1,7 @@ -/* $NetBSD: ld_cac.c,v 1.16 2006/11/28 20:29:14 ad Exp $ */ +/* $NetBSD: ld_cac.c,v 1.17 2007/02/09 21:55:27 ad Exp $ */ /*- - * Copyright (c) 2000 The NetBSD Foundation, Inc. + * Copyright (c) 2000, 2006 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ld_cac.c,v 1.16 2006/11/28 20:29:14 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_cac.c,v 1.17 2007/02/09 21:55:27 ad Exp $"); #include "rnd.h" @@ -67,9 +67,10 @@ __KERNEL_RCSID(0, "$NetBSD: ld_cac.c,v 1.16 2006/11/28 20:29:14 ad Exp $"); struct ld_cac_softc { struct ld_softc sc_ld; + kmutex_t *sc_mutex; int sc_hwunit; - struct timeval sc_serrtm; int sc_serrcnt; + struct timeval sc_serrtm; }; void ld_cac_attach(struct device *, struct device *, void *); @@ -106,6 +107,7 @@ ld_cac_attach(struct device *parent, struct device *self, void *aux) caca = (struct cac_attach_args *)aux; sc->sc_hwunit = caca->caca_unit; cac = (struct cac_softc *)parent; + sc->sc_mutex = &cac->sc_mutex; if (cac_cmd(cac, CAC_CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo), sc->sc_hwunit, 0, CAC_CCB_DATA_IN, NULL)) { @@ -194,6 +196,7 @@ ld_cac_done(struct device *dv, void *context, int error) bp = context; rv = 0; + sc = device_private(dv); if ((error & CAC_RET_CMD_REJECTED) == CAC_RET_CMD_REJECTED) { printf("%s: command rejected\n", dv->dv_xname); @@ -208,12 +211,11 @@ ld_cac_done(struct device *dv, void *context, int error) rv = EIO; } if (rv == 0 && (error & CAC_RET_SOFT_ERROR) != 0) { - sc = (struct ld_cac_softc *)dv; sc->sc_serrcnt++; if (ratecheck(&sc->sc_serrtm, &ld_cac_serrintvl)) { + sc->sc_serrcnt = 0; printf("%s: %d soft errors; array may be degraded\n", dv->dv_xname, sc->sc_serrcnt); - sc->sc_serrcnt = 0; } } @@ -224,5 +226,7 @@ ld_cac_done(struct device *dv, void *context, int error) } else bp->b_resid = 0; + mutex_exit(sc->sc_mutex); lddone((struct ld_softc *)dv, bp); + mutex_enter(sc->sc_mutex); } |
