summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2012-08-16 07:53:22 +0000
committerdlg <dlg@openbsd.org>2012-08-16 07:53:22 +0000
commite519319e9a80c2e94bb44aefa2f3815b6b298352 (patch)
treefa1868fe9741d40e98344efb6beeb575ddf54ee5 /sys
parentrework mfi_poll so it will do all the completions on a ccb including (diff)
downloadwireguard-openbsd-e519319e9a80c2e94bb44aefa2f3815b6b298352.tar.xz
wireguard-openbsd-e519319e9a80c2e94bb44aefa2f3815b6b298352.zip
fix mfi_poll by having it do delays between loops, and breaking on
timeouts. how embarrassment. implement mfi_exec for doing sync executions of commands in process contexts and cut mfi_mgmt over to it.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/mfi.c82
1 files changed, 47 insertions, 35 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c
index b888853fe94..51b20fd526a 100644
--- a/sys/dev/ic/mfi.c
+++ b/sys/dev/ic/mfi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfi.c,v 1.135 2012/08/16 07:17:04 dlg Exp $ */
+/* $OpenBSD: mfi.c,v 1.136 2012/08/16 07:53:22 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -79,6 +79,8 @@ 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);
void mfi_poll(struct mfi_softc *, struct mfi_ccb *);
+void mfi_exec(struct mfi_softc *, struct mfi_ccb *);
+void mfi_exec_done(struct mfi_softc *, struct mfi_ccb *);
int mfi_create_sgl(struct mfi_softc *, struct mfi_ccb *, int);
/* commands */
@@ -91,7 +93,6 @@ 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_softc *, struct mfi_ccb *);
void mfi_empty_done(struct mfi_softc *, struct mfi_ccb *);
#if NBIO > 0
@@ -802,8 +803,8 @@ nopcq:
void
mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
{
- struct mfi_frame_header *hdr;
- int to = 0, rv = 0;
+ struct mfi_frame_header *hdr;
+ int to = 0;
DNPRINTF(MFI_D_CMD, "%s: mfi_poll\n", DEVNAME(sc));
@@ -814,6 +815,8 @@ mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
mfi_start(sc, ccb);
for (;;) {
+ delay(1000);
+
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);
@@ -825,7 +828,7 @@ mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
printf("%s: timeout on ccb %d\n", DEVNAME(sc),
hdr->mfh_context);
ccb->ccb_flags |= MFI_CCB_F_ERR;
- rv = 1;
+ break;
}
bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
@@ -845,6 +848,38 @@ mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
ccb->ccb_done(sc, ccb);
}
+void
+mfi_exec(struct mfi_softc *sc, struct mfi_ccb *ccb)
+{
+ struct mutex m = MUTEX_INITIALIZER(IPL_BIO);
+
+#ifdef DIAGNOSTIC
+ if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL)
+ panic("mfi_exec called with cookie or done set");
+#endif
+
+ ccb->ccb_cookie = &m;
+ ccb->ccb_done = mfi_exec_done;
+
+ mfi_start(sc, ccb);
+
+ mtx_enter(&m);
+ while (ccb->ccb_cookie != NULL)
+ msleep(ccb, &m, PRIBIO, "mfiexec", 0);
+ mtx_leave(&m);
+}
+
+void
+mfi_exec_done(struct mfi_softc *sc, struct mfi_ccb *ccb)
+{
+ struct mutex *m = ccb->ccb_cookie;
+
+ mtx_enter(m);
+ ccb->ccb_cookie = NULL;
+ wakeup_one(ccb);
+ mtx_leave(m);
+}
+
int
mfi_intr(void *arg)
{
@@ -1204,9 +1239,9 @@ 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 s, rv = EINVAL;
- uint8_t *dma_buf = NULL;
+ struct mfi_dcmd_frame *dcmd;
+ uint8_t *dma_buf = NULL;
+ int rv = EINVAL;
DNPRINTF(MFI_D_MISC, "%s: mfi_do_mgmt %#x\n", DEVNAME(sc), opc);
@@ -1222,7 +1257,6 @@ mfi_do_mgmt(struct mfi_softc *sc, struct mfi_ccb *ccb, uint32_t opc,
dcmd->mdf_opcode = opc;
dcmd->mdf_header.mfh_data_len = 0;
ccb->ccb_direction = dir;
- ccb->ccb_done = mfi_mgmt_done;
ccb->ccb_frame_size = MFI_DCMD_FRAME_SIZE;
@@ -1244,18 +1278,12 @@ mfi_do_mgmt(struct mfi_softc *sc, struct mfi_ccb *ccb, uint32_t opc,
}
}
- if (cold)
+ if (cold) {
+ ccb->ccb_done = mfi_empty_done;
mfi_poll(sc, ccb);
- else {
- s = splbio();
- mfi_start(sc, ccb);
+ } else
+ mfi_exec(sc, ccb);
- DNPRINTF(MFI_D_MISC, "%s: mfi_do_mgmt sleeping\n", DEVNAME(sc));
- while (ccb->ccb_state != MFI_CCB_DONE)
- tsleep(ccb, PRIBIO, "mfimgmt", 0);
- splx(s);
-
- }
if (dcmd->mdf_header.mfh_cmd_status != MFI_STAT_OK) {
rv = EIO;
goto done;
@@ -1272,22 +1300,6 @@ done:
return (rv);
}
-void
-mfi_mgmt_done(struct mfi_softc *sc, struct mfi_ccb *ccb)
-{
- struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
-
- DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done %#x %#x\n",
- DEVNAME(sc), ccb, ccb->ccb_frame);
-
- if (hdr->mfh_cmd_status != MFI_STAT_OK)
- ccb->ccb_flags |= MFI_CCB_F_ERR;
-
- ccb->ccb_state = MFI_CCB_DONE;
-
- wakeup(ccb);
-}
-
int
mfi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag)
{