aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/ata/ahci.c60
-rw-r--r--drivers/ata/ahci.h1
-rw-r--r--drivers/ata/libahci.c57
3 files changed, 60 insertions, 58 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 6ea99df87146..fd318ac36432 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -79,8 +79,6 @@ enum board_ids {
79}; 79};
80 80
81static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 81static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
82static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
83 unsigned long deadline);
84static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 82static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
85 unsigned long deadline); 83 unsigned long deadline);
86static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 84static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
@@ -104,12 +102,6 @@ static struct ata_port_operations ahci_p5wdh_ops = {
104 .hardreset = ahci_p5wdh_hardreset, 102 .hardreset = ahci_p5wdh_hardreset,
105}; 103};
106 104
107static struct ata_port_operations ahci_sb600_ops = {
108 .inherits = &ahci_ops,
109 .softreset = ahci_sb600_softreset,
110 .pmp_softreset = ahci_sb600_softreset,
111};
112
113#define AHCI_HFLAGS(flags) .private_data = (void *)(flags) 105#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
114 106
115static const struct ata_port_info ahci_port_info[] = { 107static const struct ata_port_info ahci_port_info[] = {
@@ -188,7 +180,7 @@ static const struct ata_port_info ahci_port_info[] = {
188 .flags = AHCI_FLAG_COMMON, 180 .flags = AHCI_FLAG_COMMON,
189 .pio_mask = ATA_PIO4, 181 .pio_mask = ATA_PIO4,
190 .udma_mask = ATA_UDMA6, 182 .udma_mask = ATA_UDMA6,
191 .port_ops = &ahci_sb600_ops, 183 .port_ops = &ahci_pmp_retry_srst_ops,
192 }, 184 },
193 [board_ahci_sb700] = /* for SB700 and SB800 */ 185 [board_ahci_sb700] = /* for SB700 and SB800 */
194 { 186 {
@@ -196,7 +188,7 @@ static const struct ata_port_info ahci_port_info[] = {
196 .flags = AHCI_FLAG_COMMON, 188 .flags = AHCI_FLAG_COMMON,
197 .pio_mask = ATA_PIO4, 189 .pio_mask = ATA_PIO4,
198 .udma_mask = ATA_UDMA6, 190 .udma_mask = ATA_UDMA6,
199 .port_ops = &ahci_sb600_ops, 191 .port_ops = &ahci_pmp_retry_srst_ops,
200 }, 192 },
201 [board_ahci_vt8251] = 193 [board_ahci_vt8251] =
202 { 194 {
@@ -502,54 +494,6 @@ static void ahci_pci_init_controller(struct ata_host *host)
502 ahci_init_controller(host); 494 ahci_init_controller(host);
503} 495}
504 496
505static int ahci_sb600_check_ready(struct ata_link *link)
506{
507 void __iomem *port_mmio = ahci_port_base(link->ap);
508 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
509 u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
510
511 /*
512 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
513 * which can save timeout delay.
514 */
515 if (irq_status & PORT_IRQ_BAD_PMP)
516 return -EIO;
517
518 return ata_check_ready(status);
519}
520
521static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
522 unsigned long deadline)
523{
524 struct ata_port *ap = link->ap;
525 void __iomem *port_mmio = ahci_port_base(ap);
526 int pmp = sata_srst_pmp(link);
527 int rc;
528 u32 irq_sts;
529
530 DPRINTK("ENTER\n");
531
532 rc = ahci_do_softreset(link, class, pmp, deadline,
533 ahci_sb600_check_ready);
534
535 /*
536 * Soft reset fails on some ATI chips with IPMS set when PMP
537 * is enabled but SATA HDD/ODD is connected to SATA port,
538 * do soft reset again to port 0.
539 */
540 if (rc == -EIO) {
541 irq_sts = readl(port_mmio + PORT_IRQ_STAT);
542 if (irq_sts & PORT_IRQ_BAD_PMP) {
543 ata_link_warn(link,
544 "applying SB600 PMP SRST workaround and retrying\n");
545 rc = ahci_do_softreset(link, class, 0, deadline,
546 ahci_check_ready);
547 }
548 }
549
550 return rc;
551}
552
553static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 497static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
554 unsigned long deadline) 498 unsigned long deadline)
555{ 499{
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 12c5282e7fca..b1750007c8dc 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -312,6 +312,7 @@ extern struct device_attribute *ahci_sdev_attrs[];
312 .sdev_attrs = ahci_sdev_attrs 312 .sdev_attrs = ahci_sdev_attrs
313 313
314extern struct ata_port_operations ahci_ops; 314extern struct ata_port_operations ahci_ops;
315extern struct ata_port_operations ahci_pmp_retry_srst_ops;
315 316
316void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, 317void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
317 u32 opts); 318 u32 opts);
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{