aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ahci.c')
-rw-r--r--drivers/scsi/ahci.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 4e96ec5f2ff9..83467a05dc8e 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -48,7 +48,7 @@
48#include <asm/io.h> 48#include <asm/io.h>
49 49
50#define DRV_NAME "ahci" 50#define DRV_NAME "ahci"
51#define DRV_VERSION "1.01" 51#define DRV_VERSION "1.2"
52 52
53 53
54enum { 54enum {
@@ -558,13 +558,26 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
558 pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16); 558 pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16);
559} 559}
560 560
561static void ahci_intr_error(struct ata_port *ap, u32 irq_stat) 561static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
562{ 562{
563 void __iomem *mmio = ap->host_set->mmio_base; 563 void __iomem *mmio = ap->host_set->mmio_base;
564 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 564 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
565 u32 tmp; 565 u32 tmp;
566 int work; 566 int work;
567 567
568 if ((ap->device[0].class != ATA_DEV_ATAPI) ||
569 ((irq_stat & PORT_IRQ_TF_ERR) == 0))
570 printk(KERN_WARNING "ata%u: port reset, "
571 "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n",
572 ap->id,
573 irq_stat,
574 readl(mmio + HOST_IRQ_STAT),
575 readl(port_mmio + PORT_IRQ_STAT),
576 readl(port_mmio + PORT_CMD),
577 readl(port_mmio + PORT_TFDATA),
578 readl(port_mmio + PORT_SCR_STAT),
579 readl(port_mmio + PORT_SCR_ERR));
580
568 /* stop DMA */ 581 /* stop DMA */
569 tmp = readl(port_mmio + PORT_CMD); 582 tmp = readl(port_mmio + PORT_CMD);
570 tmp &= ~PORT_CMD_START; 583 tmp &= ~PORT_CMD_START;
@@ -602,8 +615,6 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
602 tmp |= PORT_CMD_START; 615 tmp |= PORT_CMD_START;
603 writel(tmp, port_mmio + PORT_CMD); 616 writel(tmp, port_mmio + PORT_CMD);
604 readl(port_mmio + PORT_CMD); /* flush */ 617 readl(port_mmio + PORT_CMD); /* flush */
605
606 printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id);
607} 618}
608 619
609static void ahci_eng_timeout(struct ata_port *ap) 620static void ahci_eng_timeout(struct ata_port *ap)
@@ -614,17 +625,17 @@ static void ahci_eng_timeout(struct ata_port *ap)
614 struct ata_queued_cmd *qc; 625 struct ata_queued_cmd *qc;
615 unsigned long flags; 626 unsigned long flags;
616 627
617 DPRINTK("ENTER\n"); 628 printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id);
618 629
619 spin_lock_irqsave(&host_set->lock, flags); 630 spin_lock_irqsave(&host_set->lock, flags);
620 631
621 ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
622
623 qc = ata_qc_from_tag(ap, ap->active_tag); 632 qc = ata_qc_from_tag(ap, ap->active_tag);
624 if (!qc) { 633 if (!qc) {
625 printk(KERN_ERR "ata%u: BUG: timeout without command\n", 634 printk(KERN_ERR "ata%u: BUG: timeout without command\n",
626 ap->id); 635 ap->id);
627 } else { 636 } else {
637 ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
638
628 /* hack alert! We cannot use the supplied completion 639 /* hack alert! We cannot use the supplied completion
629 * function from inside the ->eh_strategy_handler() thread. 640 * function from inside the ->eh_strategy_handler() thread.
630 * libata is the only user of ->eh_strategy_handler() in 641 * libata is the only user of ->eh_strategy_handler() in
@@ -659,9 +670,19 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
659 } 670 }
660 671
661 if (status & PORT_IRQ_FATAL) { 672 if (status & PORT_IRQ_FATAL) {
662 ahci_intr_error(ap, status); 673 unsigned int err_mask;
674 if (status & PORT_IRQ_TF_ERR)
675 err_mask = AC_ERR_DEV;
676 else if (status & PORT_IRQ_IF_ERR)
677 err_mask = AC_ERR_ATA_BUS;
678 else
679 err_mask = AC_ERR_HOST_BUS;
680
681 /* command processing has stopped due to error; restart */
682 ahci_restart_port(ap, status);
683
663 if (qc) 684 if (qc)
664 ata_qc_complete(qc, AC_ERR_OTHER); 685 ata_qc_complete(qc, err_mask);
665 } 686 }
666 687
667 return 1; 688 return 1;