[ALSA] hda-codec - Add model for Acer Aspire 5315
[safe/jmp/linux-2.6] / drivers / ata / ahci.c
index abfb72a..6f089b8 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
+#include <linux/dmi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
@@ -48,6 +49,9 @@
 #define DRV_NAME       "ahci"
 #define DRV_VERSION    "3.0"
 
+static int ahci_enable_alpm(struct ata_port *ap,
+               enum link_pm policy);
+static void ahci_disable_alpm(struct ata_port *ap);
 
 enum {
        AHCI_PCI_BAR            = 5,
@@ -98,6 +102,7 @@ enum {
        HOST_CAP_SSC            = (1 << 14), /* Slumber capable */
        HOST_CAP_PMP            = (1 << 17), /* Port Multiplier support */
        HOST_CAP_CLO            = (1 << 24), /* Command List Override support */
+       HOST_CAP_ALPM           = (1 << 26), /* Aggressive Link PM support */
        HOST_CAP_SSS            = (1 << 27), /* Staggered Spin-up */
        HOST_CAP_SNTF           = (1 << 29), /* SNotification register */
        HOST_CAP_NCQ            = (1 << 30), /* Native Command Queueing */
@@ -154,6 +159,8 @@ enum {
                                  PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
 
        /* PORT_CMD bits */
+       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_PMP            = (1 << 17), /* PMP attached */
        PORT_CMD_LIST_ON        = (1 << 15), /* cmd list DMA engine running */
@@ -177,29 +184,32 @@ enum {
        AHCI_HFLAG_MV_PATA              = (1 << 4), /* PATA port */
        AHCI_HFLAG_NO_MSI               = (1 << 5), /* no PCI MSI */
        AHCI_HFLAG_NO_PMP               = (1 << 6), /* no PMP */
+       AHCI_HFLAG_NO_HOTPLUG           = (1 << 7), /* ignore PxSERR.DIAG.N */
 
        /* ap->flags bits */
-       AHCI_FLAG_NO_HOTPLUG            = (1 << 24), /* ignore PxSERR.DIAG.N */
 
        AHCI_FLAG_COMMON                = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                          ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                         ATA_FLAG_ACPI_SATA | ATA_FLAG_AN,
+                                         ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
+                                         ATA_FLAG_IPM,
        AHCI_LFLAG_COMMON               = ATA_LFLAG_SKIP_D2H_BSY,
+
+       ICH_MAP                         = 0x90, /* ICH MAP register */
 };
 
 struct ahci_cmd_hdr {
-       u32                     opts;
-       u32                     status;
-       u32                     tbl_addr;
-       u32                     tbl_addr_hi;
-       u32                     reserved[4];
+       __le32                  opts;
+       __le32                  status;
+       __le32                  tbl_addr;
+       __le32                  tbl_addr_hi;
+       __le32                  reserved[4];
 };
 
 struct ahci_sg {
-       u32                     addr;
-       u32                     addr_hi;
-       u32                     reserved;
-       u32                     flags_size;
+       __le32                  addr;
+       __le32                  addr_hi;
+       __le32                  reserved;
+       __le32                  flags_size;
 };
 
 struct ahci_host_priv {
@@ -227,7 +237,7 @@ struct ahci_port_priv {
 
 static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
 static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
-static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
 static void ahci_irq_clear(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
@@ -239,10 +249,9 @@ static void ahci_freeze(struct ata_port *ap);
 static void ahci_thaw(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_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val);
-static int ahci_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val);
 static void ahci_error_handler(struct ata_port *ap);
 static void ahci_vt8251_error_handler(struct ata_port *ap);
+static void ahci_p5wdh_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static int ahci_port_resume(struct ata_port *ap);
 static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
@@ -254,6 +263,11 @@ 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 class_device_attribute *ahci_shost_attrs[] = {
+       &class_device_attr_link_power_management_policy,
+       NULL
+};
+
 static struct scsi_host_template ahci_sht = {
        .module                 = THIS_MODULE,
        .name                   = DRV_NAME,
@@ -271,6 +285,7 @@ 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,
+       .shost_attrs            = ahci_shost_attrs,
 };
 
 static const struct ata_port_operations ahci_ops = {
@@ -297,13 +312,13 @@ static const struct ata_port_operations ahci_ops = {
 
        .pmp_attach             = ahci_pmp_attach,
        .pmp_detach             = ahci_pmp_detach,
-       .pmp_read               = ahci_pmp_read,
-       .pmp_write              = ahci_pmp_write,
 
 #ifdef CONFIG_PM
        .port_suspend           = ahci_port_suspend,
        .port_resume            = ahci_port_resume,
 #endif
+       .enable_pm              = ahci_enable_alpm,
+       .disable_pm             = ahci_disable_alpm,
 
        .port_start             = ahci_port_start,
        .port_stop              = ahci_port_stop,
@@ -333,8 +348,40 @@ static const struct ata_port_operations ahci_vt8251_ops = {
 
        .pmp_attach             = ahci_pmp_attach,
        .pmp_detach             = ahci_pmp_detach,
-       .pmp_read               = ahci_pmp_read,
-       .pmp_write              = ahci_pmp_write,
+
+#ifdef CONFIG_PM
+       .port_suspend           = ahci_port_suspend,
+       .port_resume            = ahci_port_resume,
+#endif
+
+       .port_start             = ahci_port_start,
+       .port_stop              = ahci_port_stop,
+};
+
+static const struct ata_port_operations ahci_p5wdh_ops = {
+       .check_status           = ahci_check_status,
+       .check_altstatus        = ahci_check_status,
+       .dev_select             = ata_noop_dev_select,
+
+       .tf_read                = ahci_tf_read,
+
+       .qc_defer               = sata_pmp_qc_defer_cmd_switch,
+       .qc_prep                = ahci_qc_prep,
+       .qc_issue               = ahci_qc_issue,
+
+       .irq_clear              = ahci_irq_clear,
+
+       .scr_read               = ahci_scr_read,
+       .scr_write              = ahci_scr_write,
+
+       .freeze                 = ahci_freeze,
+       .thaw                   = ahci_thaw,
+
+       .error_handler          = ahci_p5wdh_error_handler,
+       .post_internal_cmd      = ahci_post_internal_cmd,
+
+       .pmp_attach             = ahci_pmp_attach,
+       .pmp_detach             = ahci_pmp_detach,
 
 #ifdef CONFIG_PM
        .port_suspend           = ahci_port_suspend,
@@ -491,6 +538,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci },            /* MCP77 */
        { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci },            /* MCP77 */
        { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci },            /* MCP77 */
+       { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci },            /* MCP79 */
+       { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci },            /* MCP79 */
+       { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci },            /* MCP79 */
+       { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci },            /* MCP79 */
        { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci },            /* MCP79 */
        { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci },            /* MCP79 */
        { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci },            /* MCP79 */
@@ -546,6 +597,20 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
        return __ahci_port_base(ap->host, ap->port_no);
 }
 
+static void ahci_enable_ahci(void __iomem *mmio)
+{
+       u32 tmp;
+
+       /* turn on AHCI_EN */
+       tmp = readl(mmio + HOST_CTL);
+       if (!(tmp & HOST_AHCI_EN)) {
+               tmp |= HOST_AHCI_EN;
+               writel(tmp, mmio + HOST_CTL);
+               tmp = readl(mmio + HOST_CTL);   /* flush && sanity check */
+               WARN_ON(!(tmp & HOST_AHCI_EN));
+       }
+}
+
 /**
  *     ahci_save_initial_config - Save and fixup initial config values
  *     @pdev: target PCI device
@@ -568,6 +633,9 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
        u32 cap, port_map;
        int i;
 
+       /* make sure AHCI mode is enabled before accessing CAP */
+       ahci_enable_ahci(mmio);
+
        /* Values prefixed with saved_ are written back to host after
         * reset.  Values without are used for driver operation.
         */
@@ -735,7 +803,7 @@ static int ahci_stop_engine(struct ata_port *ap)
 
        /* wait for engine to stop. This could be as long as 500 msec */
        tmp = ata_wait_register(port_mmio + PORT_CMD,
-                               PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+                               PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
        if (tmp & PORT_CMD_LIST_ON)
                return -EIO;
 
@@ -806,6 +874,130 @@ static void ahci_power_up(struct ata_port *ap)
        writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
+static void ahci_disable_alpm(struct ata_port *ap)
+{
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 cmd;
+       struct ahci_port_priv *pp = ap->private_data;
+
+       /* IPM bits should be disabled by libata-core */
+       /* get the existing command bits */
+       cmd = readl(port_mmio + PORT_CMD);
+
+       /* disable ALPM and ASP */
+       cmd &= ~PORT_CMD_ASP;
+       cmd &= ~PORT_CMD_ALPE;
+
+       /* force the interface back to active */
+       cmd |= PORT_CMD_ICC_ACTIVE;
+
+       /* write out new cmd value */
+       writel(cmd, port_mmio + PORT_CMD);
+       cmd = readl(port_mmio + PORT_CMD);
+
+       /* wait 10ms to be sure we've come out of any low power state */
+       msleep(10);
+
+       /* clear out any PhyRdy stuff from interrupt status */
+       writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
+
+       /* go ahead and clean out PhyRdy Change from Serror too */
+       ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
+
+       /*
+        * Clear flag to indicate that we should ignore all PhyRdy
+        * state changes
+        */
+       hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
+
+       /*
+        * Enable interrupts on Phy Ready.
+        */
+       pp->intr_mask |= PORT_IRQ_PHYRDY;
+       writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+       /*
+        * don't change the link pm policy - we can be called
+        * just to turn of link pm temporarily
+        */
+}
+
+static int ahci_enable_alpm(struct ata_port *ap,
+       enum link_pm policy)
+{
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 cmd;
+       struct ahci_port_priv *pp = ap->private_data;
+       u32 asp;
+
+       /* Make sure the host is capable of link power management */
+       if (!(hpriv->cap & HOST_CAP_ALPM))
+               return -EINVAL;
+
+       switch (policy) {
+       case MAX_PERFORMANCE:
+       case NOT_AVAILABLE:
+               /*
+                * if we came here with NOT_AVAILABLE,
+                * it just means this is the first time we
+                * have tried to enable - default to max performance,
+                * and let the user go to lower power modes on request.
+                */
+               ahci_disable_alpm(ap);
+               return 0;
+       case MIN_POWER:
+               /* configure HBA to enter SLUMBER */
+               asp = PORT_CMD_ASP;
+               break;
+       case MEDIUM_POWER:
+               /* configure HBA to enter PARTIAL */
+               asp = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /*
+        * Disable interrupts on Phy Ready. This keeps us from
+        * getting woken up due to spurious phy ready interrupts
+        * TBD - Hot plug should be done via polling now, is
+        * that even supported?
+        */
+       pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+       writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+       /*
+        * Set a flag to indicate that we should ignore all PhyRdy
+        * state changes since these can happen now whenever we
+        * change link state
+        */
+       hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
+
+       /* get the existing command bits */
+       cmd = readl(port_mmio + PORT_CMD);
+
+       /*
+        * Set ASP based on Policy
+        */
+       cmd |= asp;
+
+       /*
+        * Setting this bit will instruct the HBA to aggressively
+        * enter a lower power link state when it's appropriate and
+        * based on the value set above for ASP
+        */
+       cmd |= PORT_CMD_ALPE;
+
+       /* write out new cmd value */
+       writel(cmd, port_mmio + PORT_CMD);
+       cmd = readl(port_mmio + PORT_CMD);
+
+       /* IPM bits should be set by libata-core */
+       return 0;
+}
+
 #ifdef CONFIG_PM
 static void ahci_power_down(struct ata_port *ap)
 {
@@ -861,17 +1053,17 @@ static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
 static int ahci_reset_controller(struct ata_host *host)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
+       struct ahci_host_priv *hpriv = host->private_data;
        void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
        u32 tmp;
 
        /* we must be in AHCI mode, before using anything
         * AHCI-specific, such as HOST_RESET.
         */
-       tmp = readl(mmio + HOST_CTL);
-       if (!(tmp & HOST_AHCI_EN))
-               writel(tmp | HOST_AHCI_EN, mmio + HOST_CTL);
+       ahci_enable_ahci(mmio);
 
        /* global controller reset */
+       tmp = readl(mmio + HOST_CTL);
        if ((tmp & HOST_RESET) == 0) {
                writel(tmp | HOST_RESET, mmio + HOST_CTL);
                readl(mmio + HOST_CTL); /* flush */
@@ -890,8 +1082,7 @@ static int ahci_reset_controller(struct ata_host *host)
        }
 
        /* turn on AHCI mode */
-       writel(HOST_AHCI_EN, mmio + HOST_CTL);
-       (void) readl(mmio + HOST_CTL);  /* flush */
+       ahci_enable_ahci(mmio);
 
        /* some registers might be cleared on reset.  restore initial values */
        ahci_restore_initial_config(host);
@@ -901,8 +1092,10 @@ static int ahci_reset_controller(struct ata_host *host)
 
                /* configure PCS */
                pci_read_config_word(pdev, 0x92, &tmp16);
-               tmp16 |= 0xf;
-               pci_write_config_word(pdev, 0x92, tmp16);
+               if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
+                       tmp16 |= hpriv->port_map;
+                       pci_write_config_word(pdev, 0x92, tmp16);
+               }
        }
 
        return 0;
@@ -1096,9 +1289,9 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 
        /* prepare for SRST (AHCI-1.1 10.4.1) */
        rc = ahci_kick_engine(ap, 1);
-       if (rc)
+       if (rc && rc != -EOPNOTSUPP)
                ata_link_printk(link, KERN_WARNING,
-                               "failed to reset engine (errno=%d)", rc);
+                               "failed to reset engine (errno=%d)\n", rc);
 
        ata_tf_init(link->device, &tf);
 
@@ -1123,15 +1316,8 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
        tf.ctl &= ~ATA_SRST;
        ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
 
-       /* spec mandates ">= 2ms" before checking status.
-        * We wait 150ms, because that was the magic delay used for
-        * ATAPI devices in Hale Landis's ATADRVR, for the period of time
-        * between when the ATA command register is written, and then
-        * status is checked.  Because waiting for "a while" before
-        * checking status is fine, post SRST, we perform this magic
-        * delay here as well.
-        */
-       msleep(150);
+       /* wait a while before checking status */
+       ata_wait_after_reset(ap, deadline);
 
        rc = ata_wait_ready(ap, deadline);
        /* link occupied, -ENODEV too is an error */
@@ -1219,6 +1405,53 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
        return rc ?: -EAGAIN;
 }
 
+static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+                               unsigned long deadline)
+{
+       struct ata_port *ap = link->ap;
+       struct ahci_port_priv *pp = ap->private_data;
+       u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+       struct ata_taskfile tf;
+       int rc;
+
+       ahci_stop_engine(ap);
+
+       /* clear D2H reception area to properly wait for D2H FIS */
+       ata_tf_init(link->device, &tf);
+       tf.command = 0x80;
+       ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+
+       rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
+                                deadline);
+
+       ahci_start_engine(ap);
+
+       if (rc || ata_link_offline(link))
+               return rc;
+
+       /* spec mandates ">= 2ms" before checking status */
+       msleep(150);
+
+       /* The pseudo configuration device on SIMG4726 attached to
+        * ASUS P5W-DH Deluxe doesn't send signature FIS after
+        * hardreset if no device is attached to the first downstream
+        * port && the pseudo device locks up on SRST w/ PMP==0.  To
+        * work around this, wait for !BSY only briefly.  If BSY isn't
+        * cleared, perform CLO and proceed to IDENTIFY (achieved by
+        * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
+        *
+        * Wait for two seconds.  Devices attached to downstream port
+        * which can't process the following IDENTIFY after this will
+        * have to be reset again.  For most cases, this should
+        * suffice while making probing snappish enough.
+        */
+       rc = ata_wait_ready(ap, jiffies + 2 * HZ);
+       if (rc)
+               ahci_kick_engine(ap, 0);
+
+       return 0;
+}
+
 static void ahci_postreset(struct ata_link *link, unsigned int *class)
 {
        struct ata_port *ap = link->ap;
@@ -1263,35 +1496,31 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
 {
        struct scatterlist *sg;
-       struct ahci_sg *ahci_sg;
-       unsigned int n_sg = 0;
+       struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
+       unsigned int si;
 
        VPRINTK("ENTER\n");
 
        /*
         * Next, the S/G list.
         */
-       ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
-       ata_for_each_sg(sg, qc) {
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
                dma_addr_t addr = sg_dma_address(sg);
                u32 sg_len = sg_dma_len(sg);
 
-               ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
-               ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
-               ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
-
-               ahci_sg++;
-               n_sg++;
+               ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
+               ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
+               ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
        }
 
-       return n_sg;
+       return si;
 }
 
 static void ahci_qc_prep(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct ahci_port_priv *pp = ap->private_data;
-       int is_atapi = is_atapi_taskfile(&qc->tf);
+       int is_atapi = ata_is_atapi(qc->tf.protocol);
        void *cmd_tbl;
        u32 opts;
        const u32 cmd_fis_len = 5; /* five dwords */
@@ -1421,12 +1650,28 @@ static void ahci_port_intr(struct ata_port *ap)
        struct ata_eh_info *ehi = &ap->link.eh_info;
        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;
-       int rc, known_irq = 0;
+       int rc;
 
        status = readl(port_mmio + PORT_IRQ_STAT);
        writel(status, port_mmio + PORT_IRQ_STAT);
 
+       /* ignore BAD_PMP while resetting */
+       if (unlikely(resetting))
+               status &= ~PORT_IRQ_BAD_PMP;
+
+       /* If we are getting PhyRdy, this is
+        * just a power state change, we should
+        * clear out this, plus the PhyRdy/Comm
+        * Wake bits from Serror
+        */
+       if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
+               (status & PORT_IRQ_PHYRDY)) {
+               status &= ~PORT_IRQ_PHYRDY;
+               ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
+       }
+
        if (unlikely(status & PORT_IRQ_ERROR)) {
                ahci_error_intr(ap, status);
                return;
@@ -1464,74 +1709,13 @@ static void ahci_port_intr(struct ata_port *ap)
                qc_active = readl(port_mmio + PORT_CMD_ISSUE);
 
        rc = ata_qc_complete_multiple(ap, qc_active, NULL);
-       if (rc > 0)
-               return;
-       if (rc < 0) {
+
+       /* while resetting, invalid completions are expected */
+       if (unlikely(rc < 0 && !resetting)) {
                ehi->err_mask |= AC_ERR_HSM;
                ehi->action |= ATA_EH_SOFTRESET;
                ata_port_freeze(ap);
-               return;
-       }
-
-       /* hmmm... a spurious interupt */
-
-       /* if !NCQ, ignore.  No modern ATA device has broken HSM
-        * implementation for non-NCQ commands.
-        */
-       if (!ap->link.sactive)
-               return;
-
-       if (status & PORT_IRQ_D2H_REG_FIS) {
-               if (!pp->ncq_saw_d2h)
-                       ata_port_printk(ap, KERN_INFO,
-                               "D2H reg with I during NCQ, "
-                               "this message won't be printed again\n");
-               pp->ncq_saw_d2h = 1;
-               known_irq = 1;
-       }
-
-       if (status & PORT_IRQ_DMAS_FIS) {
-               if (!pp->ncq_saw_dmas)
-                       ata_port_printk(ap, KERN_INFO,
-                               "DMAS FIS during NCQ, "
-                               "this message won't be printed again\n");
-               pp->ncq_saw_dmas = 1;
-               known_irq = 1;
-       }
-
-       if (status & PORT_IRQ_SDB_FIS) {
-               const __le32 *f = pp->rx_fis + RX_FIS_SDB;
-
-               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;
        }
-
-       if (!known_irq)
-               ata_port_printk(ap, KERN_INFO, "spurious interrupt "
-                               "(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n",
-                               status, ap->link.active_tag, ap->link.sactive);
 }
 
 static void ahci_irq_clear(struct ata_port *ap)
@@ -1558,9 +1742,9 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
        if (!irq_stat)
                return IRQ_NONE;
 
-        spin_lock(&host->lock);
+       spin_lock(&host->lock);
 
-        for (i = 0; i < host->n_ports; i++) {
+       for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap;
 
                if (!(irq_stat & (1 << i)))
@@ -1664,6 +1848,19 @@ static void ahci_vt8251_error_handler(struct ata_port *ap)
                  ahci_postreset);
 }
 
+static void ahci_p5wdh_error_handler(struct ata_port *ap)
+{
+       if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+               /* restart engine */
+               ahci_stop_engine(ap);
+               ahci_start_engine(ap);
+       }
+
+       /* perform recovery */
+       ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_p5wdh_hardreset,
+                 ahci_postreset);
+}
+
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
@@ -1701,36 +1898,6 @@ static void ahci_pmp_detach(struct ata_port *ap)
        writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
-static int ahci_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val)
-{
-       struct ata_port *ap = dev->link->ap;
-       struct ata_taskfile tf;
-       int rc;
-
-       ahci_kick_engine(ap, 0);
-
-       sata_pmp_read_init_tf(&tf, dev, pmp, reg);
-       rc = ahci_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0,
-                                 SATA_PMP_SCR_TIMEOUT);
-       if (rc == 0) {
-               ahci_tf_read(ap, &tf);
-               *r_val = sata_pmp_read_val(&tf);
-       }
-       return rc;
-}
-
-static int ahci_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val)
-{
-       struct ata_port *ap = dev->link->ap;
-       struct ata_taskfile tf;
-
-       ahci_kick_engine(ap, 0);
-
-       sata_pmp_write_init_tf(&tf, dev, pmp, reg, val);
-       return ahci_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0,
-                                   SATA_PMP_SCR_TIMEOUT);
-}
-
 static int ahci_port_resume(struct ata_port *ap)
 {
        ahci_power_up(ap);
@@ -1853,9 +2020,9 @@ static int ahci_port_start(struct ata_port *ap)
        pp->cmd_tbl_dma = mem_dma;
 
        /*
-        * Save off initial list of interrupts to be enabled.
-        * This could be changed later
-        */
+        * Save off initial list of interrupts to be enabled.
+        * This could be changed later
+        */
        pp->intr_mask = DEF_PORT_IRQ;
 
        ap->private_data = pp;
@@ -1942,12 +2109,12 @@ static void ahci_print_info(struct ata_host *host)
        dev_printk(KERN_INFO, &pdev->dev,
                "AHCI %02x%02x.%02x%02x "
                "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
-               ,
+               ,
 
-               (vers >> 24) & 0xff,
-               (vers >> 16) & 0xff,
-               (vers >> 8) & 0xff,
-               vers & 0xff,
+               (vers >> 24) & 0xff,
+               (vers >> 16) & 0xff,
+               (vers >> 8) & 0xff,
+               vers & 0xff,
 
                ((cap >> 8) & 0x1f) + 1,
                (cap & 0x1f) + 1,
@@ -1959,7 +2126,7 @@ static void ahci_print_info(struct ata_host *host)
                "flags: "
                "%s%s%s%s%s%s%s"
                "%s%s%s%s%s%s%s\n"
-               ,
+               ,
 
                cap & (1 << 31) ? "64bit " : "",
                cap & (1 << 30) ? "ncq " : "",
@@ -1979,6 +2146,51 @@ static void ahci_print_info(struct ata_host *host)
                );
 }
 
+/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
+ * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
+ * support PMP and the 4726 either directly exports the device
+ * attached to the first downstream port or acts as a hardware storage
+ * controller and emulate a single ATA device (can be RAID 0/1 or some
+ * other configuration).
+ *
+ * When there's no device attached to the first downstream port of the
+ * 4726, "Config Disk" appears, which is a pseudo ATA device to
+ * configure the 4726.  However, ATA emulation of the device is very
+ * lame.  It doesn't send signature D2H Reg FIS after the initial
+ * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
+ *
+ * The following function works around the problem by always using
+ * hardreset on the port and not depending on receiving signature FIS
+ * afterward.  If signature FIS isn't received soon, ATA class is
+ * assumed without follow-up softreset.
+ */
+static void ahci_p5wdh_workaround(struct ata_host *host)
+{
+       static struct dmi_system_id sysids[] = {
+               {
+                       .ident = "P5W DH Deluxe",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR,
+                                         "ASUSTEK COMPUTER INC"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
+                       },
+               },
+               { }
+       };
+       struct pci_dev *pdev = to_pci_dev(host->dev);
+
+       if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
+           dmi_check_system(sysids)) {
+               struct ata_port *ap = host->ports[1];
+
+               dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
+                          "Deluxe on-board SIMG4726 workaround\n");
+
+               ap->ops = &ahci_p5wdh_ops;
+               ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
+       }
+}
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version;
@@ -2007,6 +2219,22 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+           (pdev->device == 0x2652 || pdev->device == 0x2653)) {
+               u8 map;
+
+               /* ICH6s share the same PCI ID for both piix and ahci
+                * modes.  Enabling ahci mode while MAP indicates
+                * combined mode is a bad idea.  Yield to ata_piix.
+                */
+               pci_read_config_byte(pdev, ICH_MAP, &map);
+               if (map & 0x3) {
+                       dev_printk(KERN_INFO, &pdev->dev, "controller is in "
+                                  "combined mode, can't enable AHCI mode\n");
+                       return -ENODEV;
+               }
+       }
+
        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
        if (!hpriv)
                return -ENOMEM;
@@ -2039,6 +2267,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                ata_port_pbar_desc(ap, AHCI_PCI_BAR,
                                   0x100 + ap->port_no * 0x80, "port");
 
+               /* set initial link pm policy */
+               ap->pm_policy = NOT_AVAILABLE;
+
                /* standard SATA port setup */
                if (hpriv->port_map & (1 << i))
                        ap->ioaddr.cmd_addr = port_mmio;
@@ -2048,6 +2279,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                        ap->ops = &ata_dummy_port_ops;
        }
 
+       /* apply workaround for ASUS P5W DH Deluxe mainboard */
+       ahci_p5wdh_workaround(host);
+
        /* initialize adapter */
        rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
        if (rc)