]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/ahci.c
[PATCH] Fix sg_page_malloc() memset
[linux-2.6-omap-h63xx.git] / drivers / scsi / ahci.c
index c710a7def7a7fd2024ea18be6ac7cfe31a382624..d113290b5fc01ccf977902881eb60b2f699c4bc1 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 {
@@ -214,7 +214,6 @@ static struct scsi_host_template ahci_sht = {
        .dma_boundary           = AHCI_DMA_BOUNDARY,
        .slave_configure        = ata_scsi_slave_config,
        .bios_param             = ata_std_bios_param,
-       .ordered_flush          = 1,
 };
 
 static const struct ata_port_operations ahci_ops = {
@@ -243,7 +242,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 +557,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,13 +614,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 (%s%s%s%s)\n",
-              ap->id,
-              irq_stat & PORT_IRQ_TF_ERR ? "taskf " : "",
-              irq_stat & PORT_IRQ_HBUS_ERR ? "hbus " : "",
-              irq_stat & PORT_IRQ_HBUS_DATA_ERR ? "hbus_data " : "",
-              irq_stat & PORT_IRQ_IF_ERR ? "if " : "");
 }
 
 static void ahci_eng_timeout(struct ata_port *ap)
@@ -619,7 +624,7 @@ 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);
 
@@ -628,7 +633,7 @@ static void ahci_eng_timeout(struct ata_port *ap)
                printk(KERN_ERR "ata%u: BUG: timeout without command\n",
                       ap->id);
        } else {
-               ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT));
+               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.
@@ -637,7 +642,8 @@ static void ahci_eng_timeout(struct ata_port *ap)
                 * not being called from the SCSI EH.
                 */
                qc->scsidone = scsi_finish_command;
-               ata_qc_complete(qc, AC_ERR_OTHER);
+               qc->err_mask |= AC_ERR_OTHER;
+               ata_qc_complete(qc);
        }
 
        spin_unlock_irqrestore(&host_set->lock, flags);
@@ -658,7 +664,8 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
        ci = readl(port_mmio + PORT_CMD_ISSUE);
        if (likely((ci & 0x1) == 0)) {
                if (qc) {
-                       ata_qc_complete(qc, 0);
+                       assert(qc->err_mask == 0);
+                       ata_qc_complete(qc);
                        qc = NULL;
                }
        }
@@ -672,10 +679,13 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
                else
                        err_mask = AC_ERR_HOST_BUS;
 
-               if (err_mask != AC_ERR_DEV)
-                       ahci_intr_error(ap, status);
-               if (qc)
-                       ata_qc_complete(qc, err_mask);
+               /* command processing has stopped due to error; restart */
+               ahci_restart_port(ap, status);
+
+               if (qc) {
+                       qc->err_mask |= AC_ERR_OTHER;
+                       ata_qc_complete(qc);
+               }
        }
 
        return 1;