mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-18 21:14:28 +00:00
pci-v4.11-fixes-3
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJY3X6QAAoJEFmIoMA60/r8GXwP/iCy0zUQu6xunEdDJQPIo1vJ JVZFl6e3DiuT5w5SUd0jNzcK6nv4oAM3bS8cLAmhYx0f/7vRAFnW2QhUQO5wQB2i iA4ZIRV/TenSXeCesIUpBeQ6I7cxQPFBY3568Bjb1eueTuvTjvKyB2CgxQiSO7sq 7ZTPTrAjg3LZPPCwfEIMU/XQD8vwMziIx48P+YkMiP5oOGt+8LPvVBNcGyxdDaoG lXDdxPtSB96h0fDGmPtyCs0bRZrbjPSH6Krlmw3UKcGFdYWrxQc5UMNIMF0g7otX u5ZQ5athDumLBhLLXxpPUsmcdKbc+HWhTgERsxfVLQWTPM0oYSQkzrxZBwOt7cfJ LadD4Zmw3/kw28WYrFvb5ZTcZK63UZN+EkTozJT8euus0PW0ySFoWanLQq9G6wM9 hnnRBT5zgKm5wo4XiEkBDJo9Mn6cVWMa/209Rn+tSocGw430oY6RQsATXuujNAjB oVQDGEbHo0/7E/qQO2He+azv2W+Mgpz3Vwma9zfvqd2VqctNxPKHyCsX26mR+NYh E6z90WSF9zpFbxLBJfeFxfKXinX9oE4FneGpGz6LDdr33bESsaEjQiwEYrPd7u8x fBuLw/u/SuLXKcRoyRQwgDoordxc2MVjxwElq41o8RbP2++7oVg+gzIWBIhKn6NP XRr5XC0Mv3HJj+RJy87O =vi64 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
d4562267b9
4 changed files with 78 additions and 24 deletions
|
@ -14,6 +14,7 @@
|
||||||
* Copyright (C) 2015 - 2016 Cavium, Inc.
|
* Copyright (C) 2015 - 2016 Cavium, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of_address.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)
|
#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)
|
static int thunder_pem_acpi_init(struct pci_config_window *cfg)
|
||||||
{
|
{
|
||||||
struct device *dev = cfg->parent;
|
struct device *dev = cfg->parent;
|
||||||
|
@ -346,10 +391,17 @@ static int thunder_pem_acpi_init(struct pci_config_window *cfg)
|
||||||
if (!res_pem)
|
if (!res_pem)
|
||||||
return -ENOMEM;
|
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) {
|
if (ret) {
|
||||||
dev_err(dev, "can't get rc base address\n");
|
thunder_pem_legacy_fw(root, res_pem);
|
||||||
return ret;
|
/* 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);
|
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 device *dev = &bdev->dev;
|
||||||
struct iproc_pcie *pcie;
|
struct iproc_pcie *pcie;
|
||||||
LIST_HEAD(res);
|
LIST_HEAD(resources);
|
||||||
struct resource res_mem;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
|
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;
|
pcie->base_addr = bdev->addr;
|
||||||
|
|
||||||
res_mem.start = bdev->addr_s[0];
|
pcie->mem.start = bdev->addr_s[0];
|
||||||
res_mem.end = bdev->addr_s[0] + SZ_128M - 1;
|
pcie->mem.end = bdev->addr_s[0] + SZ_128M - 1;
|
||||||
res_mem.name = "PCIe MEM space";
|
pcie->mem.name = "PCIe MEM space";
|
||||||
res_mem.flags = IORESOURCE_MEM;
|
pcie->mem.flags = IORESOURCE_MEM;
|
||||||
pci_add_resource(&res, &res_mem);
|
pci_add_resource(&resources, &pcie->mem);
|
||||||
|
|
||||||
pcie->map_irq = iproc_pcie_bcma_map_irq;
|
pcie->map_irq = iproc_pcie_bcma_map_irq;
|
||||||
|
|
||||||
ret = iproc_pcie_setup(pcie, &res);
|
ret = iproc_pcie_setup(pcie, &resources);
|
||||||
if (ret)
|
if (ret) {
|
||||||
dev_err(dev, "PCIe controller setup failed\n");
|
dev_err(dev, "PCIe controller setup failed\n");
|
||||||
|
pci_free_resource_list(&resources);
|
||||||
pci_free_resource_list(&res);
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bcma_set_drvdata(bdev, pcie);
|
bcma_set_drvdata(bdev, pcie);
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iproc_pcie_bcma_remove(struct bcma_device *bdev)
|
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 device_node *np = dev->of_node;
|
||||||
struct resource reg;
|
struct resource reg;
|
||||||
resource_size_t iobase = 0;
|
resource_size_t iobase = 0;
|
||||||
LIST_HEAD(res);
|
LIST_HEAD(resources);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
|
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;
|
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) {
|
if (ret) {
|
||||||
dev_err(dev,
|
dev_err(dev, "unable to get PCI host bridge resources\n");
|
||||||
"unable to get PCI host bridge resources\n");
|
|
||||||
return ret;
|
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;
|
pcie->map_irq = of_irq_parse_and_map_pci;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iproc_pcie_setup(pcie, &res);
|
ret = iproc_pcie_setup(pcie, &resources);
|
||||||
if (ret)
|
if (ret) {
|
||||||
dev_err(dev, "PCIe controller setup failed\n");
|
dev_err(dev, "PCIe controller setup failed\n");
|
||||||
|
pci_free_resource_list(&resources);
|
||||||
pci_free_resource_list(&res);
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, pcie);
|
platform_set_drvdata(pdev, pcie);
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iproc_pcie_pltfm_remove(struct platform_device *pdev)
|
static int iproc_pcie_pltfm_remove(struct platform_device *pdev)
|
||||||
|
|
|
@ -90,6 +90,7 @@ struct iproc_pcie {
|
||||||
#ifdef CONFIG_ARM
|
#ifdef CONFIG_ARM
|
||||||
struct pci_sys_data sysdata;
|
struct pci_sys_data sysdata;
|
||||||
#endif
|
#endif
|
||||||
|
struct resource mem;
|
||||||
struct pci_bus *root_bus;
|
struct pci_bus *root_bus;
|
||||||
struct phy *phy;
|
struct phy *phy;
|
||||||
int (*map_irq)(const struct pci_dev *, u8, u8);
|
int (*map_irq)(const struct pci_dev *, u8, u8);
|
||||||
|
|
Loading…
Add table
Reference in a new issue