summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/vscsi.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/sys/dev/vscsi.c b/sys/dev/vscsi.c
index 245b475bc3a..05267d38e6e 100644
--- a/sys/dev/vscsi.c
+++ b/sys/dev/vscsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vscsi.c,v 1.18 2010/09/21 04:33:35 matthew Exp $ */
+/* $OpenBSD: vscsi.c,v 1.19 2010/09/22 03:51:47 dlg Exp $ */
/*
* Copyright (c) 2008 David Gwynne <dlg@openbsd.org>
@@ -62,7 +62,7 @@ struct vscsi_softc {
struct mutex sc_state_mtx;
enum vscsi_state sc_state;
- u_int sc_ccb_count;
+ u_int sc_ref_count;
struct pool sc_ccb_pool;
struct scsi_iopool sc_iopool;
@@ -94,12 +94,13 @@ struct cfdriver vscsi_cd = {
void vscsi_cmd(struct scsi_xfer *);
int vscsi_probe(struct scsi_link *);
+void vscsi_free(struct scsi_link *);
struct scsi_adapter vscsi_switch = {
vscsi_cmd,
scsi_minphys,
vscsi_probe,
- NULL
+ vscsi_free
};
int vscsi_i2t(struct vscsi_softc *, struct vscsi_ioc_i2t *);
@@ -221,15 +222,30 @@ int
vscsi_probe(struct scsi_link *link)
{
struct vscsi_softc *sc = link->adapter_softc;
- int rv;
+ int rv = 0;
mtx_enter(&sc->sc_state_mtx);
- rv = (sc->sc_state == VSCSI_S_RUNNING) ? 0 : ENXIO;
+ if (sc->sc_state == VSCSI_S_RUNNING)
+ sc->sc_ref_count++;
+ else
+ rv = ENXIO;
mtx_leave(&sc->sc_state_mtx);
return (rv);
}
+void
+vscsi_free(struct scsi_link *link)
+{
+ struct vscsi_softc *sc = link->adapter_softc;
+
+ mtx_enter(&sc->sc_state_mtx);
+ sc->sc_ref_count--;
+ if (sc->sc_state != VSCSI_S_RUNNING && sc->sc_ref_count == 0)
+ wakeup(&sc->sc_ref_count);
+ mtx_leave(&sc->sc_state_mtx);
+}
+
int
vscsiopen(dev_t dev, int flags, int mode, struct proc *p)
{
@@ -254,6 +270,7 @@ vscsiopen(dev_t dev, int flags, int mode, struct proc *p)
pool_init(&sc->sc_ccb_pool, sizeof(struct vscsi_ccb), 0, 0, 0,
"vscsiccb", NULL);
+ pool_setipl(&sc->sc_ccb_pool, IPL_BIO);
/* we need to guarantee some ccbs will be available for the iopool */
rv = pool_prime(&sc->sc_ccb_pool, 8);
@@ -527,7 +544,6 @@ vscsiclose(dev_t dev, int flags, int mode, struct proc *p)
{
struct vscsi_softc *sc = DEV2SC(dev);
struct vscsi_ccb *ccb;
- int i;
mtx_enter(&sc->sc_state_mtx);
KASSERT(sc->sc_state == VSCSI_S_RUNNING);
@@ -546,18 +562,17 @@ vscsiclose(dev_t dev, int flags, int mode, struct proc *p)
vscsi_done(sc, ccb);
}
+ scsi_req_detach(sc->sc_scsibus, -1, -1, DETACH_FORCE);
+
mtx_enter(&sc->sc_state_mtx);
- while (sc->sc_ccb_count > 0) {
- msleep(&sc->sc_ccb_count, &sc->sc_state_mtx,
- PRIBIO, "vscsiccb", 0);
+ while (sc->sc_ref_count > 0) {
+ msleep(&sc->sc_ref_count, &sc->sc_state_mtx,
+ PRIBIO, "vscsiref", 0);
}
mtx_leave(&sc->sc_state_mtx);
pool_destroy(&sc->sc_ccb_pool);
- for (i = 0; i < sc->sc_link.adapter_buswidth; i++)
- scsi_detach_target(sc->sc_scsibus, i, DETACH_FORCE);
-
mtx_enter(&sc->sc_state_mtx);
sc->sc_state = VSCSI_S_CLOSED;
mtx_leave(&sc->sc_state_mtx);
@@ -572,15 +587,11 @@ vscsi_ccb_get(void *cookie)
struct vscsi_softc *sc = cookie;
struct vscsi_ccb *ccb = NULL;
- mtx_enter(&sc->sc_state_mtx);
- if (sc->sc_state == VSCSI_S_RUNNING &&
- (ccb = pool_get(&sc->sc_ccb_pool, PR_NOWAIT)) != NULL) {
+ ccb = pool_get(&sc->sc_ccb_pool, PR_NOWAIT);
+ if (ccb != NULL) {
ccb->ccb_tag = sc->sc_ccb_tag++;
ccb->ccb_datalen = 0;
-
- sc->sc_ccb_count++;
}
- mtx_leave(&sc->sc_state_mtx);
return (ccb);
}
@@ -591,14 +602,5 @@ vscsi_ccb_put(void *cookie, void *io)
struct vscsi_softc *sc = cookie;
struct vscsi_ccb *ccb = io;
- mtx_enter(&sc->sc_state_mtx);
-
pool_put(&sc->sc_ccb_pool, ccb);
- sc->sc_ccb_count--;
-
- if (sc->sc_state != VSCSI_S_RUNNING &&
- sc->sc_ccb_count == 0)
- wakeup(&sc->sc_ccb_count);
-
- mtx_leave(&sc->sc_state_mtx);
}