diff options
Diffstat (limited to 'target/linux/bcm53xx/patches-4.9/089-PCI-iproc-Save-host-bridge-window-resource-in-struct.patch')
-rw-r--r-- | target/linux/bcm53xx/patches-4.9/089-PCI-iproc-Save-host-bridge-window-resource-in-struct.patch | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/target/linux/bcm53xx/patches-4.9/089-PCI-iproc-Save-host-bridge-window-resource-in-struct.patch b/target/linux/bcm53xx/patches-4.9/089-PCI-iproc-Save-host-bridge-window-resource-in-struct.patch new file mode 100644 index 0000000000..3de4395348 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/089-PCI-iproc-Save-host-bridge-window-resource-in-struct.patch @@ -0,0 +1,131 @@ +From 6e347b5e05ea2ac4ac467a5a1cfaebb2c7f06f80 Mon Sep 17 00:00:00 2001 +From: Bjorn Helgaas <bhelgaas@google.com> +Date: Thu, 9 Mar 2017 11:27:07 -0600 +Subject: [PATCH] PCI: iproc: Save host bridge window resource in struct + iproc_pcie +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The host bridge memory window resource is inserted into the iomem_resource +tree and cannot be deallocated until the host bridge itself is removed. + +Previously, the window was on the stack, which meant the iomem_resource +entry pointed into the stack and was corrupted as soon as the probe +function returned, which caused memory corruption and errors like this: + + pcie_iproc_bcma bcma0:8: resource collision: [mem 0x40000000-0x47ffffff] conflicts with PCIe MEM space [mem 0x40000000-0x47ffffff] + +Move the memory window resource from the stack into struct iproc_pcie so +its lifetime matches that of the host bridge. + +Fixes: c3245a566400 ("PCI: iproc: Request host bridge window resources") +Reported-and-tested-by: Rafał Miłecki <zajec5@gmail.com> +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +CC: stable@vger.kernel.org # v4.8+ +--- + drivers/pci/host/pcie-iproc-bcma.c | 24 ++++++++++++------------ + drivers/pci/host/pcie-iproc-platform.c | 19 ++++++++++--------- + drivers/pci/host/pcie-iproc.h | 1 + + 3 files changed, 23 insertions(+), 21 deletions(-) + +--- a/drivers/pci/host/pcie-iproc-bcma.c ++++ b/drivers/pci/host/pcie-iproc-bcma.c +@@ -44,8 +44,7 @@ static int iproc_pcie_bcma_probe(struct + { + struct device *dev = &bdev->dev; + struct iproc_pcie *pcie; +- LIST_HEAD(res); +- struct resource res_mem; ++ LIST_HEAD(resources); + int ret; + + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); +@@ -62,22 +61,23 @@ static int iproc_pcie_bcma_probe(struct + + pcie->base_addr = bdev->addr; + +- res_mem.start = bdev->addr_s[0]; +- res_mem.end = bdev->addr_s[0] + SZ_128M - 1; +- res_mem.name = "PCIe MEM space"; +- res_mem.flags = IORESOURCE_MEM; +- pci_add_resource(&res, &res_mem); ++ pcie->mem.start = bdev->addr_s[0]; ++ pcie->mem.end = bdev->addr_s[0] + SZ_128M - 1; ++ pcie->mem.name = "PCIe MEM space"; ++ pcie->mem.flags = IORESOURCE_MEM; ++ pci_add_resource(&resources, &pcie->mem); + + pcie->map_irq = iproc_pcie_bcma_map_irq; + +- ret = iproc_pcie_setup(pcie, &res); +- if (ret) ++ ret = iproc_pcie_setup(pcie, &resources); ++ if (ret) { + dev_err(dev, "PCIe controller setup failed\n"); +- +- pci_free_resource_list(&res); ++ pci_free_resource_list(&resources); ++ return ret; ++ } + + bcma_set_drvdata(bdev, pcie); +- return ret; ++ return 0; + } + + static void iproc_pcie_bcma_remove(struct bcma_device *bdev) +--- a/drivers/pci/host/pcie-iproc-platform.c ++++ b/drivers/pci/host/pcie-iproc-platform.c +@@ -46,7 +46,7 @@ static int iproc_pcie_pltfm_probe(struct + struct device_node *np = dev->of_node; + struct resource reg; + resource_size_t iobase = 0; +- LIST_HEAD(res); ++ LIST_HEAD(resources); + int ret; + + of_id = of_match_device(iproc_pcie_of_match_table, dev); +@@ -108,23 +108,24 @@ static int iproc_pcie_pltfm_probe(struct + pcie->phy = NULL; + } + +- ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &iobase); ++ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &resources, ++ &iobase); + if (ret) { +- dev_err(dev, +- "unable to get PCI host bridge resources\n"); ++ dev_err(dev, "unable to get PCI host bridge resources\n"); + return ret; + } + + pcie->map_irq = of_irq_parse_and_map_pci; + +- ret = iproc_pcie_setup(pcie, &res); +- if (ret) ++ ret = iproc_pcie_setup(pcie, &resources); ++ if (ret) { + dev_err(dev, "PCIe controller setup failed\n"); +- +- pci_free_resource_list(&res); ++ pci_free_resource_list(&resources); ++ return ret; ++ } + + platform_set_drvdata(pdev, pcie); +- return ret; ++ return 0; + } + + static int iproc_pcie_pltfm_remove(struct platform_device *pdev) +--- a/drivers/pci/host/pcie-iproc.h ++++ b/drivers/pci/host/pcie-iproc.h +@@ -68,6 +68,7 @@ struct iproc_pcie { + #ifdef CONFIG_ARM + struct pci_sys_data sysdata; + #endif ++ struct resource mem; + struct pci_bus *root_bus; + struct phy *phy; + int (*map_irq)(const struct pci_dev *, u8, u8); |