diff options
author | Tejun Heo <tj@kernel.org> | 2009-01-24 21:29:38 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-01-26 06:36:31 -0500 |
commit | 2d775708bc6613f1be47f1e720781343341ecc94 (patch) | |
tree | c8aa7779b40f1c29d88a0e2b18ae890a129336d7 /drivers | |
parent | e8caa3c70e94d867ca2efe9e53fd388b52d6d0c8 (diff) |
sata_nv: fix MCP5x reset
MCP5x family of controllers seem to share much more with nf2's as far
as reset protocol is concerned. It requires heardreset to get the PHY
going and classfication code report after hardreset is unreliable.
Create a new board type MCP5x and use noclassify hardreset. SWNCQ is
modified to inherit from this new type.
This fixes hotplug regression reported in kernel bz#12351.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_nv.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 93bf5855a9b5..c49ad0e61b6f 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
@@ -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 }, |
@@ -467,8 +468,19 @@ static struct ata_port_operations nv_adma_ops = { | |||
467 | .host_stop = nv_adma_host_stop, | 468 | .host_stop = nv_adma_host_stop, |
468 | }; | 469 | }; |
469 | 470 | ||
471 | /* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to | ||
472 | * work, hardreset should be used and hardreset can't report proper | ||
473 | * signature, which suggests that mcp5x is closer to nf2 as long as | ||
474 | * reset quirkiness is concerned. Define separate ops for mcp5x with | ||
475 | * nv_noclassify_hardreset(). | ||
476 | */ | ||
477 | static struct ata_port_operations nv_mcp5x_ops = { | ||
478 | .inherits = &nv_common_ops, | ||
479 | .hardreset = nv_noclassify_hardreset, | ||
480 | }; | ||
481 | |||
470 | static struct ata_port_operations nv_swncq_ops = { | 482 | static struct ata_port_operations nv_swncq_ops = { |
471 | .inherits = &nv_generic_ops, | 483 | .inherits = &nv_mcp5x_ops, |
472 | 484 | ||
473 | .qc_defer = ata_std_qc_defer, | 485 | .qc_defer = ata_std_qc_defer, |
474 | .qc_prep = nv_swncq_qc_prep, | 486 | .qc_prep = nv_swncq_qc_prep, |
@@ -531,6 +543,15 @@ static const struct ata_port_info nv_port_info[] = { | |||
531 | .port_ops = &nv_adma_ops, | 543 | .port_ops = &nv_adma_ops, |
532 | .private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht), | 544 | .private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht), |
533 | }, | 545 | }, |
546 | /* MCP5x */ | ||
547 | { | ||
548 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | ||
549 | .pio_mask = NV_PIO_MASK, | ||
550 | .mwdma_mask = NV_MWDMA_MASK, | ||
551 | .udma_mask = NV_UDMA_MASK, | ||
552 | .port_ops = &nv_mcp5x_ops, | ||
553 | .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht), | ||
554 | }, | ||
534 | /* SWNCQ */ | 555 | /* SWNCQ */ |
535 | { | 556 | { |
536 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 557 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
@@ -2355,14 +2376,9 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2355 | if (type == CK804 && adma_enabled) { | 2376 | if (type == CK804 && adma_enabled) { |
2356 | dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); | 2377 | dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); |
2357 | type = ADMA; | 2378 | type = ADMA; |
2358 | } | 2379 | } else if (type == MCP5x && swncq_enabled) { |
2359 | 2380 | dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n"); | |
2360 | if (type == SWNCQ) { | 2381 | type = SWNCQ; |
2361 | if (swncq_enabled) | ||
2362 | dev_printk(KERN_NOTICE, &pdev->dev, | ||
2363 | "Using SWNCQ mode\n"); | ||
2364 | else | ||
2365 | type = GENERIC; | ||
2366 | } | 2382 | } |
2367 | 2383 | ||
2368 | ppi[0] = &nv_port_info[type]; | 2384 | ppi[0] = &nv_port_info[type]; |