diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 8f05475dfc2e..869a39107a81 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -918,6 +918,20 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) atu.parent_bus_addr = entry->res->start - pci->parent_bus_offset; atu.pci_addr = entry->res->start - entry->offset; + if (pp->bypass_ob_mem_iatu) { + /* + * The no-match pass-through path preserves the correct + * PCI address only for identity-mapped MEM ranges. + */ + if (atu.parent_bus_addr != atu.pci_addr) { + dev_err(pci->dev, + "Cannot bypass outbound iATU for non-identity MEM range %pr\n", + entry->res); + return -EINVAL; + } + continue; + } + /* Adjust iATU size if MSG TLP region was allocated before */ if (pp->msg_res && pp->msg_res->parent == entry->res) res_size = resource_size(entry->res) - @@ -964,8 +978,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) ret = dw_pcie_prog_outbound_atu(pci, &atu); if (ret) { - dev_err(pci->dev, "Failed to set IO range %pr\n", - entry->res); + dev_err(pci->dev, "Failed to set IO range\n"); return ret; } ob_iatu_index++; diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 1b298639165d..6d788aa00011 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -467,6 +467,7 @@ struct dw_pcie_rp { struct pci_config_window *cfg; bool ecam_enabled; bool native_ecam; + bool bypass_ob_mem_iatu; bool skip_l23_ready; bool skip_pwrctrl_off; /* Set if the RC loses power during suspend */ diff --git a/drivers/pci/controller/dwc/pcie-ultrarisc.c b/drivers/pci/controller/dwc/pcie-ultrarisc.c index a0d328c0c09b..523f454c6c52 100644 --- a/drivers/pci/controller/dwc/pcie-ultrarisc.c +++ b/drivers/pci/controller/dwc/pcie-ultrarisc.c @@ -154,6 +154,12 @@ static int ultrarisc_pcie_probe(struct platform_device *pdev) pp = &pci->pp; + /* + * DP1000 routes MEM transactions without outbound iATU windows, which + * avoids the 16-window/4GB-per-window aperture limit. + */ + pp->bypass_ob_mem_iatu = true; + platform_set_drvdata(pdev, ultra); ret = ultrarisc_pcie_init_clks(ultra);