Commit d4562267 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pci-v4.11-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI fixes from Bjorn Helgaas:

 - fix iProc memory corruption

 - fix ThunderX usage of unregistered PNP/ACPI ID

 - fix ThunderX resource reservation on early firmware

* tag 'pci-v4.11-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  PCI: thunder-pem: Add legacy firmware support for Cavium ThunderX host controller
  PCI: thunder-pem: Use Cavium assigned hardware ID for ThunderX host controller
  PCI: iproc: Save host bridge window resource in struct iproc_pcie
parents 89970a04 9abb27c7
......@@ -14,6 +14,7 @@
* Copyright (C) 2015 - 2016 Cavium, Inc.
*/
#include <linux/bitfield.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/of_address.h>
......@@ -334,6 +335,50 @@ static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg,
#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
#define PEM_RES_BASE 0x87e0c0000000UL
#define PEM_NODE_MASK GENMASK(45, 44)
#define PEM_INDX_MASK GENMASK(26, 24)
#define PEM_MIN_DOM_IN_NODE 4
#define PEM_MAX_DOM_IN_NODE 10
static void thunder_pem_reserve_range(struct device *dev, int seg,
struct resource *r)
{
resource_size_t start = r->start, end = r->end;
struct resource *res;
const char *regionid;
regionid = kasprintf(GFP_KERNEL, "PEM RC:%d", seg);
if (!regionid)
return;
res = request_mem_region(start, end - start + 1, regionid);
if (res)
res->flags &= ~IORESOURCE_BUSY;
else
kfree(regionid);
dev_info(dev, "%pR %s reserved\n", r,
res ? "has been" : "could not be");
}
static void thunder_pem_legacy_fw(struct acpi_pci_root *root,
struct resource *res_pem)
{
int node = acpi_get_node(root->device->handle);
int index;
if (node == NUMA_NO_NODE)
node = 0;
index = root->segment - PEM_MIN_DOM_IN_NODE;
index -= node * PEM_MAX_DOM_IN_NODE;
res_pem->start = PEM_RES_BASE | FIELD_PREP(PEM_NODE_MASK, node) |
FIELD_PREP(PEM_INDX_MASK, index);
res_pem->end = res_pem->start + SZ_16M - 1;
res_pem->flags = IORESOURCE_MEM;
}
static int thunder_pem_acpi_init(struct pci_config_window *cfg)
{
struct device *dev = cfg->parent;
......@@ -346,10 +391,17 @@ static int thunder_pem_acpi_init(struct pci_config_window *cfg)
if (!res_pem)
return -ENOMEM;
ret = acpi_get_rc_resources(dev, "THRX0002", root->segment, res_pem);
ret = acpi_get_rc_resources(dev, "CAVA02B", root->segment, res_pem);
/*
* If we fail to gather resources it means that we run with old
* FW where we need to calculate PEM-specific resources manually.
*/
if (ret) {
dev_err(dev, "can't get rc base address\n");
return ret;
thunder_pem_legacy_fw(root, res_pem);
/* Reserve PEM-specific resources and PCI configuration space */
thunder_pem_reserve_range(dev, root->segment, res_pem);
thunder_pem_reserve_range(dev, root->segment, &cfg->res);
}
return thunder_pem_init(dev, cfg, res_pem);
......
......@@ -44,8 +44,7 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev)
{
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);
......@@ -63,22 +62,23 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev)
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)
......
......@@ -51,7 +51,7 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
struct resource reg;
resource_size_t iobase = 0;
LIST_HEAD(res);
LIST_HEAD(resources);
int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
......@@ -96,10 +96,10 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
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;
}
......@@ -112,14 +112,15 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
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)
......
......@@ -90,6 +90,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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment