aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-10-09 02:06:48 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:47 -0400
commitb06ce3e51e3df4394a584c234f11240b1c6f8d5b (patch)
tree6a6f5a1cccdc2972b236d376afeba4fd296d5400 /drivers/ata/libata-eh.c
parentafaa5c373d2c49ee4865847031b82f1377f609d0 (diff)
libata: use ata_exec_internal() for PMP register access
PMP registers used to be accessed with dedicated accessors ->pmp_read and ->pmp_write. During reset, those callbacks are called with the port frozen so they should be able to run without depending on interrupt delivery. To achieve this, they were implemented polling. However, as resetting the host port makes the PMP to isolate fan-out ports until SError.X is cleared, resetting fan-out ports while port is frozen doesn't buy much additional safety. This patch updates libata PMP support such that PMP registers are accessed using regular ata_exec_internal() mechanism and kills ->pmp_read/write() callbacks. The following changes are made. * PMP access helpers - sata_pmp_read_init_tf(), sata_pmp_read_val(), sata_pmp_write_init_tf() are folded into sata_pmp_read/write() which are now standalone PMP register access functions. * sata_pmp_read/write() returns err_mask instead of rc. This is consistent with other functions which issue internal commands and allows more detailed error reporting. * ahci interrupt handler is modified to ignore BAD_PMP and spurious/illegal completion IRQs while reset is in progress. These conditions are expected during reset. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 1f84e40fa6a..5a2b2af4d0c 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2557,7 +2557,11 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
2557 2557
2558 /* reset */ 2558 /* reset */
2559 if (reset) { 2559 if (reset) {
2560 ata_eh_freeze_port(ap); 2560 /* if PMP is attached, this function only deals with
2561 * downstream links, port should stay thawed.
2562 */
2563 if (!ap->nr_pmp_links)
2564 ata_eh_freeze_port(ap);
2561 2565
2562 ata_port_for_each_link(link, ap) { 2566 ata_port_for_each_link(link, ap) {
2563 struct ata_eh_context *ehc = &link->eh_context; 2567 struct ata_eh_context *ehc = &link->eh_context;
@@ -2575,7 +2579,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
2575 } 2579 }
2576 } 2580 }
2577 2581
2578 ata_eh_thaw_port(ap); 2582 if (!ap->nr_pmp_links)
2583 ata_eh_thaw_port(ap);
2579 } 2584 }
2580 2585
2581 /* the rest */ 2586 /* the rest */
@@ -2610,8 +2615,14 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
2610 if (ata_eh_handle_dev_fail(dev, rc)) 2615 if (ata_eh_handle_dev_fail(dev, rc))
2611 nr_disabled_devs++; 2616 nr_disabled_devs++;
2612 2617
2613 if (ap->pflags & ATA_PFLAG_FROZEN) 2618 if (ap->pflags & ATA_PFLAG_FROZEN) {
2619 /* PMP reset requires working host port.
2620 * Can't retry if it's frozen.
2621 */
2622 if (ap->nr_pmp_links)
2623 goto out;
2614 break; 2624 break;
2625 }
2615 } 2626 }
2616 2627
2617 if (nr_failed_devs) { 2628 if (nr_failed_devs) {