diff options
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 256 |
1 files changed, 135 insertions, 121 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2ecb6ff42444..b8edcf5b5451 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -359,6 +359,11 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) | |||
359 | return SUCCESS; | 359 | return SUCCESS; |
360 | 360 | ||
361 | case MEDIUM_ERROR: | 361 | case MEDIUM_ERROR: |
362 | if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */ | ||
363 | sshdr.asc == 0x13 || /* AMNF DATA FIELD */ | ||
364 | sshdr.asc == 0x14) { /* RECORD NOT FOUND */ | ||
365 | return SUCCESS; | ||
366 | } | ||
362 | return NEEDS_RETRY; | 367 | return NEEDS_RETRY; |
363 | 368 | ||
364 | case HARDWARE_ERROR: | 369 | case HARDWARE_ERROR: |
@@ -453,6 +458,128 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) | |||
453 | } | 458 | } |
454 | 459 | ||
455 | /** | 460 | /** |
461 | * scsi_try_host_reset - ask host adapter to reset itself | ||
462 | * @scmd: SCSI cmd to send hsot reset. | ||
463 | **/ | ||
464 | static int scsi_try_host_reset(struct scsi_cmnd *scmd) | ||
465 | { | ||
466 | unsigned long flags; | ||
467 | int rtn; | ||
468 | |||
469 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", | ||
470 | __FUNCTION__)); | ||
471 | |||
472 | if (!scmd->device->host->hostt->eh_host_reset_handler) | ||
473 | return FAILED; | ||
474 | |||
475 | rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd); | ||
476 | |||
477 | if (rtn == SUCCESS) { | ||
478 | if (!scmd->device->host->hostt->skip_settle_delay) | ||
479 | ssleep(HOST_RESET_SETTLE_TIME); | ||
480 | spin_lock_irqsave(scmd->device->host->host_lock, flags); | ||
481 | scsi_report_bus_reset(scmd->device->host, | ||
482 | scmd_channel(scmd)); | ||
483 | spin_unlock_irqrestore(scmd->device->host->host_lock, flags); | ||
484 | } | ||
485 | |||
486 | return rtn; | ||
487 | } | ||
488 | |||
489 | /** | ||
490 | * scsi_try_bus_reset - ask host to perform a bus reset | ||
491 | * @scmd: SCSI cmd to send bus reset. | ||
492 | **/ | ||
493 | static int scsi_try_bus_reset(struct scsi_cmnd *scmd) | ||
494 | { | ||
495 | unsigned long flags; | ||
496 | int rtn; | ||
497 | |||
498 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", | ||
499 | __FUNCTION__)); | ||
500 | |||
501 | if (!scmd->device->host->hostt->eh_bus_reset_handler) | ||
502 | return FAILED; | ||
503 | |||
504 | rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd); | ||
505 | |||
506 | if (rtn == SUCCESS) { | ||
507 | if (!scmd->device->host->hostt->skip_settle_delay) | ||
508 | ssleep(BUS_RESET_SETTLE_TIME); | ||
509 | spin_lock_irqsave(scmd->device->host->host_lock, flags); | ||
510 | scsi_report_bus_reset(scmd->device->host, | ||
511 | scmd_channel(scmd)); | ||
512 | spin_unlock_irqrestore(scmd->device->host->host_lock, flags); | ||
513 | } | ||
514 | |||
515 | return rtn; | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev | ||
520 | * @scmd: SCSI cmd used to send BDR | ||
521 | * | ||
522 | * Notes: | ||
523 | * There is no timeout for this operation. if this operation is | ||
524 | * unreliable for a given host, then the host itself needs to put a | ||
525 | * timer on it, and set the host back to a consistent state prior to | ||
526 | * returning. | ||
527 | **/ | ||
528 | static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) | ||
529 | { | ||
530 | int rtn; | ||
531 | |||
532 | if (!scmd->device->host->hostt->eh_device_reset_handler) | ||
533 | return FAILED; | ||
534 | |||
535 | rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd); | ||
536 | if (rtn == SUCCESS) { | ||
537 | scmd->device->was_reset = 1; | ||
538 | scmd->device->expecting_cc_ua = 1; | ||
539 | } | ||
540 | |||
541 | return rtn; | ||
542 | } | ||
543 | |||
544 | static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) | ||
545 | { | ||
546 | if (!scmd->device->host->hostt->eh_abort_handler) | ||
547 | return FAILED; | ||
548 | |||
549 | return scmd->device->host->hostt->eh_abort_handler(scmd); | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * scsi_try_to_abort_cmd - Ask host to abort a running command. | ||
554 | * @scmd: SCSI cmd to abort from Lower Level. | ||
555 | * | ||
556 | * Notes: | ||
557 | * This function will not return until the user's completion function | ||
558 | * has been called. there is no timeout on this operation. if the | ||
559 | * author of the low-level driver wishes this operation to be timed, | ||
560 | * they can provide this facility themselves. helper functions in | ||
561 | * scsi_error.c can be supplied to make this easier to do. | ||
562 | **/ | ||
563 | static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) | ||
564 | { | ||
565 | /* | ||
566 | * scsi_done was called just after the command timed out and before | ||
567 | * we had a chance to process it. (db) | ||
568 | */ | ||
569 | if (scmd->serial_number == 0) | ||
570 | return SUCCESS; | ||
571 | return __scsi_try_to_abort_cmd(scmd); | ||
572 | } | ||
573 | |||
574 | static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) | ||
575 | { | ||
576 | if (__scsi_try_to_abort_cmd(scmd) != SUCCESS) | ||
577 | if (scsi_try_bus_device_reset(scmd) != SUCCESS) | ||
578 | if (scsi_try_bus_reset(scmd) != SUCCESS) | ||
579 | scsi_try_host_reset(scmd); | ||
580 | } | ||
581 | |||
582 | /** | ||
456 | * scsi_send_eh_cmnd - submit a scsi command as part of error recory | 583 | * scsi_send_eh_cmnd - submit a scsi command as part of error recory |
457 | * @scmd: SCSI command structure to hijack | 584 | * @scmd: SCSI command structure to hijack |
458 | * @cmnd: CDB to send | 585 | * @cmnd: CDB to send |
@@ -579,13 +706,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
579 | break; | 706 | break; |
580 | } | 707 | } |
581 | } else { | 708 | } else { |
582 | /* | 709 | scsi_abort_eh_cmnd(scmd); |
583 | * FIXME(eric) - we are not tracking whether we could | ||
584 | * abort a timed out command or not. not sure how | ||
585 | * we should treat them differently anyways. | ||
586 | */ | ||
587 | if (shost->hostt->eh_abort_handler) | ||
588 | shost->hostt->eh_abort_handler(scmd); | ||
589 | rtn = FAILED; | 710 | rtn = FAILED; |
590 | } | 711 | } |
591 | 712 | ||
@@ -672,8 +793,8 @@ EXPORT_SYMBOL(scsi_eh_finish_cmd); | |||
672 | * XXX: Long term this code should go away, but that needs an audit of | 793 | * XXX: Long term this code should go away, but that needs an audit of |
673 | * all LLDDs first. | 794 | * all LLDDs first. |
674 | **/ | 795 | **/ |
675 | static int scsi_eh_get_sense(struct list_head *work_q, | 796 | int scsi_eh_get_sense(struct list_head *work_q, |
676 | struct list_head *done_q) | 797 | struct list_head *done_q) |
677 | { | 798 | { |
678 | struct scsi_cmnd *scmd, *next; | 799 | struct scsi_cmnd *scmd, *next; |
679 | int rtn; | 800 | int rtn; |
@@ -715,31 +836,7 @@ static int scsi_eh_get_sense(struct list_head *work_q, | |||
715 | 836 | ||
716 | return list_empty(work_q); | 837 | return list_empty(work_q); |
717 | } | 838 | } |
718 | 839 | EXPORT_SYMBOL_GPL(scsi_eh_get_sense); | |
719 | /** | ||
720 | * scsi_try_to_abort_cmd - Ask host to abort a running command. | ||
721 | * @scmd: SCSI cmd to abort from Lower Level. | ||
722 | * | ||
723 | * Notes: | ||
724 | * This function will not return until the user's completion function | ||
725 | * has been called. there is no timeout on this operation. if the | ||
726 | * author of the low-level driver wishes this operation to be timed, | ||
727 | * they can provide this facility themselves. helper functions in | ||
728 | * scsi_error.c can be supplied to make this easier to do. | ||
729 | **/ | ||
730 | static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) | ||
731 | { | ||
732 | if (!scmd->device->host->hostt->eh_abort_handler) | ||
733 | return FAILED; | ||
734 | |||
735 | /* | ||
736 | * scsi_done was called just after the command timed out and before | ||
737 | * we had a chance to process it. (db) | ||
738 | */ | ||
739 | if (scmd->serial_number == 0) | ||
740 | return SUCCESS; | ||
741 | return scmd->device->host->hostt->eh_abort_handler(scmd); | ||
742 | } | ||
743 | 840 | ||
744 | /** | 841 | /** |
745 | * scsi_eh_tur - Send TUR to device. | 842 | * scsi_eh_tur - Send TUR to device. |
@@ -815,32 +912,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, | |||
815 | } | 912 | } |
816 | 913 | ||
817 | /** | 914 | /** |
818 | * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev | ||
819 | * @scmd: SCSI cmd used to send BDR | ||
820 | * | ||
821 | * Notes: | ||
822 | * There is no timeout for this operation. if this operation is | ||
823 | * unreliable for a given host, then the host itself needs to put a | ||
824 | * timer on it, and set the host back to a consistent state prior to | ||
825 | * returning. | ||
826 | **/ | ||
827 | static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) | ||
828 | { | ||
829 | int rtn; | ||
830 | |||
831 | if (!scmd->device->host->hostt->eh_device_reset_handler) | ||
832 | return FAILED; | ||
833 | |||
834 | rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd); | ||
835 | if (rtn == SUCCESS) { | ||
836 | scmd->device->was_reset = 1; | ||
837 | scmd->device->expecting_cc_ua = 1; | ||
838 | } | ||
839 | |||
840 | return rtn; | ||
841 | } | ||
842 | |||
843 | /** | ||
844 | * scsi_eh_try_stu - Send START_UNIT to device. | 915 | * scsi_eh_try_stu - Send START_UNIT to device. |
845 | * @scmd: Scsi cmd to send START_UNIT | 916 | * @scmd: Scsi cmd to send START_UNIT |
846 | * | 917 | * |
@@ -971,64 +1042,6 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, | |||
971 | } | 1042 | } |
972 | 1043 | ||
973 | /** | 1044 | /** |
974 | * scsi_try_bus_reset - ask host to perform a bus reset | ||
975 | * @scmd: SCSI cmd to send bus reset. | ||
976 | **/ | ||
977 | static int scsi_try_bus_reset(struct scsi_cmnd *scmd) | ||
978 | { | ||
979 | unsigned long flags; | ||
980 | int rtn; | ||
981 | |||
982 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", | ||
983 | __FUNCTION__)); | ||
984 | |||
985 | if (!scmd->device->host->hostt->eh_bus_reset_handler) | ||
986 | return FAILED; | ||
987 | |||
988 | rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd); | ||
989 | |||
990 | if (rtn == SUCCESS) { | ||
991 | if (!scmd->device->host->hostt->skip_settle_delay) | ||
992 | ssleep(BUS_RESET_SETTLE_TIME); | ||
993 | spin_lock_irqsave(scmd->device->host->host_lock, flags); | ||
994 | scsi_report_bus_reset(scmd->device->host, | ||
995 | scmd_channel(scmd)); | ||
996 | spin_unlock_irqrestore(scmd->device->host->host_lock, flags); | ||
997 | } | ||
998 | |||
999 | return rtn; | ||
1000 | } | ||
1001 | |||
1002 | /** | ||
1003 | * scsi_try_host_reset - ask host adapter to reset itself | ||
1004 | * @scmd: SCSI cmd to send hsot reset. | ||
1005 | **/ | ||
1006 | static int scsi_try_host_reset(struct scsi_cmnd *scmd) | ||
1007 | { | ||
1008 | unsigned long flags; | ||
1009 | int rtn; | ||
1010 | |||
1011 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", | ||
1012 | __FUNCTION__)); | ||
1013 | |||
1014 | if (!scmd->device->host->hostt->eh_host_reset_handler) | ||
1015 | return FAILED; | ||
1016 | |||
1017 | rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd); | ||
1018 | |||
1019 | if (rtn == SUCCESS) { | ||
1020 | if (!scmd->device->host->hostt->skip_settle_delay) | ||
1021 | ssleep(HOST_RESET_SETTLE_TIME); | ||
1022 | spin_lock_irqsave(scmd->device->host->host_lock, flags); | ||
1023 | scsi_report_bus_reset(scmd->device->host, | ||
1024 | scmd_channel(scmd)); | ||
1025 | spin_unlock_irqrestore(scmd->device->host->host_lock, flags); | ||
1026 | } | ||
1027 | |||
1028 | return rtn; | ||
1029 | } | ||
1030 | |||
1031 | /** | ||
1032 | * scsi_eh_bus_reset - send a bus reset | 1045 | * scsi_eh_bus_reset - send a bus reset |
1033 | * @shost: scsi host being recovered. | 1046 | * @shost: scsi host being recovered. |
1034 | * @eh_done_q: list_head for processed commands. | 1047 | * @eh_done_q: list_head for processed commands. |
@@ -1411,9 +1424,9 @@ static void scsi_restart_operations(struct Scsi_Host *shost) | |||
1411 | * @eh_done_q: list_head for processed commands. | 1424 | * @eh_done_q: list_head for processed commands. |
1412 | * | 1425 | * |
1413 | **/ | 1426 | **/ |
1414 | static void scsi_eh_ready_devs(struct Scsi_Host *shost, | 1427 | void scsi_eh_ready_devs(struct Scsi_Host *shost, |
1415 | struct list_head *work_q, | 1428 | struct list_head *work_q, |
1416 | struct list_head *done_q) | 1429 | struct list_head *done_q) |
1417 | { | 1430 | { |
1418 | if (!scsi_eh_stu(shost, work_q, done_q)) | 1431 | if (!scsi_eh_stu(shost, work_q, done_q)) |
1419 | if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) | 1432 | if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) |
@@ -1421,6 +1434,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost, | |||
1421 | if (!scsi_eh_host_reset(work_q, done_q)) | 1434 | if (!scsi_eh_host_reset(work_q, done_q)) |
1422 | scsi_eh_offline_sdevs(work_q, done_q); | 1435 | scsi_eh_offline_sdevs(work_q, done_q); |
1423 | } | 1436 | } |
1437 | EXPORT_SYMBOL_GPL(scsi_eh_ready_devs); | ||
1424 | 1438 | ||
1425 | /** | 1439 | /** |
1426 | * scsi_eh_flush_done_q - finish processed commands or retry them. | 1440 | * scsi_eh_flush_done_q - finish processed commands or retry them. |