From 462b58fb033996e999cc213ed0b430d4f22a28fe Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Wed, 28 Oct 2020 16:15:45 -0700 Subject: PCI: Always enable ACS even if no ACS Capability Some devices support ACS functionality even though they don't have a spec-compliant ACS Capability; pci_enable_acs() has a quirk mechanism to handle them. We want to enable ACS whenever possible, but 52fbf5bdeeef ("PCI: Cache ACS capability offset in device") inadvertently broke this by calling pci_enable_acs() only if we find an ACS Capability. This resulted in ACS not being enabled for these non-compliant devices, which means devices can't be separated into different IOMMU groups, which in turn means we may not be able to pass those devices through to VMs, as reported by Boris V: https://lore.kernel.org/r/74aeea93-8a46-5f5a-343c-790d4c655da3@bstnet.org Fixes: 52fbf5bdeeef ("PCI: Cache ACS capability offset in device") Link: https://lore.kernel.org/r/20201028231545.4116866-1-rajatja@google.com Reported-by: Boris V Signed-off-by: Rajat Jain Signed-off-by: Bjorn Helgaas Reviewed-by: Alex Williamson --- drivers/pci/pci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6d4d5a2f923d..e578d34095e9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3516,8 +3516,13 @@ void pci_acs_init(struct pci_dev *dev) { dev->acs_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); - if (dev->acs_cap) - pci_enable_acs(dev); + /* + * Attempt to enable ACS regardless of capability because some Root + * Ports (e.g. those quirked with *_intel_pch_acs_*) do not have + * the standard ACS capability but still support ACS via those + * quirks. + */ + pci_enable_acs(dev); } /** -- cgit v1.2.3 From 9fff3256f93da6eb2b806eeaec8c1dc6e9a87194 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 26 Oct 2020 10:48:52 -0500 Subject: PCI: dwc: Restore ATU memory resource setup to use last entry Prior to commit 0f71c60ffd26 ("PCI: dwc: Remove storing of PCI resources"), the DWC driver was setting up the last memory resource rather than the first memory resource. This doesn't matter for most platforms which only have 1 memory resource, but it broke Tegra194 which has a 2nd (prefetchable) memory region that requires an ATU entry. The first region on Tegra194 relies on the default 1:1 pass-thru of outbound transactions and doesn't need an ATU entry. Fixes: 0f71c60ffd26 ("PCI: dwc: Remove storing of PCI resources") Link: https://lore.kernel.org/r/20201026154852.221483-1-robh@kernel.org Reported-by: Vidya Sagar Signed-off-by: Rob Herring Signed-off-by: Bjorn Helgaas Acked-by: Lorenzo Pieralisi Acked-by: Jingoo Han Cc: Gustavo Pimentel --- drivers/pci/controller/dwc/pcie-designware-host.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 674f32db85ca..44c2a6572199 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -586,8 +586,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp) * ATU, so we should not program the ATU here. */ if (pp->bridge->child_ops == &dw_child_pcie_ops) { - struct resource_entry *entry = - resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM); + struct resource_entry *tmp, *entry = NULL; + + /* Get last memory resource entry */ + resource_list_for_each_entry(tmp, &pp->bridge->windows) + if (resource_type(tmp->res) == IORESOURCE_MEM) + entry = tmp; dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0, PCIE_ATU_TYPE_MEM, entry->res->start, -- cgit v1.2.3 From 832ea234277a2465ec6602fa6a4db5cd9ee87ae3 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 23 Oct 2020 09:52:52 -0500 Subject: PCI: mvebu: Fix duplicate resource requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With commit 669cbc708122 ("PCI: Move DT resource setup into devm_pci_alloc_host_bridge()"), the DT 'ranges' is parsed and populated into resources when the host bridge is allocated. The resources are requested as well, but that happens a second time for the mvebu driver in mvebu_pcie_parse_request_resources(). We should only be requesting the additional resources added in mvebu_pcie_parse_request_resources(). These are not added by default because they use custom properties rather than standard DT address translation. Also, the bus ranges was also populated by default, so we can remove it from mvebu_pci_host_probe(). Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=209729 Fixes: 669cbc708122 ("PCI: Move DT resource setup into devm_pci_alloc_host_bridge()") Link: https://lore.kernel.org/r/20201023145252.2691779-1-robh@kernel.org Reported-by: vtolkm@googlemail.com Tested-by: Jan Kundrát Signed-off-by: Rob Herring Signed-off-by: Bjorn Helgaas Acked-by: Lorenzo Pieralisi Cc: Thomas Petazzoni Cc: Jason Cooper Cc: Russell King --- drivers/pci/controller/pci-mvebu.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c index eee82838f4ba..ed13e81cd691 100644 --- a/drivers/pci/controller/pci-mvebu.c +++ b/drivers/pci/controller/pci-mvebu.c @@ -958,25 +958,16 @@ static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port) } /* - * We can't use devm_of_pci_get_host_bridge_resources() because we - * need to parse our special DT properties encoding the MEM and IO - * apertures. + * devm_of_pci_get_host_bridge_resources() only sets up translateable resources, + * so we need extra resource setup parsing our special DT properties encoding + * the MEM and IO apertures. */ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) { struct device *dev = &pcie->pdev->dev; - struct device_node *np = dev->of_node; struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); int ret; - /* Get the bus range */ - ret = of_pci_parse_bus_range(np, &pcie->busn); - if (ret) { - dev_err(dev, "failed to parse bus-range property: %d\n", ret); - return ret; - } - pci_add_resource(&bridge->windows, &pcie->busn); - /* Get the PCIe memory aperture */ mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); if (resource_size(&pcie->mem) == 0) { @@ -986,6 +977,9 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) pcie->mem.name = "PCI MEM"; pci_add_resource(&bridge->windows, &pcie->mem); + ret = devm_request_resource(dev, &iomem_resource, &pcie->mem); + if (ret) + return ret; /* Get the PCIe IO aperture */ mvebu_mbus_get_pcie_io_aperture(&pcie->io); @@ -999,9 +993,12 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) pcie->realio.name = "PCI I/O"; pci_add_resource(&bridge->windows, &pcie->realio); + ret = devm_request_resource(dev, &ioport_resource, &pcie->realio); + if (ret) + return ret; } - return devm_request_pci_bus_resources(dev, &bridge->windows); + return 0; } /* -- cgit v1.2.3