ahci.c: remove non-existing SB600 raid id (re-send)
[powerpc.git] / drivers / ata / ahci.c
index 334f54c..436de03 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "ahci"
-#define DRV_VERSION    "2.0"
+#define DRV_VERSION    "2.1"
 
 
 enum {
@@ -80,6 +80,7 @@ enum {
        board_ahci_pi           = 1,
        board_ahci_vt8251       = 2,
        board_ahci_ign_iferr    = 3,
+       board_ahci_sb600        = 4,
 
        /* global controller registers */
        HOST_CAP                = 0x00, /* host capabilities */
@@ -168,6 +169,7 @@ enum {
        AHCI_FLAG_NO_NCQ                = (1 << 24),
        AHCI_FLAG_IGN_IRQ_IF_ERR        = (1 << 25), /* ignore IRQ_IF_ERR */
        AHCI_FLAG_HONOR_PI              = (1 << 26), /* honor PORTS_IMPL */
+       AHCI_FLAG_IGN_SERR_INTERNAL     = (1 << 27), /* ignore SERR_INTERNAL */
 };
 
 struct ahci_cmd_hdr {
@@ -186,8 +188,10 @@ struct ahci_sg {
 };
 
 struct ahci_host_priv {
-       u32                     cap;    /* cache of HOST_CAP register */
-       u32                     port_map; /* cache of HOST_PORTS_IMPL reg */
+       u32                     cap;            /* cap to use */
+       u32                     port_map;       /* port map to use */
+       u32                     saved_cap;      /* saved initial cap */
+       u32                     saved_port_map; /* saved initial port_map */
 };
 
 struct ahci_port_priv {
@@ -200,6 +204,7 @@ struct ahci_port_priv {
        /* for NCQ spurious interrupt analysis */
        unsigned int            ncq_saw_d2h:1;
        unsigned int            ncq_saw_dmas:1;
+       unsigned int            ncq_saw_sdb:1;
 };
 
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
@@ -218,10 +223,12 @@ static void ahci_thaw(struct ata_port *ap);
 static void ahci_error_handler(struct ata_port *ap);
 static void ahci_vt8251_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+#ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
 static int ahci_port_resume(struct ata_port *ap);
 static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int ahci_pci_device_resume(struct pci_dev *pdev);
+#endif
 
 static struct scsi_host_template ahci_sht = {
        .module                 = THIS_MODULE,
@@ -240,8 +247,10 @@ static struct scsi_host_template ahci_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+#ifdef CONFIG_PM
        .suspend                = ata_scsi_device_suspend,
        .resume                 = ata_scsi_device_resume,
+#endif
 };
 
 static const struct ata_port_operations ahci_ops = {
@@ -270,8 +279,10 @@ static const struct ata_port_operations ahci_ops = {
        .error_handler          = ahci_error_handler,
        .post_internal_cmd      = ahci_post_internal_cmd,
 
+#ifdef CONFIG_PM
        .port_suspend           = ahci_port_suspend,
        .port_resume            = ahci_port_resume,
+#endif
 
        .port_start             = ahci_port_start,
        .port_stop              = ahci_port_stop,
@@ -303,8 +314,10 @@ static const struct ata_port_operations ahci_vt8251_ops = {
        .error_handler          = ahci_vt8251_error_handler,
        .post_internal_cmd      = ahci_post_internal_cmd,
 
+#ifdef CONFIG_PM
        .port_suspend           = ahci_port_suspend,
        .port_resume            = ahci_port_resume,
+#endif
 
        .port_start             = ahci_port_start,
        .port_stop              = ahci_port_stop,
@@ -353,6 +366,18 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
                .port_ops       = &ahci_ops,
        },
+       /* board_ahci_sb600 */
+       {
+               .sht            = &ahci_sht,
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 ATA_FLAG_SKIP_D2H_BSY |
+                                 AHCI_FLAG_IGN_SERR_INTERNAL,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &ahci_ops,
+       },
+
 };
 
 static const struct pci_device_id ahci_pci_tbl[] = {
@@ -380,20 +405,17 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */
+       { PCI_VDEVICE(INTEL, 0x292c), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */
        { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */
        { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */
 
-       /* JMicron */
-       { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */
-       { PCI_VDEVICE(JMICRON, 0x2361), board_ahci_ign_iferr }, /* JMB361 */
-       { PCI_VDEVICE(JMICRON, 0x2363), board_ahci_ign_iferr }, /* JMB363 */
-       { PCI_VDEVICE(JMICRON, 0x2365), board_ahci_ign_iferr }, /* JMB365 */
-       { PCI_VDEVICE(JMICRON, 0x2366), board_ahci_ign_iferr }, /* JMB366 */
+       /* JMicron 360/1/3/5/6, match class to avoid IDE function */
+       { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
 
        /* ATI */
-       { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */
-       { PCI_VDEVICE(ATI, 0x4381), board_ahci }, /* ATI SB600 raid */
+       { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
 
        /* VIA */
        { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
@@ -438,8 +460,10 @@ static struct pci_driver ahci_pci_driver = {
        .id_table               = ahci_pci_tbl,
        .probe                  = ahci_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
        .suspend                = ahci_pci_device_suspend,
        .resume                 = ahci_pci_device_resume,
+#endif
 };
 
 
@@ -454,6 +478,91 @@ static inline void __iomem *ahci_port_base(void __iomem *base,
        return base + 0x100 + (port * 0x80);
 }
 
+/**
+ *     ahci_save_initial_config - Save and fixup initial config values
+ *     @probe_ent: probe_ent of target device
+ *
+ *     Some registers containing configuration info might be setup by
+ *     BIOS and might be cleared on reset.  This function saves the
+ *     initial values of those registers into @hpriv such that they
+ *     can be restored after controller reset.
+ *
+ *     If inconsistent, config values are fixed up by this function.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ahci_save_initial_config(struct ata_probe_ent *probe_ent)
+{
+       struct ahci_host_priv *hpriv = probe_ent->private_data;
+       void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
+       u32 cap, port_map;
+       int i;
+
+       /* Values prefixed with saved_ are written back to host after
+        * reset.  Values without are used for driver operation.
+        */
+       hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
+       hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
+
+       /* fixup zero port_map */
+       if (!port_map) {
+               port_map = (1 << ahci_nr_ports(hpriv->cap)) - 1;
+               dev_printk(KERN_WARNING, probe_ent->dev,
+                          "PORTS_IMPL is zero, forcing 0x%x\n", port_map);
+
+               /* write the fixed up value to the PI register */
+               hpriv->saved_port_map = port_map;
+       }
+
+       /* cross check port_map and cap.n_ports */
+       if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
+               u32 tmp_port_map = port_map;
+               int n_ports = ahci_nr_ports(cap);
+
+               for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
+                       if (tmp_port_map & (1 << i)) {
+                               n_ports--;
+                               tmp_port_map &= ~(1 << i);
+                       }
+               }
+
+               /* Whine if inconsistent.  No need to update cap.
+                * port_map is used to determine number of ports.
+                */
+               if (n_ports || tmp_port_map)
+                       dev_printk(KERN_WARNING, probe_ent->dev,
+                                  "nr_ports (%u) and implemented port map "
+                                  "(0x%x) don't match\n",
+                                  ahci_nr_ports(cap), port_map);
+       } else {
+               /* fabricate port_map from cap.nr_ports */
+               port_map = (1 << ahci_nr_ports(cap)) - 1;
+       }
+
+       /* record values to use during operation */
+       hpriv->cap = cap;
+       hpriv->port_map = port_map;
+}
+
+/**
+ *     ahci_restore_initial_config - Restore initial config
+ *     @mmio: MMIO base for the host
+ *     @hpriv: host private data
+ *
+ *     Restore initial config stored by ahci_save_initial_config().
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ahci_restore_initial_config(void __iomem *mmio,
+                                       struct ahci_host_priv *hpriv)
+{
+       writel(hpriv->saved_cap, mmio + HOST_CAP);
+       writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
+       (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
+}
+
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
 {
        unsigned int sc_reg;
@@ -579,6 +688,7 @@ static void ahci_power_up(void __iomem *port_mmio, u32 cap)
        writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
+#ifdef CONFIG_PM
 static void ahci_power_down(void __iomem *port_mmio, u32 cap)
 {
        u32 cmd, scontrol;
@@ -596,6 +706,7 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
        cmd &= ~PORT_CMD_SPIN_UP;
        writel(cmd, port_mmio + PORT_CMD);
 }
+#endif
 
 static void ahci_init_port(void __iomem *port_mmio, u32 cap,
                           dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
@@ -628,12 +739,10 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
        return 0;
 }
 
-static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
+static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev,
+                                struct ahci_host_priv *hpriv)
 {
-       u32 cap_save, impl_save, tmp;
-
-       cap_save = readl(mmio + HOST_CAP);
-       impl_save = readl(mmio + HOST_PORTS_IMPL);
+       u32 tmp;
 
        /* global controller reset */
        tmp = readl(mmio + HOST_CTL);
@@ -658,18 +767,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
        writel(HOST_AHCI_EN, mmio + HOST_CTL);
        (void) readl(mmio + HOST_CTL);  /* flush */
 
-       /* These write-once registers are normally cleared on reset.
-        * Restore BIOS values... which we HOPE were present before
-        * reset.
-        */
-       if (!impl_save) {
-               impl_save = (1 << ahci_nr_ports(cap_save)) - 1;
-               dev_printk(KERN_WARNING, &pdev->dev,
-                          "PORTS_IMPL is zero, forcing 0x%x\n", impl_save);
-       }
-       writel(cap_save, mmio + HOST_CAP);
-       writel(impl_save, mmio + HOST_PORTS_IMPL);
-       (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
+       /* some registers might be cleared on reset.  restore initial values */
+       ahci_restore_initial_config(mmio, hpriv);
 
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
                u16 tmp16;
@@ -1056,8 +1155,11 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
        if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR)
                irq_stat &= ~PORT_IRQ_IF_ERR;
 
-       if (irq_stat & PORT_IRQ_TF_ERR)
+       if (irq_stat & PORT_IRQ_TF_ERR) {
                err_mask |= AC_ERR_DEV;
+               if (ap->flags & AHCI_FLAG_IGN_SERR_INTERNAL)
+                       serror &= ~SERR_INTERNAL;
+       }
 
        if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
                err_mask |= AC_ERR_HOST_BUS;
@@ -1160,23 +1262,31 @@ static void ahci_host_intr(struct ata_port *ap)
        }
 
        if (status & PORT_IRQ_SDB_FIS) {
-               /* SDB FIS containing spurious completions might be
-                * dangerous, whine and fail commands with HSM
-                * violation.  EH will turn off NCQ after several such
-                * failures.
-                */
                const __le32 *f = pp->rx_fis + RX_FIS_SDB;
 
-               ata_ehi_push_desc(ehi, "spurious completion during NCQ "
-                                 "issue=0x%x SAct=0x%x FIS=%08x:%08x",
-                                 readl(port_mmio + PORT_CMD_ISSUE),
-                                 readl(port_mmio + PORT_SCR_ACT),
-                                 le32_to_cpu(f[0]), le32_to_cpu(f[1]));
-
-               ehi->err_mask |= AC_ERR_HSM;
-               ehi->action |= ATA_EH_SOFTRESET;
-               ata_port_freeze(ap);
-
+               if (le32_to_cpu(f[1])) {
+                       /* SDB FIS containing spurious completions
+                        * might be dangerous, whine and fail commands
+                        * with HSM violation.  EH will turn off NCQ
+                        * after several such failures.
+                        */
+                       ata_ehi_push_desc(ehi,
+                               "spurious completions during NCQ "
+                               "issue=0x%x SAct=0x%x FIS=%08x:%08x",
+                               readl(port_mmio + PORT_CMD_ISSUE),
+                               readl(port_mmio + PORT_SCR_ACT),
+                               le32_to_cpu(f[0]), le32_to_cpu(f[1]));
+                       ehi->err_mask |= AC_ERR_HSM;
+                       ehi->action |= ATA_EH_SOFTRESET;
+                       ata_port_freeze(ap);
+               } else {
+                       if (!pp->ncq_saw_sdb)
+                               ata_port_printk(ap, KERN_INFO,
+                                       "spurious SDB FIS %08x:%08x during NCQ, "
+                                       "this message won't be printed again\n",
+                                       le32_to_cpu(f[0]), le32_to_cpu(f[1]));
+                       pp->ncq_saw_sdb = 1;
+               }
                known_irq = 1;
        }
 
@@ -1319,16 +1429,14 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
        void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
        void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 
-       if (qc->flags & ATA_QCFLAG_FAILED)
-               qc->err_mask |= AC_ERR_OTHER;
-
-       if (qc->err_mask) {
+       if (qc->flags & ATA_QCFLAG_FAILED) {
                /* make DMA engine forget about the failed command */
                ahci_stop_engine(port_mmio);
                ahci_start_engine(port_mmio);
        }
 }
 
+#ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
 {
        struct ahci_host_priv *hpriv = ap->host->private_data;
@@ -1395,7 +1503,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
                return rc;
 
        if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-               rc = ahci_reset_controller(mmio, pdev);
+               rc = ahci_reset_controller(mmio, pdev, hpriv);
                if (rc)
                        return rc;
 
@@ -1407,6 +1515,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
 
        return 0;
 }
+#endif
 
 static int ahci_port_start(struct ata_port *ap)
 {
@@ -1502,43 +1611,18 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
        struct ahci_host_priv *hpriv = probe_ent->private_data;
        struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
        void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
-       unsigned int i, cap_n_ports, using_dac;
+       unsigned int i, using_dac;
        int rc;
 
-       rc = ahci_reset_controller(mmio, pdev);
+       rc = ahci_reset_controller(mmio, pdev, hpriv);
        if (rc)
                return rc;
 
-       hpriv->cap = readl(mmio + HOST_CAP);
-       hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
-       cap_n_ports = ahci_nr_ports(hpriv->cap);
+       probe_ent->n_ports = fls(hpriv->port_map);
+       probe_ent->dummy_port_mask = ~hpriv->port_map;
 
        VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
-               hpriv->cap, hpriv->port_map, cap_n_ports);
-
-       if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
-               unsigned int n_ports = cap_n_ports;
-               u32 port_map = hpriv->port_map;
-               int max_port = 0;
-
-               for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
-                       if (port_map & (1 << i)) {
-                               n_ports--;
-                               port_map &= ~(1 << i);
-                               max_port = i;
-                       } else
-                               probe_ent->dummy_port_mask |= 1 << i;
-               }
-
-               if (n_ports || port_map)
-                       dev_printk(KERN_WARNING, &pdev->dev,
-                                  "nr_ports (%u) and implemented port map "
-                                  "(0x%x) don't match\n",
-                                  cap_n_ports, hpriv->port_map);
-
-               probe_ent->n_ports = max_port + 1;
-       } else
-               probe_ent->n_ports = cap_n_ports;
+               hpriv->cap, hpriv->port_map, probe_ent->n_ports);
 
        using_dac = hpriv->cap & HOST_CAP_64;
        if (using_dac &&
@@ -1665,13 +1749,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-       if (pdev->vendor == PCI_VENDOR_ID_JMICRON) {
-               /* Function 1 is the PATA controller except on the 368, where
-                  we are not AHCI anyway */
-               if (PCI_FUNC(pdev->devfn))
-                       return -ENODEV;
-       }
-
        rc = pcim_enable_device(pdev);
        if (rc)
                return rc;
@@ -1708,6 +1785,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        probe_ent->private_data = hpriv;
 
        /* initialize adapter */
+       ahci_save_initial_config(probe_ent);
+
        rc = ahci_host_init(probe_ent);
        if (rc)
                return rc;