From mboxrd@z Thu Jan 1 00:00:00 1970 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 4E70B220688; Sun, 26 Jan 2025 15:03: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=1737903828; cv=none; b=VlFH4u2Q6wyBnB+PtFubeYHKZb4g7zaoWqC/+lj/sw6hYFDB5d17ijDdVSdUdk1AkdIWPpn9jAyG7URw2MMd6yhsUkRcN6W1UePNQOs8dX/5/hsSmvPh/JQCBjaYs9TiT+C6oBJ6jrb8QsrQTxZCNWFxXKQwHZ5xLmVKfXYkU6k= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737903828; c=relaxed/simple; bh=6WDegq0g+rvUu4CoGCs63VWBKLiD07QZv1qR80IXc9o=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HDSqZzqOF/tVKEzkS98wVzhQ21YAwhXipA7LE6i9f0irgpxQNTt8XIltcZZ7SCGTnlSJnW0FvhLiEnMN42WWQcKshcKlaKLyC1rOOGEOcT6rB5dKsfVwZJatFf0bfITqO/fkFrmd85zdb5bnfyQFXMtZyifUyZODbA4LrOMZ7cU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tx0nSg2K; 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="tx0nSg2K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B9CEEC4CEE4; Sun, 26 Jan 2025 15:03:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1737903828; bh=6WDegq0g+rvUu4CoGCs63VWBKLiD07QZv1qR80IXc9o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tx0nSg2KStEfDYpEGyeaOI7vGABB9pD6XemFsZZ42Qf0BP3CCxpgNooAHrfF+ddPz PL7iXXcknqjuvEbOcCT19T12o+O42wSojL6H4iT03Mv/kx91sm3KCaMJN1/rqRJ2ir xHPEHsr7KwvBFTw5feJ7tXPI1g+DUNF45D0AAeP3h5OHn3gusp2JJuKTiFTqSULWO4 LThumXVh+OefdwvSg4KoMpefLlEXbJURzf8DJiHPzlIpK4hoeDEhUVQxCX6lcXl6Cs UkybB9tmbKUZEuSBA74SkCLA3BwKnV3GheRHhIOFKn5EQaSTid8DD/2dRN8EZmOa5i tR6t5Ck7+cbeA== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: "Maciej S. Szmigiero" , Sergey Ryazanov , Jakub Kicinski , Sasha Levin , m.chetan.kumar@intel.com, loic.poulain@linaro.org, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, pabeni@redhat.com, netdev@vger.kernel.org Subject: [PATCH AUTOSEL 6.6 16/19] net: wwan: iosm: Fix hibernation by re-binding the driver around it Date: Sun, 26 Jan 2025 10:03:11 -0500 Message-Id: <20250126150315.956795-16-sashal@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250126150315.956795-1-sashal@kernel.org> References: <20250126150315.956795-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.6.74 Content-Transfer-Encoding: 8bit From: "Maciej S. Szmigiero" [ Upstream commit 0b6f6593aa8c3a05f155c12fd0e7ad33a5149c31 ] Currently, the driver is seriously broken with respect to the hibernation (S4): after image restore the device is back into IPC_MEM_EXEC_STAGE_BOOT (which AFAIK means bootloader stage) and needs full re-launch of the rest of its firmware, but the driver restore handler treats the device as merely sleeping and just sends it a wake-up command. This wake-up command times out but device nodes (/dev/wwan*) remain accessible. However attempting to use them causes the bootloader to crash and enter IPC_MEM_EXEC_STAGE_CD_READY stage (which apparently means "a crash dump is ready"). It seems that the device cannot be re-initialized from this crashed stage without toggling some reset pin (on my test platform that's apparently what the device _RST ACPI method does). While it would theoretically be possible to rewrite the driver to tear down the whole MUX / IPC layers on hibernation (so the bootloader does not crash from improper access) and then re-launch the device on restore this would require significant refactoring of the driver (believe me, I've tried), since there are quite a few assumptions hard-coded in the driver about the device never being partially de-initialized (like channels other than devlink cannot be closed, for example). Probably this would also need some programming guide for this hardware. Considering that the driver seems orphaned [1] and other people are hitting this issue too [2] fix it by simply unbinding the PCI driver before hibernation and re-binding it after restore, much like USB_QUIRK_RESET_RESUME does for USB devices that exhibit a similar problem. Tested on XMM7360 in HP EliteBook 855 G7 both with s2idle (which uses the existing suspend / resume handlers) and S4 (which uses the new code). [1]: https://lore.kernel.org/all/c248f0b4-2114-4c61-905f-466a786bdebb@leemhuis.info/ [2]: https://github.com/xmm7360/xmm7360-pci/issues/211#issuecomment-1804139413 Reviewed-by: Sergey Ryazanov Signed-off-by: Maciej S. Szmigiero Link: https://patch.msgid.link/e60287ebdb0ab54c4075071b72568a40a75d0205.1736372610.git.mail@maciej.szmigiero.name Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/wwan/iosm/iosm_ipc_pcie.c | 56 ++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c index 04517bd3325a2..a066977af0be5 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c +++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "iosm_ipc_imem.h" @@ -18,6 +19,7 @@ MODULE_LICENSE("GPL v2"); /* WWAN GUID */ static guid_t wwan_acpi_guid = GUID_INIT(0xbad01b75, 0x22a8, 0x4f48, 0x87, 0x92, 0xbd, 0xde, 0x94, 0x67, 0x74, 0x7d); +static bool pci_registered; static void ipc_pcie_resources_release(struct iosm_pcie *ipc_pcie) { @@ -448,7 +450,6 @@ static struct pci_driver iosm_ipc_driver = { }, .id_table = iosm_ipc_ids, }; -module_pci_driver(iosm_ipc_driver); int ipc_pcie_addr_map(struct iosm_pcie *ipc_pcie, unsigned char *data, size_t size, dma_addr_t *mapping, int direction) @@ -530,3 +531,56 @@ void ipc_pcie_kfree_skb(struct iosm_pcie *ipc_pcie, struct sk_buff *skb) IPC_CB(skb)->mapping = 0; dev_kfree_skb(skb); } + +static int pm_notify(struct notifier_block *nb, unsigned long mode, void *_unused) +{ + if (mode == PM_HIBERNATION_PREPARE || mode == PM_RESTORE_PREPARE) { + if (pci_registered) { + pci_unregister_driver(&iosm_ipc_driver); + pci_registered = false; + } + } else if (mode == PM_POST_HIBERNATION || mode == PM_POST_RESTORE) { + if (!pci_registered) { + int ret; + + ret = pci_register_driver(&iosm_ipc_driver); + if (ret) { + pr_err(KBUILD_MODNAME ": unable to re-register PCI driver: %d\n", + ret); + } else { + pci_registered = true; + } + } + } + + return 0; +} + +static struct notifier_block pm_notifier = { + .notifier_call = pm_notify, +}; + +static int __init iosm_ipc_driver_init(void) +{ + int ret; + + ret = pci_register_driver(&iosm_ipc_driver); + if (ret) + return ret; + + pci_registered = true; + + register_pm_notifier(&pm_notifier); + + return 0; +} +module_init(iosm_ipc_driver_init); + +static void __exit iosm_ipc_driver_exit(void) +{ + unregister_pm_notifier(&pm_notifier); + + if (pci_registered) + pci_unregister_driver(&iosm_ipc_driver); +} +module_exit(iosm_ipc_driver_exit); -- 2.39.5