diff options
| author | mlelstv <mlelstv@NetBSD.org> | 2016-11-20 15:37:19 +0000 |
|---|---|---|
| committer | mlelstv <mlelstv@NetBSD.org> | 2016-11-20 15:37:19 +0000 |
| commit | ec70ca9e5859e315fce49a82349c9939d54cd1de (patch) | |
| tree | 8f0e4419d0b8b7f023b76a0e165a6c1d9137b841 /sys/dev | |
| parent | dfa1c7ef12f65bae666a4fd815a56e10daacd164 (diff) | |
Make scsipi framework MPSAFE.
Data structures are now protected by a per-adapter mutex at IPL_BIO
that is created by the scsibus or atapibus instance when the adapter
is configured.
The enable reference counter and the channel freeze counter which are
currently used by HBA code before the adapter is configured, are made
atomic.
The target drivers are now all tagged as D_MPSAFE.
Almost all HBA drivers still require the kernel lock to present,
so all callbacks into HBA code are still protected by kernel lock
unless the driver is tagged as SCSIPI_ADAPT_MPSAFE.
TODO: refactor sd and cd to use dksubr.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/scsipi/atapi_wdc.c | 6 | ||||
| -rw-r--r-- | sys/dev/scsipi/atapiconf.c | 38 | ||||
| -rw-r--r-- | sys/dev/scsipi/cd.c | 48 | ||||
| -rw-r--r-- | sys/dev/scsipi/ch.c | 6 | ||||
| -rw-r--r-- | sys/dev/scsipi/if_se.c | 6 | ||||
| -rw-r--r-- | sys/dev/scsipi/scsi_base.c | 10 | ||||
| -rw-r--r-- | sys/dev/scsipi/scsiconf.c | 57 | ||||
| -rw-r--r-- | sys/dev/scsipi/scsipi_base.c | 420 | ||||
| -rw-r--r-- | sys/dev/scsipi/scsipi_base.h | 36 | ||||
| -rw-r--r-- | sys/dev/scsipi/scsipi_ioctl.c | 32 | ||||
| -rw-r--r-- | sys/dev/scsipi/scsipiconf.c | 33 | ||||
| -rw-r--r-- | sys/dev/scsipi/scsipiconf.h | 50 | ||||
| -rw-r--r-- | sys/dev/scsipi/sd.c | 56 | ||||
| -rw-r--r-- | sys/dev/scsipi/ses.c | 6 | ||||
| -rw-r--r-- | sys/dev/scsipi/ss.c | 37 | ||||
| -rw-r--r-- | sys/dev/scsipi/ss_mustek.c | 8 | ||||
| -rw-r--r-- | sys/dev/scsipi/ss_scanjet.c | 6 | ||||
| -rw-r--r-- | sys/dev/scsipi/st.c | 40 | ||||
| -rw-r--r-- | sys/dev/scsipi/uk.c | 6 |
19 files changed, 564 insertions, 337 deletions
diff --git a/sys/dev/scsipi/atapi_wdc.c b/sys/dev/scsipi/atapi_wdc.c index 4bb472fc35f..4935c281760 100644 --- a/sys/dev/scsipi/atapi_wdc.c +++ b/sys/dev/scsipi/atapi_wdc.c @@ -1,4 +1,4 @@ -/* $NetBSD: atapi_wdc.c,v 1.122 2016/05/02 19:18:29 christos Exp $ */ +/* $NetBSD: atapi_wdc.c,v 1.123 2016/11/20 15:37:19 mlelstv Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.122 2016/05/02 19:18:29 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.123 2016/11/20 15:37:19 mlelstv Exp $"); #ifndef ATADEBUG #define ATADEBUG @@ -153,7 +153,7 @@ wdc_atapi_minphys(struct buf *bp) /* * Kill off all pending xfers for a periph. * - * Must be called at splbio(). + * Must be called with adapter lock held */ static void wdc_atapi_kill_pending(struct scsipi_periph *periph) diff --git a/sys/dev/scsipi/atapiconf.c b/sys/dev/scsipi/atapiconf.c index 2c301ac701c..24b25295760 100644 --- a/sys/dev/scsipi/atapiconf.c +++ b/sys/dev/scsipi/atapiconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: atapiconf.c,v 1.88 2016/03/13 09:01:04 tsutsui Exp $ */ +/* $NetBSD: atapiconf.c,v 1.89 2016/11/20 15:37:19 mlelstv Exp $ */ /* * Copyright (c) 1996, 2001 Manuel Bouyer. All rights reserved. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: atapiconf.c,v 1.88 2016/03/13 09:01:04 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atapiconf.c,v 1.89 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -152,6 +152,11 @@ atapibusattach(device_t parent, device_t self, void *aux) aprint_naive("\n"); aprint_normal(": %d targets\n", chan->chan_ntargets); + mutex_init(&chan->chan_adapter->adapt_mtx, MUTEX_DEFAULT, IPL_BIO); + cv_init(&chan->chan_cv_thr, "scshut"); + cv_init(&chan->chan_cv_comp, "sccomp"); + cv_init(&chan->chan_cv_xs, "xscmd"); + /* Initialize the channel. */ chan->chan_init_cb = NULL; chan->chan_init_cb_arg = NULL; @@ -172,20 +177,16 @@ atapibuschilddet(device_t self, device_t child) struct scsipi_periph *periph; int target; - /* XXXSMP scsipi */ - KERNEL_LOCK(1, curlwp); - + mutex_enter(chan_mtx(chan)); for (target = 0; target < chan->chan_ntargets; target++) { - periph = scsipi_lookup_periph(chan, target, 0); + periph = scsipi_lookup_periph_locked(chan, target, 0); if (periph == NULL || periph->periph_dev != child) continue; scsipi_remove_periph(chan, periph); - free(periph, M_DEVBUF); + scsipi_free_periph(periph); break; } - - /* XXXSMP scsipi */ - KERNEL_UNLOCK_ONE(curlwp); + mutex_exit(chan_mtx(chan)); } static int @@ -201,23 +202,32 @@ atapibusdetach(device_t self, int flags) */ scsipi_channel_shutdown(chan); - /* XXXSMP scsipi */ + /* for config_detach() */ KERNEL_LOCK(1, curlwp); /* * Now detach all of the periphs. */ + mutex_enter(chan_mtx(chan)); for (target = 0; target < chan->chan_ntargets; target++) { - periph = scsipi_lookup_periph(chan, target, 0); + periph = scsipi_lookup_periph_locked(chan, target, 0); if (periph == NULL) continue; error = config_detach(periph->periph_dev, flags); - if (error) + if (error) { + mutex_exit(chan_mtx(chan)); goto out; + } KASSERT(scsipi_lookup_periph(chan, target, 0) == NULL); } + mutex_exit(chan_mtx(chan)); out: + cv_destroy(&chan->chan_cv_xs); + cv_destroy(&chan->chan_cv_comp); + cv_destroy(&chan->chan_cv_thr); + mutex_destroy(chan_mtx(chan)); + /* XXXSMP scsipi */ KERNEL_UNLOCK_ONE(curlwp); return error; @@ -289,7 +299,7 @@ atapi_probe_device(struct atapibus_softc *sc, int target, } else { atapibusprint(sa, device_xname(sc->sc_dev)); aprint_normal(" not configured\n"); - free(periph, M_DEVBUF); + scsipi_free_periph(periph); return NULL; } } diff --git a/sys/dev/scsipi/cd.c b/sys/dev/scsipi/cd.c index e8d2f2fe526..bfd9d4676c4 100644 --- a/sys/dev/scsipi/cd.c +++ b/sys/dev/scsipi/cd.c @@ -1,4 +1,4 @@ -/* $NetBSD: cd.c,v 1.332 2016/11/20 02:38:24 pgoyette Exp $ */ +/* $NetBSD: cd.c,v 1.333 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 2001, 2003, 2004, 2005, 2008 The NetBSD Foundation, @@ -50,7 +50,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.332 2016/11/20 02:38:24 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.333 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -211,7 +211,7 @@ const struct bdevsw cd_bdevsw = { .d_dump = cddump, .d_psize = cdsize, .d_discard = nodiscard, - .d_flag = D_DISK + .d_flag = D_DISK | D_MPSAFE }; const struct cdevsw cd_cdevsw = { @@ -226,7 +226,7 @@ const struct cdevsw cd_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_DISK + .d_flag = D_DISK | D_MPSAFE }; static struct dkdriver cddkdriver = { @@ -316,7 +316,9 @@ static int cddetach(device_t self, int flags) { struct cd_softc *cd = device_private(self); - int s, bmaj, cmaj, i, mn; + struct scsipi_periph *periph = cd->sc_periph; + struct scsipi_channel *chan = periph->periph_channel; + int bmaj, cmaj, i, mn; if (cd->sc_dk.dk_openmask != 0 && (flags & DETACH_FORCE) == 0) return EBUSY; @@ -334,7 +336,7 @@ cddetach(device_t self, int flags) /* kill any pending restart */ callout_stop(&cd->sc_callout); - s = splbio(); + mutex_enter(chan_mtx(chan)); /* Kill off any queued buffers. */ bufq_drain(cd->buf_queue); @@ -342,7 +344,7 @@ cddetach(device_t self, int flags) /* Kill off any pending commands. */ scsipi_kill_pending(cd->sc_periph); - splx(s); + mutex_exit(chan_mtx(chan)); bufq_free(cd->buf_queue); @@ -576,8 +578,8 @@ cdstrategy(struct buf *bp) struct cd_softc *cd = device_lookup_private(&cd_cd,CDUNIT(bp->b_dev)); struct disklabel *lp; struct scsipi_periph *periph = cd->sc_periph; + struct scsipi_channel *chan = periph->periph_channel; daddr_t blkno; - int s; SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdstrategy ")); SC_DEBUG(cd->sc_periph, SCSIPI_DB1, @@ -719,7 +721,7 @@ cdstrategy(struct buf *bp) cd->params.blksize; } } - s = splbio(); + mutex_enter(chan_mtx(chan)); /* * Place it in the queue of disk activities for this disk. @@ -733,9 +735,9 @@ cdstrategy(struct buf *bp) * Tell the device to get going on the transfer if it's * not doing anything, otherwise just wait for completion */ - cdstart(cd->sc_periph); + cdstart(periph); - splx(s); + mutex_exit(chan_mtx(chan)); return; done: @@ -759,8 +761,8 @@ done: * have been made of the scsi driver, to ensure that the queue * continues to be drained. * - * must be called at the correct (highish) spl level - * cdstart() is called at splbio from cdstrategy, cdrestart and scsipi_done + * must be called with channel lock held + * cdstart() is called from cdstrategy, cdrestart and scsipi_done */ static void cdstart(struct scsipi_periph *periph) @@ -774,6 +776,7 @@ cdstart(struct scsipi_periph *periph) int flags, nblks, cmdlen, error __diagused; SC_DEBUG(periph, SCSIPI_DB2, ("cdstart ")); + /* * Check if the device has room for another command */ @@ -785,7 +788,7 @@ cdstart(struct scsipi_periph *periph) */ if (periph->periph_flags & PERIPH_WAITING) { periph->periph_flags &= ~PERIPH_WAITING; - wakeup((void *)periph); + cv_broadcast(periph_cv_periph(periph)); return; } @@ -864,7 +867,7 @@ cdstart(struct scsipi_periph *periph) * Call the routine that chats with the adapter. * Note: we cannot sleep as we may be an interrupt */ - xs = scsipi_make_xs(periph, cmdp, cmdlen, + xs = scsipi_make_xs_locked(periph, cmdp, cmdlen, (u_char *)bp->b_data, bp->b_bcount, CDRETRIES, 30000, bp, flags); if (__predict_false(xs == NULL)) { @@ -896,9 +899,12 @@ cdstart(struct scsipi_periph *periph) static void cdrestart(void *v) { - int s = splbio(); + struct scsipi_periph *periph = (struct scsipi_periph *)v; + struct scsipi_channel *chan = periph->periph_channel; + + mutex_enter(chan_mtx(chan)); cdstart((struct scsipi_periph *)v); - splx(s); + mutex_exit(chan_mtx(chan)); } static void @@ -951,7 +957,6 @@ cdbounce(struct buf *bp) struct buf *nbp; daddr_t blkno; long count; - int s; blkno = obp->b_rawblkno + ((obp->b_bcount - bounce->resid) / lp->d_secsize); @@ -995,10 +1000,10 @@ cdbounce(struct buf *bp) putiobuf(bp); /* enqueue the request and return */ - s = splbio(); + mutex_enter(chan_mtx(cd->sc_periph->periph_channel)); bufq_put(cd->buf_queue, nbp); cdstart(cd->sc_periph); - splx(s); + mutex_exit(chan_mtx(cd->sc_periph->periph_channel)); return; } @@ -1270,7 +1275,6 @@ cdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) struct cd_formatted_toc toc; int part = CDPART(dev); int error; - int s; #ifdef __HAVE_OLD_DISKLABEL struct disklabel *newlabel = NULL; #endif @@ -1638,6 +1642,7 @@ cdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) case DIOCGSTRATEGY: { struct disk_strategy *dks = addr; + int s; s = splbio(); strlcpy(dks->dks_name, bufq_getstrategyname(cd->buf_queue), @@ -1652,6 +1657,7 @@ cdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) struct disk_strategy *dks = addr; struct bufq_state *new; struct bufq_state *old; + int s; if ((flag & FWRITE) == 0) { return EBADF; diff --git a/sys/dev/scsipi/ch.c b/sys/dev/scsipi/ch.c index c5018ece287..dcc8ae9731a 100644 --- a/sys/dev/scsipi/ch.c +++ b/sys/dev/scsipi/ch.c @@ -1,4 +1,4 @@ -/* $NetBSD: ch.c,v 1.90 2014/07/25 08:10:38 dholland Exp $ */ +/* $NetBSD: ch.c,v 1.91 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 1999, 2004 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ch.c,v 1.90 2014/07/25 08:10:38 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ch.c,v 1.91 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -132,7 +132,7 @@ const struct cdevsw ch_cdevsw = { .d_mmap = nommap, .d_kqfilter = chkqfilter, .d_discard = nodiscard, - .d_flag = D_OTHER + .d_flag = D_OTHER | D_MPSAFE }; /* SCSI glue */ diff --git a/sys/dev/scsipi/if_se.c b/sys/dev/scsipi/if_se.c index 66a448ed87a..5d3db2e3d25 100644 --- a/sys/dev/scsipi/if_se.c +++ b/sys/dev/scsipi/if_se.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_se.c,v 1.92 2016/10/02 14:16:03 christos Exp $ */ +/* $NetBSD: if_se.c,v 1.93 2016/11/20 15:37:19 mlelstv Exp $ */ /* * Copyright (c) 1997 Ian W. Dall <ian.dall@dsto.defence.gov.au> @@ -59,7 +59,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_se.c,v 1.92 2016/10/02 14:16:03 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_se.c,v 1.93 2016/11/20 15:37:19 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -375,11 +375,9 @@ se_scsipi_cmd(struct scsipi_periph *periph, struct scsipi_generic *cmd, struct buf *bp, int flags) { int error; - int s = splbio(); error = scsipi_command(periph, cmd, cmdlen, data_addr, datalen, retries, timeout, bp, flags); - splx(s); return (error); } diff --git a/sys/dev/scsipi/scsi_base.c b/sys/dev/scsipi/scsi_base.c index e85ab373157..908f3e045d1 100644 --- a/sys/dev/scsipi/scsi_base.c +++ b/sys/dev/scsipi/scsi_base.c @@ -1,4 +1,4 @@ -/* $NetBSD: scsi_base.c,v 1.90 2012/04/20 20:23:21 bouyer Exp $ */ +/* $NetBSD: scsi_base.c,v 1.91 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: scsi_base.c,v 1.90 2012/04/20 20:23:21 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: scsi_base.c,v 1.91 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -111,7 +111,7 @@ scsi_print_addr(struct scsipi_periph *periph) /* * Kill off all pending xfers for a periph. * - * Must be called at splbio(). + * Must be called with channel lock held */ void scsi_kill_pending(struct scsipi_periph *periph) @@ -181,7 +181,7 @@ scsi_async_event_xfer_mode(struct scsipi_channel *chan, void *arg) int lun, announce, mode, period, offset; for (lun = 0; lun < chan->chan_nluns; lun++) { - periph = scsipi_lookup_periph(chan, xm->xm_target, lun); + periph = scsipi_lookup_periph_locked(chan, xm->xm_target, lun); if (periph == NULL) continue; announce = 0; @@ -232,7 +232,7 @@ scsi_fc_sas_async_event_xfer_mode(struct scsipi_channel *chan, void *arg) int lun, announce, mode; for (lun = 0; lun < chan->chan_nluns; lun++) { - periph = scsipi_lookup_periph(chan, xm->xm_target, lun); + periph = scsipi_lookup_periph_locked(chan, xm->xm_target, lun); if (periph == NULL) continue; announce = 0; diff --git a/sys/dev/scsipi/scsiconf.c b/sys/dev/scsipi/scsiconf.c index 18d459feda1..223fb7f058c 100644 --- a/sys/dev/scsipi/scsiconf.c +++ b/sys/dev/scsipi/scsiconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: scsiconf.c,v 1.275 2016/06/26 07:31:35 mlelstv Exp $ */ +/* $NetBSD: scsiconf.c,v 1.276 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: scsiconf.c,v 1.275 2016/06/26 07:31:35 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: scsiconf.c,v 1.276 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -117,7 +117,7 @@ const struct cdevsw scsibus_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_OTHER + .d_flag = D_OTHER | D_MPSAFE }; static int scsibusprint(void *, const char *); @@ -240,6 +240,12 @@ scsibusattach(device_t parent, device_t self, void *aux) chan->chan_adapter->adapt_max_periph = 256; } + mutex_init(chan_mtx(chan), MUTEX_DEFAULT, IPL_BIO); + cv_init(&chan->chan_cv_thr, "scshut"); + cv_init(&chan->chan_cv_comp, "sccomp"); + cv_init(&chan->chan_cv_xs, "xscmd"); + chan_running(chan) = true; + if (scsipi_adapter_addref(chan->chan_adapter)) return; @@ -293,8 +299,7 @@ scsibus_config(struct scsibus_softc *sc) "waiting %d seconds for devices to settle...\n", SCSI_DELAY); /* ...an identifier we know no one will use... */ - (void) tsleep(scsibus_config, PRIBIO, - "scsidly", SCSI_DELAY * hz); + kpause("scsidly", false, SCSI_DELAY * hz, NULL); } /* Make sure the devices probe in scsibus order to avoid jitter. */ @@ -331,18 +336,11 @@ scsibusdetach(device_t self, int flags) struct scsipi_xfer *xs; int error; - /* XXXSMP scsipi */ - KERNEL_LOCK(1, curlwp); - /* * Detach all of the periphs. */ - if ((error = scsipi_target_detach(chan, -1, -1, flags)) != 0) { - /* XXXSMP scsipi */ - KERNEL_UNLOCK_ONE(curlwp); - + if ((error = scsipi_target_detach(chan, -1, -1, flags)) != 0) return error; - } pmf_device_deregister(self); @@ -373,8 +371,11 @@ scsibusdetach(device_t self, int flags) */ scsipi_channel_shutdown(chan); - /* XXXSMP scsipi */ - KERNEL_UNLOCK_ONE(curlwp); + chan_running(chan) = false; + cv_destroy(&chan->chan_cv_xs); + cv_destroy(&chan->chan_cv_comp); + cv_destroy(&chan->chan_cv_thr); + mutex_destroy(chan_mtx(chan)); return 0; } @@ -390,9 +391,6 @@ scsi_probe_bus(struct scsibus_softc *sc, int target, int lun) int maxtarget, mintarget, maxlun, minlun; int error; - /* XXXSMP scsipi */ - KERNEL_LOCK(1, curlwp); - if (target == -1) { maxtarget = chan->chan_ntargets - 1; mintarget = 0; @@ -415,9 +413,7 @@ scsi_probe_bus(struct scsibus_softc *sc, int target, int lun) * Some HBAs provide an abstracted view of the bus; give them an * oppertunity to re-scan it before we do. */ - if (chan->chan_adapter->adapt_ioctl != NULL) - (*chan->chan_adapter->adapt_ioctl)(chan, SCBUSIOLLSCAN, NULL, - 0, curproc); + scsipi_adapter_ioctl(chan, SCBUSIOLLSCAN, NULL, 0, curproc); if ((error = scsipi_adapter_addref(chan->chan_adapter)) != 0) goto ret; @@ -442,7 +438,6 @@ scsi_probe_bus(struct scsibus_softc *sc, int target, int lun) } scsipi_adapter_delref(chan->chan_adapter); ret: - KERNEL_UNLOCK_ONE(curlwp); return (error); } @@ -469,17 +464,15 @@ scsidevdetached(device_t self, device_t child) target = device_locator(child, SCSIBUSCF_TARGET); lun = device_locator(child, SCSIBUSCF_LUN); - /* XXXSMP scsipi */ - KERNEL_LOCK(1, curlwp); + mutex_enter(chan_mtx(chan)); - periph = scsipi_lookup_periph(chan, target, lun); + periph = scsipi_lookup_periph_locked(chan, target, lun); KASSERT(periph->periph_dev == child); scsipi_remove_periph(chan, periph); - free(periph, M_DEVBUF); + scsipi_free_periph(periph); - /* XXXSMP scsipi */ - KERNEL_UNLOCK_ONE(curlwp); + mutex_exit(chan_mtx(chan)); } /* @@ -1044,7 +1037,7 @@ scsi_probe_device(struct scsibus_softc *sc, int target, int lun) return (docontinue); bad: - free(periph, M_DEVBUF); + scsipi_free_periph(periph); return (docontinue); } @@ -1132,11 +1125,7 @@ scsibusioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) case SCBUSIORESET: /* FALLTHROUGH */ default: - if (chan->chan_adapter->adapt_ioctl == NULL) - error = ENOTTY; - else - error = (*chan->chan_adapter->adapt_ioctl)(chan, - cmd, addr, flag, l->l_proc); + error = scsipi_adapter_ioctl(chan, cmd, addr, flag, l->l_proc); break; } diff --git a/sys/dev/scsipi/scsipi_base.c b/sys/dev/scsipi/scsipi_base.c index 93e523a9093..cfe64cbe48c 100644 --- a/sys/dev/scsipi/scsipi_base.c +++ b/sys/dev/scsipi/scsipi_base.c @@ -1,4 +1,4 @@ -/* $NetBSD: scsipi_base.c,v 1.166 2016/10/02 19:40:35 jdolecek Exp $ */ +/* $NetBSD: scsipi_base.c,v 1.167 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.166 2016/10/02 19:40:35 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.167 2016/11/20 15:37:19 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_scsi.h" @@ -49,6 +49,7 @@ __KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.166 2016/10/02 19:40:35 jdolecek E #include <sys/proc.h> #include <sys/kthread.h> #include <sys/hash.h> +#include <sys/atomic.h> #include <dev/scsipi/scsi_spc.h> #include <dev/scsipi/scsipi_all.h> @@ -78,8 +79,15 @@ static void scsipi_async_event_max_openings(struct scsipi_channel *, struct scsipi_max_openings *); static void scsipi_async_event_channel_reset(struct scsipi_channel *); +static void scsipi_channel_freeze_locked(struct scsipi_channel *, int); + +static void scsipi_adapter_lock(struct scsipi_adapter *adapt); +static void scsipi_adapter_unlock(struct scsipi_adapter *adapt); + static struct pool scsipi_xfer_pool; +int scsipi_xs_count = 0; + /* * scsipi_init: * @@ -102,6 +110,8 @@ scsipi_init(void) PAGE_SIZE / sizeof(struct scsipi_xfer)) == ENOMEM) { printf("WARNING: not enough memory for scsipi_xfer_pool\n"); } + + scsipi_ioctl_init(); } /* @@ -147,17 +157,19 @@ void scsipi_channel_shutdown(struct scsipi_channel *chan) { + mutex_enter(chan_mtx(chan)); /* * Shut down the completion thread. */ chan->chan_tflags |= SCSIPI_CHANT_SHUTDOWN; - wakeup(&chan->chan_complete); + cv_broadcast(chan_cv_complete(chan)); /* * Now wait for the thread to exit. */ while (chan->chan_thread != NULL) - (void) tsleep(&chan->chan_thread, PRIBIO, "scshut", 0); + cv_wait(chan_cv_thread(chan), chan_mtx(chan)); + mutex_exit(chan_mtx(chan)); } static uint32_t @@ -180,14 +192,13 @@ void scsipi_insert_periph(struct scsipi_channel *chan, struct scsipi_periph *periph) { uint32_t hash; - int s; hash = scsipi_chan_periph_hash(periph->periph_target, periph->periph_lun); - s = splbio(); + mutex_enter(chan_mtx(chan)); LIST_INSERT_HEAD(&chan->chan_periphtab[hash], periph, periph_hash); - splx(s); + mutex_exit(chan_mtx(chan)); } /* @@ -199,11 +210,8 @@ void scsipi_remove_periph(struct scsipi_channel *chan, struct scsipi_periph *periph) { - int s; - s = splbio(); LIST_REMOVE(periph, periph_hash); - splx(s); } /* @@ -211,14 +219,11 @@ scsipi_remove_periph(struct scsipi_channel *chan, * * Lookup a periph on the specified channel. */ -struct scsipi_periph * -scsipi_lookup_periph(struct scsipi_channel *chan, int target, int lun) +static struct scsipi_periph * +scsipi_lookup_periph_internal(struct scsipi_channel *chan, int target, int lun, bool lock) { struct scsipi_periph *periph; uint32_t hash; - int s; - - KASSERT(cold || KERNEL_LOCKED_P()); if (target >= chan->chan_ntargets || lun >= chan->chan_nluns) @@ -226,23 +231,37 @@ scsipi_lookup_periph(struct scsipi_channel *chan, int target, int lun) hash = scsipi_chan_periph_hash(target, lun); - s = splbio(); + if (lock) + mutex_enter(chan_mtx(chan)); LIST_FOREACH(periph, &chan->chan_periphtab[hash], periph_hash) { if (periph->periph_target == target && periph->periph_lun == lun) break; } - splx(s); + if (lock) + mutex_exit(chan_mtx(chan)); return (periph); } +struct scsipi_periph * +scsipi_lookup_periph_locked(struct scsipi_channel *chan, int target, int lun) +{ + return scsipi_lookup_periph_internal(chan, target, lun, false); +} + +struct scsipi_periph * +scsipi_lookup_periph(struct scsipi_channel *chan, int target, int lun) +{ + return scsipi_lookup_periph_internal(chan, target, lun, true); +} + /* * scsipi_get_resource: * * Allocate a single xfer `resource' from the channel. * - * NOTE: Must be called at splbio(). + * NOTE: Must be called with channel lock held */ static int scsipi_get_resource(struct scsipi_channel *chan) @@ -270,7 +289,7 @@ scsipi_get_resource(struct scsipi_channel *chan) * Attempt to grow resources for a channel. If this succeeds, * we allocate one for our caller. * - * NOTE: Must be called at splbio(). + * NOTE: Must be called with channel lock held */ static inline int scsipi_grow_resources(struct scsipi_channel *chan) @@ -278,17 +297,19 @@ scsipi_grow_resources(struct scsipi_channel *chan) if (chan->chan_flags & SCSIPI_CHAN_CANGROW) { if ((chan->chan_flags & SCSIPI_CHAN_TACTIVE) == 0) { + mutex_exit(chan_mtx(chan)); scsipi_adapter_request(chan, ADAPTER_REQ_GROW_RESOURCES, NULL); + mutex_enter(chan_mtx(chan)); return (scsipi_get_resource(chan)); } /* * ask the channel thread to do it. It'll have to thaw the * queue */ - scsipi_channel_freeze(chan, 1); + scsipi_channel_freeze_locked(chan, 1); chan->chan_tflags |= SCSIPI_CHANT_GROWRES; - wakeup(&chan->chan_complete); + cv_broadcast(chan_cv_complete(chan)); return (0); } @@ -300,7 +321,7 @@ scsipi_grow_resources(struct scsipi_channel *chan) * * Free a single xfer `resource' to the channel. * - * NOTE: Must be called at splbio(). + * NOTE: Must be called with channel lock held */ static void scsipi_put_resource(struct scsipi_channel *chan) @@ -318,7 +339,7 @@ scsipi_put_resource(struct scsipi_channel *chan) * * Get a tag ID for the specified xfer. * - * NOTE: Must be called at splbio(). + * NOTE: Must be called with channel lock held */ static void scsipi_get_tag(struct scsipi_xfer *xs) @@ -360,7 +381,7 @@ scsipi_get_tag(struct scsipi_xfer *xs) * * Put the tag ID for the specified xfer back into the pool. * - * NOTE: Must be called at splbio(). + * NOTE: Must be called with channel lock held */ static void scsipi_put_tag(struct scsipi_xfer *xs) @@ -381,12 +402,14 @@ scsipi_put_tag(struct scsipi_xfer *xs) * specified peripheral. If the peripheral has no more * available command openings, we either block waiting for * one to become available, or fail. + * + * When this routine is called with the channel lock held + * the flags must include XS_CTL_NOSLEEP. */ struct scsipi_xfer * scsipi_get_xs(struct scsipi_periph *periph, int flags) { struct scsipi_xfer *xs; - int s; SC_DEBUG(periph, SCSIPI_DB3, ("scsipi_get_xs\n")); @@ -404,7 +427,6 @@ scsipi_get_xs(struct scsipi_periph *periph, int flags) } #endif - s = splbio(); /* * Wait for a command opening to become available. Rules: * @@ -445,13 +467,16 @@ scsipi_get_xs(struct scsipi_periph *periph, int flags) wait_for_opening: if (flags & XS_CTL_NOSLEEP) { - splx(s); return (NULL); } SC_DEBUG(periph, SCSIPI_DB3, ("sleeping\n")); + mutex_enter(chan_mtx(periph->periph_channel)); periph->periph_flags |= PERIPH_WAITING; - (void) tsleep(periph, PRIBIO, "getxs", 0); + cv_wait(periph_cv_periph(periph), + chan_mtx(periph->periph_channel)); + mutex_exit(chan_mtx(periph->periph_channel)); } + SC_DEBUG(periph, SCSIPI_DB3, ("calling pool_get\n")); xs = pool_get(&scsipi_xfer_pool, ((flags & XS_CTL_NOSLEEP) != 0 ? PR_NOWAIT : PR_WAITOK)); @@ -465,7 +490,6 @@ scsipi_get_xs(struct scsipi_periph *periph, int flags) printf("unable to allocate %sscsipi_xfer\n", (flags & XS_CTL_URGENT) ? "URGENT " : ""); } - splx(s); SC_DEBUG(periph, SCSIPI_DB3, ("returning\n")); @@ -475,9 +499,11 @@ scsipi_get_xs(struct scsipi_periph *periph, int flags) xs->xs_periph = periph; xs->xs_control = flags; xs->xs_status = 0; - s = splbio(); + if ((flags & XS_CTL_NOSLEEP) == 0) + mutex_enter(chan_mtx(periph->periph_channel)); TAILQ_INSERT_TAIL(&periph->periph_xferq, xs, device_q); - splx(s); + if ((flags & XS_CTL_NOSLEEP) == 0) + mutex_exit(chan_mtx(periph->periph_channel)); } return (xs); } @@ -490,7 +516,7 @@ scsipi_get_xs(struct scsipi_periph *periph, int flags) * an opening, wake it up. If not, kick any queued I/O the * peripheral may have. * - * NOTE: Must be called at splbio(). + * NOTE: Must be called with channel lock held */ void scsipi_put_xs(struct scsipi_xfer *xs) @@ -521,12 +547,12 @@ scsipi_put_xs(struct scsipi_xfer *xs) if (periph->periph_active == 0 && (periph->periph_flags & PERIPH_WAITDRAIN) != 0) { periph->periph_flags &= ~PERIPH_WAITDRAIN; - wakeup(&periph->periph_active); + cv_broadcast(periph_cv_active(periph)); } if (periph->periph_flags & PERIPH_WAITING) { periph->periph_flags &= ~PERIPH_WAITING; - wakeup(periph); + cv_broadcast(periph_cv_periph(periph)); } else { if (periph->periph_switch->psw_start != NULL && device_is_active(periph->periph_dev)) { @@ -545,11 +571,20 @@ scsipi_put_xs(struct scsipi_xfer *xs) void scsipi_channel_freeze(struct scsipi_channel *chan, int count) { - int s; + bool lock = chan_running(chan); + + if (lock) + mutex_enter(chan_mtx(chan)); + chan->chan_qfreeze += count; + if (lock) + mutex_exit(chan_mtx(chan)); +} + +static void +scsipi_channel_freeze_locked(struct scsipi_channel *chan, int count) +{ - s = splbio(); chan->chan_qfreeze += count; - splx(s); } /* @@ -560,9 +595,10 @@ scsipi_channel_freeze(struct scsipi_channel *chan, int count) void scsipi_channel_thaw(struct scsipi_channel *chan, int count) { - int s; + bool lock = chan_running(chan); - s = splbio(); + if (lock) + mutex_enter(chan_mtx(chan)); chan->chan_qfreeze -= count; /* * Don't let the freeze count go negative. @@ -574,7 +610,15 @@ scsipi_channel_thaw(struct scsipi_channel *chan, int count) if (chan->chan_qfreeze < 0) { chan->chan_qfreeze = 0; } - splx(s); + if (lock) + mutex_exit(chan_mtx(chan)); + + /* + * until the channel is running + */ + if (!lock) + return; + /* * Kick the channel's queue here. Note, we may be running in * interrupt context (softclock or HBA's interrupt), so the adapter @@ -604,13 +648,10 @@ scsipi_channel_timed_thaw(void *arg) * Freeze a device's xfer queue. */ void -scsipi_periph_freeze(struct scsipi_periph *periph, int count) +scsipi_periph_freeze_locked(struct scsipi_periph *periph, int count) { - int s; - s = splbio(); periph->periph_qfreeze += count; - splx(s); } /* @@ -619,11 +660,9 @@ scsipi_periph_freeze(struct scsipi_periph *periph, int count) * Thaw a device's xfer queue. */ void -scsipi_periph_thaw(struct scsipi_periph *periph, int count) +scsipi_periph_thaw_locked(struct scsipi_periph *periph, int count) { - int s; - s = splbio(); periph->periph_qfreeze -= count; #ifdef DIAGNOSTIC if (periph->periph_qfreeze < 0) { @@ -635,8 +674,25 @@ scsipi_periph_thaw(struct scsipi_periph *periph, int count) #endif if (periph->periph_qfreeze == 0 && (periph->periph_flags & PERIPH_WAITING) != 0) - wakeup(periph); - splx(s); + cv_broadcast(periph_cv_periph(periph)); +} + +void +scsipi_periph_freeze(struct scsipi_periph *periph, int count) +{ + + mutex_enter(chan_mtx(periph->periph_channel)); + scsipi_periph_freeze_locked(periph, count); + mutex_exit(chan_mtx(periph->periph_channel)); +} + +void +scsipi_periph_thaw(struct scsipi_periph *periph, int count) +{ + + mutex_enter(chan_mtx(periph->periph_channel)); + scsipi_periph_thaw_locked(periph, count); + mutex_exit(chan_mtx(periph->periph_channel)); } /* @@ -647,28 +703,29 @@ scsipi_periph_thaw(struct scsipi_periph *periph, int count) void scsipi_periph_timed_thaw(void *arg) { - int s; struct scsipi_periph *periph = arg; + struct scsipi_channel *chan = periph->periph_channel; callout_stop(&periph->periph_callout); - s = splbio(); - scsipi_periph_thaw(periph, 1); + mutex_enter(chan_mtx(chan)); + scsipi_periph_thaw_locked(periph, 1); if ((periph->periph_channel->chan_flags & SCSIPI_CHAN_TACTIVE) == 0) { /* * Kick the channel's queue here. Note, we're running in * interrupt context (softclock), so the adapter driver * had better not sleep. */ + mutex_exit(chan_mtx(chan)); scsipi_run_queue(periph->periph_channel); } else { /* * Tell the completion thread to kick the channel's queue here. */ periph->periph_channel->chan_tflags |= SCSIPI_CHANT_KICK; - wakeup(&periph->periph_channel->chan_complete); + cv_broadcast(chan_cv_complete(chan)); + mutex_exit(chan_mtx(chan)); } - splx(s); } /* @@ -679,14 +736,14 @@ scsipi_periph_timed_thaw(void *arg) void scsipi_wait_drain(struct scsipi_periph *periph) { - int s; + struct scsipi_channel *chan = periph->periph_channel; - s = splbio(); + mutex_enter(chan_mtx(chan)); while (periph->periph_active != 0) { periph->periph_flags |= PERIPH_WAITDRAIN; - (void) tsleep(&periph->periph_active, PRIBIO, "sxdrn", 0); + cv_wait(periph_cv_active(periph), chan_mtx(chan)); } - splx(s); + mutex_exit(chan_mtx(chan)); } /* @@ -694,14 +751,18 @@ scsipi_wait_drain(struct scsipi_periph *periph) * * Kill off all pending xfers for a periph. * - * NOTE: Must be called at splbio(). + * NOTE: Must be called with channel lock held */ void scsipi_kill_pending(struct scsipi_periph *periph) { + struct scsipi_channel *chan = periph->periph_channel; - (*periph->periph_channel->chan_bustype->bustype_kill_pending)(periph); - scsipi_wait_drain(periph); + (*chan->chan_bustype->bustype_kill_pending)(periph); + while (periph->periph_active != 0) { + periph->periph_flags |= PERIPH_WAITDRAIN; + cv_wait(periph_cv_active(periph), chan_mtx(chan)); + } } /* @@ -1285,9 +1346,7 @@ scsipi_done(struct scsipi_xfer *xs) { struct scsipi_periph *periph = xs->xs_periph; struct scsipi_channel *chan = periph->periph_channel; - int s, freezecnt; - - KASSERT(cold || KERNEL_LOCKED_P()); + int freezecnt; SC_DEBUG(periph, SCSIPI_DB2, ("scsipi_done\n")); #ifdef SCSIPI_DEBUG @@ -1295,7 +1354,7 @@ scsipi_done(struct scsipi_xfer *xs) show_scsipi_cmd(xs); #endif - s = splbio(); + mutex_enter(chan_mtx(chan)); /* * The resource this command was using is now free. */ @@ -1310,7 +1369,7 @@ scsipi_done(struct scsipi_xfer *xs) * that this won't ever happen (and can be turned into * a KASSERT(). */ - splx(s); + mutex_exit(chan_mtx(chan)); goto out; } scsipi_put_resource(chan); @@ -1344,7 +1403,7 @@ scsipi_done(struct scsipi_xfer *xs) if (xs->xs_control & XS_CTL_FREEZE_PERIPH) freezecnt++; if (freezecnt != 0) - scsipi_periph_freeze(periph, freezecnt); + scsipi_periph_freeze_locked(periph, freezecnt); /* * record the xfer with a pending sense, in case a SCSI reset is @@ -1361,7 +1420,6 @@ scsipi_done(struct scsipi_xfer *xs) * in its context. */ if ((xs->xs_control & XS_CTL_ASYNC) == 0) { - splx(s); /* * If it's a polling job, just return, to unwind the * call graph. We don't need to restart the queue, @@ -1370,9 +1428,12 @@ scsipi_done(struct scsipi_xfer *xs) * (XXX or during boot-time autconfiguration of * ATAPI devices). */ - if (xs->xs_control & XS_CTL_POLL) + if (xs->xs_control & XS_CTL_POLL) { + mutex_exit(chan_mtx(chan)); return; - wakeup(xs); + } + cv_broadcast(xs_cv(xs)); + mutex_exit(chan_mtx(chan)); goto out; } @@ -1382,7 +1443,7 @@ scsipi_done(struct scsipi_xfer *xs) * if we can handle it in interrupt context. */ if (xs->error == XS_NOERROR) { - splx(s); + mutex_exit(chan_mtx(chan)); (void) scsipi_complete(xs); goto out; } @@ -1392,8 +1453,8 @@ scsipi_done(struct scsipi_xfer *xs) * completion queue, and wake up the completion thread. */ TAILQ_INSERT_TAIL(&chan->chan_complete, xs, channel_q); - splx(s); - wakeup(&chan->chan_complete); + mutex_exit(chan_mtx(chan)); + cv_broadcast(chan_cv_complete(chan)); out: /* @@ -1437,7 +1498,7 @@ scsipi_complete(struct scsipi_xfer *xs) { struct scsipi_periph *periph = xs->xs_periph; struct scsipi_channel *chan = periph->periph_channel; - int error, s; + int error; #ifdef DIAGNOSTIC if ((xs->xs_control & XS_CTL_ASYNC) != 0 && xs->bp == NULL) @@ -1447,10 +1508,10 @@ scsipi_complete(struct scsipi_xfer *xs) * If command terminated with a CHECK CONDITION, we need to issue a * REQUEST_SENSE command. Once the REQUEST_SENSE has been processed * we'll have the real status. - * Must be processed at splbio() to avoid missing a SCSI bus reset - * for this command. + * Must be processed with channel lock held to avoid missing + * a SCSI bus reset for this command. */ - s = splbio(); + mutex_enter(chan_mtx(chan)); if (xs->error == XS_BUSY && xs->status == SCSI_CHECK) { /* request sense for a request sense ? */ if (xs->xs_control & XS_CTL_REQSENSE) { @@ -1458,8 +1519,8 @@ scsipi_complete(struct scsipi_xfer *xs) printf("request sense for a request sense ?\n"); /* XXX maybe we should reset the device ? */ /* we've been frozen because xs->error != XS_NOERROR */ - scsipi_periph_thaw(periph, 1); - splx(s); + scsipi_periph_thaw_locked(periph, 1); + mutex_exit(chan_mtx(chan)); if (xs->resid < xs->datalen) { printf("we read %d bytes of sense anyway:\n", xs->datalen - xs->resid); @@ -1467,9 +1528,10 @@ scsipi_complete(struct scsipi_xfer *xs) } return EINVAL; } + mutex_exit(chan_mtx(chan)); // XXX allows other commands to queue or run scsipi_request_sense(xs); - } - splx(s); + } else + mutex_exit(chan_mtx(chan)); /* * If it's a user level request, bypass all usual completion @@ -1477,8 +1539,10 @@ scsipi_complete(struct scsipi_xfer *xs) */ if ((xs->xs_control & XS_CTL_USERCMD) != 0) { SC_DEBUG(periph, SCSIPI_DB3, ("calling user done()\n")); + mutex_enter(chan_mtx(chan)); if (xs->error != XS_NOERROR) - scsipi_periph_thaw(periph, 1); + scsipi_periph_thaw_locked(periph, 1); + mutex_exit(chan_mtx(chan)); scsipi_user_done(xs); SC_DEBUG(periph, SCSIPI_DB3, ("returned from user done()\n ")); return 0; @@ -1537,15 +1601,17 @@ scsipi_complete(struct scsipi_xfer *xs) /* * Wait one second, and try again. */ + mutex_enter(chan_mtx(chan)); if ((xs->xs_control & XS_CTL_POLL) || (chan->chan_flags & SCSIPI_CHAN_TACTIVE) == 0) { /* XXX: quite extreme */ - kpause("xsbusy", false, hz, NULL); + kpause("xsbusy", false, hz, chan_mtx(chan)); } else if (!callout_pending(&periph->periph_callout)) { - scsipi_periph_freeze(periph, 1); + scsipi_periph_freeze_locked(periph, 1); callout_reset(&periph->periph_callout, hz, scsipi_periph_timed_thaw, periph); } + mutex_exit(chan_mtx(chan)); error = ERESTART; } else error = EBUSY; @@ -1600,7 +1666,7 @@ scsipi_complete(struct scsipi_xfer *xs) break; } - s = splbio(); + mutex_enter(chan_mtx(chan)); if (error == ERESTART) { /* * If we get here, the periph has been thawed and frozen @@ -1616,8 +1682,8 @@ scsipi_complete(struct scsipi_xfer *xs) xs->xs_requeuecnt++; error = scsipi_enqueue(xs); if (error == 0) { - scsipi_periph_thaw(periph, 1); - splx(s); + scsipi_periph_thaw_locked(periph, 1); + mutex_exit(chan_mtx(chan)); return (ERESTART); } } @@ -1627,14 +1693,16 @@ scsipi_complete(struct scsipi_xfer *xs) * Thaw it here. */ if (xs->error != XS_NOERROR) - scsipi_periph_thaw(periph, 1); + scsipi_periph_thaw_locked(periph, 1); + mutex_exit(chan_mtx(chan)); if (periph->periph_switch->psw_done) periph->periph_switch->psw_done(xs, error); + mutex_enter(chan_mtx(chan)); if (xs->xs_control & XS_CTL_ASYNC) scsipi_put_xs(xs); - splx(s); + mutex_exit(chan_mtx(chan)); return (error); } @@ -1642,7 +1710,7 @@ scsipi_complete(struct scsipi_xfer *xs) /* * Issue a request sense for the given scsipi_xfer. Called when the xfer * returns with a CHECK_CONDITION status. Must be called in valid thread - * context and at splbio(). + * context and with channel lock held. */ static void @@ -1708,9 +1776,6 @@ scsipi_enqueue(struct scsipi_xfer *xs) { struct scsipi_channel *chan = xs->xs_periph->periph_channel; struct scsipi_xfer *qxs; - int s; - - s = splbio(); /* * If the xfer is to be polled, and there are already jobs on @@ -1718,7 +1783,6 @@ scsipi_enqueue(struct scsipi_xfer *xs) */ if ((xs->xs_control & XS_CTL_POLL) != 0 && TAILQ_FIRST(&chan->chan_queue) != NULL) { - splx(s); xs->error = XS_DRIVER_STUFFUP; return (EAGAIN); } @@ -1758,8 +1822,7 @@ scsipi_enqueue(struct scsipi_xfer *xs) TAILQ_INSERT_TAIL(&chan->chan_queue, xs, channel_q); out: if (xs->xs_control & XS_CTL_THAW_PERIPH) - scsipi_periph_thaw(xs->xs_periph, 1); - splx(s); + scsipi_periph_thaw_locked(xs->xs_periph, 1); return (0); } @@ -1773,17 +1836,16 @@ scsipi_run_queue(struct scsipi_channel *chan) { struct scsipi_xfer *xs; struct scsipi_periph *periph; - int s; for (;;) { - s = splbio(); + mutex_enter(chan_mtx(chan)); /* * If the channel is frozen, we can't do any work right * now. */ if (chan->chan_qfreeze != 0) { - splx(s); + mutex_exit(chan_mtx(chan)); return; } @@ -1813,7 +1875,7 @@ scsipi_run_queue(struct scsipi_channel *chan) /* * Can't find any work to do right now. */ - splx(s); + mutex_exit(chan_mtx(chan)); return; got_one: @@ -1838,7 +1900,7 @@ scsipi_run_queue(struct scsipi_channel *chan) "adapter resources"); /* We'll panic shortly... */ } - splx(s); + mutex_exit(chan_mtx(chan)); /* * XXX: We should be able to note that @@ -1866,7 +1928,7 @@ scsipi_run_queue(struct scsipi_channel *chan) else periph->periph_flags |= PERIPH_UNTAG; periph->periph_sent++; - splx(s); + mutex_exit(chan_mtx(chan)); scsipi_adapter_request(chan, ADAPTER_REQ_RUN_XFER, xs); } @@ -1885,10 +1947,9 @@ scsipi_execute_xs(struct scsipi_xfer *xs) { struct scsipi_periph *periph = xs->xs_periph; struct scsipi_channel *chan = periph->periph_channel; - int oasync, async, poll, error, s; + int oasync, async, poll, error; KASSERT(!cold); - KASSERT(KERNEL_LOCKED_P()); (chan->chan_bustype->bustype_cmd)(xs); @@ -1992,8 +2053,10 @@ scsipi_execute_xs(struct scsipi_xfer *xs) goto free_xs; } + mutex_exit(chan_mtx(chan)); restarted: scsipi_run_queue(chan); + mutex_enter(chan_mtx(chan)); /* * The xfer is enqueued, and possibly running. If it's to be @@ -2005,21 +2068,20 @@ scsipi_execute_xs(struct scsipi_xfer *xs) /* * Not an asynchronous command; wait for it to complete. */ - s = splbio(); while ((xs->xs_status & XS_STS_DONE) == 0) { if (poll) { scsipi_printaddr(periph); printf("polling command not done\n"); panic("scsipi_execute_xs"); } - (void) tsleep(xs, PRIBIO, "xscmd", 0); + cv_wait(xs_cv(xs), chan_mtx(chan)); } - splx(s); /* * Command is complete. scsipi_done() has awakened us to perform * the error handling. */ + mutex_exit(chan_mtx(chan)); error = scsipi_complete(xs); if (error == ERESTART) goto restarted; @@ -2034,10 +2096,10 @@ scsipi_execute_xs(struct scsipi_xfer *xs) * Command completed successfully or fatal error occurred. Fall * into.... */ + mutex_enter(chan_mtx(chan)); free_xs: - s = splbio(); scsipi_put_xs(xs); - splx(s); + mutex_exit(chan_mtx(chan)); /* * Kick the queue, keep it running in case it stopped for some @@ -2045,6 +2107,7 @@ scsipi_execute_xs(struct scsipi_xfer *xs) */ scsipi_run_queue(chan); + mutex_enter(chan_mtx(chan)); return (error); } @@ -2060,38 +2123,36 @@ scsipi_completion_thread(void *arg) { struct scsipi_channel *chan = arg; struct scsipi_xfer *xs; - int s; if (chan->chan_init_cb) (*chan->chan_init_cb)(chan, chan->chan_init_cb_arg); - s = splbio(); + mutex_enter(chan_mtx(chan)); chan->chan_flags |= SCSIPI_CHAN_TACTIVE; - splx(s); + mutex_exit(chan_mtx(chan)); for (;;) { - s = splbio(); + mutex_enter(chan_mtx(chan)); xs = TAILQ_FIRST(&chan->chan_complete); if (xs == NULL && chan->chan_tflags == 0) { /* nothing to do; wait */ - (void) tsleep(&chan->chan_complete, PRIBIO, - "sccomp", 0); - splx(s); + cv_wait(chan_cv_complete(chan), chan_mtx(chan)); + mutex_exit(chan_mtx(chan)); continue; } if (chan->chan_tflags & SCSIPI_CHANT_CALLBACK) { /* call chan_callback from thread context */ chan->chan_tflags &= ~SCSIPI_CHANT_CALLBACK; chan->chan_callback(chan, chan->chan_callback_arg); - splx(s); + mutex_exit(chan_mtx(chan)); continue; } if (chan->chan_tflags & SCSIPI_CHANT_GROWRES) { /* attempt to get more openings for this channel */ chan->chan_tflags &= ~SCSIPI_CHANT_GROWRES; + mutex_exit(chan_mtx(chan)); scsipi_adapter_request(chan, ADAPTER_REQ_GROW_RESOURCES, NULL); scsipi_channel_thaw(chan, 1); - splx(s); if (chan->chan_tflags & SCSIPI_CHANT_GROWRES) kpause("scsizzz", FALSE, hz/10, NULL); continue; @@ -2099,17 +2160,17 @@ scsipi_completion_thread(void *arg) if (chan->chan_tflags & SCSIPI_CHANT_KICK) { /* explicitly run the queues for this channel */ chan->chan_tflags &= ~SCSIPI_CHANT_KICK; + mutex_exit(chan_mtx(chan)); scsipi_run_queue(chan); - splx(s); continue; } if (chan->chan_tflags & SCSIPI_CHANT_SHUTDOWN) { - splx(s); + mutex_exit(chan_mtx(chan)); break; } if (xs) { TAILQ_REMOVE(&chan->chan_complete, xs, channel_q); - splx(s); + mutex_exit(chan_mtx(chan)); /* * Have an xfer with an error; process it. @@ -2122,14 +2183,14 @@ scsipi_completion_thread(void *arg) */ scsipi_run_queue(chan); } else { - splx(s); + mutex_exit(chan_mtx(chan)); } } chan->chan_thread = NULL; /* In case parent is waiting for us to exit. */ - wakeup(&chan->chan_thread); + cv_broadcast(chan_cv_thread(chan)); kthread_exit(0); } @@ -2142,24 +2203,23 @@ int scsipi_thread_call_callback(struct scsipi_channel *chan, void (*callback)(struct scsipi_channel *, void *), void *arg) { - int s; - s = splbio(); + mutex_enter(chan_mtx(chan)); if ((chan->chan_flags & SCSIPI_CHAN_TACTIVE) == 0) { /* kernel thread doesn't exist yet */ - splx(s); + mutex_exit(chan_mtx(chan)); return ESRCH; } if (chan->chan_tflags & SCSIPI_CHANT_CALLBACK) { - splx(s); + mutex_exit(chan_mtx(chan)); return EBUSY; } scsipi_channel_freeze(chan, 1); chan->chan_callback = callback; chan->chan_callback_arg = arg; chan->chan_tflags |= SCSIPI_CHANT_CALLBACK; - wakeup(&chan->chan_complete); - splx(s); + cv_broadcast(chan_cv_complete(chan)); + mutex_exit(chan_mtx(chan)); return(0); } @@ -2172,9 +2232,8 @@ void scsipi_async_event(struct scsipi_channel *chan, scsipi_async_event_t event, void *arg) { - int s; - s = splbio(); + mutex_enter(chan_mtx(chan)); switch (event) { case ASYNC_EVENT_MAX_OPENINGS: scsipi_async_event_max_openings(chan, @@ -2191,7 +2250,7 @@ scsipi_async_event(struct scsipi_channel *chan, scsipi_async_event_t event, scsipi_async_event_channel_reset(chan); break; } - splx(s); + mutex_exit(chan_mtx(chan)); } /* @@ -2240,7 +2299,7 @@ scsipi_set_xfer_mode(struct scsipi_channel *chan, int target, int immed) { struct scsipi_xfer_mode xm; struct scsipi_periph *itperiph; - int lun, s; + int lun; /* * Go to the minimal xfer mode. @@ -2263,9 +2322,7 @@ scsipi_set_xfer_mode(struct scsipi_channel *chan, int target, int immed) /* * Now issue the request to the adapter. */ - s = splbio(); scsipi_adapter_request(chan, ADAPTER_REQ_SET_XFER_MODE, &xm); - splx(s); /* * If we want this to happen immediately, issue a dummy * command, since most adapters can't really negotiate unless @@ -2284,7 +2341,7 @@ scsipi_set_xfer_mode(struct scsipi_channel *chan, int target, int immed) * scsipi_channel_reset: * * handle scsi bus reset - * called at splbio + * called with channel lock held */ static void scsipi_async_event_channel_reset(struct scsipi_channel *chan) @@ -2310,7 +2367,7 @@ scsipi_async_event_channel_reset(struct scsipi_channel *chan) channel_q); } } - wakeup(&chan->chan_complete); + cv_broadcast(chan_cv_complete(chan)); /* Catch xs with pending sense which may not have a REQSENSE xs yet */ for (target = 0; target < chan->chan_ntargets; target++) { if (target == chan->chan_id) @@ -2388,15 +2445,16 @@ scsipi_target_detach(struct scsipi_channel *chan, int target, int lun, int scsipi_adapter_addref(struct scsipi_adapter *adapt) { - int s, error = 0; + int error = 0; - s = splbio(); - if (adapt->adapt_refcnt++ == 0 && adapt->adapt_enable != NULL) { - error = (*adapt->adapt_enable)(adapt->adapt_dev, 1); + if (atomic_inc_uint_nv(&adapt->adapt_refcnt) == 1 + && adapt->adapt_enable != NULL) { + scsipi_adapter_lock(adapt); + error = scsipi_adapter_enable(adapt, 1); + scsipi_adapter_unlock(adapt); if (error) - adapt->adapt_refcnt--; + atomic_dec_uint(&adapt->adapt_refcnt); } - splx(s); return (error); } @@ -2409,12 +2467,13 @@ scsipi_adapter_addref(struct scsipi_adapter *adapt) void scsipi_adapter_delref(struct scsipi_adapter *adapt) { - int s; - s = splbio(); - if (adapt->adapt_refcnt-- == 1 && adapt->adapt_enable != NULL) - (void) (*adapt->adapt_enable)(adapt->adapt_dev, 0); - splx(s); + if (atomic_dec_uint_nv(&adapt->adapt_refcnt) == 0 + && adapt->adapt_enable != NULL) { + scsipi_adapter_lock(adapt); + (void) scsipi_adapter_enable(adapt, 0); + scsipi_adapter_unlock(adapt); + } } static struct scsipi_syncparam { @@ -2469,6 +2528,71 @@ scsipi_sync_factor_to_freq(int factor) return (10000000 / ((factor * 4) * 10)); } +static inline void +scsipi_adapter_lock(struct scsipi_adapter *adapt) +{ + + if ((adapt->adapt_flags & SCSIPI_ADAPT_MPSAFE) == 0) + KERNEL_LOCK(1, NULL); +} + +static inline void +scsipi_adapter_unlock(struct scsipi_adapter *adapt) +{ + + if ((adapt->adapt_flags & SCSIPI_ADAPT_MPSAFE) == 0) + KERNEL_UNLOCK_ONE(NULL); +} + +void +scsipi_adapter_minphys(struct scsipi_channel *chan, struct buf *bp) +{ + struct scsipi_adapter *adapt = chan->chan_adapter; + + scsipi_adapter_lock(adapt); + (adapt->adapt_minphys)(bp); + scsipi_adapter_unlock(chan->chan_adapter); +} + +void +scsipi_adapter_request(struct scsipi_channel *chan, + scsipi_adapter_req_t req, void *arg) + +{ + struct scsipi_adapter *adapt = chan->chan_adapter; + + scsipi_adapter_lock(adapt); + (adapt->adapt_request)(chan, req, arg); + scsipi_adapter_unlock(adapt); +} + +int +scsipi_adapter_ioctl(struct scsipi_channel *chan, u_long cmd, + void *data, int flag, struct proc *p) +{ + struct scsipi_adapter *adapt = chan->chan_adapter; + int error; + + if (adapt->adapt_ioctl == NULL) + return ENOTTY; + + scsipi_adapter_lock(adapt); + error = (adapt->adapt_ioctl)(chan, cmd, data, flag, p); + scsipi_adapter_unlock(adapt); + return error; +} + +int +scsipi_adapter_enable(struct scsipi_adapter *adapt, int enable) +{ + int error; + + scsipi_adapter_lock(adapt); + error = (adapt->adapt_enable)(adapt->adapt_dev, enable); + scsipi_adapter_unlock(adapt); + return error; +} + #ifdef SCSIPI_DEBUG /* * Given a scsipi_xfer, dump the request, in all its glory diff --git a/sys/dev/scsipi/scsipi_base.h b/sys/dev/scsipi/scsipi_base.h index ea099a9f5b5..ea96d7d8699 100644 --- a/sys/dev/scsipi/scsipi_base.h +++ b/sys/dev/scsipi/scsipi_base.h @@ -1,4 +1,4 @@ -/* $NetBSD: scsipi_base.h,v 1.22 2008/04/28 20:23:58 martin Exp $ */ +/* $NetBSD: scsipi_base.h,v 1.23 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. @@ -35,7 +35,17 @@ struct scsipi_xfer *scsipi_get_xs(struct scsipi_periph *, int); void scsipi_put_xs(struct scsipi_xfer *); -static __inline struct scsipi_xfer *scsipi_make_xs(struct scsipi_periph *, +static __inline struct scsipi_xfer *scsipi_make_xs_internal(struct scsipi_periph *, + struct scsipi_generic *, int cmdlen, u_char *data_addr, + int datalen, int retries, int timeout, struct buf *, + int flags) __unused; + +static __inline struct scsipi_xfer *scsipi_make_xs_unlocked(struct scsipi_periph *, + struct scsipi_generic *, int cmdlen, u_char *data_addr, + int datalen, int retries, int timeout, struct buf *, + int flags) __unused; + +static __inline struct scsipi_xfer *scsipi_make_xs_locked(struct scsipi_periph *, struct scsipi_generic *, int cmdlen, u_char *data_addr, int datalen, int retries, int timeout, struct buf *, int flags) __unused; @@ -45,7 +55,7 @@ static __inline struct scsipi_xfer *scsipi_make_xs(struct scsipi_periph *, */ static __inline struct scsipi_xfer * -scsipi_make_xs(struct scsipi_periph *periph, struct scsipi_generic *cmd, +scsipi_make_xs_internal(struct scsipi_periph *periph, struct scsipi_generic *cmd, int cmdlen, u_char *data_addr, int datalen, int retries, int timeout, struct buf *bp, int flags) { @@ -70,4 +80,24 @@ scsipi_make_xs(struct scsipi_periph *periph, struct scsipi_generic *cmd, return (xs); } +static __inline struct scsipi_xfer * +scsipi_make_xs_unlocked(struct scsipi_periph *periph, struct scsipi_generic *cmd, + int cmdlen, u_char *data_addr, int datalen, int retries, int timeout, + struct buf *bp, int flags) +{ + + return scsipi_make_xs_internal(periph, cmd, cmdlen, data_addr, + datalen, retries, timeout, bp, flags & ~XS_CTL_NOSLEEP); +} + +static __inline struct scsipi_xfer * +scsipi_make_xs_locked(struct scsipi_periph *periph, struct scsipi_generic *cmd, + int cmdlen, u_char *data_addr, int datalen, int retries, int timeout, + struct buf *bp, int flags) +{ + + return scsipi_make_xs_internal(periph, cmd, cmdlen, data_addr, + datalen, retries, timeout, bp, flags | XS_CTL_NOSLEEP); +} + #endif /* _DEV_SCSIPI_SCSIPI_BASE_H_ */ diff --git a/sys/dev/scsipi/scsipi_ioctl.c b/sys/dev/scsipi/scsipi_ioctl.c index d21598a7a6c..39e0643a823 100644 --- a/sys/dev/scsipi/scsipi_ioctl.c +++ b/sys/dev/scsipi/scsipi_ioctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: scsipi_ioctl.c,v 1.68 2015/08/24 22:50:33 pooka Exp $ */ +/* $NetBSD: scsipi_ioctl.c,v 1.69 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: scsipi_ioctl.c,v 1.68 2015/08/24 22:50:33 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: scsipi_ioctl.c,v 1.69 2016/11/20 15:37:19 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_freebsd.h" @@ -72,29 +72,35 @@ struct scsi_ioctl { }; static LIST_HEAD(, scsi_ioctl) si_head; +static kmutex_t si_lock; + +void +scsipi_ioctl_init(void) +{ + + mutex_init(&si_lock, MUTEX_DEFAULT, IPL_BIO); +} static struct scsi_ioctl * si_get(void) { struct scsi_ioctl *si; - int s; si = malloc(sizeof(struct scsi_ioctl), M_TEMP, M_WAITOK|M_ZERO); buf_init(&si->si_bp); - s = splbio(); + mutex_enter(&si_lock); LIST_INSERT_HEAD(&si_head, si, si_list); - splx(s); + mutex_exit(&si_lock); return (si); } static void si_free(struct scsi_ioctl *si) { - int s; - s = splbio(); + mutex_enter(&si_lock); LIST_REMOVE(si, si_list); - splx(s); + mutex_exit(&si_lock); buf_destroy(&si->si_bp); free(si, M_TEMP); } @@ -103,13 +109,12 @@ static struct scsi_ioctl * si_find(struct buf *bp) { struct scsi_ioctl *si; - int s; - s = splbio(); + mutex_enter(&si_lock); for (si = si_head.lh_first; si != 0; si = si->si_list.le_next) if (bp == &si->si_bp) break; - splx(s); + mutex_exit(&si_lock); return (si); } @@ -128,7 +133,6 @@ scsipi_user_done(struct scsipi_xfer *xs) struct scsi_ioctl *si; scsireq_t *screq; struct scsipi_periph *periph = xs->xs_periph; - int s; bp = xs->bp; #ifdef DIAGNOSTIC @@ -200,9 +204,9 @@ scsipi_user_done(struct scsipi_xfer *xs) } if (xs->xs_control & XS_CTL_ASYNC) { - s = splbio(); + mutex_enter(chan_mtx(periph->periph_channel)); scsipi_put_xs(xs); - splx(s); + mutex_exit(chan_mtx(periph->periph_channel)); } } diff --git a/sys/dev/scsipi/scsipiconf.c b/sys/dev/scsipi/scsipiconf.c index cebab06e7c9..467accd5936 100644 --- a/sys/dev/scsipi/scsipiconf.c +++ b/sys/dev/scsipi/scsipiconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: scsipiconf.c,v 1.41 2016/05/02 19:18:29 christos Exp $ */ +/* $NetBSD: scsipiconf.c,v 1.42 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: scsipiconf.c,v 1.41 2016/05/02 19:18:29 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: scsipiconf.c,v 1.42 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -69,7 +69,8 @@ void (*scsipi_print_sense_data)(struct scsi_sense_data *, int) = int scsi_verbose_loaded = 0; -int scsipi_print_sense_stub(struct scsipi_xfer * xs, int verbosity) +int +scsipi_print_sense_stub(struct scsipi_xfer * xs, int verbosity) { scsipi_load_verbose(); if (scsi_verbose_loaded) @@ -78,7 +79,8 @@ int scsipi_print_sense_stub(struct scsipi_xfer * xs, int verbosity) return 0; } -void scsipi_print_sense_data_stub(struct scsi_sense_data *sense, int verbosity) +void +scsipi_print_sense_data_stub(struct scsi_sense_data *sense, int verbosity) { scsipi_load_verbose(); if (scsi_verbose_loaded) @@ -91,13 +93,21 @@ scsipi_command(struct scsipi_periph *periph, struct scsipi_generic *cmd, struct buf *bp, int flags) { struct scsipi_xfer *xs; + int rc; - xs = scsipi_make_xs(periph, cmd, cmdlen, data_addr, datalen, retries, + /* + * execute unlocked to allow waiting for memory + */ + xs = scsipi_make_xs_unlocked(periph, cmd, cmdlen, data_addr, datalen, retries, timeout, bp, flags); if (!xs) return (ENOMEM); - return (scsipi_execute_xs(xs)); + mutex_enter(chan_mtx(periph->periph_channel)); + rc = scsipi_execute_xs(xs); + mutex_exit(chan_mtx(periph->periph_channel)); + + return rc; } /* @@ -137,11 +147,22 @@ scsipi_alloc_periph(int malloc_flag) TAILQ_INIT(&periph->periph_xferq); callout_init(&periph->periph_callout, 0); + cv_init(&periph->periph_cv, "periph"); return periph; } /* + * cleanup and free scsipi_periph structure + */ +void +scsipi_free_periph(struct scsipi_periph *periph) +{ + cv_destroy(&periph->periph_cv); + free(periph, M_DEVBUF); +} + +/* * Return a priority based on how much of the inquiry data matches * the patterns for the particular driver. */ diff --git a/sys/dev/scsipi/scsipiconf.h b/sys/dev/scsipi/scsipiconf.h index 5c6b14d101b..7c6b378c5ef 100644 --- a/sys/dev/scsipi/scsipiconf.h +++ b/sys/dev/scsipi/scsipiconf.h @@ -1,4 +1,4 @@ -/* $NetBSD: scsipiconf.h,v 1.123 2016/05/02 19:18:29 christos Exp $ */ +/* $NetBSD: scsipiconf.h,v 1.124 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2004 The NetBSD Foundation, Inc. @@ -54,6 +54,7 @@ typedef int boolean; #include <sys/callout.h> #include <sys/queue.h> +#include <sys/condvar.h> #include <dev/scsipi/scsi_spc.h> #include <dev/scsipi/scsipi_debug.h> @@ -188,7 +189,7 @@ struct scsipi_inquiry_pattern; struct scsipi_adapter { device_t adapt_dev; /* pointer to adapter's device */ int adapt_nchannels; /* number of adapter channels */ - int adapt_refcnt; /* adapter's reference count */ + volatile int adapt_refcnt; /* adapter's reference count */ int adapt_openings; /* total # of command openings */ int adapt_max_periph; /* max openings per periph */ int adapt_flags; @@ -203,23 +204,22 @@ struct scsipi_adapter { struct disk_parms *, u_long); int (*adapt_accesschk)(struct scsipi_periph *, struct scsipi_inquiry_pattern *); + + kmutex_t adapt_mtx; + bool adapt_running; /* attachment initialized */ }; #endif /* adapt_flags */ #define SCSIPI_ADAPT_POLL_ONLY 0x01 /* Adaptor can't do interrupts. */ +#define SCSIPI_ADAPT_MPSAFE 0x02 /* Adaptor doesn't need kernel lock */ -#define scsipi_adapter_minphys(chan, bp) \ - (*(chan)->chan_adapter->adapt_minphys)((bp)) - -#define scsipi_adapter_request(chan, req, arg) \ - (*(chan)->chan_adapter->adapt_request)((chan), (req), (arg)) - -#define scsipi_adapter_ioctl(chan, cmd, data, flag, p) \ - (*(chan)->chan_adapter->adapt_ioctl)((chan), (cmd), (data), (flag), (p)) - -#define scsipi_adapter_enable(chan, enable) \ - (*(chan)->chan_adapt->adapt_enable)((chan), (enable)) +void scsipi_adapter_minphys(struct scsipi_channel *, struct buf *); +void scsipi_adapter_request(struct scsipi_channel *, + scsipi_adapter_req_t, void *); +int scsipi_adapter_ioctl(struct scsipi_channel *, u_long, + void *, int, struct proc *); +int scsipi_adapter_enable(struct scsipi_adapter *, int); /* @@ -307,7 +307,17 @@ struct scsipi_channel { /* callback we may have to call after forking the kthread */ void (*chan_init_cb)(struct scsipi_channel *, void *); void *chan_init_cb_arg; + + kcondvar_t chan_cv_comp; + kcondvar_t chan_cv_thr; + kcondvar_t chan_cv_xs; + +#define chan_cv_complete(ch) (&(ch)->chan_cv_comp) +#define chan_cv_thread(ch) (&(ch)->chan_cv_thr) }; + +#define chan_running(ch) ((ch)->chan_adapter->adapt_running) +#define chan_mtx(ch) (&(ch)->chan_adapter->adapt_mtx) #endif /* chan_flags */ @@ -401,6 +411,9 @@ struct scsipi_periph { /* xfer which has a pending CHECK_CONDITION */ struct scsipi_xfer *periph_xscheck; + kcondvar_t periph_cv; +#define periph_cv_periph(p) (&(p)->periph_cv) +#define periph_cv_active(p) (&(p)->periph_cv) }; #endif @@ -482,6 +495,7 @@ typedef enum { XS_REQUEUE /* requeue this command */ } scsipi_xfer_result_t; +#ifdef _KERNEL /* * Each scsipi transaction is fully described by one of these structures * It includes information about the source of the command and also the @@ -544,7 +558,10 @@ struct scsipi_xfer { struct scsipi_generic cmdstore __aligned(4); /* stash the command in here */ + +#define xs_cv(xs) (&(xs)->xs_periph->periph_channel->chan_cv_xs) }; +#endif /* * scsipi_xfer control flags @@ -635,6 +652,7 @@ struct scsi_quirk_inquiry_pattern { #ifdef _KERNEL void scsipi_init(void); +void scsipi_ioctl_init(void); void scsipi_load_verbose(void); int scsipi_command(struct scsipi_periph *, struct scsipi_generic *, int, u_char *, int, int, int, struct buf *, int); @@ -662,6 +680,7 @@ int scsipi_interpret_sense(struct scsipi_xfer *); void scsipi_wait_drain(struct scsipi_periph *); void scsipi_kill_pending(struct scsipi_periph *); struct scsipi_periph *scsipi_alloc_periph(int); +void scsipi_free_periph(struct scsipi_periph *); /* Function pointers for scsiverbose module */ extern int (*scsipi_print_sense)(struct scsipi_xfer *, int); @@ -692,6 +711,8 @@ void scsipi_remove_periph(struct scsipi_channel *, struct scsipi_periph *); struct scsipi_periph *scsipi_lookup_periph(struct scsipi_channel *, int, int); +struct scsipi_periph *scsipi_lookup_periph_locked(struct scsipi_channel *, + int, int); int scsipi_target_detach(struct scsipi_channel *, int, int, int); int scsipi_adapter_addref(struct scsipi_adapter *); @@ -705,6 +726,9 @@ void scsipi_periph_freeze(struct scsipi_periph *, int); void scsipi_periph_thaw(struct scsipi_periph *, int); void scsipi_periph_timed_thaw(void *); +void scsipi_periph_freeze_locked(struct scsipi_periph *, int); +void scsipi_periph_thaw_locked(struct scsipi_periph *, int); + int scsipi_sync_period_to_factor(int); int scsipi_sync_factor_to_period(int); int scsipi_sync_factor_to_freq(int); diff --git a/sys/dev/scsipi/sd.c b/sys/dev/scsipi/sd.c index 6fbd3e1d684..f00da0d1224 100644 --- a/sys/dev/scsipi/sd.c +++ b/sys/dev/scsipi/sd.c @@ -1,4 +1,4 @@ -/* $NetBSD: sd.c,v 1.318 2016/11/20 02:38:24 pgoyette Exp $ */ +/* $NetBSD: sd.c,v 1.319 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. @@ -47,12 +47,14 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.318 2016/11/20 02:38:24 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.319 2016/11/20 15:37:19 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_scsi.h" #endif +#define SD_MPSAFE D_MPSAFE + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -165,7 +167,7 @@ const struct bdevsw sd_bdevsw = { .d_dump = sddump, .d_psize = sdsize, .d_discard = nodiscard, - .d_flag = D_DISK + .d_flag = D_DISK | SD_MPSAFE }; const struct cdevsw sd_cdevsw = { @@ -180,7 +182,7 @@ const struct cdevsw sd_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_DISK + .d_flag = D_DISK | SD_MPSAFE }; static struct dkdriver sddkdriver = { @@ -356,7 +358,9 @@ static int sddetach(device_t self, int flags) { struct sd_softc *sd = device_private(self); - int s, bmaj, cmaj, i, mn, rc; + struct scsipi_periph *periph = sd->sc_periph; + struct scsipi_channel *chan = periph->periph_channel; + int bmaj, cmaj, i, mn, rc; rnd_add_uint32(&sd->rnd_source, 0); @@ -380,7 +384,7 @@ sddetach(device_t self, int flags) /* Delete all of our wedges. */ dkwedge_delall(&sd->sc_dk); - s = splbio(); + mutex_enter(chan_mtx(chan)); /* Kill off any queued buffers. */ bufq_drain(sd->buf_queue); @@ -388,7 +392,7 @@ sddetach(device_t self, int flags) /* Kill off any pending commands. */ scsipi_kill_pending(sd->sc_periph); - splx(s); + mutex_exit(chan_mtx(chan)); bufq_free(sd->buf_queue); @@ -669,9 +673,9 @@ sdstrategy(struct buf *bp) { struct sd_softc *sd = device_lookup_private(&sd_cd, SDUNIT(bp->b_dev)); struct scsipi_periph *periph = sd->sc_periph; + struct scsipi_channel *chan = periph->periph_channel; struct disklabel *lp; daddr_t blkno; - int s; bool sector_aligned; SC_DEBUG(sd->sc_periph, SCSIPI_DB2, ("sdstrategy ")); @@ -740,7 +744,7 @@ sdstrategy(struct buf *bp) bp->b_rawblkno = blkno; - s = splbio(); + mutex_enter(chan_mtx(chan)); /* * Place it in the queue of disk activities for this disk. @@ -754,9 +758,9 @@ sdstrategy(struct buf *bp) * Tell the device to get going on the transfer if it's * not doing anything, otherwise just wait for completion */ - sdstart(sd->sc_periph); + sdstart(periph); - splx(s); + mutex_exit(chan_mtx(chan)); return; done: @@ -780,8 +784,8 @@ done: * have been made of the scsi driver, to ensure that the queue * continues to be drained. * - * must be called at the correct (highish) spl level - * sdstart() is called at splbio from sdstrategy, sdrestart and scsipi_done + * must be called with channel lock held + * sdstart() is called from sdstrategy, sdrestart and scsipi_done */ static void sdstart(struct scsipi_periph *periph) @@ -797,6 +801,7 @@ sdstart(struct scsipi_periph *periph) int nblks, cmdlen, error __diagused, flags; SC_DEBUG(periph, SCSIPI_DB2, ("sdstart ")); + /* * Check if the device has room for another command */ @@ -808,7 +813,7 @@ sdstart(struct scsipi_periph *periph) */ if (periph->periph_flags & PERIPH_WAITING) { periph->periph_flags &= ~PERIPH_WAITING; - wakeup((void *)periph); + cv_broadcast(periph_cv_periph(periph)); return; } @@ -902,7 +907,7 @@ sdstart(struct scsipi_periph *periph) * Call the routine that chats with the adapter. * Note: we cannot sleep as we may be an interrupt */ - xs = scsipi_make_xs(periph, cmdp, cmdlen, + xs = scsipi_make_xs_locked(periph, cmdp, cmdlen, (u_char *)bp->b_data, bp->b_bcount, SDRETRIES, SD_IO_TIMEOUT, bp, flags); if (__predict_false(xs == NULL)) { @@ -934,9 +939,12 @@ sdstart(struct scsipi_periph *periph) static void sdrestart(void *v) { - int s = splbio(); + struct scsipi_periph *periph = v; + struct scsipi_channel *chan = periph->periph_channel; + + mutex_enter(chan_mtx(chan)); sdstart((struct scsipi_periph *)v); - splx(s); + mutex_exit(chan_mtx(chan)); } static void @@ -1020,7 +1028,6 @@ sdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) struct scsipi_periph *periph = sd->sc_periph; int part = SDPART(dev); int error; - int s; #ifdef __HAVE_OLD_DISKLABEL struct disklabel *newlabel = NULL; #endif @@ -1206,6 +1213,7 @@ sdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) case DIOCGSTRATEGY: { struct disk_strategy *dks = addr; + int s; s = splbio(); strlcpy(dks->dks_name, bufq_getstrategyname(sd->buf_queue), @@ -1221,6 +1229,7 @@ sdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) struct disk_strategy *dks = addr; struct bufq_state *new_bufq; struct bufq_state *old_bufq; + int s; if ((flag & FWRITE) == 0) { return EBADF; @@ -1367,9 +1376,10 @@ static int sd_interpret_sense(struct scsipi_xfer *xs) { struct scsipi_periph *periph = xs->xs_periph; + struct scsipi_channel *chan = periph->periph_channel; struct scsi_sense_data *sense = &xs->sense.scsi_sense; struct sd_softc *sd = device_private(periph->periph_dev); - int s, error, retval = EJUSTRETURN; + int error, retval = EJUSTRETURN; /* * If the periph is already recovering, just do the normal @@ -1427,9 +1437,9 @@ sd_interpret_sense(struct scsipi_xfer *xs) } else if (sense->ascq == 0x02) { printf("%s: pack is stopped, restarting...\n", device_xname(sd->sc_dev)); - s = splbio(); + mutex_enter(chan_mtx(chan)); periph->periph_flags |= PERIPH_RECOVERING; - splx(s); + mutex_exit(chan_mtx(chan)); error = scsipi_start(periph, SSS_START, XS_CTL_URGENT|XS_CTL_HEAD_TAG| XS_CTL_THAW_PERIPH|XS_CTL_FREEZE_PERIPH); @@ -1439,9 +1449,9 @@ sd_interpret_sense(struct scsipi_xfer *xs) retval = error; } else retval = ERESTART; - s = splbio(); + mutex_enter(chan_mtx(chan)); periph->periph_flags &= ~PERIPH_RECOVERING; - splx(s); + mutex_exit(chan_mtx(chan)); } } if (SSD_SENSE_KEY(sense->flags) == SKEY_MEDIUM_ERROR && diff --git a/sys/dev/scsipi/ses.c b/sys/dev/scsipi/ses.c index f448e199ddd..38c120a7d4a 100644 --- a/sys/dev/scsipi/ses.c +++ b/sys/dev/scsipi/ses.c @@ -1,4 +1,4 @@ -/* $NetBSD: ses.c,v 1.49 2016/07/14 10:19:06 msaitoh Exp $ */ +/* $NetBSD: ses.c,v 1.50 2016/11/20 15:37:19 mlelstv Exp $ */ /* * Copyright (C) 2000 National Aeronautics & Space Administration * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ses.c,v 1.49 2016/07/14 10:19:06 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ses.c,v 1.50 2016/11/20 15:37:19 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_scsi.h" @@ -150,7 +150,7 @@ const struct cdevsw ses_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_OTHER + .d_flag = D_OTHER | D_MPSAFE }; static int ses_runcmd(struct ses_softc *, char *, int, char *, int *); diff --git a/sys/dev/scsipi/ss.c b/sys/dev/scsipi/ss.c index 3c4cebc6d6b..c4690bbd94b 100644 --- a/sys/dev/scsipi/ss.c +++ b/sys/dev/scsipi/ss.c @@ -1,4 +1,4 @@ -/* $NetBSD: ss.c,v 1.87 2016/11/20 02:38:24 pgoyette Exp $ */ +/* $NetBSD: ss.c,v 1.88 2016/11/20 15:37:19 mlelstv Exp $ */ /* * Copyright (c) 1995 Kenneth Stailey. All rights reserved. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ss.c,v 1.87 2016/11/20 02:38:24 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ss.c,v 1.88 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -100,7 +100,7 @@ const struct cdevsw ss_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_OTHER + .d_flag = D_OTHER | D_MPSAFE }; static void ssstrategy(struct buf *); @@ -199,7 +199,9 @@ static int ssdetach(device_t self, int flags) { struct ss_softc *ss = device_private(self); - int s, cmaj, mn; + struct scsipi_periph *periph = ss->sc_periph; + struct scsipi_channel *chan = periph->periph_channel; + int cmaj, mn; /* locate the major number */ cmaj = cdevsw_lookup_major(&ss_cdevsw); @@ -207,15 +209,15 @@ ssdetach(device_t self, int flags) /* kill any pending restart */ callout_stop(&ss->sc_callout); - s = splbio(); + mutex_enter(chan_mtx(chan)); /* Kill off any queued buffers. */ bufq_drain(ss->buf_queue); /* Kill off any pending commands. */ - scsipi_kill_pending(ss->sc_periph); + scsipi_kill_pending(periph); - splx(s); + mutex_exit(chan_mtx(chan)); bufq_free(ss->buf_queue); @@ -388,7 +390,7 @@ ssstrategy(struct buf *bp) { struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev)); struct scsipi_periph *periph = ss->sc_periph; - int s; + struct scsipi_channel *chan = periph->periph_channel; SC_DEBUG(ss->sc_periph, SCSIPI_DB1, ("ssstrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount, @@ -416,7 +418,7 @@ ssstrategy(struct buf *bp) if (bp->b_bcount == 0) goto done; - s = splbio(); + mutex_enter(chan_mtx(chan)); /* * Place it in the queue of activities for this scanner @@ -430,9 +432,9 @@ ssstrategy(struct buf *bp) * not doing anything, otherwise just wait for completion * (All a bit silly if we're only allowing 1 open but..) */ - ssstart(ss->sc_periph); + ssstart(periph); - splx(s); + mutex_exit(chan_mtx(chan)); return; done: /* Correctly set the buf to indicate a completed xfer */ @@ -452,7 +454,7 @@ done: * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. - * ssstart() is called at splbio + * ssstart() is called with channel lock held. */ static void ssstart(struct scsipi_periph *periph) @@ -467,7 +469,7 @@ ssstart(struct scsipi_periph *periph) /* if a special awaits, let it proceed first */ if (periph->periph_flags & PERIPH_WAITING) { periph->periph_flags &= ~PERIPH_WAITING; - wakeup((void *)periph); + cv_broadcast(periph_cv_periph(periph)); return; } @@ -487,9 +489,12 @@ ssstart(struct scsipi_periph *periph) void ssrestart(void *v) { - int s = splbio(); - ssstart((struct scsipi_periph *)v); - splx(s); + struct scsipi_periph *periph = v; + struct scsipi_channel *chan = periph->periph_channel; + + mutex_enter(chan_mtx(chan)); + ssstart(periph); + mutex_exit(chan_mtx(chan)); } static void diff --git a/sys/dev/scsipi/ss_mustek.c b/sys/dev/scsipi/ss_mustek.c index d9761a83a8c..0e80cbcf4c0 100644 --- a/sys/dev/scsipi/ss_mustek.c +++ b/sys/dev/scsipi/ss_mustek.c @@ -1,4 +1,4 @@ -/* $NetBSD: ss_mustek.c,v 1.42 2013/10/25 16:04:57 martin Exp $ */ +/* $NetBSD: ss_mustek.c,v 1.43 2016/11/20 15:37:19 mlelstv Exp $ */ /* * Copyright (c) 1995 Joachim Koenig-Baltes. All rights reserved. @@ -46,7 +46,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ss_mustek.c,v 1.42 2013/10/25 16:04:57 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ss_mustek.c,v 1.43 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -466,7 +466,7 @@ mustek_read(struct ss_softc *ss, struct buf *bp) _lto3b(lines_to_read, cmd.length); /* go ask the adapter to do all this for us */ - xs = scsipi_make_xs(periph, + xs = scsipi_make_xs_locked(periph, (struct scsipi_generic *) &cmd, sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount, MUSTEK_RETRIES, 10000, bp, @@ -532,7 +532,7 @@ mustek_get_status(struct ss_softc *ss, int timeout, int update) (timeout-- <= 0)) break; /* please wait a second */ - tsleep((void *)mustek_get_status, PRIBIO + 1, "mtkrdy", hz); + kpause("mtkrdy", false, hz, NULL); } if (update) { diff --git a/sys/dev/scsipi/ss_scanjet.c b/sys/dev/scsipi/ss_scanjet.c index da1c2290a28..90d6d55f374 100644 --- a/sys/dev/scsipi/ss_scanjet.c +++ b/sys/dev/scsipi/ss_scanjet.c @@ -1,4 +1,4 @@ -/* $NetBSD: ss_scanjet.c,v 1.53 2013/10/25 16:05:47 martin Exp $ */ +/* $NetBSD: ss_scanjet.c,v 1.54 2016/11/20 15:37:19 mlelstv Exp $ */ /* * Copyright (c) 1995 Kenneth Stailey. All rights reserved. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ss_scanjet.c,v 1.53 2013/10/25 16:05:47 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ss_scanjet.c,v 1.54 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -266,7 +266,7 @@ scanjet_read(struct ss_softc *ss, struct buf *bp) _lto3b(bp->b_bcount, cmd.len); /* go ask the adapter to do all this for us */ - xs = scsipi_make_xs(periph, + xs = scsipi_make_xs_locked(periph, (struct scsipi_generic *)&cmd, sizeof(cmd), (u_char *)bp->b_data, bp->b_bcount, SCANJET_RETRIES, 100000, bp, diff --git a/sys/dev/scsipi/st.c b/sys/dev/scsipi/st.c index 9a27c706faf..0a8990ca549 100644 --- a/sys/dev/scsipi/st.c +++ b/sys/dev/scsipi/st.c @@ -1,4 +1,4 @@ -/* $NetBSD: st.c,v 1.229 2016/11/20 02:38:24 pgoyette Exp $ */ +/* $NetBSD: st.c,v 1.230 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. @@ -50,7 +50,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: st.c,v 1.229 2016/11/20 02:38:24 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: st.c,v 1.230 2016/11/20 15:37:19 mlelstv Exp $"); #ifdef _KERNEL_OPT #include "opt_scsi.h" @@ -114,7 +114,7 @@ const struct bdevsw st_bdevsw = { .d_dump = stdump, .d_psize = nosize, .d_discard = nodiscard, - .d_flag = D_TAPE + .d_flag = D_TAPE | D_MPSAFE }; const struct cdevsw st_cdevsw = { @@ -129,7 +129,7 @@ const struct cdevsw st_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_TAPE + .d_flag = D_TAPE | D_MPSAFE }; /* @@ -431,7 +431,9 @@ int stdetach(device_t self, int flags) { struct st_softc *st = device_private(self); - int s, bmaj, cmaj, mn; + struct scsipi_periph *periph = st->sc_periph; + struct scsipi_channel *chan = periph->periph_channel; + int bmaj, cmaj, mn; /* locate the major number */ bmaj = bdevsw_lookup_major(&st_bdevsw); @@ -440,7 +442,7 @@ stdetach(device_t self, int flags) /* kill any pending restart */ callout_stop(&st->sc_callout); - s = splbio(); + mutex_enter(chan_mtx(chan)); /* Kill off any queued buffers. */ bufq_drain(st->buf_queue); @@ -448,7 +450,7 @@ stdetach(device_t self, int flags) /* Kill off any pending commands. */ scsipi_kill_pending(st->sc_periph); - splx(s); + mutex_exit(chan_mtx(chan)); bufq_free(st->buf_queue); @@ -1042,9 +1044,10 @@ static void ststrategy(struct buf *bp) { struct st_softc *st = device_lookup_private(&st_cd, STUNIT(bp->b_dev)); - int s; + struct scsipi_periph *periph = st->sc_periph; + struct scsipi_channel *chan = periph->periph_channel; - SC_DEBUG(st->sc_periph, SCSIPI_DB1, + SC_DEBUG(periph, SCSIPI_DB1, ("ststrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno)); /* If it's a null transfer, return immediately */ @@ -1074,7 +1077,7 @@ ststrategy(struct buf *bp) bp->b_error = EIO; goto abort; } - s = splbio(); + mutex_enter(chan_mtx(chan)); /* * Place it in the queue of activities for this tape @@ -1088,9 +1091,9 @@ ststrategy(struct buf *bp) * not doing anything, otherwise just wait for completion * (All a bit silly if we're only allowing 1 open but..) */ - ststart(st->sc_periph); + ststart(periph); - splx(s); + mutex_exit(chan_mtx(chan)); return; abort: /* @@ -1114,7 +1117,7 @@ abort: * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. - * ststart() is called at splbio + * ststart() is called with channel lock held */ static void ststart(struct scsipi_periph *periph) @@ -1131,7 +1134,7 @@ ststart(struct scsipi_periph *periph) /* if a special awaits, let it proceed first */ if (periph->periph_flags & PERIPH_WAITING) { periph->periph_flags &= ~PERIPH_WAITING; - wakeup((void *)periph); + cv_broadcast(periph_cv_periph(periph)); return; } @@ -1230,7 +1233,7 @@ ststart(struct scsipi_periph *periph) st->flags &= ~ST_POSUPDATED; /* go ask the adapter to do all this for us */ - xs = scsipi_make_xs(periph, + xs = scsipi_make_xs_locked(periph, (struct scsipi_generic *)&cmd, sizeof(cmd), (u_char *)bp->b_data, bp->b_bcount, 0, ST_IO_TIME, bp, flags); @@ -1263,9 +1266,12 @@ ststart(struct scsipi_periph *periph) static void strestart(void *v) { - int s = splbio(); + struct scsipi_periph *periph = (struct scsipi_periph *)v; + struct scsipi_channel *chan = periph->periph_channel; + + mutex_enter(chan_mtx(chan)); ststart((struct scsipi_periph *)v); - splx(s); + mutex_exit(chan_mtx(chan)); } static void diff --git a/sys/dev/scsipi/uk.c b/sys/dev/scsipi/uk.c index f63b009e7b3..0b3cb7a9abc 100644 --- a/sys/dev/scsipi/uk.c +++ b/sys/dev/scsipi/uk.c @@ -1,4 +1,4 @@ -/* $NetBSD: uk.c,v 1.64 2016/08/05 17:04:58 maya Exp $ */ +/* $NetBSD: uk.c,v 1.65 2016/11/20 15:37:19 mlelstv Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uk.c,v 1.64 2016/08/05 17:04:58 maya Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uk.c,v 1.65 2016/11/20 15:37:19 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -87,7 +87,7 @@ const struct cdevsw uk_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_OTHER + .d_flag = D_OTHER | D_MPSAFE }; static int |
