From db047f8a931275e50563dd79c3d62d977074959a Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 15 Aug 2016 17:50:41 +0100 Subject: [PATCH 1/6] PCI: aardvark: 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 bridge's 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 aardvark 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: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas CC: Thomas Petazzoni --- drivers/pci/host/pci-aardvark.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/host/pci-aardvark.c index ef9893fa3176..4f5e567fd7e0 100644 --- a/drivers/pci/host/pci-aardvark.c +++ b/drivers/pci/host/pci-aardvark.c @@ -848,7 +848,7 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) int err, res_valid = 0; struct device *dev = &pcie->pdev->dev; struct device_node *np = dev->of_node; - struct resource_entry *win; + struct resource_entry *win, *tmp; resource_size_t iobase; INIT_LIST_HEAD(&pcie->resources); @@ -862,7 +862,7 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) if (err) goto out_release_res; - resource_list_for_each_entry(win, &pcie->resources) { + resource_list_for_each_entry_safe(win, tmp, &pcie->resources) { struct resource *res = win->res; switch (resource_type(res)) { @@ -874,9 +874,11 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) lower_32_bits(res->start), OB_PCIE_IO); err = pci_remap_iospace(res, iobase); - if (err) + if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); + resource_list_destroy_entry(win); + } break; case IORESOURCE_MEM: advk_pcie_set_ob_win(pcie, 0, From bcd7b7186fcba434e7486648de85cf93a56c845c Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 15 Aug 2016 17:50:42 +0100 Subject: [PATCH 2/6] 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 Signed-off-by: Bjorn Helgaas CC: Jingoo Han CC: Pratyush Anand --- drivers/pci/host/pcie-designware.c | 21 ++++++++++++--------- 1 file 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) struct resource *cfg_res; int i, ret; LIST_HEAD(res); - struct resource_entry *win; + struct resource_entry *win, *tmp; cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); if (cfg_res) { @@ -457,17 +457,20 @@ int dw_pcie_host_init(struct pcie_port *pp) goto error; /* Get the I/O and memory ranges from DT */ - resource_list_for_each_entry(win, &res) { + resource_list_for_each_entry_safe(win, tmp, &res) { switch (resource_type(win->res)) { case IORESOURCE_IO: - pp->io = win->res; - pp->io->name = "I/O"; - pp->io_size = resource_size(pp->io); - pp->io_bus_addr = pp->io->start - win->offset; - ret = pci_remap_iospace(pp->io, pp->io_base); - if (ret) + ret = pci_remap_iospace(win->res, pp->io_base); + if (ret) { dev_warn(pp->dev, "error %d: failed to map resource %pR\n", - ret, pp->io); + ret, win->res); + resource_list_destroy_entry(win); + } else { + pp->io = win->res; + pp->io->name = "I/O"; + pp->io_size = resource_size(pp->io); + pp->io_bus_addr = pp->io->start - win->offset; + } break; case IORESOURCE_MEM: pp->mem = win->res; From 53f4f7ee28076a36e427274d7d5c33b23dfc6221 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 15 Aug 2016 17:50:43 +0100 Subject: [PATCH 3/6] PCI: versatile: 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 versatile 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: b7e78170efd4 ("PCI: versatile: Add DT-based ARM Versatile PB PCIe host driver") Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas CC: Rob Herring --- drivers/pci/host/pci-versatile.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c index f234405770ab..b7dc07002f13 100644 --- a/drivers/pci/host/pci-versatile.c +++ b/drivers/pci/host/pci-versatile.c @@ -74,7 +74,7 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, int err, mem = 1, res_valid = 0; struct device_node *np = dev->of_node; resource_size_t iobase; - struct resource_entry *win; + struct resource_entry *win, *tmp; err = of_pci_get_host_bridge_resources(np, 0, 0xff, res, &iobase); if (err) @@ -84,15 +84,17 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, if (err) goto out_release_res; - resource_list_for_each_entry(win, res) { + resource_list_for_each_entry_safe(win, tmp, res) { struct resource *res = win->res; switch (resource_type(res)) { case IORESOURCE_IO: err = pci_remap_iospace(res, iobase); - if (err) + if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); + resource_list_destroy_entry(win); + } break; case IORESOURCE_MEM: res_valid |= !(res->flags & IORESOURCE_PREFETCH); From 5e8c873270cc618e3326eb6a47437b517ef85c52 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 15 Aug 2016 17:50:44 +0100 Subject: [PATCH 4/6] PCI: rcar: 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 rcar 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: 5d2917d469fa ("PCI: rcar: Convert to DT resource parsing API") Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas CC: Phil Edworthy CC: Simon Horman --- drivers/pci/host/pcie-rcar.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 65db7a221509..5f7fcc971cae 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -945,7 +945,7 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) struct device *dev = pci->dev; struct device_node *np = dev->of_node; resource_size_t iobase; - struct resource_entry *win; + struct resource_entry *win, *tmp; err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase); if (err) @@ -955,14 +955,17 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) if (err) goto out_release_res; - resource_list_for_each_entry(win, &pci->resources) { + resource_list_for_each_entry_safe(win, tmp, &pci->resources) { struct resource *res = win->res; if (resource_type(res) == IORESOURCE_IO) { err = pci_remap_iospace(res, iobase); - if (err) + if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); + + resource_list_destroy_entry(win); + } } } From 43281ede019ede33fd0c40a14a86b304a51e4555 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 15 Aug 2016 17:50:45 +0100 Subject: [PATCH 5/6] PCI: generic: 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 common 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: 4e64dbe226e7 ("PCI: generic: Expose pci_host_common_probe() for use by other drivers") Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas Acked-by: Will Deacon --- drivers/pci/host/pci-host-common.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c index 9d9d34e959b6..61eb4d46eb50 100644 --- a/drivers/pci/host/pci-host-common.c +++ b/drivers/pci/host/pci-host-common.c @@ -29,7 +29,7 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, int err, res_valid = 0; struct device_node *np = dev->of_node; resource_size_t iobase; - struct resource_entry *win; + struct resource_entry *win, *tmp; err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase); if (err) @@ -39,15 +39,17 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, if (err) return err; - resource_list_for_each_entry(win, resources) { + resource_list_for_each_entry_safe(win, tmp, resources) { struct resource *res = win->res; switch (resource_type(res)) { case IORESOURCE_IO: err = pci_remap_iospace(res, iobase); - if (err) + if (err) { dev_warn(dev, "error %d: failed to map resource %pR\n", err, res); + resource_list_destroy_entry(win); + } break; case IORESOURCE_MEM: res_valid |= !(res->flags & IORESOURCE_PREFETCH); From 13f392ebc37e31568fae72a73ee378ae22a9740f Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 15 Aug 2016 17:50:46 +0100 Subject: [PATCH 6/6] PCI: tegra: 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 tegra host bridge driver adds the PCI IO resource retrieved from firmware to the host bridge resource windows even 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). Add the PCI host bridge driver pci_remap_iospace() failure path and do not add the corresponding PCI host bridge PCI IO resources retrieved through firmware when the pci_remap_iospace() function call fails, fixing the issue. Fixes: e6e9f471f5fe ("PCI: tegra: Use generic pci_remap_iospace() rather than ARM32-specific one") Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas CC: Thierry Reding --- drivers/pci/host/pci-tegra.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 6de0757b11e4..8c2590db609b 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -621,7 +621,11 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) if (err < 0) return err; - pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset); + err = pci_remap_iospace(&pcie->pio, pcie->io.start); + if (!err) + pci_add_resource_offset(&sys->resources, &pcie->pio, + sys->io_offset); + pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); pci_add_resource_offset(&sys->resources, &pcie->prefetch, sys->mem_offset); @@ -631,7 +635,6 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) if (err < 0) return err; - pci_remap_iospace(&pcie->pio, pcie->io.start); return 1; }