summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorad <ad@NetBSD.org>2007-02-09 21:55:00 +0000
committerad <ad@NetBSD.org>2007-02-09 21:55:00 +0000
commitb07ec3fc388a5aeae51e8871aa89eefea3ce1e53 (patch)
treec93d3b23a29f98ac0e26c9d43afb509219d0ea42 /sys/dev/ic
parent5c1aad3ad0b9d2403784bd52128e8e8399e22254 (diff)
Merge newlock2 to head.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/cac.c79
-rw-r--r--sys/dev/ic/cacvar.h7
-rw-r--r--sys/dev/ic/ld_cac.c16
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);
}