diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/libata-eh.c | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 073b88156b3c..df3f3140c9c7 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -587,7 +587,6 @@ static void ata_eh_unload(struct ata_port *ap) | |||
587 | void ata_scsi_error(struct Scsi_Host *host) | 587 | void ata_scsi_error(struct Scsi_Host *host) |
588 | { | 588 | { |
589 | struct ata_port *ap = ata_shost_to_port(host); | 589 | struct ata_port *ap = ata_shost_to_port(host); |
590 | int i; | ||
591 | unsigned long flags; | 590 | unsigned long flags; |
592 | LIST_HEAD(eh_work_q); | 591 | LIST_HEAD(eh_work_q); |
593 | 592 | ||
@@ -597,6 +596,34 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
597 | list_splice_init(&host->eh_cmd_q, &eh_work_q); | 596 | list_splice_init(&host->eh_cmd_q, &eh_work_q); |
598 | spin_unlock_irqrestore(host->host_lock, flags); | 597 | spin_unlock_irqrestore(host->host_lock, flags); |
599 | 598 | ||
599 | ata_scsi_cmd_error_handler(host, ap, &eh_work_q); | ||
600 | |||
601 | /* If we timed raced normal completion and there is nothing to | ||
602 | recover nr_timedout == 0 why exactly are we doing error recovery ? */ | ||
603 | ata_scsi_port_error_handler(host, ap); | ||
604 | |||
605 | /* finish or retry handled scmd's and clean up */ | ||
606 | WARN_ON(host->host_failed || !list_empty(&eh_work_q)); | ||
607 | |||
608 | DPRINTK("EXIT\n"); | ||
609 | } | ||
610 | |||
611 | /** | ||
612 | * ata_scsi_cmd_error_handler - error callback for a list of commands | ||
613 | * @host: scsi host containing the port | ||
614 | * @ap: ATA port within the host | ||
615 | * @eh_work_q: list of commands to process | ||
616 | * | ||
617 | * process the given list of commands and return those finished to the | ||
618 | * ap->eh_done_q. This function is the first part of the libata error | ||
619 | * handler which processes a given list of failed commands. | ||
620 | */ | ||
621 | void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, | ||
622 | struct list_head *eh_work_q) | ||
623 | { | ||
624 | int i; | ||
625 | unsigned long flags; | ||
626 | |||
600 | /* make sure sff pio task is not running */ | 627 | /* make sure sff pio task is not running */ |
601 | ata_sff_flush_pio_task(ap); | 628 | ata_sff_flush_pio_task(ap); |
602 | 629 | ||
@@ -632,7 +659,7 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
632 | if (ap->ops->lost_interrupt) | 659 | if (ap->ops->lost_interrupt) |
633 | ap->ops->lost_interrupt(ap); | 660 | ap->ops->lost_interrupt(ap); |
634 | 661 | ||
635 | list_for_each_entry_safe(scmd, tmp, &eh_work_q, eh_entry) { | 662 | list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) { |
636 | struct ata_queued_cmd *qc; | 663 | struct ata_queued_cmd *qc; |
637 | 664 | ||
638 | for (i = 0; i < ATA_MAX_QUEUE; i++) { | 665 | for (i = 0; i < ATA_MAX_QUEUE; i++) { |
@@ -676,8 +703,20 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
676 | } else | 703 | } else |
677 | spin_unlock_wait(ap->lock); | 704 | spin_unlock_wait(ap->lock); |
678 | 705 | ||
679 | /* If we timed raced normal completion and there is nothing to | 706 | } |
680 | recover nr_timedout == 0 why exactly are we doing error recovery ? */ | 707 | EXPORT_SYMBOL(ata_scsi_cmd_error_handler); |
708 | |||
709 | /** | ||
710 | * ata_scsi_port_error_handler - recover the port after the commands | ||
711 | * @host: SCSI host containing the port | ||
712 | * @ap: the ATA port | ||
713 | * | ||
714 | * Handle the recovery of the port @ap after all the commands | ||
715 | * have been recovered. | ||
716 | */ | ||
717 | void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) | ||
718 | { | ||
719 | unsigned long flags; | ||
681 | 720 | ||
682 | /* invoke error handler */ | 721 | /* invoke error handler */ |
683 | if (ap->ops->error_handler) { | 722 | if (ap->ops->error_handler) { |
@@ -766,9 +805,6 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
766 | ap->ops->eng_timeout(ap); | 805 | ap->ops->eng_timeout(ap); |
767 | } | 806 | } |
768 | 807 | ||
769 | /* finish or retry handled scmd's and clean up */ | ||
770 | WARN_ON(host->host_failed || !list_empty(&eh_work_q)); | ||
771 | |||
772 | scsi_eh_flush_done_q(&ap->eh_done_q); | 808 | scsi_eh_flush_done_q(&ap->eh_done_q); |
773 | 809 | ||
774 | /* clean up */ | 810 | /* clean up */ |
@@ -789,9 +825,8 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
789 | wake_up_all(&ap->eh_wait_q); | 825 | wake_up_all(&ap->eh_wait_q); |
790 | 826 | ||
791 | spin_unlock_irqrestore(ap->lock, flags); | 827 | spin_unlock_irqrestore(ap->lock, flags); |
792 | |||
793 | DPRINTK("EXIT\n"); | ||
794 | } | 828 | } |
829 | EXPORT_SYMBOL_GPL(ata_scsi_port_error_handler); | ||
795 | 830 | ||
796 | /** | 831 | /** |
797 | * ata_port_wait_eh - Wait for the currently pending EH to complete | 832 | * ata_port_wait_eh - Wait for the currently pending EH to complete |