diff options
Diffstat (limited to 'drivers/ata/sata_sil24.c')
-rw-r--r-- | drivers/ata/sata_sil24.c | 111 |
1 files changed, 40 insertions, 71 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 4f522ec04049..e6223ba667da 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c | |||
@@ -331,7 +331,6 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); | |||
331 | static void sil24_qc_prep(struct ata_queued_cmd *qc); | 331 | static void sil24_qc_prep(struct ata_queued_cmd *qc); |
332 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); | 332 | static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); |
333 | static void sil24_irq_clear(struct ata_port *ap); | 333 | static void sil24_irq_clear(struct ata_port *ap); |
334 | static irqreturn_t sil24_interrupt(int irq, void *dev_instance); | ||
335 | static void sil24_freeze(struct ata_port *ap); | 334 | static void sil24_freeze(struct ata_port *ap); |
336 | static void sil24_thaw(struct ata_port *ap); | 335 | static void sil24_thaw(struct ata_port *ap); |
337 | static void sil24_error_handler(struct ata_port *ap); | 336 | static void sil24_error_handler(struct ata_port *ap); |
@@ -401,7 +400,6 @@ static const struct ata_port_operations sil24_ops = { | |||
401 | .qc_prep = sil24_qc_prep, | 400 | .qc_prep = sil24_qc_prep, |
402 | .qc_issue = sil24_qc_issue, | 401 | .qc_issue = sil24_qc_issue, |
403 | 402 | ||
404 | .irq_handler = sil24_interrupt, | ||
405 | .irq_clear = sil24_irq_clear, | 403 | .irq_clear = sil24_irq_clear, |
406 | .irq_on = ata_dummy_irq_on, | 404 | .irq_on = ata_dummy_irq_on, |
407 | .irq_ack = ata_dummy_irq_ack, | 405 | .irq_ack = ata_dummy_irq_ack, |
@@ -424,10 +422,9 @@ static const struct ata_port_operations sil24_ops = { | |||
424 | #define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30) | 422 | #define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30) |
425 | #define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1) | 423 | #define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1) |
426 | 424 | ||
427 | static struct ata_port_info sil24_port_info[] = { | 425 | static const struct ata_port_info sil24_port_info[] = { |
428 | /* sil_3124 */ | 426 | /* sil_3124 */ |
429 | { | 427 | { |
430 | .sht = &sil24_sht, | ||
431 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | | 428 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | |
432 | SIL24_FLAG_PCIX_IRQ_WOC, | 429 | SIL24_FLAG_PCIX_IRQ_WOC, |
433 | .pio_mask = 0x1f, /* pio0-4 */ | 430 | .pio_mask = 0x1f, /* pio0-4 */ |
@@ -437,7 +434,6 @@ static struct ata_port_info sil24_port_info[] = { | |||
437 | }, | 434 | }, |
438 | /* sil_3132 */ | 435 | /* sil_3132 */ |
439 | { | 436 | { |
440 | .sht = &sil24_sht, | ||
441 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), | 437 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), |
442 | .pio_mask = 0x1f, /* pio0-4 */ | 438 | .pio_mask = 0x1f, /* pio0-4 */ |
443 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 439 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
@@ -446,7 +442,6 @@ static struct ata_port_info sil24_port_info[] = { | |||
446 | }, | 442 | }, |
447 | /* sil_3131/sil_3531 */ | 443 | /* sil_3131/sil_3531 */ |
448 | { | 444 | { |
449 | .sht = &sil24_sht, | ||
450 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), | 445 | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), |
451 | .pio_mask = 0x1f, /* pio0-4 */ | 446 | .pio_mask = 0x1f, /* pio0-4 */ |
452 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 447 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
@@ -961,11 +956,10 @@ static int sil24_port_start(struct ata_port *ap) | |||
961 | return 0; | 956 | return 0; |
962 | } | 957 | } |
963 | 958 | ||
964 | static void sil24_init_controller(struct pci_dev *pdev, int n_ports, | 959 | static void sil24_init_controller(struct ata_host *host) |
965 | unsigned long port_flags, | ||
966 | void __iomem *host_base, | ||
967 | void __iomem *port_base) | ||
968 | { | 960 | { |
961 | void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; | ||
962 | void __iomem *port_base = host->iomap[SIL24_PORT_BAR]; | ||
969 | u32 tmp; | 963 | u32 tmp; |
970 | int i; | 964 | int i; |
971 | 965 | ||
@@ -976,7 +970,7 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports, | |||
976 | writel(0, host_base + HOST_CTRL); | 970 | writel(0, host_base + HOST_CTRL); |
977 | 971 | ||
978 | /* init ports */ | 972 | /* init ports */ |
979 | for (i = 0; i < n_ports; i++) { | 973 | for (i = 0; i < host->n_ports; i++) { |
980 | void __iomem *port = port_base + i * PORT_REGS_SIZE; | 974 | void __iomem *port = port_base + i * PORT_REGS_SIZE; |
981 | 975 | ||
982 | /* Initial PHY setting */ | 976 | /* Initial PHY setting */ |
@@ -990,12 +984,12 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports, | |||
990 | PORT_CS_PORT_RST, | 984 | PORT_CS_PORT_RST, |
991 | PORT_CS_PORT_RST, 10, 100); | 985 | PORT_CS_PORT_RST, 10, 100); |
992 | if (tmp & PORT_CS_PORT_RST) | 986 | if (tmp & PORT_CS_PORT_RST) |
993 | dev_printk(KERN_ERR, &pdev->dev, | 987 | dev_printk(KERN_ERR, host->dev, |
994 | "failed to clear port RST\n"); | 988 | "failed to clear port RST\n"); |
995 | } | 989 | } |
996 | 990 | ||
997 | /* Configure IRQ WoC */ | 991 | /* Configure IRQ WoC */ |
998 | if (port_flags & SIL24_FLAG_PCIX_IRQ_WOC) | 992 | if (host->ports[0]->flags & SIL24_FLAG_PCIX_IRQ_WOC) |
999 | writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); | 993 | writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); |
1000 | else | 994 | else |
1001 | writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); | 995 | writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); |
@@ -1023,18 +1017,17 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports, | |||
1023 | static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 1017 | static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
1024 | { | 1018 | { |
1025 | static int printed_version = 0; | 1019 | static int printed_version = 0; |
1026 | struct device *dev = &pdev->dev; | 1020 | struct ata_port_info pi = sil24_port_info[ent->driver_data]; |
1027 | unsigned int board_id = (unsigned int)ent->driver_data; | 1021 | const struct ata_port_info *ppi[] = { &pi, NULL }; |
1028 | struct ata_port_info *pinfo = &sil24_port_info[board_id]; | 1022 | void __iomem * const *iomap; |
1029 | struct ata_probe_ent *probe_ent; | 1023 | struct ata_host *host; |
1030 | void __iomem *host_base; | ||
1031 | void __iomem *port_base; | ||
1032 | int i, rc; | 1024 | int i, rc; |
1033 | u32 tmp; | 1025 | u32 tmp; |
1034 | 1026 | ||
1035 | if (!printed_version++) | 1027 | if (!printed_version++) |
1036 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | 1028 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); |
1037 | 1029 | ||
1030 | /* acquire resources */ | ||
1038 | rc = pcim_enable_device(pdev); | 1031 | rc = pcim_enable_device(pdev); |
1039 | if (rc) | 1032 | if (rc) |
1040 | return rc; | 1033 | return rc; |
@@ -1044,33 +1037,36 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1044 | DRV_NAME); | 1037 | DRV_NAME); |
1045 | if (rc) | 1038 | if (rc) |
1046 | return rc; | 1039 | return rc; |
1040 | iomap = pcim_iomap_table(pdev); | ||
1047 | 1041 | ||
1048 | /* allocate & init probe_ent */ | 1042 | /* apply workaround for completion IRQ loss on PCI-X errata */ |
1049 | probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL); | 1043 | if (pi.flags & SIL24_FLAG_PCIX_IRQ_WOC) { |
1050 | if (!probe_ent) | 1044 | tmp = readl(iomap[SIL24_HOST_BAR] + HOST_CTRL); |
1051 | return -ENOMEM; | 1045 | if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL)) |
1046 | dev_printk(KERN_INFO, &pdev->dev, | ||
1047 | "Applying completion IRQ loss on PCI-X " | ||
1048 | "errata fix\n"); | ||
1049 | else | ||
1050 | pi.flags &= ~SIL24_FLAG_PCIX_IRQ_WOC; | ||
1051 | } | ||
1052 | 1052 | ||
1053 | probe_ent->dev = pci_dev_to_dev(pdev); | 1053 | /* allocate and fill host */ |
1054 | INIT_LIST_HEAD(&probe_ent->node); | 1054 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, |
1055 | SIL24_FLAG2NPORTS(ppi[0]->flags)); | ||
1056 | if (!host) | ||
1057 | return -ENOMEM; | ||
1058 | host->iomap = iomap; | ||
1055 | 1059 | ||
1056 | probe_ent->sht = pinfo->sht; | 1060 | for (i = 0; i < host->n_ports; i++) { |
1057 | probe_ent->port_flags = pinfo->flags; | 1061 | void __iomem *port = iomap[SIL24_PORT_BAR] + i * PORT_REGS_SIZE; |
1058 | probe_ent->pio_mask = pinfo->pio_mask; | ||
1059 | probe_ent->mwdma_mask = pinfo->mwdma_mask; | ||
1060 | probe_ent->udma_mask = pinfo->udma_mask; | ||
1061 | probe_ent->port_ops = pinfo->port_ops; | ||
1062 | probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->flags); | ||
1063 | 1062 | ||
1064 | probe_ent->irq = pdev->irq; | 1063 | host->ports[i]->ioaddr.cmd_addr = port; |
1065 | probe_ent->irq_flags = IRQF_SHARED; | 1064 | host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL; |
1066 | probe_ent->iomap = pcim_iomap_table(pdev); | ||
1067 | 1065 | ||
1068 | host_base = probe_ent->iomap[SIL24_HOST_BAR]; | 1066 | ata_std_ports(&host->ports[i]->ioaddr); |
1069 | port_base = probe_ent->iomap[SIL24_PORT_BAR]; | 1067 | } |
1070 | 1068 | ||
1071 | /* | 1069 | /* configure and activate the device */ |
1072 | * Configure the device | ||
1073 | */ | ||
1074 | if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { | 1070 | if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { |
1075 | rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); | 1071 | rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); |
1076 | if (rc) { | 1072 | if (rc) { |
@@ -1096,36 +1092,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1096 | } | 1092 | } |
1097 | } | 1093 | } |
1098 | 1094 | ||
1099 | /* Apply workaround for completion IRQ loss on PCI-X errata */ | 1095 | sil24_init_controller(host); |
1100 | if (probe_ent->port_flags & SIL24_FLAG_PCIX_IRQ_WOC) { | ||
1101 | tmp = readl(host_base + HOST_CTRL); | ||
1102 | if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL)) | ||
1103 | dev_printk(KERN_INFO, &pdev->dev, | ||
1104 | "Applying completion IRQ loss on PCI-X " | ||
1105 | "errata fix\n"); | ||
1106 | else | ||
1107 | probe_ent->port_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC; | ||
1108 | } | ||
1109 | |||
1110 | for (i = 0; i < probe_ent->n_ports; i++) { | ||
1111 | void __iomem *port = port_base + i * PORT_REGS_SIZE; | ||
1112 | |||
1113 | probe_ent->port[i].cmd_addr = port; | ||
1114 | probe_ent->port[i].scr_addr = port + PORT_SCONTROL; | ||
1115 | |||
1116 | ata_std_ports(&probe_ent->port[i]); | ||
1117 | } | ||
1118 | |||
1119 | sil24_init_controller(pdev, probe_ent->n_ports, probe_ent->port_flags, | ||
1120 | host_base, port_base); | ||
1121 | 1096 | ||
1122 | pci_set_master(pdev); | 1097 | pci_set_master(pdev); |
1123 | 1098 | return ata_host_activate(host, pdev->irq, sil24_interrupt, IRQF_SHARED, | |
1124 | if (!ata_device_add(probe_ent)) | 1099 | &sil24_sht); |
1125 | return -ENODEV; | ||
1126 | |||
1127 | devm_kfree(dev, probe_ent); | ||
1128 | return 0; | ||
1129 | } | 1100 | } |
1130 | 1101 | ||
1131 | #ifdef CONFIG_PM | 1102 | #ifdef CONFIG_PM |
@@ -1133,7 +1104,6 @@ static int sil24_pci_device_resume(struct pci_dev *pdev) | |||
1133 | { | 1104 | { |
1134 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | 1105 | struct ata_host *host = dev_get_drvdata(&pdev->dev); |
1135 | void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; | 1106 | void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; |
1136 | void __iomem *port_base = host->iomap[SIL24_PORT_BAR]; | ||
1137 | int rc; | 1107 | int rc; |
1138 | 1108 | ||
1139 | rc = ata_pci_device_do_resume(pdev); | 1109 | rc = ata_pci_device_do_resume(pdev); |
@@ -1143,8 +1113,7 @@ static int sil24_pci_device_resume(struct pci_dev *pdev) | |||
1143 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) | 1113 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) |
1144 | writel(HOST_CTRL_GLOBAL_RST, host_base + HOST_CTRL); | 1114 | writel(HOST_CTRL_GLOBAL_RST, host_base + HOST_CTRL); |
1145 | 1115 | ||
1146 | sil24_init_controller(pdev, host->n_ports, host->ports[0]->flags, | 1116 | sil24_init_controller(host); |
1147 | host_base, port_base); | ||
1148 | 1117 | ||
1149 | ata_host_resume(host); | 1118 | ata_host_resume(host); |
1150 | 1119 | ||