diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 23:58:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 23:58:52 -0500 |
commit | c75059c46293adf1560162c17148ab94624f5ed2 (patch) | |
tree | 75847b97da3477ce5c7aa32d81d0861f992e61ce /drivers/pci | |
parent | f74ea36848ad49cb011aae55f56b0475702ffb79 (diff) | |
parent | 149792795d2bab33954bc025fcf145a8009683f6 (diff) |
Merge tag 'pci-v3.19-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI changes from Bjorn Helgaas:
"Here are the PCI changes intended for v3.19. I don't think there's
anything very exciting here, but there was a lot of MSI-related stuff
coming via Thomas.
Details:
NUMA
- Allow numa_node override via sysfs (Prarit Bhargava)
Resource management
- Restore detection of read-only BARs (Myron Stowe)
- Shrink decoding-disabled window while sizing BARs (Myron Stowe)
- Add informational printk for invalid BARs (Myron Stowe)
- Remove fixed parameter in pci_iov_resource_bar() (Myron Stowe)
MSI
- Add pci_msi_ignore_mask to prevent writes to MSI/MSI-X Mask Bits (Yijing Wang)
- Revert "PCI: Add x86_msi.msi_mask_irq() and msix_mask_irq()" (Yijing Wang)
- s390/MSI: Use __msi_mask_irq() instead of default_msi_mask_irq() (Yijing Wang)
Virtualization
- xen: Process failure for pcifront_(re)scan_root() (Chen Gang)
- Make FLR and AF FLR reset warning messages different (Gavin Shan)
Generic host bridge driver
- Allocate config space windows after limiting bus number range (Lorenzo Pieralisi)
- Convert to DT resource parsing API (Lorenzo Pieralisi)
Freescale Layerscape
- Add Freescale Layerscape PCIe driver (Minghuan Lian)
NVIDIA Tegra
- Do not build on 64-bit ARM (Thierry Reding)
- Add Kconfig help text (Thierry Reding)
Renesas R-Car
- Make rcar_pci static (Jingoo Han)
Samsung Exynos
- Add exynos prefix to add_pcie_port(), pcie_init() (Jingoo Han)
ST Microelectronics SPEAr13xx
- Add spear prefix to add_pcie_port(), pcie_init() (Jingoo Han)
- Make spear13xx_add_pcie_port() __init (Jingoo Han)
- Remove unnecessary OOM message (Jingoo Han)
TI DRA7xx
- Add dra7xx prefix to add_pcie_port() (Jingoo Han)
- Make dra7xx_add_pcie_port() __init (Jingoo Han)
TI Keystone
- Make ks_dw_pcie_msi_domain_ops static (Jingoo Han)
- Remove unnecessary OOM message (Jingoo Han)
Miscellaneous
- Delete unnecessary NULL pointer checks (Markus Elfring)
- Remove unused to_hotplug_slot() (Gavin Shan)
- Whitespace cleanup (Jingoo Han)
- Simplify if-return sequences (Quentin Lambert)"
* tag 'pci-v3.19-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (28 commits)
PCI: Remove fixed parameter in pci_iov_resource_bar()
PCI: Add informational printk for invalid BARs
PCI: tegra: Add Kconfig help text
PCI: tegra: Do not build on 64-bit ARM
PCI: spear: Remove unnecessary OOM message
PCI: mvebu: Add a blank line after declarations
PCI: designware: Add a blank line after declarations
PCI: exynos: Remove unnecessary return statement
PCI: imx6: Use tabs for indentation
PCI: keystone: Remove unnecessary OOM message
PCI: Remove unused and broken to_hotplug_slot()
PCI: Make FLR and AF FLR reset warning messages different
PCI: dra7xx: Add __init annotation to dra7xx_add_pcie_port()
PCI: spear: Add __init annotation to spear13xx_add_pcie_port()
PCI: spear: Rename add_pcie_port(), pcie_init() to spear13xx_add_pcie_port(), etc.
PCI: dra7xx: Rename add_pcie_port() to dra7xx_add_pcie_port()
PCI: layerscape: Add Freescale Layerscape PCIe driver
PCI: Simplify if-return sequences
PCI: Delete unnecessary NULL pointer checks
PCI: Shrink decoding-disabled window while sizing BARs
...
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/Kconfig | 13 | ||||
-rw-r--r-- | drivers/pci/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/host/pci-dra7xx.c | 6 | ||||
-rw-r--r-- | drivers/pci/host/pci-exynos.c | 18 | ||||
-rw-r--r-- | drivers/pci/host/pci-host-generic.c | 126 | ||||
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 4 | ||||
-rw-r--r-- | drivers/pci/host/pci-keystone-dw.c | 2 | ||||
-rw-r--r-- | drivers/pci/host/pci-keystone.c | 5 | ||||
-rw-r--r-- | drivers/pci/host/pci-layerscape.c | 179 | ||||
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 2 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-rcar.c | 2 | ||||
-rw-r--r-- | drivers/pci/host/pcie-spear13xx.c | 13 | ||||
-rw-r--r-- | drivers/pci/hotplug/ibmphp_res.c | 5 | ||||
-rw-r--r-- | drivers/pci/iov.c | 11 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 3 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 27 | ||||
-rw-r--r-- | drivers/pci/pci.c | 21 | ||||
-rw-r--r-- | drivers/pci/pci.h | 6 | ||||
-rw-r--r-- | drivers/pci/probe.c | 80 | ||||
-rw-r--r-- | drivers/pci/search.c | 3 | ||||
-rw-r--r-- | drivers/pci/xen-pcifront.c | 13 |
22 files changed, 331 insertions, 210 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 3dc25fad490c..c4b6568e486d 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
@@ -32,7 +32,10 @@ config PCI_IMX6 | |||
32 | 32 | ||
33 | config PCI_TEGRA | 33 | config PCI_TEGRA |
34 | bool "NVIDIA Tegra PCIe controller" | 34 | bool "NVIDIA Tegra PCIe controller" |
35 | depends on ARCH_TEGRA | 35 | depends on ARCH_TEGRA && !ARM64 |
36 | help | ||
37 | Say Y here if you want support for the PCIe host controller found | ||
38 | on NVIDIA Tegra SoCs. | ||
36 | 39 | ||
37 | config PCI_RCAR_GEN2 | 40 | config PCI_RCAR_GEN2 |
38 | bool "Renesas R-Car Gen2 Internal PCI controller" | 41 | bool "Renesas R-Car Gen2 Internal PCI controller" |
@@ -91,4 +94,12 @@ config PCI_XGENE | |||
91 | There are 5 internal PCIe ports available. Each port is GEN3 capable | 94 | There are 5 internal PCIe ports available. Each port is GEN3 capable |
92 | and have varied lanes from x1 to x8. | 95 | and have varied lanes from x1 to x8. |
93 | 96 | ||
97 | config PCI_LAYERSCAPE | ||
98 | bool "Freescale Layerscape PCIe controller" | ||
99 | depends on OF && ARM | ||
100 | select PCIE_DW | ||
101 | select MFD_SYSCON | ||
102 | help | ||
103 | Say Y here if you want PCIe controller support on Layerscape SoCs. | ||
104 | |||
94 | endmenu | 105 | endmenu |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 26b3461d68d7..44c26998027f 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
@@ -11,3 +11,4 @@ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o | |||
11 | obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o | 11 | obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o |
12 | obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o | 12 | obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o |
13 | obj-$(CONFIG_PCI_XGENE) += pci-xgene.o | 13 | obj-$(CONFIG_PCI_XGENE) += pci-xgene.o |
14 | obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o | ||
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 52b34fee07fd..8c6969747acd 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c | |||
@@ -270,8 +270,8 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg) | |||
270 | return IRQ_HANDLED; | 270 | return IRQ_HANDLED; |
271 | } | 271 | } |
272 | 272 | ||
273 | static int add_pcie_port(struct dra7xx_pcie *dra7xx, | 273 | static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, |
274 | struct platform_device *pdev) | 274 | struct platform_device *pdev) |
275 | { | 275 | { |
276 | int ret; | 276 | int ret; |
277 | struct pcie_port *pp; | 277 | struct pcie_port *pp; |
@@ -398,7 +398,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
398 | 398 | ||
399 | platform_set_drvdata(pdev, dra7xx); | 399 | platform_set_drvdata(pdev, dra7xx); |
400 | 400 | ||
401 | ret = add_pcie_port(dra7xx, pdev); | 401 | ret = dra7xx_add_pcie_port(dra7xx, pdev); |
402 | if (ret < 0) | 402 | if (ret < 0) |
403 | goto err_add_port; | 403 | goto err_add_port; |
404 | 404 | ||
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index c5d0ca384502..850c9f951a3f 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -312,7 +312,6 @@ static void exynos_pcie_assert_reset(struct pcie_port *pp) | |||
312 | if (exynos_pcie->reset_gpio >= 0) | 312 | if (exynos_pcie->reset_gpio >= 0) |
313 | devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio, | 313 | devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio, |
314 | GPIOF_OUT_INIT_HIGH, "RESET"); | 314 | GPIOF_OUT_INIT_HIGH, "RESET"); |
315 | return; | ||
316 | } | 315 | } |
317 | 316 | ||
318 | static int exynos_pcie_establish_link(struct pcie_port *pp) | 317 | static int exynos_pcie_establish_link(struct pcie_port *pp) |
@@ -388,7 +387,6 @@ static void exynos_pcie_clear_irq_pulse(struct pcie_port *pp) | |||
388 | 387 | ||
389 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE); | 388 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE); |
390 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE); | 389 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE); |
391 | return; | ||
392 | } | 390 | } |
393 | 391 | ||
394 | static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) | 392 | static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) |
@@ -400,7 +398,6 @@ static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) | |||
400 | val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | | 398 | val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | |
401 | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT, | 399 | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT, |
402 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE); | 400 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE); |
403 | return; | ||
404 | } | 401 | } |
405 | 402 | ||
406 | static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) | 403 | static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) |
@@ -429,7 +426,6 @@ static void exynos_pcie_msi_init(struct pcie_port *pp) | |||
429 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); | 426 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); |
430 | val |= IRQ_MSI_ENABLE; | 427 | val |= IRQ_MSI_ENABLE; |
431 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); | 428 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); |
432 | return; | ||
433 | } | 429 | } |
434 | 430 | ||
435 | static void exynos_pcie_enable_interrupts(struct pcie_port *pp) | 431 | static void exynos_pcie_enable_interrupts(struct pcie_port *pp) |
@@ -438,8 +434,6 @@ static void exynos_pcie_enable_interrupts(struct pcie_port *pp) | |||
438 | 434 | ||
439 | if (IS_ENABLED(CONFIG_PCI_MSI)) | 435 | if (IS_ENABLED(CONFIG_PCI_MSI)) |
440 | exynos_pcie_msi_init(pp); | 436 | exynos_pcie_msi_init(pp); |
441 | |||
442 | return; | ||
443 | } | 437 | } |
444 | 438 | ||
445 | static inline void exynos_pcie_readl_rc(struct pcie_port *pp, | 439 | static inline void exynos_pcie_readl_rc(struct pcie_port *pp, |
@@ -448,7 +442,6 @@ static inline void exynos_pcie_readl_rc(struct pcie_port *pp, | |||
448 | exynos_pcie_sideband_dbi_r_mode(pp, true); | 442 | exynos_pcie_sideband_dbi_r_mode(pp, true); |
449 | *val = readl(dbi_base); | 443 | *val = readl(dbi_base); |
450 | exynos_pcie_sideband_dbi_r_mode(pp, false); | 444 | exynos_pcie_sideband_dbi_r_mode(pp, false); |
451 | return; | ||
452 | } | 445 | } |
453 | 446 | ||
454 | static inline void exynos_pcie_writel_rc(struct pcie_port *pp, | 447 | static inline void exynos_pcie_writel_rc(struct pcie_port *pp, |
@@ -457,7 +450,6 @@ static inline void exynos_pcie_writel_rc(struct pcie_port *pp, | |||
457 | exynos_pcie_sideband_dbi_w_mode(pp, true); | 450 | exynos_pcie_sideband_dbi_w_mode(pp, true); |
458 | writel(val, dbi_base); | 451 | writel(val, dbi_base); |
459 | exynos_pcie_sideband_dbi_w_mode(pp, false); | 452 | exynos_pcie_sideband_dbi_w_mode(pp, false); |
460 | return; | ||
461 | } | 453 | } |
462 | 454 | ||
463 | static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | 455 | static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, |
@@ -509,8 +501,8 @@ static struct pcie_host_ops exynos_pcie_host_ops = { | |||
509 | .host_init = exynos_pcie_host_init, | 501 | .host_init = exynos_pcie_host_init, |
510 | }; | 502 | }; |
511 | 503 | ||
512 | static int __init add_pcie_port(struct pcie_port *pp, | 504 | static int __init exynos_add_pcie_port(struct pcie_port *pp, |
513 | struct platform_device *pdev) | 505 | struct platform_device *pdev) |
514 | { | 506 | { |
515 | int ret; | 507 | int ret; |
516 | 508 | ||
@@ -615,7 +607,7 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
615 | goto fail_bus_clk; | 607 | goto fail_bus_clk; |
616 | } | 608 | } |
617 | 609 | ||
618 | ret = add_pcie_port(pp, pdev); | 610 | ret = exynos_add_pcie_port(pp, pdev); |
619 | if (ret < 0) | 611 | if (ret < 0) |
620 | goto fail_bus_clk; | 612 | goto fail_bus_clk; |
621 | 613 | ||
@@ -656,11 +648,11 @@ static struct platform_driver exynos_pcie_driver = { | |||
656 | 648 | ||
657 | /* Exynos PCIe driver does not allow module unload */ | 649 | /* Exynos PCIe driver does not allow module unload */ |
658 | 650 | ||
659 | static int __init pcie_init(void) | 651 | static int __init exynos_pcie_init(void) |
660 | { | 652 | { |
661 | return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); | 653 | return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); |
662 | } | 654 | } |
663 | subsys_initcall(pcie_init); | 655 | subsys_initcall(exynos_pcie_init); |
664 | 656 | ||
665 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | 657 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); |
666 | MODULE_DESCRIPTION("Samsung PCIe host controller driver"); | 658 | MODULE_DESCRIPTION("Samsung PCIe host controller driver"); |
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c index 3d2076f59911..18959075d164 100644 --- a/drivers/pci/host/pci-host-generic.c +++ b/drivers/pci/host/pci-host-generic.c | |||
@@ -32,7 +32,7 @@ struct gen_pci_cfg_bus_ops { | |||
32 | 32 | ||
33 | struct gen_pci_cfg_windows { | 33 | struct gen_pci_cfg_windows { |
34 | struct resource res; | 34 | struct resource res; |
35 | struct resource bus_range; | 35 | struct resource *bus_range; |
36 | void __iomem **win; | 36 | void __iomem **win; |
37 | 37 | ||
38 | const struct gen_pci_cfg_bus_ops *ops; | 38 | const struct gen_pci_cfg_bus_ops *ops; |
@@ -50,7 +50,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus, | |||
50 | { | 50 | { |
51 | struct pci_sys_data *sys = bus->sysdata; | 51 | struct pci_sys_data *sys = bus->sysdata; |
52 | struct gen_pci *pci = sys->private_data; | 52 | struct gen_pci *pci = sys->private_data; |
53 | resource_size_t idx = bus->number - pci->cfg.bus_range.start; | 53 | resource_size_t idx = bus->number - pci->cfg.bus_range->start; |
54 | 54 | ||
55 | return pci->cfg.win[idx] + ((devfn << 8) | where); | 55 | return pci->cfg.win[idx] + ((devfn << 8) | where); |
56 | } | 56 | } |
@@ -66,7 +66,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, | |||
66 | { | 66 | { |
67 | struct pci_sys_data *sys = bus->sysdata; | 67 | struct pci_sys_data *sys = bus->sysdata; |
68 | struct gen_pci *pci = sys->private_data; | 68 | struct gen_pci *pci = sys->private_data; |
69 | resource_size_t idx = bus->number - pci->cfg.bus_range.start; | 69 | resource_size_t idx = bus->number - pci->cfg.bus_range->start; |
70 | 70 | ||
71 | return pci->cfg.win[idx] + ((devfn << 12) | where); | 71 | return pci->cfg.win[idx] + ((devfn << 12) | where); |
72 | } | 72 | } |
@@ -138,106 +138,50 @@ static const struct of_device_id gen_pci_of_match[] = { | |||
138 | }; | 138 | }; |
139 | MODULE_DEVICE_TABLE(of, gen_pci_of_match); | 139 | MODULE_DEVICE_TABLE(of, gen_pci_of_match); |
140 | 140 | ||
141 | static int gen_pci_calc_io_offset(struct device *dev, | ||
142 | struct of_pci_range *range, | ||
143 | struct resource *res, | ||
144 | resource_size_t *offset) | ||
145 | { | ||
146 | static atomic_t wins = ATOMIC_INIT(0); | ||
147 | int err, idx, max_win; | ||
148 | unsigned int window; | ||
149 | |||
150 | if (!PAGE_ALIGNED(range->cpu_addr)) | ||
151 | return -EINVAL; | ||
152 | |||
153 | max_win = (IO_SPACE_LIMIT + 1) / SZ_64K; | ||
154 | idx = atomic_inc_return(&wins); | ||
155 | if (idx > max_win) | ||
156 | return -ENOSPC; | ||
157 | |||
158 | window = (idx - 1) * SZ_64K; | ||
159 | err = pci_ioremap_io(window, range->cpu_addr); | ||
160 | if (err) | ||
161 | return err; | ||
162 | |||
163 | of_pci_range_to_resource(range, dev->of_node, res); | ||
164 | res->start = window; | ||
165 | res->end = res->start + range->size - 1; | ||
166 | *offset = window - range->pci_addr; | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int gen_pci_calc_mem_offset(struct device *dev, | ||
171 | struct of_pci_range *range, | ||
172 | struct resource *res, | ||
173 | resource_size_t *offset) | ||
174 | { | ||
175 | of_pci_range_to_resource(range, dev->of_node, res); | ||
176 | *offset = range->cpu_addr - range->pci_addr; | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) | 141 | static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) |
181 | { | 142 | { |
182 | struct pci_host_bridge_window *win; | ||
183 | |||
184 | list_for_each_entry(win, &pci->resources, list) | ||
185 | release_resource(win->res); | ||
186 | |||
187 | pci_free_resource_list(&pci->resources); | 143 | pci_free_resource_list(&pci->resources); |
188 | } | 144 | } |
189 | 145 | ||
190 | static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) | 146 | static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) |
191 | { | 147 | { |
192 | struct of_pci_range range; | ||
193 | struct of_pci_range_parser parser; | ||
194 | int err, res_valid = 0; | 148 | int err, res_valid = 0; |
195 | struct device *dev = pci->host.dev.parent; | 149 | struct device *dev = pci->host.dev.parent; |
196 | struct device_node *np = dev->of_node; | 150 | struct device_node *np = dev->of_node; |
151 | resource_size_t iobase; | ||
152 | struct pci_host_bridge_window *win; | ||
197 | 153 | ||
198 | if (of_pci_range_parser_init(&parser, np)) { | 154 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, |
199 | dev_err(dev, "missing \"ranges\" property\n"); | 155 | &iobase); |
200 | return -EINVAL; | 156 | if (err) |
201 | } | 157 | return err; |
202 | |||
203 | for_each_of_pci_range(&parser, &range) { | ||
204 | struct resource *parent, *res; | ||
205 | resource_size_t offset; | ||
206 | u32 restype = range.flags & IORESOURCE_TYPE_BITS; | ||
207 | 158 | ||
208 | res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL); | 159 | list_for_each_entry(win, &pci->resources, list) { |
209 | if (!res) { | 160 | struct resource *parent, *res = win->res; |
210 | err = -ENOMEM; | ||
211 | goto out_release_res; | ||
212 | } | ||
213 | 161 | ||
214 | switch (restype) { | 162 | switch (resource_type(res)) { |
215 | case IORESOURCE_IO: | 163 | case IORESOURCE_IO: |
216 | parent = &ioport_resource; | 164 | parent = &ioport_resource; |
217 | err = gen_pci_calc_io_offset(dev, &range, res, &offset); | 165 | err = pci_remap_iospace(res, iobase); |
166 | if (err) { | ||
167 | dev_warn(dev, "error %d: failed to map resource %pR\n", | ||
168 | err, res); | ||
169 | continue; | ||
170 | } | ||
218 | break; | 171 | break; |
219 | case IORESOURCE_MEM: | 172 | case IORESOURCE_MEM: |
220 | parent = &iomem_resource; | 173 | parent = &iomem_resource; |
221 | err = gen_pci_calc_mem_offset(dev, &range, res, &offset); | 174 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); |
222 | res_valid |= !(res->flags & IORESOURCE_PREFETCH || err); | ||
223 | break; | 175 | break; |
176 | case IORESOURCE_BUS: | ||
177 | pci->cfg.bus_range = res; | ||
224 | default: | 178 | default: |
225 | err = -EINVAL; | ||
226 | continue; | ||
227 | } | ||
228 | |||
229 | if (err) { | ||
230 | dev_warn(dev, | ||
231 | "error %d: failed to add resource [type 0x%x, %lld bytes]\n", | ||
232 | err, restype, range.size); | ||
233 | continue; | 179 | continue; |
234 | } | 180 | } |
235 | 181 | ||
236 | err = request_resource(parent, res); | 182 | err = devm_request_resource(dev, parent, res); |
237 | if (err) | 183 | if (err) |
238 | goto out_release_res; | 184 | goto out_release_res; |
239 | |||
240 | pci_add_resource_offset(&pci->resources, res, offset); | ||
241 | } | 185 | } |
242 | 186 | ||
243 | if (!res_valid) { | 187 | if (!res_valid) { |
@@ -262,38 +206,30 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) | |||
262 | struct device *dev = pci->host.dev.parent; | 206 | struct device *dev = pci->host.dev.parent; |
263 | struct device_node *np = dev->of_node; | 207 | struct device_node *np = dev->of_node; |
264 | 208 | ||
265 | if (of_pci_parse_bus_range(np, &pci->cfg.bus_range)) | ||
266 | pci->cfg.bus_range = (struct resource) { | ||
267 | .name = np->name, | ||
268 | .start = 0, | ||
269 | .end = 0xff, | ||
270 | .flags = IORESOURCE_BUS, | ||
271 | }; | ||
272 | |||
273 | err = of_address_to_resource(np, 0, &pci->cfg.res); | 209 | err = of_address_to_resource(np, 0, &pci->cfg.res); |
274 | if (err) { | 210 | if (err) { |
275 | dev_err(dev, "missing \"reg\" property\n"); | 211 | dev_err(dev, "missing \"reg\" property\n"); |
276 | return err; | 212 | return err; |
277 | } | 213 | } |
278 | 214 | ||
279 | pci->cfg.win = devm_kcalloc(dev, resource_size(&pci->cfg.bus_range), | 215 | /* Limit the bus-range to fit within reg */ |
216 | bus_max = pci->cfg.bus_range->start + | ||
217 | (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1; | ||
218 | pci->cfg.bus_range->end = min_t(resource_size_t, | ||
219 | pci->cfg.bus_range->end, bus_max); | ||
220 | |||
221 | pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range), | ||
280 | sizeof(*pci->cfg.win), GFP_KERNEL); | 222 | sizeof(*pci->cfg.win), GFP_KERNEL); |
281 | if (!pci->cfg.win) | 223 | if (!pci->cfg.win) |
282 | return -ENOMEM; | 224 | return -ENOMEM; |
283 | 225 | ||
284 | /* Limit the bus-range to fit within reg */ | ||
285 | bus_max = pci->cfg.bus_range.start + | ||
286 | (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1; | ||
287 | pci->cfg.bus_range.end = min_t(resource_size_t, pci->cfg.bus_range.end, | ||
288 | bus_max); | ||
289 | |||
290 | /* Map our Configuration Space windows */ | 226 | /* Map our Configuration Space windows */ |
291 | if (!devm_request_mem_region(dev, pci->cfg.res.start, | 227 | if (!devm_request_mem_region(dev, pci->cfg.res.start, |
292 | resource_size(&pci->cfg.res), | 228 | resource_size(&pci->cfg.res), |
293 | "Configuration Space")) | 229 | "Configuration Space")) |
294 | return -ENOMEM; | 230 | return -ENOMEM; |
295 | 231 | ||
296 | bus_range = &pci->cfg.bus_range; | 232 | bus_range = pci->cfg.bus_range; |
297 | for (busn = bus_range->start; busn <= bus_range->end; ++busn) { | 233 | for (busn = bus_range->start; busn <= bus_range->end; ++busn) { |
298 | u32 idx = busn - bus_range->start; | 234 | u32 idx = busn - bus_range->start; |
299 | u32 sz = 1 << pci->cfg.ops->bus_shift; | 235 | u32 sz = 1 << pci->cfg.ops->bus_shift; |
@@ -305,8 +241,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) | |||
305 | return -ENOMEM; | 241 | return -ENOMEM; |
306 | } | 242 | } |
307 | 243 | ||
308 | /* Register bus resource */ | ||
309 | pci_add_resource(&pci->resources, bus_range); | ||
310 | return 0; | 244 | return 0; |
311 | } | 245 | } |
312 | 246 | ||
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 69202d1eb8fb..d1a26d17b586 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -533,8 +533,8 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp, | |||
533 | } | 533 | } |
534 | 534 | ||
535 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, | 535 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, |
536 | imx6_pcie_msi_handler, | 536 | imx6_pcie_msi_handler, |
537 | IRQF_SHARED, "mx6-pcie-msi", pp); | 537 | IRQF_SHARED, "mx6-pcie-msi", pp); |
538 | if (ret) { | 538 | if (ret) { |
539 | dev_err(&pdev->dev, "failed to request MSI irq\n"); | 539 | dev_err(&pdev->dev, "failed to request MSI irq\n"); |
540 | return -ENODEV; | 540 | return -ENODEV; |
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c index 313338db0e43..66d8ea41b972 100644 --- a/drivers/pci/host/pci-keystone-dw.c +++ b/drivers/pci/host/pci-keystone-dw.c | |||
@@ -201,7 +201,7 @@ static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, | |||
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = { | 204 | static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = { |
205 | .map = ks_dw_pcie_msi_map, | 205 | .map = ks_dw_pcie_msi_map, |
206 | }; | 206 | }; |
207 | 207 | ||
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c index 1b893bc8b842..62b9454c86fb 100644 --- a/drivers/pci/host/pci-keystone.c +++ b/drivers/pci/host/pci-keystone.c | |||
@@ -353,10 +353,9 @@ static int __init ks_pcie_probe(struct platform_device *pdev) | |||
353 | 353 | ||
354 | ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie), | 354 | ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie), |
355 | GFP_KERNEL); | 355 | GFP_KERNEL); |
356 | if (!ks_pcie) { | 356 | if (!ks_pcie) |
357 | dev_err(dev, "no memory for keystone pcie\n"); | ||
358 | return -ENOMEM; | 357 | return -ENOMEM; |
359 | } | 358 | |
360 | pp = &ks_pcie->pp; | 359 | pp = &ks_pcie->pp; |
361 | 360 | ||
362 | /* initialize SerDes Phy if present */ | 361 | /* initialize SerDes Phy if present */ |
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c new file mode 100644 index 000000000000..6697b1a4d4fa --- /dev/null +++ b/drivers/pci/host/pci-layerscape.c | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * PCIe host controller driver for Freescale Layerscape SoCs | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor. | ||
5 | * | ||
6 | * Author: Minghuan Lian <Minghuan.Lian@freescale.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/of_pci.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/of_irq.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/resource.h> | ||
24 | #include <linux/mfd/syscon.h> | ||
25 | #include <linux/regmap.h> | ||
26 | |||
27 | #include "pcie-designware.h" | ||
28 | |||
29 | /* PEX1/2 Misc Ports Status Register */ | ||
30 | #define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) | ||
31 | #define LTSSM_STATE_SHIFT 20 | ||
32 | #define LTSSM_STATE_MASK 0x3f | ||
33 | #define LTSSM_PCIE_L0 0x11 /* L0 state */ | ||
34 | |||
35 | /* Symbol Timer Register and Filter Mask Register 1 */ | ||
36 | #define PCIE_STRFMR1 0x71c | ||
37 | |||
38 | struct ls_pcie { | ||
39 | struct list_head node; | ||
40 | struct device *dev; | ||
41 | struct pci_bus *bus; | ||
42 | void __iomem *dbi; | ||
43 | struct regmap *scfg; | ||
44 | struct pcie_port pp; | ||
45 | int index; | ||
46 | int msi_irq; | ||
47 | }; | ||
48 | |||
49 | #define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) | ||
50 | |||
51 | static int ls_pcie_link_up(struct pcie_port *pp) | ||
52 | { | ||
53 | u32 state; | ||
54 | struct ls_pcie *pcie = to_ls_pcie(pp); | ||
55 | |||
56 | regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state); | ||
57 | state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; | ||
58 | |||
59 | if (state < LTSSM_PCIE_L0) | ||
60 | return 0; | ||
61 | |||
62 | return 1; | ||
63 | } | ||
64 | |||
65 | static void ls_pcie_host_init(struct pcie_port *pp) | ||
66 | { | ||
67 | struct ls_pcie *pcie = to_ls_pcie(pp); | ||
68 | int count = 0; | ||
69 | u32 val; | ||
70 | |||
71 | dw_pcie_setup_rc(pp); | ||
72 | |||
73 | while (!ls_pcie_link_up(pp)) { | ||
74 | usleep_range(100, 1000); | ||
75 | count++; | ||
76 | if (count >= 200) { | ||
77 | dev_err(pp->dev, "phy link never came up\n"); | ||
78 | return; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * LS1021A Workaround for internal TKT228622 | ||
84 | * to fix the INTx hang issue | ||
85 | */ | ||
86 | val = ioread32(pcie->dbi + PCIE_STRFMR1); | ||
87 | val &= 0xffff; | ||
88 | iowrite32(val, pcie->dbi + PCIE_STRFMR1); | ||
89 | } | ||
90 | |||
91 | static struct pcie_host_ops ls_pcie_host_ops = { | ||
92 | .link_up = ls_pcie_link_up, | ||
93 | .host_init = ls_pcie_host_init, | ||
94 | }; | ||
95 | |||
96 | static int ls_add_pcie_port(struct ls_pcie *pcie) | ||
97 | { | ||
98 | struct pcie_port *pp; | ||
99 | int ret; | ||
100 | |||
101 | pp = &pcie->pp; | ||
102 | pp->dev = pcie->dev; | ||
103 | pp->dbi_base = pcie->dbi; | ||
104 | pp->root_bus_nr = -1; | ||
105 | pp->ops = &ls_pcie_host_ops; | ||
106 | |||
107 | ret = dw_pcie_host_init(pp); | ||
108 | if (ret) { | ||
109 | dev_err(pp->dev, "failed to initialize host\n"); | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int __init ls_pcie_probe(struct platform_device *pdev) | ||
117 | { | ||
118 | struct ls_pcie *pcie; | ||
119 | struct resource *dbi_base; | ||
120 | u32 index[2]; | ||
121 | int ret; | ||
122 | |||
123 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); | ||
124 | if (!pcie) | ||
125 | return -ENOMEM; | ||
126 | |||
127 | pcie->dev = &pdev->dev; | ||
128 | |||
129 | dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); | ||
130 | if (!dbi_base) { | ||
131 | dev_err(&pdev->dev, "missing *regs* space\n"); | ||
132 | return -ENODEV; | ||
133 | } | ||
134 | |||
135 | pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base); | ||
136 | if (IS_ERR(pcie->dbi)) | ||
137 | return PTR_ERR(pcie->dbi); | ||
138 | |||
139 | pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | ||
140 | "fsl,pcie-scfg"); | ||
141 | if (IS_ERR(pcie->scfg)) { | ||
142 | dev_err(&pdev->dev, "No syscfg phandle specified\n"); | ||
143 | return PTR_ERR(pcie->scfg); | ||
144 | } | ||
145 | |||
146 | ret = of_property_read_u32_array(pdev->dev.of_node, | ||
147 | "fsl,pcie-scfg", index, 2); | ||
148 | if (ret) | ||
149 | return ret; | ||
150 | pcie->index = index[1]; | ||
151 | |||
152 | ret = ls_add_pcie_port(pcie); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | platform_set_drvdata(pdev, pcie); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static const struct of_device_id ls_pcie_of_match[] = { | ||
162 | { .compatible = "fsl,ls1021a-pcie" }, | ||
163 | { }, | ||
164 | }; | ||
165 | MODULE_DEVICE_TABLE(of, ls_pcie_of_match); | ||
166 | |||
167 | static struct platform_driver ls_pcie_driver = { | ||
168 | .driver = { | ||
169 | .name = "layerscape-pcie", | ||
170 | .owner = THIS_MODULE, | ||
171 | .of_match_table = ls_pcie_of_match, | ||
172 | }, | ||
173 | }; | ||
174 | |||
175 | module_platform_driver_probe(ls_pcie_driver, ls_pcie_probe); | ||
176 | |||
177 | MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@freescale.com>"); | ||
178 | MODULE_DESCRIPTION("Freescale Layerscape PCIe host controller driver"); | ||
179 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 9aa810b733a8..fed3fab132f2 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -622,6 +622,7 @@ static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie, | |||
622 | 622 | ||
623 | for (i = 0; i < pcie->nports; i++) { | 623 | for (i = 0; i < pcie->nports; i++) { |
624 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 624 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
625 | |||
625 | if (bus->number == 0 && port->devfn == devfn) | 626 | if (bus->number == 0 && port->devfn == devfn) |
626 | return port; | 627 | return port; |
627 | if (bus->number != 0 && | 628 | if (bus->number != 0 && |
@@ -751,6 +752,7 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | |||
751 | 752 | ||
752 | for (i = 0; i < pcie->nports; i++) { | 753 | for (i = 0; i < pcie->nports; i++) { |
753 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 754 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
755 | |||
754 | if (!port->base) | 756 | if (!port->base) |
755 | continue; | 757 | continue; |
756 | mvebu_pcie_setup_hw(port); | 758 | mvebu_pcie_setup_hw(port); |
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 17b51550f9b5..df781cdf13c1 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -380,6 +380,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp) | |||
380 | /* Get the I/O and memory ranges from DT */ | 380 | /* Get the I/O and memory ranges from DT */ |
381 | for_each_of_pci_range(&parser, &range) { | 381 | for_each_of_pci_range(&parser, &range) { |
382 | unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; | 382 | unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; |
383 | |||
383 | if (restype == IORESOURCE_IO) { | 384 | if (restype == IORESOURCE_IO) { |
384 | of_pci_range_to_resource(&range, np, &pp->io); | 385 | of_pci_range_to_resource(&range, np, &pp->io); |
385 | pp->io.name = "I/O"; | 386 | pp->io.name = "I/O"; |
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index d3053e53cf35..5519e939e412 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c | |||
@@ -380,7 +380,7 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys) | |||
380 | return 1; | 380 | return 1; |
381 | } | 381 | } |
382 | 382 | ||
383 | struct hw_pci rcar_pci = { | 383 | static struct hw_pci rcar_pci = { |
384 | .setup = rcar_pcie_setup, | 384 | .setup = rcar_pcie_setup, |
385 | .map_irq = of_irq_parse_and_map_pci, | 385 | .map_irq = of_irq_parse_and_map_pci, |
386 | .ops = &rcar_pcie_ops, | 386 | .ops = &rcar_pcie_ops, |
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c index 85f594e1708f..2ca10cc887ee 100644 --- a/drivers/pci/host/pcie-spear13xx.c +++ b/drivers/pci/host/pcie-spear13xx.c | |||
@@ -269,7 +269,8 @@ static struct pcie_host_ops spear13xx_pcie_host_ops = { | |||
269 | .host_init = spear13xx_pcie_host_init, | 269 | .host_init = spear13xx_pcie_host_init, |
270 | }; | 270 | }; |
271 | 271 | ||
272 | static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev) | 272 | static int __init spear13xx_add_pcie_port(struct pcie_port *pp, |
273 | struct platform_device *pdev) | ||
273 | { | 274 | { |
274 | struct device *dev = &pdev->dev; | 275 | struct device *dev = &pdev->dev; |
275 | int ret; | 276 | int ret; |
@@ -308,10 +309,8 @@ static int __init spear13xx_pcie_probe(struct platform_device *pdev) | |||
308 | int ret; | 309 | int ret; |
309 | 310 | ||
310 | spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL); | 311 | spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL); |
311 | if (!spear13xx_pcie) { | 312 | if (!spear13xx_pcie) |
312 | dev_err(dev, "no memory for SPEAr13xx pcie\n"); | ||
313 | return -ENOMEM; | 313 | return -ENOMEM; |
314 | } | ||
315 | 314 | ||
316 | spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy"); | 315 | spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy"); |
317 | if (IS_ERR(spear13xx_pcie->phy)) { | 316 | if (IS_ERR(spear13xx_pcie->phy)) { |
@@ -352,7 +351,7 @@ static int __init spear13xx_pcie_probe(struct platform_device *pdev) | |||
352 | if (of_property_read_bool(np, "st,pcie-is-gen1")) | 351 | if (of_property_read_bool(np, "st,pcie-is-gen1")) |
353 | spear13xx_pcie->is_gen1 = true; | 352 | spear13xx_pcie->is_gen1 = true; |
354 | 353 | ||
355 | ret = add_pcie_port(pp, pdev); | 354 | ret = spear13xx_add_pcie_port(pp, pdev); |
356 | if (ret < 0) | 355 | if (ret < 0) |
357 | goto fail_clk; | 356 | goto fail_clk; |
358 | 357 | ||
@@ -382,11 +381,11 @@ static struct platform_driver spear13xx_pcie_driver __initdata = { | |||
382 | 381 | ||
383 | /* SPEAr13xx PCIe driver does not allow module unload */ | 382 | /* SPEAr13xx PCIe driver does not allow module unload */ |
384 | 383 | ||
385 | static int __init pcie_init(void) | 384 | static int __init spear13xx_pcie_init(void) |
386 | { | 385 | { |
387 | return platform_driver_register(&spear13xx_pcie_driver); | 386 | return platform_driver_register(&spear13xx_pcie_driver); |
388 | } | 387 | } |
389 | module_init(pcie_init); | 388 | module_init(spear13xx_pcie_init); |
390 | 389 | ||
391 | MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver"); | 390 | MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver"); |
392 | MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>"); | 391 | MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>"); |
diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index 219ba8090a37..f279060cf6e2 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c | |||
@@ -376,10 +376,7 @@ int __init ibmphp_rsrc_init (void) | |||
376 | if (rc) | 376 | if (rc) |
377 | return rc; | 377 | return rc; |
378 | } | 378 | } |
379 | rc = once_over (); /* This is to align ranges (so no -1) */ | 379 | return once_over (); /* This is to align ranges (so no -1) */ |
380 | if (rc) | ||
381 | return rc; | ||
382 | return 0; | ||
383 | } | 380 | } |
384 | 381 | ||
385 | /******************************************************************************** | 382 | /******************************************************************************** |
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 4d109c07294a..4b3a4eaad996 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
@@ -479,20 +479,16 @@ void pci_iov_release(struct pci_dev *dev) | |||
479 | * pci_iov_resource_bar - get position of the SR-IOV BAR | 479 | * pci_iov_resource_bar - get position of the SR-IOV BAR |
480 | * @dev: the PCI device | 480 | * @dev: the PCI device |
481 | * @resno: the resource number | 481 | * @resno: the resource number |
482 | * @type: the BAR type to be filled in | ||
483 | * | 482 | * |
484 | * Returns position of the BAR encapsulated in the SR-IOV capability. | 483 | * Returns position of the BAR encapsulated in the SR-IOV capability. |
485 | */ | 484 | */ |
486 | int pci_iov_resource_bar(struct pci_dev *dev, int resno, | 485 | int pci_iov_resource_bar(struct pci_dev *dev, int resno) |
487 | enum pci_bar_type *type) | ||
488 | { | 486 | { |
489 | if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END) | 487 | if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END) |
490 | return 0; | 488 | return 0; |
491 | 489 | ||
492 | BUG_ON(!dev->is_physfn); | 490 | BUG_ON(!dev->is_physfn); |
493 | 491 | ||
494 | *type = pci_bar_unknown; | ||
495 | |||
496 | return dev->sriov->pos + PCI_SRIOV_BAR + | 492 | return dev->sriov->pos + PCI_SRIOV_BAR + |
497 | 4 * (resno - PCI_IOV_RESOURCES); | 493 | 4 * (resno - PCI_IOV_RESOURCES); |
498 | } | 494 | } |
@@ -510,13 +506,12 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno, | |||
510 | resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) | 506 | resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) |
511 | { | 507 | { |
512 | struct resource tmp; | 508 | struct resource tmp; |
513 | enum pci_bar_type type; | 509 | int reg = pci_iov_resource_bar(dev, resno); |
514 | int reg = pci_iov_resource_bar(dev, resno, &type); | ||
515 | 510 | ||
516 | if (!reg) | 511 | if (!reg) |
517 | return 0; | 512 | return 0; |
518 | 513 | ||
519 | __pci_read_base(dev, type, &tmp, reg); | 514 | __pci_read_base(dev, pci_bar_unknown, &tmp, reg); |
520 | return resource_alignment(&tmp); | 515 | return resource_alignment(&tmp); |
521 | } | 516 | } |
522 | 517 | ||
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 6ebf8edc5f3c..3542150fc8a3 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -322,8 +322,7 @@ static void pci_acpi_wake_dev(struct work_struct *work) | |||
322 | pci_wakeup_event(pci_dev); | 322 | pci_wakeup_event(pci_dev); |
323 | pm_runtime_resume(&pci_dev->dev); | 323 | pm_runtime_resume(&pci_dev->dev); |
324 | 324 | ||
325 | if (pci_dev->subordinate) | 325 | pci_pme_wakeup_bus(pci_dev->subordinate); |
326 | pci_pme_wakeup_bus(pci_dev->subordinate); | ||
327 | } | 326 | } |
328 | 327 | ||
329 | /** | 328 | /** |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 2c6643fdc0cf..a5addbc9c026 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -221,12 +221,37 @@ static ssize_t enable_show(struct device *dev, struct device_attribute *attr, | |||
221 | static DEVICE_ATTR_RW(enable); | 221 | static DEVICE_ATTR_RW(enable); |
222 | 222 | ||
223 | #ifdef CONFIG_NUMA | 223 | #ifdef CONFIG_NUMA |
224 | static ssize_t numa_node_store(struct device *dev, | ||
225 | struct device_attribute *attr, const char *buf, | ||
226 | size_t count) | ||
227 | { | ||
228 | struct pci_dev *pdev = to_pci_dev(dev); | ||
229 | int node, ret; | ||
230 | |||
231 | if (!capable(CAP_SYS_ADMIN)) | ||
232 | return -EPERM; | ||
233 | |||
234 | ret = kstrtoint(buf, 0, &node); | ||
235 | if (ret) | ||
236 | return ret; | ||
237 | |||
238 | if (!node_online(node)) | ||
239 | return -EINVAL; | ||
240 | |||
241 | add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); | ||
242 | dev_alert(&pdev->dev, FW_BUG "Overriding NUMA node to %d. Contact your vendor for updates.", | ||
243 | node); | ||
244 | |||
245 | dev->numa_node = node; | ||
246 | return count; | ||
247 | } | ||
248 | |||
224 | static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, | 249 | static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, |
225 | char *buf) | 250 | char *buf) |
226 | { | 251 | { |
227 | return sprintf(buf, "%d\n", dev->numa_node); | 252 | return sprintf(buf, "%d\n", dev->numa_node); |
228 | } | 253 | } |
229 | static DEVICE_ATTR_RO(numa_node); | 254 | static DEVICE_ATTR_RW(numa_node); |
230 | #endif | 255 | #endif |
231 | 256 | ||
232 | static ssize_t dma_mask_bits_show(struct device *dev, | 257 | static ssize_t dma_mask_bits_show(struct device *dev, |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 625a4ace10b4..a7ac72639c52 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1012,11 +1012,7 @@ int pci_save_state(struct pci_dev *dev) | |||
1012 | if (i != 0) | 1012 | if (i != 0) |
1013 | return i; | 1013 | return i; |
1014 | 1014 | ||
1015 | i = pci_save_vc_state(dev); | 1015 | return pci_save_vc_state(dev); |
1016 | if (i != 0) | ||
1017 | return i; | ||
1018 | |||
1019 | return 0; | ||
1020 | } | 1016 | } |
1021 | EXPORT_SYMBOL(pci_save_state); | 1017 | EXPORT_SYMBOL(pci_save_state); |
1022 | 1018 | ||
@@ -3144,12 +3140,10 @@ static int pcie_flr(struct pci_dev *dev, int probe) | |||
3144 | return 0; | 3140 | return 0; |
3145 | 3141 | ||
3146 | if (!pci_wait_for_pending_transaction(dev)) | 3142 | if (!pci_wait_for_pending_transaction(dev)) |
3147 | dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n"); | 3143 | dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n"); |
3148 | 3144 | ||
3149 | pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); | 3145 | pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); |
3150 | |||
3151 | msleep(100); | 3146 | msleep(100); |
3152 | |||
3153 | return 0; | 3147 | return 0; |
3154 | } | 3148 | } |
3155 | 3149 | ||
@@ -3174,16 +3168,12 @@ static int pci_af_flr(struct pci_dev *dev, int probe) | |||
3174 | * is used, so we use the conrol offset rather than status and shift | 3168 | * is used, so we use the conrol offset rather than status and shift |
3175 | * the test bit to match. | 3169 | * the test bit to match. |
3176 | */ | 3170 | */ |
3177 | if (pci_wait_for_pending(dev, pos + PCI_AF_CTRL, | 3171 | if (!pci_wait_for_pending(dev, pos + PCI_AF_CTRL, |
3178 | PCI_AF_STATUS_TP << 8)) | 3172 | PCI_AF_STATUS_TP << 8)) |
3179 | goto clear; | 3173 | dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n"); |
3180 | |||
3181 | dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n"); | ||
3182 | 3174 | ||
3183 | clear: | ||
3184 | pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); | 3175 | pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); |
3185 | msleep(100); | 3176 | msleep(100); |
3186 | |||
3187 | return 0; | 3177 | return 0; |
3188 | } | 3178 | } |
3189 | 3179 | ||
@@ -4180,7 +4170,8 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) | |||
4180 | return dev->rom_base_reg; | 4170 | return dev->rom_base_reg; |
4181 | } else if (resno < PCI_BRIDGE_RESOURCES) { | 4171 | } else if (resno < PCI_BRIDGE_RESOURCES) { |
4182 | /* device specific resource */ | 4172 | /* device specific resource */ |
4183 | reg = pci_iov_resource_bar(dev, resno, type); | 4173 | *type = pci_bar_unknown; |
4174 | reg = pci_iov_resource_bar(dev, resno); | ||
4184 | if (reg) | 4175 | if (reg) |
4185 | return reg; | 4176 | return reg; |
4186 | } | 4177 | } |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 4a3902d8e6fe..8aff29a804ff 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -253,8 +253,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev) | |||
253 | #ifdef CONFIG_PCI_IOV | 253 | #ifdef CONFIG_PCI_IOV |
254 | int pci_iov_init(struct pci_dev *dev); | 254 | int pci_iov_init(struct pci_dev *dev); |
255 | void pci_iov_release(struct pci_dev *dev); | 255 | void pci_iov_release(struct pci_dev *dev); |
256 | int pci_iov_resource_bar(struct pci_dev *dev, int resno, | 256 | int pci_iov_resource_bar(struct pci_dev *dev, int resno); |
257 | enum pci_bar_type *type); | ||
258 | resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); | 257 | resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); |
259 | void pci_restore_iov_state(struct pci_dev *dev); | 258 | void pci_restore_iov_state(struct pci_dev *dev); |
260 | int pci_iov_bus_range(struct pci_bus *bus); | 259 | int pci_iov_bus_range(struct pci_bus *bus); |
@@ -268,8 +267,7 @@ static inline void pci_iov_release(struct pci_dev *dev) | |||
268 | 267 | ||
269 | { | 268 | { |
270 | } | 269 | } |
271 | static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno, | 270 | static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno) |
272 | enum pci_bar_type *type) | ||
273 | { | 271 | { |
274 | return 0; | 272 | return 0; |
275 | } | 273 | } |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c8ca98c2b480..23212f8ae09b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -87,8 +87,7 @@ static void release_pcibus_dev(struct device *dev) | |||
87 | { | 87 | { |
88 | struct pci_bus *pci_bus = to_pci_bus(dev); | 88 | struct pci_bus *pci_bus = to_pci_bus(dev); |
89 | 89 | ||
90 | if (pci_bus->bridge) | 90 | put_device(pci_bus->bridge); |
91 | put_device(pci_bus->bridge); | ||
92 | pci_bus_remove_resources(pci_bus); | 91 | pci_bus_remove_resources(pci_bus); |
93 | pci_release_bus_of_node(pci_bus); | 92 | pci_release_bus_of_node(pci_bus); |
94 | kfree(pci_bus); | 93 | kfree(pci_bus); |
@@ -175,7 +174,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
175 | u64 l64, sz64, mask64; | 174 | u64 l64, sz64, mask64; |
176 | u16 orig_cmd; | 175 | u16 orig_cmd; |
177 | struct pci_bus_region region, inverted_region; | 176 | struct pci_bus_region region, inverted_region; |
178 | bool bar_too_big = false, bar_too_high = false, bar_invalid = false; | ||
179 | 177 | ||
180 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; | 178 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; |
181 | 179 | ||
@@ -201,8 +199,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
201 | * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit | 199 | * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit |
202 | * 1 must be clear. | 200 | * 1 must be clear. |
203 | */ | 201 | */ |
204 | if (!sz || sz == 0xffffffff) | 202 | if (sz == 0xffffffff) |
205 | goto fail; | 203 | sz = 0; |
206 | 204 | ||
207 | /* | 205 | /* |
208 | * I don't know how l can have all bits set. Copied from old code. | 206 | * I don't know how l can have all bits set. Copied from old code. |
@@ -215,23 +213,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
215 | res->flags = decode_bar(dev, l); | 213 | res->flags = decode_bar(dev, l); |
216 | res->flags |= IORESOURCE_SIZEALIGN; | 214 | res->flags |= IORESOURCE_SIZEALIGN; |
217 | if (res->flags & IORESOURCE_IO) { | 215 | if (res->flags & IORESOURCE_IO) { |
218 | l &= PCI_BASE_ADDRESS_IO_MASK; | 216 | l64 = l & PCI_BASE_ADDRESS_IO_MASK; |
219 | mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; | 217 | sz64 = sz & PCI_BASE_ADDRESS_IO_MASK; |
218 | mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT; | ||
220 | } else { | 219 | } else { |
221 | l &= PCI_BASE_ADDRESS_MEM_MASK; | 220 | l64 = l & PCI_BASE_ADDRESS_MEM_MASK; |
222 | mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; | 221 | sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK; |
222 | mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK; | ||
223 | } | 223 | } |
224 | } else { | 224 | } else { |
225 | res->flags |= (l & IORESOURCE_ROM_ENABLE); | 225 | res->flags |= (l & IORESOURCE_ROM_ENABLE); |
226 | l &= PCI_ROM_ADDRESS_MASK; | 226 | l64 = l & PCI_ROM_ADDRESS_MASK; |
227 | mask = (u32)PCI_ROM_ADDRESS_MASK; | 227 | sz64 = sz & PCI_ROM_ADDRESS_MASK; |
228 | mask64 = (u32)PCI_ROM_ADDRESS_MASK; | ||
228 | } | 229 | } |
229 | 230 | ||
230 | if (res->flags & IORESOURCE_MEM_64) { | 231 | if (res->flags & IORESOURCE_MEM_64) { |
231 | l64 = l; | ||
232 | sz64 = sz; | ||
233 | mask64 = mask | (u64)~0 << 32; | ||
234 | |||
235 | pci_read_config_dword(dev, pos + 4, &l); | 232 | pci_read_config_dword(dev, pos + 4, &l); |
236 | pci_write_config_dword(dev, pos + 4, ~0); | 233 | pci_write_config_dword(dev, pos + 4, ~0); |
237 | pci_read_config_dword(dev, pos + 4, &sz); | 234 | pci_read_config_dword(dev, pos + 4, &sz); |
@@ -239,18 +236,30 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
239 | 236 | ||
240 | l64 |= ((u64)l << 32); | 237 | l64 |= ((u64)l << 32); |
241 | sz64 |= ((u64)sz << 32); | 238 | sz64 |= ((u64)sz << 32); |
239 | mask64 |= ((u64)~0 << 32); | ||
240 | } | ||
242 | 241 | ||
243 | sz64 = pci_size(l64, sz64, mask64); | 242 | if (!dev->mmio_always_on && (orig_cmd & PCI_COMMAND_DECODE_ENABLE)) |
243 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | ||
244 | 244 | ||
245 | if (!sz64) | 245 | if (!sz64) |
246 | goto fail; | 246 | goto fail; |
247 | 247 | ||
248 | sz64 = pci_size(l64, sz64, mask64); | ||
249 | if (!sz64) { | ||
250 | dev_info(&dev->dev, FW_BUG "reg 0x%x: invalid BAR (can't size)\n", | ||
251 | pos); | ||
252 | goto fail; | ||
253 | } | ||
254 | |||
255 | if (res->flags & IORESOURCE_MEM_64) { | ||
248 | if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && | 256 | if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && |
249 | sz64 > 0x100000000ULL) { | 257 | sz64 > 0x100000000ULL) { |
250 | res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; | 258 | res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; |
251 | res->start = 0; | 259 | res->start = 0; |
252 | res->end = 0; | 260 | res->end = 0; |
253 | bar_too_big = true; | 261 | dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", |
262 | pos, (unsigned long long)sz64); | ||
254 | goto out; | 263 | goto out; |
255 | } | 264 | } |
256 | 265 | ||
@@ -259,22 +268,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
259 | res->flags |= IORESOURCE_UNSET; | 268 | res->flags |= IORESOURCE_UNSET; |
260 | res->start = 0; | 269 | res->start = 0; |
261 | res->end = sz64; | 270 | res->end = sz64; |
262 | bar_too_high = true; | 271 | dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n", |
272 | pos, (unsigned long long)l64); | ||
263 | goto out; | 273 | goto out; |
264 | } else { | ||
265 | region.start = l64; | ||
266 | region.end = l64 + sz64; | ||
267 | } | 274 | } |
268 | } else { | ||
269 | sz = pci_size(l, sz, mask); | ||
270 | |||
271 | if (!sz) | ||
272 | goto fail; | ||
273 | |||
274 | region.start = l; | ||
275 | region.end = l + sz; | ||
276 | } | 275 | } |
277 | 276 | ||
277 | region.start = l64; | ||
278 | region.end = l64 + sz64; | ||
279 | |||
278 | pcibios_bus_to_resource(dev->bus, res, ®ion); | 280 | pcibios_bus_to_resource(dev->bus, res, ®ion); |
279 | pcibios_resource_to_bus(dev->bus, &inverted_region, res); | 281 | pcibios_resource_to_bus(dev->bus, &inverted_region, res); |
280 | 282 | ||
@@ -293,7 +295,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
293 | res->flags |= IORESOURCE_UNSET; | 295 | res->flags |= IORESOURCE_UNSET; |
294 | res->start = 0; | 296 | res->start = 0; |
295 | res->end = region.end - region.start; | 297 | res->end = region.end - region.start; |
296 | bar_invalid = true; | 298 | dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n", |
299 | pos, (unsigned long long)region.start); | ||
297 | } | 300 | } |
298 | 301 | ||
299 | goto out; | 302 | goto out; |
@@ -302,19 +305,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
302 | fail: | 305 | fail: |
303 | res->flags = 0; | 306 | res->flags = 0; |
304 | out: | 307 | out: |
305 | if (!dev->mmio_always_on && | ||
306 | (orig_cmd & PCI_COMMAND_DECODE_ENABLE)) | ||
307 | pci_write_config_word(dev, PCI_COMMAND, orig_cmd); | ||
308 | |||
309 | if (bar_too_big) | ||
310 | dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", | ||
311 | pos, (unsigned long long) sz64); | ||
312 | if (bar_too_high) | ||
313 | dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n", | ||
314 | pos, (unsigned long long) l64); | ||
315 | if (bar_invalid) | ||
316 | dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n", | ||
317 | pos, (unsigned long long) region.start); | ||
318 | if (res->flags) | 308 | if (res->flags) |
319 | dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); | 309 | dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); |
320 | 310 | ||
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index a81f413083e4..a20ce7d5e2a7 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
@@ -271,8 +271,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, | |||
271 | match_pci_dev_by_id); | 271 | match_pci_dev_by_id); |
272 | if (dev) | 272 | if (dev) |
273 | pdev = to_pci_dev(dev); | 273 | pdev = to_pci_dev(dev); |
274 | if (from) | 274 | pci_dev_put(from); |
275 | pci_dev_put(from); | ||
276 | return pdev; | 275 | return pdev; |
277 | } | 276 | } |
278 | 277 | ||
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 116ca3746adb..b1ffebec9b9e 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c | |||
@@ -596,8 +596,7 @@ static pci_ers_result_t pcifront_common_process(int cmd, | |||
596 | pcidev = pci_get_bus_and_slot(bus, devfn); | 596 | pcidev = pci_get_bus_and_slot(bus, devfn); |
597 | if (!pcidev || !pcidev->driver) { | 597 | if (!pcidev || !pcidev->driver) { |
598 | dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); | 598 | dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); |
599 | if (pcidev) | 599 | pci_dev_put(pcidev); |
600 | pci_dev_put(pcidev); | ||
601 | return result; | 600 | return result; |
602 | } | 601 | } |
603 | pdrv = pcidev->driver; | 602 | pdrv = pcidev->driver; |
@@ -866,6 +865,11 @@ static int pcifront_try_connect(struct pcifront_device *pdev) | |||
866 | xenbus_dev_error(pdev->xdev, err, | 865 | xenbus_dev_error(pdev->xdev, err, |
867 | "No PCI Roots found, trying 0000:00"); | 866 | "No PCI Roots found, trying 0000:00"); |
868 | err = pcifront_scan_root(pdev, 0, 0); | 867 | err = pcifront_scan_root(pdev, 0, 0); |
868 | if (err) { | ||
869 | xenbus_dev_fatal(pdev->xdev, err, | ||
870 | "Error scanning PCI root 0000:00"); | ||
871 | goto out; | ||
872 | } | ||
869 | num_roots = 0; | 873 | num_roots = 0; |
870 | } else if (err != 1) { | 874 | } else if (err != 1) { |
871 | if (err == 0) | 875 | if (err == 0) |
@@ -947,6 +951,11 @@ static int pcifront_attach_devices(struct pcifront_device *pdev) | |||
947 | xenbus_dev_error(pdev->xdev, err, | 951 | xenbus_dev_error(pdev->xdev, err, |
948 | "No PCI Roots found, trying 0000:00"); | 952 | "No PCI Roots found, trying 0000:00"); |
949 | err = pcifront_rescan_root(pdev, 0, 0); | 953 | err = pcifront_rescan_root(pdev, 0, 0); |
954 | if (err) { | ||
955 | xenbus_dev_fatal(pdev->xdev, err, | ||
956 | "Error scanning PCI root 0000:00"); | ||
957 | goto out; | ||
958 | } | ||
950 | num_roots = 0; | 959 | num_roots = 0; |
951 | } else if (err != 1) { | 960 | } else if (err != 1) { |
952 | if (err == 0) | 961 | if (err == 0) |