aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-06-10 03:29:07 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-06-10 11:05:26 -0400
commit7f4774b38ee6270bbc6c3015cb3fa6c415ffb340 (patch)
tree4680fb8c7afdf439bc73dc9a201a69faa6c9e197 /drivers
parent58a09b38cfcd700b796ea07ae3d2e0efbb28b561 (diff)
sata_nv: use hardreset only for post-boot probing
When I thought it was finally defeated, it came back with vengeance. The failure cases are ever more convoluted. Now there is a single combination which fails boot probing - MCP5x + Intel SSD and there are two hotplug failure reports on different flavors where softreset fails to bring up the device. Through the many bug reports after the switch to hardreset, the following patterns emerged. - Softreset during boot always works. - Hardreset during boot sometimes fails to bring up the link on certain comibnations and device signature acquisition is unreliable. - Hardreset is often necessary after hotplug. It looks like the old behavior of preferring softreset was somehow pretty close to the working reset protocol although it could have lost a device during phy error handling by issuing hardreset. This patch implements nv_hardreset() which kicks in only for post-boot (!LOADING) device probing resets. This should be able to work around all known problem cases. This isn't perfect but given the various hardreset quirks on these controllers, I think this is as good as it can get. Tested on mcp5x (swncq), nf3 and ck804 for all both boot, warm and hot probing cases. Kudos to all the bug reporters and their painful hours with these damn controllers. ;-) Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Robert Hancock <hancockr@shaw.ca> Reported-by: David Lang <david@lang.hm> Reported-by: Samo Vodopivec <lament.email.si@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/sata_nv.c131
1 files changed, 81 insertions, 50 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 6cda12ba8122..b2d11f300c39 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -305,8 +305,8 @@ 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, 308static int nv_hardreset(struct ata_link *link, unsigned int *class,
309 unsigned long deadline); 309 unsigned long deadline);
310static void nv_nf2_freeze(struct ata_port *ap); 310static void nv_nf2_freeze(struct ata_port *ap);
311static void nv_nf2_thaw(struct ata_port *ap); 311static void nv_nf2_thaw(struct ata_port *ap);
312static void nv_ck804_freeze(struct ata_port *ap); 312static void nv_ck804_freeze(struct ata_port *ap);
@@ -406,49 +406,82 @@ static struct scsi_host_template nv_swncq_sht = {
406 .slave_configure = nv_swncq_slave_config, 406 .slave_configure = nv_swncq_slave_config,
407}; 407};
408 408
409static struct ata_port_operations nv_common_ops = { 409/*
410 * NV SATA controllers have various different problems with hardreset
411 * protocol depending on the specific controller and device.
412 *
413 * GENERIC:
414 *
415 * bko11195 reports that link doesn't come online after hardreset on
416 * generic nv's and there have been several other similar reports on
417 * linux-ide.
418 *
419 * bko12351#c23 reports that warmplug on MCP61 doesn't work with
420 * softreset.
421 *
422 * NF2/3:
423 *
424 * bko3352 reports nf2/3 controllers can't determine device signature
425 * reliably after hardreset. The following thread reports detection
426 * failure on cold boot with the standard debouncing timing.
427 *
428 * http://thread.gmane.org/gmane.linux.ide/34098
429 *
430 * bko12176 reports that hardreset fails to bring up the link during
431 * boot on nf2.
432 *
433 * CK804:
434 *
435 * For initial probing after boot and hot plugging, hardreset mostly
436 * works fine on CK804 but curiously, reprobing on the initial port
437 * by rescanning or rmmod/insmod fails to acquire the initial D2H Reg
438 * FIS in somewhat undeterministic way.
439 *
440 * SWNCQ:
441 *
442 * bko12351 reports that when SWNCQ is enabled, for hotplug to work,
443 * hardreset should be used and hardreset can't report proper
444 * signature, which suggests that mcp5x is closer to nf2 as long as
445 * reset quirkiness is concerned.
446 *
447 * bko12703 reports that boot probing fails for intel SSD with
448 * hardreset. Link fails to come online. Softreset works fine.
449 *
450 * The failures are varied but the following patterns seem true for
451 * all flavors.
452 *
453 * - Softreset during boot always works.
454 *
455 * - Hardreset during boot sometimes fails to bring up the link on
456 * certain comibnations and device signature acquisition is
457 * unreliable.
458 *
459 * - Hardreset is often necessary after hotplug.
460 *
461 * So, preferring softreset for boot probing and error handling (as
462 * hardreset might bring down the link) but using hardreset for
463 * post-boot probing should work around the above issues in most
464 * cases. Define nv_hardreset() which only kicks in for post-boot
465 * probing and use it for all variants.
466 */
467static struct ata_port_operations nv_generic_ops = {
410 .inherits = &ata_bmdma_port_ops, 468 .inherits = &ata_bmdma_port_ops,
411 .lost_interrupt = ATA_OP_NULL, 469 .lost_interrupt = ATA_OP_NULL,
412 .scr_read = nv_scr_read, 470 .scr_read = nv_scr_read,
413 .scr_write = nv_scr_write, 471 .scr_write = nv_scr_write,
472 .hardreset = nv_hardreset,
414}; 473};
415 474
416/* OSDL bz11195 reports that link doesn't come online after hardreset
417 * on generic nv's and there have been several other similar reports
418 * on linux-ide. Disable hardreset for generic nv's.
419 */
420static struct ata_port_operations nv_generic_ops = {
421 .inherits = &nv_common_ops,
422 .hardreset = ATA_OP_NULL,
423};
424
425/* nf2 is ripe with hardreset related problems.
426 *
427 * kernel bz#3352 reports nf2/3 controllers can't determine device
428 * signature reliably. The following thread reports detection failure
429 * on cold boot with the standard debouncing timing.
430 *
431 * http://thread.gmane.org/gmane.linux.ide/34098
432 *
433 * And bz#12176 reports that hardreset simply doesn't work on nf2.
434 * Give up on it and just don't do hardreset.
435 */
436static struct ata_port_operations nv_nf2_ops = { 475static struct ata_port_operations nv_nf2_ops = {
437 .inherits = &nv_generic_ops, 476 .inherits = &nv_generic_ops,
438 .freeze = nv_nf2_freeze, 477 .freeze = nv_nf2_freeze,
439 .thaw = nv_nf2_thaw, 478 .thaw = nv_nf2_thaw,
440}; 479};
441 480
442/* For initial probing after boot and hot plugging, hardreset mostly
443 * works fine on CK804 but curiously, reprobing on the initial port by
444 * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS
445 * in somewhat undeterministic way. Use noclassify hardreset.
446 */
447static struct ata_port_operations nv_ck804_ops = { 481static struct ata_port_operations nv_ck804_ops = {
448 .inherits = &nv_common_ops, 482 .inherits = &nv_generic_ops,
449 .freeze = nv_ck804_freeze, 483 .freeze = nv_ck804_freeze,
450 .thaw = nv_ck804_thaw, 484 .thaw = nv_ck804_thaw,
451 .hardreset = nv_noclassify_hardreset,
452 .host_stop = nv_ck804_host_stop, 485 .host_stop = nv_ck804_host_stop,
453}; 486};
454 487
@@ -476,19 +509,8 @@ static struct ata_port_operations nv_adma_ops = {
476 .host_stop = nv_adma_host_stop, 509 .host_stop = nv_adma_host_stop,
477}; 510};
478 511
479/* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to
480 * work, hardreset should be used and hardreset can't report proper
481 * signature, which suggests that mcp5x is closer to nf2 as long as
482 * reset quirkiness is concerned. Define separate ops for mcp5x with
483 * nv_noclassify_hardreset().
484 */
485static struct ata_port_operations nv_mcp5x_ops = {
486 .inherits = &nv_common_ops,
487 .hardreset = nv_noclassify_hardreset,
488};
489
490static struct ata_port_operations nv_swncq_ops = { 512static struct ata_port_operations nv_swncq_ops = {
491 .inherits = &nv_mcp5x_ops, 513 .inherits = &nv_generic_ops,
492 514
493 .qc_defer = ata_std_qc_defer, 515 .qc_defer = ata_std_qc_defer,
494 .qc_prep = nv_swncq_qc_prep, 516 .qc_prep = nv_swncq_qc_prep,
@@ -557,7 +579,7 @@ static const struct ata_port_info nv_port_info[] = {
557 .pio_mask = NV_PIO_MASK, 579 .pio_mask = NV_PIO_MASK,
558 .mwdma_mask = NV_MWDMA_MASK, 580 .mwdma_mask = NV_MWDMA_MASK,
559 .udma_mask = NV_UDMA_MASK, 581 .udma_mask = NV_UDMA_MASK,
560 .port_ops = &nv_mcp5x_ops, 582 .port_ops = &nv_generic_ops,
561 .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht), 583 .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
562 }, 584 },
563 /* SWNCQ */ 585 /* SWNCQ */
@@ -1559,15 +1581,24 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
1559 return 0; 1581 return 0;
1560} 1582}
1561 1583
1562static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class, 1584static int nv_hardreset(struct ata_link *link, unsigned int *class,
1563 unsigned long deadline) 1585 unsigned long deadline)
1564{ 1586{
1565 bool online; 1587 struct ata_eh_context *ehc = &link->eh_context;
1566 int rc;
1567 1588
1568 rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, 1589 /* Do hardreset iff it's post-boot probing, please read the
1569 &online, NULL); 1590 * comment above port ops for details.
1570 return online ? -EAGAIN : rc; 1591 */
1592 if (!(link->ap->pflags & ATA_PFLAG_LOADING) &&
1593 !ata_dev_enabled(link->device))
1594 sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
1595 NULL, NULL);
1596 else if (!(ehc->i.flags & ATA_EHI_QUIET))
1597 ata_link_printk(link, KERN_INFO,
1598 "nv: skipping hardreset on occupied port\n");
1599
1600 /* device signature acquisition is unreliable */
1601 return -EAGAIN;
1571} 1602}
1572 1603
1573static void nv_nf2_freeze(struct ata_port *ap) 1604static void nv_nf2_freeze(struct ata_port *ap)