]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/ata/sata_sil.c
sata_sil: ignore and clear spurious IRQs while executing commands by polling
[karo-tx-linux.git] / drivers / ata / sata_sil.c
index 907faa87239b20d59515b4bc5a3faf904ed98a55..baeb34404dbeb1e3caf69f0ee1d632616745d8ca 100644 (file)
@@ -56,7 +56,7 @@ enum {
        SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
        SIL_FLAG_MOD15WRITE     = (1 << 30),
 
-       SIL_DFL_HOST_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+       SIL_DFL_PORT_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME,
 
        /*
@@ -109,25 +109,27 @@ enum {
 };
 
 static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+#ifdef CONFIG_PM
 static int sil_pci_device_resume(struct pci_dev *pdev);
+#endif
 static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void sil_post_set_mode (struct ata_port *ap);
-static irqreturn_t sil_interrupt(int irq, void *dev_instance,
-                                struct pt_regs *regs);
+static irqreturn_t sil_interrupt(int irq, void *dev_instance);
 static void sil_freeze(struct ata_port *ap);
 static void sil_thaw(struct ata_port *ap);
 
 
 static const struct pci_device_id sil_pci_tbl[] = {
-       { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
-       { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
-       { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-       { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
-       { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
+       { PCI_VDEVICE(CMD, 0x3112), sil_3112 },
+       { PCI_VDEVICE(CMD, 0x0240), sil_3112 },
+       { PCI_VDEVICE(CMD, 0x3512), sil_3512 },
+       { PCI_VDEVICE(CMD, 0x3114), sil_3114 },
+       { PCI_VDEVICE(ATI, 0x436e), sil_3112 },
+       { PCI_VDEVICE(ATI, 0x4379), sil_3112_no_sata_irq },
+       { PCI_VDEVICE(ATI, 0x437a), sil_3112_no_sata_irq },
+
        { }     /* terminate list */
 };
 
@@ -157,8 +159,10 @@ static struct pci_driver sil_pci_driver = {
        .id_table               = sil_pci_tbl,
        .probe                  = sil_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ata_pci_device_suspend,
        .resume                 = sil_pci_device_resume,
+#endif
 };
 
 static struct scsi_host_template sil_sht = {
@@ -214,7 +218,7 @@ static const struct ata_port_info sil_port_info[] = {
        /* sil_3112 */
        {
                .sht            = &sil_sht,
-               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE,
+               .flags          = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -223,7 +227,7 @@ static const struct ata_port_info sil_port_info[] = {
        /* sil_3112_no_sata_irq */
        {
                .sht            = &sil_sht,
-               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE |
+               .flags          = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE |
                                  SIL_FLAG_NO_SATA_IRQ,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
@@ -233,7 +237,7 @@ static const struct ata_port_info sil_port_info[] = {
        /* sil_3512 */
        {
                .sht            = &sil_sht,
-               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
+               .flags          = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -242,7 +246,7 @@ static const struct ata_port_info sil_port_info[] = {
        /* sil_3114 */
        {
                .sht            = &sil_sht,
-               .host_flags     = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
+               .flags          = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -291,10 +295,9 @@ static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
 
 static void sil_post_set_mode (struct ata_port *ap)
 {
-       struct ata_host_set *host_set = ap->host_set;
+       struct ata_host *host = ap->host;
        struct ata_device *dev;
-       void __iomem *addr =
-               host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
+       void __iomem *addr = host->mmio_base + sil_port[ap->port_no].xfer_mode;
        u32 tmp, dev_mode[2];
        unsigned int i;
 
@@ -346,13 +349,14 @@ static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
 
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
-       void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
+       void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
        if (mmio)
                writel(val, mmio);
 }
 
 static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
 {
+       struct ata_eh_info *ehi = &ap->eh_info;
        struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
        u8 status;
 
@@ -379,9 +383,15 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
                goto freeze;
        }
 
-       if (unlikely(!qc || qc->tf.ctl & ATA_NIEN))
+       if (unlikely(!qc))
                goto freeze;
 
+       if (unlikely(qc->tf.flags & ATA_TFLAG_POLLING)) {
+               /* this sometimes happens, just clear IRQ */
+               ata_chk_status(ap);
+               return;
+       }
+
        /* Check whether we are expecting interrupt in this state */
        switch (ap->hsm_task_state) {
        case HSM_ST_FIRST:
@@ -425,6 +435,10 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
        /* kick HSM in the ass */
        ata_hsm_move(ap, qc, status, 0);
 
+       if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
+                                      qc->tf.protocol == ATA_PROT_ATAPI_DMA))
+               ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
+
        return;
 
  err_hsm:
@@ -433,18 +447,17 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
        ata_port_freeze(ap);
 }
 
-static irqreturn_t sil_interrupt(int irq, void *dev_instance,
-                                struct pt_regs *regs)
+static irqreturn_t sil_interrupt(int irq, void *dev_instance)
 {
-       struct ata_host_set *host_set = dev_instance;
-       void __iomem *mmio_base = host_set->mmio_base;
+       struct ata_host *host = dev_instance;
+       void __iomem *mmio_base = host->mmio_base;
        int handled = 0;
        int i;
 
-       spin_lock(&host_set->lock);
+       spin_lock(&host->lock);
 
-       for (i = 0; i < host_set->n_ports; i++) {
-               struct ata_port *ap = host_set->ports[i];
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap = host->ports[i];
                u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
 
                if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
@@ -462,14 +475,14 @@ static irqreturn_t sil_interrupt(int irq, void *dev_instance,
                handled = 1;
        }
 
-       spin_unlock(&host_set->lock);
+       spin_unlock(&host->lock);
 
        return IRQ_RETVAL(handled);
 }
 
 static void sil_freeze(struct ata_port *ap)
 {
-       void __iomem *mmio_base = ap->host_set->mmio_base;
+       void __iomem *mmio_base = ap->host->mmio_base;
        u32 tmp;
 
        /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */
@@ -484,7 +497,7 @@ static void sil_freeze(struct ata_port *ap)
 
 static void sil_thaw(struct ata_port *ap)
 {
-       void __iomem *mmio_base = ap->host_set->mmio_base;
+       void __iomem *mmio_base = ap->host->mmio_base;
        u32 tmp;
 
        /* clear IRQ */
@@ -532,6 +545,7 @@ static void sil_thaw(struct ata_port *ap)
  */
 static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
+       int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
        unsigned int n, quirks = 0;
        unsigned char model_num[41];
 
@@ -547,23 +561,25 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
        if (slow_down ||
            ((ap->flags & SIL_FLAG_MOD15WRITE) &&
             (quirks & SIL_QUIRK_MOD15WRITE))) {
-               ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix "
-                              "(mod15write workaround)\n");
+               if (print_info)
+                       ata_dev_printk(dev, KERN_INFO, "applying Seagate "
+                                      "errata fix (mod15write workaround)\n");
                dev->max_sectors = 15;
                return;
        }
 
        /* limit to udma5 */
        if (quirks & SIL_QUIRK_UDMA5MAX) {
-               ata_dev_printk(dev, KERN_INFO,
-                              "applying Maxtor errata fix %s\n", model_num);
+               if (print_info)
+                       ata_dev_printk(dev, KERN_INFO, "applying Maxtor "
+                                      "errata fix %s\n", model_num);
                dev->udma_mask &= ATA_UDMA5;
                return;
        }
 }
 
 static void sil_init_controller(struct pci_dev *pdev,
-                               int n_ports, unsigned long host_flags,
+                               int n_ports, unsigned long port_flags,
                                void __iomem *mmio_base)
 {
        u8 cls;
@@ -583,7 +599,7 @@ static void sil_init_controller(struct pci_dev *pdev,
                           "cache line size not set.  Driver may not function\n");
 
        /* Apply R_ERR on DMA activate FIS errata workaround */
-       if (host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
+       if (port_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
                int cnt;
 
                for (i = 0, cnt = 0; i < n_ports; i++) {
@@ -654,7 +670,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
                probe_ent->irq = pdev->irq;
                probe_ent->irq_flags = IRQF_SHARED;
-       probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
+       probe_ent->port_flags = sil_port_info[ent->driver_data].flags;
 
        mmio_base = pci_iomap(pdev, 5, 0);
        if (mmio_base == NULL) {
@@ -675,7 +691,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                ata_std_ports(&probe_ent->port[i]);
        }
 
-       sil_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
+       sil_init_controller(pdev, probe_ent->n_ports, probe_ent->port_flags,
                            mmio_base);
 
        pci_set_master(pdev);
@@ -696,17 +712,19 @@ err_out:
        return rc;
 }
 
+#ifdef CONFIG_PM
 static int sil_pci_device_resume(struct pci_dev *pdev)
 {
-       struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
 
        ata_pci_device_do_resume(pdev);
-       sil_init_controller(pdev, host_set->n_ports, host_set->ports[0]->flags,
-                           host_set->mmio_base);
-       ata_host_set_resume(host_set);
+       sil_init_controller(pdev, host->n_ports, host->ports[0]->flags,
+                           host->mmio_base);
+       ata_host_resume(host);
 
        return 0;
 }
+#endif
 
 static int __init sil_init(void)
 {