[PATCH] mark several libata datastructures const
[pandora-kernel.git] / drivers / scsi / ahci.c
index 4e96ec5..cfbdd3f 100644 (file)
@@ -48,7 +48,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ahci"
-#define DRV_VERSION    "1.01"
+#define DRV_VERSION    "1.2"
 
 
 enum {
@@ -243,7 +243,7 @@ static const struct ata_port_operations ahci_ops = {
        .port_stop              = ahci_port_stop,
 };
 
-static struct ata_port_info ahci_port_info[] = {
+static const struct ata_port_info ahci_port_info[] = {
        /* board_ahci */
        {
                .sht            = &ahci_sht,
@@ -558,13 +558,26 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
        pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16);
 }
 
-static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
+static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
 {
        void __iomem *mmio = ap->host_set->mmio_base;
        void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        u32 tmp;
        int work;
 
+       if ((ap->device[0].class != ATA_DEV_ATAPI) ||
+           ((irq_stat & PORT_IRQ_TF_ERR) == 0))
+               printk(KERN_WARNING "ata%u: port reset, "
+                      "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n",
+                       ap->id,
+                       irq_stat,
+                       readl(mmio + HOST_IRQ_STAT),
+                       readl(port_mmio + PORT_IRQ_STAT),
+                       readl(port_mmio + PORT_CMD),
+                       readl(port_mmio + PORT_TFDATA),
+                       readl(port_mmio + PORT_SCR_STAT),
+                       readl(port_mmio + PORT_SCR_ERR));
+
        /* stop DMA */
        tmp = readl(port_mmio + PORT_CMD);
        tmp &= ~PORT_CMD_START;
@@ -602,8 +615,6 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
        tmp |= PORT_CMD_START;
        writel(tmp, port_mmio + PORT_CMD);
        readl(port_mmio + PORT_CMD); /* flush */
-
-       printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id);
 }
 
 static void ahci_eng_timeout(struct ata_port *ap)
@@ -614,17 +625,17 @@ static void ahci_eng_timeout(struct ata_port *ap)
        struct ata_queued_cmd *qc;
        unsigned long flags;
 
-       DPRINTK("ENTER\n");
+       printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id);
 
        spin_lock_irqsave(&host_set->lock, flags);
 
-       ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
-
        qc = ata_qc_from_tag(ap, ap->active_tag);
        if (!qc) {
                printk(KERN_ERR "ata%u: BUG: timeout without command\n",
                       ap->id);
        } else {
+               ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
+
                /* hack alert!  We cannot use the supplied completion
                 * function from inside the ->eh_strategy_handler() thread.
                 * 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)
        }
 
        if (status & PORT_IRQ_FATAL) {
-               ahci_intr_error(ap, status);
+               unsigned int err_mask;
+               if (status & PORT_IRQ_TF_ERR)
+                       err_mask = AC_ERR_DEV;
+               else if (status & PORT_IRQ_IF_ERR)
+                       err_mask = AC_ERR_ATA_BUS;
+               else
+                       err_mask = AC_ERR_HOST_BUS;
+
+               /* command processing has stopped due to error; restart */
+               ahci_restart_port(ap, status);
+
                if (qc)
-                       ata_qc_complete(qc, AC_ERR_OTHER);
+                       ata_qc_complete(qc, err_mask);
        }
 
        return 1;