summaryrefslogtreecommitdiff
path: root/sys/dev/mfi
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mfi')
-rw-r--r--sys/dev/mfi/mfi.c150
-rw-r--r--sys/dev/mfi/mfireg.h2
2 files changed, 94 insertions, 58 deletions
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index 592aa00e6d1d..2e9f4e7b47eb 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -573,7 +573,7 @@ mfi_release_command(struct mfi_command *cm)
* as 32 bit words. Clear out the first S/G entry too for safety.
*/
hdr = &cm->cm_frame->header;
- if (hdr->sg_count) {
+ if (cm->cm_data != NULL && hdr->sg_count) {
cm->cm_sg->sg32[0].len = 0;
cm->cm_sg->sg32[0].addr = 0;
}
@@ -2096,33 +2096,48 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
context = cm->cm_frame->header.context;
bcopy(ioc->mfi_frame.raw, cm->cm_frame,
- ioc->mfi_sgl_off); /* Linux can do 2 frames ? */
- 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;
+ 2 * MFI_DCMD_FRAME_SIZE); /* this isn't quite right */
+ cm->cm_total_frame_size = (sizeof(union mfi_sgl) * ioc->mfi_sge_count) + ioc->mfi_sgl_off;
+ if (ioc->mfi_sge_count) {
+ cm->cm_sg =
+ (union mfi_sgl *)&cm->cm_frame->bytes[ioc->mfi_sgl_off];
+ }
+ cm->cm_flags = 0;
+ if (cm->cm_frame->header.flags & MFI_FRAME_DATAIN)
+ cm->cm_flags |= MFI_CMD_DATAIN;
+ if (cm->cm_frame->header.flags & MFI_FRAME_DATAOUT)
+ cm->cm_flags |= MFI_CMD_DATAOUT;
+ /* Legacy app shim */
+ if (cm->cm_flags == 0)
+ 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);
- if (cm->cm_data == NULL) {
- device_printf(sc->mfi_dev, "Malloc failed\n");
- goto out;
+ if (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT)) {
+ cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF,
+ M_WAITOK | M_ZERO);
+ if (cm->cm_data == NULL) {
+ device_printf(sc->mfi_dev, "Malloc failed\n");
+ goto out;
+ }
+ } else {
+ cm->cm_data = 0;
}
/* restore header context */
cm->cm_frame->header.context = context;
temp = data;
- for (i = 0; i < ioc->mfi_sge_count; i++) {
- error = copyin(ioc->mfi_sgl[i].iov_base,
- temp,
- ioc->mfi_sgl[i].iov_len);
- if (error != 0) {
- device_printf(sc->mfi_dev,
- "Copy in failed\n");
- goto out;
+ if (cm->cm_flags & MFI_CMD_DATAOUT) {
+ for (i = 0; i < ioc->mfi_sge_count; i++) {
+ error = copyin(ioc->mfi_sgl[i].iov_base,
+ temp,
+ ioc->mfi_sgl[i].iov_len);
+ if (error != 0) {
+ device_printf(sc->mfi_dev,
+ "Copy in failed\n");
+ goto out;
+ }
+ temp = &temp[ioc->mfi_sgl[i].iov_len];
}
- temp = &temp[ioc->mfi_sgl[i].iov_len];
}
if (cm->cm_frame->header.cmd == MFI_CMD_DCMD)
@@ -2146,16 +2161,18 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
mtx_unlock(&sc->mfi_io_lock);
temp = data;
- for (i = 0; i < ioc->mfi_sge_count; i++) {
- error = copyout(temp,
- ioc->mfi_sgl[i].iov_base,
- ioc->mfi_sgl[i].iov_len);
- if (error != 0) {
- device_printf(sc->mfi_dev,
- "Copy out failed\n");
- goto out;
+ if (cm->cm_flags & MFI_CMD_DATAIN) {
+ for (i = 0; i < ioc->mfi_sge_count; i++) {
+ error = copyout(temp,
+ ioc->mfi_sgl[i].iov_base,
+ ioc->mfi_sgl[i].iov_len);
+ if (error != 0) {
+ device_printf(sc->mfi_dev,
+ "Copy out failed\n");
+ goto out;
+ }
+ temp = &temp[ioc->mfi_sgl[i].iov_len];
}
- temp = &temp[ioc->mfi_sgl[i].iov_len];
}
if (ioc->mfi_sense_len) {
@@ -2282,31 +2299,46 @@ mfi_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_threa
context = cm->cm_frame->header.context;
bcopy(l_ioc.lioc_frame.raw, cm->cm_frame,
- l_ioc.lioc_sgl_off); /* Linux can do 2 frames ? */
- 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;
+ 2 * MFI_DCMD_FRAME_SIZE); /* this isn't quite right */
+ cm->cm_total_frame_size = (sizeof(union mfi_sgl) * l_ioc.lioc_sge_count) + l_ioc.lioc_sgl_off;
+ if (l_ioc.lioc_sge_count)
+ cm->cm_sg =
+ (union mfi_sgl *)&cm->cm_frame->bytes[l_ioc.lioc_sgl_off];
+ cm->cm_flags = 0;
+ if (cm->cm_frame->header.flags & MFI_FRAME_DATAIN)
+ cm->cm_flags |= MFI_CMD_DATAIN;
+ if (cm->cm_frame->header.flags & MFI_FRAME_DATAOUT)
+ cm->cm_flags |= 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);
+ if (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT)) {
+ cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF,
+ M_WAITOK | M_ZERO);
+ if (cm->cm_data == NULL) {
+ device_printf(sc->mfi_dev, "Malloc failed\n");
+ goto out;
+ }
+ } else {
+ cm->cm_data = 0;
+ }
/* restore header context */
cm->cm_frame->header.context = context;
temp = data;
- for (i = 0; i < l_ioc.lioc_sge_count; i++) {
- temp_convert =
- (void *)(uintptr_t)l_ioc.lioc_sgl[i].iov_base;
- error = copyin(temp_convert,
- temp,
- l_ioc.lioc_sgl[i].iov_len);
- if (error != 0) {
- device_printf(sc->mfi_dev,
- "Copy in failed\n");
- goto out;
+ if (cm->cm_flags & MFI_CMD_DATAOUT) {
+ for (i = 0; i < l_ioc.lioc_sge_count; i++) {
+ temp_convert =
+ (void *)(uintptr_t)l_ioc.lioc_sgl[i].iov_base;
+ error = copyin(temp_convert,
+ temp,
+ l_ioc.lioc_sgl[i].iov_len);
+ if (error != 0) {
+ device_printf(sc->mfi_dev,
+ "Copy in failed\n");
+ goto out;
+ }
+ temp = &temp[l_ioc.lioc_sgl[i].iov_len];
}
- temp = &temp[l_ioc.lioc_sgl[i].iov_len];
}
if (cm->cm_frame->header.cmd == MFI_CMD_DCMD)
@@ -2330,18 +2362,20 @@ mfi_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_threa
mtx_unlock(&sc->mfi_io_lock);
temp = data;
- for (i = 0; i < l_ioc.lioc_sge_count; i++) {
- temp_convert =
- (void *)(uintptr_t)l_ioc.lioc_sgl[i].iov_base;
- error = copyout(temp,
- temp_convert,
- l_ioc.lioc_sgl[i].iov_len);
- if (error != 0) {
- device_printf(sc->mfi_dev,
- "Copy out failed\n");
- goto out;
+ if (cm->cm_flags & MFI_CMD_DATAIN) {
+ for (i = 0; i < l_ioc.lioc_sge_count; i++) {
+ temp_convert =
+ (void *)(uintptr_t)l_ioc.lioc_sgl[i].iov_base;
+ error = copyout(temp,
+ temp_convert,
+ l_ioc.lioc_sgl[i].iov_len);
+ if (error != 0) {
+ device_printf(sc->mfi_dev,
+ "Copy out failed\n");
+ goto out;
+ }
+ temp = &temp[l_ioc.lioc_sgl[i].iov_len];
}
- temp = &temp[l_ioc.lioc_sgl[i].iov_len];
}
if (l_ioc.lioc_sense_len) {
diff --git a/sys/dev/mfi/mfireg.h b/sys/dev/mfi/mfireg.h
index 2bd8a51d3a9a..c54602664003 100644
--- a/sys/dev/mfi/mfireg.h
+++ b/sys/dev/mfi/mfireg.h
@@ -352,6 +352,8 @@ struct mfi_frame_header {
uint32_t context;
uint32_t pad0;
uint16_t flags;
+#define MFI_FRAME_DATAOUT 0x08
+#define MFI_FRAME_DATAIN 0x10
uint16_t timeout;
uint32_t data_len;
} __packed;