diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2014-09-15 12:00:05 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2014-09-15 12:00:05 +0000 |
commit | 7eb662dd8f4683e3c765572966de1fa26569d8cd (patch) | |
tree | 9aabc561603e15bb8ea0832e69dec0661bd9407e /sys/dev | |
parent | 9e6fb0887b2d319c3a96817a536789c7ca236675 (diff) |
mark the interrupt handler mpsafe, and drop the kernel lock in the scs_cmd
paths. take it again when going back to other parts of the kernel.
tested by and ok kettenis@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/mpi.c | 41 | ||||
-rw-r--r-- | sys/dev/pci/mpi_pci.c | 4 |
2 files changed, 28 insertions, 17 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c index a42503bfa99..e7dcdb7fe34 100644 --- a/sys/dev/ic/mpi.c +++ b/sys/dev/ic/mpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpi.c,v 1.196 2014/09/14 14:17:24 jsg Exp $ */ +/* $OpenBSD: mpi.c,v 1.197 2014/09/15 12:00:04 dlg Exp $ */ /* * Copyright (c) 2005, 2006, 2009 David Gwynne <dlg@openbsd.org> @@ -1310,6 +1310,8 @@ mpi_scsi_cmd(struct scsi_xfer *xs) DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd\n", DEVNAME(sc)); + KERNEL_UNLOCK(); + if (xs->cmdlen > MPI_CDB_LEN) { DNPRINTF(MPI_D_CMD, "%s: CBD too big %d\n", DEVNAME(sc), xs->cmdlen); @@ -1318,8 +1320,7 @@ mpi_scsi_cmd(struct scsi_xfer *xs) xs->sense.flags = SKEY_ILLEGAL_REQUEST; xs->sense.add_sense_code = 0x20; xs->error = XS_SENSE; - scsi_done(xs); - return; + goto done; } ccb = xs->io; @@ -1371,23 +1372,25 @@ mpi_scsi_cmd(struct scsi_xfer *xs) htolem32(&io->sense_buf_low_addr, ccb->ccb_cmd_dva + ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb)); - if (mpi_load_xs(ccb) != 0) { - xs->error = XS_DRIVER_STUFFUP; - scsi_done(xs); - return; - } + if (mpi_load_xs(ccb) != 0) + goto stuffup; timeout_set(&xs->stimeout, mpi_timeout_xs, ccb); if (xs->flags & SCSI_POLL) { - if (mpi_poll(sc, ccb, xs->timeout) != 0) { - xs->error = XS_DRIVER_STUFFUP; - scsi_done(xs); - } - return; - } + if (mpi_poll(sc, ccb, xs->timeout) != 0) + goto stuffup; + } else + mpi_start(sc, ccb); - mpi_start(sc, ccb); + KERNEL_LOCK(); + return; + +stuffup: + xs->error = XS_DRIVER_STUFFUP; +done: + KERNEL_LOCK(); + scsi_done(xs); } void @@ -1414,7 +1417,9 @@ mpi_scsi_cmd_done(struct mpi_ccb *ccb) if (ccb->ccb_rcb == NULL) { /* no scsi error, we're ok so drop out early */ xs->status = SCSI_OK; + KERNEL_LOCK(); scsi_done(xs); + KERNEL_UNLOCK(); return; } @@ -2369,14 +2374,18 @@ mpi_evt_sas(struct mpi_softc *sc, struct mpi_rcb *rcb) switch (ch->reason) { case MPI_EVT_SASCH_REASON_ADDED: case MPI_EVT_SASCH_REASON_NO_PERSIST_ADDED: + KERNEL_LOCK(); if (scsi_req_probe(sc->sc_scsibus, ch->target, -1) != 0) { printf("%s: unable to request attach of %d\n", DEVNAME(sc), ch->target); } + KERNEL_UNLOCK(); break; case MPI_EVT_SASCH_REASON_NOT_RESPONDING: + KERNEL_LOCK(); scsi_activate(sc->sc_scsibus, ch->target, -1, DVACT_DEACTIVATE); + KERNEL_UNLOCK(); mtx_enter(&sc->sc_evt_scan_mtx); SIMPLEQ_INSERT_TAIL(&sc->sc_evt_scan_queue, rcb, rcb_link); @@ -2450,11 +2459,13 @@ mpi_evt_sas_detach_done(struct mpi_ccb *ccb) struct mpi_softc *sc = ccb->ccb_sc; struct mpi_msg_scsi_task_reply *r = ccb->ccb_rcb->rcb_reply; + KERNEL_LOCK(); if (scsi_req_detach(sc->sc_scsibus, r->target_id, -1, DETACH_FORCE) != 0) { printf("%s: unable to request detach of %d\n", DEVNAME(sc), r->target_id); } + KERNEL_UNLOCK(); mpi_push_reply(sc, ccb->ccb_rcb); scsi_io_put(&sc->sc_iopool, ccb); diff --git a/sys/dev/pci/mpi_pci.c b/sys/dev/pci/mpi_pci.c index a92a15eac8e..ac017549fe9 100644 --- a/sys/dev/pci/mpi_pci.c +++ b/sys/dev/pci/mpi_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpi_pci.c,v 1.24 2011/06/09 04:55:44 deraadt Exp $ */ +/* $OpenBSD: mpi_pci.c,v 1.25 2014/09/15 12:00:04 dlg Exp $ */ /* * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> @@ -142,7 +142,7 @@ mpi_pci_attach(struct device *parent, struct device *self, void *aux) goto unmap; } intrstr = pci_intr_string(psc->psc_pc, ih); - psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO, + psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO | IPL_MPSAFE, mpi_intr, sc, sc->sc_dev.dv_xname); if (psc->psc_ih == NULL) { printf(": unable to map interrupt%s%s\n", |