Commit c75059c46293adf1560162c17148ab94624f5ed2
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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 ...
Showing 26 changed files Side-by-side Diff
- Documentation/ABI/testing/sysfs-bus-pci
- Documentation/devicetree/bindings/pci/layerscape-pci.txt
- MAINTAINERS
- drivers/pci/host/Kconfig
- drivers/pci/host/Makefile
- drivers/pci/host/pci-dra7xx.c
- drivers/pci/host/pci-exynos.c
- drivers/pci/host/pci-host-generic.c
- drivers/pci/host/pci-imx6.c
- drivers/pci/host/pci-keystone-dw.c
- drivers/pci/host/pci-keystone.c
- drivers/pci/host/pci-layerscape.c
- drivers/pci/host/pci-mvebu.c
- drivers/pci/host/pcie-designware.c
- drivers/pci/host/pcie-rcar.c
- drivers/pci/host/pcie-spear13xx.c
- drivers/pci/hotplug/ibmphp_res.c
- drivers/pci/iov.c
- drivers/pci/pci-acpi.c
- drivers/pci/pci-sysfs.c
- drivers/pci/pci.c
- drivers/pci/pci.h
- drivers/pci/probe.c
- drivers/pci/search.c
- drivers/pci/xen-pcifront.c
- include/linux/pci_hotplug.h
Documentation/ABI/testing/sysfs-bus-pci
... | ... | @@ -281,4 +281,17 @@ |
281 | 281 | opt-out of driver binding using a driver_override name such as |
282 | 282 | "none". Only a single driver may be specified in the override, |
283 | 283 | there is no support for parsing delimiters. |
284 | + | |
285 | +What: /sys/bus/pci/devices/.../numa_node | |
286 | +Date: Oct 2014 | |
287 | +Contact: Prarit Bhargava <prarit@redhat.com> | |
288 | +Description: | |
289 | + This file contains the NUMA node to which the PCI device is | |
290 | + attached, or -1 if the node is unknown. The initial value | |
291 | + comes from an ACPI _PXM method or a similar firmware | |
292 | + source. If that is missing or incorrect, this file can be | |
293 | + written to override the node. In that case, please report | |
294 | + a firmware bug to the system vendor. Writing to this file | |
295 | + taints the kernel with TAINT_FIRMWARE_WORKAROUND, which | |
296 | + reduces the supportability of your system. |
Documentation/devicetree/bindings/pci/layerscape-pci.txt
1 | +Freescale Layerscape PCIe controller | |
2 | + | |
3 | +This PCIe host controller is based on the Synopsis Designware PCIe IP | |
4 | +and thus inherits all the common properties defined in designware-pcie.txt. | |
5 | + | |
6 | +Required properties: | |
7 | +- compatible: should contain the platform identifier such as "fsl,ls1021a-pcie" | |
8 | +- reg: base addresses and lengths of the PCIe controller | |
9 | +- interrupts: A list of interrupt outputs of the controller. Must contain an | |
10 | + entry for each entry in the interrupt-names property. | |
11 | +- interrupt-names: Must include the following entries: | |
12 | + "intr": The interrupt that is asserted for controller interrupts | |
13 | +- fsl,pcie-scfg: Must include two entries. | |
14 | + The first entry must be a link to the SCFG device node | |
15 | + The second entry must be '0' or '1' based on physical PCIe controller index. | |
16 | + This is used to get SCFG PEXN registers | |
17 | + | |
18 | +Example: | |
19 | + | |
20 | + pcie@3400000 { | |
21 | + compatible = "fsl,ls1021a-pcie", "snps,dw-pcie"; | |
22 | + reg = <0x00 0x03400000 0x0 0x00010000 /* controller registers */ | |
23 | + 0x40 0x00000000 0x0 0x00002000>; /* configuration space */ | |
24 | + reg-names = "regs", "config"; | |
25 | + interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */ | |
26 | + interrupt-names = "intr"; | |
27 | + fsl,pcie-scfg = <&scfg 0>; | |
28 | + #address-cells = <3>; | |
29 | + #size-cells = <2>; | |
30 | + device_type = "pci"; | |
31 | + num-lanes = <4>; | |
32 | + bus-range = <0x0 0xff>; | |
33 | + ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */ | |
34 | + 0xc2000000 0x0 0x20000000 0x40 0x20000000 0x0 0x20000000 /* prefetchable memory */ | |
35 | + 0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ | |
36 | + #interrupt-cells = <1>; | |
37 | + interrupt-map-mask = <0 0 0 7>; | |
38 | + interrupt-map = <0000 0 0 1 &gic GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, | |
39 | + <0000 0 0 2 &gic GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, | |
40 | + <0000 0 0 3 &gic GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>, | |
41 | + <0000 0 0 4 &gic GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; | |
42 | + }; |
MAINTAINERS
... | ... | @@ -7086,6 +7086,16 @@ |
7086 | 7086 | F: Documentation/devicetree/bindings/pci/xgene-pci.txt |
7087 | 7087 | F: drivers/pci/host/pci-xgene.c |
7088 | 7088 | |
7089 | +PCI DRIVER FOR FREESCALE LAYERSCAPE | |
7090 | +M: Minghuan Lian <minghuan.Lian@freescale.com> | |
7091 | +M: Mingkai Hu <mingkai.hu@freescale.com> | |
7092 | +M: Roy Zang <tie-fei.zang@freescale.com> | |
7093 | +L: linuxppc-dev@lists.ozlabs.org | |
7094 | +L: linux-pci@vger.kernel.org | |
7095 | +L: linux-arm-kernel@lists.infradead.org | |
7096 | +S: Maintained | |
7097 | +F: drivers/pci/host/*layerscape* | |
7098 | + | |
7089 | 7099 | PCI DRIVER FOR IMX6 |
7090 | 7100 | M: Richard Zhu <r65037@freescale.com> |
7091 | 7101 | M: Lucas Stach <l.stach@pengutronix.de> |
drivers/pci/host/Kconfig
... | ... | @@ -32,7 +32,10 @@ |
32 | 32 | |
33 | 33 | config PCI_TEGRA |
34 | 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 | 40 | config PCI_RCAR_GEN2 |
38 | 41 | bool "Renesas R-Car Gen2 Internal PCI controller" |
... | ... | @@ -90,6 +93,14 @@ |
90 | 93 | Say Y here if you want internal PCI support on APM X-Gene SoC. |
91 | 94 | There are 5 internal PCIe ports available. Each port is GEN3 capable |
92 | 95 | and have varied lanes from x1 to x8. |
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. | |
93 | 104 | |
94 | 105 | endmenu |
drivers/pci/host/Makefile
drivers/pci/host/pci-dra7xx.c
... | ... | @@ -270,8 +270,8 @@ |
270 | 270 | return IRQ_HANDLED; |
271 | 271 | } |
272 | 272 | |
273 | -static int add_pcie_port(struct dra7xx_pcie *dra7xx, | |
274 | - struct platform_device *pdev) | |
273 | +static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, | |
274 | + struct platform_device *pdev) | |
275 | 275 | { |
276 | 276 | int ret; |
277 | 277 | struct pcie_port *pp; |
... | ... | @@ -398,7 +398,7 @@ |
398 | 398 | |
399 | 399 | platform_set_drvdata(pdev, dra7xx); |
400 | 400 | |
401 | - ret = add_pcie_port(dra7xx, pdev); | |
401 | + ret = dra7xx_add_pcie_port(dra7xx, pdev); | |
402 | 402 | if (ret < 0) |
403 | 403 | goto err_add_port; |
404 | 404 |
drivers/pci/host/pci-exynos.c
... | ... | @@ -312,7 +312,6 @@ |
312 | 312 | if (exynos_pcie->reset_gpio >= 0) |
313 | 313 | devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio, |
314 | 314 | GPIOF_OUT_INIT_HIGH, "RESET"); |
315 | - return; | |
316 | 315 | } |
317 | 316 | |
318 | 317 | static int exynos_pcie_establish_link(struct pcie_port *pp) |
... | ... | @@ -388,7 +387,6 @@ |
388 | 387 | |
389 | 388 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE); |
390 | 389 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE); |
391 | - return; | |
392 | 390 | } |
393 | 391 | |
394 | 392 | static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) |
... | ... | @@ -400,7 +398,6 @@ |
400 | 398 | val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | |
401 | 399 | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT, |
402 | 400 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE); |
403 | - return; | |
404 | 401 | } |
405 | 402 | |
406 | 403 | static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) |
... | ... | @@ -429,7 +426,6 @@ |
429 | 426 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); |
430 | 427 | val |= IRQ_MSI_ENABLE; |
431 | 428 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); |
432 | - return; | |
433 | 429 | } |
434 | 430 | |
435 | 431 | static void exynos_pcie_enable_interrupts(struct pcie_port *pp) |
... | ... | @@ -438,8 +434,6 @@ |
438 | 434 | |
439 | 435 | if (IS_ENABLED(CONFIG_PCI_MSI)) |
440 | 436 | exynos_pcie_msi_init(pp); |
441 | - | |
442 | - return; | |
443 | 437 | } |
444 | 438 | |
445 | 439 | static inline void exynos_pcie_readl_rc(struct pcie_port *pp, |
... | ... | @@ -448,7 +442,6 @@ |
448 | 442 | exynos_pcie_sideband_dbi_r_mode(pp, true); |
449 | 443 | *val = readl(dbi_base); |
450 | 444 | exynos_pcie_sideband_dbi_r_mode(pp, false); |
451 | - return; | |
452 | 445 | } |
453 | 446 | |
454 | 447 | static inline void exynos_pcie_writel_rc(struct pcie_port *pp, |
... | ... | @@ -457,7 +450,6 @@ |
457 | 450 | exynos_pcie_sideband_dbi_w_mode(pp, true); |
458 | 451 | writel(val, dbi_base); |
459 | 452 | exynos_pcie_sideband_dbi_w_mode(pp, false); |
460 | - return; | |
461 | 453 | } |
462 | 454 | |
463 | 455 | static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, |
... | ... | @@ -509,8 +501,8 @@ |
509 | 501 | .host_init = exynos_pcie_host_init, |
510 | 502 | }; |
511 | 503 | |
512 | -static int __init add_pcie_port(struct pcie_port *pp, | |
513 | - struct platform_device *pdev) | |
504 | +static int __init exynos_add_pcie_port(struct pcie_port *pp, | |
505 | + struct platform_device *pdev) | |
514 | 506 | { |
515 | 507 | int ret; |
516 | 508 | |
... | ... | @@ -615,7 +607,7 @@ |
615 | 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 | 611 | if (ret < 0) |
620 | 612 | goto fail_bus_clk; |
621 | 613 | |
622 | 614 | |
... | ... | @@ -656,11 +648,11 @@ |
656 | 648 | |
657 | 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 | 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 | 657 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); |
666 | 658 | MODULE_DESCRIPTION("Samsung PCIe host controller driver"); |
drivers/pci/host/pci-host-generic.c
... | ... | @@ -32,7 +32,7 @@ |
32 | 32 | |
33 | 33 | struct gen_pci_cfg_windows { |
34 | 34 | struct resource res; |
35 | - struct resource bus_range; | |
35 | + struct resource *bus_range; | |
36 | 36 | void __iomem **win; |
37 | 37 | |
38 | 38 | const struct gen_pci_cfg_bus_ops *ops; |
... | ... | @@ -50,7 +50,7 @@ |
50 | 50 | { |
51 | 51 | struct pci_sys_data *sys = bus->sysdata; |
52 | 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 | 55 | return pci->cfg.win[idx] + ((devfn << 8) | where); |
56 | 56 | } |
... | ... | @@ -66,7 +66,7 @@ |
66 | 66 | { |
67 | 67 | struct pci_sys_data *sys = bus->sysdata; |
68 | 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 | 71 | return pci->cfg.win[idx] + ((devfn << 12) | where); |
72 | 72 | } |
73 | 73 | |
74 | 74 | |
75 | 75 | |
76 | 76 | |
77 | 77 | |
78 | 78 | |
79 | 79 | |
80 | 80 | |
81 | 81 | |
82 | 82 | |
83 | 83 | |
84 | 84 | |
... | ... | @@ -138,106 +138,50 @@ |
138 | 138 | }; |
139 | 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 | 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 | 143 | pci_free_resource_list(&pci->resources); |
188 | 144 | } |
189 | 145 | |
190 | 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 | 148 | int err, res_valid = 0; |
195 | 149 | struct device *dev = pci->host.dev.parent; |
196 | 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)) { | |
199 | - dev_err(dev, "missing \"ranges\" property\n"); | |
200 | - return -EINVAL; | |
201 | - } | |
154 | + err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, | |
155 | + &iobase); | |
156 | + if (err) | |
157 | + return err; | |
202 | 158 | |
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; | |
159 | + list_for_each_entry(win, &pci->resources, list) { | |
160 | + struct resource *parent, *res = win->res; | |
207 | 161 | |
208 | - res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL); | |
209 | - if (!res) { | |
210 | - err = -ENOMEM; | |
211 | - goto out_release_res; | |
212 | - } | |
213 | - | |
214 | - switch (restype) { | |
162 | + switch (resource_type(res)) { | |
215 | 163 | case IORESOURCE_IO: |
216 | 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 | 171 | break; |
219 | 172 | case IORESOURCE_MEM: |
220 | 173 | parent = &iomem_resource; |
221 | - err = gen_pci_calc_mem_offset(dev, &range, res, &offset); | |
222 | - res_valid |= !(res->flags & IORESOURCE_PREFETCH || err); | |
174 | + res_valid |= !(res->flags & IORESOURCE_PREFETCH); | |
223 | 175 | break; |
176 | + case IORESOURCE_BUS: | |
177 | + pci->cfg.bus_range = res; | |
224 | 178 | default: |
225 | - err = -EINVAL; | |
226 | 179 | continue; |
227 | 180 | } |
228 | 181 | |
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; | |
234 | - } | |
235 | - | |
236 | - err = request_resource(parent, res); | |
182 | + err = devm_request_resource(dev, parent, res); | |
237 | 183 | if (err) |
238 | 184 | goto out_release_res; |
239 | - | |
240 | - pci_add_resource_offset(&pci->resources, res, offset); | |
241 | 185 | } |
242 | 186 | |
243 | 187 | if (!res_valid) { |
244 | 188 | |
245 | 189 | |
246 | 190 | |
... | ... | @@ -262,38 +206,30 @@ |
262 | 206 | struct device *dev = pci->host.dev.parent; |
263 | 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 | 209 | err = of_address_to_resource(np, 0, &pci->cfg.res); |
274 | 210 | if (err) { |
275 | 211 | dev_err(dev, "missing \"reg\" property\n"); |
276 | 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 | 222 | sizeof(*pci->cfg.win), GFP_KERNEL); |
281 | 223 | if (!pci->cfg.win) |
282 | 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 | 226 | /* Map our Configuration Space windows */ |
291 | 227 | if (!devm_request_mem_region(dev, pci->cfg.res.start, |
292 | 228 | resource_size(&pci->cfg.res), |
293 | 229 | "Configuration Space")) |
294 | 230 | return -ENOMEM; |
295 | 231 | |
296 | - bus_range = &pci->cfg.bus_range; | |
232 | + bus_range = pci->cfg.bus_range; | |
297 | 233 | for (busn = bus_range->start; busn <= bus_range->end; ++busn) { |
298 | 234 | u32 idx = busn - bus_range->start; |
299 | 235 | u32 sz = 1 << pci->cfg.ops->bus_shift; |
... | ... | @@ -305,8 +241,6 @@ |
305 | 241 | return -ENOMEM; |
306 | 242 | } |
307 | 243 | |
308 | - /* Register bus resource */ | |
309 | - pci_add_resource(&pci->resources, bus_range); | |
310 | 244 | return 0; |
311 | 245 | } |
312 | 246 |
drivers/pci/host/pci-imx6.c
... | ... | @@ -533,8 +533,8 @@ |
533 | 533 | } |
534 | 534 | |
535 | 535 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, |
536 | - imx6_pcie_msi_handler, | |
537 | - IRQF_SHARED, "mx6-pcie-msi", pp); | |
536 | + imx6_pcie_msi_handler, | |
537 | + IRQF_SHARED, "mx6-pcie-msi", pp); | |
538 | 538 | if (ret) { |
539 | 539 | dev_err(&pdev->dev, "failed to request MSI irq\n"); |
540 | 540 | return -ENODEV; |
drivers/pci/host/pci-keystone-dw.c
drivers/pci/host/pci-keystone.c
... | ... | @@ -353,10 +353,9 @@ |
353 | 353 | |
354 | 354 | ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie), |
355 | 355 | GFP_KERNEL); |
356 | - if (!ks_pcie) { | |
357 | - dev_err(dev, "no memory for keystone pcie\n"); | |
356 | + if (!ks_pcie) | |
358 | 357 | return -ENOMEM; |
359 | - } | |
358 | + | |
360 | 359 | pp = &ks_pcie->pp; |
361 | 360 | |
362 | 361 | /* initialize SerDes Phy if present */ |
drivers/pci/host/pci-layerscape.c
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"); |
drivers/pci/host/pci-mvebu.c
... | ... | @@ -622,6 +622,7 @@ |
622 | 622 | |
623 | 623 | for (i = 0; i < pcie->nports; i++) { |
624 | 624 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
625 | + | |
625 | 626 | if (bus->number == 0 && port->devfn == devfn) |
626 | 627 | return port; |
627 | 628 | if (bus->number != 0 && |
... | ... | @@ -751,6 +752,7 @@ |
751 | 752 | |
752 | 753 | for (i = 0; i < pcie->nports; i++) { |
753 | 754 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
755 | + | |
754 | 756 | if (!port->base) |
755 | 757 | continue; |
756 | 758 | mvebu_pcie_setup_hw(port); |
drivers/pci/host/pcie-designware.c
... | ... | @@ -380,6 +380,7 @@ |
380 | 380 | /* Get the I/O and memory ranges from DT */ |
381 | 381 | for_each_of_pci_range(&parser, &range) { |
382 | 382 | unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; |
383 | + | |
383 | 384 | if (restype == IORESOURCE_IO) { |
384 | 385 | of_pci_range_to_resource(&range, np, &pp->io); |
385 | 386 | pp->io.name = "I/O"; |
drivers/pci/host/pcie-rcar.c
drivers/pci/host/pcie-spear13xx.c
... | ... | @@ -269,7 +269,8 @@ |
269 | 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 | 275 | struct device *dev = &pdev->dev; |
275 | 276 | int ret; |
276 | 277 | |
... | ... | @@ -308,10 +309,8 @@ |
308 | 309 | int ret; |
309 | 310 | |
310 | 311 | spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL); |
311 | - if (!spear13xx_pcie) { | |
312 | - dev_err(dev, "no memory for SPEAr13xx pcie\n"); | |
312 | + if (!spear13xx_pcie) | |
313 | 313 | return -ENOMEM; |
314 | - } | |
315 | 314 | |
316 | 315 | spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy"); |
317 | 316 | if (IS_ERR(spear13xx_pcie->phy)) { |
... | ... | @@ -352,7 +351,7 @@ |
352 | 351 | if (of_property_read_bool(np, "st,pcie-is-gen1")) |
353 | 352 | spear13xx_pcie->is_gen1 = true; |
354 | 353 | |
355 | - ret = add_pcie_port(pp, pdev); | |
354 | + ret = spear13xx_add_pcie_port(pp, pdev); | |
356 | 355 | if (ret < 0) |
357 | 356 | goto fail_clk; |
358 | 357 | |
359 | 358 | |
... | ... | @@ -382,11 +381,11 @@ |
382 | 381 | |
383 | 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 | 386 | return platform_driver_register(&spear13xx_pcie_driver); |
388 | 387 | } |
389 | -module_init(pcie_init); | |
388 | +module_init(spear13xx_pcie_init); | |
390 | 389 | |
391 | 390 | MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver"); |
392 | 391 | MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>"); |
drivers/pci/hotplug/ibmphp_res.c
... | ... | @@ -376,10 +376,7 @@ |
376 | 376 | if (rc) |
377 | 377 | return rc; |
378 | 378 | } |
379 | - rc = once_over (); /* This is to align ranges (so no -1) */ | |
380 | - if (rc) | |
381 | - return rc; | |
382 | - return 0; | |
379 | + return once_over (); /* This is to align ranges (so no -1) */ | |
383 | 380 | } |
384 | 381 | |
385 | 382 | /******************************************************************************** |
drivers/pci/iov.c
... | ... | @@ -479,20 +479,16 @@ |
479 | 479 | * pci_iov_resource_bar - get position of the SR-IOV BAR |
480 | 480 | * @dev: the PCI device |
481 | 481 | * @resno: the resource number |
482 | - * @type: the BAR type to be filled in | |
483 | 482 | * |
484 | 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, | |
487 | - enum pci_bar_type *type) | |
485 | +int pci_iov_resource_bar(struct pci_dev *dev, int resno) | |
488 | 486 | { |
489 | 487 | if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END) |
490 | 488 | return 0; |
491 | 489 | |
492 | 490 | BUG_ON(!dev->is_physfn); |
493 | 491 | |
494 | - *type = pci_bar_unknown; | |
495 | - | |
496 | 492 | return dev->sriov->pos + PCI_SRIOV_BAR + |
497 | 493 | 4 * (resno - PCI_IOV_RESOURCES); |
498 | 494 | } |
499 | 495 | |
... | ... | @@ -510,13 +506,12 @@ |
510 | 506 | resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) |
511 | 507 | { |
512 | 508 | struct resource tmp; |
513 | - enum pci_bar_type type; | |
514 | - int reg = pci_iov_resource_bar(dev, resno, &type); | |
509 | + int reg = pci_iov_resource_bar(dev, resno); | |
515 | 510 | |
516 | 511 | if (!reg) |
517 | 512 | return 0; |
518 | 513 | |
519 | - __pci_read_base(dev, type, &tmp, reg); | |
514 | + __pci_read_base(dev, pci_bar_unknown, &tmp, reg); | |
520 | 515 | return resource_alignment(&tmp); |
521 | 516 | } |
522 | 517 |
drivers/pci/pci-acpi.c
drivers/pci/pci-sysfs.c
... | ... | @@ -221,12 +221,37 @@ |
221 | 221 | static DEVICE_ATTR_RW(enable); |
222 | 222 | |
223 | 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 | 249 | static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, |
225 | 250 | char *buf) |
226 | 251 | { |
227 | 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 | 255 | #endif |
231 | 256 | |
232 | 257 | static ssize_t dma_mask_bits_show(struct device *dev, |
drivers/pci/pci.c
... | ... | @@ -1012,11 +1012,7 @@ |
1012 | 1012 | if (i != 0) |
1013 | 1013 | return i; |
1014 | 1014 | |
1015 | - i = pci_save_vc_state(dev); | |
1016 | - if (i != 0) | |
1017 | - return i; | |
1018 | - | |
1019 | - return 0; | |
1015 | + return pci_save_vc_state(dev); | |
1020 | 1016 | } |
1021 | 1017 | EXPORT_SYMBOL(pci_save_state); |
1022 | 1018 | |
1023 | 1019 | |
1024 | 1020 | |
... | ... | @@ -3144,12 +3140,10 @@ |
3144 | 3140 | return 0; |
3145 | 3141 | |
3146 | 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 | 3145 | pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); |
3150 | - | |
3151 | 3146 | msleep(100); |
3152 | - | |
3153 | 3147 | return 0; |
3154 | 3148 | } |
3155 | 3149 | |
3156 | 3150 | |
3157 | 3151 | |
3158 | 3152 | |
... | ... | @@ -3174,16 +3168,12 @@ |
3174 | 3168 | * is used, so we use the conrol offset rather than status and shift |
3175 | 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 | 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 | 3174 | |
3181 | - dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n"); | |
3182 | - | |
3183 | -clear: | |
3184 | 3175 | pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); |
3185 | 3176 | msleep(100); |
3186 | - | |
3187 | 3177 | return 0; |
3188 | 3178 | } |
3189 | 3179 | |
... | ... | @@ -4180,7 +4170,8 @@ |
4180 | 4170 | return dev->rom_base_reg; |
4181 | 4171 | } else if (resno < PCI_BRIDGE_RESOURCES) { |
4182 | 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 | 4175 | if (reg) |
4185 | 4176 | return reg; |
4186 | 4177 | } |
drivers/pci/pci.h
... | ... | @@ -253,8 +253,7 @@ |
253 | 253 | #ifdef CONFIG_PCI_IOV |
254 | 254 | int pci_iov_init(struct pci_dev *dev); |
255 | 255 | void pci_iov_release(struct pci_dev *dev); |
256 | -int pci_iov_resource_bar(struct pci_dev *dev, int resno, | |
257 | - enum pci_bar_type *type); | |
256 | +int pci_iov_resource_bar(struct pci_dev *dev, int resno); | |
258 | 257 | resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); |
259 | 258 | void pci_restore_iov_state(struct pci_dev *dev); |
260 | 259 | int pci_iov_bus_range(struct pci_bus *bus); |
... | ... | @@ -268,8 +267,7 @@ |
268 | 267 | |
269 | 268 | { |
270 | 269 | } |
271 | -static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno, | |
272 | - enum pci_bar_type *type) | |
270 | +static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno) | |
273 | 271 | { |
274 | 272 | return 0; |
275 | 273 | } |
drivers/pci/probe.c
... | ... | @@ -87,8 +87,7 @@ |
87 | 87 | { |
88 | 88 | struct pci_bus *pci_bus = to_pci_bus(dev); |
89 | 89 | |
90 | - if (pci_bus->bridge) | |
91 | - put_device(pci_bus->bridge); | |
90 | + put_device(pci_bus->bridge); | |
92 | 91 | pci_bus_remove_resources(pci_bus); |
93 | 92 | pci_release_bus_of_node(pci_bus); |
94 | 93 | kfree(pci_bus); |
... | ... | @@ -175,7 +174,6 @@ |
175 | 174 | u64 l64, sz64, mask64; |
176 | 175 | u16 orig_cmd; |
177 | 176 | struct pci_bus_region region, inverted_region; |
178 | - bool bar_too_big = false, bar_too_high = false, bar_invalid = false; | |
179 | 177 | |
180 | 178 | mask = type ? PCI_ROM_ADDRESS_MASK : ~0; |
181 | 179 | |
... | ... | @@ -201,8 +199,8 @@ |
201 | 199 | * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit |
202 | 200 | * 1 must be clear. |
203 | 201 | */ |
204 | - if (!sz || sz == 0xffffffff) | |
205 | - goto fail; | |
202 | + if (sz == 0xffffffff) | |
203 | + sz = 0; | |
206 | 204 | |
207 | 205 | /* |
208 | 206 | * I don't know how l can have all bits set. Copied from old code. |
209 | 207 | |
210 | 208 | |
211 | 209 | |
... | ... | @@ -215,23 +213,22 @@ |
215 | 213 | res->flags = decode_bar(dev, l); |
216 | 214 | res->flags |= IORESOURCE_SIZEALIGN; |
217 | 215 | if (res->flags & IORESOURCE_IO) { |
218 | - l &= PCI_BASE_ADDRESS_IO_MASK; | |
219 | - mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; | |
216 | + l64 = l & PCI_BASE_ADDRESS_IO_MASK; | |
217 | + sz64 = sz & PCI_BASE_ADDRESS_IO_MASK; | |
218 | + mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT; | |
220 | 219 | } else { |
221 | - l &= PCI_BASE_ADDRESS_MEM_MASK; | |
222 | - mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; | |
220 | + l64 = l & PCI_BASE_ADDRESS_MEM_MASK; | |
221 | + sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK; | |
222 | + mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK; | |
223 | 223 | } |
224 | 224 | } else { |
225 | 225 | res->flags |= (l & IORESOURCE_ROM_ENABLE); |
226 | - l &= PCI_ROM_ADDRESS_MASK; | |
227 | - mask = (u32)PCI_ROM_ADDRESS_MASK; | |
226 | + l64 = l & PCI_ROM_ADDRESS_MASK; | |
227 | + sz64 = sz & PCI_ROM_ADDRESS_MASK; | |
228 | + mask64 = (u32)PCI_ROM_ADDRESS_MASK; | |
228 | 229 | } |
229 | 230 | |
230 | 231 | if (res->flags & IORESOURCE_MEM_64) { |
231 | - l64 = l; | |
232 | - sz64 = sz; | |
233 | - mask64 = mask | (u64)~0 << 32; | |
234 | - | |
235 | 232 | pci_read_config_dword(dev, pos + 4, &l); |
236 | 233 | pci_write_config_dword(dev, pos + 4, ~0); |
237 | 234 | pci_read_config_dword(dev, pos + 4, &sz); |
238 | 235 | |
239 | 236 | |
240 | 237 | |
241 | 238 | |
... | ... | @@ -239,18 +236,30 @@ |
239 | 236 | |
240 | 237 | l64 |= ((u64)l << 32); |
241 | 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) | |
246 | - goto fail; | |
245 | + if (!sz64) | |
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 | 256 | if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && |
249 | 257 | sz64 > 0x100000000ULL) { |
250 | 258 | res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; |
251 | 259 | res->start = 0; |
252 | 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 | 263 | goto out; |
255 | 264 | } |
256 | 265 | |
257 | 266 | |
258 | 267 | |
259 | 268 | |
... | ... | @@ -259,22 +268,15 @@ |
259 | 268 | res->flags |= IORESOURCE_UNSET; |
260 | 269 | res->start = 0; |
261 | 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 | 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 | 280 | pcibios_bus_to_resource(dev->bus, res, ®ion); |
279 | 281 | pcibios_resource_to_bus(dev->bus, &inverted_region, res); |
280 | 282 | |
... | ... | @@ -293,7 +295,8 @@ |
293 | 295 | res->flags |= IORESOURCE_UNSET; |
294 | 296 | res->start = 0; |
295 | 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 | 302 | goto out; |
... | ... | @@ -302,19 +305,6 @@ |
302 | 305 | fail: |
303 | 306 | res->flags = 0; |
304 | 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 | 308 | if (res->flags) |
319 | 309 | dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); |
320 | 310 |
drivers/pci/search.c
drivers/pci/xen-pcifront.c
... | ... | @@ -596,8 +596,7 @@ |
596 | 596 | pcidev = pci_get_bus_and_slot(bus, devfn); |
597 | 597 | if (!pcidev || !pcidev->driver) { |
598 | 598 | dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); |
599 | - if (pcidev) | |
600 | - pci_dev_put(pcidev); | |
599 | + pci_dev_put(pcidev); | |
601 | 600 | return result; |
602 | 601 | } |
603 | 602 | pdrv = pcidev->driver; |
... | ... | @@ -866,6 +865,11 @@ |
866 | 865 | xenbus_dev_error(pdev->xdev, err, |
867 | 866 | "No PCI Roots found, trying 0000:00"); |
868 | 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 | 873 | num_roots = 0; |
870 | 874 | } else if (err != 1) { |
871 | 875 | if (err == 0) |
... | ... | @@ -947,6 +951,11 @@ |
947 | 951 | xenbus_dev_error(pdev->xdev, err, |
948 | 952 | "No PCI Roots found, trying 0000:00"); |
949 | 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 | 959 | num_roots = 0; |
951 | 960 | } else if (err != 1) { |
952 | 961 | if (err == 0) |
include/linux/pci_hotplug.h