From nobody Tue Feb 10 04:13:25 2026 Received: from TY3P286CU002.outbound.protection.outlook.com (mail-japaneastazon11020140.outbound.protection.outlook.com [52.101.229.140]) (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 C52C832571D; Sat, 24 Jan 2026 14:50:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.229.140 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769266230; cv=fail; b=maJrwGFEVgBlQlO8PhhlOEE2bAeM1t1aBpDm0W5WFidUDxgAaBfNeqCr8XQsjOh8m5fk158Ld8u42EYTDp9z7B9n54BV+S8ftOnRCtTAAg8QWdjckCL6ZCYii6wiKBvlqi7o9vUlsPdqRKU8mRtgfK9cX6oBHEZbYV8K2JHOmjE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769266230; c=relaxed/simple; bh=Nrr1N8YrAcN/x2RJ3s+AoXox1a1Wprq6uDFmtn4RU94=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=kJyxV0Iw4khURYzabm+PnC4KtIPuHujKqCXetIxSLeu9oTH2+N2t6Q8pgMHYQCeK/hWkKIIivi0OIEhrX8CHkXlB/DHknEdwrHHL/gyLD/KL6BXWzl3v3crDUoYUI5OSpjRPl/Eyy9+CgBRX/0EfoDmciFWWtaGDdSNVF9Fwqqs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp; spf=pass smtp.mailfrom=valinux.co.jp; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b=DkAGHsqo; arc=fail smtp.client-ip=52.101.229.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b="DkAGHsqo" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=UeNNa2mE3T9KahkiOJaUJLb2cfXgcamib0+qNgKbVCjUBNIT9mcR7l6N19Kh1gdQn+Zv5A4C/yboMA/RBALqkePnTd2wjMIh9oY0ILUo0R/e4WQnZ7mbHN53vGp48Opy/OQi+5dss6t62UmUg1sX6SiyWFIj+jIrSNJJce1Qmay1Bjmyeaim8/nCxfqGCjMqvXOhcq7K0ywTDJF0diDDy9n0KSIBLpmfgVE+rKlRmN+bHyr+MWUsimdFWo325SYllX72tr63qpIdsm5Pjd6ucZJwPHxQ75F2xYZqRKADKnHMH8OEq4o0RPyx7xr72VWt2hNPhmkNAvbZjm+/pL63ng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=sVazY870yWu71QphbkyJ+nXef387QUAjnwNViDU/egk=; b=WFjyJT4wWpbIshdrD0P9/7W4imjyOyhAa9UezpjobhbCi688tR0vKrJd/fzl+1MtZt3rJjXw8dpP4tqkYQtIjjHA8DYwOhvsPk8df60xmH+7YPK378fdHtNDwDt47pNkECIQGLGsucVXycycQI0NhxDjIYyBEhd5nz99kheQ2gqcoKKuDdUI8P9YAwo7Slv3IREcPkEAqzqJWYkJmb+KgRKjvX3e9Oq3XLoWT4kjAu7kwvT9LZoAWIq7pjF7xyjSetyCQjhXzn2SZnIhWxqyNbyCgaaHkqC7X8CZQXEfIODeaE63iERunSvN6/P3TShhVYBLvZ8qL4itLhYSVqWoiA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=valinux.co.jp; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=sVazY870yWu71QphbkyJ+nXef387QUAjnwNViDU/egk=; b=DkAGHsqo0t4MPBDx1eBw2el5ItC20xg0hn1hkJCKnuwVK2tUXs3TZy8OB6U1ShHfGCpMbJYiEcuZwOrkM16Z0g2RiazdJYHihA5JUveArWEwJiRNwe64QeNqdqvVk7eH+RHZYjlVgaOA9Vb1pQaIB5O2rds+88Mc+QCIb9caCe4= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) by TYYP286MB4692.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:19c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.11; Sat, 24 Jan 2026 14:50:19 +0000 Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32]) by TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32%5]) with mapi id 15.20.9542.010; Sat, 24 Jan 2026 14:50:19 +0000 From: Koichiro Den To: jingoohan1@gmail.com, mani@kernel.org, lpieralisi@kernel.org, kwilczynski@kernel.org, robh@kernel.org, bhelgaas@google.com, cassel@kernel.org, Frank.Li@nxp.com Cc: vigneshr@ti.com, s-vadapalli@ti.com, hongxing.zhu@nxp.com, l.stach@pengutronix.de, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, minghuan.Lian@nxp.com, mingkai.hu@nxp.com, roy.zang@nxp.com, jesper.nilsson@axis.com, heiko@sntech.de, srikanth.thokala@intel.com, marek.vasut+renesas@gmail.com, yoshihiro.shimoda.uh@renesas.com, geert+renesas@glider.be, magnus.damm@gmail.com, christian.bruel@foss.st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, thierry.reding@gmail.com, jonathanh@nvidia.com, hayashi.kunihiko@socionext.com, mhiramat@kernel.org, kishon@kernel.org, jirislaby@kernel.org, rongqianfeng@vivo.com, 18255117159@163.com, shawn.lin@rock-chips.com, nicolas.frattaroli@collabora.com, linux.amoon@gmail.com, vidyas@nvidia.com, shuah@kernel.org, linux-omap@vger.kernel.org, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, imx@lists.linux.dev, linuxppc-dev@lists.ozlabs.org, linux-arm-kernel@axis.com, linux-rockchip@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-tegra@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v10 4/8] PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match Mode iATU Date: Sat, 24 Jan 2026 23:50:08 +0900 Message-ID: <20260124145012.2794108-5-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260124145012.2794108-1-den@valinux.co.jp> References: <20260124145012.2794108-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TY4P286CA0017.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:2b0::19) To TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: TY7P286MB7722:EE_|TYYP286MB4692:EE_ X-MS-Office365-Filtering-Correlation-Id: 50f518f8-9f18-4aa1-22c9-08de5b57e508 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|7416014|1800799024|10070799003|366016; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?PZfrxwa+5zGu5bv+4MYCzki3d4cV4SVRImrXM6rwj06sCo2YXfopoNQccMMy?= =?us-ascii?Q?NX79JCNrOQjelDDFec8CJ5veYDkNZDgRd2Lcq1mCyaxXG3TPSYxWSu169ly4?= =?us-ascii?Q?Iedlzof/zLiSbAgPRmj23MXsSNTtYZ2W9zKC7tGjJ7N4vF4XN7zilQ/YRGdL?= =?us-ascii?Q?zyYyw4fdrr3o6dr93Q+tbPSBtXjTw/oS/VJpTs2uxNzTslA16+LEXMvvAqf5?= =?us-ascii?Q?Mkow2LYtHseMhlaW37xLO2+aYi+lNuWepQboz9AH0JZDRSpN0rwlirm0y/VK?= =?us-ascii?Q?4vI7fE5ydA1og0HCX7Kae9dmi9lrbXgiySvUPynPpt0UiNi+nfvLsVaEuf1P?= =?us-ascii?Q?ITZCahVrDvYmQKPc53mieTlemjQWUn91T5py0xvjlaOkNg4LfAcIsT+M6npU?= =?us-ascii?Q?CzF6PbF2SPe7jdIK4NoWeXne+63bbkq5hELm/6i/0JnPJ/G0VocqIavHPsu5?= =?us-ascii?Q?aX2hV8x3VEByEou39uqpRNMIKqSEq0yQXSbAIabWUxsQZoKh2u7aI4P5Gt2i?= =?us-ascii?Q?XsM2vF2NKqv29r1tCqospySwEG+yU+smQBfPMf39VJdRhRoCWulGRqFRLoix?= =?us-ascii?Q?JQlEpoZZLDUhrHj+IvZB5pjKPeqIYoitL+u4FJu1XghGdLKeTbgz27kSDGbB?= =?us-ascii?Q?vIeHlCYzHREJiqtu0J4OzHZK22cPxmuE4aZ/FH/3X14vkeXpgeVaUE+zHWK2?= =?us-ascii?Q?DCZhZvFjVWCwfbyLKxLgeM/DjAotchWN4RkG5VgwqGdFY5ayCCrr9CWrnVdz?= =?us-ascii?Q?2DptJtSAbYZew+5ivYkodQl7Xh5yG2VkG5RMCGuhDxKXFdRw7ikMpDDuTNIa?= =?us-ascii?Q?Mm0mWrP2qAZSN7wTU/Qy3vlfBfUcJCBiI5ddT/z+nAbhJLuKhbZIPBC533tT?= =?us-ascii?Q?9AoJyglMELi+yvPSy15RqnB2A1lU7HHp9dAUGjRcve5Wk7qfUkRl8I+TULwc?= =?us-ascii?Q?two/onIJ7sHaH+xYsvxmZTi+aRnDHJBDXYBf4tWYmJayTPKO31Ae8GuoHbMQ?= =?us-ascii?Q?RI0WrTIbcFTEjMsJHLF6OVZyrJecyExOuKsi4nqT8vbukWBXlu1TjMpPs7jW?= =?us-ascii?Q?f3nfBh9R4EsaXIruQ+gDWDTST1ivhYVmI52rr21eeIr3ZMnQLU/dHrT2R7so?= =?us-ascii?Q?uu8NTRnpZp3wr3CQgrZPVnFGcU8YFmvlvZCMnoWq2RgVcgYrHlMAHtI6oZY9?= =?us-ascii?Q?YAghrWrZh1Xg7Cq4juBUY8Huc9p5vLIJ7rG3OOqDlMHMw1ZSwyBJkTFOLp4H?= =?us-ascii?Q?+K6S7lnACRgjTcJsBJN/GPG9VjLkLzgTcTb4iUUzGx5MMRpyjN/AeDqP35ya?= =?us-ascii?Q?GxeSrz6ovBg/TbmXlPxO0WfaD5FU1ritDbUFKVDVidDJoAsIJISItWFOnK3O?= =?us-ascii?Q?2uTT9EbUMnMHio/gGHWiYzeFyrJ18CTKz2O8kNrUYYrzcuA784Q9fAKWH5sI?= =?us-ascii?Q?SJFDPFPTgt8dHwXdO4rMLrgwvjqf/qr3eBjAr9EqTadag0aSCDRtlzzGeM/P?= =?us-ascii?Q?HqhgyO0Pj0kvcRSsyG4CqUmQJ8ujrz19DCi76lGNF9600uOuxmuaGTa8Xx2S?= =?us-ascii?Q?8Iya8YF0+xawRtdYybU=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(376014)(7416014)(1800799024)(10070799003)(366016);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?OXYRfCNp7nnH/pbScJTj+0K9qtYAO+tiPhuZ1RyFPtNDE1c83Jf6r7Gga3/r?= =?us-ascii?Q?JppovCn3NVnr6KMjvRJis/rHN42RKTFK9xlvmrid86MW1rATeziol+QgGAh4?= =?us-ascii?Q?8vKkrvB6j02v444mJKB0f+Wsq8KMX7lwak3wZSxnHI0mkU+RxUSkyl/hN6zX?= =?us-ascii?Q?piGdJg75BWvVWu4Ld7O/KGkUfZ49ToJnPnzVFeWHct/TBwcePl4MPSfIHVsx?= =?us-ascii?Q?MxpsPfBhTmkEqh8MYu/sLg7O/hx1iTO8+314e1VxLf9+lwMx+f0BVmCkFXrn?= =?us-ascii?Q?Tzb1LvrrJMcyXBps/Z4hRsIoGO8CPMtl6WYToM18Uqp03H7553tkUSrk0Z2J?= =?us-ascii?Q?5mppxqMu5Y3OPGj3II1lagmrytIIaXTK8NDiKR++PoPlVSRKAdLCVqnBMlBy?= =?us-ascii?Q?srfrsOzb7Jmouoksea0/Yzf9mfzG0c2/YTNzVBdAKbDcoXESBqcCplm4JccA?= =?us-ascii?Q?NucHYqFkrGrkW+ndpfH/oRwvTNyNoyMxZ3/DGIqxJ0r+V40vo22/hcQIX+hy?= =?us-ascii?Q?Xlbh97ZCBQO/p8nANlU+AFC12D7tT5yzUjypy3ebd6o5bWrpIRpF7HYdOJrD?= =?us-ascii?Q?n0i6XDUQfvMEvyv/6Yzqo+3+tAsn2Fu4HmI6oQJjgYTc9Q07VEvO/fD+6eV7?= =?us-ascii?Q?RruPfsM+sEwV0dH2NxXZy4W4VAUBkEEedBNEWvQnM7FAWDfeqDpvVQ3VFfGT?= =?us-ascii?Q?TaiUMUVMZvzKVSwNw86rt2bCpgLAI+liogBoRk5ucBxlvF+H2ooEALzGYeNc?= =?us-ascii?Q?xg6twV2M/I6joXN5EzXOdvrrk7bj0Q8jBV3NNdeFEIR6oJxJYAPPG7llonAe?= =?us-ascii?Q?mA1xDfLSGKqw4XkmY53Xilm2zKyQKh8/0G87eIybhv/5oU2DGuGSPGdntFOh?= =?us-ascii?Q?OI6dihV6eH8DnsI9IYjBPcFDYX6C5+gWU6Ch57k6j8EmEeMpzPJlD2sH9Wjr?= =?us-ascii?Q?+P33gFxU+RZLvc6lHD17zjQ8cTl3nOEdqTzVKyQxgPXzqTJFUbjw8dI3q4Dr?= =?us-ascii?Q?RcXWX0DUOJab0reoOw8Udb1G1Vpu9x+vzHzAEZvNEfDSGR/C+0uK1cAF/ANu?= =?us-ascii?Q?nf9j/VTM2bJFO3cyXJuAz6l4ls7C4v3dXQk9DFMh41rvD24+OArzMGgGJUDF?= =?us-ascii?Q?T7/6/vP/BuOFbUzOZ6e1QHTbhT43oMdiY6A4JuNESBTJq7cJYmwBOZ7Jq7k+?= =?us-ascii?Q?QEZl8p0Ky2+Yd4qkbhpt4S8UAyRanM9nrhgKlfDiXGaDeBZ14pW3dwBSGmyC?= =?us-ascii?Q?g+YzIAx6IYWO5P6smqreFNMXOMsQtHBg0plrQ19okoQZyAqnnDIYKSHQ5cSC?= =?us-ascii?Q?C+Zvi0JVJgMMhrPHMpNhXA3xpdGj0NsDDjIz0oMyuDJumulFRsQBx/RgYfPU?= =?us-ascii?Q?ybyNv1bHryx/Yhb/zJsZveRdzyzNVGQx90D8YlNLHkkFFUEttrpG9KzBD3/j?= =?us-ascii?Q?KzOsQbwERvZv1ftk5qq5embF6lxmarfe9wCblluzbP/QQhr+AheMaVXEgcxA?= =?us-ascii?Q?HrLVZ8Lzu3z595MQv8BJsbQIMkwAfFStumvviTxVzGskcr2NRr9ytVP3mb5d?= =?us-ascii?Q?n8IuGAeUGU6A4G+Koy9qCin1Ul/tq5FoTs+QMT/gpdb8WR+UhtoZi1DqiOEF?= =?us-ascii?Q?S/QQLJqeu/DZuqpSUgIOl5oSC3XevyvsQ4y/sM1Gcv5GxJDOXPnoT72NCi0d?= =?us-ascii?Q?74q/WS261NVwL73edEQV5cyGC132Ekiu4ayaopDd9gav/OflFs/aOQh2ZVO/?= =?us-ascii?Q?A9LDtwxfvMK+q40ryMSrt371PAITmgq+v0FdThsQIFtZEWHTgr6j?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: 50f518f8-9f18-4aa1-22c9-08de5b57e508 X-MS-Exchange-CrossTenant-AuthSource: TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Jan 2026 14:50:19.6463 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 7a57bee8-f73d-4c5f-a4f7-d72c91c8c111 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: +iYyQC9GcoWbEfqbe3jaYDcqC7Ed7+teK7aVo8fmIHbok66/9RjkQBw7Qkd9C79a/8om5YCa45a2w6WllcSVmQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TYYP286MB4692 Content-Type: text/plain; charset="utf-8" Extend dw_pcie_ep_set_bar() to support inbound mappings for BAR subranges using Address Match Mode IB iATU when pci_epf_bar.num_submap is non-zero. Rename the existing BAR-match helper into dw_pcie_ep_ib_atu_bar() and introduce dw_pcie_ep_ib_atu_addr() for Address Match Mode. When num_submap is non-zero, read the assigned BAR base address and program one inbound iATU window per subrange. Validate the submap array before programming: - each subrange is aligned to pci->region_align - subranges cover the whole BAR (no gaps and no overlaps) Track Address Match Mode mappings and tear them down on clear_bar() and on set_bar() error paths to avoid leaving half-programmed state or untranslated BAR holes. Advertise this capability by extending the common feature bit initializer macro (DWC_EPC_COMMON_FEATURES). This enables multiple inbound windows within a single BAR, which is useful on platforms where usable BARs are scarce but EPFs need multiple inbound regions. Reviewed-by: Frank Li Signed-off-by: Koichiro Den Reviewed-by: Niklas Cassel --- .../pci/controller/dwc/pcie-designware-ep.c | 212 +++++++++++++++++- drivers/pci/controller/dwc/pcie-designware.h | 7 +- 2 files changed, 208 insertions(+), 11 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/= controller/dwc/pcie-designware-ep.c index cfd59899c7b8..de09cd786edc 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -100,9 +100,10 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc= , u8 func_no, u8 vfunc_no, return 0; } =20 -static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int t= ype, - dma_addr_t parent_bus_addr, enum pci_barno bar, - size_t size) +/* BAR Match Mode inbound iATU mapping */ +static int dw_pcie_ep_ib_atu_bar(struct dw_pcie_ep *ep, u8 func_no, int ty= pe, + dma_addr_t parent_bus_addr, enum pci_barno bar, + size_t size) { int ret; u32 free_win; @@ -135,6 +136,179 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *= ep, u8 func_no, int type, return 0; } =20 +static void dw_pcie_ep_clear_ib_maps(struct dw_pcie_ep *ep, enum pci_barno= bar) +{ + struct dw_pcie *pci =3D to_dw_pcie_from_ep(ep); + struct device *dev =3D pci->dev; + unsigned int i, num; + u32 atu_index; + u32 *indexes; + + /* Tear down the BAR Match Mode mapping, if any. */ + if (ep->bar_to_atu[bar]) { + atu_index =3D ep->bar_to_atu[bar] - 1; + dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index); + clear_bit(atu_index, ep->ib_window_map); + ep->bar_to_atu[bar] =3D 0; + } + + /* Tear down all Address Match Mode mappings, if any. */ + indexes =3D ep->ib_atu_indexes[bar]; + num =3D ep->num_ib_atu_indexes[bar]; + ep->ib_atu_indexes[bar] =3D NULL; + ep->num_ib_atu_indexes[bar] =3D 0; + if (!indexes) + return; + for (i =3D 0; i < num; i++) { + dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, indexes[i]); + clear_bit(indexes[i], ep->ib_window_map); + } + devm_kfree(dev, indexes); +} + +static u64 dw_pcie_ep_read_bar_assigned(struct dw_pcie_ep *ep, u8 func_no, + enum pci_barno bar, int flags) +{ + u32 reg =3D PCI_BASE_ADDRESS_0 + (4 * bar); + u32 lo, hi; + u64 addr; + + lo =3D dw_pcie_ep_readl_dbi(ep, func_no, reg); + + if (flags & PCI_BASE_ADDRESS_SPACE) + return lo & PCI_BASE_ADDRESS_IO_MASK; + + addr =3D lo & PCI_BASE_ADDRESS_MEM_MASK; + if (!(flags & PCI_BASE_ADDRESS_MEM_TYPE_64)) + return addr; + + hi =3D dw_pcie_ep_readl_dbi(ep, func_no, reg + 4); + return addr | ((u64)hi << 32); +} + +static int dw_pcie_ep_validate_submap(struct dw_pcie_ep *ep, + const struct pci_epf_bar_submap *submap, + unsigned int num_submap, size_t bar_size) +{ + struct dw_pcie *pci =3D to_dw_pcie_from_ep(ep); + u32 align =3D pci->region_align; + size_t off =3D 0; + unsigned int i; + size_t size; + + if (!align || !IS_ALIGNED(bar_size, align)) + return -EINVAL; + + /* + * The submap array order defines the BAR layout (submap[0] starts + * at offset 0 and each entry immediately follows the previous + * one). Here, validate that it forms a strict, gapless + * decomposition of the BAR: + * - each entry has a non-zero size + * - sizes, implicit offsets and phys_addr are aligned to + * pci->region_align + * - each entry lies within the BAR range + * - the entries exactly cover the whole BAR + * + * Note: dw_pcie_prog_inbound_atu() also checks alignment for the + * PCI address and the target phys_addr, but validating up-front + * avoids partially programming iATU windows in vain. + */ + for (i =3D 0; i < num_submap; i++) { + size =3D submap[i].size; + + if (!size) + return -EINVAL; + + if (!IS_ALIGNED(size, align) || !IS_ALIGNED(off, align)) + return -EINVAL; + + if (!IS_ALIGNED(submap[i].phys_addr, align)) + return -EINVAL; + + if (off > bar_size || size > bar_size - off) + return -EINVAL; + + off +=3D size; + } + if (off !=3D bar_size) + return -EINVAL; + + return 0; +} + +/* Address Match Mode inbound iATU mapping */ +static int dw_pcie_ep_ib_atu_addr(struct dw_pcie_ep *ep, u8 func_no, int t= ype, + const struct pci_epf_bar *epf_bar) +{ + const struct pci_epf_bar_submap *submap =3D epf_bar->submap; + struct dw_pcie *pci =3D to_dw_pcie_from_ep(ep); + enum pci_barno bar =3D epf_bar->barno; + struct device *dev =3D pci->dev; + u64 pci_addr, parent_bus_addr; + u64 size, base, off =3D 0; + int free_win, ret; + unsigned int i; + u32 *indexes; + + if (!epf_bar->num_submap || !submap || !epf_bar->size) + return -EINVAL; + + ret =3D dw_pcie_ep_validate_submap(ep, submap, epf_bar->num_submap, + epf_bar->size); + if (ret) + return ret; + + base =3D dw_pcie_ep_read_bar_assigned(ep, func_no, bar, epf_bar->flags); + if (!base) { + dev_err(dev, + "BAR%u not assigned, cannot set up sub-range mappings\n", + bar); + return -EINVAL; + } + + indexes =3D devm_kcalloc(dev, epf_bar->num_submap, sizeof(*indexes), + GFP_KERNEL); + if (!indexes) + return -ENOMEM; + + ep->ib_atu_indexes[bar] =3D indexes; + ep->num_ib_atu_indexes[bar] =3D 0; + + for (i =3D 0; i < epf_bar->num_submap; i++) { + size =3D submap[i].size; + parent_bus_addr =3D submap[i].phys_addr; + + if (off > (~0ULL) - base) { + ret =3D -EINVAL; + goto err; + } + + pci_addr =3D base + off; + off +=3D size; + + free_win =3D find_first_zero_bit(ep->ib_window_map, + pci->num_ib_windows); + if (free_win >=3D pci->num_ib_windows) { + ret =3D -ENOSPC; + goto err; + } + + ret =3D dw_pcie_prog_inbound_atu(pci, free_win, type, + parent_bus_addr, pci_addr, size); + if (ret) + goto err; + + set_bit(free_win, ep->ib_window_map); + indexes[i] =3D free_win; + ep->num_ib_atu_indexes[bar] =3D i + 1; + } + return 0; +err: + dw_pcie_ep_clear_ib_maps(ep, bar); + return ret; +} + static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, struct dw_pcie_ob_atu_cfg *atu) { @@ -165,17 +339,15 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc,= u8 func_no, u8 vfunc_no, struct dw_pcie_ep *ep =3D epc_get_drvdata(epc); struct dw_pcie *pci =3D to_dw_pcie_from_ep(ep); enum pci_barno bar =3D epf_bar->barno; - u32 atu_index =3D ep->bar_to_atu[bar] - 1; =20 - if (!ep->bar_to_atu[bar]) + if (!ep->epf_bar[bar]) return; =20 __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags); =20 - dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index); - clear_bit(atu_index, ep->ib_window_map); + dw_pcie_ep_clear_ib_maps(ep, bar); + ep->epf_bar[bar] =3D NULL; - ep->bar_to_atu[bar] =3D 0; } =20 static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci, @@ -331,11 +503,27 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8= func_no, u8 vfunc_no, ep->epf_bar[bar]->flags !=3D flags) return -EINVAL; =20 + /* + * When dynamically changing a BAR, tear down any existing + * mappings before re-programming. + */ + if (ep->epf_bar[bar]->num_submap || epf_bar->num_submap) + dw_pcie_ep_clear_ib_maps(ep, bar); + /* * When dynamically changing a BAR, skip writing the BAR reg, as * that would clear the BAR's PCI address assigned by the host. */ goto config_atu; + } else { + /* + * Subrange mapping is an update-only operation. + * The BAR must have been configured once without submaps so that + * subsequent set_bar() calls can update inbound mappings without + * touching the BAR register (and clobbering the host-assigned address). + */ + if (epf_bar->num_submap) + return -EINVAL; } =20 bar_type =3D dw_pcie_ep_get_bar_type(ep, bar); @@ -369,8 +557,12 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 = func_no, u8 vfunc_no, else type =3D PCIE_ATU_TYPE_IO; =20 - ret =3D dw_pcie_ep_inbound_atu(ep, func_no, type, epf_bar->phys_addr, bar, - size); + if (epf_bar->num_submap) + ret =3D dw_pcie_ep_ib_atu_addr(ep, func_no, type, epf_bar); + else + ret =3D dw_pcie_ep_ib_atu_bar(ep, func_no, type, + epf_bar->phys_addr, bar, size); + if (ret) return ret; =20 diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/con= troller/dwc/pcie-designware.h index 7ca9d0f6b7f2..8f170122ad78 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -306,7 +306,8 @@ #define DMA_LLP_MEM_SIZE PAGE_SIZE =20 /* Common struct pci_epc_feature bits among DWC EP glue drivers */ -#define DWC_EPC_COMMON_FEATURES .dynamic_inbound_mapping =3D true +#define DWC_EPC_COMMON_FEATURES .dynamic_inbound_mapping =3D true, \ + .subrange_mapping =3D true =20 struct dw_pcie; struct dw_pcie_rp; @@ -487,6 +488,10 @@ struct dw_pcie_ep { phys_addr_t msi_mem_phys; struct pci_epf_bar *epf_bar[PCI_STD_NUM_BARS]; =20 + /* Only for Address Match Mode inbound iATU */ + u32 *ib_atu_indexes[PCI_STD_NUM_BARS]; + unsigned int num_ib_atu_indexes[PCI_STD_NUM_BARS]; + /* MSI outbound iATU state */ bool msi_iatu_mapped; u64 msi_msg_addr; --=20 2.51.0