aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-11-14 13:56:37 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-11-14 13:56:37 -0500
commitad36d1a533da91d3448029b4da1113c5b880f25d (patch)
tree00e66685a3572daed99fa8def4580ea6022b6db7
parent4ba529a8a39e15688b6a3d31b11930d1f8a1edad (diff)
[libata ahci] error handling fixes
Needed to get ATAPI working. - dump hardware error bits, if hardware signals an error - only reset hardware during timeout if a command was active - call ata_qc_complete() with a fine-grained error mask. Needed so that atapi_qc_complete() can distinguish between device errors and other errors.
-rw-r--r--drivers/scsi/ahci.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 4e96ec5f2ff9..c710a7def7a7 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -603,7 +603,12 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
603 writel(tmp, port_mmio + PORT_CMD); 603 writel(tmp, port_mmio + PORT_CMD);
604 readl(port_mmio + PORT_CMD); /* flush */ 604 readl(port_mmio + PORT_CMD); /* flush */
605 605
606 printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id); 606 printk(KERN_WARNING "ata%u: error occurred, port reset (%s%s%s%s)\n",
607 ap->id,
608 irq_stat & PORT_IRQ_TF_ERR ? "taskf " : "",
609 irq_stat & PORT_IRQ_HBUS_ERR ? "hbus " : "",
610 irq_stat & PORT_IRQ_HBUS_DATA_ERR ? "hbus_data " : "",
611 irq_stat & PORT_IRQ_IF_ERR ? "if " : "");
607} 612}
608 613
609static void ahci_eng_timeout(struct ata_port *ap) 614static void ahci_eng_timeout(struct ata_port *ap)
@@ -618,13 +623,13 @@ static void ahci_eng_timeout(struct ata_port *ap)
618 623
619 spin_lock_irqsave(&host_set->lock, flags); 624 spin_lock_irqsave(&host_set->lock, flags);
620 625
621 ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
622
623 qc = ata_qc_from_tag(ap, ap->active_tag); 626 qc = ata_qc_from_tag(ap, ap->active_tag);
624 if (!qc) { 627 if (!qc) {
625 printk(KERN_ERR "ata%u: BUG: timeout without command\n", 628 printk(KERN_ERR "ata%u: BUG: timeout without command\n",
626 ap->id); 629 ap->id);
627 } else { 630 } else {
631 ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
632
628 /* hack alert! We cannot use the supplied completion 633 /* hack alert! We cannot use the supplied completion
629 * function from inside the ->eh_strategy_handler() thread. 634 * function from inside the ->eh_strategy_handler() thread.
630 * libata is the only user of ->eh_strategy_handler() in 635 * libata is the only user of ->eh_strategy_handler() in
@@ -659,9 +664,18 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
659 } 664 }
660 665
661 if (status & PORT_IRQ_FATAL) { 666 if (status & PORT_IRQ_FATAL) {
662 ahci_intr_error(ap, status); 667 unsigned int err_mask;
668 if (status & PORT_IRQ_TF_ERR)
669 err_mask = AC_ERR_DEV;
670 else if (status & PORT_IRQ_IF_ERR)
671 err_mask = AC_ERR_ATA_BUS;
672 else
673 err_mask = AC_ERR_HOST_BUS;
674
675 if (err_mask != AC_ERR_DEV)
676 ahci_intr_error(ap, status);
663 if (qc) 677 if (qc)
664 ata_qc_complete(qc, AC_ERR_OTHER); 678 ata_qc_complete(qc, err_mask);
665 } 679 }
666 680
667 return 1; 681 return 1;