aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/host/pci-tegra.c
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-08-01 08:15:11 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-09-04 16:49:26 -0400
commit41534e53786df49b708c1e06f5d6ef9b53fbb689 (patch)
treebe4a816b4887ea8e9d54257ce208c1813e8f9660 /drivers/pci/host/pci-tegra.c
parent019fa46ebc93c654da1b29f472a66b3bf7880464 (diff)
PCI: tegra: Implement a proper resource hierarchy
Currently the resource hierarchy generated from the PCIe host bridge is completely flat: $ cat /proc/iomem 00000000-00000fff : /pcie-controller@00003000/pci@1,0 00003000-000037ff : pads 00003800-000039ff : afi 10000000-1fffffff : cs 28000000-28003fff : r8169 28004000-28004fff : r8169 ... The host bridge driver doesn't request all the resources that are used. Windows allocated to each of the root ports aren't tracked, so there is no way for resources allocated to individual devices to be matched up with the correct parent resource by the PCI core. This patch addresses this in two steps. It first takes the union of all regions associated with the PCIe host bridge (control registers, root port registers, configuration space, I/O and prefetchable as well as non- prefetchable memory regions) and uses it as the new root of the resource hierarchy. Subsequently, regions are allocated from within this new root resource so that the resource tree looks much more like what's expected: # cat /proc/iomem 00000000-3fffffff : /pcie-controller@00003000 00000000-00000fff : /pcie-controller@00003000/pci@1,0 00003000-000037ff : pads 00003800-000039ff : afi 10000000-1fffffff : cs 20000000-27ffffff : non-prefetchable 28000000-3fffffff : prefetchable 28000000-280fffff : PCI Bus 0000:01 28000000-28003fff : 0000:01:00.0 28000000-28003fff : r8169 28004000-28004fff : 0000:01:00.0 28004000-28004fff : r8169 ... Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/host/pci-tegra.c')
-rw-r--r--drivers/pci/host/pci-tegra.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 5fbf31e02c77..7be31f58a4e6 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -253,6 +253,7 @@ struct tegra_pcie {
253 struct list_head buses; 253 struct list_head buses;
254 struct resource *cs; 254 struct resource *cs;
255 255
256 struct resource all;
256 struct resource io; 257 struct resource io;
257 struct resource mem; 258 struct resource mem;
258 struct resource prefetch; 259 struct resource prefetch;
@@ -626,6 +627,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
626static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) 627static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
627{ 628{
628 struct tegra_pcie *pcie = sys_to_pcie(sys); 629 struct tegra_pcie *pcie = sys_to_pcie(sys);
630 int err;
631
632 err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem);
633 if (err < 0)
634 return err;
635
636 err = devm_request_resource(pcie->dev, &pcie->all, &pcie->prefetch);
637 if (err)
638 return err;
629 639
630 pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); 640 pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
631 pci_add_resource_offset(&sys->resources, &pcie->prefetch, 641 pci_add_resource_offset(&sys->resources, &pcie->prefetch,
@@ -1518,6 +1528,12 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
1518 struct resource res; 1528 struct resource res;
1519 int err; 1529 int err;
1520 1530
1531 memset(&pcie->all, 0, sizeof(pcie->all));
1532 pcie->all.flags = IORESOURCE_MEM;
1533 pcie->all.name = np->full_name;
1534 pcie->all.start = ~0;
1535 pcie->all.end = 0;
1536
1521 if (of_pci_range_parser_init(&parser, np)) { 1537 if (of_pci_range_parser_init(&parser, np)) {
1522 dev_err(pcie->dev, "missing \"ranges\" property\n"); 1538 dev_err(pcie->dev, "missing \"ranges\" property\n");
1523 return -EINVAL; 1539 return -EINVAL;
@@ -1529,21 +1545,31 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
1529 switch (res.flags & IORESOURCE_TYPE_BITS) { 1545 switch (res.flags & IORESOURCE_TYPE_BITS) {
1530 case IORESOURCE_IO: 1546 case IORESOURCE_IO:
1531 memcpy(&pcie->io, &res, sizeof(res)); 1547 memcpy(&pcie->io, &res, sizeof(res));
1532 pcie->io.name = "I/O"; 1548 pcie->io.name = np->full_name;
1533 break; 1549 break;
1534 1550
1535 case IORESOURCE_MEM: 1551 case IORESOURCE_MEM:
1536 if (res.flags & IORESOURCE_PREFETCH) { 1552 if (res.flags & IORESOURCE_PREFETCH) {
1537 memcpy(&pcie->prefetch, &res, sizeof(res)); 1553 memcpy(&pcie->prefetch, &res, sizeof(res));
1538 pcie->prefetch.name = "PREFETCH"; 1554 pcie->prefetch.name = "prefetchable";
1539 } else { 1555 } else {
1540 memcpy(&pcie->mem, &res, sizeof(res)); 1556 memcpy(&pcie->mem, &res, sizeof(res));
1541 pcie->mem.name = "MEM"; 1557 pcie->mem.name = "non-prefetchable";
1542 } 1558 }
1543 break; 1559 break;
1544 } 1560 }
1561
1562 if (res.start <= pcie->all.start)
1563 pcie->all.start = res.start;
1564
1565 if (res.end >= pcie->all.end)
1566 pcie->all.end = res.end;
1545 } 1567 }
1546 1568
1569 err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->all);
1570 if (err < 0)
1571 return err;
1572
1547 err = of_pci_parse_bus_range(np, &pcie->busn); 1573 err = of_pci_parse_bus_range(np, &pcie->busn);
1548 if (err < 0) { 1574 if (err < 0) {
1549 dev_err(pcie->dev, "failed to parse ranges property: %d\n", 1575 dev_err(pcie->dev, "failed to parse ranges property: %d\n",