diff options
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 5f84a148eb14..2cfcbffa41fd 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <scsi/scsi_cmnd.h> | 30 | #include <scsi/scsi_cmnd.h> |
31 | #include <scsi/scsi_dbg.h> | 31 | #include <scsi/scsi_dbg.h> |
32 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
33 | #include <scsi/scsi_driver.h> | ||
33 | #include <scsi/scsi_eh.h> | 34 | #include <scsi/scsi_eh.h> |
34 | #include <scsi/scsi_transport.h> | 35 | #include <scsi/scsi_transport.h> |
35 | #include <scsi/scsi_host.h> | 36 | #include <scsi/scsi_host.h> |
@@ -141,11 +142,11 @@ enum blk_eh_timer_return scsi_times_out(struct request *req) | |||
141 | else if (host->hostt->eh_timed_out) | 142 | else if (host->hostt->eh_timed_out) |
142 | rtn = host->hostt->eh_timed_out(scmd); | 143 | rtn = host->hostt->eh_timed_out(scmd); |
143 | 144 | ||
145 | scmd->result |= DID_TIME_OUT << 16; | ||
146 | |||
144 | if (unlikely(rtn == BLK_EH_NOT_HANDLED && | 147 | if (unlikely(rtn == BLK_EH_NOT_HANDLED && |
145 | !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { | 148 | !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) |
146 | scmd->result |= DID_TIME_OUT << 16; | ||
147 | rtn = BLK_EH_HANDLED; | 149 | rtn = BLK_EH_HANDLED; |
148 | } | ||
149 | 150 | ||
150 | return rtn; | 151 | return rtn; |
151 | } | 152 | } |
@@ -366,6 +367,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) | |||
366 | return TARGET_ERROR; | 367 | return TARGET_ERROR; |
367 | 368 | ||
368 | case ILLEGAL_REQUEST: | 369 | case ILLEGAL_REQUEST: |
370 | if (sshdr.asc == 0x20 || /* Invalid command operation code */ | ||
371 | sshdr.asc == 0x21 || /* Logical block address out of range */ | ||
372 | sshdr.asc == 0x24 || /* Invalid field in cdb */ | ||
373 | sshdr.asc == 0x26) { /* Parameter value invalid */ | ||
374 | return TARGET_ERROR; | ||
375 | } | ||
376 | return SUCCESS; | ||
377 | |||
369 | default: | 378 | default: |
370 | return SUCCESS; | 379 | return SUCCESS; |
371 | } | 380 | } |
@@ -770,6 +779,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
770 | int cmnd_size, int timeout, unsigned sense_bytes) | 779 | int cmnd_size, int timeout, unsigned sense_bytes) |
771 | { | 780 | { |
772 | struct scsi_device *sdev = scmd->device; | 781 | struct scsi_device *sdev = scmd->device; |
782 | struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd); | ||
773 | struct Scsi_Host *shost = sdev->host; | 783 | struct Scsi_Host *shost = sdev->host; |
774 | DECLARE_COMPLETION_ONSTACK(done); | 784 | DECLARE_COMPLETION_ONSTACK(done); |
775 | unsigned long timeleft; | 785 | unsigned long timeleft; |
@@ -824,6 +834,10 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
824 | } | 834 | } |
825 | 835 | ||
826 | scsi_eh_restore_cmnd(scmd, &ses); | 836 | scsi_eh_restore_cmnd(scmd, &ses); |
837 | |||
838 | if (sdrv->eh_action) | ||
839 | rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn); | ||
840 | |||
827 | return rtn; | 841 | return rtn; |
828 | } | 842 | } |
829 | 843 | ||
@@ -1540,7 +1554,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) | |||
1540 | * Need to modify host byte to signal a | 1554 | * Need to modify host byte to signal a |
1541 | * permanent target failure | 1555 | * permanent target failure |
1542 | */ | 1556 | */ |
1543 | scmd->result |= (DID_TARGET_FAILURE << 16); | 1557 | set_host_byte(scmd, DID_TARGET_FAILURE); |
1544 | rtn = SUCCESS; | 1558 | rtn = SUCCESS; |
1545 | } | 1559 | } |
1546 | /* if rtn == FAILED, we have no sense information; | 1560 | /* if rtn == FAILED, we have no sense information; |
@@ -1560,7 +1574,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) | |||
1560 | case RESERVATION_CONFLICT: | 1574 | case RESERVATION_CONFLICT: |
1561 | sdev_printk(KERN_INFO, scmd->device, | 1575 | sdev_printk(KERN_INFO, scmd->device, |
1562 | "reservation conflict\n"); | 1576 | "reservation conflict\n"); |
1563 | scmd->result |= (DID_NEXUS_FAILURE << 16); | 1577 | set_host_byte(scmd, DID_NEXUS_FAILURE); |
1564 | return SUCCESS; /* causes immediate i/o error */ | 1578 | return SUCCESS; /* causes immediate i/o error */ |
1565 | default: | 1579 | default: |
1566 | return FAILED; | 1580 | return FAILED; |