diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2010-09-22 03:51:48 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2010-09-22 03:51:48 +0000 |
commit | 6282beeb12aa3874a83b4a3f1ebdcac6324818f0 (patch) | |
tree | 3cb0107ed3871517829114a42037ee6573e81b9b /sys/dev/vscsi.c | |
parent | e41d9f7ea16f7ce341e82419efe19761578e7d54 (diff) |
when vscsi is closed request a detach of its children devices from
the same thread theyre attached in (syswq) rather than in teh vscsi
process context. this serialises attach and detach so we can avoid
weird races with autoconf.
also, count the devices on the bus rather than the outstanding commands.
fixes some stuff for matthew@
ok matthew@
Diffstat (limited to 'sys/dev/vscsi.c')
-rw-r--r-- | sys/dev/vscsi.c | 56 |
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); } |