diff options
author | Yuan-Hsin Chen <yhchen@faraday-tech.com> | 2011-06-21 05:17:38 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2011-07-23 17:57:36 -0400 |
commit | 345347c5d767332d7352f220808fe9b5e4af8c6b (patch) | |
tree | 7168a49db28e6fa13f938e21d6d661ff2b0be7ae /drivers/ata/libahci.c | |
parent | 8ea7645c5a949f9d0ea86edc0778713b5e63ab74 (diff) |
ahci: move ahci_sb600_softreset to libahci.c and rename it
ahci_sb600_softreset was in ahci.c. This function is used
to fix soft reset failure and renames as ahci_pmp_retry_softreset
in libahci.c.
Signed-off-by: Yuan-Hsin Chen <yhchen@faraday-tech.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/ata/libahci.c')
-rw-r--r-- | drivers/ata/libahci.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index c102d7d64282..3c92dbd751e0 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c | |||
@@ -82,6 +82,8 @@ static void ahci_pmp_attach(struct ata_port *ap); | |||
82 | static void ahci_pmp_detach(struct ata_port *ap); | 82 | static void ahci_pmp_detach(struct ata_port *ap); |
83 | static int ahci_softreset(struct ata_link *link, unsigned int *class, | 83 | static int ahci_softreset(struct ata_link *link, unsigned int *class, |
84 | unsigned long deadline); | 84 | unsigned long deadline); |
85 | static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class, | ||
86 | unsigned long deadline); | ||
85 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, | 87 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, |
86 | unsigned long deadline); | 88 | unsigned long deadline); |
87 | static void ahci_postreset(struct ata_link *link, unsigned int *class); | 89 | static void ahci_postreset(struct ata_link *link, unsigned int *class); |
@@ -178,6 +180,12 @@ struct ata_port_operations ahci_ops = { | |||
178 | }; | 180 | }; |
179 | EXPORT_SYMBOL_GPL(ahci_ops); | 181 | EXPORT_SYMBOL_GPL(ahci_ops); |
180 | 182 | ||
183 | struct ata_port_operations ahci_pmp_retry_srst_ops = { | ||
184 | .inherits = &ahci_ops, | ||
185 | .softreset = ahci_pmp_retry_softreset, | ||
186 | }; | ||
187 | EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops); | ||
188 | |||
181 | int ahci_em_messages = 1; | 189 | int ahci_em_messages = 1; |
182 | EXPORT_SYMBOL_GPL(ahci_em_messages); | 190 | EXPORT_SYMBOL_GPL(ahci_em_messages); |
183 | module_param(ahci_em_messages, int, 0444); | 191 | module_param(ahci_em_messages, int, 0444); |
@@ -1319,6 +1327,55 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class, | |||
1319 | } | 1327 | } |
1320 | EXPORT_SYMBOL_GPL(ahci_do_softreset); | 1328 | EXPORT_SYMBOL_GPL(ahci_do_softreset); |
1321 | 1329 | ||
1330 | static int ahci_bad_pmp_check_ready(struct ata_link *link) | ||
1331 | { | ||
1332 | void __iomem *port_mmio = ahci_port_base(link->ap); | ||
1333 | u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; | ||
1334 | u32 irq_status = readl(port_mmio + PORT_IRQ_STAT); | ||
1335 | |||
1336 | /* | ||
1337 | * There is no need to check TFDATA if BAD PMP is found due to HW bug, | ||
1338 | * which can save timeout delay. | ||
1339 | */ | ||
1340 | if (irq_status & PORT_IRQ_BAD_PMP) | ||
1341 | return -EIO; | ||
1342 | |||
1343 | return ata_check_ready(status); | ||
1344 | } | ||
1345 | |||
1346 | int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class, | ||
1347 | unsigned long deadline) | ||
1348 | { | ||
1349 | struct ata_port *ap = link->ap; | ||
1350 | void __iomem *port_mmio = ahci_port_base(ap); | ||
1351 | int pmp = sata_srst_pmp(link); | ||
1352 | int rc; | ||
1353 | u32 irq_sts; | ||
1354 | |||
1355 | DPRINTK("ENTER\n"); | ||
1356 | |||
1357 | rc = ahci_do_softreset(link, class, pmp, deadline, | ||
1358 | ahci_bad_pmp_check_ready); | ||
1359 | |||
1360 | /* | ||
1361 | * Soft reset fails with IPMS set when PMP is enabled but | ||
1362 | * SATA HDD/ODD is connected to SATA port, do soft reset | ||
1363 | * again to port 0. | ||
1364 | */ | ||
1365 | if (rc == -EIO) { | ||
1366 | irq_sts = readl(port_mmio + PORT_IRQ_STAT); | ||
1367 | if (irq_sts & PORT_IRQ_BAD_PMP) { | ||
1368 | ata_link_printk(link, KERN_WARNING, | ||
1369 | "applying PMP SRST workaround " | ||
1370 | "and retrying\n"); | ||
1371 | rc = ahci_do_softreset(link, class, 0, deadline, | ||
1372 | ahci_check_ready); | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | return rc; | ||
1377 | } | ||
1378 | |||
1322 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, | 1379 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, |
1323 | unsigned long deadline) | 1380 | unsigned long deadline) |
1324 | { | 1381 | { |