diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 168 |
1 files changed, 136 insertions, 32 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 97f83fb2ee2e..6a4a2a25d97a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -89,6 +89,8 @@ 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, | ||
93 | board_ahci_nopmp = 7, | ||
92 | 94 | ||
93 | /* global controller registers */ | 95 | /* global controller registers */ |
94 | HOST_CAP = 0x00, /* host capabilities */ | 96 | HOST_CAP = 0x00, /* host capabilities */ |
@@ -190,6 +192,7 @@ enum { | |||
190 | AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ | 192 | AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ |
191 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ | 193 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ |
192 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ | 194 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ |
195 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ | ||
193 | 196 | ||
194 | /* ap->flags bits */ | 197 | /* ap->flags bits */ |
195 | 198 | ||
@@ -253,6 +256,8 @@ static void ahci_pmp_attach(struct ata_port *ap); | |||
253 | static void ahci_pmp_detach(struct ata_port *ap); | 256 | static void ahci_pmp_detach(struct ata_port *ap); |
254 | static int ahci_softreset(struct ata_link *link, unsigned int *class, | 257 | static int ahci_softreset(struct ata_link *link, unsigned int *class, |
255 | unsigned long deadline); | 258 | unsigned long deadline); |
259 | static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, | ||
260 | unsigned long deadline); | ||
256 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, | 261 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, |
257 | unsigned long deadline); | 262 | unsigned long deadline); |
258 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, | 263 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, |
@@ -329,6 +334,12 @@ static struct ata_port_operations ahci_p5wdh_ops = { | |||
329 | .hardreset = ahci_p5wdh_hardreset, | 334 | .hardreset = ahci_p5wdh_hardreset, |
330 | }; | 335 | }; |
331 | 336 | ||
337 | static struct ata_port_operations ahci_sb600_ops = { | ||
338 | .inherits = &ahci_ops, | ||
339 | .softreset = ahci_sb600_softreset, | ||
340 | .pmp_softreset = ahci_sb600_softreset, | ||
341 | }; | ||
342 | |||
332 | #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) | 343 | #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) |
333 | 344 | ||
334 | static const struct ata_port_info ahci_port_info[] = { | 345 | static const struct ata_port_info ahci_port_info[] = { |
@@ -359,11 +370,11 @@ static const struct ata_port_info ahci_port_info[] = { | |||
359 | { | 370 | { |
360 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | | 371 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | |
361 | AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | | 372 | AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | |
362 | AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP), | 373 | AHCI_HFLAG_SECT255), |
363 | .flags = AHCI_FLAG_COMMON, | 374 | .flags = AHCI_FLAG_COMMON, |
364 | .pio_mask = 0x1f, /* pio0-4 */ | 375 | .pio_mask = 0x1f, /* pio0-4 */ |
365 | .udma_mask = ATA_UDMA6, | 376 | .udma_mask = ATA_UDMA6, |
366 | .port_ops = &ahci_ops, | 377 | .port_ops = &ahci_sb600_ops, |
367 | }, | 378 | }, |
368 | /* board_ahci_mv */ | 379 | /* board_ahci_mv */ |
369 | { | 380 | { |
@@ -377,8 +388,23 @@ static const struct ata_port_info ahci_port_info[] = { | |||
377 | }, | 388 | }, |
378 | /* board_ahci_sb700 */ | 389 | /* board_ahci_sb700 */ |
379 | { | 390 | { |
380 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | | 391 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), |
381 | AHCI_HFLAG_NO_PMP), | 392 | .flags = AHCI_FLAG_COMMON, |
393 | .pio_mask = 0x1f, /* pio0-4 */ | ||
394 | .udma_mask = ATA_UDMA6, | ||
395 | .port_ops = &ahci_sb600_ops, | ||
396 | }, | ||
397 | /* board_ahci_mcp65 */ | ||
398 | { | ||
399 | AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), | ||
400 | .flags = AHCI_FLAG_COMMON, | ||
401 | .pio_mask = 0x1f, /* pio0-4 */ | ||
402 | .udma_mask = ATA_UDMA6, | ||
403 | .port_ops = &ahci_ops, | ||
404 | }, | ||
405 | /* board_ahci_nopmp */ | ||
406 | { | ||
407 | AHCI_HFLAGS (AHCI_HFLAG_NO_PMP), | ||
382 | .flags = AHCI_FLAG_COMMON, | 408 | .flags = AHCI_FLAG_COMMON, |
383 | .pio_mask = 0x1f, /* pio0-4 */ | 409 | .pio_mask = 0x1f, /* pio0-4 */ |
384 | .udma_mask = ATA_UDMA6, | 410 | .udma_mask = ATA_UDMA6, |
@@ -438,14 +464,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
438 | { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ | 464 | { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ |
439 | 465 | ||
440 | /* NVIDIA */ | 466 | /* NVIDIA */ |
441 | { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci }, /* MCP65 */ | 467 | { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ |
442 | { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci }, /* MCP65 */ | 468 | { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ |
443 | { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci }, /* MCP65 */ | 469 | { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ |
444 | { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci }, /* MCP65 */ | 470 | { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ |
445 | { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci }, /* MCP65 */ | 471 | { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ |
446 | { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci }, /* MCP65 */ | 472 | { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ |
447 | { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci }, /* MCP65 */ | 473 | { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ |
448 | { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci }, /* MCP65 */ | 474 | { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ |
449 | { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */ | 475 | { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */ |
450 | { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */ | 476 | { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */ |
451 | { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */ | 477 | { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */ |
@@ -502,15 +528,15 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
502 | { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */ | 528 | { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */ |
503 | { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */ | 529 | { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */ |
504 | { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */ | 530 | { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */ |
505 | { PCI_VDEVICE(NVIDIA, 0x0bd0), board_ahci }, /* MCP7B */ | 531 | { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */ |
506 | { PCI_VDEVICE(NVIDIA, 0x0bd1), board_ahci }, /* MCP7B */ | 532 | { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */ |
507 | { PCI_VDEVICE(NVIDIA, 0x0bd2), board_ahci }, /* MCP7B */ | 533 | { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */ |
508 | { PCI_VDEVICE(NVIDIA, 0x0bd3), board_ahci }, /* MCP7B */ | 534 | { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */ |
509 | 535 | ||
510 | /* SiS */ | 536 | /* SiS */ |
511 | { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ | 537 | { PCI_VDEVICE(SI, 0x1184), board_ahci_nopmp }, /* SiS 966 */ |
512 | { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ | 538 | { PCI_VDEVICE(SI, 0x1185), board_ahci_nopmp }, /* SiS 968 */ |
513 | { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ | 539 | { PCI_VDEVICE(SI, 0x0186), board_ahci_nopmp }, /* SiS 968 */ |
514 | 540 | ||
515 | /* Marvell */ | 541 | /* Marvell */ |
516 | { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ | 542 | { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ |
@@ -624,12 +650,26 @@ static void ahci_save_initial_config(struct pci_dev *pdev, | |||
624 | cap &= ~HOST_CAP_NCQ; | 650 | cap &= ~HOST_CAP_NCQ; |
625 | } | 651 | } |
626 | 652 | ||
653 | if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) { | ||
654 | dev_printk(KERN_INFO, &pdev->dev, | ||
655 | "controller can do NCQ, turning on CAP_NCQ\n"); | ||
656 | cap |= HOST_CAP_NCQ; | ||
657 | } | ||
658 | |||
627 | if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) { | 659 | if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) { |
628 | dev_printk(KERN_INFO, &pdev->dev, | 660 | dev_printk(KERN_INFO, &pdev->dev, |
629 | "controller can't do PMP, turning off CAP_PMP\n"); | 661 | "controller can't do PMP, turning off CAP_PMP\n"); |
630 | cap &= ~HOST_CAP_PMP; | 662 | cap &= ~HOST_CAP_PMP; |
631 | } | 663 | } |
632 | 664 | ||
665 | if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 && | ||
666 | port_map != 1) { | ||
667 | dev_printk(KERN_INFO, &pdev->dev, | ||
668 | "JMB361 has only one port, port_map 0x%x -> 0x%x\n", | ||
669 | port_map, 1); | ||
670 | port_map = 1; | ||
671 | } | ||
672 | |||
633 | /* | 673 | /* |
634 | * Temporary Marvell 6145 hack: PATA port presence | 674 | * Temporary Marvell 6145 hack: PATA port presence |
635 | * is asserted through the standard AHCI port | 675 | * is asserted through the standard AHCI port |
@@ -1262,19 +1302,11 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp, | |||
1262 | return 0; | 1302 | return 0; |
1263 | } | 1303 | } |
1264 | 1304 | ||
1265 | static int ahci_check_ready(struct ata_link *link) | 1305 | static int ahci_do_softreset(struct ata_link *link, unsigned int *class, |
1266 | { | 1306 | int pmp, unsigned long deadline, |
1267 | void __iomem *port_mmio = ahci_port_base(link->ap); | 1307 | int (*check_ready)(struct ata_link *link)) |
1268 | u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; | ||
1269 | |||
1270 | return ata_check_ready(status); | ||
1271 | } | ||
1272 | |||
1273 | static int ahci_softreset(struct ata_link *link, unsigned int *class, | ||
1274 | unsigned long deadline) | ||
1275 | { | 1308 | { |
1276 | struct ata_port *ap = link->ap; | 1309 | struct ata_port *ap = link->ap; |
1277 | int pmp = sata_srst_pmp(link); | ||
1278 | const char *reason = NULL; | 1310 | const char *reason = NULL; |
1279 | unsigned long now, msecs; | 1311 | unsigned long now, msecs; |
1280 | struct ata_taskfile tf; | 1312 | struct ata_taskfile tf; |
@@ -1312,7 +1344,7 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class, | |||
1312 | ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0); | 1344 | ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0); |
1313 | 1345 | ||
1314 | /* wait for link to become ready */ | 1346 | /* wait for link to become ready */ |
1315 | rc = ata_wait_after_reset(link, deadline, ahci_check_ready); | 1347 | rc = ata_wait_after_reset(link, deadline, check_ready); |
1316 | /* link occupied, -ENODEV too is an error */ | 1348 | /* link occupied, -ENODEV too is an error */ |
1317 | if (rc) { | 1349 | if (rc) { |
1318 | reason = "device not ready"; | 1350 | reason = "device not ready"; |
@@ -1328,6 +1360,72 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class, | |||
1328 | return rc; | 1360 | return rc; |
1329 | } | 1361 | } |
1330 | 1362 | ||
1363 | static int ahci_check_ready(struct ata_link *link) | ||
1364 | { | ||
1365 | void __iomem *port_mmio = ahci_port_base(link->ap); | ||
1366 | u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; | ||
1367 | |||
1368 | return ata_check_ready(status); | ||
1369 | } | ||
1370 | |||
1371 | static int ahci_softreset(struct ata_link *link, unsigned int *class, | ||
1372 | unsigned long deadline) | ||
1373 | { | ||
1374 | int pmp = sata_srst_pmp(link); | ||
1375 | |||
1376 | DPRINTK("ENTER\n"); | ||
1377 | |||
1378 | return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready); | ||
1379 | } | ||
1380 | |||
1381 | static int ahci_sb600_check_ready(struct ata_link *link) | ||
1382 | { | ||
1383 | void __iomem *port_mmio = ahci_port_base(link->ap); | ||
1384 | u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; | ||
1385 | u32 irq_status = readl(port_mmio + PORT_IRQ_STAT); | ||
1386 | |||
1387 | /* | ||
1388 | * There is no need to check TFDATA if BAD PMP is found due to HW bug, | ||
1389 | * which can save timeout delay. | ||
1390 | */ | ||
1391 | if (irq_status & PORT_IRQ_BAD_PMP) | ||
1392 | return -EIO; | ||
1393 | |||
1394 | return ata_check_ready(status); | ||
1395 | } | ||
1396 | |||
1397 | static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, | ||
1398 | unsigned long deadline) | ||
1399 | { | ||
1400 | struct ata_port *ap = link->ap; | ||
1401 | void __iomem *port_mmio = ahci_port_base(ap); | ||
1402 | int pmp = sata_srst_pmp(link); | ||
1403 | int rc; | ||
1404 | u32 irq_sts; | ||
1405 | |||
1406 | DPRINTK("ENTER\n"); | ||
1407 | |||
1408 | rc = ahci_do_softreset(link, class, pmp, deadline, | ||
1409 | ahci_sb600_check_ready); | ||
1410 | |||
1411 | /* | ||
1412 | * Soft reset fails on some ATI chips with IPMS set when PMP | ||
1413 | * is enabled but SATA HDD/ODD is connected to SATA port, | ||
1414 | * do soft reset again to port 0. | ||
1415 | */ | ||
1416 | if (rc == -EIO) { | ||
1417 | irq_sts = readl(port_mmio + PORT_IRQ_STAT); | ||
1418 | if (irq_sts & PORT_IRQ_BAD_PMP) { | ||
1419 | ata_link_printk(link, KERN_WARNING, | ||
1420 | "failed due to HW bug, retry pmp=0\n"); | ||
1421 | rc = ahci_do_softreset(link, class, 0, deadline, | ||
1422 | ahci_check_ready); | ||
1423 | } | ||
1424 | } | ||
1425 | |||
1426 | return rc; | ||
1427 | } | ||
1428 | |||
1331 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, | 1429 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, |
1332 | unsigned long deadline) | 1430 | unsigned long deadline) |
1333 | { | 1431 | { |
@@ -2118,7 +2216,8 @@ static void ahci_p5wdh_workaround(struct ata_host *host) | |||
2118 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 2216 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
2119 | { | 2217 | { |
2120 | static int printed_version; | 2218 | static int printed_version; |
2121 | struct ata_port_info pi = ahci_port_info[ent->driver_data]; | 2219 | unsigned int board_id = ent->driver_data; |
2220 | struct ata_port_info pi = ahci_port_info[board_id]; | ||
2122 | const struct ata_port_info *ppi[] = { &pi, NULL }; | 2221 | const struct ata_port_info *ppi[] = { &pi, NULL }; |
2123 | struct device *dev = &pdev->dev; | 2222 | struct device *dev = &pdev->dev; |
2124 | struct ahci_host_priv *hpriv; | 2223 | struct ahci_host_priv *hpriv; |
@@ -2167,6 +2266,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2167 | return -ENOMEM; | 2266 | return -ENOMEM; |
2168 | hpriv->flags |= (unsigned long)pi.private_data; | 2267 | hpriv->flags |= (unsigned long)pi.private_data; |
2169 | 2268 | ||
2269 | /* MCP65 revision A1 and A2 can't do MSI */ | ||
2270 | if (board_id == board_ahci_mcp65 && | ||
2271 | (pdev->revision == 0xa1 || pdev->revision == 0xa2)) | ||
2272 | hpriv->flags |= AHCI_HFLAG_NO_MSI; | ||
2273 | |||
2170 | if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) | 2274 | if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) |
2171 | pci_intx(pdev, 1); | 2275 | pci_intx(pdev, 1); |
2172 | 2276 | ||