diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2012-08-16 03:50:15 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2012-08-16 03:50:15 +0000 |
commit | 1b68470b18fe61a6b8e926bd995aa474a8628170 (patch) | |
tree | 5f79d8fffe66c8ef2705301f8e535a0def05c7da /sys | |
parent | d190c6fdc4f4ea4cb00d8ab82de6cb7c6d2130d6 (diff) |
rewrite the mfii_mgmt path to be a bit more... symmetrical.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/mfii.c | 286 |
1 files changed, 133 insertions, 153 deletions
diff --git a/sys/dev/pci/mfii.c b/sys/dev/pci/mfii.c index 4808c64e1c4..b88d5b49a3f 100644 --- a/sys/dev/pci/mfii.c +++ b/sys/dev/pci/mfii.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mfii.c,v 1.1 2012/08/14 00:27:51 dlg Exp $ */ +/* $OpenBSD: mfii.c,v 1.2 2012/08/16 03:50:14 dlg Exp $ */ /* * Copyright (c) 2012 David Gwynne <dlg@openbsd.org> @@ -131,8 +131,6 @@ struct mfii_ccb { bus_dmamap_t ccb_dmamap; - union mfi_sgl *ccb_sgl; - /* data for sgl */ void *ccb_data; size_t ccb_len; @@ -240,30 +238,26 @@ void mfii_start(struct mfii_softc *, struct mfii_ccb *); void mfii_done(struct mfii_softc *, struct mfii_ccb *); int mfii_poll(struct mfii_softc *, struct mfii_ccb *); void mfii_poll_done(struct mfii_softc *, struct mfii_ccb *); +int mfii_exec(struct mfii_softc *, struct mfii_ccb *); +void mfii_exec_done(struct mfii_softc *, struct mfii_ccb *); int mfii_my_intr(struct mfii_softc *); int mfii_intr(void *); void mfii_postq(struct mfii_softc *); -void mfii_empty_done(struct mfii_softc *, - struct mfii_ccb *); int mfii_load_ccb(struct mfii_softc *, struct mfii_ccb *, void *, int); +int mfii_load_mfa(struct mfii_softc *, struct mfii_ccb *, + void *, int); int mfii_mfa_poll(struct mfii_softc *, struct mfii_ccb *); -int mfii_mgmt(struct mfii_softc *, u_int32_t, u_int32_t, - u_int32_t, void *, u_int8_t *); -int mfii_do_mgmt(struct mfii_softc *, struct mfii_ccb *, - u_int32_t, u_int32_t, u_int32_t, void *, - u_int8_t *); -void mfii_mgmt_done(struct mfii_softc *, struct mfii_ccb *); +int mfii_mgmt(struct mfii_softc *, struct mfii_ccb *, + u_int32_t, u_int8_t *, void *, size_t, int); int mfii_scsi_cmd_io(struct mfii_softc *, struct scsi_xfer *); int mfii_scsi_cmd_cdb(struct mfii_softc *, struct scsi_xfer *); -int mfii_create_sgl(struct mfii_softc *, struct mfii_ccb *, - int); #define mfii_fw_state(_sc) mfii_read((_sc), MFI_OSP) @@ -541,9 +535,16 @@ mfii_transition_firmware(struct mfii_softc *sc) int mfii_get_info(struct mfii_softc *sc) { - if (mfii_mgmt(sc, MR_DCMD_CTRL_GET_INFO, MFII_DATA_IN, - sizeof(sc->sc_info), &sc->sc_info, NULL)) - return (1); + struct mfii_ccb *ccb; + int rv; + + ccb = scsi_io_get(&sc->sc_iopool, 0); + rv = mfii_mgmt(sc, ccb, MR_DCMD_CTRL_GET_INFO, NULL, + &sc->sc_info, sizeof(sc->sc_info), SCSI_DATA_IN|SCSI_NOSLEEP); + scsi_io_put(&sc->sc_iopool, ccb); + + if (rv != 0) + return (rv); #ifdef MFI_DEBUG for (i = 0; i < sc->sc_info.mci_image_component_count; i++) { @@ -698,9 +699,14 @@ mfii_mfa_poll(struct mfii_softc *sc, struct mfii_ccb *ccb) u_int64_t r; int to = 0, rv = 0; +#ifdef DIAGNOSTIC + if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL) + panic("mfii_mfa_poll called with cookie or done set"); +#endif + hdr->mfh_context = ccb->ccb_smid; hdr->mfh_cmd_status = 0xff; - hdr->mfh_flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; + hdr->mfh_flags |= htole16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE); r = MFII_REQ_MFA(ccb->ccb_request_dva); memcpy(&ccb->ccb_req, &r, sizeof(ccb->ccb_req)); @@ -730,7 +736,14 @@ mfii_mfa_poll(struct mfii_softc *sc, struct mfii_ccb *ccb) delay(1000); } - ccb->ccb_done(sc, ccb); + if (ccb->ccb_len > 0) { + bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, + 0, ccb->ccb_dmamap->dm_mapsize, + (ccb->ccb_direction == MFII_DATA_IN) ? + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); + + bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap); + } return (rv); } @@ -751,7 +764,7 @@ mfii_poll(struct mfii_softc *sc, struct mfii_ccb *ccb) mfii_start(sc, ccb); do { - delay(1); + delay(10); mfii_postq(sc); } while (rv == 1); @@ -770,157 +783,131 @@ mfii_poll_done(struct mfii_softc *sc, struct mfii_ccb *ccb) } int -mfii_mgmt(struct mfii_softc *sc, u_int32_t opc, u_int32_t dir, u_int32_t len, - void *buf, uint8_t *mbox) +mfii_exec(struct mfii_softc *sc, struct mfii_ccb *ccb) { - struct mfii_ccb *ccb; - int rv; + struct mutex m = MUTEX_INITIALIZER(IPL_BIO); - ccb = scsi_io_get(&sc->sc_iopool, 0); - mfii_scrub_ccb(ccb); - rv = mfii_do_mgmt(sc, ccb, opc, dir, len, buf, mbox); - scsi_io_put(&sc->sc_iopool, ccb); +#ifdef DIAGNOSTIC + if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL) + panic("mfii_exec called with cookie or done set"); +#endif - return (rv); + ccb->ccb_cookie = &m; + ccb->ccb_done = mfii_exec_done; + + mtx_enter(&m); + while (ccb->ccb_done != NULL) + msleep(ccb, &m, PRIBIO, "mfiiexec", 0); + mtx_leave(&m); + + return (0); +} + +void +mfii_exec_done(struct mfii_softc *sc, struct mfii_ccb *ccb) +{ + struct mutex *m = ccb->ccb_cookie; + + mtx_enter(m); + ccb->ccb_cookie = NULL; + wakeup_one(ccb); + mtx_leave(m); } int -mfii_do_mgmt(struct mfii_softc *sc, struct mfii_ccb *ccb, u_int32_t opc, - u_int32_t dir, u_int32_t len, void *buf, uint8_t *mbox) +mfii_mgmt(struct mfii_softc *sc, struct mfii_ccb *ccb, + u_int32_t opc, u_int8_t *mbox, void *buf, size_t len, int flags) { - struct mfi_dcmd_frame *dcmd; - int rv = EINVAL; - uint8_t *dma_buf = NULL; - //int s; + struct mfi_dcmd_frame *dcmd = ccb->ccb_request; + struct mfi_frame_header *hdr = &dcmd->mdf_header; + u_int64_t r; + u_int8_t *dma_buf; + int rv = EIO; dma_buf = dma_alloc(len, PR_WAITOK); if (dma_buf == NULL) + return (ENOMEM); + + mfii_scrub_ccb(ccb); + ccb->ccb_data = dma_buf; + ccb->ccb_len = len; + switch (flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { + case SCSI_DATA_IN: + ccb->ccb_direction = MFII_DATA_IN; + hdr->mfh_flags = htole16(MFI_FRAME_DIR_READ); + break; + case SCSI_DATA_OUT: + ccb->ccb_direction = MFII_DATA_OUT; + hdr->mfh_flags = htole16(MFI_FRAME_DIR_WRITE); + bcopy(buf, dma_buf, len); + break; + } + + if (mfii_load_mfa(sc, ccb, &dcmd->mdf_sgl, + ISSET(flags, SCSI_NOSLEEP)) != 0) { + rv = ENOMEM; goto done; + } - dcmd = ccb->ccb_request; - memset(dcmd->mdf_mbox, 0, MFI_MBOX_SIZE); - dcmd->mdf_header.mfh_cmd = MFI_CMD_DCMD; - dcmd->mdf_header.mfh_timeout = 0; + hdr->mfh_cmd = MFI_CMD_DCMD; + hdr->mfh_context = ccb->ccb_smid; + hdr->mfh_data_len = htole32(len); + hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs; dcmd->mdf_opcode = opc; - dcmd->mdf_header.mfh_data_len = htole32(0); - ccb->ccb_direction = dir; - ccb->ccb_cookie = ccb; - ccb->ccb_done = mfii_mgmt_done; - /* handle special opcodes */ - if (mbox) + if (mbox != NULL) memcpy(dcmd->mdf_mbox, mbox, MFI_MBOX_SIZE); - if (dir != MFII_DATA_NONE) { - if (dir == MFII_DATA_OUT) - bcopy(buf, dma_buf, len); - dcmd->mdf_header.mfh_data_len = htole32(len); - ccb->ccb_data = dma_buf; - ccb->ccb_len = len; - ccb->ccb_sgl = &dcmd->mdf_sgl; - - if (mfii_create_sgl(sc, ccb, BUS_DMA_WAITOK)) { - rv = EINVAL; - goto done; - } + 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)); + mfii_exec(sc, ccb); } - if (cold) { - if (mfii_mfa_poll(sc, ccb)) { - rv = EIO; - goto done; - } - } else { - panic("%s !cold", __func__); -#if 0 - s = splbio(); - mfii_start(sc, ccb); - - while (ccb->ccb_cookie != NULL) - tsleep(ccb, PRIBIO, "mfimgmt", 0); - splx(s); + if (hdr->mfh_cmd_status == MFI_STAT_OK) { + rv = 0; - if (ccb->ccb_flags & MFI_CCB_F_ERR) { - rv = EIO; - goto done; - } -#endif + if (ccb->ccb_direction == MFII_DATA_IN) + bcopy(dma_buf, buf, len); } - if (dir == MFII_DATA_IN) - bcopy(dma_buf, buf, len); - - rv = 0; done: - if (dma_buf) - dma_free(dma_buf, len); + dma_free(dma_buf, len); return (rv); } -void -mfii_mgmt_done(struct mfii_softc *sc, struct mfii_ccb *ccb) -{ - struct mfi_frame_header *hdr = ccb->ccb_request; - - if (ccb->ccb_data != NULL) { - bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, - ccb->ccb_dmamap->dm_mapsize, - (ccb->ccb_direction & MFII_DATA_IN) ? - BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); - - bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap); - } - - if (hdr->mfh_cmd_status != MFI_STAT_OK) - ccb->ccb_flags |= MFI_CCB_F_ERR; - - ccb->ccb_cookie = NULL; - - wakeup(ccb); -} - -int -mfii_create_sgl(struct mfii_softc *sc, struct mfii_ccb *ccb, int flags) +int +mfii_load_mfa(struct mfii_softc *sc, struct mfii_ccb *ccb, + void *sglp, int nosleep) { - struct mfi_frame_header *hdr; - bus_dma_segment_t *sgd; - union mfi_sgl *sgl; - int error, i; - - if (ccb->ccb_data == NULL) - return (1); + union mfi_sgl *sgl = sglp; + bus_dmamap_t dmap = ccb->ccb_dmamap; + int error; + int i; - error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap, - ccb->ccb_data, ccb->ccb_len, NULL, flags); - if (error) { - if (error == EFBIG) - printf("more than %d dma segs\n", sc->sc_max_sgl); - else - printf("error %d loading dma map\n", error); - return (1); - } + if (ccb->ccb_len == 0) + return (0); - hdr = ccb->ccb_request; - sgl = ccb->ccb_sgl; - sgd = ccb->ccb_dmamap->dm_segs; - for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) { - sgl->sg32[i].addr = htole32(sgd[i].ds_addr); - sgl->sg32[i].len = htole32(sgd[i].ds_len); - } + error = bus_dmamap_load(sc->sc_dmat, dmap, + ccb->ccb_data, ccb->ccb_len, NULL, + nosleep ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); + if (error) { + printf("%s: error %d loading dmamap\n", DEVNAME(sc), error); + return (1); + } - if (ccb->ccb_direction == MFII_DATA_IN) { - hdr->mfh_flags |= MFI_FRAME_DIR_READ; - bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, - ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); - } else { - hdr->mfh_flags |= MFI_FRAME_DIR_WRITE; - bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, - ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); + for (i = 0; i < dmap->dm_nsegs; i++) { + sgl->sg32[i].addr = htole32(dmap->dm_segs[i].ds_addr); + sgl->sg32[i].len = htole32(dmap->dm_segs[i].ds_len); } - hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs; + bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, + ccb->ccb_direction == MFII_DATA_OUT ? + BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); return (0); } @@ -947,13 +934,16 @@ mfii_done(struct mfii_softc *sc, struct mfii_ccb *ccb) ccb->ccb_request_offset, MFII_REQUEST_SIZE, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - ccb->ccb_done(sc, ccb); -} + if (ccb->ccb_len > 0) { + bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, + 0, ccb->ccb_dmamap->dm_mapsize, + (ccb->ccb_direction == MFII_DATA_IN) ? + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); -void -mfii_empty_done(struct mfii_softc *sc, struct mfii_ccb *ccb) -{ - /* nop */ + bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap); + } + + ccb->ccb_done(sc, ccb); } int @@ -1012,7 +1002,6 @@ mfii_initialise_firmware(struct mfii_softc *sc) bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(m), 0, sizeof(*iiq), BUS_DMASYNC_PREREAD); - ccb->ccb_done = mfii_empty_done; rv = mfii_mfa_poll(sc, ccb); bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(m), @@ -1157,17 +1146,9 @@ void mfii_scsi_cmd_done(struct mfii_softc *sc, struct mfii_ccb *ccb) { struct scsi_xfer *xs = ccb->ccb_cookie; - bus_dmamap_t dmap = ccb->ccb_dmamap; struct mpii_msg_scsi_io *io = ccb->ccb_request; struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1); - if (ccb->ccb_len != 0) { - bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, - ccb->ccb_direction == MFII_DATA_OUT ? - BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); - bus_dmamap_unload(sc->sc_dmat, dmap); - } - switch (ctx->status) { case MFI_STAT_OK: break; @@ -1312,7 +1293,6 @@ mfii_scrub_ccb(struct mfii_ccb *ccb) ccb->ccb_flags = 0; ccb->ccb_done = NULL; ccb->ccb_direction = 0; - ccb->ccb_sgl = NULL; ccb->ccb_data = NULL; ccb->ccb_len = 0; |