aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_error.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r--drivers/scsi/scsi_error.c24
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;