From nobody Tue Oct 7 01:53:54 2025 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 61B9728540B; Tue, 15 Jul 2025 14:21:11 +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=1752589271; cv=none; b=tiuTB3Y1sG8tOSaL/UYLNl6sTybO0vA7QQScvRMN3Z0IrttYGaDRTgdhZjTfZvN5sCId4h1z9/NW1dm28VQM4gE4kZUiv900YpY11g148Qazczr7HH/8MA5Li4ER30oP2IpaB8LINS1uYnEYeASnxul9NkBz622zeMN+brZkx48= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752589271; c=relaxed/simple; bh=G4Llr4ESGjruK8vWpxnM41n2mNWvPlgKfuaT3QZitm4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ESzyKQHSdYEk/21QaW1UqjmMxgcTNI+WnGSbq6onyhmhagVEEGdOKgjntGl3El8t3gMrlXXKXM2h+FeTOOA9lva3sdWTcOIhE58Wui8CkqlOZna2Ytdhh70K38l00k/6CY9NW0TZLjhb9S3K7D8RLAkjmwrt3YE9Q2eI+eOmTDM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EmlC91Fl; 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="EmlC91Fl" Received: by smtp.kernel.org (Postfix) with ESMTPS id F1A85C4CEF4; Tue, 15 Jul 2025 14:21:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752589271; bh=G4Llr4ESGjruK8vWpxnM41n2mNWvPlgKfuaT3QZitm4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=EmlC91FlUemG4T8iSwn0YR+Cis7TCmKufMG5GpwD2mozGkYCJ3CcuYBq3J22Fg5gt ECOfrGiyShuCnm7r+zJHgMx7JAFgW3aetfPlHSebZmjCk5MzBsSYtfjWipTvQFGRkH 8pr4WW33JxC1wHjN0vFAFBUVbm5JfZ6ba+TrAeJcDF9cp2iANoXGMz0vlnTar3MyKZ ovaGmCRBYDjMz0lE8GmfUbNrrv8dr8Igp7yNNQ0Bc631w5M8aMqsbQly27Tnqh4wE/ +B2SEtBQriSRvYhq3Pp6IRlSlyA6NmGkUYjZFX+dXw9mp5PcPVl942cwbmBL91jqkT 77bcbTJ6WC26g== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E1B6BC83F17; Tue, 15 Jul 2025 14:21:10 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Jul 2025 19:51:04 +0530 Subject: [PATCH v6 1/4] PCI/ERR: Add support for resetting the Root Ports in a platform specific way Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250715-pci-port-reset-v6-1-6f9cce94e7bb@oss.qualcomm.com> References: <20250715-pci-port-reset-v6-0-6f9cce94e7bb@oss.qualcomm.com> In-Reply-To: <20250715-pci-port-reset-v6-0-6f9cce94e7bb@oss.qualcomm.com> To: Bjorn Helgaas , Mahesh J Salgaonkar , Oliver O'Halloran , Will Deacon , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Manivannan Sadhasivam , Rob Herring , Heiko Stuebner , Philipp Zabel Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-rockchip@lists.infradead.org, Niklas Cassel , Wilfred Mallawa , Krishna Chaitanya Chundru , mani@kernel.org, Lukas Wunner , Manivannan Sadhasivam , Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3274; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=vO0v800CGm0YlQFOi4cUiTQ2vqZZXbTs8BWQyyTq7Kc=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBodmPU7n0J5kTP8lJg9aNe1FZSaO/nXrn/HTEZk ZHlRKCt+l6JATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaHZj1AAKCRBVnxHm/pHO 9RLAB/95sKFXGToL/hcbo9zAzXQnyfkmN2pcsNyW7EhIf4hxdOIRHD8TR0NfjAjRJibAzR9v4cR WkIvzUbXTs8/X5JOPjQ3Z1I/uGUk1FIT6of2o+rcWr6qs01QYGxO3IrNudNUZ6CX9mnyYpGM9TV Jhd0an56Xhndu3J5KRU8UKD7WyCjLYe4iPyC/Nyb1tiS/GooDWvjMIwvtKjwzoi8HJJeHx6H/wL onVysaMSa+1Q/iygv7QB/ywkCFcsX97LWwSjG3bkJtMtj918d3pVARwT2uEXSA542Zhf0QdQ6se WWIORNZC3bttW0nKoBxa4VQXUJ1e0WB2jGBVHGwzNLRFxOQh X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Manivannan Sadhasivam Some host bridge devices require resetting the Root Ports in a platform specific way to recover them from error conditions such as Fatal AER errors, Link Down etc... So introduce pci_host_bridge::reset_root_port() callback and call it from pcibios_reset_secondary_bus() if available. Also, save the Root Port config space before reset and restore it afterwards. The 'reset_root_port' callback is responsible for resetting the given Root Port referenced by the 'pci_dev' pointer in a platform specific way and bring it back to the working state if possible. If any error occurs during the reset operation, relevant errno should be returned. Signed-off-by: Manivannan Sadhasivam Signed-off-by: Manivannan Sadhasivam Reviewed-by: Frank Li Tested-by: Brian Norris Tested-by: Krishna Chaitanya Chundru Tested-by: Niklas Cassel --- drivers/pci/pci.c | 20 ++++++++++++++++++++ drivers/pci/pcie/err.c | 5 ----- include/linux/pci.h | 1 + 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e9448d55113bdfd2263d8e2f6b3ec802f56b712e..b29264aa2be33b18a58b3b3db1d= 1fb0f6483e5e8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4964,6 +4964,26 @@ void pci_reset_secondary_bus(struct pci_dev *dev) =20 void __weak pcibios_reset_secondary_bus(struct pci_dev *dev) { + struct pci_host_bridge *host =3D pci_find_host_bridge(dev->bus); + int ret; + + if (pci_is_root_bus(dev->bus) && host->reset_root_port) { + /* + * Save the config space of the Root Port before doing the + * reset, since the state could be lost. The Endpoint state + * should've been saved by the caller. + */ + pci_save_state(dev); + ret =3D host->reset_root_port(host, dev); + if (ret) + pci_err(dev, "Failed to reset Root Port: %d\n", ret); + else + /* Now restore it on success */ + pci_restore_state(dev); + + return; + } + pci_reset_secondary_bus(dev); } =20 diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index de6381c690f5c21f00021cdc7bde8d93a5c7db52..b834fc0d705938540d3d7d3d873= 9770c09fe7cf1 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -234,11 +234,6 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, } =20 if (status =3D=3D PCI_ERS_RESULT_NEED_RESET) { - /* - * TODO: Should call platform-specific - * functions to reset slot before calling - * drivers' slot_reset callbacks? - */ status =3D PCI_ERS_RESULT_RECOVERED; pci_dbg(bridge, "broadcast slot_reset message\n"); pci_walk_bridge(bridge, report_slot_reset, &status); diff --git a/include/linux/pci.h b/include/linux/pci.h index 05e68f35f39238f8b9ce08df97b384d1c1e89bbe..e7c118a961910a307ec365f17b8= fe4f2585267e8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -599,6 +599,7 @@ struct pci_host_bridge { void (*release_fn)(struct pci_host_bridge *); int (*enable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); void (*disable_device)(struct pci_host_bridge *bridge, struct pci_dev *de= v); + int (*reset_root_port)(struct pci_host_bridge *bridge, struct pci_dev *de= v); void *release_data; unsigned int ignore_reset_delay:1; /* For entire hierarchy */ unsigned int no_ext_tags:1; /* No Extended Tags */ --=20 2.45.2 From nobody Tue Oct 7 01:53:54 2025 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 61B2D285404; Tue, 15 Jul 2025 14:21:11 +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=1752589271; cv=none; b=PnQ6dKhsL8lgOWOvinZ3Unk0b7KfsNsDEVSGA/1blvOm8Xn5KLJFJIC5UyjCMA3oK2DbJRMvZPpFfkQRHLp4BxOC6T9htASlBePaelDJ0Z8raWe2RyjDx+2ncW4urJaL7lcxtVl9ZKvpXR7KYtQN/JrFhiFkQnhyjWKBWcOg9fk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752589271; c=relaxed/simple; bh=HUiqe9BfJu8+IE5qBDSonrm/7cSZb3FrNqj6ffWbMIU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cBNWgtS0knOkcUEeQvQuX57f2Yi+PSOWu2UZ4aDnpp2Fafq26Y2Lepxmi/GslhjPBxJ4AjhEZbnwtV0FkcctSZThJcBldcV+XYFWVOGqYvlYXfvT639LTaAAvF5d2SD/9iiw/YKeHbdE5KEauLJkTHMxSN7R4w3E2pyFypyu4bY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cSOPpAqA; 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="cSOPpAqA" Received: by smtp.kernel.org (Postfix) with ESMTPS id 08581C4CEF8; Tue, 15 Jul 2025 14:21:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752589271; bh=HUiqe9BfJu8+IE5qBDSonrm/7cSZb3FrNqj6ffWbMIU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=cSOPpAqAU6Kde3IQHaYWfRC1pHrB6jAYvqgThr6JdD9Ew4kffLWBRluaazgz5Gqa9 W8s9IzIewr++ugD6yGjta08xl2b3O8/jtBOfDHLJW47SHtqu5J11sMlYZGryVQr6To GbZj3/DZPzu4+BrUrsqIY5wWlU1QPw0XIPHigvCm60WSw1SwRs/ldDLF6zEJSEY/8+ VPBbElVM6/vj2XoO+Ie3ymB2t7I+XFQ/XHxWiUIkVSdOJNxJuA4+czOIPEPH9hNCEz ujjwEZSvRhHcslsgsznPRI86LJeLHJnuY65YyP0m4zUtNu9m/V+hbBeZxA2PL2F2tR GIHjjEaZClLsw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF759C83F2D; Tue, 15 Jul 2025 14:21:10 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Jul 2025 19:51:05 +0530 Subject: [PATCH v6 2/4] PCI: host-common: Add link down handling for Root Ports Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250715-pci-port-reset-v6-2-6f9cce94e7bb@oss.qualcomm.com> References: <20250715-pci-port-reset-v6-0-6f9cce94e7bb@oss.qualcomm.com> In-Reply-To: <20250715-pci-port-reset-v6-0-6f9cce94e7bb@oss.qualcomm.com> To: Bjorn Helgaas , Mahesh J Salgaonkar , Oliver O'Halloran , Will Deacon , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Manivannan Sadhasivam , Rob Herring , Heiko Stuebner , Philipp Zabel Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-rockchip@lists.infradead.org, Niklas Cassel , Wilfred Mallawa , Krishna Chaitanya Chundru , mani@kernel.org, Lukas Wunner , Manivannan Sadhasivam , Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=4883; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=yclKXg12a4Ms/Jc9pFHjTrFPlwGCKmI6VWDeeqlj8XE=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBodmPUesZqzIw510tKLlbnICAV2RA0RCl15yWpa AkTWHG8fIqJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaHZj1AAKCRBVnxHm/pHO 9dMPCACpNns3R+yAsxZwXke3SJFVnnZNTmZk9e3XJZNXxBvOmDY3pXwmKOH2mjAf3Wyz6y4jBvR lSDlRFXz/+BSPaZbQH6QD3WKSwwIPTCnJCeE2kjR8mf3pQ3XBpGjPNtXZ9waTI5p4eVgn7DgtvY v8rY9FgrSqh1dk5yY1XqCi6KSUxP4mSd9BUdB0nSyN3A+/DKhwHuhYiJsg685g2+QsoYCh2wR4Y riOaWlurn7idL8rwXGt16wKX1ZWQiq9/OaOzbDIoN16sRqRAMOBzQlPviLPxeHB4XpPhCTag/aF h9bI6uBHzbzSxgCxjDVKkqU959ySUJMjGG5Q1UA9bWvD2Xjl X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Manivannan Sadhasivam The PCI link, when down, needs to be recovered to bring it back. But on some platforms, that cannot be done in a generic way as link recovery procedure is platform specific. So add a new API pci_host_handle_link_down() that could be called by the host bridge drivers for a specific Root Port when the link goes down. The API accepts the 'pci_dev' corresponding to the Root Port which observed the link down event. If CONFIG_PCIEAER is enabled, the API calls pcie_do_recovery() function with 'pci_channel_io_frozen' as the state. This will result in the execution of the AER Fatal error handling code. Since the link down recovery is pretty much the same as AER Fatal error handling, pcie_do_recovery() helper is reused here. First, the AER error_detected() callback will be triggered for the bridge and then for the downstream devices. Finally, pci_host_reset_root_port() will be called for the Root Port, which will reset the Root Port using 'reset_root_port' callback to recover the link. Once that's done, resume message will be broadcasted to the bridge and the downstream devices, indicating successful link recovery. But if CONFIG_PCIEAER is not enabled in the kernel, only pci_host_reset_root_port() API will be called, which will in turn call pci_bus_error_reset() to just reset the Root Port as there is no way we could inform the drivers about link recovery. Signed-off-by: Manivannan Sadhasivam Signed-off-by: Manivannan Sadhasivam Reviewed-by: Frank Li Tested-by: Brian Norris Tested-by: Krishna Chaitanya Chundru Tested-by: Niklas Cassel --- drivers/pci/controller/pci-host-common.c | 33 ++++++++++++++++++++++++++++= ++++ drivers/pci/controller/pci-host-common.h | 1 + drivers/pci/pci.c | 1 + drivers/pci/pcie/err.c | 1 + 4 files changed, 36 insertions(+) diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/control= ler/pci-host-common.c index b0992325dd65f0da8e216ec8a2153af365225d1d..51eacb6cb57443338e995f17afd= 3b2564bbd1f83 100644 --- a/drivers/pci/controller/pci-host-common.c +++ b/drivers/pci/controller/pci-host-common.c @@ -12,9 +12,11 @@ #include #include #include +#include #include #include =20 +#include "../pci.h" #include "pci-host-common.h" =20 static void gen_pci_unmap_cfg(void *ptr) @@ -104,5 +106,36 @@ void pci_host_common_remove(struct platform_device *pd= ev) } EXPORT_SYMBOL_GPL(pci_host_common_remove); =20 +static pci_ers_result_t pci_host_reset_root_port(struct pci_dev *dev) +{ + int ret; + + ret =3D pci_bus_error_reset(dev); + if (ret) { + pci_err(dev, "Failed to reset Root Port: %d\n", ret); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_info(dev, "Root Port has been reset\n"); + + return PCI_ERS_RESULT_RECOVERED; +} + +static void pci_host_recover_root_port(struct pci_dev *port) +{ +#if IS_ENABLED(CONFIG_PCIEAER) + pcie_do_recovery(port, pci_channel_io_frozen, pci_host_reset_root_port); +#else + pci_host_reset_root_port(port); +#endif +} + +void pci_host_handle_link_down(struct pci_dev *port) +{ + pci_info(port, "Recovering Root Port due to Link Down\n"); + pci_host_recover_root_port(port); +} +EXPORT_SYMBOL_GPL(pci_host_handle_link_down); + MODULE_DESCRIPTION("Common library for PCI host controller drivers"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/pci-host-common.h b/drivers/pci/control= ler/pci-host-common.h index 65bd9e032353827221a6af59858c46fdbe5916bf..cb0a07c8773ec87838164e994b3= 4a62d2c8118be 100644 --- a/drivers/pci/controller/pci-host-common.h +++ b/drivers/pci/controller/pci-host-common.h @@ -16,5 +16,6 @@ int pci_host_common_probe(struct platform_device *pdev); int pci_host_common_init(struct platform_device *pdev, const struct pci_ecam_ops *ops); void pci_host_common_remove(struct platform_device *pdev); +void pci_host_handle_link_down(struct pci_dev *port); =20 #endif diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b29264aa2be33b18a58b3b3db1d1fb0f6483e5e8..39310422634a9551efc8aded565= b7cc30f4989d0 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5768,6 +5768,7 @@ int pci_bus_error_reset(struct pci_dev *bridge) mutex_unlock(&pci_slot_mutex); return pci_bus_reset(bridge->subordinate, PCI_RESET_DO_RESET); } +EXPORT_SYMBOL_GPL(pci_bus_error_reset); =20 /** * pci_probe_reset_bus - probe whether a PCI bus can be reset diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index b834fc0d705938540d3d7d3d8739770c09fe7cf1..3e3084bb7cb7fa06b526e6fab60= e77927aba0ad0 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -270,3 +270,4 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, =20 return status; } +EXPORT_SYMBOL_GPL(pcie_do_recovery); --=20 2.45.2 From nobody Tue Oct 7 01:53:54 2025 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 3E29D2853E0; Tue, 15 Jul 2025 14:21:11 +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=1752589271; cv=none; b=PkEaN68eeAGiP1KKgDf0eMcpbDfJoMnTw13+5RAYkXkvtpT4HfPzcN4KJTAFonSl6Qe+p7v6IzxaKXT86U3Nj2wWNnBOQ4vJV80+vzdEA5BQswQQgL4YXWOkK9Y2XQ6buuYh/r47RGi/jGqydpzdJ6H+ZVQbevqaIuGy/QEzftY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752589271; c=relaxed/simple; bh=4JhhB1mQygUC88Tou4uhVLdc03cPbzCj4an+sUn3wpI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=X3NxTeAr1n/d2FpRmmzI1LmDEhJdZC86XkMri/sajRoQNYZ6CLN0shLlqo56vXAna8u1xhray4gFJ1jRyIFHIj74yqipaUG6mOSaEw3cqE5HniDMrNOFNTz/Nj0YOcOoomvw9pHmcBFv8p7DyR6YMWk4G5PJ6zj26rLZo9COLqk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ivfVQ2ir; 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="ivfVQ2ir" Received: by smtp.kernel.org (Postfix) with ESMTPS id 14956C4CEF9; Tue, 15 Jul 2025 14:21:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752589271; bh=4JhhB1mQygUC88Tou4uhVLdc03cPbzCj4an+sUn3wpI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=ivfVQ2ircVep7BPS9t+rG8HnvvCgxj5NjO8ajrts+mexcBueojXU/zdq2mwnyUbdX kzxUmMLRJkTPpaUfhoUT08vN68qbgelnLF5VQZ8s0iH1h4zTNtZO1Eeja/zb7/JoEp EONq0qYyjbb/oGmPKK799Mez0Iafaj9ctQSTpFZgDLQS7xFlJi3p2FEu+fYpFMql5k hrmXaa7gsiQe2Ko6cCv3ZK5EYABSkSv3kAYAJzlQAesRr2yw4UIXTVU4O3Jzoc7GPl mayivOXECqQ5/6St3r39oucBkCG9i/HjV1wFP6wHxfS5+OIHotjHD+VYxWhTDvCtN4 Qc26zOEU/40Zw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0C0DCC83F34; Tue, 15 Jul 2025 14:21:11 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Jul 2025 19:51:06 +0530 Subject: [PATCH v6 3/4] PCI: qcom: Add support for resetting the Root Port due to link down event Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250715-pci-port-reset-v6-3-6f9cce94e7bb@oss.qualcomm.com> References: <20250715-pci-port-reset-v6-0-6f9cce94e7bb@oss.qualcomm.com> In-Reply-To: <20250715-pci-port-reset-v6-0-6f9cce94e7bb@oss.qualcomm.com> To: Bjorn Helgaas , Mahesh J Salgaonkar , Oliver O'Halloran , Will Deacon , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Manivannan Sadhasivam , Rob Herring , Heiko Stuebner , Philipp Zabel Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-rockchip@lists.infradead.org, Niklas Cassel , Wilfred Mallawa , Krishna Chaitanya Chundru , mani@kernel.org, Lukas Wunner , Manivannan Sadhasivam , Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=8942; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=hcHUE0Es+rhE1k65uaN43jzCwIv2KxCfrP4I/tTARuY=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBodmPU7h4g+XiDGSCp70X2Mbn0SjERWhtNglsfA wwuX+QzMCqJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaHZj1AAKCRBVnxHm/pHO 9c1aB/9ZXgau1A2R7jRCcx+v1G7ANPo8guKtUwp2ehiqWQZH7I+bAbr2CbE1DDDZ5RgitzGddvx HYya5RGzlC4C8gWmM2liAGPGzVK7KybirCIp5xRctnMMKJPe3iVSQFT/UHNA0tG5E5rWjOtKqK3 6Uo52UtsP2MNZbfO0/ouFqwC0glZysSfSJdQkaAu6Rj0KOLGA7rMgcBpVtonP/od+SjskcHasqI Yf2fVhIuc3QK216G+MzLYQ6QXbkGbcrxI9B/35VdHaHejwrGhIfSE72OGqlNqSaP/18Papfvh9q NPrTgY7xRKJx0jaJt6MpEtsItzJb4zj2D7QzVb/TboVhufYU X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Manivannan Sadhasivam The PCIe link can go down under circumstances such as the device firmware crash, link instability, etc... When that happens, the PCIe Root Port needs to be reset to make it operational again. Currently, the driver is not handling the link down event, due to which the users have to restart the machine to make PCIe link operational again. So fix it by detecting the link down event and resetting the Root Port. Since the Qcom PCIe controllers report the link down event through the 'global' IRQ, enable the link down event by setting PARF_INT_ALL_LINK_DOWN bit in PARF_INT_ALL_MASK register. In the case of the event, iterate through the available Root Ports and call pci_host_handle_link_down() API with Root Port 'pci_dev' to let the PCI core handle the link down condition. Note that both link up and link down events could be set at a time when the handler runs. So always handle link down first. Since Qcom PCIe controllers only support one Root Port per controller instance, the API will be called only once. But the looping is necessary as there is no PCI API available to fetch the Root Port instance without the child 'pci_dev'. The API will internally call, 'pci_host_bridge::reset_root_port()' callback to reset the Root Port in a platform specific way. So implement the callback to reset the Root Port by first resetting the PCIe core, followed by reinitializing the resources and then finally starting the link again. Signed-off-by: Manivannan Sadhasivam Signed-off-by: Manivannan Sadhasivam Tested-by: Brian Norris Tested-by: Krishna Chaitanya Chundru Tested-by: Niklas Cassel --- drivers/pci/controller/dwc/Kconfig | 1 + drivers/pci/controller/dwc/pcie-qcom.c | 120 +++++++++++++++++++++++++++++= +--- 2 files changed, 113 insertions(+), 8 deletions(-) diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dw= c/Kconfig index d9f0386396edf66ad0e514a0f545ed24d89fcb6c..ce04ee6fbd99cbcce5d2f3a75eb= d72a17070b7b7 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -296,6 +296,7 @@ config PCIE_QCOM select PCIE_DW_HOST select CRC8 select PCIE_QCOM_COMMON + select PCI_HOST_COMMON help Say Y here to enable PCIe controller support on Qualcomm SoCs. The PCIe controller uses the DesignWare core plus Qualcomm-specific diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controlle= r/dwc/pcie-qcom.c index c789e3f856550bcfa1ce09962ba9c086d117de05..5f7b2b80aace742780e5bc5b479= f4f64ab778453 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -34,6 +34,7 @@ #include =20 #include "../../pci.h" +#include "../pci-host-common.h" #include "pcie-designware.h" #include "pcie-qcom-common.h" =20 @@ -55,6 +56,7 @@ #define PARF_INT_ALL_STATUS 0x224 #define PARF_INT_ALL_CLEAR 0x228 #define PARF_INT_ALL_MASK 0x22c +#define PARF_STATUS 0x230 #define PARF_SID_OFFSET 0x234 #define PARF_BDF_TRANSLATE_CFG 0x24c #define PARF_DBI_BASE_ADDR_V2 0x350 @@ -130,9 +132,14 @@ =20 /* PARF_LTSSM register fields */ #define LTSSM_EN BIT(8) +#define SW_CLEAR_FLUSH_MODE BIT(10) +#define FLUSH_MODE BIT(11) =20 /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */ -#define PARF_INT_ALL_LINK_UP BIT(13) +#define INT_ALL_LINK_DOWN 1 +#define INT_ALL_LINK_UP 13 +#define PARF_INT_ALL_LINK_DOWN BIT(INT_ALL_LINK_DOWN) +#define PARF_INT_ALL_LINK_UP BIT(INT_ALL_LINK_UP) #define PARF_INT_MSI_DEV_0_7 GENMASK(30, 23) =20 /* PARF_NO_SNOOP_OVERRIDE register fields */ @@ -145,6 +152,9 @@ /* PARF_BDF_TO_SID_CFG fields */ #define BDF_TO_SID_BYPASS BIT(0) =20 +/* PARF_STATUS fields */ +#define FLUSH_COMPLETED BIT(8) + /* ELBI_SYS_CTRL register fields */ #define ELBI_SYS_CTRL_LT_ENABLE BIT(0) =20 @@ -169,6 +179,7 @@ PCIE_CAP_SLOT_POWER_LIMIT_SCALE) =20 #define PERST_DELAY_US 1000 +#define FLUSH_TIMEOUT_US 100 =20 #define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) =20 @@ -274,11 +285,14 @@ struct qcom_pcie { struct icc_path *icc_cpu; const struct qcom_pcie_cfg *cfg; struct dentry *debugfs; + int global_irq; bool suspended; bool use_pm_opp; }; =20 #define to_qcom_pcie(x) dev_get_drvdata((x)->dev) +static int qcom_pcie_reset_root_port(struct pci_host_bridge *bridge, + struct pci_dev *pdev); =20 static void qcom_ep_reset_assert(struct qcom_pcie *pcie) { @@ -1263,6 +1277,8 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp) goto err_assert_reset; } =20 + pp->bridge->reset_root_port =3D qcom_pcie_reset_root_port; + return 0; =20 err_assert_reset: @@ -1517,6 +1533,78 @@ static void qcom_pcie_icc_opp_update(struct qcom_pci= e *pcie) } } =20 +/* + * Qcom PCIe controllers only support one Root Port per controller instanc= e. So + * this function ignores the 'pci_dev' associated with the Root Port and j= ust + * resets the host bridge, which in turn resets the Root Port also. + */ +static int qcom_pcie_reset_root_port(struct pci_host_bridge *bridge, + struct pci_dev *pdev) +{ + struct pci_bus *bus =3D bridge->bus; + struct dw_pcie_rp *pp =3D bus->sysdata; + struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); + struct qcom_pcie *pcie =3D to_qcom_pcie(pci); + struct device *dev =3D pcie->pci->dev; + u32 val; + int ret; + + /* Wait for the pending transactions to be completed */ + ret =3D readl_relaxed_poll_timeout(pcie->parf + PARF_STATUS, val, + val & FLUSH_COMPLETED, 10, + FLUSH_TIMEOUT_US); + if (ret) { + dev_err(dev, "Flush completion failed: %d\n", ret); + goto err_host_deinit; + } + + /* Clear the FLUSH_MODE to allow the core to be reset */ + val =3D readl(pcie->parf + PARF_LTSSM); + val |=3D SW_CLEAR_FLUSH_MODE; + writel(val, pcie->parf + PARF_LTSSM); + + /* Wait for the FLUSH_MODE to clear */ + ret =3D readl_relaxed_poll_timeout(pcie->parf + PARF_LTSSM, val, + !(val & FLUSH_MODE), 10, + FLUSH_TIMEOUT_US); + if (ret) { + dev_err(dev, "Flush mode clear failed: %d\n", ret); + goto err_host_deinit; + } + + qcom_pcie_host_deinit(pp); + + ret =3D qcom_pcie_host_init(pp); + if (ret) { + dev_err(dev, "Host init failed\n"); + return ret; + } + + ret =3D dw_pcie_setup_rc(pp); + if (ret) + goto err_host_deinit; + + /* + * Re-enable global IRQ events as the PARF_INT_ALL_MASK register is + * non-sticky. + */ + if (pcie->global_irq) + writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_ALL_LINK_DOWN | + PARF_INT_MSI_DEV_0_7, pcie->parf + PARF_INT_ALL_MASK); + + qcom_pcie_start_link(pci); + dw_pcie_wait_for_link(pci); + + dev_dbg(dev, "Root Port reset completed\n"); + + return 0; + +err_host_deinit: + qcom_pcie_host_deinit(pp); + + return ret; +} + static int qcom_pcie_link_transition_count(struct seq_file *s, void *data) { struct qcom_pcie *pcie =3D (struct qcom_pcie *)dev_get_drvdata(s->private= ); @@ -1559,11 +1647,24 @@ static irqreturn_t qcom_pcie_global_irq_thread(int = irq, void *data) struct qcom_pcie *pcie =3D data; struct dw_pcie_rp *pp =3D &pcie->pci->pp; struct device *dev =3D pcie->pci->dev; - u32 status =3D readl_relaxed(pcie->parf + PARF_INT_ALL_STATUS); + struct pci_dev *port; + unsigned long status =3D readl_relaxed(pcie->parf + PARF_INT_ALL_STATUS); =20 writel_relaxed(status, pcie->parf + PARF_INT_ALL_CLEAR); =20 - if (FIELD_GET(PARF_INT_ALL_LINK_UP, status)) { + /* + * It is possible that both Link Up and Link Down events might have + * happended. So always handle Link Down first. + */ + if (test_and_clear_bit(INT_ALL_LINK_DOWN, &status)) { + dev_dbg(dev, "Received Link down event\n"); + for_each_pci_bridge(port, pp->bridge->bus) { + if (pci_pcie_type(port) =3D=3D PCI_EXP_TYPE_ROOT_PORT) + pci_host_handle_link_down(port); + } + } + + if (test_and_clear_bit(INT_ALL_LINK_UP, &status)) { dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); /* Rescan the bus to enumerate endpoint devices */ pci_lock_rescan_remove(); @@ -1571,11 +1672,12 @@ static irqreturn_t qcom_pcie_global_irq_thread(int = irq, void *data) pci_unlock_rescan_remove(); =20 qcom_pcie_icc_opp_update(pcie); - } else { - dev_WARN_ONCE(dev, 1, "Received unknown event. INT_STATUS: 0x%08x\n", - status); } =20 + if (status) + dev_WARN_ONCE(dev, 1, "Received unknown event. INT_STATUS: 0x%08x\n", + (u32) status); + return IRQ_HANDLED; } =20 @@ -1732,8 +1834,10 @@ static int qcom_pcie_probe(struct platform_device *p= dev) goto err_host_deinit; } =20 - writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_MSI_DEV_0_7, - pcie->parf + PARF_INT_ALL_MASK); + writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_ALL_LINK_DOWN | + PARF_INT_MSI_DEV_0_7, pcie->parf + PARF_INT_ALL_MASK); + + pcie->global_irq =3D irq; } =20 qcom_pcie_icc_opp_update(pcie); --=20 2.45.2 From nobody Tue Oct 7 01:53:54 2025 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 4D5BF2853F8; Tue, 15 Jul 2025 14:21:11 +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=1752589271; cv=none; b=PZymYf0nTZsI/5YbHOzJ4It16OgZA19HA+1HjyjwqmIw0H6IIvCKTzkuaj/RuNjPoazcONw5LYd+GJKvD6PWav3WhJhOLPc5wKyyt/Dj+4utdS64acrOCEDlh/+2hb13hxDzF2aa1Iqxk9ARB+aGJZmzzXvhUamUsGIQc9MBCSc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752589271; c=relaxed/simple; bh=G7l//qGdXYPqxEASGJgJ2nJDbecOqNR6zMbP4pmekmI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=F8MRvIvo2vgWHgPAhn4fvBlZIN/9XLm9QJG+HPWeo9G5ehxdnwIn8PX3tX6VM3A/VeC9WiB0xpZE+M3WfORVmudaugMPCdk49evXEFJFP3Rurut+rodlXOJq1HwjDodEVPD3IOpzsowUh37HEAnv3lRkruBjmwjc4n5LPddP7d4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BPRxkXAy; 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="BPRxkXAy" Received: by smtp.kernel.org (Postfix) with ESMTPS id 259E8C4CEFA; Tue, 15 Jul 2025 14:21:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752589271; bh=G7l//qGdXYPqxEASGJgJ2nJDbecOqNR6zMbP4pmekmI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=BPRxkXAy4avJ7lkPrwOdhgVDNXTOkUcLn6x2SrTuKEac80l0VDI3/+Y4FQOR+BKFE Gp9/omtL02JYojbJPlD6MCeiP6gJvVa8Y+FigNi1DvL04ddWq3eLBz9xPyqGSfP/8t 7fogamvophjaLFCnTjfo3f6It80bs113w7x/adWHhDyBC0RFf8aG6RiFW5j1ht9xLV ktW8WilrIycmDXvvKrkvoyPNkj3E11Zqbrbqs7k1s/VMpPVr+/VONi90OOzF7gJUqI gxz7B8gAw596nRaJxobNaxwSeay3xvr20UZPwVvDB6OnBNLHu6D+qMqXb3/MfOw8pN /cicgn5DgRcaQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A013C83F22; Tue, 15 Jul 2025 14:21:11 +0000 (UTC) From: Manivannan Sadhasivam via B4 Relay Date: Tue, 15 Jul 2025 19:51:07 +0530 Subject: [PATCH v6 4/4] PCI: dw-rockchip: Add support to reset Root Port upon link down event Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250715-pci-port-reset-v6-4-6f9cce94e7bb@oss.qualcomm.com> References: <20250715-pci-port-reset-v6-0-6f9cce94e7bb@oss.qualcomm.com> In-Reply-To: <20250715-pci-port-reset-v6-0-6f9cce94e7bb@oss.qualcomm.com> To: Bjorn Helgaas , Mahesh J Salgaonkar , Oliver O'Halloran , Will Deacon , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Manivannan Sadhasivam , Rob Herring , Heiko Stuebner , Philipp Zabel Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-rockchip@lists.infradead.org, Niklas Cassel , Wilfred Mallawa , Krishna Chaitanya Chundru , mani@kernel.org, Lukas Wunner , Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6494; i=manivannan.sadhasivam@oss.qualcomm.com; h=from:subject:message-id; bh=qm+3CMghWKFd+O3bZU1o020L8vQ/E6aH1MlFdMAO6mw=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBodmPUEht58g/m1MEl9CiEJpYG+gEPLb6qZmkLg 17gt0+/UWKJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaHZj1AAKCRBVnxHm/pHO 9bcvCACog/qU6v0/olHy9NV34E/7u439Cz/PsWLzz23mGRR95QAEtPckJ29Y1ReoXl9kRlBdEId s/ovkySUmIURZga8nOC7zVHFfFr23wBEF97zAJgyYKqRATv2x3wb2/OleIMcB6PgDH5arice5yO ZpIK7nMHSLoiqFBcPhdxbb/niu6d86Zqohw9mWyqObF9PweBctF/wXkvdg5Bh8JXyiOEH5VEQnK W69HHb4lv+/0WcQBvHfMuzFtzYb0wfcSLKzvzn1r9p48kJvfNjL1QdGxDHa8CXYybbkaWtgDvUX i0JqWYZjdOHMBKHRC9J+wqRHnGJyk238VRQsipjpNPJN4rxk X-Developer-Key: i=manivannan.sadhasivam@oss.qualcomm.com; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@oss.qualcomm.com/default with auth_id=461 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@oss.qualcomm.com From: Wilfred Mallawa The PCIe link may go down in cases like firmware crashes or unstable connections. When this occurs, the PCIe Root Port must be reset to restore the functionality. However, the current driver lacks link down handling, forcing users to reboot the system to recover. This patch implements the `reset_root_port` callback for link down handling for Rockchip DWC PCIe host controller. In which, the RC is reset, reconfigured and link training initiated to recover from the link down event. This also by extension fixes issues with sysfs initiated bus resets. In that, currently, when a sysfs initiated bus reset is issued, the endpoint device is non-functional after (may link up with downgraded link status). With the link down handling support, a sysfs initiated bus reset works as intended. Testing conducted on a ROCK5B board with an M.2 NVMe drive. Signed-off-by: Wilfred Mallawa [mani: rebased on top of the new version of reset_root_port series] Signed-off-by: Manivannan Sadhasivam Tested-by: Brian Norris Tested-by: Krishna Chaitanya Chundru Tested-by: Niklas Cassel --- drivers/pci/controller/dwc/Kconfig | 1 + drivers/pci/controller/dwc/pcie-dw-rockchip.c | 91 +++++++++++++++++++++++= +++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dw= c/Kconfig index ce04ee6fbd99cbcce5d2f3a75ebd72a17070b7b7..01e2650242ccc345bdd0568d082= 19527f00ed395 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -348,6 +348,7 @@ config PCIE_ROCKCHIP_DW_HOST depends on OF select PCIE_DW_HOST select PCIE_ROCKCHIP_DW + select PCI_HOST_COMMON help Enables support for the DesignWare PCIe controller in the Rockchip SoC (except RK3399) to work in host mode. diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/co= ntroller/dwc/pcie-dw-rockchip.c index 93171a3928794915ad1e8c03c017ce0afc1f9169..8f1a34c5fbabaacbd9624048ca4= c4f8dc29f2171 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -23,6 +23,7 @@ #include =20 #include "../../pci.h" +#include "../pci-host-common.h" #include "pcie-designware.h" =20 /* @@ -84,6 +85,9 @@ struct rockchip_pcie_of_data { const struct pci_epc_features *epc_features; }; =20 +static int rockchip_pcie_rc_reset_root_port(struct pci_host_bridge *bridge, + struct pci_dev *pdev); + static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip, u32 reg) { return readl_relaxed(rockchip->apb_base + reg); @@ -257,6 +261,7 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *p= p) rockchip); =20 rockchip_pcie_enable_l0s(pci); + pp->bridge->reset_root_port =3D rockchip_pcie_rc_reset_root_port; =20 return 0; } @@ -448,6 +453,7 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int = irq, void *arg) struct dw_pcie *pci =3D &rockchip->pci; struct dw_pcie_rp *pp =3D &pci->pp; struct device *dev =3D pci->dev; + struct pci_dev *port; u32 reg; =20 reg =3D rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); @@ -456,6 +462,14 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int= irq, void *arg) dev_dbg(dev, "PCIE_CLIENT_INTR_STATUS_MISC: %#x\n", reg); dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip)); =20 + if (reg & PCIE_LINK_REQ_RST_NOT_INT) { + dev_dbg(dev, "hot reset or link-down reset\n"); + for_each_pci_bridge(port, pp->bridge->bus) { + if (pci_pcie_type(port) =3D=3D PCI_EXP_TYPE_ROOT_PORT) + pci_host_handle_link_down(port); + } + } + if (reg & PCIE_RDLH_LINK_UP_CHGED) { if (rockchip_pcie_link_up(pci)) { dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); @@ -537,8 +551,8 @@ static int rockchip_pcie_configure_rc(struct platform_d= evice *pdev, return ret; } =20 - /* unmask DLL up/down indicator */ - val =3D HIWORD_UPDATE(PCIE_RDLH_LINK_UP_CHGED, 0); + /* unmask DLL up/down indicator and hot reset/link-down reset irq */ + val =3D HIWORD_UPDATE(PCIE_RDLH_LINK_UP_CHGED | PCIE_LINK_REQ_RST_NOT_INT= , 0); rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_INTR_MASK_MISC); =20 return ret; @@ -689,6 +703,79 @@ static int rockchip_pcie_probe(struct platform_device = *pdev) return ret; } =20 +static int rockchip_pcie_rc_reset_root_port(struct pci_host_bridge *bridge, + struct pci_dev *pdev) +{ + struct pci_bus *bus =3D bridge->bus; + struct dw_pcie_rp *pp =3D bus->sysdata; + struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); + struct rockchip_pcie *rockchip =3D to_rockchip_pcie(pci); + struct device *dev =3D rockchip->pci.dev; + u32 val; + int ret; + + dw_pcie_stop_link(pci); + clk_bulk_disable_unprepare(rockchip->clk_cnt, rockchip->clks); + rockchip_pcie_phy_deinit(rockchip); + + ret =3D reset_control_assert(rockchip->rst); + if (ret) + return ret; + + ret =3D rockchip_pcie_phy_init(rockchip); + if (ret) + goto disable_regulator; + + ret =3D reset_control_deassert(rockchip->rst); + if (ret) + goto deinit_phy; + + ret =3D rockchip_pcie_clk_init(rockchip); + if (ret) + goto deinit_phy; + + ret =3D pp->ops->init(pp); + if (ret) { + dev_err(dev, "Host init failed: %d\n", ret); + goto deinit_clk; + } + + /* LTSSM enable control mode */ + val =3D HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); + rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); + + rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, PCIE_CLIENT_GENER= AL_CON); + + ret =3D dw_pcie_setup_rc(pp); + if (ret) { + dev_err(dev, "Failed to setup RC: %d\n", ret); + goto deinit_clk; + } + + /* unmask DLL up/down indicator and hot reset/link-down reset irq */ + val =3D HIWORD_UPDATE(PCIE_RDLH_LINK_UP_CHGED | PCIE_LINK_REQ_RST_NOT_INT= , 0); + rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_INTR_MASK_MISC); + + ret =3D dw_pcie_start_link(pci); + if (ret) + goto deinit_clk; + + /* Ignore errors, the link may come up later */ + dw_pcie_wait_for_link(pci); + dev_dbg(dev, "Root Port reset completed\n"); + return ret; + +deinit_clk: + clk_bulk_disable_unprepare(rockchip->clk_cnt, rockchip->clks); +deinit_phy: + rockchip_pcie_phy_deinit(rockchip); +disable_regulator: + if (rockchip->vpcie3v3) + regulator_disable(rockchip->vpcie3v3); + + return ret; +} + static const struct rockchip_pcie_of_data rockchip_pcie_rc_of_data_rk3568 = =3D { .mode =3D DW_PCIE_RC_TYPE, }; --=20 2.45.2