summaryrefslogtreecommitdiffstats
path: root/sys/dev/amr/amr.c
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2005-03-04 06:11:00 +0000
committerscottl <scottl@FreeBSD.org>2005-03-04 06:11:00 +0000
commitb042141f6f3005d8bf076b8fb71894486766efd7 (patch)
treecf23aeedb1d99fbfe06a3cda4e0f176ae2f8190a /sys/dev/amr/amr.c
parent0dda2674af70acfb29e67fc9b8bbfe2e370d8482 (diff)
downloadFreeBSD-src-b042141f6f3005d8bf076b8fb71894486766efd7.zip
FreeBSD-src-b042141f6f3005d8bf076b8fb71894486766efd7.tar.gz
Fix the ioctl path by ensuring that amr_start1() gets called for commands
with no associated data. Also revert previous changes that allocate off of the stack instead of using malloc, as it's not needed. Many thanks to LSI for investigating and fixing these problems. Submitted by: rajeshpr @ lsil . com
Diffstat (limited to 'sys/dev/amr/amr.c')
-rw-r--r--sys/dev/amr/amr.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index 72dd89f..1600020 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -417,6 +417,7 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
unsigned char *au_cmd;
int *au_statusp, au_direction;
int error;
+ struct amr_passthrough *ap; /* 60 bytes */
debug_called(1);
@@ -462,6 +463,7 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
error = 0;
dp = NULL;
ac = NULL;
+ ap = NULL;
/* Logical Drive not supported by the driver */
if (au_cmd[0] == 0xa4 && au_cmd[1] == 0x1c)
@@ -472,6 +474,9 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
if ((dp = malloc(au_length, M_DEVBUF, M_WAITOK)) == NULL)
return(ENOMEM);
+ if ((ap = malloc(sizeof(struct amr_passthrough ), M_DEVBUF, M_WAITOK)) == NULL)
+ return(ENOMEM);
+
if ((error = copyin(au_buffer, dp, au_length)) != 0) {
free(dp, M_DEVBUF);
return (error);
@@ -487,27 +492,26 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
/* handle SCSI passthrough command */
if (au_cmd[0] == AMR_CMD_PASS) {
- struct amr_passthrough ap; /* 60 bytes */
int len;
/* copy cdb */
len = au_cmd[2];
- ap.ap_cdb_length = len;
- bcopy(au_cmd + 3, ap.ap_cdb, len);
+ ap->ap_cdb_length = len;
+ bcopy(au_cmd + 3, ap->ap_cdb, len);
/* build passthrough */
- ap.ap_timeout = au_cmd[len + 3] & 0x07;
- ap.ap_ars = (au_cmd[len + 3] & 0x08) ? 1 : 0;
- ap.ap_islogical = (au_cmd[len + 3] & 0x80) ? 1 : 0;
- ap.ap_logical_drive_no = au_cmd[len + 4];
- ap.ap_channel = au_cmd[len + 5];
- ap.ap_scsi_id = au_cmd[len + 6];
- ap.ap_request_sense_length = 14;
- ap.ap_data_transfer_length = au_length;
+ ap->ap_timeout = au_cmd[len + 3] & 0x07;
+ ap->ap_ars = (au_cmd[len + 3] & 0x08) ? 1 : 0;
+ ap->ap_islogical = (au_cmd[len + 3] & 0x80) ? 1 : 0;
+ ap->ap_logical_drive_no = au_cmd[len + 4];
+ ap->ap_channel = au_cmd[len + 5];
+ ap->ap_scsi_id = au_cmd[len + 6];
+ ap->ap_request_sense_length = 14;
+ ap->ap_data_transfer_length = au_length;
/* XXX what about the request-sense area? does the caller want it? */
/* build command */
- ac->ac_data = &ap;
+ ac->ac_data = ap;
ac->ac_length = sizeof(struct amr_passthrough);
ac->ac_flags |= AMR_CMD_DATAOUT;
ac->ac_ccb_data = dp;
@@ -560,6 +564,7 @@ out:
* objects have been allocated.
*/
free(dp, M_DEVBUF);
+ free(ap, M_DEVBUF);
amr_releasecmd(ac);
mtx_unlock(&sc->amr_io_lock);
return(error);
@@ -1266,7 +1271,6 @@ amr_mapcmd(struct amr_command *ac)
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
}
} else {
-
if (bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_dmamap, ac->ac_data,
ac->ac_length, amr_setup_dmamap, ac, BUS_DMA_NOWAIT) != 0){
return (ENOMEM);
@@ -1276,8 +1280,11 @@ amr_mapcmd(struct amr_command *ac)
0) == EINPROGRESS) {
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
}
- }
- }
+ }
+ } else if ((ac->ac_flags & AMR_CMD_MAPPED) == 0) {
+ amr_start1(sc, ac);
+ }
+
return (0);
}
@@ -1309,9 +1316,6 @@ amr_unmapcmd(struct amr_command *ac)
bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_ccb_dmamap);
- debug(3, "slot %d %d segments at 0x%x, passthrough at 0x%x\n",
- ac->ac_slot, aep->ap_no_sg_elements, aep->ap_data_transfer_address,
- ac->ac_dataphys);
}
ac->ac_flags &= ~AMR_CMD_MAPPED;
}
OpenPOWER on IntegriCloud