intelfb: support i854
[safe/jmp/linux-2.6] / drivers / ata / ahci.c
index 3c71d31..08186ec 100644 (file)
 #define DRV_NAME       "ahci"
 #define DRV_VERSION    "3.0"
 
+/* Enclosure Management Control */
+#define EM_CTRL_MSG_TYPE              0x000f0000
+
+/* Enclosure Management LED Message Type */
+#define EM_MSG_LED_HBA_PORT           0x0000000f
+#define EM_MSG_LED_PMP_SLOT           0x0000ff00
+#define EM_MSG_LED_VALUE              0xffff0000
+#define EM_MSG_LED_VALUE_ACTIVITY     0x00070000
+#define EM_MSG_LED_VALUE_OFF          0xfff80000
+#define EM_MSG_LED_VALUE_ON           0x00010000
+
 static int ahci_skip_host_reset;
+static int ahci_ignore_sss;
+
 module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
 MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
 
+module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
+MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
+
 static int ahci_enable_alpm(struct ata_port *ap,
                enum link_pm policy);
 static void ahci_disable_alpm(struct ata_port *ap);
@@ -62,6 +78,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
 static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
                                        ssize_t size);
 #define MAX_SLOTS 8
+#define MAX_RETRY 15
 
 enum {
        AHCI_PCI_BAR            = 5,
@@ -94,9 +111,10 @@ enum {
        board_ahci_ign_iferr    = 2,
        board_ahci_sb600        = 3,
        board_ahci_mv           = 4,
-       board_ahci_sb700        = 5,
+       board_ahci_sb700        = 5, /* for SB700 and SB800 */
        board_ahci_mcp65        = 6,
        board_ahci_nopmp        = 7,
+       board_ahci_yesncq       = 8,
 
        /* global controller registers */
        HOST_CAP                = 0x00, /* host capabilities */
@@ -388,7 +406,7 @@ static const struct ata_port_info ahci_port_info[] = {
        /* board_ahci */
        {
                .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = 0x1f, /* pio0-4 */
+               .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
@@ -396,7 +414,7 @@ static const struct ata_port_info ahci_port_info[] = {
        {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
                .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = 0x1f, /* pio0-4 */
+               .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_vt8251_ops,
        },
@@ -404,7 +422,7 @@ static const struct ata_port_info ahci_port_info[] = {
        {
                AHCI_HFLAGS     (AHCI_HFLAG_IGN_IRQ_IF_ERR),
                .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = 0x1f, /* pio0-4 */
+               .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
@@ -414,7 +432,7 @@ static const struct ata_port_info ahci_port_info[] = {
                                 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
                                 AHCI_HFLAG_SECT255),
                .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = 0x1f, /* pio0-4 */
+               .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_sb600_ops,
        },
@@ -424,15 +442,15 @@ static const struct ata_port_info ahci_port_info[] = {
                                 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
-               .pio_mask       = 0x1f, /* pio0-4 */
+               .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
-       /* board_ahci_sb700 */
+       /* board_ahci_sb700, for SB700 and SB800 */
        {
                AHCI_HFLAGS     (AHCI_HFLAG_IGN_SERR_INTERNAL),
                .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = 0x1f, /* pio0-4 */
+               .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_sb600_ops,
        },
@@ -440,7 +458,7 @@ static const struct ata_port_info ahci_port_info[] = {
        {
                AHCI_HFLAGS     (AHCI_HFLAG_YES_NCQ),
                .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = 0x1f, /* pio0-4 */
+               .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
@@ -448,7 +466,15 @@ static const struct ata_port_info ahci_port_info[] = {
        {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_PMP),
                .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = 0x1f, /* pio0-4 */
+               .pio_mask       = ATA_PIO4,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &ahci_ops,
+       },
+       /* board_ahci_yesncq */
+       {
+               AHCI_HFLAGS     (AHCI_HFLAG_YES_NCQ),
+               .flags          = AHCI_FLAG_COMMON,
+               .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
@@ -518,30 +544,30 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },      /* MCP65 */
        { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },      /* MCP65 */
        { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },      /* MCP65 */
-       { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci },            /* MCP67 */
-       { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci },            /* MCP73 */
-       { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci },            /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_yesncq },     /* MCP67 */
+       { 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, 0x07f0), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_yesncq },     /* MCP73 */
+       { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_yesncq },     /* MCP73 */
        { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci },            /* MCP77 */
        { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci },            /* MCP77 */
        { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci },            /* MCP77 */
@@ -566,18 +592,18 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci },            /* MCP79 */
        { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci },            /* MCP79 */
        { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci },            /* MCP79 */
-       { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci },            /* MCP7B */
+       { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci },            /* MCP89 */
 
        /* SiS */
        { PCI_VDEVICE(SI, 0x1184), board_ahci },                /* SiS 966 */
@@ -1099,6 +1125,8 @@ static void ahci_start_port(struct ata_port *ap)
        struct ahci_port_priv *pp = ap->private_data;
        struct ata_link *link;
        struct ahci_em_priv *emp;
+       ssize_t rc;
+       int i;
 
        /* enable FIS reception */
        ahci_start_fis_rx(ap);
@@ -1108,14 +1136,24 @@ static void ahci_start_port(struct ata_port *ap)
 
        /* turn on LEDs */
        if (ap->flags & ATA_FLAG_EM) {
-               ata_port_for_each_link(link, ap) {
+               ata_for_each_link(link, ap, EDGE) {
                        emp = &pp->em_priv[link->pmp];
-                       ahci_transmit_led_message(ap, emp->led_state, 4);
+
+                       /* EM Transmit bit maybe busy during init */
+                       for (i = 0; i < MAX_RETRY; i++) {
+                               rc = ahci_transmit_led_message(ap,
+                                                              emp->led_state,
+                                                              4);
+                               if (rc == -EBUSY)
+                                       udelay(100);
+                               else
+                                       break;
+                       }
                }
        }
 
        if (ap->flags & ATA_FLAG_SW_ACTIVITY)
-               ata_port_for_each_link(link, ap)
+               ata_for_each_link(link, ap, EDGE)
                        ahci_init_sw_activity(link);
 
 }
@@ -1225,7 +1263,7 @@ static void ahci_sw_activity_blink(unsigned long arg)
        u32 activity_led_state;
        unsigned long flags;
 
-       led_message &= 0xffff0000;
+       led_message &= EM_MSG_LED_VALUE;
        led_message |= ap->port_no | (link->pmp << 8);
 
        /* check to see if we've had activity.  If so,
@@ -1236,7 +1274,7 @@ static void ahci_sw_activity_blink(unsigned long arg)
        if (emp->saved_activity != emp->activity) {
                emp->saved_activity = emp->activity;
                /* get the current LED state */
-               activity_led_state = led_message & 0x00010000;
+               activity_led_state = led_message & EM_MSG_LED_VALUE_ON;
 
                if (activity_led_state)
                        activity_led_state = 0;
@@ -1244,14 +1282,14 @@ static void ahci_sw_activity_blink(unsigned long arg)
                        activity_led_state = 1;
 
                /* clear old state */
-               led_message &= 0xfff8ffff;
+               led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
 
                /* toggle state */
                led_message |= (activity_led_state << 16);
                mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
        } else {
                /* switch to idle */
-               led_message &= 0xfff8ffff;
+               led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
                if (emp->blink_policy == BLINK_OFF)
                        led_message |= (1 << 16);
        }
@@ -1300,7 +1338,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
        struct ahci_em_priv *emp;
 
        /* get the slot number from the message */
-       pmp = (state & 0x0000ff00) >> 8;
+       pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
        if (pmp < MAX_SLOTS)
                emp = &pp->em_priv[pmp];
        else
@@ -1315,7 +1353,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
        em_ctl = readl(mmio + HOST_EM_CTL);
        if (em_ctl & EM_CTL_TM) {
                spin_unlock_irqrestore(ap->lock, flags);
-               return -EINVAL;
+               return -EBUSY;
        }
 
        /*
@@ -1325,14 +1363,14 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
        message[0] |= (4 << 8);
 
        /* ignore 0:4 of byte zero, fill in port info yourself */
-       message[1] = ((state & 0xfffffff0) | ap->port_no);
+       message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no);
 
        /* write message to EM_LOC */
        writel(message[0], mmio + hpriv->em_loc);
        writel(message[1], mmio + hpriv->em_loc+4);
 
        /* save off new led state for port/slot */
-       emp->led_state = message[1];
+       emp->led_state = state;
 
        /*
         * tell hardware to transmit the message
@@ -1350,7 +1388,7 @@ static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
        struct ahci_em_priv *emp;
        int rc = 0;
 
-       ata_port_for_each_link(link, ap) {
+       ata_for_each_link(link, ap, EDGE) {
                emp = &pp->em_priv[link->pmp];
                rc += sprintf(buf, "%lx\n", emp->led_state);
        }
@@ -1368,7 +1406,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
        state = simple_strtoul(buf, NULL, 0);
 
        /* get the slot number from the message */
-       pmp = (state & 0x0000ff00) >> 8;
+       pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
        if (pmp < MAX_SLOTS)
                emp = &pp->em_priv[pmp];
        else
@@ -1379,7 +1417,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
         * activity led through em_message
         */
        if (emp->blink_policy)
-               state &= 0xfff8ffff;
+               state &= ~EM_MSG_LED_VALUE_ACTIVITY;
 
        return ahci_transmit_led_message(ap, state, size);
 }
@@ -1398,16 +1436,16 @@ static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
                link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
 
                /* set the LED to OFF */
-               port_led_state &= 0xfff80000;
+               port_led_state &= EM_MSG_LED_VALUE_OFF;
                port_led_state |= (ap->port_no | (link->pmp << 8));
                ahci_transmit_led_message(ap, port_led_state, 4);
        } else {
                link->flags |= ATA_LFLAG_SW_ACTIVITY;
                if (val == BLINK_OFF) {
                        /* set LED to ON for idle */
-                       port_led_state &= 0xfff80000;
+                       port_led_state &= EM_MSG_LED_VALUE_OFF;
                        port_led_state |= (ap->port_no | (link->pmp << 8));
-                       port_led_state |= 0x00010000; /* check this */
+                       port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */
                        ahci_transmit_led_message(ap, port_led_state, 4);
                }
        }
@@ -1930,7 +1968,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
        u32 serror;
 
        /* determine active link */
-       ata_port_for_each_link(link, ap)
+       ata_for_each_link(link, ap, EDGE)
                if (ata_link_active(link))
                        break;
        if (!link)
@@ -2389,10 +2427,10 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
        int rc;
 
        if (using_dac &&
-           !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-               rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
                if (rc) {
-                       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+                       rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
                        if (rc) {
                                dev_printk(KERN_ERR, &pdev->dev,
                                           "64-bit DMA enable failed\n");
@@ -2400,13 +2438,13 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
                        }
                }
        } else {
-               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_printk(KERN_ERR, &pdev->dev,
                                   "32-bit DMA enable failed\n");
                        return rc;
                }
-               rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
                if (rc) {
                        dev_printk(KERN_ERR, &pdev->dev,
                                   "32-bit consistent DMA enable failed\n");
@@ -2435,6 +2473,8 @@ static void ahci_print_info(struct ata_host *host)
                speed_s = "1.5";
        else if (speed == 2)
                speed_s = "3";
+       else if (speed == 3)
+               speed_s = "6";
        else
                speed_s = "?";
 
@@ -2535,6 +2575,41 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
        }
 }
 
+static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
+{
+       static const struct dmi_system_id broken_systems[] = {
+               {
+                       .ident = "HP Compaq nx6310",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
+                       },
+                       /* PCI slot number of the controller */
+                       .driver_data = (void *)0x1FUL,
+               },
+               {
+                       .ident = "HP Compaq 6720s",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
+                       },
+                       /* PCI slot number of the controller */
+                       .driver_data = (void *)0x1FUL,
+               },
+
+               { }     /* terminate list */
+       };
+       const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+       if (dmi) {
+               unsigned long slot = (unsigned long)dmi->driver_data;
+               /* apply the quirk only to on-board controllers */
+               return slot == PCI_SLOT(pdev->devfn);
+       }
+
+       return false;
+}
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version;
@@ -2599,8 +2674,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
            (pdev->revision == 0xa1 || pdev->revision == 0xa2))
                hpriv->flags |= AHCI_HFLAG_NO_MSI;
 
-       if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
-               pci_intx(pdev, 1);
+       /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
+       if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
+               hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
+
+       if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
+               pci_enable_msi(pdev);
 
        /* save initial config */
        ahci_save_initial_config(pdev, hpriv);
@@ -2618,7 +2697,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                u32 em_loc = readl(mmio + HOST_EM_LOC);
                u32 em_ctl = readl(mmio + HOST_EM_CTL);
 
-               messages = (em_ctl & 0x000f0000) >> 16;
+               messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16;
 
                /* we only support LED message type right now */
                if ((messages & 0x01) && (ahci_em_messages == 1)) {
@@ -2630,6 +2709,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
+       if (ahci_broken_system_poweroff(pdev)) {
+               pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
+               dev_info(&pdev->dev,
+                       "quirky BIOS, skipping spindown on poweroff\n");
+       }
+
        /* CAP.NP sometimes indicate the index of the last enabled
         * port, at other times, that of the last possible port, so
         * determining the maximum port number requires looking at
@@ -2643,6 +2728,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        host->iomap = pcim_iomap_table(pdev);
        host->private_data = hpriv;
 
+       if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
+               host->flags |= ATA_HOST_PARALLEL_SCAN;
+       else
+               printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
+
        if (pi.flags & ATA_FLAG_EM)
                ahci_reset_em(host);