aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_nv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/sata_nv.c')
-rw-r--r--drivers/ata/sata_nv.c77
1 files changed, 49 insertions, 28 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 6f1460614325..444af0415ca1 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -305,10 +305,10 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
305static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 305static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
306static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 306static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
307 307
308static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
309 unsigned long deadline);
308static void nv_nf2_freeze(struct ata_port *ap); 310static void nv_nf2_freeze(struct ata_port *ap);
309static void nv_nf2_thaw(struct ata_port *ap); 311static void nv_nf2_thaw(struct ata_port *ap);
310static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
311 unsigned long deadline);
312static void nv_ck804_freeze(struct ata_port *ap); 312static void nv_ck804_freeze(struct ata_port *ap);
313static void nv_ck804_thaw(struct ata_port *ap); 313static void nv_ck804_thaw(struct ata_port *ap);
314static int nv_adma_slave_config(struct scsi_device *sdev); 314static int nv_adma_slave_config(struct scsi_device *sdev);
@@ -352,6 +352,7 @@ enum nv_host_type
352 NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ 352 NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */
353 CK804, 353 CK804,
354 ADMA, 354 ADMA,
355 MCP5x,
355 SWNCQ, 356 SWNCQ,
356}; 357};
357 358
@@ -363,10 +364,10 @@ static const struct pci_device_id nv_pci_tbl[] = {
363 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 }, 364 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },
364 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 }, 365 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },
365 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 }, 366 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },
366 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), SWNCQ }, 367 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), MCP5x },
367 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ }, 368 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), MCP5x },
368 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ }, 369 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), MCP5x },
369 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ }, 370 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), MCP5x },
370 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC }, 371 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
371 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC }, 372 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
372 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC }, 373 { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
@@ -432,14 +433,19 @@ static struct ata_port_operations nv_nf2_ops = {
432 .inherits = &nv_common_ops, 433 .inherits = &nv_common_ops,
433 .freeze = nv_nf2_freeze, 434 .freeze = nv_nf2_freeze,
434 .thaw = nv_nf2_thaw, 435 .thaw = nv_nf2_thaw,
435 .hardreset = nv_nf2_hardreset, 436 .hardreset = nv_noclassify_hardreset,
436}; 437};
437 438
438/* CK804 finally gets hardreset right */ 439/* For initial probing after boot and hot plugging, hardreset mostly
440 * works fine on CK804 but curiously, reprobing on the initial port by
441 * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS
442 * in somewhat undeterministic way. Use noclassify hardreset.
443 */
439static struct ata_port_operations nv_ck804_ops = { 444static struct ata_port_operations nv_ck804_ops = {
440 .inherits = &nv_common_ops, 445 .inherits = &nv_common_ops,
441 .freeze = nv_ck804_freeze, 446 .freeze = nv_ck804_freeze,
442 .thaw = nv_ck804_thaw, 447 .thaw = nv_ck804_thaw,
448 .hardreset = nv_noclassify_hardreset,
443 .host_stop = nv_ck804_host_stop, 449 .host_stop = nv_ck804_host_stop,
444}; 450};
445 451
@@ -467,8 +473,19 @@ static struct ata_port_operations nv_adma_ops = {
467 .host_stop = nv_adma_host_stop, 473 .host_stop = nv_adma_host_stop,
468}; 474};
469 475
476/* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to
477 * work, hardreset should be used and hardreset can't report proper
478 * signature, which suggests that mcp5x is closer to nf2 as long as
479 * reset quirkiness is concerned. Define separate ops for mcp5x with
480 * nv_noclassify_hardreset().
481 */
482static struct ata_port_operations nv_mcp5x_ops = {
483 .inherits = &nv_common_ops,
484 .hardreset = nv_noclassify_hardreset,
485};
486
470static struct ata_port_operations nv_swncq_ops = { 487static struct ata_port_operations nv_swncq_ops = {
471 .inherits = &nv_generic_ops, 488 .inherits = &nv_mcp5x_ops,
472 489
473 .qc_defer = ata_std_qc_defer, 490 .qc_defer = ata_std_qc_defer,
474 .qc_prep = nv_swncq_qc_prep, 491 .qc_prep = nv_swncq_qc_prep,
@@ -531,6 +548,15 @@ static const struct ata_port_info nv_port_info[] = {
531 .port_ops = &nv_adma_ops, 548 .port_ops = &nv_adma_ops,
532 .private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht), 549 .private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht),
533 }, 550 },
551 /* MCP5x */
552 {
553 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
554 .pio_mask = NV_PIO_MASK,
555 .mwdma_mask = NV_MWDMA_MASK,
556 .udma_mask = NV_UDMA_MASK,
557 .port_ops = &nv_mcp5x_ops,
558 .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
559 },
534 /* SWNCQ */ 560 /* SWNCQ */
535 { 561 {
536 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 562 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
@@ -1530,6 +1556,17 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
1530 return 0; 1556 return 0;
1531} 1557}
1532 1558
1559static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
1560 unsigned long deadline)
1561{
1562 bool online;
1563 int rc;
1564
1565 rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
1566 &online, NULL);
1567 return online ? -EAGAIN : rc;
1568}
1569
1533static void nv_nf2_freeze(struct ata_port *ap) 1570static void nv_nf2_freeze(struct ata_port *ap)
1534{ 1571{
1535 void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr; 1572 void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
@@ -1554,17 +1591,6 @@ static void nv_nf2_thaw(struct ata_port *ap)
1554 iowrite8(mask, scr_addr + NV_INT_ENABLE); 1591 iowrite8(mask, scr_addr + NV_INT_ENABLE);
1555} 1592}
1556 1593
1557static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
1558 unsigned long deadline)
1559{
1560 bool online;
1561 int rc;
1562
1563 rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
1564 &online, NULL);
1565 return online ? -EAGAIN : rc;
1566}
1567
1568static void nv_ck804_freeze(struct ata_port *ap) 1594static void nv_ck804_freeze(struct ata_port *ap)
1569{ 1595{
1570 void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; 1596 void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
@@ -2355,14 +2381,9 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2355 if (type == CK804 && adma_enabled) { 2381 if (type == CK804 && adma_enabled) {
2356 dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); 2382 dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
2357 type = ADMA; 2383 type = ADMA;
2358 } 2384 } else if (type == MCP5x && swncq_enabled) {
2359 2385 dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n");
2360 if (type == SWNCQ) { 2386 type = SWNCQ;
2361 if (swncq_enabled)
2362 dev_printk(KERN_NOTICE, &pdev->dev,
2363 "Using SWNCQ mode\n");
2364 else
2365 type = GENERIC;
2366 } 2387 }
2367 2388
2368 ppi[0] = &nv_port_info[type]; 2389 ppi[0] = &nv_port_info[type];