summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJonathan Matthew <jmatthew@cvs.openbsd.org>2018-05-18 05:11:54 +0000
committerJonathan Matthew <jmatthew@cvs.openbsd.org>2018-05-18 05:11:54 +0000
commit570d5e75bc836a4c99272ab9fdba1749fc6ae922 (patch)
treed4e8cac7b1094770bbc873e9b7ce8f6282f70a1d /sys/dev
parentb4203f13b690259739b8550c07e9494558de452e (diff)
Use passthrough IO rather than MFA for management commands.
Investigation by Naoki Fukaumi determined that this is necessary on some controllers and works on all of them. Tested on SAS2208, SAS3008, SAS3108, SAS3508. ok dlg@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/mfii.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/sys/dev/pci/mfii.c b/sys/dev/pci/mfii.c
index 1f31bacd71f..0dcd739b608 100644
--- a/sys/dev/pci/mfii.c
+++ b/sys/dev/pci/mfii.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfii.c,v 1.50 2018/03/16 05:12:37 jmatthew Exp $ */
+/* $OpenBSD: mfii.c,v 1.51 2018/05/18 05:11:53 jmatthew Exp $ */
/*
* Copyright (c) 2012 David Gwynne <dlg@openbsd.org>
@@ -373,6 +373,7 @@ int mfii_mfa_poll(struct mfii_softc *, struct mfii_ccb *);
int mfii_mgmt(struct mfii_softc *, struct mfii_ccb *,
u_int32_t, const union mfi_mbox *,
void *, size_t, int);
+void mfii_empty_done(struct mfii_softc *, struct mfii_ccb *);
int mfii_scsi_cmd_io(struct mfii_softc *,
struct scsi_xfer *);
@@ -1444,6 +1445,8 @@ mfii_exec(struct mfii_softc *sc, struct mfii_ccb *ccb)
ccb->ccb_cookie = &m;
ccb->ccb_done = mfii_exec_done;
+ mfii_start(sc, ccb);
+
mtx_enter(&m);
while (ccb->ccb_cookie != NULL)
msleep(ccb, &m, PRIBIO, "mfiiexec", 0);
@@ -1468,9 +1471,11 @@ mfii_mgmt(struct mfii_softc *sc, struct mfii_ccb *ccb,
u_int32_t opc, const union mfi_mbox *mbox, void *buf, size_t len,
int flags)
{
- struct mfi_dcmd_frame *dcmd = ccb->ccb_request;
- struct mfi_frame_header *hdr = &dcmd->mdf_header;
- u_int64_t r;
+ struct mpii_msg_scsi_io *io = ccb->ccb_request;
+ struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
+ struct mfii_sge *sge = (struct mfii_sge *)(ctx + 1);
+ struct mfi_dcmd_frame *dcmd = ccb->ccb_mfi;
+ struct mfi_frame_header *hdr = &dcmd->mdf_header;
u_int8_t *dma_buf;
int rv = EIO;
@@ -1509,13 +1514,22 @@ mfii_mgmt(struct mfii_softc *sc, struct mfii_ccb *ccb,
if (mbox != NULL)
memcpy(&dcmd->mdf_mbox, mbox, sizeof(dcmd->mdf_mbox));
- if (ISSET(flags, SCSI_NOSLEEP))
- mfii_mfa_poll(sc, ccb);
- else {
- r = MFII_REQ_MFA(ccb->ccb_request_dva);
- memcpy(&ccb->ccb_req, &r, sizeof(ccb->ccb_req));
+ io->function = MFII_FUNCTION_PASSTHRU_IO;
+ io->sgl_offset0 = ((u_int8_t *)sge - (u_int8_t *)io) / 4;
+ io->chain_offset = ((u_int8_t *)sge - (u_int8_t *)io) / 16;
+
+ htolem64(&sge->sg_addr, ccb->ccb_mfi_dva);
+ htolem32(&sge->sg_len, MFI_FRAME_SIZE);
+ sge->sg_flags = MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA;
+
+ ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
+ ccb->ccb_req.smid = letoh16(ccb->ccb_smid);
+
+ if (ISSET(flags, SCSI_NOSLEEP)) {
+ ccb->ccb_done = mfii_empty_done;
+ mfii_poll(sc, ccb);
+ } else
mfii_exec(sc, ccb);
- }
if (hdr->mfh_cmd_status == MFI_STAT_OK) {
rv = 0;
@@ -1530,6 +1544,12 @@ done:
return (rv);
}
+void
+mfii_empty_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
+{
+ return;
+}
+
int
mfii_load_mfa(struct mfii_softc *sc, struct mfii_ccb *ccb,
void *sglp, int nosleep)