Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 124619
b: refs/heads/master
c: b60af5b
h: refs/heads/master
i:
  124617: 82015e0
  124615: a27ceea
v: v3
  • Loading branch information
Alan Stern authored and James Bottomley committed Dec 29, 2008
1 parent a9001ae commit 197800f
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 60 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 67e6d58d812ec3e95918266076d4c836cdec849a
refs/heads/master: b60af5b0adf0da24c673598c8d3fb4d4189a15ce
136 changes: 77 additions & 59 deletions trunk/drivers/scsi/scsi_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 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)
{
Expand All @@ -896,6 +904,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int sense_deferred = 0;
enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
ACTION_DELAYED_RETRY} action;
char *description = NULL;

if (result) {
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
Expand Down Expand Up @@ -947,27 +958,29 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
return;
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) {
case UNIT_ATTENTION:
if (cmd->device->removable) {
/* Detected disc change. Set a bit
* and quietly refuse further access.
*/
cmd->device->changed = 1;
scsi_end_request(cmd, -EIO, this_count, 1);
return;
description = "Media Changed";
action = ACTION_FAIL;
} else {
/* Must have been a power glitch, or a
* bus reset. Could not have been a
* 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;
case ILLEGAL_REQUEST:
Expand All @@ -983,21 +996,18 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
sshdr.asc == 0x20 && sshdr.ascq == 0x00) &&
(cmd->cmnd[0] == READ_10 ||
cmd->cmnd[0] == WRITE_10)) {
/* This will issue a new 6-byte command. */
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:
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;
case NOT_READY:
/* If the device is in the process of becoming
Expand All @@ -1012,49 +1022,57 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
case 0x07: /* operation in progress */
case 0x08: /* Long write in progress */
case 0x09: /* self test in progress */
scsi_requeue_command(q, cmd);
return;
default:
action = ACTION_DELAYED_RETRY;
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:
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. */
scsi_end_request(cmd, -EIO, this_count, 1);
return;
action = ACTION_FAIL;
break;
default:
description = "Unhandled sense code";
action = ACTION_FAIL;
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 (description)
scmd_printk(KERN_INFO, cmd, "%s",
description);
scsi_print_result(cmd);
if (driver_byte(result) & DRIVER_SENSE)
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,
Expand Down

0 comments on commit 197800f

Please sign in to comment.