aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@suse.de>2011-01-23 10:42:50 -0500
committerJeff Garzik <jgarzik@redhat.com>2011-03-02 02:36:45 -0500
commit0e0b494ca8c54a7297d0cc549405091019b3b77e (patch)
tree7d675c0ccae0763402585e91c38f1aa42818031c /drivers/ata
parentc34aeebc06e8bdde93e8c8f40d9903b1aaab63c6 (diff)
libata: separate error handler into usable components
Right at the moment, the libata error handler is incredibly monolithic. This makes it impossible to use from composite drivers like libsas and ipr which have to handle error themselves in the first instance. The essence of the change is to split the monolithic error handler into two components: one which handles a queue of ata commands for processing and the other which handles the back end of readying a port. This allows the upper error handler fine grained control in calling libsas functions (and making sure they only get called for ATA commands whose lower errors have been fixed up). Signed-off-by: James Bottomley <James.Bottomley@suse.de> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-eh.c53
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)
587void ata_scsi_error(struct Scsi_Host *host) 587void 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 */
621void 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 ? */ 707EXPORT_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 */
717void 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}
829EXPORT_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