aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-09-23 00:19:54 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:44 -0400
commit3454dc6922dc550c0d3ccf292c4e227403b10b6e (patch)
treed87c26e26d52725ee7f54d1cf81e81c0a4adc53f
parent31f88384443b3e0d7e2c9d36a96647b7e82edad3 (diff)
sata_sil24: implement PMP support
Implement PMP support. sil24 supports full FIS-switching. However, it has a PMP DMA CS errata which requires port-wide resetting if commands are outstanding to three or more devices when an error occurs on one of them. ATAPI commands often result in CHECK SENSE and it's crucial to not reset them before fetching sense data. Unfortunately, ATAPI CHECK SENSE causes a lot of problem if command is outstanding to any other device usually resulting in port-wide reset. So, sata_sil24 implements sil24_qc_defer() which guarantees ATAPI command is run by itself. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/sata_sil24.c227
1 files changed, 206 insertions, 21 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index b4f81eb8bbbe..03bfbb65c533 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -30,7 +30,7 @@
30#include <linux/libata.h> 30#include <linux/libata.h>
31 31
32#define DRV_NAME "sata_sil24" 32#define DRV_NAME "sata_sil24"
33#define DRV_VERSION "1.0" 33#define DRV_VERSION "1.1"
34 34
35/* 35/*
36 * Port request block (PRB) 32 bytes 36 * Port request block (PRB) 32 bytes
@@ -238,7 +238,7 @@ enum {
238 SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 238 SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
239 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | 239 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
240 ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | 240 ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
241 ATA_FLAG_AN, 241 ATA_FLAG_AN | ATA_FLAG_PMP,
242 SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY, 242 SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY,
243 SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ 243 SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
244 244
@@ -330,9 +330,14 @@ static u8 sil24_check_status(struct ata_port *ap);
330static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); 330static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val);
331static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); 331static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
332static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); 332static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
333static int sil24_qc_defer(struct ata_queued_cmd *qc);
333static void sil24_qc_prep(struct ata_queued_cmd *qc); 334static void sil24_qc_prep(struct ata_queued_cmd *qc);
334static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); 335static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
335static void sil24_irq_clear(struct ata_port *ap); 336static void sil24_irq_clear(struct ata_port *ap);
337static void sil24_pmp_attach(struct ata_port *ap);
338static void sil24_pmp_detach(struct ata_port *ap);
339static int sil24_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val);
340static int sil24_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val);
336static void sil24_freeze(struct ata_port *ap); 341static void sil24_freeze(struct ata_port *ap);
337static void sil24_thaw(struct ata_port *ap); 342static void sil24_thaw(struct ata_port *ap);
338static void sil24_error_handler(struct ata_port *ap); 343static void sil24_error_handler(struct ata_port *ap);
@@ -341,6 +346,7 @@ static int sil24_port_start(struct ata_port *ap);
341static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 346static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
342#ifdef CONFIG_PM 347#ifdef CONFIG_PM
343static int sil24_pci_device_resume(struct pci_dev *pdev); 348static int sil24_pci_device_resume(struct pci_dev *pdev);
349static int sil24_port_resume(struct ata_port *ap);
344#endif 350#endif
345 351
346static const struct pci_device_id sil24_pci_tbl[] = { 352static const struct pci_device_id sil24_pci_tbl[] = {
@@ -393,7 +399,7 @@ static const struct ata_port_operations sil24_ops = {
393 399
394 .tf_read = sil24_tf_read, 400 .tf_read = sil24_tf_read,
395 401
396 .qc_defer = ata_std_qc_defer, 402 .qc_defer = sil24_qc_defer,
397 .qc_prep = sil24_qc_prep, 403 .qc_prep = sil24_qc_prep,
398 .qc_issue = sil24_qc_issue, 404 .qc_issue = sil24_qc_issue,
399 405
@@ -402,12 +408,21 @@ static const struct ata_port_operations sil24_ops = {
402 .scr_read = sil24_scr_read, 408 .scr_read = sil24_scr_read,
403 .scr_write = sil24_scr_write, 409 .scr_write = sil24_scr_write,
404 410
411 .pmp_attach = sil24_pmp_attach,
412 .pmp_detach = sil24_pmp_detach,
413 .pmp_read = sil24_pmp_read,
414 .pmp_write = sil24_pmp_write,
415
405 .freeze = sil24_freeze, 416 .freeze = sil24_freeze,
406 .thaw = sil24_thaw, 417 .thaw = sil24_thaw,
407 .error_handler = sil24_error_handler, 418 .error_handler = sil24_error_handler,
408 .post_internal_cmd = sil24_post_internal_cmd, 419 .post_internal_cmd = sil24_post_internal_cmd,
409 420
410 .port_start = sil24_port_start, 421 .port_start = sil24_port_start,
422
423#ifdef CONFIG_PM
424 .port_resume = sil24_port_resume,
425#endif
411}; 426};
412 427
413/* 428/*
@@ -521,11 +536,40 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
521 *tf = pp->tf; 536 *tf = pp->tf;
522} 537}
523 538
539static void sil24_config_pmp(struct ata_port *ap, int attached)
540{
541 void __iomem *port = ap->ioaddr.cmd_addr;
542
543 if (attached)
544 writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT);
545 else
546 writel(PORT_CS_PMP_EN, port + PORT_CTRL_CLR);
547}
548
549static void sil24_clear_pmp(struct ata_port *ap)
550{
551 void __iomem *port = ap->ioaddr.cmd_addr;
552 int i;
553
554 writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR);
555
556 for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
557 void __iomem *pmp_base = port + PORT_PMP + i * PORT_PMP_SIZE;
558
559 writel(0, pmp_base + PORT_PMP_STATUS);
560 writel(0, pmp_base + PORT_PMP_QACTIVE);
561 }
562}
563
524static int sil24_init_port(struct ata_port *ap) 564static int sil24_init_port(struct ata_port *ap)
525{ 565{
526 void __iomem *port = ap->ioaddr.cmd_addr; 566 void __iomem *port = ap->ioaddr.cmd_addr;
527 u32 tmp; 567 u32 tmp;
528 568
569 /* clear PMP error status */
570 if (ap->nr_pmp_links)
571 sil24_clear_pmp(ap);
572
529 writel(PORT_CS_INIT, port + PORT_CTRL_STAT); 573 writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
530 ata_wait_register(port + PORT_CTRL_STAT, 574 ata_wait_register(port + PORT_CTRL_STAT,
531 PORT_CS_INIT, PORT_CS_INIT, 10, 100); 575 PORT_CS_INIT, PORT_CS_INIT, 10, 100);
@@ -640,7 +684,7 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
640static int sil24_softreset(struct ata_link *link, unsigned int *class, 684static int sil24_softreset(struct ata_link *link, unsigned int *class,
641 unsigned long deadline) 685 unsigned long deadline)
642{ 686{
643 return sil24_do_softreset(link, class, 0, deadline); 687 return sil24_do_softreset(link, class, SATA_PMP_CTRL_PORT, deadline);
644} 688}
645 689
646static int sil24_hardreset(struct ata_link *link, unsigned int *class, 690static int sil24_hardreset(struct ata_link *link, unsigned int *class,
@@ -708,6 +752,38 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
708 } 752 }
709} 753}
710 754
755static int sil24_qc_defer(struct ata_queued_cmd *qc)
756{
757 struct ata_link *link = qc->dev->link;
758 struct ata_port *ap = link->ap;
759 u8 prot = qc->tf.protocol;
760 int is_atapi = (prot == ATA_PROT_ATAPI ||
761 prot == ATA_PROT_ATAPI_NODATA ||
762 prot == ATA_PROT_ATAPI_DMA);
763
764 /* ATAPI commands completing with CHECK_SENSE cause various
765 * weird problems if other commands are active. PMP DMA CS
766 * errata doesn't cover all and HSM violation occurs even with
767 * only one other device active. Always run an ATAPI command
768 * by itself.
769 */
770 if (unlikely(ap->excl_link)) {
771 if (link == ap->excl_link) {
772 if (ap->nr_active_links)
773 return ATA_DEFER_PORT;
774 qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
775 } else
776 return ATA_DEFER_PORT;
777 } else if (unlikely(is_atapi)) {
778 ap->excl_link = link;
779 if (ap->nr_active_links)
780 return ATA_DEFER_PORT;
781 qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
782 }
783
784 return ata_std_qc_defer(qc);
785}
786
711static void sil24_qc_prep(struct ata_queued_cmd *qc) 787static void sil24_qc_prep(struct ata_queued_cmd *qc)
712{ 788{
713 struct ata_port *ap = qc->ap; 789 struct ata_port *ap = qc->ap;
@@ -751,7 +827,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
751 } 827 }
752 828
753 prb->ctrl = cpu_to_le16(ctrl); 829 prb->ctrl = cpu_to_le16(ctrl);
754 ata_tf_to_fis(&qc->tf, 0, 1, prb->fis); 830 ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, prb->fis);
755 831
756 if (qc->flags & ATA_QCFLAG_DMAMAP) 832 if (qc->flags & ATA_QCFLAG_DMAMAP)
757 sil24_fill_sg(qc, sge); 833 sil24_fill_sg(qc, sge);
@@ -780,6 +856,65 @@ static void sil24_irq_clear(struct ata_port *ap)
780 /* unused */ 856 /* unused */
781} 857}
782 858
859static void sil24_pmp_attach(struct ata_port *ap)
860{
861 sil24_config_pmp(ap, 1);
862 sil24_init_port(ap);
863}
864
865static void sil24_pmp_detach(struct ata_port *ap)
866{
867 sil24_init_port(ap);
868 sil24_config_pmp(ap, 0);
869}
870
871static int sil24_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val)
872{
873 struct ata_port *ap = dev->link->ap;
874 struct ata_taskfile tf;
875 int rc;
876
877 sata_pmp_read_init_tf(&tf, dev, pmp, reg);
878 rc = sil24_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0,
879 SATA_PMP_SCR_TIMEOUT);
880 if (rc == 0) {
881 sil24_read_tf(ap, 0, &tf);
882 *r_val = sata_pmp_read_val(&tf);
883 }
884 return rc;
885}
886
887static int sil24_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val)
888{
889 struct ata_port *ap = dev->link->ap;
890 struct ata_taskfile tf;
891
892 sata_pmp_write_init_tf(&tf, dev, pmp, reg, val);
893 return sil24_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0,
894 SATA_PMP_SCR_TIMEOUT);
895}
896
897static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class,
898 unsigned long deadline)
899{
900 return sil24_do_softreset(link, class, link->pmp, deadline);
901}
902
903static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
904 unsigned long deadline)
905{
906 int rc;
907
908 rc = sil24_init_port(link->ap);
909 if (rc) {
910 ata_link_printk(link, KERN_ERR,
911 "hardreset failed (port not ready)\n");
912 return rc;
913 }
914
915 return sata_pmp_std_hardreset(link, class, deadline);
916}
917
783static void sil24_freeze(struct ata_port *ap) 918static void sil24_freeze(struct ata_port *ap)
784{ 919{
785 void __iomem *port = ap->ioaddr.cmd_addr; 920 void __iomem *port = ap->ioaddr.cmd_addr;
@@ -807,8 +942,10 @@ static void sil24_error_intr(struct ata_port *ap)
807{ 942{
808 void __iomem *port = ap->ioaddr.cmd_addr; 943 void __iomem *port = ap->ioaddr.cmd_addr;
809 struct sil24_port_priv *pp = ap->private_data; 944 struct sil24_port_priv *pp = ap->private_data;
810 struct ata_eh_info *ehi = &ap->link.eh_info; 945 struct ata_queued_cmd *qc = NULL;
811 int freeze = 0; 946 struct ata_link *link;
947 struct ata_eh_info *ehi;
948 int abort = 0, freeze = 0;
812 u32 irq_stat; 949 u32 irq_stat;
813 950
814 /* on error, we need to clear IRQ explicitly */ 951 /* on error, we need to clear IRQ explicitly */
@@ -816,6 +953,8 @@ static void sil24_error_intr(struct ata_port *ap)
816 writel(irq_stat, port + PORT_IRQ_STAT); 953 writel(irq_stat, port + PORT_IRQ_STAT);
817 954
818 /* first, analyze and record host port events */ 955 /* first, analyze and record host port events */
956 link = &ap->link;
957 ehi = &link->eh_info;
819 ata_ehi_clear_desc(ehi); 958 ata_ehi_clear_desc(ehi);
820 959
821 ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); 960 ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
@@ -844,8 +983,43 @@ static void sil24_error_intr(struct ata_port *ap)
844 if (irq_stat & PORT_IRQ_ERROR) { 983 if (irq_stat & PORT_IRQ_ERROR) {
845 struct sil24_cerr_info *ci = NULL; 984 struct sil24_cerr_info *ci = NULL;
846 unsigned int err_mask = 0, action = 0; 985 unsigned int err_mask = 0, action = 0;
847 struct ata_queued_cmd *qc; 986 u32 context, cerr;
848 u32 cerr; 987 int pmp;
988
989 abort = 1;
990
991 /* DMA Context Switch Failure in Port Multiplier Mode
992 * errata. If we have active commands to 3 or more
993 * devices, any error condition on active devices can
994 * corrupt DMA context switching.
995 */
996 if (ap->nr_active_links >= 3) {
997 ehi->err_mask |= AC_ERR_OTHER;
998 ehi->action |= ATA_EH_HARDRESET;
999 ata_ehi_push_desc(ehi, "PMP DMA CS errata");
1000 freeze = 1;
1001 }
1002
1003 /* find out the offending link and qc */
1004 if (ap->nr_pmp_links) {
1005 context = readl(port + PORT_CONTEXT);
1006 pmp = (context >> 5) & 0xf;
1007
1008 if (pmp < ap->nr_pmp_links) {
1009 link = &ap->pmp_link[pmp];
1010 ehi = &link->eh_info;
1011 qc = ata_qc_from_tag(ap, link->active_tag);
1012
1013 ata_ehi_clear_desc(ehi);
1014 ata_ehi_push_desc(ehi, "irq_stat 0x%08x",
1015 irq_stat);
1016 } else {
1017 err_mask |= AC_ERR_HSM;
1018 action |= ATA_EH_HARDRESET;
1019 freeze = 1;
1020 }
1021 } else
1022 qc = ata_qc_from_tag(ap, link->active_tag);
849 1023
850 /* analyze CMD_ERR */ 1024 /* analyze CMD_ERR */
851 cerr = readl(port + PORT_CMD_ERR); 1025 cerr = readl(port + PORT_CMD_ERR);
@@ -864,7 +1038,6 @@ static void sil24_error_intr(struct ata_port *ap)
864 } 1038 }
865 1039
866 /* record error info */ 1040 /* record error info */
867 qc = ata_qc_from_tag(ap, ap->link.active_tag);
868 if (qc) { 1041 if (qc) {
869 sil24_read_tf(ap, qc->tag, &pp->tf); 1042 sil24_read_tf(ap, qc->tag, &pp->tf);
870 qc->err_mask |= err_mask; 1043 qc->err_mask |= err_mask;
@@ -872,13 +1045,21 @@ static void sil24_error_intr(struct ata_port *ap)
872 ehi->err_mask |= err_mask; 1045 ehi->err_mask |= err_mask;
873 1046
874 ehi->action |= action; 1047 ehi->action |= action;
1048
1049 /* if PMP, resume */
1050 if (ap->nr_pmp_links)
1051 writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT);
875 } 1052 }
876 1053
877 /* freeze or abort */ 1054 /* freeze or abort */
878 if (freeze) 1055 if (freeze)
879 ata_port_freeze(ap); 1056 ata_port_freeze(ap);
880 else 1057 else if (abort) {
881 ata_port_abort(ap); 1058 if (qc)
1059 ata_link_abort(qc->dev->link);
1060 else
1061 ata_port_abort(ap);
1062 }
882} 1063}
883 1064
884static void sil24_finish_qc(struct ata_queued_cmd *qc) 1065static void sil24_finish_qc(struct ata_queued_cmd *qc)
@@ -971,16 +1152,14 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
971 1152
972static void sil24_error_handler(struct ata_port *ap) 1153static void sil24_error_handler(struct ata_port *ap)
973{ 1154{
974 struct ata_eh_context *ehc = &ap->link.eh_context; 1155 if (sil24_init_port(ap))
975
976 if (sil24_init_port(ap)) {
977 ata_eh_freeze_port(ap); 1156 ata_eh_freeze_port(ap);
978 ehc->i.action |= ATA_EH_HARDRESET;
979 }
980 1157
981 /* perform recovery */ 1158 /* perform recovery */
982 ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, 1159 sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
983 ata_std_postreset); 1160 ata_std_postreset, sata_pmp_std_prereset,
1161 sil24_pmp_softreset, sil24_pmp_hardreset,
1162 sata_pmp_std_postreset);
984} 1163}
985 1164
986static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) 1165static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
@@ -988,8 +1167,8 @@ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
988 struct ata_port *ap = qc->ap; 1167 struct ata_port *ap = qc->ap;
989 1168
990 /* make DMA engine forget about the failed command */ 1169 /* make DMA engine forget about the failed command */
991 if (qc->flags & ATA_QCFLAG_FAILED) 1170 if ((qc->flags & ATA_QCFLAG_FAILED) && sil24_init_port(ap))
992 sil24_init_port(ap); 1171 ata_eh_freeze_port(ap);
993} 1172}
994 1173
995static int sil24_port_start(struct ata_port *ap) 1174static int sil24_port_start(struct ata_port *ap)
@@ -1190,6 +1369,12 @@ static int sil24_pci_device_resume(struct pci_dev *pdev)
1190 1369
1191 return 0; 1370 return 0;
1192} 1371}
1372
1373static int sil24_port_resume(struct ata_port *ap)
1374{
1375 sil24_config_pmp(ap, ap->nr_pmp_links);
1376 return 0;
1377}
1193#endif 1378#endif
1194 1379
1195static int __init sil24_init(void) 1380static int __init sil24_init(void)