aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libahci.c
diff options
context:
space:
mode:
authorYuan-Hsin Chen <yhchen@faraday-tech.com>2011-06-21 05:17:38 -0400
committerJeff Garzik <jgarzik@pobox.com>2011-07-23 17:57:36 -0400
commit345347c5d767332d7352f220808fe9b5e4af8c6b (patch)
tree7168a49db28e6fa13f938e21d6d661ff2b0be7ae /drivers/ata/libahci.c
parent8ea7645c5a949f9d0ea86edc0778713b5e63ab74 (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.c57
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);
82static void ahci_pmp_detach(struct ata_port *ap); 82static void ahci_pmp_detach(struct ata_port *ap);
83static int ahci_softreset(struct ata_link *link, unsigned int *class, 83static int ahci_softreset(struct ata_link *link, unsigned int *class,
84 unsigned long deadline); 84 unsigned long deadline);
85static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
86 unsigned long deadline);
85static int ahci_hardreset(struct ata_link *link, unsigned int *class, 87static int ahci_hardreset(struct ata_link *link, unsigned int *class,
86 unsigned long deadline); 88 unsigned long deadline);
87static void ahci_postreset(struct ata_link *link, unsigned int *class); 89static void ahci_postreset(struct ata_link *link, unsigned int *class);
@@ -178,6 +180,12 @@ struct ata_port_operations ahci_ops = {
178}; 180};
179EXPORT_SYMBOL_GPL(ahci_ops); 181EXPORT_SYMBOL_GPL(ahci_ops);
180 182
183struct ata_port_operations ahci_pmp_retry_srst_ops = {
184 .inherits = &ahci_ops,
185 .softreset = ahci_pmp_retry_softreset,
186};
187EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);
188
181int ahci_em_messages = 1; 189int ahci_em_messages = 1;
182EXPORT_SYMBOL_GPL(ahci_em_messages); 190EXPORT_SYMBOL_GPL(ahci_em_messages);
183module_param(ahci_em_messages, int, 0444); 191module_param(ahci_em_messages, int, 0444);
@@ -1319,6 +1327,55 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class,
1319} 1327}
1320EXPORT_SYMBOL_GPL(ahci_do_softreset); 1328EXPORT_SYMBOL_GPL(ahci_do_softreset);
1321 1329
1330static 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
1346int 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
1322static int ahci_hardreset(struct ata_link *link, unsigned int *class, 1379static int ahci_hardreset(struct ata_link *link, unsigned int *class,
1323 unsigned long deadline) 1380 unsigned long deadline)
1324{ 1381{