Blackfin: fix cache Kconfig typo
[safe/jmp/linux-2.6] / drivers / ata / ahci.c
index a4e4cf1..a3241a1 100644 (file)
@@ -122,6 +122,7 @@ enum {
        HOST_VERSION            = 0x10, /* AHCI spec. version compliancy */
        HOST_EM_LOC             = 0x1c, /* Enclosure Management location */
        HOST_EM_CTL             = 0x20, /* Enclosure Management Control */
+       HOST_CAP2               = 0x24, /* host capabilities, extended */
 
        /* HOST_CTL bits */
        HOST_RESET              = (1 << 0),  /* reset controller; self-clear */
@@ -129,16 +130,29 @@ enum {
        HOST_AHCI_EN            = (1 << 31), /* AHCI enabled */
 
        /* HOST_CAP bits */
+       HOST_CAP_SXS            = (1 << 5),  /* Supports External SATA */
        HOST_CAP_EMS            = (1 << 6),  /* Enclosure Management support */
-       HOST_CAP_SSC            = (1 << 14), /* Slumber capable */
+       HOST_CAP_CCC            = (1 << 7),  /* Command Completion Coalescing */
+       HOST_CAP_PART           = (1 << 13), /* Partial state capable */
+       HOST_CAP_SSC            = (1 << 14), /* Slumber state capable */
+       HOST_CAP_PIO_MULTI      = (1 << 15), /* PIO multiple DRQ support */
+       HOST_CAP_FBS            = (1 << 16), /* FIS-based switching support */
        HOST_CAP_PMP            = (1 << 17), /* Port Multiplier support */
+       HOST_CAP_ONLY           = (1 << 18), /* Supports AHCI mode only */
        HOST_CAP_CLO            = (1 << 24), /* Command List Override support */
+       HOST_CAP_LED            = (1 << 25), /* Supports activity LED */
        HOST_CAP_ALPM           = (1 << 26), /* Aggressive Link PM support */
        HOST_CAP_SSS            = (1 << 27), /* Staggered Spin-up */
+       HOST_CAP_MPS            = (1 << 28), /* Mechanical presence switch */
        HOST_CAP_SNTF           = (1 << 29), /* SNotification register */
        HOST_CAP_NCQ            = (1 << 30), /* Native Command Queueing */
        HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA) support */
 
+       /* HOST_CAP2 bits */
+       HOST_CAP2_BOH           = (1 << 0),  /* BIOS/OS handoff supported */
+       HOST_CAP2_NVMHCI        = (1 << 1),  /* NVMHCI supported */
+       HOST_CAP2_APST          = (1 << 2),  /* Automatic partial to slumber */
+
        /* registers for each SATA port */
        PORT_LST_ADDR           = 0x00, /* command list DMA addr */
        PORT_LST_ADDR_HI        = 0x04, /* command list DMA addr hi */
@@ -267,8 +281,10 @@ struct ahci_em_priv {
 struct ahci_host_priv {
        unsigned int            flags;          /* AHCI_HFLAG_* */
        u32                     cap;            /* cap to use */
+       u32                     cap2;           /* cap2 to use */
        u32                     port_map;       /* port map to use */
        u32                     saved_cap;      /* saved initial cap */
+       u32                     saved_cap2;     /* saved initial cap2 */
        u32                     saved_port_map; /* saved initial port_map */
        u32                     em_loc; /* enclosure management location */
 };
@@ -331,12 +347,15 @@ static void ahci_init_sw_activity(struct ata_link *link);
 
 static ssize_t ahci_show_host_caps(struct device *dev,
                                   struct device_attribute *attr, char *buf);
+static ssize_t ahci_show_host_cap2(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
 static ssize_t ahci_show_host_version(struct device *dev,
                                      struct device_attribute *attr, char *buf);
 static ssize_t ahci_show_port_cmd(struct device *dev,
                                  struct device_attribute *attr, char *buf);
 
 DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
+DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
 DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
 DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
 
@@ -345,6 +364,7 @@ static struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_em_message_type,
        &dev_attr_em_message,
        &dev_attr_ahci_host_caps,
+       &dev_attr_ahci_host_cap2,
        &dev_attr_ahci_host_version,
        &dev_attr_ahci_port_cmd,
        NULL
@@ -447,7 +467,8 @@ static const struct ata_port_info ahci_port_info[] = {
        [board_ahci_sb600] =
        {
                AHCI_HFLAGS     (AHCI_HFLAG_IGN_SERR_INTERNAL |
-                                AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255),
+                                AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
+                                AHCI_HFLAG_32BIT_ONLY),
                .flags          = AHCI_FLAG_COMMON,
                .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
@@ -553,6 +574,12 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
        { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
 
+       /* AMD */
+       { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
+       /* AMD is using RAID class only for ahci controllers */
+       { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
+
        /* VIA */
        { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
        { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
@@ -578,6 +605,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq },     /* MCP67 */
        { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq },     /* MCP67 */
        { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_yesncq },     /* Linux ID */
        { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq },     /* MCP73 */
        { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq },     /* MCP73 */
        { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq },     /* MCP73 */
@@ -726,6 +754,16 @@ static ssize_t ahci_show_host_caps(struct device *dev,
        return sprintf(buf, "%x\n", hpriv->cap);
 }
 
+static ssize_t ahci_show_host_cap2(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct ata_port *ap = ata_shost_to_port(shost);
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+
+       return sprintf(buf, "%x\n", hpriv->cap2);
+}
+
 static ssize_t ahci_show_host_version(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
@@ -765,7 +803,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
                                     struct ahci_host_priv *hpriv)
 {
        void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
-       u32 cap, port_map;
+       u32 cap, cap2, vers, port_map;
        int i;
        int mv;
 
@@ -778,6 +816,14 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
        hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
        hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
 
+       /* CAP2 register is only defined for AHCI 1.2 and later */
+       vers = readl(mmio + HOST_VERSION);
+       if ((vers >> 16) > 1 ||
+          ((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200))
+               hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2);
+       else
+               hpriv->saved_cap2 = cap2 = 0;
+
        /* some chips have errata preventing 64bit use */
        if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
                dev_printk(KERN_INFO, &pdev->dev,
@@ -863,6 +909,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
 
        /* record values to use during operation */
        hpriv->cap = cap;
+       hpriv->cap2 = cap2;
        hpriv->port_map = port_map;
 }
 
@@ -881,6 +928,8 @@ static void ahci_restore_initial_config(struct ata_host *host)
        void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 
        writel(hpriv->saved_cap, mmio + HOST_CAP);
+       if (hpriv->saved_cap2)
+               writel(hpriv->saved_cap2, mmio + HOST_CAP2);
        writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
        (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
 }
@@ -1628,7 +1677,7 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
        pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
 }
 
-static int ahci_kick_engine(struct ata_port *ap, int force_restart)
+static int ahci_kick_engine(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
        struct ahci_host_priv *hpriv = ap->host->private_data;
@@ -1636,18 +1685,16 @@ static int ahci_kick_engine(struct ata_port *ap, int force_restart)
        u32 tmp;
        int busy, rc;
 
-       /* do we need to kick the port? */
-       busy = status & (ATA_BUSY | ATA_DRQ);
-       if (!busy && !force_restart)
-               return 0;
-
        /* stop engine */
        rc = ahci_stop_engine(ap);
        if (rc)
                goto out_restart;
 
-       /* need to do CLO? */
-       if (!busy) {
+       /* need to do CLO?
+        * always do CLO if PMP is attached (AHCI-1.3 9.2)
+        */
+       busy = status & (ATA_BUSY | ATA_DRQ);
+       if (!busy && !sata_pmp_attached(ap)) {
                rc = 0;
                goto out_restart;
        }
@@ -1695,7 +1742,7 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
                tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
                                        1, timeout_msec);
                if (tmp & 0x1) {
-                       ahci_kick_engine(ap, 1);
+                       ahci_kick_engine(ap);
                        return -EBUSY;
                }
        } else
@@ -1718,7 +1765,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
        DPRINTK("ENTER\n");
 
        /* prepare for SRST (AHCI-1.1 10.4.1) */
-       rc = ahci_kick_engine(ap, 1);
+       rc = ahci_kick_engine(ap);
        if (rc && rc != -EOPNOTSUPP)
                ata_link_printk(link, KERN_WARNING,
                                "failed to reset engine (errno=%d)\n", rc);
@@ -1934,7 +1981,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
                rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
                                          ahci_check_ready);
                if (rc)
-                       ahci_kick_engine(ap, 0);
+                       ahci_kick_engine(ap);
        }
        return rc;
 }
@@ -2315,7 +2362,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 
        /* make DMA engine forget about the failed command */
        if (qc->flags & ATA_QCFLAG_FAILED)
-               ahci_kick_engine(ap, 1);
+               ahci_kick_engine(ap);
 }
 
 static void ahci_pmp_attach(struct ata_port *ap)
@@ -2530,13 +2577,14 @@ static void ahci_print_info(struct ata_host *host)
        struct ahci_host_priv *hpriv = host->private_data;
        struct pci_dev *pdev = to_pci_dev(host->dev);
        void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-       u32 vers, cap, impl, speed;
+       u32 vers, cap, cap2, impl, speed;
        const char *speed_s;
        u16 cc;
        const char *scc_s;
 
        vers = readl(mmio + HOST_VERSION);
        cap = hpriv->cap;
+       cap2 = hpriv->cap2;
        impl = hpriv->port_map;
 
        speed = (cap >> 20) & 0xf;
@@ -2579,25 +2627,29 @@ static void ahci_print_info(struct ata_host *host)
                "flags: "
                "%s%s%s%s%s%s%s"
                "%s%s%s%s%s%s%s"
-               "%s\n"
+               "%s%s%s%s%s%s\n"
                ,
 
-               cap & (1 << 31) ? "64bit " : "",
-               cap & (1 << 30) ? "ncq " : "",
-               cap & (1 << 29) ? "sntf " : "",
-               cap & (1 << 28) ? "ilck " : "",
-               cap & (1 << 27) ? "stag " : "",
-               cap & (1 << 26) ? "pm " : "",
-               cap & (1 << 25) ? "led " : "",
-
-               cap & (1 << 24) ? "clo " : "",
-               cap & (1 << 19) ? "nz " : "",
-               cap & (1 << 18) ? "only " : "",
-               cap & (1 << 17) ? "pmp " : "",
-               cap & (1 << 15) ? "pio " : "",
-               cap & (1 << 14) ? "slum " : "",
-               cap & (1 << 13) ? "part " : "",
-               cap & (1 << 6) ? "ems ": ""
+               cap & HOST_CAP_64 ? "64bit " : "",
+               cap & HOST_CAP_NCQ ? "ncq " : "",
+               cap & HOST_CAP_SNTF ? "sntf " : "",
+               cap & HOST_CAP_MPS ? "ilck " : "",
+               cap & HOST_CAP_SSS ? "stag " : "",
+               cap & HOST_CAP_ALPM ? "pm " : "",
+               cap & HOST_CAP_LED ? "led " : "",
+               cap & HOST_CAP_CLO ? "clo " : "",
+               cap & HOST_CAP_ONLY ? "only " : "",
+               cap & HOST_CAP_PMP ? "pmp " : "",
+               cap & HOST_CAP_FBS ? "fbs " : "",
+               cap & HOST_CAP_PIO_MULTI ? "pio " : "",
+               cap & HOST_CAP_SSC ? "slum " : "",
+               cap & HOST_CAP_PART ? "part " : "",
+               cap & HOST_CAP_CCC ? "ccc " : "",
+               cap & HOST_CAP_EMS ? "ems " : "",
+               cap & HOST_CAP_SXS ? "sxs " : "",
+               cap2 & HOST_CAP2_APST ? "apst " : "",
+               cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
+               cap2 & HOST_CAP2_BOH ? "boh " : ""
                );
 }
 
@@ -2646,17 +2698,15 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
        }
 }
 
-/*
- * SB600 ahci controller on certain boards can't do 64bit DMA with
- * older BIOS.
- */
-static bool ahci_sb600_32bit_only(struct pci_dev *pdev)
+/* only some SB600 ahci controllers can do 64bit DMA */
+static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
 {
        static const struct dmi_system_id sysids[] = {
                /*
                 * The oldest version known to be broken is 0901 and
                 * working is 1501 which was released on 2007-10-26.
-                * Force 32bit DMA on anything older than 1501.
+                * Enable 64bit DMA on 1501 and anything newer.
+                *
                 * Please read bko#9412 for more info.
                 */
                {
@@ -2669,46 +2719,57 @@ static bool ahci_sb600_32bit_only(struct pci_dev *pdev)
                        .driver_data = "20071026",      /* yyyymmdd */
                },
                /*
-                * It's yet unknown whether more recent BIOS fixes the
-                * problem.  Blacklist the whole board for the time
-                * being.  Please read the following thread for more
-                * info.
+                * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
+                * support 64bit DMA.
+                *
+                * BIOS versions earlier than 1.5 had the Manufacturer DMI
+                * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
+                * This spelling mistake was fixed in BIOS version 1.5, so
+                * 1.5 and later have the Manufacturer as
+                * "MICRO-STAR INTERNATIONAL CO.,LTD".
+                * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
                 *
-                * http://thread.gmane.org/gmane.linux.ide/42326
+                * BIOS versions earlier than 1.9 had a Board Product Name
+                * DMI field of "MS-7376". This was changed to be
+                * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
+                * match on DMI_BOARD_NAME of "MS-7376".
                 */
                {
-                       .ident = "Gigabyte GA-MA69VM-S2",
+                       .ident = "MSI K9A2 Platinum",
                        .matches = {
                                DMI_MATCH(DMI_BOARD_VENDOR,
-                                         "Gigabyte Technology Co., Ltd."),
-                               DMI_MATCH(DMI_BOARD_NAME, "GA-MA69VM-S2"),
+                                         "MICRO-STAR INTER"),
+                               DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
                        },
                },
                { }
        };
        const struct dmi_system_id *match;
+       int year, month, date;
+       char buf[9];
 
        match = dmi_first_match(sysids);
        if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
            !match)
                return false;
 
-       if (match->driver_data) {
-               int year, month, date;
-               char buf[9];
-
-               dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
-               snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
+       if (!match->driver_data)
+               goto enable_64bit;
 
-               if (strcmp(buf, match->driver_data) >= 0)
-                       return false;
+       dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
+       snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
 
+       if (strcmp(buf, match->driver_data) >= 0)
+               goto enable_64bit;
+       else {
                dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
                           "forcing 32bit DMA, update BIOS\n", match->ident);
-       } else
-               dev_printk(KERN_WARNING, &pdev->dev, "%s: this board can't "
-                          "do 64bit DMA, forcing 32bit\n", match->ident);
+               return false;
+       }
 
+enable_64bit:
+       dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
+                  match->ident);
        return true;
 }
 
@@ -2854,6 +2915,55 @@ static bool ahci_broken_online(struct pci_dev *pdev)
        return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
 }
 
+#ifdef CONFIG_ATA_ACPI
+static void ahci_gtf_filter_workaround(struct ata_host *host)
+{
+       static const struct dmi_system_id sysids[] = {
+               /*
+                * Aspire 3810T issues a bunch of SATA enable commands
+                * via _GTF including an invalid one and one which is
+                * rejected by the device.  Among the successful ones
+                * is FPDMA non-zero offset enable which when enabled
+                * only on the drive side leads to NCQ command
+                * failures.  Filter it out.
+                */
+               {
+                       .ident = "Aspire 3810T",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
+                       },
+                       .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
+               },
+               { }
+       };
+       const struct dmi_system_id *dmi = dmi_first_match(sysids);
+       unsigned int filter;
+       int i;
+
+       if (!dmi)
+               return;
+
+       filter = (unsigned long)dmi->driver_data;
+       dev_printk(KERN_INFO, host->dev,
+                  "applying extra ACPI _GTF filter 0x%x for %s\n",
+                  filter, dmi->ident);
+
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap = host->ports[i];
+               struct ata_link *link;
+               struct ata_device *dev;
+
+               ata_for_each_link(link, ap, EDGE)
+                       ata_for_each_dev(dev, link, ALL)
+                               dev->gtf_filter |= filter;
+       }
+}
+#else
+static inline void ahci_gtf_filter_workaround(struct ata_host *host)
+{}
+#endif
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version;
@@ -2922,12 +3032,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
                hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
 
-       /* apply sb600 32bit only quirk */
-       if (ahci_sb600_32bit_only(pdev))
-               hpriv->flags |= AHCI_HFLAG_32BIT_ONLY;
+       /* only some SB600s can do 64bit DMA */
+       if (ahci_sb600_enable_64bit(pdev))
+               hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
 
-       if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
-               pci_enable_msi(pdev);
+       if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
+               pci_intx(pdev, 1);
 
        /* save initial config */
        ahci_save_initial_config(pdev, hpriv);
@@ -3019,6 +3129,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* apply workaround for ASUS P5W DH Deluxe mainboard */
        ahci_p5wdh_workaround(host);
 
+       /* apply gtf filter quirk */
+       ahci_gtf_filter_workaround(host);
+
        /* initialize adapter */
        rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
        if (rc)