bcm53xx: use upstream fix for iproc regression
[openwrt/openwrt.git] / target / linux / bcm53xx / patches-4.9 / 089-PCI-iproc-Save-host-bridge-window-resource-in-struct.patch
1 From 6e347b5e05ea2ac4ac467a5a1cfaebb2c7f06f80 Mon Sep 17 00:00:00 2001
2 From: Bjorn Helgaas <bhelgaas@google.com>
3 Date: Thu, 9 Mar 2017 11:27:07 -0600
4 Subject: [PATCH] PCI: iproc: Save host bridge window resource in struct
5 iproc_pcie
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 The host bridge memory window resource is inserted into the iomem_resource
11 tree and cannot be deallocated until the host bridge itself is removed.
12
13 Previously, the window was on the stack, which meant the iomem_resource
14 entry pointed into the stack and was corrupted as soon as the probe
15 function returned, which caused memory corruption and errors like this:
16
17 pcie_iproc_bcma bcma0:8: resource collision: [mem 0x40000000-0x47ffffff] conflicts with PCIe MEM space [mem 0x40000000-0x47ffffff]
18
19 Move the memory window resource from the stack into struct iproc_pcie so
20 its lifetime matches that of the host bridge.
21
22 Fixes: c3245a566400 ("PCI: iproc: Request host bridge window resources")
23 Reported-and-tested-by: Rafał Miłecki <zajec5@gmail.com>
24 Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
25 CC: stable@vger.kernel.org # v4.8+
26 ---
27 drivers/pci/host/pcie-iproc-bcma.c | 24 ++++++++++++------------
28 drivers/pci/host/pcie-iproc-platform.c | 19 ++++++++++---------
29 drivers/pci/host/pcie-iproc.h | 1 +
30 3 files changed, 23 insertions(+), 21 deletions(-)
31
32 --- a/drivers/pci/host/pcie-iproc-bcma.c
33 +++ b/drivers/pci/host/pcie-iproc-bcma.c
34 @@ -44,8 +44,7 @@ static int iproc_pcie_bcma_probe(struct
35 {
36 struct device *dev = &bdev->dev;
37 struct iproc_pcie *pcie;
38 - LIST_HEAD(res);
39 - struct resource res_mem;
40 + LIST_HEAD(resources);
41 int ret;
42
43 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
44 @@ -62,22 +61,23 @@ static int iproc_pcie_bcma_probe(struct
45
46 pcie->base_addr = bdev->addr;
47
48 - res_mem.start = bdev->addr_s[0];
49 - res_mem.end = bdev->addr_s[0] + SZ_128M - 1;
50 - res_mem.name = "PCIe MEM space";
51 - res_mem.flags = IORESOURCE_MEM;
52 - pci_add_resource(&res, &res_mem);
53 + pcie->mem.start = bdev->addr_s[0];
54 + pcie->mem.end = bdev->addr_s[0] + SZ_128M - 1;
55 + pcie->mem.name = "PCIe MEM space";
56 + pcie->mem.flags = IORESOURCE_MEM;
57 + pci_add_resource(&resources, &pcie->mem);
58
59 pcie->map_irq = iproc_pcie_bcma_map_irq;
60
61 - ret = iproc_pcie_setup(pcie, &res);
62 - if (ret)
63 + ret = iproc_pcie_setup(pcie, &resources);
64 + if (ret) {
65 dev_err(dev, "PCIe controller setup failed\n");
66 -
67 - pci_free_resource_list(&res);
68 + pci_free_resource_list(&resources);
69 + return ret;
70 + }
71
72 bcma_set_drvdata(bdev, pcie);
73 - return ret;
74 + return 0;
75 }
76
77 static void iproc_pcie_bcma_remove(struct bcma_device *bdev)
78 --- a/drivers/pci/host/pcie-iproc-platform.c
79 +++ b/drivers/pci/host/pcie-iproc-platform.c
80 @@ -46,7 +46,7 @@ static int iproc_pcie_pltfm_probe(struct
81 struct device_node *np = dev->of_node;
82 struct resource reg;
83 resource_size_t iobase = 0;
84 - LIST_HEAD(res);
85 + LIST_HEAD(resources);
86 int ret;
87
88 of_id = of_match_device(iproc_pcie_of_match_table, dev);
89 @@ -108,23 +108,24 @@ static int iproc_pcie_pltfm_probe(struct
90 pcie->phy = NULL;
91 }
92
93 - ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &iobase);
94 + ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &resources,
95 + &iobase);
96 if (ret) {
97 - dev_err(dev,
98 - "unable to get PCI host bridge resources\n");
99 + dev_err(dev, "unable to get PCI host bridge resources\n");
100 return ret;
101 }
102
103 pcie->map_irq = of_irq_parse_and_map_pci;
104
105 - ret = iproc_pcie_setup(pcie, &res);
106 - if (ret)
107 + ret = iproc_pcie_setup(pcie, &resources);
108 + if (ret) {
109 dev_err(dev, "PCIe controller setup failed\n");
110 -
111 - pci_free_resource_list(&res);
112 + pci_free_resource_list(&resources);
113 + return ret;
114 + }
115
116 platform_set_drvdata(pdev, pcie);
117 - return ret;
118 + return 0;
119 }
120
121 static int iproc_pcie_pltfm_remove(struct platform_device *pdev)
122 --- a/drivers/pci/host/pcie-iproc.h
123 +++ b/drivers/pci/host/pcie-iproc.h
124 @@ -68,6 +68,7 @@ struct iproc_pcie {
125 #ifdef CONFIG_ARM
126 struct pci_sys_data sysdata;
127 #endif
128 + struct resource mem;
129 struct pci_bus *root_bus;
130 struct phy *phy;
131 int (*map_irq)(const struct pci_dev *, u8, u8);