aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2016-08-15 12:50:42 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-09-06 13:39:38 -0400
commitbcd7b7186fcba434e7486648de85cf93a56c845c (patch)
tree1e4d11f6c592af639646dc84f211243c1fb97b75
parentdb047f8a931275e50563dd79c3d62d977074959a (diff)
PCI: designware: Fix pci_remap_iospace() failure path
On ARM/ARM64 architectures, PCI IO ports are emulated through memory mapped IO, by reserving a chunk of virtual address space starting at PCI_IOBASE and by mapping the PCI host bridges memory address space driving PCI IO cycles to it. PCI host bridge drivers that enable downstream PCI IO cycles map the host bridge memory address responding to PCI IO cycles to the fixed virtual address space through the pci_remap_iospace() API. This means that if the pci_remap_iospace() function fails, the corresponding host bridge PCI IO resource must be considered invalid, in that there is no way for the kernel to actually drive PCI IO transactions if the memory addresses responding to PCI IO cycles cannot be mapped into the CPU virtual address space. The PCI designware host bridge driver does not remove the PCI IO resource from the host bridge resource windows if the pci_remap_iospace() call fails; this is an actual bug in that the PCI host bridge would consider the PCI IO resource valid (and possibly assign it to downstream devices) even if the kernel was not able to map the PCI host bridge memory address driving IO cycle to the CPU virtual address space (ie pci_remap_iospace() failures). Fix the PCI host bridge driver pci_remap_iospace() failure path, by destroying the PCI host bridge PCI IO resources retrieved through firmware when the pci_remap_iospace() function call fails, therefore preventing the kernel from adding the respective PCI IO resource to the list of PCI host bridge valid resources, fixing the issue. Fixes: cbce7900598c ("PCI: designware: Make driver arch-agnostic") Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> CC: Jingoo Han <jingoohan1@gmail.com> CC: Pratyush Anand <pratyush.anand@gmail.com>
-rw-r--r--drivers/pci/host/pcie-designware.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 12afce19890b..2a500f270c01 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -436,7 +436,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
436 struct resource *cfg_res; 436 struct resource *cfg_res;
437 int i, ret; 437 int i, ret;
438 LIST_HEAD(res); 438 LIST_HEAD(res);
439 struct resource_entry *win; 439 struct resource_entry *win, *tmp;
440 440
441 cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); 441 cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
442 if (cfg_res) { 442 if (cfg_res) {
@@ -457,17 +457,20 @@ int dw_pcie_host_init(struct pcie_port *pp)
457 goto error; 457 goto error;
458 458
459 /* Get the I/O and memory ranges from DT */ 459 /* Get the I/O and memory ranges from DT */
460 resource_list_for_each_entry(win, &res) { 460 resource_list_for_each_entry_safe(win, tmp, &res) {
461 switch (resource_type(win->res)) { 461 switch (resource_type(win->res)) {
462 case IORESOURCE_IO: 462 case IORESOURCE_IO:
463 pp->io = win->res; 463 ret = pci_remap_iospace(win->res, pp->io_base);
464 pp->io->name = "I/O"; 464 if (ret) {
465 pp->io_size = resource_size(pp->io);
466 pp->io_bus_addr = pp->io->start - win->offset;
467 ret = pci_remap_iospace(pp->io, pp->io_base);
468 if (ret)
469 dev_warn(pp->dev, "error %d: failed to map resource %pR\n", 465 dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
470 ret, pp->io); 466 ret, win->res);
467 resource_list_destroy_entry(win);
468 } else {
469 pp->io = win->res;
470 pp->io->name = "I/O";
471 pp->io_size = resource_size(pp->io);
472 pp->io_bus_addr = pp->io->start - win->offset;
473 }
471 break; 474 break;
472 case IORESOURCE_MEM: 475 case IORESOURCE_MEM:
473 pp->mem = win->res; 476 pp->mem = win->res;