diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2018-04-04 14:28:45 -0400 |
---|---|---|
committer | Bjorn Helgaas <helgaas@kernel.org> | 2018-04-04 14:28:45 -0400 |
commit | 1ad9a8730e8fd15c6f2ed2230e38a61c3a61d438 (patch) | |
tree | 9bc5e197aac73b91a8c039a57ea1568fba4f3af2 | |
parent | f3c91098a444c905b69a83a4947d9dbc774f986d (diff) | |
parent | 1f319cb0538a10339d1ca73ee124331d611b43bf (diff) |
Merge branch 'lorenzo/pci/dwc-msi'
* lorenzo/pci/dwc-msi:
PCI: dwc: Expand maximum number of MSI IRQs from 32 to 256
PCI: dwc: Remove old MSI IRQs API
PCI: dwc: Move MSI IRQs allocation to IRQ domains hierarchical API
-rw-r--r-- | drivers/pci/dwc/pci-exynos.c | 18 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-imx6.c | 18 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone-dw.c | 91 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone.c | 1 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone.h | 4 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-layerscape.c | 3 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-artpec6.c | 18 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware-host.c | 396 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware-plat.c | 16 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware.h | 30 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-histb.c | 15 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-qcom.c | 16 |
12 files changed, 256 insertions, 370 deletions
diff --git a/drivers/pci/dwc/pci-exynos.c b/drivers/pci/dwc/pci-exynos.c index ca6278113936..4cc1e5df8c79 100644 --- a/drivers/pci/dwc/pci-exynos.c +++ b/drivers/pci/dwc/pci-exynos.c | |||
@@ -294,15 +294,6 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) | |||
294 | return IRQ_HANDLED; | 294 | return IRQ_HANDLED; |
295 | } | 295 | } |
296 | 296 | ||
297 | static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg) | ||
298 | { | ||
299 | struct exynos_pcie *ep = arg; | ||
300 | struct dw_pcie *pci = ep->pci; | ||
301 | struct pcie_port *pp = &pci->pp; | ||
302 | |||
303 | return dw_handle_msi_irq(pp); | ||
304 | } | ||
305 | |||
306 | static void exynos_pcie_msi_init(struct exynos_pcie *ep) | 297 | static void exynos_pcie_msi_init(struct exynos_pcie *ep) |
307 | { | 298 | { |
308 | struct dw_pcie *pci = ep->pci; | 299 | struct dw_pcie *pci = ep->pci; |
@@ -428,15 +419,6 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *ep, | |||
428 | dev_err(dev, "failed to get msi irq\n"); | 419 | dev_err(dev, "failed to get msi irq\n"); |
429 | return pp->msi_irq; | 420 | return pp->msi_irq; |
430 | } | 421 | } |
431 | |||
432 | ret = devm_request_irq(dev, pp->msi_irq, | ||
433 | exynos_pcie_msi_irq_handler, | ||
434 | IRQF_SHARED | IRQF_NO_THREAD, | ||
435 | "exynos-pcie", ep); | ||
436 | if (ret) { | ||
437 | dev_err(dev, "failed to request msi irq\n"); | ||
438 | return ret; | ||
439 | } | ||
440 | } | 422 | } |
441 | 423 | ||
442 | pp->root_bus_nr = -1; | 424 | pp->root_bus_nr = -1; |
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 4fddbd08b089..4818ef875f8a 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c | |||
@@ -542,15 +542,6 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie) | |||
542 | return -EINVAL; | 542 | return -EINVAL; |
543 | } | 543 | } |
544 | 544 | ||
545 | static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg) | ||
546 | { | ||
547 | struct imx6_pcie *imx6_pcie = arg; | ||
548 | struct dw_pcie *pci = imx6_pcie->pci; | ||
549 | struct pcie_port *pp = &pci->pp; | ||
550 | |||
551 | return dw_handle_msi_irq(pp); | ||
552 | } | ||
553 | |||
554 | static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) | 545 | static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) |
555 | { | 546 | { |
556 | struct dw_pcie *pci = imx6_pcie->pci; | 547 | struct dw_pcie *pci = imx6_pcie->pci; |
@@ -674,15 +665,6 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, | |||
674 | dev_err(dev, "failed to get MSI irq\n"); | 665 | dev_err(dev, "failed to get MSI irq\n"); |
675 | return -ENODEV; | 666 | return -ENODEV; |
676 | } | 667 | } |
677 | |||
678 | ret = devm_request_irq(dev, pp->msi_irq, | ||
679 | imx6_pcie_msi_handler, | ||
680 | IRQF_SHARED | IRQF_NO_THREAD, | ||
681 | "mx6-pcie-msi", imx6_pcie); | ||
682 | if (ret) { | ||
683 | dev_err(dev, "failed to request MSI irq\n"); | ||
684 | return ret; | ||
685 | } | ||
686 | } | 668 | } |
687 | 669 | ||
688 | pp->root_bus_nr = -1; | 670 | pp->root_bus_nr = -1; |
diff --git a/drivers/pci/dwc/pci-keystone-dw.c b/drivers/pci/dwc/pci-keystone-dw.c index 99a0e7076221..0682213328e9 100644 --- a/drivers/pci/dwc/pci-keystone-dw.c +++ b/drivers/pci/dwc/pci-keystone-dw.c | |||
@@ -120,20 +120,15 @@ void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset) | |||
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | static void ks_dw_pcie_msi_irq_ack(struct irq_data *d) | 123 | void ks_dw_pcie_msi_irq_ack(int irq, struct pcie_port *pp) |
124 | { | 124 | { |
125 | u32 offset, reg_offset, bit_pos; | 125 | u32 reg_offset, bit_pos; |
126 | struct keystone_pcie *ks_pcie; | 126 | struct keystone_pcie *ks_pcie; |
127 | struct msi_desc *msi; | ||
128 | struct pcie_port *pp; | ||
129 | struct dw_pcie *pci; | 127 | struct dw_pcie *pci; |
130 | 128 | ||
131 | msi = irq_data_get_msi_desc(d); | ||
132 | pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); | ||
133 | pci = to_dw_pcie_from_pp(pp); | 129 | pci = to_dw_pcie_from_pp(pp); |
134 | ks_pcie = to_keystone_pcie(pci); | 130 | ks_pcie = to_keystone_pcie(pci); |
135 | offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); | 131 | update_reg_offset_bit_pos(irq, ®_offset, &bit_pos); |
136 | update_reg_offset_bit_pos(offset, ®_offset, &bit_pos); | ||
137 | 132 | ||
138 | ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4), | 133 | ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4), |
139 | BIT(bit_pos)); | 134 | BIT(bit_pos)); |
@@ -162,85 +157,9 @@ void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) | |||
162 | BIT(bit_pos)); | 157 | BIT(bit_pos)); |
163 | } | 158 | } |
164 | 159 | ||
165 | static void ks_dw_pcie_msi_irq_mask(struct irq_data *d) | 160 | int ks_dw_pcie_msi_host_init(struct pcie_port *pp) |
166 | { | ||
167 | struct msi_desc *msi; | ||
168 | struct pcie_port *pp; | ||
169 | u32 offset; | ||
170 | |||
171 | msi = irq_data_get_msi_desc(d); | ||
172 | pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); | ||
173 | offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); | ||
174 | |||
175 | /* Mask the end point if PVM implemented */ | ||
176 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
177 | if (msi->msi_attrib.maskbit) | ||
178 | pci_msi_mask_irq(d); | ||
179 | } | ||
180 | |||
181 | ks_dw_pcie_msi_clear_irq(pp, offset); | ||
182 | } | ||
183 | |||
184 | static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d) | ||
185 | { | ||
186 | struct msi_desc *msi; | ||
187 | struct pcie_port *pp; | ||
188 | u32 offset; | ||
189 | |||
190 | msi = irq_data_get_msi_desc(d); | ||
191 | pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); | ||
192 | offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); | ||
193 | |||
194 | /* Mask the end point if PVM implemented */ | ||
195 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
196 | if (msi->msi_attrib.maskbit) | ||
197 | pci_msi_unmask_irq(d); | ||
198 | } | ||
199 | |||
200 | ks_dw_pcie_msi_set_irq(pp, offset); | ||
201 | } | ||
202 | |||
203 | static struct irq_chip ks_dw_pcie_msi_irq_chip = { | ||
204 | .name = "Keystone-PCIe-MSI-IRQ", | ||
205 | .irq_ack = ks_dw_pcie_msi_irq_ack, | ||
206 | .irq_mask = ks_dw_pcie_msi_irq_mask, | ||
207 | .irq_unmask = ks_dw_pcie_msi_irq_unmask, | ||
208 | }; | ||
209 | |||
210 | static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, | ||
211 | irq_hw_number_t hwirq) | ||
212 | { | 161 | { |
213 | irq_set_chip_and_handler(irq, &ks_dw_pcie_msi_irq_chip, | 162 | return dw_pcie_allocate_domains(pp); |
214 | handle_level_irq); | ||
215 | irq_set_chip_data(irq, domain->host_data); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = { | ||
221 | .map = ks_dw_pcie_msi_map, | ||
222 | }; | ||
223 | |||
224 | int ks_dw_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip) | ||
225 | { | ||
226 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | ||
227 | struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); | ||
228 | struct device *dev = pci->dev; | ||
229 | int i; | ||
230 | |||
231 | pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np, | ||
232 | MAX_MSI_IRQS, | ||
233 | &ks_dw_pcie_msi_domain_ops, | ||
234 | chip); | ||
235 | if (!pp->irq_domain) { | ||
236 | dev_err(dev, "irq domain init failed\n"); | ||
237 | return -ENXIO; | ||
238 | } | ||
239 | |||
240 | for (i = 0; i < MAX_MSI_IRQS; i++) | ||
241 | irq_create_mapping(pp->irq_domain, i); | ||
242 | |||
243 | return 0; | ||
244 | } | 163 | } |
245 | 164 | ||
246 | void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie) | 165 | void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie) |
diff --git a/drivers/pci/dwc/pci-keystone.c b/drivers/pci/dwc/pci-keystone.c index d4f8ab90c018..d55ae0716adf 100644 --- a/drivers/pci/dwc/pci-keystone.c +++ b/drivers/pci/dwc/pci-keystone.c | |||
@@ -297,6 +297,7 @@ static const struct dw_pcie_host_ops keystone_pcie_host_ops = { | |||
297 | .msi_clear_irq = ks_dw_pcie_msi_clear_irq, | 297 | .msi_clear_irq = ks_dw_pcie_msi_clear_irq, |
298 | .get_msi_addr = ks_dw_pcie_get_msi_addr, | 298 | .get_msi_addr = ks_dw_pcie_get_msi_addr, |
299 | .msi_host_init = ks_dw_pcie_msi_host_init, | 299 | .msi_host_init = ks_dw_pcie_msi_host_init, |
300 | .msi_irq_ack = ks_dw_pcie_msi_irq_ack, | ||
300 | .scan_bus = ks_dw_pcie_v3_65_scan_bus, | 301 | .scan_bus = ks_dw_pcie_v3_65_scan_bus, |
301 | }; | 302 | }; |
302 | 303 | ||
diff --git a/drivers/pci/dwc/pci-keystone.h b/drivers/pci/dwc/pci-keystone.h index 1dd1f3ef98e7..8a13da391543 100644 --- a/drivers/pci/dwc/pci-keystone.h +++ b/drivers/pci/dwc/pci-keystone.h | |||
@@ -49,9 +49,9 @@ int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
49 | unsigned int devfn, int where, int size, u32 *val); | 49 | unsigned int devfn, int where, int size, u32 *val); |
50 | void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie); | 50 | void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie); |
51 | void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie); | 51 | void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie); |
52 | void ks_dw_pcie_msi_irq_ack(int i, struct pcie_port *pp); | ||
52 | void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq); | 53 | void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq); |
53 | void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq); | 54 | void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq); |
54 | void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp); | 55 | void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp); |
55 | int ks_dw_pcie_msi_host_init(struct pcie_port *pp, | 56 | int ks_dw_pcie_msi_host_init(struct pcie_port *pp); |
56 | struct msi_controller *chip); | ||
57 | int ks_dw_pcie_link_up(struct dw_pcie *pci); | 57 | int ks_dw_pcie_link_up(struct dw_pcie *pci); |
diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c index a7b4159631ae..3724d3ef7008 100644 --- a/drivers/pci/dwc/pci-layerscape.c +++ b/drivers/pci/dwc/pci-layerscape.c | |||
@@ -182,8 +182,7 @@ static int ls1021_pcie_host_init(struct pcie_port *pp) | |||
182 | return ls_pcie_host_init(pp); | 182 | return ls_pcie_host_init(pp); |
183 | } | 183 | } |
184 | 184 | ||
185 | static int ls_pcie_msi_host_init(struct pcie_port *pp, | 185 | static int ls_pcie_msi_host_init(struct pcie_port *pp) |
186 | struct msi_controller *chip) | ||
187 | { | 186 | { |
188 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 187 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
189 | struct device *dev = pci->dev; | 188 | struct device *dev = pci->dev; |
diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 93b3df9ed1b5..e66cede2b5b7 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c | |||
@@ -383,15 +383,6 @@ static const struct dw_pcie_host_ops artpec6_pcie_host_ops = { | |||
383 | .host_init = artpec6_pcie_host_init, | 383 | .host_init = artpec6_pcie_host_init, |
384 | }; | 384 | }; |
385 | 385 | ||
386 | static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg) | ||
387 | { | ||
388 | struct artpec6_pcie *artpec6_pcie = arg; | ||
389 | struct dw_pcie *pci = artpec6_pcie->pci; | ||
390 | struct pcie_port *pp = &pci->pp; | ||
391 | |||
392 | return dw_handle_msi_irq(pp); | ||
393 | } | ||
394 | |||
395 | static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, | 386 | static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, |
396 | struct platform_device *pdev) | 387 | struct platform_device *pdev) |
397 | { | 388 | { |
@@ -406,15 +397,6 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, | |||
406 | dev_err(dev, "failed to get MSI irq\n"); | 397 | dev_err(dev, "failed to get MSI irq\n"); |
407 | return pp->msi_irq; | 398 | return pp->msi_irq; |
408 | } | 399 | } |
409 | |||
410 | ret = devm_request_irq(dev, pp->msi_irq, | ||
411 | artpec6_pcie_msi_handler, | ||
412 | IRQF_SHARED | IRQF_NO_THREAD, | ||
413 | "artpec6-pcie-msi", artpec6_pcie); | ||
414 | if (ret) { | ||
415 | dev_err(dev, "failed to request MSI irq\n"); | ||
416 | return ret; | ||
417 | } | ||
418 | } | 400 | } |
419 | 401 | ||
420 | pp->root_bus_nr = -1; | 402 | pp->root_bus_nr = -1; |
diff --git a/drivers/pci/dwc/pcie-designware-host.c b/drivers/pci/dwc/pcie-designware-host.c index 8de2d5c69b1d..550fdbb5c226 100644 --- a/drivers/pci/dwc/pcie-designware-host.c +++ b/drivers/pci/dwc/pcie-designware-host.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Author: Jingoo Han <jg1.han@samsung.com> | 8 | * Author: Jingoo Han <jg1.han@samsung.com> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/irqchip/chained_irq.h> | ||
11 | #include <linux/irqdomain.h> | 12 | #include <linux/irqdomain.h> |
12 | #include <linux/of_address.h> | 13 | #include <linux/of_address.h> |
13 | #include <linux/of_pci.h> | 14 | #include <linux/of_pci.h> |
@@ -42,22 +43,46 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, | |||
42 | return dw_pcie_write(pci->dbi_base + where, size, val); | 43 | return dw_pcie_write(pci->dbi_base + where, size, val); |
43 | } | 44 | } |
44 | 45 | ||
45 | static struct irq_chip dw_msi_irq_chip = { | 46 | static void dw_msi_ack_irq(struct irq_data *d) |
47 | { | ||
48 | irq_chip_ack_parent(d); | ||
49 | } | ||
50 | |||
51 | static void dw_msi_mask_irq(struct irq_data *d) | ||
52 | { | ||
53 | pci_msi_mask_irq(d); | ||
54 | irq_chip_mask_parent(d); | ||
55 | } | ||
56 | |||
57 | static void dw_msi_unmask_irq(struct irq_data *d) | ||
58 | { | ||
59 | pci_msi_unmask_irq(d); | ||
60 | irq_chip_unmask_parent(d); | ||
61 | } | ||
62 | |||
63 | static struct irq_chip dw_pcie_msi_irq_chip = { | ||
46 | .name = "PCI-MSI", | 64 | .name = "PCI-MSI", |
47 | .irq_enable = pci_msi_unmask_irq, | 65 | .irq_ack = dw_msi_ack_irq, |
48 | .irq_disable = pci_msi_mask_irq, | 66 | .irq_mask = dw_msi_mask_irq, |
49 | .irq_mask = pci_msi_mask_irq, | 67 | .irq_unmask = dw_msi_unmask_irq, |
50 | .irq_unmask = pci_msi_unmask_irq, | 68 | }; |
69 | |||
70 | static struct msi_domain_info dw_pcie_msi_domain_info = { | ||
71 | .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | | ||
72 | MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI), | ||
73 | .chip = &dw_pcie_msi_irq_chip, | ||
51 | }; | 74 | }; |
52 | 75 | ||
53 | /* MSI int handler */ | 76 | /* MSI int handler */ |
54 | irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) | 77 | irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) |
55 | { | 78 | { |
56 | u32 val; | ||
57 | int i, pos, irq; | 79 | int i, pos, irq; |
80 | u32 val, num_ctrls; | ||
58 | irqreturn_t ret = IRQ_NONE; | 81 | irqreturn_t ret = IRQ_NONE; |
59 | 82 | ||
60 | for (i = 0; i < MAX_MSI_CTRLS; i++) { | 83 | num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; |
84 | |||
85 | for (i = 0; i < num_ctrls; i++) { | ||
61 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, | 86 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, |
62 | &val); | 87 | &val); |
63 | if (!val) | 88 | if (!val) |
@@ -78,206 +103,216 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) | |||
78 | return ret; | 103 | return ret; |
79 | } | 104 | } |
80 | 105 | ||
81 | void dw_pcie_msi_init(struct pcie_port *pp) | 106 | /* Chained MSI interrupt service routine */ |
107 | static void dw_chained_msi_isr(struct irq_desc *desc) | ||
82 | { | 108 | { |
83 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 109 | struct irq_chip *chip = irq_desc_get_chip(desc); |
84 | struct device *dev = pci->dev; | 110 | struct pcie_port *pp; |
85 | struct page *page; | ||
86 | u64 msi_target; | ||
87 | 111 | ||
88 | page = alloc_page(GFP_KERNEL); | 112 | chained_irq_enter(chip, desc); |
89 | pp->msi_data = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); | ||
90 | if (dma_mapping_error(dev, pp->msi_data)) { | ||
91 | dev_err(dev, "failed to map MSI data\n"); | ||
92 | __free_page(page); | ||
93 | return; | ||
94 | } | ||
95 | msi_target = (u64)pp->msi_data; | ||
96 | 113 | ||
97 | /* program the msi_data */ | 114 | pp = irq_desc_get_handler_data(desc); |
98 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, | 115 | dw_handle_msi_irq(pp); |
99 | (u32)(msi_target & 0xffffffff)); | 116 | |
100 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, | 117 | chained_irq_exit(chip, desc); |
101 | (u32)(msi_target >> 32 & 0xffffffff)); | ||
102 | } | 118 | } |
103 | 119 | ||
104 | static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) | 120 | static void dw_pci_setup_msi_msg(struct irq_data *data, struct msi_msg *msg) |
105 | { | 121 | { |
106 | unsigned int res, bit, val; | 122 | struct pcie_port *pp = irq_data_get_irq_chip_data(data); |
123 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | ||
124 | u64 msi_target; | ||
107 | 125 | ||
108 | res = (irq / 32) * 12; | 126 | if (pp->ops->get_msi_addr) |
109 | bit = irq % 32; | 127 | msi_target = pp->ops->get_msi_addr(pp); |
110 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); | 128 | else |
111 | val &= ~(1 << bit); | 129 | msi_target = (u64)pp->msi_data; |
112 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); | ||
113 | } | ||
114 | 130 | ||
115 | static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base, | 131 | msg->address_lo = lower_32_bits(msi_target); |
116 | unsigned int nvec, unsigned int pos) | 132 | msg->address_hi = upper_32_bits(msi_target); |
117 | { | ||
118 | unsigned int i; | ||
119 | |||
120 | for (i = 0; i < nvec; i++) { | ||
121 | irq_set_msi_desc_off(irq_base, i, NULL); | ||
122 | /* Disable corresponding interrupt on MSI controller */ | ||
123 | if (pp->ops->msi_clear_irq) | ||
124 | pp->ops->msi_clear_irq(pp, pos + i); | ||
125 | else | ||
126 | dw_pcie_msi_clear_irq(pp, pos + i); | ||
127 | } | ||
128 | 133 | ||
129 | bitmap_release_region(pp->msi_irq_in_use, pos, order_base_2(nvec)); | 134 | if (pp->ops->get_msi_data) |
135 | msg->data = pp->ops->get_msi_data(pp, data->hwirq); | ||
136 | else | ||
137 | msg->data = data->hwirq; | ||
138 | |||
139 | dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n", | ||
140 | (int)data->hwirq, msg->address_hi, msg->address_lo); | ||
130 | } | 141 | } |
131 | 142 | ||
132 | static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq) | 143 | static int dw_pci_msi_set_affinity(struct irq_data *irq_data, |
144 | const struct cpumask *mask, bool force) | ||
133 | { | 145 | { |
134 | unsigned int res, bit, val; | 146 | return -EINVAL; |
135 | |||
136 | res = (irq / 32) * 12; | ||
137 | bit = irq % 32; | ||
138 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); | ||
139 | val |= 1 << bit; | ||
140 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); | ||
141 | } | 147 | } |
142 | 148 | ||
143 | static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) | 149 | static void dw_pci_bottom_mask(struct irq_data *data) |
144 | { | 150 | { |
145 | int irq, pos0, i; | 151 | struct pcie_port *pp = irq_data_get_irq_chip_data(data); |
146 | struct pcie_port *pp; | 152 | unsigned int res, bit, ctrl; |
147 | 153 | unsigned long flags; | |
148 | pp = (struct pcie_port *)msi_desc_to_pci_sysdata(desc); | ||
149 | pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS, | ||
150 | order_base_2(no_irqs)); | ||
151 | if (pos0 < 0) | ||
152 | goto no_valid_irq; | ||
153 | 154 | ||
154 | irq = irq_find_mapping(pp->irq_domain, pos0); | 155 | raw_spin_lock_irqsave(&pp->lock, flags); |
155 | if (!irq) | ||
156 | goto no_valid_irq; | ||
157 | 156 | ||
158 | /* | 157 | if (pp->ops->msi_clear_irq) { |
159 | * irq_create_mapping (called from dw_pcie_host_init) pre-allocates | 158 | pp->ops->msi_clear_irq(pp, data->hwirq); |
160 | * descs so there is no need to allocate descs here. We can therefore | 159 | } else { |
161 | * assume that if irq_find_mapping above returns non-zero, then the | 160 | ctrl = data->hwirq / 32; |
162 | * descs are also successfully allocated. | 161 | res = ctrl * 12; |
163 | */ | 162 | bit = data->hwirq % 32; |
164 | 163 | ||
165 | for (i = 0; i < no_irqs; i++) { | 164 | pp->irq_status[ctrl] &= ~(1 << bit); |
166 | if (irq_set_msi_desc_off(irq, i, desc) != 0) { | 165 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, |
167 | clear_irq_range(pp, irq, i, pos0); | 166 | pp->irq_status[ctrl]); |
168 | goto no_valid_irq; | ||
169 | } | ||
170 | /*Enable corresponding interrupt in MSI interrupt controller */ | ||
171 | if (pp->ops->msi_set_irq) | ||
172 | pp->ops->msi_set_irq(pp, pos0 + i); | ||
173 | else | ||
174 | dw_pcie_msi_set_irq(pp, pos0 + i); | ||
175 | } | 167 | } |
176 | 168 | ||
177 | *pos = pos0; | 169 | raw_spin_unlock_irqrestore(&pp->lock, flags); |
178 | desc->nvec_used = no_irqs; | ||
179 | desc->msi_attrib.multiple = order_base_2(no_irqs); | ||
180 | |||
181 | return irq; | ||
182 | |||
183 | no_valid_irq: | ||
184 | *pos = pos0; | ||
185 | return -ENOSPC; | ||
186 | } | 170 | } |
187 | 171 | ||
188 | static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos) | 172 | static void dw_pci_bottom_unmask(struct irq_data *data) |
189 | { | 173 | { |
190 | struct msi_msg msg; | 174 | struct pcie_port *pp = irq_data_get_irq_chip_data(data); |
191 | u64 msi_target; | 175 | unsigned int res, bit, ctrl; |
176 | unsigned long flags; | ||
192 | 177 | ||
193 | if (pp->ops->get_msi_addr) | 178 | raw_spin_lock_irqsave(&pp->lock, flags); |
194 | msi_target = pp->ops->get_msi_addr(pp); | ||
195 | else | ||
196 | msi_target = (u64)pp->msi_data; | ||
197 | 179 | ||
198 | msg.address_lo = (u32)(msi_target & 0xffffffff); | 180 | if (pp->ops->msi_set_irq) { |
199 | msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff); | 181 | pp->ops->msi_set_irq(pp, data->hwirq); |
182 | } else { | ||
183 | ctrl = data->hwirq / 32; | ||
184 | res = ctrl * 12; | ||
185 | bit = data->hwirq % 32; | ||
200 | 186 | ||
201 | if (pp->ops->get_msi_data) | 187 | pp->irq_status[ctrl] |= 1 << bit; |
202 | msg.data = pp->ops->get_msi_data(pp, pos); | 188 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, |
203 | else | 189 | pp->irq_status[ctrl]); |
204 | msg.data = pos; | 190 | } |
205 | 191 | ||
206 | pci_write_msi_msg(irq, &msg); | 192 | raw_spin_unlock_irqrestore(&pp->lock, flags); |
207 | } | 193 | } |
208 | 194 | ||
209 | static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, | 195 | static void dw_pci_bottom_ack(struct irq_data *d) |
210 | struct msi_desc *desc) | ||
211 | { | 196 | { |
212 | int irq, pos; | 197 | struct msi_desc *msi = irq_data_get_msi_desc(d); |
213 | struct pcie_port *pp = pdev->bus->sysdata; | 198 | struct pcie_port *pp; |
214 | |||
215 | if (desc->msi_attrib.is_msix) | ||
216 | return -EINVAL; | ||
217 | |||
218 | irq = assign_irq(1, desc, &pos); | ||
219 | if (irq < 0) | ||
220 | return irq; | ||
221 | 199 | ||
222 | dw_msi_setup_msg(pp, irq, pos); | 200 | pp = msi_desc_to_pci_sysdata(msi); |
223 | 201 | ||
224 | return 0; | 202 | if (pp->ops->msi_irq_ack) |
203 | pp->ops->msi_irq_ack(d->hwirq, pp); | ||
225 | } | 204 | } |
226 | 205 | ||
227 | static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev, | 206 | static struct irq_chip dw_pci_msi_bottom_irq_chip = { |
228 | int nvec, int type) | 207 | .name = "DWPCI-MSI", |
208 | .irq_ack = dw_pci_bottom_ack, | ||
209 | .irq_compose_msi_msg = dw_pci_setup_msi_msg, | ||
210 | .irq_set_affinity = dw_pci_msi_set_affinity, | ||
211 | .irq_mask = dw_pci_bottom_mask, | ||
212 | .irq_unmask = dw_pci_bottom_unmask, | ||
213 | }; | ||
214 | |||
215 | static int dw_pcie_irq_domain_alloc(struct irq_domain *domain, | ||
216 | unsigned int virq, unsigned int nr_irqs, | ||
217 | void *args) | ||
229 | { | 218 | { |
230 | #ifdef CONFIG_PCI_MSI | 219 | struct pcie_port *pp = domain->host_data; |
231 | int irq, pos; | 220 | unsigned long flags; |
232 | struct msi_desc *desc; | 221 | u32 i; |
233 | struct pcie_port *pp = pdev->bus->sysdata; | 222 | int bit; |
223 | |||
224 | raw_spin_lock_irqsave(&pp->lock, flags); | ||
234 | 225 | ||
235 | /* MSI-X interrupts are not supported */ | 226 | bit = bitmap_find_free_region(pp->msi_irq_in_use, pp->num_vectors, |
236 | if (type == PCI_CAP_ID_MSIX) | 227 | order_base_2(nr_irqs)); |
237 | return -EINVAL; | ||
238 | 228 | ||
239 | WARN_ON(!list_is_singular(&pdev->dev.msi_list)); | 229 | raw_spin_unlock_irqrestore(&pp->lock, flags); |
240 | desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list); | ||
241 | 230 | ||
242 | irq = assign_irq(nvec, desc, &pos); | 231 | if (bit < 0) |
243 | if (irq < 0) | 232 | return -ENOSPC; |
244 | return irq; | ||
245 | 233 | ||
246 | dw_msi_setup_msg(pp, irq, pos); | 234 | for (i = 0; i < nr_irqs; i++) |
235 | irq_domain_set_info(domain, virq + i, bit + i, | ||
236 | &dw_pci_msi_bottom_irq_chip, | ||
237 | pp, handle_edge_irq, | ||
238 | NULL, NULL); | ||
247 | 239 | ||
248 | return 0; | 240 | return 0; |
249 | #else | ||
250 | return -EINVAL; | ||
251 | #endif | ||
252 | } | 241 | } |
253 | 242 | ||
254 | static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) | 243 | static void dw_pcie_irq_domain_free(struct irq_domain *domain, |
244 | unsigned int virq, unsigned int nr_irqs) | ||
255 | { | 245 | { |
256 | struct irq_data *data = irq_get_irq_data(irq); | 246 | struct irq_data *data = irq_domain_get_irq_data(domain, virq); |
257 | struct msi_desc *msi = irq_data_get_msi_desc(data); | 247 | struct pcie_port *pp = irq_data_get_irq_chip_data(data); |
258 | struct pcie_port *pp = (struct pcie_port *)msi_desc_to_pci_sysdata(msi); | 248 | unsigned long flags; |
259 | 249 | ||
260 | clear_irq_range(pp, irq, 1, data->hwirq); | 250 | raw_spin_lock_irqsave(&pp->lock, flags); |
251 | bitmap_release_region(pp->msi_irq_in_use, data->hwirq, | ||
252 | order_base_2(nr_irqs)); | ||
253 | raw_spin_unlock_irqrestore(&pp->lock, flags); | ||
261 | } | 254 | } |
262 | 255 | ||
263 | static struct msi_controller dw_pcie_msi_chip = { | 256 | static const struct irq_domain_ops dw_pcie_msi_domain_ops = { |
264 | .setup_irq = dw_msi_setup_irq, | 257 | .alloc = dw_pcie_irq_domain_alloc, |
265 | .setup_irqs = dw_msi_setup_irqs, | 258 | .free = dw_pcie_irq_domain_free, |
266 | .teardown_irq = dw_msi_teardown_irq, | ||
267 | }; | 259 | }; |
268 | 260 | ||
269 | static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, | 261 | int dw_pcie_allocate_domains(struct pcie_port *pp) |
270 | irq_hw_number_t hwirq) | ||
271 | { | 262 | { |
272 | irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq); | 263 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
273 | irq_set_chip_data(irq, domain->host_data); | 264 | struct fwnode_handle *fwnode = of_node_to_fwnode(pci->dev->of_node); |
265 | |||
266 | pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors, | ||
267 | &dw_pcie_msi_domain_ops, pp); | ||
268 | if (!pp->irq_domain) { | ||
269 | dev_err(pci->dev, "failed to create IRQ domain\n"); | ||
270 | return -ENOMEM; | ||
271 | } | ||
272 | |||
273 | pp->msi_domain = pci_msi_create_irq_domain(fwnode, | ||
274 | &dw_pcie_msi_domain_info, | ||
275 | pp->irq_domain); | ||
276 | if (!pp->msi_domain) { | ||
277 | dev_err(pci->dev, "failed to create MSI domain\n"); | ||
278 | irq_domain_remove(pp->irq_domain); | ||
279 | return -ENOMEM; | ||
280 | } | ||
274 | 281 | ||
275 | return 0; | 282 | return 0; |
276 | } | 283 | } |
277 | 284 | ||
278 | static const struct irq_domain_ops msi_domain_ops = { | 285 | void dw_pcie_free_msi(struct pcie_port *pp) |
279 | .map = dw_pcie_msi_map, | 286 | { |
280 | }; | 287 | irq_set_chained_handler(pp->msi_irq, NULL); |
288 | irq_set_handler_data(pp->msi_irq, NULL); | ||
289 | |||
290 | irq_domain_remove(pp->msi_domain); | ||
291 | irq_domain_remove(pp->irq_domain); | ||
292 | } | ||
293 | |||
294 | void dw_pcie_msi_init(struct pcie_port *pp) | ||
295 | { | ||
296 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | ||
297 | struct device *dev = pci->dev; | ||
298 | struct page *page; | ||
299 | u64 msi_target; | ||
300 | |||
301 | page = alloc_page(GFP_KERNEL); | ||
302 | pp->msi_data = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); | ||
303 | if (dma_mapping_error(dev, pp->msi_data)) { | ||
304 | dev_err(dev, "failed to map MSI data\n"); | ||
305 | __free_page(page); | ||
306 | return; | ||
307 | } | ||
308 | msi_target = (u64)pp->msi_data; | ||
309 | |||
310 | /* program the msi_data */ | ||
311 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, | ||
312 | lower_32_bits(msi_target)); | ||
313 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, | ||
314 | upper_32_bits(msi_target)); | ||
315 | } | ||
281 | 316 | ||
282 | int dw_pcie_host_init(struct pcie_port *pp) | 317 | int dw_pcie_host_init(struct pcie_port *pp) |
283 | { | 318 | { |
@@ -285,11 +320,13 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
285 | struct device *dev = pci->dev; | 320 | struct device *dev = pci->dev; |
286 | struct device_node *np = dev->of_node; | 321 | struct device_node *np = dev->of_node; |
287 | struct platform_device *pdev = to_platform_device(dev); | 322 | struct platform_device *pdev = to_platform_device(dev); |
323 | struct resource_entry *win, *tmp; | ||
288 | struct pci_bus *bus, *child; | 324 | struct pci_bus *bus, *child; |
289 | struct pci_host_bridge *bridge; | 325 | struct pci_host_bridge *bridge; |
290 | struct resource *cfg_res; | 326 | struct resource *cfg_res; |
291 | int i, ret; | 327 | int ret; |
292 | struct resource_entry *win, *tmp; | 328 | |
329 | raw_spin_lock_init(&pci->pp.lock); | ||
293 | 330 | ||
294 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); | 331 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); |
295 | if (cfg_res) { | 332 | if (cfg_res) { |
@@ -388,20 +425,35 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
388 | pci->num_viewport = 2; | 425 | pci->num_viewport = 2; |
389 | 426 | ||
390 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | 427 | if (IS_ENABLED(CONFIG_PCI_MSI)) { |
391 | if (!pp->ops->msi_host_init) { | 428 | /* |
392 | pp->irq_domain = irq_domain_add_linear(dev->of_node, | 429 | * If a specific SoC driver needs to change the |
393 | MAX_MSI_IRQS, &msi_domain_ops, | 430 | * default number of vectors, it needs to implement |
394 | &dw_pcie_msi_chip); | 431 | * the set_num_vectors callback. |
395 | if (!pp->irq_domain) { | 432 | */ |
396 | dev_err(dev, "irq domain init failed\n"); | 433 | if (!pp->ops->set_num_vectors) { |
397 | ret = -ENXIO; | 434 | pp->num_vectors = MSI_DEF_NUM_VECTORS; |
435 | } else { | ||
436 | pp->ops->set_num_vectors(pp); | ||
437 | |||
438 | if (pp->num_vectors > MAX_MSI_IRQS || | ||
439 | pp->num_vectors == 0) { | ||
440 | dev_err(dev, | ||
441 | "Invalid number of vectors\n"); | ||
398 | goto error; | 442 | goto error; |
399 | } | 443 | } |
444 | } | ||
400 | 445 | ||
401 | for (i = 0; i < MAX_MSI_IRQS; i++) | 446 | if (!pp->ops->msi_host_init) { |
402 | irq_create_mapping(pp->irq_domain, i); | 447 | ret = dw_pcie_allocate_domains(pp); |
448 | if (ret) | ||
449 | goto error; | ||
450 | |||
451 | if (pp->msi_irq) | ||
452 | irq_set_chained_handler_and_data(pp->msi_irq, | ||
453 | dw_chained_msi_isr, | ||
454 | pp); | ||
403 | } else { | 455 | } else { |
404 | ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip); | 456 | ret = pp->ops->msi_host_init(pp); |
405 | if (ret < 0) | 457 | if (ret < 0) |
406 | goto error; | 458 | goto error; |
407 | } | 459 | } |
@@ -421,10 +473,6 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
421 | bridge->ops = &dw_pcie_ops; | 473 | bridge->ops = &dw_pcie_ops; |
422 | bridge->map_irq = of_irq_parse_and_map_pci; | 474 | bridge->map_irq = of_irq_parse_and_map_pci; |
423 | bridge->swizzle_irq = pci_common_swizzle; | 475 | bridge->swizzle_irq = pci_common_swizzle; |
424 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
425 | bridge->msi = &dw_pcie_msi_chip; | ||
426 | dw_pcie_msi_chip.dev = dev; | ||
427 | } | ||
428 | 476 | ||
429 | ret = pci_scan_root_bus_bridge(bridge); | 477 | ret = pci_scan_root_bus_bridge(bridge); |
430 | if (ret) | 478 | if (ret) |
@@ -593,11 +641,17 @@ static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci) | |||
593 | 641 | ||
594 | void dw_pcie_setup_rc(struct pcie_port *pp) | 642 | void dw_pcie_setup_rc(struct pcie_port *pp) |
595 | { | 643 | { |
596 | u32 val; | 644 | u32 val, ctrl, num_ctrls; |
597 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 645 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
598 | 646 | ||
599 | dw_pcie_setup(pci); | 647 | dw_pcie_setup(pci); |
600 | 648 | ||
649 | num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; | ||
650 | |||
651 | /* Initialize IRQ Status array */ | ||
652 | for (ctrl = 0; ctrl < num_ctrls; ctrl++) | ||
653 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + (ctrl * 12), 4, | ||
654 | &pp->irq_status[ctrl]); | ||
601 | /* setup RC BARs */ | 655 | /* setup RC BARs */ |
602 | dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004); | 656 | dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004); |
603 | dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000); | 657 | dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000); |
diff --git a/drivers/pci/dwc/pcie-designware-plat.c b/drivers/pci/dwc/pcie-designware-plat.c index ebdf28bcd67d..5416aa8a07a5 100644 --- a/drivers/pci/dwc/pcie-designware-plat.c +++ b/drivers/pci/dwc/pcie-designware-plat.c | |||
@@ -25,13 +25,6 @@ struct dw_plat_pcie { | |||
25 | struct dw_pcie *pci; | 25 | struct dw_pcie *pci; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg) | ||
29 | { | ||
30 | struct pcie_port *pp = arg; | ||
31 | |||
32 | return dw_handle_msi_irq(pp); | ||
33 | } | ||
34 | |||
35 | static int dw_plat_pcie_host_init(struct pcie_port *pp) | 28 | static int dw_plat_pcie_host_init(struct pcie_port *pp) |
36 | { | 29 | { |
37 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 30 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
@@ -63,15 +56,6 @@ static int dw_plat_add_pcie_port(struct pcie_port *pp, | |||
63 | pp->msi_irq = platform_get_irq(pdev, 0); | 56 | pp->msi_irq = platform_get_irq(pdev, 0); |
64 | if (pp->msi_irq < 0) | 57 | if (pp->msi_irq < 0) |
65 | return pp->msi_irq; | 58 | return pp->msi_irq; |
66 | |||
67 | ret = devm_request_irq(dev, pp->msi_irq, | ||
68 | dw_plat_pcie_msi_irq_handler, | ||
69 | IRQF_SHARED | IRQF_NO_THREAD, | ||
70 | "dw-plat-pcie-msi", pp); | ||
71 | if (ret) { | ||
72 | dev_err(dev, "failed to request MSI IRQ\n"); | ||
73 | return ret; | ||
74 | } | ||
75 | } | 59 | } |
76 | 60 | ||
77 | pp->root_bus_nr = -1; | 61 | pp->root_bus_nr = -1; |
diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index 11b13864a406..fe811dbc12cf 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h | |||
@@ -107,13 +107,10 @@ | |||
107 | #define MSI_MESSAGE_DATA_32 0x58 | 107 | #define MSI_MESSAGE_DATA_32 0x58 |
108 | #define MSI_MESSAGE_DATA_64 0x5C | 108 | #define MSI_MESSAGE_DATA_64 0x5C |
109 | 109 | ||
110 | /* | 110 | #define MAX_MSI_IRQS 256 |
111 | * Maximum number of MSI IRQs can be 256 per controller. But keep | 111 | #define MAX_MSI_IRQS_PER_CTRL 32 |
112 | * it 32 as of now. Probably we will never need more than 32. If needed, | 112 | #define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL) |
113 | * then increment it in multiple of 32. | 113 | #define MSI_DEF_NUM_VECTORS 32 |
114 | */ | ||
115 | #define MAX_MSI_IRQS 32 | ||
116 | #define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) | ||
117 | 114 | ||
118 | /* Maximum number of inbound/outbound iATUs */ | 115 | /* Maximum number of inbound/outbound iATUs */ |
119 | #define MAX_IATU_IN 256 | 116 | #define MAX_IATU_IN 256 |
@@ -149,7 +146,9 @@ struct dw_pcie_host_ops { | |||
149 | phys_addr_t (*get_msi_addr)(struct pcie_port *pp); | 146 | phys_addr_t (*get_msi_addr)(struct pcie_port *pp); |
150 | u32 (*get_msi_data)(struct pcie_port *pp, int pos); | 147 | u32 (*get_msi_data)(struct pcie_port *pp, int pos); |
151 | void (*scan_bus)(struct pcie_port *pp); | 148 | void (*scan_bus)(struct pcie_port *pp); |
152 | int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip); | 149 | void (*set_num_vectors)(struct pcie_port *pp); |
150 | int (*msi_host_init)(struct pcie_port *pp); | ||
151 | void (*msi_irq_ack)(int irq, struct pcie_port *pp); | ||
153 | }; | 152 | }; |
154 | 153 | ||
155 | struct pcie_port { | 154 | struct pcie_port { |
@@ -174,7 +173,11 @@ struct pcie_port { | |||
174 | const struct dw_pcie_host_ops *ops; | 173 | const struct dw_pcie_host_ops *ops; |
175 | int msi_irq; | 174 | int msi_irq; |
176 | struct irq_domain *irq_domain; | 175 | struct irq_domain *irq_domain; |
176 | struct irq_domain *msi_domain; | ||
177 | dma_addr_t msi_data; | 177 | dma_addr_t msi_data; |
178 | u32 num_vectors; | ||
179 | u32 irq_status[MAX_MSI_CTRLS]; | ||
180 | raw_spinlock_t lock; | ||
178 | DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); | 181 | DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); |
179 | }; | 182 | }; |
180 | 183 | ||
@@ -316,8 +319,10 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci) | |||
316 | #ifdef CONFIG_PCIE_DW_HOST | 319 | #ifdef CONFIG_PCIE_DW_HOST |
317 | irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); | 320 | irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); |
318 | void dw_pcie_msi_init(struct pcie_port *pp); | 321 | void dw_pcie_msi_init(struct pcie_port *pp); |
322 | void dw_pcie_free_msi(struct pcie_port *pp); | ||
319 | void dw_pcie_setup_rc(struct pcie_port *pp); | 323 | void dw_pcie_setup_rc(struct pcie_port *pp); |
320 | int dw_pcie_host_init(struct pcie_port *pp); | 324 | int dw_pcie_host_init(struct pcie_port *pp); |
325 | int dw_pcie_allocate_domains(struct pcie_port *pp); | ||
321 | #else | 326 | #else |
322 | static inline irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) | 327 | static inline irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) |
323 | { | 328 | { |
@@ -328,6 +333,10 @@ static inline void dw_pcie_msi_init(struct pcie_port *pp) | |||
328 | { | 333 | { |
329 | } | 334 | } |
330 | 335 | ||
336 | static inline void dw_pcie_free_msi(struct pcie_port *pp) | ||
337 | { | ||
338 | } | ||
339 | |||
331 | static inline void dw_pcie_setup_rc(struct pcie_port *pp) | 340 | static inline void dw_pcie_setup_rc(struct pcie_port *pp) |
332 | { | 341 | { |
333 | } | 342 | } |
@@ -336,6 +345,11 @@ static inline int dw_pcie_host_init(struct pcie_port *pp) | |||
336 | { | 345 | { |
337 | return 0; | 346 | return 0; |
338 | } | 347 | } |
348 | |||
349 | static inline int dw_pcie_allocate_domains(struct pcie_port *pp) | ||
350 | { | ||
351 | return 0; | ||
352 | } | ||
339 | #endif | 353 | #endif |
340 | 354 | ||
341 | #ifdef CONFIG_PCIE_DW_EP | 355 | #ifdef CONFIG_PCIE_DW_EP |
diff --git a/drivers/pci/dwc/pcie-histb.c b/drivers/pci/dwc/pcie-histb.c index 4cef0a514944..3611d6ce9a92 100644 --- a/drivers/pci/dwc/pcie-histb.c +++ b/drivers/pci/dwc/pcie-histb.c | |||
@@ -208,13 +208,6 @@ static struct dw_pcie_host_ops histb_pcie_host_ops = { | |||
208 | .host_init = histb_pcie_host_init, | 208 | .host_init = histb_pcie_host_init, |
209 | }; | 209 | }; |
210 | 210 | ||
211 | static irqreturn_t histb_pcie_msi_irq_handler(int irq, void *arg) | ||
212 | { | ||
213 | struct pcie_port *pp = arg; | ||
214 | |||
215 | return dw_handle_msi_irq(pp); | ||
216 | } | ||
217 | |||
218 | static void histb_pcie_host_disable(struct histb_pcie *hipcie) | 211 | static void histb_pcie_host_disable(struct histb_pcie *hipcie) |
219 | { | 212 | { |
220 | reset_control_assert(hipcie->soft_reset); | 213 | reset_control_assert(hipcie->soft_reset); |
@@ -413,14 +406,6 @@ static int histb_pcie_probe(struct platform_device *pdev) | |||
413 | dev_err(dev, "Failed to get MSI IRQ\n"); | 406 | dev_err(dev, "Failed to get MSI IRQ\n"); |
414 | return pp->msi_irq; | 407 | return pp->msi_irq; |
415 | } | 408 | } |
416 | |||
417 | ret = devm_request_irq(dev, pp->msi_irq, | ||
418 | histb_pcie_msi_irq_handler, | ||
419 | IRQF_SHARED, "histb-pcie-msi", pp); | ||
420 | if (ret) { | ||
421 | dev_err(dev, "cannot request MSI IRQ\n"); | ||
422 | return ret; | ||
423 | } | ||
424 | } | 409 | } |
425 | 410 | ||
426 | hipcie->phy = devm_phy_get(dev, "phy"); | 411 | hipcie->phy = devm_phy_get(dev, "phy"); |
diff --git a/drivers/pci/dwc/pcie-qcom.c b/drivers/pci/dwc/pcie-qcom.c index ed4e75472831..5897af7d3355 100644 --- a/drivers/pci/dwc/pcie-qcom.c +++ b/drivers/pci/dwc/pcie-qcom.c | |||
@@ -181,13 +181,6 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) | |||
181 | usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); | 181 | usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); |
182 | } | 182 | } |
183 | 183 | ||
184 | static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg) | ||
185 | { | ||
186 | struct pcie_port *pp = arg; | ||
187 | |||
188 | return dw_handle_msi_irq(pp); | ||
189 | } | ||
190 | |||
191 | static int qcom_pcie_establish_link(struct qcom_pcie *pcie) | 184 | static int qcom_pcie_establish_link(struct qcom_pcie *pcie) |
192 | { | 185 | { |
193 | struct dw_pcie *pci = pcie->pci; | 186 | struct dw_pcie *pci = pcie->pci; |
@@ -1261,15 +1254,6 @@ static int qcom_pcie_probe(struct platform_device *pdev) | |||
1261 | pp->msi_irq = platform_get_irq_byname(pdev, "msi"); | 1254 | pp->msi_irq = platform_get_irq_byname(pdev, "msi"); |
1262 | if (pp->msi_irq < 0) | 1255 | if (pp->msi_irq < 0) |
1263 | return pp->msi_irq; | 1256 | return pp->msi_irq; |
1264 | |||
1265 | ret = devm_request_irq(dev, pp->msi_irq, | ||
1266 | qcom_pcie_msi_irq_handler, | ||
1267 | IRQF_SHARED | IRQF_NO_THREAD, | ||
1268 | "qcom-pcie-msi", pp); | ||
1269 | if (ret) { | ||
1270 | dev_err(dev, "cannot request msi irq\n"); | ||
1271 | return ret; | ||
1272 | } | ||
1273 | } | 1257 | } |
1274 | 1258 | ||
1275 | ret = phy_init(pcie->phy); | 1259 | ret = phy_init(pcie->phy); |