diff options
author | ambrisko <ambrisko@FreeBSD.org> | 2007-06-04 16:39:22 +0000 |
---|---|---|
committer | ambrisko <ambrisko@FreeBSD.org> | 2007-06-04 16:39:22 +0000 |
commit | 7261dfb6565a4be5ae3898d377820496ee90bfe3 (patch) | |
tree | f3672f1ac2d63131707571540fee279fd099d9e2 /sys | |
parent | 2f12bfb53bf6e3f5bcca552f363c6b8e040a3d84 (diff) | |
download | FreeBSD-src-7261dfb6565a4be5ae3898d377820496ee90bfe3.zip FreeBSD-src-7261dfb6565a4be5ae3898d377820496ee90bfe3.tar.gz |
Add in a couple of things:
- In the ioctl path let command get queued up and return
when complete _without_ blocking the driving waiting for
the response. This way the driver doesn't "lock up" for
~30s during a flash command. Submitted by scottl.
- Add a guard so that if a DCMD of 0 is sent down the ioctl
path don't send it to the controller. Return with a
status of OK. This is a little strange since MegaCli
doesn't seem to like something and will issue some DCMD
of 0. This doesn't happen under Linux. So the emulation
needs to be improved but I'm not sure what. Another strange
thing is that when a DCMD of 0 gets issued under i386 the
controller returns OK but in amd64 the context is messed
up.
- Add a guard so the context has to be with-in the legal
limit so we get a reasonable error assertion versus random
panic.
It's going to be a challenge to figure out why MegaCli is not totally
happy and then sends some bogus commands. This means that flashing
firmware via the Linux tool won't work since it generates a DCMD of
0 when it should be opening the firmware for a flash update. Without
this problem flashing works fine. This means there is no publicly
available tool to upgrade the RAID firmware under FreeBSD right now.
I plan to MFC all of the mfi changes to 6.X shortly. This might not
include the SCSI pass-through changes.
Submitted by: scottl
Reviewed by: scottl
MFC after: 3 days
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/mfi/mfi.c | 51 | ||||
-rw-r--r-- | sys/dev/mfi/mfivar.h | 1 |
2 files changed, 33 insertions, 19 deletions
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c index 7bc7e41..583ecad 100644 --- a/sys/dev/mfi/mfi.c +++ b/sys/dev/mfi/mfi.c @@ -679,9 +679,21 @@ mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm) mtx_assert(&sc->mfi_io_lock, MA_OWNED); cm->cm_complete = NULL; + + /* + * MegaCli can issue a DCMD of 0. In this case do nothing + * and return 0 to it as status + */ + if (cm->cm_frame->dcmd.opcode == 0) { + cm->cm_frame->header.cmd_status = MFI_STAT_OK; + cm->cm_error = 0; + return (cm->cm_error); + } mfi_enqueue_ready(cm); mfi_startio(sc); - return (msleep(cm, &sc->mfi_io_lock, PRIBIO, "mfiwait", 0)); + if ((cm->cm_flags & MFI_CMD_COMPLETED) == 0) + msleep(cm, &sc->mfi_io_lock, PRIBIO, "mfiwait", 0); + return (cm->cm_error); } void @@ -779,9 +791,12 @@ mfi_intr(void *arg) mtx_lock(&sc->mfi_io_lock); while (ci != pi) { context = sc->mfi_comms->hw_reply_q[ci]; - cm = &sc->mfi_commands[context]; - mfi_remove_busy(cm); - mfi_complete(sc, cm); + if (context < sc->mfi_max_fw_cmds) { + cm = &sc->mfi_commands[context]; + mfi_remove_busy(cm); + cm->cm_error = 0; + mfi_complete(sc, cm); + } if (++ci == (sc->mfi_max_fw_cmds + 1)) { ci = 0; } @@ -1537,14 +1552,18 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) struct mfi_softc *sc; int i, dir; - if (error) - return; - cm = (struct mfi_command *)arg; sc = cm->cm_sc; hdr = &cm->cm_frame->header; sgl = cm->cm_sg; + if (error) { + printf("error %d in callback\n", error); + cm->cm_error = error; + mfi_complete(sc, cm); + return; + } + if ((sc->mfi_flags & MFI_FLAGS_SG64) == 0) { for (i = 0; i < nsegs; i++) { sgl->sg32[i].addr = segs[i].ds_addr; @@ -1656,6 +1675,8 @@ mfi_complete(struct mfi_softc *sc, struct mfi_command *cm) cm->cm_flags &= ~MFI_CMD_MAPPED; } + cm->cm_flags |= MFI_CMD_COMPLETED; + if (cm->cm_complete != NULL) cm->cm_complete(cm); else @@ -1846,8 +1867,7 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) cm->cm_total_frame_size = ioc->mfi_sgl_off; cm->cm_sg = (union mfi_sgl *)&cm->cm_frame->bytes[ioc->mfi_sgl_off]; - cm->cm_flags = MFI_CMD_DATAIN | MFI_CMD_DATAOUT - | MFI_CMD_POLLED; + cm->cm_flags = MFI_CMD_DATAIN | MFI_CMD_DATAOUT; cm->cm_len = cm->cm_frame->header.data_len; cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF, M_WAITOK | M_ZERO); @@ -1873,16 +1893,13 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) } mtx_lock(&sc->mfi_io_lock); - if ((error = mfi_mapcmd(sc, cm)) != 0) { + if ((error = mfi_wait_command(sc, cm)) != 0) { device_printf(sc->mfi_dev, "Controller polled failed\n"); mtx_unlock(&sc->mfi_io_lock); goto out; } - bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap); mtx_unlock(&sc->mfi_io_lock); temp = data; @@ -2034,8 +2051,7 @@ mfi_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_threa cm->cm_total_frame_size = l_ioc.lioc_sgl_off; cm->cm_sg = (union mfi_sgl *)&cm->cm_frame->bytes[l_ioc.lioc_sgl_off]; - cm->cm_flags = MFI_CMD_DATAIN | MFI_CMD_DATAOUT - | MFI_CMD_POLLED; + cm->cm_flags = MFI_CMD_DATAIN | MFI_CMD_DATAOUT; cm->cm_len = cm->cm_frame->header.data_len; cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF, M_WAITOK | M_ZERO); @@ -2059,16 +2075,13 @@ mfi_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_threa } mtx_lock(&sc->mfi_io_lock); - if ((error = mfi_mapcmd(sc, cm)) != 0) { + if ((error = mfi_wait_command(sc, cm)) != 0) { device_printf(sc->mfi_dev, "Controller polled failed\n"); mtx_unlock(&sc->mfi_io_lock); goto out; } - bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap); mtx_unlock(&sc->mfi_io_lock); temp = data; diff --git a/sys/dev/mfi/mfivar.h b/sys/dev/mfi/mfivar.h index 1230033..874ae1f 100644 --- a/sys/dev/mfi/mfivar.h +++ b/sys/dev/mfi/mfivar.h @@ -74,6 +74,7 @@ struct mfi_command { void (* cm_complete)(struct mfi_command *cm); void *cm_private; int cm_index; + int cm_error; }; struct mfi_disk { |