From patchwork Fri Mar 7 12:47:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 14006436 X-Patchwork-Delegate: kw@linux.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 C4CD520F06C for ; Fri, 7 Mar 2025 12:47:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741351668; cv=none; b=l5S8Ndm5pXoQy4+TARqzsydax7r01pt2ERhjjEOX54qq/Nh8cRYp9KN80HbuKndE93M6e5JlYIfv9QJKMdpQiU34vFPR7Bj+Zj3/hjBH8cgf7+DZG8UoQ7OJZr3wtbWwVY1Lq7T1H8hLO5hp03GswQy9ziIiHne3OSb6XDu7B0I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741351668; c=relaxed/simple; bh=EXWgdA5zPTltOnxenAQytrNbeINQ16wRUkuJVLLiGic=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jEcoX9qRlBYkSrO/c2CywfyJpAJ1b8l2evCt8LJ+7CfW2TTy92wR7W2MpD3DR9gcS+xgdvrdo2Bp76dFPMHj0niPlPfzUzkZ4PpMCAvSQ4hpAyHJ+YSgbs3J0Bl442b62nU3SISVYkRM+GPYWOmfJEJ0gRTGGH90BqW1b4pwCMA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gbtG1ZMF; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gbtG1ZMF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DE870C4CED1; Fri, 7 Mar 2025 12:47:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741351668; bh=EXWgdA5zPTltOnxenAQytrNbeINQ16wRUkuJVLLiGic=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gbtG1ZMFsyLJLNC1YrPTe9nwGM7haQl1sXapchjA9MqA0D8v8VhMovVT8ydFiXBrp SL5Poh9xBxDpOnln+1PPk/qZFnGj2ZS0eHzF5OAdab8Ld81uM0ZQ3u6cdp6luq4ApX 7AOuXFJiZpuM4Oi7lSUuxXZ/A/ZyXHJyKardmDS9CaCVeFnLjNYXV1fiJzlcHwql7t BWA9lJcR35u8nvae6Nww88oRLMKDJimwOVZ6EpmzMVmXgzDUhd50ZrVzAysqb2ERFV fECr9eg9qqyOu1kT0A3FhGvDrgH5RscHBwM+YLVt/KC3RCsaH4Va3Twpko6O+uGU7i fvvVY+NIQW6sg== From: Niklas Cassel To: Jingoo Han , Manivannan Sadhasivam , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84?= =?utf-8?q?ski?= , Rob Herring , Bjorn Helgaas Cc: Shawn Lin , Damien Le Moal , Niklas Cassel , linux-pci@vger.kernel.org Subject: [PATCH v2 1/2] PCI: dwc: ep: Add dw_pcie_ep_hide_ext_capability() Date: Fri, 7 Mar 2025 13:47:34 +0100 Message-ID: <20250307124732.704375-5-cassel@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250307124732.704375-4-cassel@kernel.org> References: <20250307124732.704375-4-cassel@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3308; i=cassel@kernel.org; h=from:subject; bh=EXWgdA5zPTltOnxenAQytrNbeINQ16wRUkuJVLLiGic=; b=owGbwMvMwCV2MsVw8cxjvkWMp9WSGNJPvXo6IeO54e9K26oYv5j2T7HV6g/nxp5XKwhJag22a BPYmH6mo5SFQYyLQVZMkcX3h8v+4m73KccV79jAzGFlAhnCwMUpABN5l8zIcOv1Z+3yUx2XQvca 8N0J2bf/YXRgbfPiygVs91avWeod+5Thf1SbR8w0S91cz6XS6902R90V+Plk4tFzBwvnMWfGPNn cwAsA X-Developer-Key: i=cassel@kernel.org; a=openpgp; fpr=5ADE635C0E631CBBD5BE065A352FE6582ED9B5DA Add dw_pcie_ep_hide_ext_capability() which can be used by an endpoint controller driver to hide a capability. This can be useful to hide a capability that is buggy, such that the host side does not try to enable the buggy capability. Suggested-by: Manivannan Sadhasivam Signed-off-by: Niklas Cassel --- .../pci/controller/dwc/pcie-designware-ep.c | 38 +++++++++++++++++++ drivers/pci/controller/dwc/pcie-designware.h | 7 ++++ 2 files changed, 45 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index a8568808b5e5..d671fea1e7c6 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -102,6 +102,44 @@ static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap) return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap); } +/** + * dw_pcie_ep_hide_ext_capability - Hide a capability from the linked list + * @pci: DWC PCI device + * @prev_cap: Capability preceding the capability that should be hidden + * @cap: Capability that should be hidden + * + * Return: 0 if success, errno otherwise. + */ +int dw_pcie_ep_hide_ext_capability(struct dw_pcie *pci, u8 prev_cap, u8 cap) +{ + u16 prev_cap_offset, cap_offset; + u32 prev_cap_header, cap_header; + + prev_cap_offset = dw_pcie_find_ext_capability(pci, prev_cap); + if (!prev_cap_offset) + return -EINVAL; + + prev_cap_header = dw_pcie_readl_dbi(pci, prev_cap_offset); + cap_offset = PCI_EXT_CAP_NEXT(prev_cap_header); + cap_header = dw_pcie_readl_dbi(pci, cap_offset); + + /* cap must immediately follow prev_cap. */ + if (PCI_EXT_CAP_ID(cap_header) != cap) + return -EINVAL; + + /* Clear next ptr. */ + prev_cap_header &= ~GENMASK(31, 20); + + /* Set next ptr to next ptr of cap. */ + prev_cap_header |= cap_header & GENMASK(31, 20); + + dw_pcie_dbi_ro_wr_en(pci); + dw_pcie_writel_dbi(pci, prev_cap_offset, prev_cap_header); + dw_pcie_dbi_ro_wr_dis(pci); + + return 0; +} + static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct pci_epf_header *hdr) { diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index a03b3799fb27..2d1de81d47b6 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -781,6 +781,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no, u16 interrupt_num); void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar); +int dw_pcie_ep_hide_ext_capability(struct dw_pcie *pci, u8 prev_cap, u8 cap); struct dw_pcie_ep_func * dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no); #else @@ -838,6 +839,12 @@ static inline void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) { } +static inline int dw_pcie_ep_hide_ext_capability(struct dw_pcie *pci, + u8 prev_cap, u8 cap) +{ + return 0; +} + static inline struct dw_pcie_ep_func * dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no) { From patchwork Fri Mar 7 12:47:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Cassel X-Patchwork-Id: 14006437 X-Patchwork-Delegate: kw@linux.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 5CEED25771 for ; Fri, 7 Mar 2025 12:47:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741351672; cv=none; b=r76gPSOAb/ZElyv7nCV+QT2il9RcKvkTAbux4d48Am92IB/u2I7OuHlECPV3PimsTBCkpj5+X5m/EONLnEQ5lfThIjA+KaQHHGVfrK7o1hdUfd/J3/6Z7QanqIfyaviOy3LTAm6EYRH5hoY5Dr1KwXIbK8D4u1fapxE9Xj1K2jA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741351672; c=relaxed/simple; bh=yMoYyGKM6FbagclOTpM00d2Qgsis276wrIoNJyyP4ys=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IUCSS1myDZBMy+Bq8b3xHT6LD/CKekhNPXIbJNVKd7roTSO5n4AswlTw3CNOVt6f2UE/GJ0Ypir7csgOvafieBMQHXLqdcDIePz9p0eUvLQm7nwLUQUExOXKoUf5rzy9Fy6ItEjQ+NcjzLQB8uC9ne74cMjrLxdZi6PpjynKfqA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BBJ1kRJy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BBJ1kRJy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 02946C4CED1; Fri, 7 Mar 2025 12:47:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741351671; bh=yMoYyGKM6FbagclOTpM00d2Qgsis276wrIoNJyyP4ys=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BBJ1kRJym+MLwffziarp2SQHYX9pyoStle3jVRUQBNdBy3oDTq4dDapuJPRmxunJI w09KYtz1P+421K4elybUlI8X05IOOYpOZqmovKrBpZlIvc346m7Ci7balOmeQn7gh4 48RPPPEeNBPlAXbIp29J89DRDMtZacL1bbuSjm7Dbak7nM7/+A2Mj9j5VWlkE/dApe ey0VWv7kjjmylm40OXOcVQkFzoefoRSj6rKBMZ7McpOtFbi9jrlEhv8OfATBNEOJNQ Aqkc4sqmjA1mdA9Di9IgxHvN4xsL2OE7CoEUwZQBsJfLAH/rydd2OlsTLSS9ZoAzEz Z3hguMCot8d1A== From: Niklas Cassel To: Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy?= =?utf-8?q?=C5=84ski?= , Manivannan Sadhasivam , Rob Herring , Bjorn Helgaas , Heiko Stuebner Cc: Shawn Lin , Damien Le Moal , Niklas Cassel , linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org Subject: [PATCH v2 2/2] PCI: dw-rockchip: Hide broken ATS capability Date: Fri, 7 Mar 2025 13:47:35 +0100 Message-ID: <20250307124732.704375-6-cassel@kernel.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250307124732.704375-4-cassel@kernel.org> References: <20250307124732.704375-4-cassel@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3114; i=cassel@kernel.org; h=from:subject; bh=yMoYyGKM6FbagclOTpM00d2Qgsis276wrIoNJyyP4ys=; b=owGbwMvMwCV2MsVw8cxjvkWMp9WSGNJPvXq6heN+eXtTh3Nz7VpNf+O8nt0i97p2qMsq3tJcz yKwftvDjlIWBjEuBlkxRRbfHy77i7vdpxxXvGMDM4eVCWQIAxenAExk1WyG/4VC5o0b+TZrSTI8 c2G0+L/5Cvfiiv25Eq4xz0ILbq6ZqMjw359lfYihXWdqwdfrhueelSuudWreHn436bgJ+wVufe2 97AA= X-Developer-Key: i=cassel@kernel.org; a=openpgp; fpr=5ADE635C0E631CBBD5BE065A352FE6582ED9B5DA When running the rk3588 in endpoint mode, with an Intel host with IOMMU enabled, the host side prints: DMAR: VT-d detected Invalidation Time-out Error: SID 0 When running the rk3588 in endpoint mode, with an AMD host with IOMMU enabled, the host side prints: iommu ivhd0: AMD-Vi: Event logged [IOTLB_INV_TIMEOUT device=63:00.0 address=0x42b5b01a0] Rockchip has confirmed that the ATS support for rk3588 only works when running the PCIe controller in RC mode [0]. Usually, to handle these issues, we add a quirk for the PCI vendor and device ID in drivers/pci/quirks.c with quirk_no_ats(). That is because we cannot usually modify the capabilities on the EP side. In this case, we can modify the capabilities on the EP side. Thus, hide the broken ATS capability on rk3588 when running in EP mode. That way, we don't need any quirk on the host side, and we see no errors on the host side, and we can run pci_endpoint_test successfully, with the IOMMU enabled on the host side. [0] https://lore.kernel.org/linux-pci/93cdce39-1ae6-4939-a3fc-db10be7564e5@rock-chips.com/ Acked-by: Shawn Lin Signed-off-by: Niklas Cassel --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index 836ea10eafbb..bc4339252a03 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -242,6 +242,32 @@ static const struct dw_pcie_host_ops rockchip_pcie_host_ops = { .init = rockchip_pcie_host_init, }; +/* + * ATS does not work on rk3588 when running in EP mode. + * After a host has enabled ATS on the EP side, it will send an IOTLB + * invalidation request to the EP side. The rk3588 will never send a completion + * back and eventually the host will print an IOTLB_INV_TIMEOUT error, and the + * EP will not be operational. If we hide the ATS cap, things work as expected. + */ +static void rockchip_pcie_ep_hide_broken_ats_cap_rk3588(struct dw_pcie_ep *ep) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct device *dev = pci->dev; + + /* Only hide the ATS cap for rk3588 running in EP mode */ + if (!of_device_is_compatible(dev->of_node, "rockchip,rk3588-pcie-ep")) + return; + + if (dw_pcie_ep_hide_ext_capability(pci, PCI_EXT_CAP_ID_SECPCI, + PCI_EXT_CAP_ID_ATS)) + dev_err(dev, "failed to hide ATS cap\n"); +} + +static void rockchip_pcie_ep_pre_init(struct dw_pcie_ep *ep) +{ + rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep); +} + static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); @@ -314,6 +340,7 @@ rockchip_pcie_get_features(struct dw_pcie_ep *ep) static const struct dw_pcie_ep_ops rockchip_pcie_ep_ops = { .init = rockchip_pcie_ep_init, + .pre_init = rockchip_pcie_ep_pre_init, .raise_irq = rockchip_pcie_raise_irq, .get_features = rockchip_pcie_get_features, };