aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-13 23:52:39 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-13 23:52:39 -0400
commit4ae127d1b6c71f9240dd4245f240e6dd8fc98014 (patch)
treeb7aa27b3e0c655f4613fe2146cb57d7f69e421f6 /drivers/ata/ahci.c
parent875ec4333b99144e2589e900a0bcd2c25c757b27 (diff)
parent7775c9753b94fe429dc4323360d6502c95e0dd6e (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/smc911x.c
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c137
1 files changed, 112 insertions, 25 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 544b7d6c617c..966ab401e523 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
@@ -253,6 +255,8 @@ static void ahci_pmp_attach(struct ata_port *ap);
253static void ahci_pmp_detach(struct ata_port *ap); 255static void ahci_pmp_detach(struct ata_port *ap);
254static int ahci_softreset(struct ata_link *link, unsigned int *class, 256static int ahci_softreset(struct ata_link *link, unsigned int *class,
255 unsigned long deadline); 257 unsigned long deadline);
258static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
259 unsigned long deadline);
256static int ahci_hardreset(struct ata_link *link, unsigned int *class, 260static int ahci_hardreset(struct ata_link *link, unsigned int *class,
257 unsigned long deadline); 261 unsigned long deadline);
258static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 262static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
@@ -329,6 +333,12 @@ static struct ata_port_operations ahci_p5wdh_ops = {
329 .hardreset = ahci_p5wdh_hardreset, 333 .hardreset = ahci_p5wdh_hardreset,
330}; 334};
331 335
336static struct ata_port_operations ahci_sb600_ops = {
337 .inherits = &ahci_ops,
338 .softreset = ahci_sb600_softreset,
339 .pmp_softreset = ahci_sb600_softreset,
340};
341
332#define AHCI_HFLAGS(flags) .private_data = (void *)(flags) 342#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
333 343
334static const struct ata_port_info ahci_port_info[] = { 344static const struct ata_port_info ahci_port_info[] = {
@@ -359,11 +369,11 @@ static const struct ata_port_info ahci_port_info[] = {
359 { 369 {
360 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 370 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
361 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | 371 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
362 AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP), 372 AHCI_HFLAG_SECT255),
363 .flags = AHCI_FLAG_COMMON, 373 .flags = AHCI_FLAG_COMMON,
364 .pio_mask = 0x1f, /* pio0-4 */ 374 .pio_mask = 0x1f, /* pio0-4 */
365 .udma_mask = ATA_UDMA6, 375 .udma_mask = ATA_UDMA6,
366 .port_ops = &ahci_ops, 376 .port_ops = &ahci_sb600_ops,
367 }, 377 },
368 /* board_ahci_mv */ 378 /* board_ahci_mv */
369 { 379 {
@@ -377,8 +387,15 @@ static const struct ata_port_info ahci_port_info[] = {
377 }, 387 },
378 /* board_ahci_sb700 */ 388 /* board_ahci_sb700 */
379 { 389 {
380 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 390 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
381 AHCI_HFLAG_NO_PMP), 391 .flags = AHCI_FLAG_COMMON,
392 .pio_mask = 0x1f, /* pio0-4 */
393 .udma_mask = ATA_UDMA6,
394 .port_ops = &ahci_sb600_ops,
395 },
396 /* board_ahci_mcp65 */
397 {
398 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
382 .flags = AHCI_FLAG_COMMON, 399 .flags = AHCI_FLAG_COMMON,
383 .pio_mask = 0x1f, /* pio0-4 */ 400 .pio_mask = 0x1f, /* pio0-4 */
384 .udma_mask = ATA_UDMA6, 401 .udma_mask = ATA_UDMA6,
@@ -438,14 +455,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
438 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 455 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
439 456
440 /* NVIDIA */ 457 /* NVIDIA */
441 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci }, /* MCP65 */ 458 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */
442 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci }, /* MCP65 */ 459 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */
443 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci }, /* MCP65 */ 460 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */
444 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci }, /* MCP65 */ 461 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */
445 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci }, /* MCP65 */ 462 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */
446 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci }, /* MCP65 */ 463 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */
447 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci }, /* MCP65 */ 464 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */
448 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci }, /* MCP65 */ 465 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */
449 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */ 466 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */
450 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */ 467 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */
451 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */ 468 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */
@@ -624,6 +641,12 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
624 cap &= ~HOST_CAP_NCQ; 641 cap &= ~HOST_CAP_NCQ;
625 } 642 }
626 643
644 if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
645 dev_printk(KERN_INFO, &pdev->dev,
646 "controller can do NCQ, turning on CAP_NCQ\n");
647 cap |= HOST_CAP_NCQ;
648 }
649
627 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) { 650 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
628 dev_printk(KERN_INFO, &pdev->dev, 651 dev_printk(KERN_INFO, &pdev->dev,
629 "controller can't do PMP, turning off CAP_PMP\n"); 652 "controller can't do PMP, turning off CAP_PMP\n");
@@ -1262,19 +1285,11 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
1262 return 0; 1285 return 0;
1263} 1286}
1264 1287
1265static int ahci_check_ready(struct ata_link *link) 1288static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1266{ 1289 int pmp, unsigned long deadline,
1267 void __iomem *port_mmio = ahci_port_base(link->ap); 1290 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
1273static int ahci_softreset(struct ata_link *link, unsigned int *class,
1274 unsigned long deadline)
1275{ 1291{
1276 struct ata_port *ap = link->ap; 1292 struct ata_port *ap = link->ap;
1277 int pmp = sata_srst_pmp(link);
1278 const char *reason = NULL; 1293 const char *reason = NULL;
1279 unsigned long now, msecs; 1294 unsigned long now, msecs;
1280 struct ata_taskfile tf; 1295 struct ata_taskfile tf;
@@ -1312,7 +1327,7 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class,
1312 ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0); 1327 ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
1313 1328
1314 /* wait for link to become ready */ 1329 /* wait for link to become ready */
1315 rc = ata_wait_after_reset(link, deadline, ahci_check_ready); 1330 rc = ata_wait_after_reset(link, deadline, check_ready);
1316 /* link occupied, -ENODEV too is an error */ 1331 /* link occupied, -ENODEV too is an error */
1317 if (rc) { 1332 if (rc) {
1318 reason = "device not ready"; 1333 reason = "device not ready";
@@ -1328,6 +1343,72 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class,
1328 return rc; 1343 return rc;
1329} 1344}
1330 1345
1346static int ahci_check_ready(struct ata_link *link)
1347{
1348 void __iomem *port_mmio = ahci_port_base(link->ap);
1349 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1350
1351 return ata_check_ready(status);
1352}
1353
1354static int ahci_softreset(struct ata_link *link, unsigned int *class,
1355 unsigned long deadline)
1356{
1357 int pmp = sata_srst_pmp(link);
1358
1359 DPRINTK("ENTER\n");
1360
1361 return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
1362}
1363
1364static int ahci_sb600_check_ready(struct ata_link *link)
1365{
1366 void __iomem *port_mmio = ahci_port_base(link->ap);
1367 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1368 u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
1369
1370 /*
1371 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
1372 * which can save timeout delay.
1373 */
1374 if (irq_status & PORT_IRQ_BAD_PMP)
1375 return -EIO;
1376
1377 return ata_check_ready(status);
1378}
1379
1380static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
1381 unsigned long deadline)
1382{
1383 struct ata_port *ap = link->ap;
1384 void __iomem *port_mmio = ahci_port_base(ap);
1385 int pmp = sata_srst_pmp(link);
1386 int rc;
1387 u32 irq_sts;
1388
1389 DPRINTK("ENTER\n");
1390
1391 rc = ahci_do_softreset(link, class, pmp, deadline,
1392 ahci_sb600_check_ready);
1393
1394 /*
1395 * Soft reset fails on some ATI chips with IPMS set when PMP
1396 * is enabled but SATA HDD/ODD is connected to SATA port,
1397 * do soft reset again to port 0.
1398 */
1399 if (rc == -EIO) {
1400 irq_sts = readl(port_mmio + PORT_IRQ_STAT);
1401 if (irq_sts & PORT_IRQ_BAD_PMP) {
1402 ata_link_printk(link, KERN_WARNING,
1403 "failed due to HW bug, retry pmp=0\n");
1404 rc = ahci_do_softreset(link, class, 0, deadline,
1405 ahci_check_ready);
1406 }
1407 }
1408
1409 return rc;
1410}
1411
1331static int ahci_hardreset(struct ata_link *link, unsigned int *class, 1412static int ahci_hardreset(struct ata_link *link, unsigned int *class,
1332 unsigned long deadline) 1413 unsigned long deadline)
1333{ 1414{
@@ -2118,7 +2199,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) 2199static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2119{ 2200{
2120 static int printed_version; 2201 static int printed_version;
2121 struct ata_port_info pi = ahci_port_info[ent->driver_data]; 2202 unsigned int board_id = ent->driver_data;
2203 struct ata_port_info pi = ahci_port_info[board_id];
2122 const struct ata_port_info *ppi[] = { &pi, NULL }; 2204 const struct ata_port_info *ppi[] = { &pi, NULL };
2123 struct device *dev = &pdev->dev; 2205 struct device *dev = &pdev->dev;
2124 struct ahci_host_priv *hpriv; 2206 struct ahci_host_priv *hpriv;
@@ -2167,6 +2249,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2167 return -ENOMEM; 2249 return -ENOMEM;
2168 hpriv->flags |= (unsigned long)pi.private_data; 2250 hpriv->flags |= (unsigned long)pi.private_data;
2169 2251
2252 /* MCP65 revision A1 and A2 can't do MSI */
2253 if (board_id == board_ahci_mcp65 &&
2254 (pdev->revision == 0xa1 || pdev->revision == 0xa2))
2255 hpriv->flags |= AHCI_HFLAG_NO_MSI;
2256
2170 if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) 2257 if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
2171 pci_intx(pdev, 1); 2258 pci_intx(pdev, 1);
2172 2259