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 | |
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>
-rw-r--r-- | drivers/ata/ahci.c | 60 | ||||
-rw-r--r-- | drivers/ata/ahci.h | 1 | ||||
-rw-r--r-- | drivers/ata/libahci.c | 57 |
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 | ||
81 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 81 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
82 | static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, | ||
83 | unsigned long deadline); | ||
84 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, | 82 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, |
85 | unsigned long deadline); | 83 | unsigned long deadline); |
86 | static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, | 84 | static 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 | ||
107 | static 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 | ||
115 | static const struct ata_port_info ahci_port_info[] = { | 107 | static 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 | ||
505 | static 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 | |||
521 | static 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 | |||
553 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, | 497 | static 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 | ||
314 | extern struct ata_port_operations ahci_ops; | 314 | extern struct ata_port_operations ahci_ops; |
315 | extern struct ata_port_operations ahci_pmp_retry_srst_ops; | ||
315 | 316 | ||
316 | void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, | 317 | void 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); | |||
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 | { |