summaryrefslogtreecommitdiff
path: root/sys/dev/ic/mfi.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2010-12-30 08:53:51 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2010-12-30 08:53:51 +0000
commit6ad2a0b8c9cdd20f0f52baef150b521939c59572 (patch)
tree15faa2de15fe252951fafed715d0d6b5f5551132 /sys/dev/ic/mfi.c
parent1def543700ac1ab92b7f65e3178f9c25b08795ef (diff)
cut mfi over to using iopools.
this gets rid of NO_CCB, provides better scheduling of io between busy logical volumes on the same controller, and makes the ioctl and sensor paths more reliable. this is the least intrusive version of this change i could come up with. it only took 4 or 5 goes... ok marco@ deraadt@ says this is a good time for this change.
Diffstat (limited to 'sys/dev/ic/mfi.c')
-rw-r--r--sys/dev/ic/mfi.c91
1 files changed, 42 insertions, 49 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c
index d588363b0e9..d2d1799d57a 100644
--- a/sys/dev/ic/mfi.c
+++ b/sys/dev/ic/mfi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfi.c,v 1.113 2010/09/24 01:30:05 dlg Exp $ */
+/* $OpenBSD: mfi.c,v 1.114 2010/12/30 08:53:50 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -63,8 +63,8 @@ struct scsi_adapter mfi_switch = {
mfi_scsi_cmd, mfiminphys, 0, 0, mfi_scsi_ioctl
};
-struct mfi_ccb *mfi_get_ccb(struct mfi_softc *);
-void mfi_put_ccb(struct mfi_ccb *);
+void * mfi_get_ccb(void *);
+void mfi_put_ccb(void *, void *);
int mfi_init_ccb(struct mfi_softc *);
struct mfi_mem *mfi_allocmem(struct mfi_softc *, size_t);
@@ -85,6 +85,8 @@ int mfi_scsi_io(struct mfi_ccb *, struct scsi_xfer *, uint64_t,
void mfi_scsi_xs_done(struct mfi_ccb *);
int mfi_mgmt(struct mfi_softc *, uint32_t, uint32_t, uint32_t,
void *, uint8_t *);
+int mfi_do_mgmt(struct mfi_softc *, struct mfi_ccb * , uint32_t,
+ uint32_t, uint32_t, void *, uint8_t *);
void mfi_mgmt_done(struct mfi_ccb *);
#if NBIO > 0
@@ -146,9 +148,10 @@ static const struct mfi_iop_ops mfi_iop_gen2 = {
#define mfi_my_intr(_s) ((_s)->sc_iop->mio_intr(_s))
#define mfi_post(_s, _c) ((_s)->sc_iop->mio_post((_s), (_c)))
-struct mfi_ccb *
-mfi_get_ccb(struct mfi_softc *sc)
+void *
+mfi_get_ccb(void *cookie)
{
+ struct mfi_softc *sc = cookie;
struct mfi_ccb *ccb;
mtx_enter(&sc->sc_ccb_mtx);
@@ -165,9 +168,10 @@ mfi_get_ccb(struct mfi_softc *sc)
}
void
-mfi_put_ccb(struct mfi_ccb *ccb)
+mfi_put_ccb(void *cookie, void *io)
{
- struct mfi_softc *sc = ccb->ccb_sc;
+ struct mfi_softc *sc = cookie;
+ struct mfi_ccb *ccb = io;
struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
DNPRINTF(MFI_D_CCB, "%s: mfi_put_ccb: %p\n", DEVNAME(sc), ccb);
@@ -239,7 +243,7 @@ mfi_init_ccb(struct mfi_softc *sc)
ccb->ccb_dmamap);
/* add ccb to queue */
- mfi_put_ccb(ccb);
+ mfi_put_ccb(sc, ccb);
}
return (0);
@@ -436,7 +440,7 @@ mfi_initialize_firmware(struct mfi_softc *sc)
return (1);
}
- mfi_put_ccb(ccb);
+ mfi_put_ccb(sc, ccb);
return (0);
}
@@ -638,6 +642,7 @@ mfi_attach(struct mfi_softc *sc, enum mfi_iop iop)
SLIST_INIT(&sc->sc_ccb_freeq);
mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
+ scsi_iopool_init(&sc->sc_iopool, sc, mfi_get_ccb, mfi_put_ccb);
rw_init(&sc->sc_lock, "mfi_lock");
@@ -718,6 +723,7 @@ mfi_attach(struct mfi_softc *sc, enum mfi_iop iop)
sc->sc_link.adapter = &mfi_switch;
sc->sc_link.adapter_target = MFI_MAX_LD;
sc->sc_link.adapter_buswidth = sc->sc_max_ld;
+ sc->sc_link.pool = &sc->sc_iopool;
bzero(&saa, sizeof(saa));
saa.saa_sc_link = &sc->sc_link;
@@ -931,7 +937,6 @@ mfi_scsi_xs_done(struct mfi_ccb *ccb)
break;
}
- mfi_put_ccb(ccb);
scsi_done(xs);
}
@@ -988,7 +993,7 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
struct scsi_link *link = xs->sc_link;
struct mfi_softc *sc = link->adapter_softc;
struct device *dev = link->device_softc;
- struct mfi_ccb *ccb;
+ struct mfi_ccb *ccb = xs->io;
struct scsi_rw *rw;
struct scsi_rw_big *rwb;
struct scsi_rw_16 *rw16;
@@ -1007,13 +1012,6 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
goto stuffup;
}
- if ((ccb = mfi_get_ccb(sc)) == NULL) {
- DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_cmd no ccb\n", DEVNAME(sc));
- xs->error = XS_NO_CCB;
- scsi_done(xs);
- return;
- }
-
xs->error = XS_NOERROR;
switch (xs->cmd->opcode) {
@@ -1023,10 +1021,8 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
rwb = (struct scsi_rw_big *)xs->cmd;
blockno = (uint64_t)_4btol(rwb->addr);
blockcnt = _2btol(rwb->length);
- if (mfi_scsi_io(ccb, xs, blockno, blockcnt)) {
- mfi_put_ccb(ccb);
+ if (mfi_scsi_io(ccb, xs, blockno, blockcnt))
goto stuffup;
- }
break;
case READ_COMMAND:
@@ -1035,10 +1031,8 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
blockno =
(uint64_t)(_3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff));
blockcnt = rw->length ? rw->length : 0x100;
- if (mfi_scsi_io(ccb, xs, blockno, blockcnt)) {
- mfi_put_ccb(ccb);
+ if (mfi_scsi_io(ccb, xs, blockno, blockcnt))
goto stuffup;
- }
break;
case READ_16:
@@ -1046,18 +1040,14 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
rw16 = (struct scsi_rw_16 *)xs->cmd;
blockno = _8btol(rw16->addr);
blockcnt = _4btol(rw16->length);
- if (mfi_scsi_io(ccb, xs, blockno, blockcnt)) {
- mfi_put_ccb(ccb);
+ if (mfi_scsi_io(ccb, xs, blockno, blockcnt))
goto stuffup;
- }
break;
case SYNCHRONIZE_CACHE:
- mfi_put_ccb(ccb); /* we don't need this */
-
mbox[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
- if (mfi_mgmt(sc, MR_DCMD_CTRL_CACHE_FLUSH, MFI_DATA_NONE,
- 0, NULL, mbox))
+ if (mfi_do_mgmt(sc, ccb, MR_DCMD_CTRL_CACHE_FLUSH,
+ MFI_DATA_NONE, 0, NULL, mbox))
goto stuffup;
goto complete;
@@ -1072,10 +1062,8 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
/* FALLTHROUGH */
default:
- if (mfi_scsi_ld(ccb, xs)) {
- mfi_put_ccb(ccb);
+ if (mfi_scsi_ld(ccb, xs))
goto stuffup;
- }
break;
}
@@ -1094,7 +1082,6 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
xs->error = XS_SENSE;
}
- mfi_put_ccb(ccb);
scsi_done(xs);
return;
}
@@ -1180,16 +1167,25 @@ int
mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len,
void *buf, uint8_t *mbox)
{
- struct mfi_ccb *ccb;
+ struct mfi_ccb *ccb;
+ int rv;
+
+ ccb = scsi_io_get(&sc->sc_iopool, 0);
+ rv = mfi_do_mgmt(sc, ccb, opc, dir, len, buf, mbox);
+ scsi_io_put(&sc->sc_iopool, ccb);
+
+ return (rv);
+}
+
+int
+mfi_do_mgmt(struct mfi_softc *sc, struct mfi_ccb *ccb, uint32_t opc,
+ uint32_t dir, uint32_t len, void *buf, uint8_t *mbox)
+{
struct mfi_dcmd_frame *dcmd;
- int rv = 1;
int s;
DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt %#x\n", DEVNAME(sc), opc);
- if ((ccb = mfi_get_ccb(sc)) == NULL)
- return (rv);
-
dcmd = &ccb->ccb_frame->mfr_dcmd;
memset(dcmd->mdf_mbox, 0, MFI_MBOX_SIZE);
dcmd->mdf_header.mfh_cmd = MFI_CMD_DCMD;
@@ -1213,12 +1209,12 @@ mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len,
ccb->ccb_sgl = &dcmd->mdf_sgl;
if (mfi_create_sgl(ccb, BUS_DMA_WAITOK))
- goto done;
+ return (EINVAL);
}
if (cold) {
if (mfi_poll(ccb))
- goto done;
+ return (EIO);
} else {
s = splbio();
mfi_start(sc, ccb);
@@ -1229,14 +1225,10 @@ mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len,
splx(s);
if (ccb->ccb_flags & MFI_CCB_F_ERR)
- goto done;
+ return (EIO);
}
- rv = 0;
-
-done:
- mfi_put_ccb(ccb);
- return (rv);
+ return (0);
}
void
@@ -1351,7 +1343,8 @@ mfi_bio_getitall(struct mfi_softc *sc)
cfg = malloc(sizeof *cfg, M_DEVBUF, M_NOWAIT | M_ZERO);
if (cfg == NULL)
goto done;
- if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg, NULL))
+ if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg,
+ NULL))
goto done;
size = cfg->mfc_size;