| From db047f8a931275e50563dd79c3d62d977074959a Mon Sep 17 00:00:00 2001 |
| From: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| Date: Mon, 15 Aug 2016 17:50:41 +0100 |
| Subject: PCI: aardvark: Fix pci_remap_iospace() failure path |
| |
| From: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| |
| commit db047f8a931275e50563dd79c3d62d977074959a upstream. |
| |
| 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 <lorenzo.pieralisi@arm.com> |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| CC: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/pci/host/pci-aardvark.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| --- 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_pc |
| 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_pc |
| 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_pc |
| 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, |