diff options
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 45c75649b9e0..991de3c15cfc 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -223,7 +223,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost, | |||
223 | * @scmd: Cmd to have sense checked. | 223 | * @scmd: Cmd to have sense checked. |
224 | * | 224 | * |
225 | * Return value: | 225 | * Return value: |
226 | * SUCCESS or FAILED or NEEDS_RETRY | 226 | * SUCCESS or FAILED or NEEDS_RETRY or TARGET_ERROR |
227 | * | 227 | * |
228 | * Notes: | 228 | * Notes: |
229 | * When a deferred error is detected the current command has | 229 | * When a deferred error is detected the current command has |
@@ -326,17 +326,19 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) | |||
326 | */ | 326 | */ |
327 | return SUCCESS; | 327 | return SUCCESS; |
328 | 328 | ||
329 | /* these three are not supported */ | 329 | /* these are not supported */ |
330 | case COPY_ABORTED: | 330 | case COPY_ABORTED: |
331 | case VOLUME_OVERFLOW: | 331 | case VOLUME_OVERFLOW: |
332 | case MISCOMPARE: | 332 | case MISCOMPARE: |
333 | return SUCCESS; | 333 | case BLANK_CHECK: |
334 | case DATA_PROTECT: | ||
335 | return TARGET_ERROR; | ||
334 | 336 | ||
335 | case MEDIUM_ERROR: | 337 | case MEDIUM_ERROR: |
336 | if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */ | 338 | if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */ |
337 | sshdr.asc == 0x13 || /* AMNF DATA FIELD */ | 339 | sshdr.asc == 0x13 || /* AMNF DATA FIELD */ |
338 | sshdr.asc == 0x14) { /* RECORD NOT FOUND */ | 340 | sshdr.asc == 0x14) { /* RECORD NOT FOUND */ |
339 | return SUCCESS; | 341 | return TARGET_ERROR; |
340 | } | 342 | } |
341 | return NEEDS_RETRY; | 343 | return NEEDS_RETRY; |
342 | 344 | ||
@@ -344,11 +346,9 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) | |||
344 | if (scmd->device->retry_hwerror) | 346 | if (scmd->device->retry_hwerror) |
345 | return ADD_TO_MLQUEUE; | 347 | return ADD_TO_MLQUEUE; |
346 | else | 348 | else |
347 | return SUCCESS; | 349 | return TARGET_ERROR; |
348 | 350 | ||
349 | case ILLEGAL_REQUEST: | 351 | case ILLEGAL_REQUEST: |
350 | case BLANK_CHECK: | ||
351 | case DATA_PROTECT: | ||
352 | default: | 352 | default: |
353 | return SUCCESS; | 353 | return SUCCESS; |
354 | } | 354 | } |
@@ -787,6 +787,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
787 | case SUCCESS: | 787 | case SUCCESS: |
788 | case NEEDS_RETRY: | 788 | case NEEDS_RETRY: |
789 | case FAILED: | 789 | case FAILED: |
790 | case TARGET_ERROR: | ||
790 | break; | 791 | break; |
791 | case ADD_TO_MLQUEUE: | 792 | case ADD_TO_MLQUEUE: |
792 | rtn = NEEDS_RETRY; | 793 | rtn = NEEDS_RETRY; |
@@ -1469,6 +1470,14 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) | |||
1469 | rtn = scsi_check_sense(scmd); | 1470 | rtn = scsi_check_sense(scmd); |
1470 | if (rtn == NEEDS_RETRY) | 1471 | if (rtn == NEEDS_RETRY) |
1471 | goto maybe_retry; | 1472 | goto maybe_retry; |
1473 | else if (rtn == TARGET_ERROR) { | ||
1474 | /* | ||
1475 | * Need to modify host byte to signal a | ||
1476 | * permanent target failure | ||
1477 | */ | ||
1478 | scmd->result |= (DID_TARGET_FAILURE << 16); | ||
1479 | rtn = SUCCESS; | ||
1480 | } | ||
1472 | /* if rtn == FAILED, we have no sense information; | 1481 | /* if rtn == FAILED, we have no sense information; |
1473 | * returning FAILED will wake the error handler thread | 1482 | * returning FAILED will wake the error handler thread |
1474 | * to collect the sense and redo the decide | 1483 | * to collect the sense and redo the decide |
@@ -1486,6 +1495,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) | |||
1486 | case RESERVATION_CONFLICT: | 1495 | case RESERVATION_CONFLICT: |
1487 | sdev_printk(KERN_INFO, scmd->device, | 1496 | sdev_printk(KERN_INFO, scmd->device, |
1488 | "reservation conflict\n"); | 1497 | "reservation conflict\n"); |
1498 | scmd->result |= (DID_NEXUS_FAILURE << 16); | ||
1489 | return SUCCESS; /* causes immediate i/o error */ | 1499 | return SUCCESS; /* causes immediate i/o error */ |
1490 | default: | 1500 | default: |
1491 | return FAILED; | 1501 | return FAILED; |