aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_ioctl.c46
-rw-r--r--drivers/scsi/scsi_lib.c94
-rw-r--r--drivers/scsi/sd.c5
-rw-r--r--drivers/scsi/sr.c2
-rw-r--r--include/scsi/scsi_device.h13
-rw-r--r--include/scsi/scsi_request.h15
6 files changed, 64 insertions, 111 deletions
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index f5bf5c07be91..5f399c9c68ee 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -88,25 +88,21 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
int timeout, int retries)
{
- struct scsi_request *sreq;
int result;
struct scsi_sense_hdr sshdr;
+ char sense[SCSI_SENSE_BUFFERSIZE];
SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd));
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq) {
- printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n");
- return -ENOMEM;
- }
- sreq->sr_data_direction = DMA_NONE;
- scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+ memset(sense, 0, sizeof(*sense));
+ result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0,
+ sense, timeout, retries);
- SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result));
+ SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result));
- if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
- (scsi_request_normalize_sense(sreq, &sshdr))) {
+ if ((driver_byte(result) & DRIVER_SENSE) &&
+ (scsi_normalize_sense(sense, sizeof(*sense), &sshdr))) {
switch (sshdr.sense_key) {
case ILLEGAL_REQUEST:
if (cmd[0] == ALLOW_MEDIUM_REMOVAL)
@@ -125,7 +121,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
case UNIT_ATTENTION:
if (sdev->removable) {
sdev->changed = 1;
- sreq->sr_result = 0; /* This is no longer considered an error */
+ result = 0; /* This is no longer considered an error */
break;
}
default: /* Fall through for non-removable media */
@@ -135,15 +131,13 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
sdev->channel,
sdev->id,
sdev->lun,
- sreq->sr_result);
- scsi_print_req_sense(" ", sreq);
+ result);
+ __scsi_print_sense(" ", sense, sizeof(*sense));
break;
}
}
- result = sreq->sr_result;
SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n"));
- scsi_release_request(sreq);
return result;
}
@@ -208,8 +202,8 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
{
char *buf;
unsigned char cmd[MAX_COMMAND_SIZE];
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
char __user *cmd_in;
- struct scsi_request *sreq;
unsigned char opcode;
unsigned int inlen, outlen, cmdlen;
unsigned int needed, buf_needed;
@@ -321,31 +315,23 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
break;
}
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq) {
- result = -EINTR;
- goto error;
- }
-
- sreq->sr_data_direction = data_direction;
- scsi_wait_req(sreq, cmd, buf, needed, timeout, retries);
-
+ result = scsi_execute_req(sdev, cmd, data_direction, buf, needed,
+ sense, timeout, retries);
+
/*
* If there was an error condition, pass the info back to the user.
*/
- result = sreq->sr_result;
if (result) {
- int sb_len = sizeof(sreq->sr_sense_buffer);
+ int sb_len = sizeof(*sense);
sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
- if (copy_to_user(cmd_in, sreq->sr_sense_buffer, sb_len))
+ if (copy_to_user(cmd_in, sense, sb_len))
result = -EFAULT;
} else {
if (copy_to_user(cmd_in, buf, outlen))
result = -EFAULT;
}
- scsi_release_request(sreq);
error:
kfree(buf);
return result;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 278e0c99b2ae..3f3accd6cd46 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1615,7 +1615,7 @@ void scsi_exit_queue(void)
/**
* __scsi_mode_sense - issue a mode sense, falling back from 10 to
* six bytes if necessary.
- * @sreq: SCSI request to fill in with the MODE_SENSE
+ * @sdev: SCSI device to be queried
* @dbd: set if mode sense will allow block descriptors to be returned
* @modepage: mode page being requested
* @buffer: request buffer (may not be smaller than eight bytes)
@@ -1623,26 +1623,38 @@ void scsi_exit_queue(void)
* @timeout: command timeout
* @retries: number of retries before failing
* @data: returns a structure abstracting the mode header data
+ * @sense: place to put sense data (or NULL if no sense to be collected).
+ * must be SCSI_SENSE_BUFFERSIZE big.
*
* Returns zero if unsuccessful, or the header offset (either 4
* or 8 depending on whether a six or ten byte command was
* issued) if successful.
**/
int
-__scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
+scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
unsigned char *buffer, int len, int timeout, int retries,
- struct scsi_mode_data *data) {
+ struct scsi_mode_data *data, char *sense) {
unsigned char cmd[12];
int use_10_for_ms;
int header_length;
+ int result;
+ char *sense_buffer = NULL;
memset(data, 0, sizeof(*data));
memset(&cmd[0], 0, 12);
cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */
cmd[2] = modepage;
+ if (!sense) {
+ sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+ if (!sense_buffer) {
+ dev_printk(KERN_ERR, &sdev->sdev_gendev, "failed to allocate sense buffer\n");
+ return 0;
+ }
+ sense = sense_buffer;
+ }
retry:
- use_10_for_ms = sreq->sr_device->use_10_for_ms;
+ use_10_for_ms = sdev->use_10_for_ms;
if (use_10_for_ms) {
if (len < 8)
@@ -1660,36 +1672,35 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
header_length = 4;
}
- sreq->sr_cmd_len = 0;
- memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer));
- sreq->sr_data_direction = DMA_FROM_DEVICE;
+ memset(sense, 0, SCSI_SENSE_BUFFERSIZE);
memset(buffer, 0, len);
- scsi_wait_req(sreq, cmd, buffer, len, timeout, retries);
+ result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+ sense, timeout, retries);
/* This code looks awful: what it's doing is making sure an
* ILLEGAL REQUEST sense return identifies the actual command
* byte as the problem. MODE_SENSE commands can return
* ILLEGAL REQUEST if the code page isn't supported */
- if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) &&
- (driver_byte(sreq->sr_result) & DRIVER_SENSE)) {
+ if (use_10_for_ms && !scsi_status_is_good(result) &&
+ (driver_byte(result) & DRIVER_SENSE)) {
struct scsi_sense_hdr sshdr;
- if (scsi_request_normalize_sense(sreq, &sshdr)) {
+ if (scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
if ((sshdr.sense_key == ILLEGAL_REQUEST) &&
(sshdr.asc == 0x20) && (sshdr.ascq == 0)) {
/*
* Invalid command operation code
*/
- sreq->sr_device->use_10_for_ms = 0;
+ sdev->use_10_for_ms = 0;
goto retry;
}
}
}
- if(scsi_status_is_good(sreq->sr_result)) {
+ if(scsi_status_is_good(result)) {
data->header_length = header_length;
if(use_10_for_ms) {
data->length = buffer[0]*256 + buffer[1] + 2;
@@ -1706,73 +1717,34 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
}
}
- return sreq->sr_result;
-}
-EXPORT_SYMBOL(__scsi_mode_sense);
-
-/**
- * scsi_mode_sense - issue a mode sense, falling back from 10 to
- * six bytes if necessary.
- * @sdev: scsi device to send command to.
- * @dbd: set if mode sense will disable block descriptors in the return
- * @modepage: mode page being requested
- * @buffer: request buffer (may not be smaller than eight bytes)
- * @len: length of request buffer.
- * @timeout: command timeout
- * @retries: number of retries before failing
- *
- * Returns zero if unsuccessful, or the header offset (either 4
- * or 8 depending on whether a six or ten byte command was
- * issued) if successful.
- **/
-int
-scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
- unsigned char *buffer, int len, int timeout, int retries,
- struct scsi_mode_data *data)
-{
- struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- int ret;
-
- if (!sreq)
- return -1;
-
- ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len,
- timeout, retries, data);
-
- scsi_release_request(sreq);
-
- return ret;
+ kfree(sense_buffer);
+ return result;
}
EXPORT_SYMBOL(scsi_mode_sense);
int
scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
{
- struct scsi_request *sreq;
char cmd[] = {
TEST_UNIT_READY, 0, 0, 0, 0, 0,
};
+ char sense[SCSI_SENSE_BUFFERSIZE];
int result;
- sreq = scsi_allocate_request(sdev, GFP_KERNEL);
- if (!sreq)
- return -ENOMEM;
-
- sreq->sr_data_direction = DMA_NONE;
- scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+ result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sense,
+ timeout, retries);
- if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) {
+ if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) {
struct scsi_sense_hdr sshdr;
- if ((scsi_request_normalize_sense(sreq, &sshdr)) &&
+ if ((scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE,
+ &sshdr)) &&
((sshdr.sense_key == UNIT_ATTENTION) ||
(sshdr.sense_key == NOT_READY))) {
sdev->changed = 1;
- sreq->sr_result = 0;
+ result = 0;
}
}
- result = sreq->sr_result;
- scsi_release_request(sreq);
return result;
}
EXPORT_SYMBOL(scsi_test_unit_ready);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 0410e1bf109a..15c2039059c9 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1299,8 +1299,9 @@ static inline int
sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage,
unsigned char *buffer, int len, struct scsi_mode_data *data)
{
- return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len,
- SD_TIMEOUT, SD_MAX_RETRIES, data);
+ return scsi_mode_sense(SRpnt->sr_device, dbd, modepage, buffer, len,
+ SD_TIMEOUT, SD_MAX_RETRIES, data,
+ SRpnt->sr_sense_buffer);
}
/*
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 2f259f249522..8cbe6e004187 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -817,7 +817,7 @@ static void get_capabilities(struct scsi_cd *cd)
/* ask for mode page 0x2a */
rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
- SR_TIMEOUT, 3, &data);
+ SR_TIMEOUT, 3, &data, NULL);
if (!scsi_status_is_good(rc)) {
/* failed, drive doesn't have capabilities mode page */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 835af8ecbb7c..9181068883ce 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -8,9 +8,17 @@
struct request_queue;
struct scsi_cmnd;
-struct scsi_mode_data;
struct scsi_lun;
+struct scsi_mode_data {
+ __u32 length;
+ __u16 block_descriptor_length;
+ __u8 medium_type;
+ __u8 device_specific;
+ __u8 header_length;
+ __u8 longlba:1;
+};
+
/*
* sdev state: If you alter this, you also need to alter scsi_sysfs.c
* (for the ascii descriptions) and the state model enforcer:
@@ -228,7 +236,8 @@ extern int scsi_set_medium_removal(struct scsi_device *, char);
extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
unsigned char *buffer, int len, int timeout,
- int retries, struct scsi_mode_data *data);
+ int retries, struct scsi_mode_data *data,
+ char *sense);
extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
int retries);
extern int scsi_device_set_state(struct scsi_device *sdev,
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
index d64903a617c3..f5dfdfec9fea 100644
--- a/include/scsi/scsi_request.h
+++ b/include/scsi/scsi_request.h
@@ -58,19 +58,4 @@ extern int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd,
int data_direction, void *buffer, unsigned bufflen,
unsigned char *sense, int timeout, int retries);
-struct scsi_mode_data {
- __u32 length;
- __u16 block_descriptor_length;
- __u8 medium_type;
- __u8 device_specific;
- __u8 header_length;
- __u8 longlba:1;
-};
-
-extern int __scsi_mode_sense(struct scsi_request *SRpnt, int dbd,
- int modepage, unsigned char *buffer, int len,
- int timeout, int retries,
- struct scsi_mode_data *data);
-
-
#endif /* _SCSI_SCSI_REQUEST_H */