Commit 78d0b1a9 authored by Douglas Gilbert's avatar Douglas Gilbert Committed by James Bottomley

SCSI: descriptor sense format, mid-level

   - generalize sense data logic to cope with both fixed and
     descriptor format
   - use KERN_INFO on most printk()s to limit console noise
   - retire mid-level usage of sense_class(), sense_error() and
     sense_valid() macros which are SCSI-1 remnants. Now only
     cpqfcTSinit.c seems to use them
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 57ef63e0
...@@ -268,16 +268,42 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost, ...@@ -268,16 +268,42 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
* *
* Return value: * Return value:
* SUCCESS or FAILED or NEEDS_RETRY * SUCCESS or FAILED or NEEDS_RETRY
*
* Notes:
* When a deferred error is detected the current command has
* not been executed and needs retrying.
**/ **/
static int scsi_check_sense(struct scsi_cmnd *scmd) static int scsi_check_sense(struct scsi_cmnd *scmd)
{ {
if (!SCSI_SENSE_VALID(scmd)) struct scsi_sense_hdr sshdr;
return FAILED;
if (! scsi_command_normalize_sense(scmd, &sshdr))
return FAILED; /* no valid sense data */
if (scsi_sense_is_deferred(&sshdr))
return NEEDS_RETRY;
/*
* Previous logic looked for FILEMARK, EOM or ILI which are
* mainly associated with tapes and returned SUCCESS.
*/
if (sshdr.response_code == 0x70) {
/* fixed format */
if (scmd->sense_buffer[2] & 0xe0) if (scmd->sense_buffer[2] & 0xe0)
return SUCCESS; return SUCCESS;
} else {
/*
* descriptor format: look for "stream commands sense data
* descriptor" (see SSC-3). Assume single sense data
* descriptor. Ignore ILI from SBC-2 READ LONG and WRITE LONG.
*/
if ((sshdr.additional_length > 3) &&
(scmd->sense_buffer[8] == 0x4) &&
(scmd->sense_buffer[11] & 0xe0))
return SUCCESS;
}
switch (scmd->sense_buffer[2] & 0xf) { switch (sshdr.sense_key) {
case NO_SENSE: case NO_SENSE:
return SUCCESS; return SUCCESS;
case RECOVERED_ERROR: case RECOVERED_ERROR:
...@@ -301,19 +327,15 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) ...@@ -301,19 +327,15 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
* if the device is in the process of becoming ready, we * if the device is in the process of becoming ready, we
* should retry. * should retry.
*/ */
if ((scmd->sense_buffer[12] == 0x04) && if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01))
(scmd->sense_buffer[13] == 0x01)) {
return NEEDS_RETRY; return NEEDS_RETRY;
}
/* /*
* if the device is not started, we need to wake * if the device is not started, we need to wake
* the error handler to start the motor * the error handler to start the motor
*/ */
if (scmd->device->allow_restart && if (scmd->device->allow_restart &&
(scmd->sense_buffer[12] == 0x04) && (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
(scmd->sense_buffer[13] == 0x02)) {
return FAILED; return FAILED;
}
return SUCCESS; return SUCCESS;
/* these three are not supported */ /* these three are not supported */
...@@ -1358,7 +1380,8 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) ...@@ -1358,7 +1380,8 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
return SUCCESS; return SUCCESS;
case RESERVATION_CONFLICT: case RESERVATION_CONFLICT:
printk("scsi%d (%d,%d,%d) : reservation conflict\n", printk(KERN_INFO "scsi: reservation conflict: host"
" %d channel %d id %d lun %d\n",
scmd->device->host->host_no, scmd->device->channel, scmd->device->host->host_no, scmd->device->channel,
scmd->device->id, scmd->device->lun); scmd->device->id, scmd->device->lun);
return SUCCESS; /* causes immediate i/o error */ return SUCCESS; /* causes immediate i/o error */
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <scsi/scsi_ioctl.h> #include <scsi/scsi_ioctl.h>
#include <scsi/scsi_request.h> #include <scsi/scsi_request.h>
#include <scsi/sg.h> #include <scsi/sg.h>
#include <scsi/scsi_dbg.h>
#include "scsi_logging.h" #include "scsi_logging.h"
...@@ -94,12 +95,13 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, ...@@ -94,12 +95,13 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
{ {
struct scsi_request *sreq; struct scsi_request *sreq;
int result; int result;
struct scsi_sense_hdr sshdr;
SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd));
sreq = scsi_allocate_request(sdev, GFP_KERNEL); sreq = scsi_allocate_request(sdev, GFP_KERNEL);
if (!sreq) { if (!sreq) {
printk("SCSI internal ioctl failed, no memory\n"); printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -108,17 +110,21 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, ...@@ -108,17 +110,21 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result));
if (driver_byte(sreq->sr_result)) { if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
switch (sreq->sr_sense_buffer[2] & 0xf) { (scsi_request_normalize_sense(sreq, &sshdr))) {
switch (sshdr.sense_key) {
case ILLEGAL_REQUEST: case ILLEGAL_REQUEST:
if (cmd[0] == ALLOW_MEDIUM_REMOVAL) if (cmd[0] == ALLOW_MEDIUM_REMOVAL)
sdev->lockable = 0; sdev->lockable = 0;
else else
printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); printk(KERN_INFO "ioctl_internal_command: "
"ILLEGAL REQUEST asc=0x%x ascq=0x%x\n",
sshdr.asc, sshdr.ascq);
break; break;
case NOT_READY: /* This happens if there is no disc in drive */ case NOT_READY: /* This happens if there is no disc in drive */
if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) { if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) {
printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); printk(KERN_INFO "Device not ready. Make sure"
" there is a disc in the drive.\n");
break; break;
} }
case UNIT_ATTENTION: case UNIT_ATTENTION:
...@@ -128,16 +134,15 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, ...@@ -128,16 +134,15 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
break; break;
} }
default: /* Fall through for non-removable media */ default: /* Fall through for non-removable media */
printk("SCSI error: host %d id %d lun %d return code = %x\n", printk(KERN_INFO "ioctl_internal_command: <%d %d %d "
"%d> return code = %x\n",
sdev->host->host_no, sdev->host->host_no,
sdev->channel,
sdev->id, sdev->id,
sdev->lun, sdev->lun,
sreq->sr_result); sreq->sr_result);
printk("\tSense class %x, sense error %x, extended sense %x\n", scsi_print_req_sense(" ", sreq);
sense_class(sreq->sr_sense_buffer[0]), break;
sense_error(sreq->sr_sense_buffer[0]),
sreq->sr_sense_buffer[2] & 0xf);
} }
} }
...@@ -401,7 +406,8 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) ...@@ -401,7 +406,8 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
case SCSI_IOCTL_SYNC: case SCSI_IOCTL_SYNC:
case SCSI_IOCTL_START_UNIT: case SCSI_IOCTL_START_UNIT:
case SCSI_IOCTL_STOP_UNIT: case SCSI_IOCTL_STOP_UNIT:
printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm); printk(KERN_WARNING "program %s is using a deprecated SCSI "
"ioctl, please convert it to SG_IO\n", current->comm);
break; break;
default: default:
break; break;
......
...@@ -718,7 +718,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, ...@@ -718,7 +718,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
clear_errors = 0; clear_errors = 0;
if (scsi_command_normalize_sense(cmd, &sshdr)) { if (scsi_command_normalize_sense(cmd, &sshdr)) {
/* /*
* SG_IO wants to know about deferred errors * SG_IO wants current and deferred errors
*/ */
int len = 8 + cmd->sense_buffer[7]; int len = 8 + cmd->sense_buffer[7];
...@@ -844,9 +844,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, ...@@ -844,9 +844,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
cmd = scsi_end_request(cmd, 0, this_count, 1); cmd = scsi_end_request(cmd, 0, this_count, 1);
return; return;
case VOLUME_OVERFLOW: case VOLUME_OVERFLOW:
printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ", printk(KERN_INFO "Volume overflow <%d %d %d %d> CDB: ",
cmd->device->host->host_no, (int) cmd->device->channel, cmd->device->host->host_no,
(int) cmd->device->id, (int) cmd->device->lun); (int)cmd->device->channel,
(int)cmd->device->id, (int)cmd->device->lun);
__scsi_print_command(cmd->data_cmnd); __scsi_print_command(cmd->data_cmnd);
scsi_print_sense("", cmd); scsi_print_sense("", cmd);
cmd = scsi_end_request(cmd, 0, block_bytes, 1); cmd = scsi_end_request(cmd, 0, block_bytes, 1);
...@@ -865,8 +866,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, ...@@ -865,8 +866,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
return; return;
} }
if (result) { if (result) {
printk("SCSI error : <%d %d %d %d> return code = 0x%x\n", printk(KERN_INFO "SCSI error : <%d %d %d %d> return code "
cmd->device->host->host_no, "= 0x%x\n", cmd->device->host->host_no,
cmd->device->channel, cmd->device->channel,
cmd->device->id, cmd->device->id,
cmd->device->lun, result); cmd->device->lun, result);
...@@ -1604,13 +1605,16 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) ...@@ -1604,13 +1605,16 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
sreq->sr_data_direction = DMA_NONE; sreq->sr_data_direction = DMA_NONE;
scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) {
((sreq->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION || struct scsi_sense_hdr sshdr;
(sreq->sr_sense_buffer[2] & 0x0f) == NOT_READY) &&
sdev->removable) { if ((scsi_request_normalize_sense(sreq, &sshdr)) &&
((sshdr.sense_key == UNIT_ATTENTION) ||
(sshdr.sense_key == NOT_READY))) {
sdev->changed = 1; sdev->changed = 1;
sreq->sr_result = 0; sreq->sr_result = 0;
} }
}
result = sreq->sr_result; result = sreq->sr_result;
scsi_release_request(sreq); scsi_release_request(sreq);
return result; return result;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include <scsi/scsi_request.h> #include <scsi/scsi_request.h>
#include <scsi/scsi_transport.h> #include <scsi/scsi_transport.h>
#include <scsi/scsi_eh.h>
#include "scsi_priv.h" #include "scsi_priv.h"
#include "scsi_logging.h" #include "scsi_logging.h"
...@@ -325,6 +326,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, ...@@ -325,6 +326,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
int first_inquiry_len, try_inquiry_len, next_inquiry_len; int first_inquiry_len, try_inquiry_len, next_inquiry_len;
int response_len = 0; int response_len = 0;
int pass, count; int pass, count;
struct scsi_sense_hdr sshdr;
*bflags = 0; *bflags = 0;
...@@ -360,18 +362,21 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, ...@@ -360,18 +362,21 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result,
sreq->sr_result)); sreq->sr_result));
if (sreq->sr_result) { if (sreq->sr_result) {
/*
/* not-ready to ready transition or power-on - good */ * not-ready to ready transition [asc/ascq=0x28/0x0]
/* dpg: bogus? INQUIRY never returns UNIT_ATTENTION */ * or power-on, reset [asc/ascq=0x29/0x0], continue.
/* Supposedly, but many buggy devices do so anyway. */ * INQUIRY should not yield UNIT_ATTENTION
* but many buggy devices do so anyway.
*/
if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
(sreq->sr_sense_buffer[2] & 0xf) == scsi_request_normalize_sense(sreq, &sshdr)) {
UNIT_ATTENTION && if ((sshdr.sense_key == UNIT_ATTENTION) &&
(sreq->sr_sense_buffer[12] == 0x28 || ((sshdr.asc == 0x28) ||
sreq->sr_sense_buffer[12] == 0x29) && (sshdr.asc == 0x29)) &&
sreq->sr_sense_buffer[13] == 0) (sshdr.ascq == 0))
continue; continue;
} }
}
break; break;
} }
...@@ -898,6 +903,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, ...@@ -898,6 +903,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
struct scsi_lun *lunp, *lun_data; struct scsi_lun *lunp, *lun_data;
struct scsi_request *sreq; struct scsi_request *sreq;
u8 *data; u8 *data;
struct scsi_sense_hdr sshdr;
/* /*
* Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
...@@ -975,10 +981,13 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, ...@@ -975,10 +981,13 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
" %s (try %d) result 0x%x\n", sreq->sr_result " %s (try %d) result 0x%x\n", sreq->sr_result
? "failed" : "successful", retries, ? "failed" : "successful", retries,
sreq->sr_result)); sreq->sr_result));
if (sreq->sr_result == 0 || if (sreq->sr_result == 0)
sreq->sr_sense_buffer[2] != UNIT_ATTENTION) break;
else if (scsi_request_normalize_sense(sreq, &sshdr)) {
if (sshdr.sense_key != UNIT_ATTENTION)
break; break;
} }
}
if (sreq->sr_result) { if (sreq->sr_result) {
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment