summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2012-08-16 07:17:04 +0000
committerdlg <dlg@openbsd.org>2012-08-16 07:17:04 +0000
commit08cea9bb2f8a41799b8fab875db5ca9189b3027d (patch)
treeb77d7daa357a5b87c32aab1091f7d4f68251d208 /sys
parentstop passing mfi_softc around as a member of the ccb, consistently give it (diff)
downloadwireguard-openbsd-08cea9bb2f8a41799b8fab875db5ca9189b3027d.tar.xz
wireguard-openbsd-08cea9bb2f8a41799b8fab875db5ca9189b3027d.zip
rework mfi_poll so it will do all the completions on a ccb including
calling the done handler. this makes it consistently complete scsi io with all the proper error checking.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/mfi.c92
1 files changed, 45 insertions, 47 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c
index c2ba0bcb7aa..b888853fe94 100644
--- a/sys/dev/ic/mfi.c
+++ b/sys/dev/ic/mfi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfi.c,v 1.134 2012/08/16 06:45:51 dlg Exp $ */
+/* $OpenBSD: mfi.c,v 1.135 2012/08/16 07:17:04 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -78,7 +78,7 @@ int mfi_initialize_firmware(struct mfi_softc *);
int mfi_get_info(struct mfi_softc *);
uint32_t mfi_read(struct mfi_softc *, bus_size_t);
void mfi_write(struct mfi_softc *, bus_size_t, uint32_t);
-int mfi_poll(struct mfi_softc *, struct mfi_ccb *);
+void mfi_poll(struct mfi_softc *, struct mfi_ccb *);
int mfi_create_sgl(struct mfi_softc *, struct mfi_ccb *, int);
/* commands */
@@ -92,6 +92,7 @@ int mfi_mgmt(struct mfi_softc *, uint32_t, uint32_t, uint32_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_softc *, struct mfi_ccb *);
+void mfi_empty_done(struct mfi_softc *, struct mfi_ccb *);
#if NBIO > 0
int mfi_ioctl(struct device *, u_long, caddr_t);
@@ -432,7 +433,7 @@ mfi_initialize_firmware(struct mfi_softc *sc)
struct mfi_ccb *ccb;
struct mfi_init_frame *init;
struct mfi_init_qinfo *qinfo;
- int rv;
+ int rv = 0;
DNPRINTF(MFI_D_MISC, "%s: mfi_initialize_firmware\n", DEVNAME(sc));
@@ -462,13 +463,22 @@ mfi_initialize_firmware(struct mfi_softc *sc)
0, MFIMEM_LEN(sc->sc_pcq),
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- rv = mfi_poll(sc, ccb);
+ ccb->ccb_done = mfi_empty_done;
+ mfi_poll(sc, ccb);
+ if (init->mif_header.mfh_cmd_status != MFI_STAT_OK)
+ rv = 1;
mfi_put_ccb(sc, ccb);
return (rv);
}
+void
+mfi_empty_done(struct mfi_softc *sc, struct mfi_ccb *ccb)
+{
+ /* nop */
+}
+
int
mfi_get_info(struct mfi_softc *sc)
{
@@ -789,7 +799,7 @@ nopcq:
return (1);
}
-int
+void
mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
{
struct mfi_frame_header *hdr;
@@ -803,19 +813,27 @@ mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
mfi_start(sc, ccb);
- while (hdr->mfh_cmd_status == 0xff) {
- delay(1000);
- if (to++ > 5000) /* XXX 5 seconds busywait sucks */
+ for (;;) {
+ bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
+ ccb->ccb_pframe_offset, sc->sc_frames_size,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ if (hdr->mfh_cmd_status != 0xff)
break;
- }
- if (hdr->mfh_cmd_status == 0xff) {
- printf("%s: timeout on ccb %d\n", DEVNAME(sc),
- hdr->mfh_context);
- ccb->ccb_flags |= MFI_CCB_F_ERR;
- rv = 1;
+
+ if (to++ > 5000) {
+ printf("%s: timeout on ccb %d\n", DEVNAME(sc),
+ hdr->mfh_context);
+ ccb->ccb_flags |= MFI_CCB_F_ERR;
+ rv = 1;
+ }
+
+ bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
+ ccb->ccb_pframe_offset, sc->sc_frames_size,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
- if (ccb->ccb_direction != MFI_DATA_NONE) {
+ if (ccb->ccb_len > 0) {
bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
ccb->ccb_dmamap->dm_mapsize,
(ccb->ccb_direction & MFI_DATA_IN) ?
@@ -824,7 +842,7 @@ mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
}
- return (rv);
+ ccb->ccb_done(sc, ccb);
}
int
@@ -1085,27 +1103,10 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
DNPRINTF(MFI_D_CMD, "%s: start io %d\n", DEVNAME(sc), target);
- if (xs->flags & SCSI_POLL) {
- if (mfi_poll(sc, ccb)) {
- /* XXX check for sense in ccb->ccb_sense? */
- printf("%s: mfi_scsi_cmd poll failed\n",
- DEVNAME(sc));
- bzero(&xs->sense, sizeof(xs->sense));
- xs->sense.error_code = SSD_ERRCODE_VALID |
- SSD_ERRCODE_CURRENT;
- xs->sense.flags = SKEY_ILLEGAL_REQUEST;
- xs->sense.add_sense_code = 0x20; /* invalid opcode */
- xs->error = XS_SENSE;
- }
-
- scsi_done(xs);
- return;
- }
-
- mfi_start(sc, ccb);
-
- DNPRINTF(MFI_D_DMA, "%s: mfi_scsi_cmd queued %d\n", DEVNAME(sc),
- ccb->ccb_dmamap->dm_nsegs);
+ if (xs->flags & SCSI_POLL)
+ mfi_poll(sc, ccb);
+ else
+ mfi_start(sc, ccb);
return;
@@ -1243,12 +1244,9 @@ mfi_do_mgmt(struct mfi_softc *sc, struct mfi_ccb *ccb, uint32_t opc,
}
}
- if (cold) {
- if (mfi_poll(sc, ccb)) {
- rv = EIO;
- goto done;
- }
- } else {
+ if (cold)
+ mfi_poll(sc, ccb);
+ else {
s = splbio();
mfi_start(sc, ccb);
@@ -1257,10 +1255,10 @@ mfi_do_mgmt(struct mfi_softc *sc, struct mfi_ccb *ccb, uint32_t opc,
tsleep(ccb, PRIBIO, "mfimgmt", 0);
splx(s);
- if (ccb->ccb_flags & MFI_CCB_F_ERR) {
- rv = EIO;
- goto done;
- }
+ }
+ if (dcmd->mdf_header.mfh_cmd_status != MFI_STAT_OK) {
+ rv = EIO;
+ goto done;
}
if (dir == MFI_DATA_IN)