From nobody Sun Feb 8 00:03:45 2026 Received: from Atcsqr.andestech.com (60-248-80-70.hinet-ip.hinet.net [60.248.80.70]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7BFF2334C24 for ; Fri, 9 Jan 2026 11:34:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=60.248.80.70 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767958500; cv=none; b=oUNftZ/t2nnBJ1Xel7E+t9Y+ihMWAc2NTKVCE5dzWA9m2+EVCZXxLIlkw92ihNo06kf2Eym4zcJCN/DQFreyhcpGxPivimlwgWeJThHqys9MkAnVPJUxMCRx1HeLEF+tLS7G1yKtChSgYf6e/4dGREom2u1zBDJZDb2xbNjre7I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767958500; c=relaxed/simple; bh=Uhlkk3LVxRsNvWI7huS9pzK+/qSKKm9V9GgFmplCnCA=; h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; b=t5/g6e5v5BhJo3+lC3zq3QyoXqyKHZ8mDK1Kwi/V4pzOQoElQTv9GjAY5GhFS69PJ82oXxsX3H48bG20lVzcafGqRb4b9HqxqvhtqSbfB16Y6ysdg3Ckll817G5fig3c2VYt5RjR4AKp9Anjjy0Bd4PjKxp6wHbcIBXWQJhdqrU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=permerror header.from=andestech.com; spf=pass smtp.mailfrom=andestech.com; arc=none smtp.client-ip=60.248.80.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=permerror header.from=andestech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=andestech.com Received: from mail.andestech.com (ATCPCS34.andestech.com [10.0.1.134]) by Atcsqr.andestech.com with ESMTPS id 609BYdaA080471 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=OK); Fri, 9 Jan 2026 19:34:39 +0800 (+08) (envelope-from randolph@andestech.com) Received: from swlinux02.andestech.com (10.0.15.183) by ATCPCS34.andestech.com (10.0.1.134) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 9 Jan 2026 19:34:39 +0800 From: Randolph To: CC: , , , , , , , , , , , , Randolph Lin Subject: [PATCH v2] PCI: dwc: Use multiple ATU regions for large bridge windows Date: Fri, 9 Jan 2026 19:34:30 +0800 Message-ID: <20260109113430.2767264-1-randolph@andestech.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: ATCPCS33.andestech.com (10.0.1.100) To ATCPCS34.andestech.com (10.0.1.134) X-DKIM-Results: atcpcs34.andestech.com; dkim=none; X-DNSRBL: X-SPAM-SOURCE-CHECK: pass X-MAIL: Atcsqr.andestech.com 609BYdaA080471 Content-Type: text/plain; charset="utf-8" From: Samuel Holland Some SoCs may allocate more address space for a bridge window than can be covered by a single ATU region. Allow using a larger bridge window by allocating multiple adjacent ATU regions. Signed-off-by: Samuel Holland Reviewed-by: Frank Li Acked-by: Charles Mirabile Signed-off-by: Charles Mirabile Co-developed-by: Randolph Lin Signed-off-by: Randolph Lin Reviewed-by: Niklas Cassel --- Since our changes depend on the original patch and no updated revision has been posted by the original author, we reached out to Samuel Holland directly and received his approval.I have consolidated the required changes and am resending them as v2. --- .../pci/controller/dwc/pcie-designware-host.c | 72 ++++++++++++++----- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pc= i/controller/dwc/pcie-designware-host.c index 372207c33a85..771e71b40f76 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -903,29 +903,49 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) =20 i =3D 0; resource_list_for_each_entry(entry, &pp->bridge->windows) { + resource_size_t res_size; + if (resource_type(entry->res) !=3D IORESOURCE_MEM) continue; =20 - if (pci->num_ob_windows <=3D ++i) + if (pci->num_ob_windows <=3D i + 1) break; =20 - atu.index =3D i; atu.type =3D PCIE_ATU_TYPE_MEM; atu.parent_bus_addr =3D entry->res->start - pci->parent_bus_offset; atu.pci_addr =3D entry->res->start - entry->offset; =20 /* Adjust iATU size if MSG TLP region was allocated before */ if (pp->msg_res && pp->msg_res->parent =3D=3D entry->res) - atu.size =3D resource_size(entry->res) - + res_size =3D resource_size(entry->res) - resource_size(pp->msg_res); else - atu.size =3D resource_size(entry->res); + res_size =3D resource_size(entry->res); + + while (res_size > 0) { + /* + * Make sure to fail probe if we run out of windows + * in the middle and we would end up only partially + * mapping a single resource + */ + if (pci->num_ob_windows <=3D ++i) { + dev_err(pci->dev, "Exhausted outbound windows mapping %pr\n", + entry->res); + return -ENOMEM; + } + atu.index =3D i; + atu.size =3D MIN(pci->region_limit + 1, res_size); =20 - ret =3D dw_pcie_prog_outbound_atu(pci, &atu); - if (ret) { - dev_err(pci->dev, "Failed to set MEM range %pr\n", - entry->res); - return ret; + ret =3D dw_pcie_prog_outbound_atu(pci, &atu); + if (ret) { + dev_err(pci->dev, "Failed to set MEM range %pr\n", + entry->res); + return ret; + } + + atu.parent_bus_addr +=3D atu.size; + atu.pci_addr +=3D atu.size; + res_size -=3D atu.size; } } =20 @@ -956,20 +976,38 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) =20 i =3D 0; resource_list_for_each_entry(entry, &pp->bridge->dma_ranges) { + resource_size_t res_start, res_size, window_size; + if (resource_type(entry->res) !=3D IORESOURCE_MEM) continue; =20 if (pci->num_ib_windows <=3D i) break; =20 - ret =3D dw_pcie_prog_inbound_atu(pci, i++, PCIE_ATU_TYPE_MEM, - entry->res->start, - entry->res->start - entry->offset, - resource_size(entry->res)); - if (ret) { - dev_err(pci->dev, "Failed to set DMA range %pr\n", - entry->res); - return ret; + res_size =3D resource_size(entry->res); + res_start =3D entry->res->start; + while (res_size >=3D 0) { + /* + * Make sure to fail probe if we run out of windows + * in the middle and we would end up only partially + * mapping a single resource + */ + if (pci->num_ib_windows <=3D i) { + dev_err(pci->dev, "Exhausted inbound windows mapping %pr\n", + entry->res); + return -ENOMEM; + } + window_size =3D MIN(pci->region_limit + 1, res_size); + ret =3D dw_pcie_prog_inbound_atu(pci, i++, PCIE_ATU_TYPE_MEM, res_start, + res_start - entry->offset, window_size); + if (ret) { + dev_err(pci->dev, "Failed to set DMA range %pr\n", + entry->res); + return ret; + } + + res_start +=3D window_size; + res_size -=3D window_size; } } =20 --=20 2.34.1