aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-06-09 11:13:04 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-06-13 02:46:17 -0400
commite297d99e103f951a71fcb1534f1ff3480dd3a851 (patch)
tree7e8b044efeb0f1ea048acba881a00e8326a4a0ab
parent5dd34572ad9a3be430632dd42e4af2ea370b397b (diff)
ahci: workarounds for mcp65
MCP65 ahci can do NCQ but doesn't set the CAP bit and rev A0 and A1 can't do MSI but have MSI capability. Implement AHCI_HFLAG_YES_NCQ and apply appropriate workarounds. Signed-off-by: Tejun Heo <htejun@gmail.com> Cc: Peer Chen <pchen@nvidia.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/ahci.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 544b7d6c617c..1c62b8e39645 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -89,6 +89,7 @@ enum {
89 board_ahci_sb600 = 3, 89 board_ahci_sb600 = 3,
90 board_ahci_mv = 4, 90 board_ahci_mv = 4,
91 board_ahci_sb700 = 5, 91 board_ahci_sb700 = 5,
92 board_ahci_mcp65 = 6,
92 93
93 /* global controller registers */ 94 /* global controller registers */
94 HOST_CAP = 0x00, /* host capabilities */ 95 HOST_CAP = 0x00, /* host capabilities */
@@ -190,6 +191,7 @@ enum {
190 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ 191 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
191 AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ 192 AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
192 AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ 193 AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
194 AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
193 195
194 /* ap->flags bits */ 196 /* ap->flags bits */
195 197
@@ -384,6 +386,14 @@ static const struct ata_port_info ahci_port_info[] = {
384 .udma_mask = ATA_UDMA6, 386 .udma_mask = ATA_UDMA6,
385 .port_ops = &ahci_ops, 387 .port_ops = &ahci_ops,
386 }, 388 },
389 /* board_ahci_mcp65 */
390 {
391 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
392 .flags = AHCI_FLAG_COMMON,
393 .pio_mask = 0x1f, /* pio0-4 */
394 .udma_mask = ATA_UDMA6,
395 .port_ops = &ahci_ops,
396 },
387}; 397};
388 398
389static const struct pci_device_id ahci_pci_tbl[] = { 399static const struct pci_device_id ahci_pci_tbl[] = {
@@ -438,14 +448,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
438 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 448 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
439 449
440 /* NVIDIA */ 450 /* NVIDIA */
441 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci }, /* MCP65 */ 451 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */
442 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci }, /* MCP65 */ 452 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */
443 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci }, /* MCP65 */ 453 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */
444 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci }, /* MCP65 */ 454 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */
445 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci }, /* MCP65 */ 455 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */
446 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci }, /* MCP65 */ 456 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */
447 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci }, /* MCP65 */ 457 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */
448 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci }, /* MCP65 */ 458 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */
449 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */ 459 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */
450 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */ 460 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */
451 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */ 461 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */
@@ -624,6 +634,12 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
624 cap &= ~HOST_CAP_NCQ; 634 cap &= ~HOST_CAP_NCQ;
625 } 635 }
626 636
637 if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
638 dev_printk(KERN_INFO, &pdev->dev,
639 "controller can do NCQ, turning on CAP_NCQ\n");
640 cap |= HOST_CAP_NCQ;
641 }
642
627 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) { 643 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
628 dev_printk(KERN_INFO, &pdev->dev, 644 dev_printk(KERN_INFO, &pdev->dev,
629 "controller can't do PMP, turning off CAP_PMP\n"); 645 "controller can't do PMP, turning off CAP_PMP\n");
@@ -2118,7 +2134,8 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
2118static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 2134static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2119{ 2135{
2120 static int printed_version; 2136 static int printed_version;
2121 struct ata_port_info pi = ahci_port_info[ent->driver_data]; 2137 unsigned int board_id = ent->driver_data;
2138 struct ata_port_info pi = ahci_port_info[board_id];
2122 const struct ata_port_info *ppi[] = { &pi, NULL }; 2139 const struct ata_port_info *ppi[] = { &pi, NULL };
2123 struct device *dev = &pdev->dev; 2140 struct device *dev = &pdev->dev;
2124 struct ahci_host_priv *hpriv; 2141 struct ahci_host_priv *hpriv;
@@ -2167,6 +2184,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2167 return -ENOMEM; 2184 return -ENOMEM;
2168 hpriv->flags |= (unsigned long)pi.private_data; 2185 hpriv->flags |= (unsigned long)pi.private_data;
2169 2186
2187 /* MCP65 revision A1 and A2 can't do MSI */
2188 if (board_id == board_ahci_mcp65 &&
2189 (pdev->revision == 0xa1 || pdev->revision == 0xa2))
2190 hpriv->flags |= AHCI_HFLAG_NO_MSI;
2191
2170 if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) 2192 if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
2171 pci_intx(pdev, 1); 2193 pci_intx(pdev, 1);
2172 2194