|
@@ -875,16 +875,24 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
|
|
* (the normal case for most drivers), we don't need
|
|
* (the normal case for most drivers), we don't need
|
|
* the logic to deal with cleaning up afterwards.
|
|
* the logic to deal with cleaning up afterwards.
|
|
*
|
|
*
|
|
- * We must do one of several things here:
|
|
|
|
- *
|
|
|
|
- * a) Call scsi_end_request. This will finish off the
|
|
|
|
- * specified number of sectors. If we are done, the
|
|
|
|
- * command block will be released, and the queue
|
|
|
|
- * function will be goosed. If we are not done, then
|
|
|
|
- * scsi_end_request will directly goose the queue.
|
|
|
|
- *
|
|
|
|
- * b) We can just use scsi_requeue_command() here. This would
|
|
|
|
- * be used if we just wanted to retry, for example.
|
|
|
|
|
|
+ * We must call scsi_end_request(). This will finish off
|
|
|
|
+ * the specified number of sectors. If we are done, the
|
|
|
|
+ * command block will be released and the queue function
|
|
|
|
+ * will be goosed. If we are not done then we have to
|
|
|
|
+ * figure out what to do next:
|
|
|
|
+ *
|
|
|
|
+ * a) We can call scsi_requeue_command(). The request
|
|
|
|
+ * will be unprepared and put back on the queue. Then
|
|
|
|
+ * a new command will be created for it. This should
|
|
|
|
+ * be used if we made forward progress, or if we want
|
|
|
|
+ * to switch from READ(10) to READ(6) for example.
|
|
|
|
+ *
|
|
|
|
+ * b) We can call scsi_queue_insert(). The request will
|
|
|
|
+ * be put back on the queue and retried using the same
|
|
|
|
+ * command as before, possibly after a delay.
|
|
|
|
+ *
|
|
|
|
+ * c) We can call blk_end_request() with -EIO to fail
|
|
|
|
+ * the remainder of the request.
|
|
*/
|
|
*/
|
|
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|
{
|
|
{
|
|
@@ -896,6 +904,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|
struct scsi_sense_hdr sshdr;
|
|
struct scsi_sense_hdr sshdr;
|
|
int sense_valid = 0;
|
|
int sense_valid = 0;
|
|
int sense_deferred = 0;
|
|
int sense_deferred = 0;
|
|
|
|
+ enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
|
|
|
|
+ ACTION_DELAYED_RETRY} action;
|
|
|
|
+ char *description = NULL;
|
|
|
|
|
|
if (result) {
|
|
if (result) {
|
|
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
|
|
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
|
|
@@ -947,10 +958,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|
return;
|
|
return;
|
|
this_count = blk_rq_bytes(req);
|
|
this_count = blk_rq_bytes(req);
|
|
|
|
|
|
- /* good_bytes = 0, or (inclusive) there were leftovers and
|
|
|
|
- * result = 0, so scsi_end_request couldn't retry.
|
|
|
|
- */
|
|
|
|
- if (sense_valid && !sense_deferred) {
|
|
|
|
|
|
+ if (host_byte(result) == DID_RESET) {
|
|
|
|
+ /* Third party bus reset or reset for error recovery
|
|
|
|
+ * reasons. Just retry the command and see what
|
|
|
|
+ * happens.
|
|
|
|
+ */
|
|
|
|
+ action = ACTION_RETRY;
|
|
|
|
+ } else if (sense_valid && !sense_deferred) {
|
|
switch (sshdr.sense_key) {
|
|
switch (sshdr.sense_key) {
|
|
case UNIT_ATTENTION:
|
|
case UNIT_ATTENTION:
|
|
if (cmd->device->removable) {
|
|
if (cmd->device->removable) {
|
|
@@ -958,16 +972,15 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|
* and quietly refuse further access.
|
|
* and quietly refuse further access.
|
|
*/
|
|
*/
|
|
cmd->device->changed = 1;
|
|
cmd->device->changed = 1;
|
|
- scsi_end_request(cmd, -EIO, this_count, 1);
|
|
|
|
- return;
|
|
|
|
|
|
+ description = "Media Changed";
|
|
|
|
+ action = ACTION_FAIL;
|
|
} else {
|
|
} else {
|
|
/* Must have been a power glitch, or a
|
|
/* Must have been a power glitch, or a
|
|
* bus reset. Could not have been a
|
|
* bus reset. Could not have been a
|
|
* media change, so we just retry the
|
|
* media change, so we just retry the
|
|
- * request and see what happens.
|
|
|
|
|
|
+ * command and see what happens.
|
|
*/
|
|
*/
|
|
- scsi_requeue_command(q, cmd);
|
|
|
|
- return;
|
|
|
|
|
|
+ action = ACTION_RETRY;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case ILLEGAL_REQUEST:
|
|
case ILLEGAL_REQUEST:
|
|
@@ -983,21 +996,18 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|
sshdr.asc == 0x20 && sshdr.ascq == 0x00) &&
|
|
sshdr.asc == 0x20 && sshdr.ascq == 0x00) &&
|
|
(cmd->cmnd[0] == READ_10 ||
|
|
(cmd->cmnd[0] == READ_10 ||
|
|
cmd->cmnd[0] == WRITE_10)) {
|
|
cmd->cmnd[0] == WRITE_10)) {
|
|
|
|
+ /* This will issue a new 6-byte command. */
|
|
cmd->device->use_10_for_rw = 0;
|
|
cmd->device->use_10_for_rw = 0;
|
|
- /* This will cause a retry with a
|
|
|
|
- * 6-byte command.
|
|
|
|
- */
|
|
|
|
- scsi_requeue_command(q, cmd);
|
|
|
|
- } else if (sshdr.asc == 0x10) /* DIX */
|
|
|
|
- scsi_end_request(cmd, -EIO, this_count, 0);
|
|
|
|
- else
|
|
|
|
- scsi_end_request(cmd, -EIO, this_count, 1);
|
|
|
|
- return;
|
|
|
|
|
|
+ action = ACTION_REPREP;
|
|
|
|
+ } else
|
|
|
|
+ action = ACTION_FAIL;
|
|
|
|
+ break;
|
|
case ABORTED_COMMAND:
|
|
case ABORTED_COMMAND:
|
|
if (sshdr.asc == 0x10) { /* DIF */
|
|
if (sshdr.asc == 0x10) { /* DIF */
|
|
- scsi_end_request(cmd, -EIO, this_count, 0);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ action = ACTION_FAIL;
|
|
|
|
+ description = "Data Integrity Failure";
|
|
|
|
+ } else
|
|
|
|
+ action = ACTION_RETRY;
|
|
break;
|
|
break;
|
|
case NOT_READY:
|
|
case NOT_READY:
|
|
/* If the device is in the process of becoming
|
|
/* If the device is in the process of becoming
|
|
@@ -1012,49 +1022,57 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|
case 0x07: /* operation in progress */
|
|
case 0x07: /* operation in progress */
|
|
case 0x08: /* Long write in progress */
|
|
case 0x08: /* Long write in progress */
|
|
case 0x09: /* self test in progress */
|
|
case 0x09: /* self test in progress */
|
|
- scsi_requeue_command(q, cmd);
|
|
|
|
- return;
|
|
|
|
- default:
|
|
|
|
|
|
+ action = ACTION_DELAYED_RETRY;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ } else {
|
|
|
|
+ description = "Device not ready";
|
|
|
|
+ action = ACTION_FAIL;
|
|
}
|
|
}
|
|
- if (!(req->cmd_flags & REQ_QUIET))
|
|
|
|
- scsi_cmd_print_sense_hdr(cmd,
|
|
|
|
- "Device not ready",
|
|
|
|
- &sshdr);
|
|
|
|
-
|
|
|
|
- scsi_end_request(cmd, -EIO, this_count, 1);
|
|
|
|
- return;
|
|
|
|
|
|
+ break;
|
|
case VOLUME_OVERFLOW:
|
|
case VOLUME_OVERFLOW:
|
|
- if (!(req->cmd_flags & REQ_QUIET)) {
|
|
|
|
- scmd_printk(KERN_INFO, cmd,
|
|
|
|
- "Volume overflow, CDB: ");
|
|
|
|
- __scsi_print_command(cmd->cmnd);
|
|
|
|
- scsi_print_sense("", cmd);
|
|
|
|
- }
|
|
|
|
/* See SSC3rXX or current. */
|
|
/* See SSC3rXX or current. */
|
|
- scsi_end_request(cmd, -EIO, this_count, 1);
|
|
|
|
- return;
|
|
|
|
|
|
+ action = ACTION_FAIL;
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
|
|
+ description = "Unhandled sense code";
|
|
|
|
+ action = ACTION_FAIL;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ } else {
|
|
|
|
+ description = "Unhandled error code";
|
|
|
|
+ action = ACTION_FAIL;
|
|
}
|
|
}
|
|
- if (host_byte(result) == DID_RESET) {
|
|
|
|
- /* Third party bus reset or reset for error recovery
|
|
|
|
- * reasons. Just retry the request and see what
|
|
|
|
- * happens.
|
|
|
|
- */
|
|
|
|
- scsi_requeue_command(q, cmd);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- if (result) {
|
|
|
|
|
|
+
|
|
|
|
+ switch (action) {
|
|
|
|
+ case ACTION_FAIL:
|
|
|
|
+ /* Give up and fail the remainder of the request */
|
|
if (!(req->cmd_flags & REQ_QUIET)) {
|
|
if (!(req->cmd_flags & REQ_QUIET)) {
|
|
|
|
+ if (description)
|
|
|
|
+ scmd_printk(KERN_INFO, cmd, "%s",
|
|
|
|
+ description);
|
|
scsi_print_result(cmd);
|
|
scsi_print_result(cmd);
|
|
if (driver_byte(result) & DRIVER_SENSE)
|
|
if (driver_byte(result) & DRIVER_SENSE)
|
|
scsi_print_sense("", cmd);
|
|
scsi_print_sense("", cmd);
|
|
}
|
|
}
|
|
|
|
+ blk_end_request(req, -EIO, blk_rq_bytes(req));
|
|
|
|
+ scsi_next_command(cmd);
|
|
|
|
+ break;
|
|
|
|
+ case ACTION_REPREP:
|
|
|
|
+ /* Unprep the request and put it back at the head of the queue.
|
|
|
|
+ * A new command will be prepared and issued.
|
|
|
|
+ */
|
|
|
|
+ scsi_requeue_command(q, cmd);
|
|
|
|
+ break;
|
|
|
|
+ case ACTION_RETRY:
|
|
|
|
+ /* Retry the same command immediately */
|
|
|
|
+ scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
|
|
|
|
+ break;
|
|
|
|
+ case ACTION_DELAYED_RETRY:
|
|
|
|
+ /* Retry the same command after a delay */
|
|
|
|
+ scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
- scsi_end_request(cmd, -EIO, this_count, !result);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
|
|
static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
|