libata: don't whine on spurious IRQ
[safe/jmp/linux-2.6] / drivers / ata / ahci.c
index d4cd9c2..5326af2 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
 #include <linux/dmi.h>
+#include <linux/gfp.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
@@ -93,6 +94,9 @@ enum {
        AHCI_CMD_TBL_AR_SZ      = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
        AHCI_PORT_PRIV_DMA_SZ   = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
                                  AHCI_RX_FIS_SZ,
+       AHCI_PORT_PRIV_FBS_DMA_SZ       = AHCI_CMD_SLOT_SZ +
+                                         AHCI_CMD_TBL_AR_SZ +
+                                         (AHCI_RX_FIS_SZ * 16),
        AHCI_IRQ_ON_SG          = (1 << 31),
        AHCI_CMD_ATAPI          = (1 << 5),
        AHCI_CMD_WRITE          = (1 << 6),
@@ -113,6 +117,7 @@ enum {
        board_ahci_mcp65        = 6,
        board_ahci_nopmp        = 7,
        board_ahci_yesncq       = 8,
+       board_ahci_nosntf       = 9,
 
        /* global controller registers */
        HOST_CAP                = 0x00, /* host capabilities */
@@ -122,6 +127,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 +135,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 */
@@ -155,6 +174,7 @@ enum {
        PORT_SCR_ERR            = 0x30, /* SATA phy register: SError */
        PORT_SCR_ACT            = 0x34, /* SATA phy register: SActive */
        PORT_SCR_NTF            = 0x3c, /* SATA phy register: SNotification */
+       PORT_FBS                = 0x40, /* FIS-based Switching */
 
        /* PORT_IRQ_{STAT,MASK} bits */
        PORT_IRQ_COLD_PRES      = (1 << 31), /* cold presence detect */
@@ -193,6 +213,7 @@ enum {
        PORT_CMD_ASP            = (1 << 27), /* Aggressive Slumber/Partial */
        PORT_CMD_ALPE           = (1 << 26), /* Aggressive Link PM enable */
        PORT_CMD_ATAPI          = (1 << 24), /* Device is ATAPI */
+       PORT_CMD_FBSCP          = (1 << 22), /* FBS Capable Port */
        PORT_CMD_PMP            = (1 << 17), /* PMP attached */
        PORT_CMD_LIST_ON        = (1 << 15), /* cmd list DMA engine running */
        PORT_CMD_FIS_ON         = (1 << 14), /* FIS DMA engine running */
@@ -207,6 +228,14 @@ enum {
        PORT_CMD_ICC_PARTIAL    = (0x2 << 28), /* Put i/f in partial state */
        PORT_CMD_ICC_SLUMBER    = (0x6 << 28), /* Put i/f in slumber state */
 
+       PORT_FBS_DWE_OFFSET     = 16, /* FBS device with error offset */
+       PORT_FBS_ADO_OFFSET     = 12, /* FBS active dev optimization offset */
+       PORT_FBS_DEV_OFFSET     = 8,  /* FBS device to issue offset */
+       PORT_FBS_DEV_MASK       = (0xf << PORT_FBS_DEV_OFFSET),  /* FBS.DEV */
+       PORT_FBS_SDE            = (1 << 2), /* FBS single device error */
+       PORT_FBS_DEC            = (1 << 1), /* FBS device error clear */
+       PORT_FBS_EN             = (1 << 0), /* Enable FBS */
+
        /* hpriv->flags bits */
        AHCI_HFLAG_NO_NCQ               = (1 << 0),
        AHCI_HFLAG_IGN_IRQ_IF_ERR       = (1 << 1), /* ignore IRQ_IF_ERR */
@@ -221,6 +250,7 @@ enum {
        AHCI_HFLAG_NO_SUSPEND           = (1 << 10), /* don't suspend */
        AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
                                                        link offline */
+       AHCI_HFLAG_NO_SNTF              = (1 << 12), /* no sntf */
 
        /* ap->flags bits */
 
@@ -267,8 +297,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 */
 };
@@ -286,6 +318,9 @@ struct ahci_port_priv {
        unsigned int            ncq_saw_dmas:1;
        unsigned int            ncq_saw_sdb:1;
        u32                     intr_mask;      /* interrupts to enable */
+       bool                    fbs_supported;  /* set iff FBS is supported */
+       bool                    fbs_enabled;    /* set iff FBS is enabled */
+       int                     fbs_last_dev;   /* save FBS.DEV of last FIS */
        /* enclosure management info per PM slot */
        struct ahci_em_priv     em_priv[EM_MAX_SLOTS];
 };
@@ -297,9 +332,12 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
 static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
+static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc);
 static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static void ahci_freeze(struct ata_port *ap);
 static void ahci_thaw(struct ata_port *ap);
+static void ahci_enable_fbs(struct ata_port *ap);
+static void ahci_disable_fbs(struct ata_port *ap);
 static void ahci_pmp_attach(struct ata_port *ap);
 static void ahci_pmp_detach(struct ata_port *ap);
 static int ahci_softreset(struct ata_link *link, unsigned int *class,
@@ -331,20 +369,24 @@ 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_version, S_IRUGO, ahci_show_host_version, NULL);
-DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
+static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
+static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
+static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
+static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
 
 static struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_link_power_management_policy,
        &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
@@ -368,7 +410,7 @@ static struct scsi_host_template ahci_sht = {
 static struct ata_port_operations ahci_ops = {
        .inherits               = &sata_pmp_port_ops,
 
-       .qc_defer               = sata_pmp_qc_defer_cmd_switch,
+       .qc_defer               = ahci_pmp_qc_defer,
        .qc_prep                = ahci_qc_prep,
        .qc_issue               = ahci_qc_issue,
        .qc_fill_rtf            = ahci_qc_fill_rtf,
@@ -447,7 +489,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,
@@ -487,7 +530,7 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
-       /* board_ahci_yesncq */
+       [board_ahci_yesncq] =
        {
                AHCI_HFLAGS     (AHCI_HFLAG_YES_NCQ),
                .flags          = AHCI_FLAG_COMMON,
@@ -495,6 +538,14 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
+       [board_ahci_nosntf] =
+       {
+               AHCI_HFLAGS     (AHCI_HFLAG_NO_SNTF),
+               .flags          = AHCI_FLAG_COMMON,
+               .pio_mask       = ATA_PIO4,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &ahci_ops,
+       },
 };
 
 static const struct pci_device_id ahci_pci_tbl[] = {
@@ -510,7 +561,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
        { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
        { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
-       { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
+       { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
        { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
        { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
        { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
@@ -539,6 +590,12 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
+       { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
+       { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
+       { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
+       { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
+       { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
+       { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
 
        /* 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,
@@ -554,7 +611,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
 
        /* AMD */
-       { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD SB900 */
+       { 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 },
@@ -584,6 +641,22 @@ 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, 0x0581), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_yesncq },     /* Linux ID */
+       { PCI_VDEVICE(NVIDIA, 0x058f), 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 */
@@ -732,6 +805,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)
 {
@@ -771,7 +854,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;
 
@@ -784,6 +867,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,
@@ -809,6 +900,12 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
                cap &= ~HOST_CAP_PMP;
        }
 
+       if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) {
+               dev_printk(KERN_INFO, &pdev->dev,
+                          "controller can't do SNTF, turning off CAP_SNTF\n");
+               cap &= ~HOST_CAP_SNTF;
+       }
+
        if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
            port_map != 1) {
                dev_printk(KERN_INFO, &pdev->dev,
@@ -869,6 +966,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;
 }
 
@@ -887,6 +985,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 */
 }
@@ -1986,6 +2086,17 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
        return si;
 }
 
+static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct ahci_port_priv *pp = ap->private_data;
+
+       if (!sata_pmp_attached(ap) || pp->fbs_enabled)
+               return ata_std_qc_defer(qc);
+       else
+               return sata_pmp_qc_defer_cmd_switch(qc);
+}
+
 static void ahci_qc_prep(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
@@ -2024,6 +2135,31 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
        ahci_fill_cmd_slot(pp, qc->tag, opts);
 }
 
+static void ahci_fbs_dec_intr(struct ata_port *ap)
+{
+       struct ahci_port_priv *pp = ap->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 fbs = readl(port_mmio + PORT_FBS);
+       int retries = 3;
+
+       DPRINTK("ENTER\n");
+       BUG_ON(!pp->fbs_enabled);
+
+       /* time to wait for DEC is not specified by AHCI spec,
+        * add a retry loop for safety.
+        */
+       writel(fbs | PORT_FBS_DEC, port_mmio + PORT_FBS);
+       fbs = readl(port_mmio + PORT_FBS);
+       while ((fbs & PORT_FBS_DEC) && retries--) {
+               udelay(1);
+               fbs = readl(port_mmio + PORT_FBS);
+       }
+
+       if (fbs & PORT_FBS_DEC)
+               dev_printk(KERN_ERR, ap->host->dev,
+                          "failed to clear device error\n");
+}
+
 static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
 {
        struct ahci_host_priv *hpriv = ap->host->private_data;
@@ -2032,12 +2168,26 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
        struct ata_link *link = NULL;
        struct ata_queued_cmd *active_qc;
        struct ata_eh_info *active_ehi;
+       bool fbs_need_dec = false;
        u32 serror;
 
-       /* determine active link */
-       ata_for_each_link(link, ap, EDGE)
-               if (ata_link_active(link))
-                       break;
+       /* determine active link with error */
+       if (pp->fbs_enabled) {
+               void __iomem *port_mmio = ahci_port_base(ap);
+               u32 fbs = readl(port_mmio + PORT_FBS);
+               int pmp = fbs >> PORT_FBS_DWE_OFFSET;
+
+               if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links) &&
+                   ata_link_online(&ap->pmp_link[pmp])) {
+                       link = &ap->pmp_link[pmp];
+                       fbs_need_dec = true;
+               }
+
+       } else
+               ata_for_each_link(link, ap, EDGE)
+                       if (ata_link_active(link))
+                               break;
+
        if (!link)
                link = &ap->link;
 
@@ -2094,8 +2244,13 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
        }
 
        if (irq_stat & PORT_IRQ_IF_ERR) {
-               host_ehi->err_mask |= AC_ERR_ATA_BUS;
-               host_ehi->action |= ATA_EH_RESET;
+               if (fbs_need_dec)
+                       active_ehi->err_mask |= AC_ERR_DEV;
+               else {
+                       host_ehi->err_mask |= AC_ERR_ATA_BUS;
+                       host_ehi->action |= ATA_EH_RESET;
+               }
+
                ata_ehi_push_desc(host_ehi, "interface fatal error");
        }
 
@@ -2110,7 +2265,10 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
 
        if (irq_stat & PORT_IRQ_FREEZE)
                ata_port_freeze(ap);
-       else
+       else if (fbs_need_dec) {
+               ata_link_abort(link);
+               ahci_fbs_dec_intr(ap);
+       } else
                ata_port_abort(ap);
 }
 
@@ -2121,7 +2279,7 @@ static void ahci_port_intr(struct ata_port *ap)
        struct ahci_port_priv *pp = ap->private_data;
        struct ahci_host_priv *hpriv = ap->host->private_data;
        int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
-       u32 status, qc_active;
+       u32 status, qc_active = 0;
        int rc;
 
        status = readl(port_mmio + PORT_IRQ_STAT);
@@ -2163,20 +2321,38 @@ static void ahci_port_intr(struct ata_port *ap)
                        /* If the 'N' bit in word 0 of the FIS is set,
                         * we just received asynchronous notification.
                         * Tell libata about it.
+                        *
+                        * Lack of SNotification should not appear in
+                        * ahci 1.2, so the workaround is unnecessary
+                        * when FBS is enabled.
                         */
-                       const __le32 *f = pp->rx_fis + RX_FIS_SDB;
-                       u32 f0 = le32_to_cpu(f[0]);
-
-                       if (f0 & (1 << 15))
-                               sata_async_notification(ap);
+                       if (pp->fbs_enabled)
+                               WARN_ON_ONCE(1);
+                       else {
+                               const __le32 *f = pp->rx_fis + RX_FIS_SDB;
+                               u32 f0 = le32_to_cpu(f[0]);
+                               if (f0 & (1 << 15))
+                                       sata_async_notification(ap);
+                       }
                }
        }
 
-       /* pp->active_link is valid iff any command is in flight */
-       if (ap->qc_active && pp->active_link->sactive)
-               qc_active = readl(port_mmio + PORT_SCR_ACT);
-       else
-               qc_active = readl(port_mmio + PORT_CMD_ISSUE);
+       /* pp->active_link is not reliable once FBS is enabled, both
+        * PORT_SCR_ACT and PORT_CMD_ISSUE should be checked because
+        * NCQ and non-NCQ commands may be in flight at the same time.
+        */
+       if (pp->fbs_enabled) {
+               if (ap->qc_active) {
+                       qc_active = readl(port_mmio + PORT_SCR_ACT);
+                       qc_active |= readl(port_mmio + PORT_CMD_ISSUE);
+               }
+       } else {
+               /* pp->active_link is valid iff any command is in flight */
+               if (ap->qc_active && pp->active_link->sactive)
+                       qc_active = readl(port_mmio + PORT_SCR_ACT);
+               else
+                       qc_active = readl(port_mmio + PORT_CMD_ISSUE);
+       }
 
        rc = ata_qc_complete_multiple(ap, qc_active);
 
@@ -2262,6 +2438,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
 
        if (qc->tf.protocol == ATA_PROT_NCQ)
                writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
+
+       if (pp->fbs_enabled && pp->fbs_last_dev != qc->dev->link->pmp) {
+               u32 fbs = readl(port_mmio + PORT_FBS);
+               fbs &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC);
+               fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET;
+               writel(fbs, port_mmio + PORT_FBS);
+               pp->fbs_last_dev = qc->dev->link->pmp;
+       }
+
        writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
 
        ahci_sw_activity(qc->dev->link);
@@ -2274,6 +2459,9 @@ static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
        struct ahci_port_priv *pp = qc->ap->private_data;
        u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
 
+       if (pp->fbs_enabled)
+               d2h_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
+
        ata_tf_from_fis(d2h_fis, &qc->result_tf);
        return true;
 }
@@ -2322,6 +2510,71 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
                ahci_kick_engine(ap);
 }
 
+static void ahci_enable_fbs(struct ata_port *ap)
+{
+       struct ahci_port_priv *pp = ap->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 fbs;
+       int rc;
+
+       if (!pp->fbs_supported)
+               return;
+
+       fbs = readl(port_mmio + PORT_FBS);
+       if (fbs & PORT_FBS_EN) {
+               pp->fbs_enabled = true;
+               pp->fbs_last_dev = -1; /* initialization */
+               return;
+       }
+
+       rc = ahci_stop_engine(ap);
+       if (rc)
+               return;
+
+       writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS);
+       fbs = readl(port_mmio + PORT_FBS);
+       if (fbs & PORT_FBS_EN) {
+               dev_printk(KERN_INFO, ap->host->dev, "FBS is enabled.\n");
+               pp->fbs_enabled = true;
+               pp->fbs_last_dev = -1; /* initialization */
+       } else
+               dev_printk(KERN_ERR, ap->host->dev, "Failed to enable FBS\n");
+
+       ahci_start_engine(ap);
+}
+
+static void ahci_disable_fbs(struct ata_port *ap)
+{
+       struct ahci_port_priv *pp = ap->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 fbs;
+       int rc;
+
+       if (!pp->fbs_supported)
+               return;
+
+       fbs = readl(port_mmio + PORT_FBS);
+       if ((fbs & PORT_FBS_EN) == 0) {
+               pp->fbs_enabled = false;
+               return;
+       }
+
+       rc = ahci_stop_engine(ap);
+       if (rc)
+               return;
+
+       writel(fbs & ~PORT_FBS_EN, port_mmio + PORT_FBS);
+       fbs = readl(port_mmio + PORT_FBS);
+       if (fbs & PORT_FBS_EN)
+               dev_printk(KERN_ERR, ap->host->dev, "Failed to disable FBS\n");
+       else {
+               dev_printk(KERN_INFO, ap->host->dev, "FBS is disabled.\n");
+               pp->fbs_enabled = false;
+       }
+
+       ahci_start_engine(ap);
+}
+
 static void ahci_pmp_attach(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
@@ -2332,6 +2585,8 @@ static void ahci_pmp_attach(struct ata_port *ap)
        cmd |= PORT_CMD_PMP;
        writel(cmd, port_mmio + PORT_CMD);
 
+       ahci_enable_fbs(ap);
+
        pp->intr_mask |= PORT_IRQ_BAD_PMP;
        writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
@@ -2342,6 +2597,8 @@ static void ahci_pmp_detach(struct ata_port *ap)
        struct ahci_port_priv *pp = ap->private_data;
        u32 cmd;
 
+       ahci_disable_fbs(ap);
+
        cmd = readl(port_mmio + PORT_CMD);
        cmd &= ~PORT_CMD_PMP;
        writel(cmd, port_mmio + PORT_CMD);
@@ -2433,20 +2690,40 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
 
 static int ahci_port_start(struct ata_port *ap)
 {
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        struct device *dev = ap->host->dev;
        struct ahci_port_priv *pp;
        void *mem;
        dma_addr_t mem_dma;
+       size_t dma_sz, rx_fis_sz;
 
        pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
        if (!pp)
                return -ENOMEM;
 
-       mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
-                                 GFP_KERNEL);
+       /* check FBS capability */
+       if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) {
+               void __iomem *port_mmio = ahci_port_base(ap);
+               u32 cmd = readl(port_mmio + PORT_CMD);
+               if (cmd & PORT_CMD_FBSCP)
+                       pp->fbs_supported = true;
+               else
+                       dev_printk(KERN_WARNING, dev,
+                                  "The port is not capable of FBS\n");
+       }
+
+       if (pp->fbs_supported) {
+               dma_sz = AHCI_PORT_PRIV_FBS_DMA_SZ;
+               rx_fis_sz = AHCI_RX_FIS_SZ * 16;
+       } else {
+               dma_sz = AHCI_PORT_PRIV_DMA_SZ;
+               rx_fis_sz = AHCI_RX_FIS_SZ;
+       }
+
+       mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL);
        if (!mem)
                return -ENOMEM;
-       memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
+       memset(mem, 0, dma_sz);
 
        /*
         * First item in chunk of DMA memory: 32-slot command table,
@@ -2464,8 +2741,8 @@ static int ahci_port_start(struct ata_port *ap)
        pp->rx_fis = mem;
        pp->rx_fis_dma = mem_dma;
 
-       mem += AHCI_RX_FIS_SZ;
-       mem_dma += AHCI_RX_FIS_SZ;
+       mem += rx_fis_sz;
+       mem_dma += rx_fis_sz;
 
        /*
         * Third item: data area for storing a single command
@@ -2534,13 +2811,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;
@@ -2583,25 +2861,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 " : ""
                );
 }
 
@@ -2650,17 +2932,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.
                 */
                {
@@ -2673,46 +2953,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;
 }
 
@@ -2758,6 +3049,14 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
                 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
                 * to the harddisk doesn't become online after
                 * resuming from STR.  Warn and fail suspend.
+                *
+                * http://bugzilla.kernel.org/show_bug.cgi?id=12276
+                *
+                * Use dates instead of versions to match as HP is
+                * apparently recycling both product and version
+                * strings.
+                *
+                * http://bugzilla.kernel.org/show_bug.cgi?id=15462
                 */
                {
                        .ident = "dv4",
@@ -2766,7 +3065,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
                                DMI_MATCH(DMI_PRODUCT_NAME,
                                          "HP Pavilion dv4 Notebook PC"),
                        },
-                       .driver_data = "F.30", /* cutoff BIOS version */
+                       .driver_data = "20090105",      /* F.30 */
                },
                {
                        .ident = "dv5",
@@ -2775,7 +3074,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
                                DMI_MATCH(DMI_PRODUCT_NAME,
                                          "HP Pavilion dv5 Notebook PC"),
                        },
-                       .driver_data = "F.16", /* cutoff BIOS version */
+                       .driver_data = "20090506",      /* F.16 */
                },
                {
                        .ident = "dv6",
@@ -2784,7 +3083,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
                                DMI_MATCH(DMI_PRODUCT_NAME,
                                          "HP Pavilion dv6 Notebook PC"),
                        },
-                       .driver_data = "F.21",  /* cutoff BIOS version */
+                       .driver_data = "20090423",      /* F.21 */
                },
                {
                        .ident = "HDX18",
@@ -2793,19 +3092,38 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
                                DMI_MATCH(DMI_PRODUCT_NAME,
                                          "HP HDX18 Notebook PC"),
                        },
-                       .driver_data = "F.23",  /* cutoff BIOS version */
+                       .driver_data = "20090430",      /* F.23 */
+               },
+               /*
+                * Acer eMachines G725 has the same problem.  BIOS
+                * V1.03 is known to be broken.  V3.04 is known to
+                * work.  Inbetween, there are V1.06, V2.06 and V3.03
+                * that we don't have much idea about.  For now,
+                * blacklist anything older than V3.04.
+                *
+                * http://bugzilla.kernel.org/show_bug.cgi?id=15104
+                */
+               {
+                       .ident = "G725",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
+                       },
+                       .driver_data = "20091216",      /* V3.04 */
                },
                { }     /* terminate list */
        };
        const struct dmi_system_id *dmi = dmi_first_match(sysids);
-       const char *ver;
+       int year, month, date;
+       char buf[9];
 
        if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
                return false;
 
-       ver = dmi_get_system_info(DMI_BIOS_VERSION);
+       dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
+       snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
 
-       return !ver || strcmp(ver, dmi->driver_data) < 0;
+       return strcmp(buf, dmi->driver_data) < 0;
 }
 
 static bool ahci_broken_online(struct pci_dev *pdev)
@@ -2858,6 +3176,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;
@@ -2882,6 +3249,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
                return -ENODEV;
 
+       /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
+        * At the moment, we can only use the AHCI mode. Let the users know
+        * that for SAS drives they're out of luck.
+        */
+       if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
+               dev_printk(KERN_INFO, &pdev->dev, "PDC42819 "
+                          "can only drive SATA devices with this driver\n");
+
        /* acquire resources */
        rc = pcim_enable_device(pdev);
        if (rc)
@@ -2926,19 +3301,27 @@ 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);
 
        /* prepare host */
-       if (hpriv->cap & HOST_CAP_NCQ)
-               pi.flags |= ATA_FLAG_NCQ | ATA_FLAG_FPDMA_AA;
+       if (hpriv->cap & HOST_CAP_NCQ) {
+               pi.flags |= ATA_FLAG_NCQ;
+               /* Auto-activate optimization is supposed to be supported on
+                  all AHCI controllers indicating NCQ support, but it seems
+                  to be broken at least on some NVIDIA MCP79 chipsets.
+                  Until we get info on which NVIDIA chipsets don't have this
+                  issue, if any, disable AA on all NVIDIA AHCIs. */
+               if (pdev->vendor != PCI_VENDOR_ID_NVIDIA)
+                       pi.flags |= ATA_FLAG_FPDMA_AA;
+       }
 
        if (hpriv->cap & HOST_CAP_PMP)
                pi.flags |= ATA_FLAG_PMP;
@@ -3023,6 +3406,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)