From patchwork Thu Apr 17 17:16:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manivannan Sadhasivam X-Patchwork-Id: 14055906 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 88056253F23; Thu, 17 Apr 2025 17:16:37 +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=1744910197; cv=none; b=my6vRsbQs1Xbpzw5aajZ2cxXR9tGvQho2syZiSWnkwOiOG61oalYNsqYxGQqga7O4js9K/q9qzY1d0uZhNJSIlpBWQGhHqbTzhx8AY7uEdgCWcLb4L0l1AeF1LKEBRqC84KMHSG+DDl0aHFo+SMiKSwJuIcFDI+3ji4Nvd3x9RE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744910197; c=relaxed/simple; bh=dMHzWB9kIKTL59eAbp8GBWm7d2Y/GBPQQozuBhIlVTI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gCZ6VMiDOwEXcKRydkzA2EanbGgurnXgy5XUduxZYBmt6YgML6wJ4h15EVs98exihNrrV7ntARh43eOYSMVfa9Iqtqt4zzjCn23acxwCLBmc/410z+uv3oDUAKLXr137On8Z+LCf5QZasPQ6+Yt12ZiVk0OnyYnocd6OjrsG4Cc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pVheOy78; 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="pVheOy78" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2493AC4CEF1; Thu, 17 Apr 2025 17:16:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744910197; bh=dMHzWB9kIKTL59eAbp8GBWm7d2Y/GBPQQozuBhIlVTI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=pVheOy78yI5PLUwpmg7RUGQ+xIHQIXO+yJSlXozJnxTMYjawtMKurEOjz+3RxNknY JrKHwEtgYXM37k38xqP82RQARzN8w5WSr+MbdjpG/O2mXeV3JqWBEIRHy6E8wcU/jR AL4xucccXEu8an1syJHUJvWAqpRIEQCBkxWDg0izEc8itI8mj867eLi6yJWhHj64ss fKHy0XNpd+6KcF9TgV//foshvYOUEAZ7Yy5SRqCmiDYygNELYeHhPV9TtwabbTj4NE u8+rL3yKafsNnrPoRhaeGh6BaEybNqXNis7r56D7W/BD21/qFFD67kh5cTua0bgpni JKiySu7Dz2K8g== 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 19F10C369CA; Thu, 17 Apr 2025 17:16:37 +0000 (UTC) Date: Thu, 17 Apr 2025 22:46:30 +0530 Subject: [PATCH v3 4/5] PCI: host-common: Add link down handling for host bridges Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250417-pcie-reset-slot-v3-4-59a10811c962@linaro.org> References: <20250417-pcie-reset-slot-v3-0-59a10811c962@linaro.org> In-Reply-To: <20250417-pcie-reset-slot-v3-0-59a10811c962@linaro.org> To: Mahesh J Salgaonkar , Oliver O'Halloran , Bjorn Helgaas , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy?= =?utf-8?q?=C5=84ski?= , Rob Herring , Zhou Wang , Will Deacon , Robert Richter , Alyssa Rosenzweig , Marc Zyngier , Conor Dooley , Daire McNamara Cc: dingwei@marvell.com, cassel@kernel.org, Lukas Wunner , Krishna Chaitanya Chundru , linuxppc-dev@lists.ozlabs.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-riscv@lists.infradead.org, Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5013; i=manivannan.sadhasivam@linaro.org; h=from:subject:message-id; bh=qpK9YNjA+2cjuQSqqCobAzDIsbb17j/aI+T6GzJd5yE=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBoATdwdRz5XBSP4wHusIJXgeOncEvLTPVCWEVyK gYb95hvbZmJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaAE3cAAKCRBVnxHm/pHO 9ZNCB/9zQ/PnbnjJRfU/Jt3gZkk4/FjfLeijn6gOspoxKHnLK3fq67GJzSRTPSvwGC/zDeAzr+D VQ3uA4GoLC+4aHNvnhmD4m1tugl2NmPkICyXeAH006qrks6ihnGSf5XKuKOE0WdziPusbXQuS07 +V6pAB3VV5pLdexUfvcXveyEugHIOp+Xgs2luquQKWCdHTsd7Cdjd3jEUUzynwmuwUFUxb5njCu LFpnBARVHf7oLISwESilqg1fQYnIhemWshp48v4Tukhl/40bs0BSaqhiDXj85kUxlOJaW6fPpQM TLIjtX4lLy/BkiAxxK6C22p9N47lBv7seRHKUJcFzzZ3qWuG X-Developer-Key: i=manivannan.sadhasivam@linaro.org; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 X-Endpoint-Received: by B4 Relay for manivannan.sadhasivam@linaro.org/default with auth_id=185 X-Original-From: Manivannan Sadhasivam Reply-To: manivannan.sadhasivam@linaro.org From: Manivannan Sadhasivam From: Manivannan Sadhasivam The PCI link, when down, needs to be recovered to bring it back. But that cannot be done in a generic way as link recovery procedure is specific to host bridges. So add a new API pci_host_handle_link_down() that could be called by the host bridge drivers when the link goes down. The API will iterate through all the slots and calls the 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 the downstream devices. Then, pci_host_reset_slot() will be called for the slot, which will reset the slot using 'reset_slot' 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. In case if the AER support is not enabled in the kernel, only pci_bus_error_reset() will be called for each slots as there is no way we could inform the drivers about link recovery. Signed-off-by: Manivannan Sadhasivam --- drivers/pci/controller/pci-host-common.c | 58 ++++++++++++++++++++++++++++++++ drivers/pci/controller/pci-host-common.h | 1 + drivers/pci/pci.c | 1 + drivers/pci/pcie/err.c | 1 + 4 files changed, 61 insertions(+) diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/controller/pci-host-common.c index f93bc7034e697250711833a5151f7ef177cd62a0..f916f0a874a61ddfbfd99f96975c00fb66dd224c 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 +#include "../pci.h" #include "pci-host-common.h" static void gen_pci_unmap_cfg(void *ptr) @@ -96,5 +98,61 @@ void pci_host_common_remove(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(pci_host_common_remove); +#if IS_ENABLED(CONFIG_PCIEAER) +static pci_ers_result_t pci_host_reset_slot(struct pci_dev *dev) +{ + int ret; + + ret = pci_bus_error_reset(dev); + if (ret) { + pci_err(dev, "Failed to reset slot: %d\n", ret); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_info(dev, "Slot has been reset\n"); + + return PCI_ERS_RESULT_RECOVERED; +} + +static void pci_host_recover_slots(struct pci_host_bridge *host) +{ + struct pci_bus *bus = host->bus; + struct pci_dev *dev; + + for_each_pci_bridge(dev, bus) { + if (!pci_is_root_bus(bus)) + continue; + + pcie_do_recovery(dev, pci_channel_io_frozen, + pci_host_reset_slot); + } +} +#else +static void pci_host_recover_slots(struct pci_host_bridge *host) +{ + struct pci_bus *bus = host->bus; + struct pci_dev *dev; + int ret; + + for_each_pci_bridge(dev, bus) { + if (!pci_is_root_bus(bus)) + continue; + + ret = pci_bus_error_reset(dev); + if (ret) + pci_err(dev, "Failed to reset slot: %d\n", ret); + else + pci_info(dev, "Slot has been reset\n"); + } +} +#endif + +void pci_host_handle_link_down(struct pci_host_bridge *bridge) +{ + dev_info(&bridge->dev, "Recovering slots due to Link Down\n"); + pci_host_recover_slots(bridge); +} +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/controller/pci-host-common.h index 30253ff26e01fb445ecf67b795209e6d0a9ec7c4..f5d05d6c761ffea551c670f9af2cea870a8c2daa 100644 --- a/drivers/pci/controller/pci-host-common.h +++ b/drivers/pci/controller/pci-host-common.h @@ -12,5 +12,6 @@ int pci_host_common_probe(struct platform_device *pdev); void pci_host_common_remove(struct platform_device *pdev); +void pci_host_handle_link_down(struct pci_host_bridge *bridge); #endif diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 13709bb898a967968540826a2b7ee8ade6b7e082..4d396bbab4a8f33cae0ffe8982da120a9f1d92c9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5781,6 +5781,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); /** * 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..3e3084bb7cb7fa06b526e6fab60e77927aba0ad0 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, return status; } +EXPORT_SYMBOL_GPL(pcie_do_recovery);