From nobody Sun Oct 5 23:38:28 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 9558223535F; Mon, 28 Jul 2025 08:24: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=1753691088; cv=none; b=UipmtD7cH5IovpXXjf+qmgGKaql/LeToemtYX4bY1d6Xdk5//YLw2HTI60TIjhML3oSsOqpfHRG57ZfU+2xqZdyRgjj2y6FN7pCh3LYSvNX9ML65qrtFiAy7O0LGS22msQF4XWGFG5Gy1M2HCBduf6zk+Xu7GDh6jP7hZA2En+E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691088; c=relaxed/simple; bh=339S8W+LIbjLrc20LVLjOM20MZJcWx7ggezRpXxT290=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=spKFkSHrjMDHkKYn74NbWNECtAgrKK4EfMJQbd13Wc7Q6HwhRG4EK21hFjoEPe4g166fUAbLeIebNHxnn8n/uNia5ttPa/0QQtIpWySc+xgNlhIqz6RajUwkOTWXWJ4xak+qoySVrF4++p2Va6OMgUW1ngMQXsnwh2sIQyPBF8I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Keksb5hB; 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="Keksb5hB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 93042C4CEF9; Mon, 28 Jul 2025 08:24:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691088; bh=339S8W+LIbjLrc20LVLjOM20MZJcWx7ggezRpXxT290=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Keksb5hBboY7LZ/TRxonenEr39KjJj2lrEO06nYmBJmzdKjWAZZjlRnAEfp9y8tGW lvoxJBKn37mhQMYn8quJt1/klA3Irm9/BH4roP86BfhUOoz+oXxipVKiWjEzhna8SW PgerGsO1jpZHxCch9pO5rhcRwkaymMCFa1oZwe0xnxHJNPHyAai2fJa0MTeeX+Xwry ActoKKkoL8BUyxQpVeTLeThD5t477BQeXqNk/AhlGT1Y5xkTinGKESIQlYmMfC924D 4PfMzLWNYcvXfP94YamRzAXRx8vazDuxZ3utreP65y0GNYk30Ag/Lxi858qO582Q/q q2uvb7UzalM9w== From: Chris Li Date: Mon, 28 Jul 2025 01:24:31 -0700 Subject: [PATCH RFC 01/25] PCI/LUO: Register with Liveupdate Orchestrator 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: <20250728-luo-pci-v1-1-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Register PCI subsystem with the Liveupdate Orchestrator and provide noop liveupdate callbacks. Signed-off-by: Chris Li --- drivers/pci/Makefile | 1 + drivers/pci/liveupdate.c | 54 ++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 55 insertions(+) diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 67647f1880fb8fb0629d680398f5b88d69aac660..aa1bac7aed7d12c641a6b55e561= 76fb3cdde4c91 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_PCI_DOE) +=3D doe.o obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) +=3D of_property.o obj-$(CONFIG_PCI_NPEM) +=3D npem.o obj-$(CONFIG_PCIE_TPH) +=3D tph.o +obj-$(CONFIG_LIVEUPDATE) +=3D liveupdate.o =20 # Endpoint library must be initialized before its users obj-$(CONFIG_PCI_ENDPOINT) +=3D endpoint/ diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c new file mode 100644 index 0000000000000000000000000000000000000000..86b4f3a2fb44781c6e323ba029d= b510450556fa9 --- /dev/null +++ b/drivers/pci/liveupdate.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright (c) 2025, Google LLC. + * Chris Li + */ + +#define pr_fmt(fmt) "PCI liveupdate: " fmt + +#include + +#define PCI_SUBSYSTEM_NAME "pci" + +static int pci_liveupdate_prepare(void *arg, u64 *data) +{ + pr_info("prepare data[%llx]\n", *data); + return 0; +} + +static int pci_liveupdate_freeze(void *arg, u64 *data) +{ + pr_info("freeze data[%llx]\n", *data); + return 0; +} + +static void pci_liveupdate_cancel(void *arg, u64 data) +{ + pr_info("cancel data[%llx]\n", data); +} + +static void pci_liveupdate_finish(void *arg, u64 data) +{ + pr_info("finish data[%llx]\n", data); +} + +struct liveupdate_subsystem pci_liveupdate_ops =3D { + .prepare =3D pci_liveupdate_prepare, + .freeze =3D pci_liveupdate_freeze, + .cancel =3D pci_liveupdate_cancel, + .finish =3D pci_liveupdate_finish, + .name =3D PCI_SUBSYSTEM_NAME, +}; + +static int __init pci_liveupdate_init(void) +{ + int ret; + + ret =3D liveupdate_register_subsystem(&pci_liveupdate_ops); + if (ret && liveupdate_state_updated()) + panic("PCI liveupdate: Register subsystem failed: %d", ret); + WARN(ret, "PCI liveupdate: Register subsystem failed %d", ret); + return 0; +} +late_initcall_sync(pci_liveupdate_init); --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 DF9EA2367D5; Mon, 28 Jul 2025 08:24: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=1753691089; cv=none; b=jjf90Wpl+LO8dC2AT+rnopu8f/c6sz21VGQmaH/xvjup7DPOK5gGgKKlRiGyDwunf+5KfiXls+ht17hJ04MAKHZzUq42iP5MMH/jPtO0rBG3GvRKYLwEEiDGwUI6rwF6G807tS3MnegUpjTR7ek2qbGhLSGhqBnTVGoPEpV4Hr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691089; c=relaxed/simple; bh=DDHEw2l9COqoOnSii06vLrGixN7NrFhwB0y2CTTbV2w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Y4FfA0fFHdXaOugoaL3dUD8HEKUVDr9tBn8UL0v9MlBGPlJzNvXsuvBR0ieVrf3Jw9CikRGpgXUO6nWkNNftym23uOPCbOG3f40vYdfWMIJ4QgnJxZ7qvbSoJQxlocV/gGCz35MzFoprmGySfJrSKS4jl1x00QAf/OK8ig1J670= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=srjVlvxl; 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="srjVlvxl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3F48AC4AF0B; Mon, 28 Jul 2025 08:24:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691088; bh=DDHEw2l9COqoOnSii06vLrGixN7NrFhwB0y2CTTbV2w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=srjVlvxlluDoh0Vj/xjN5mI3mQSTgoM1mo//6tuiu1tHx51su7COlep1BroTMmKj6 lcwCqto57s1tx7mHEJWsYlbaVqGaGNcTwIaWf1Wn+ovuJv0Iq84ZaqIkUfk+yFAqP1 Ys5Thwto14y/A7TtLXAo7alqS+POX+TnBrAXAzgqkQTijkJyLSfQrR3kRQEaOKOckC 3la8bJXllKcVxheHB8oj6LUaMmomgF2+pmOFZ0VGaH0aMdul93AzP0dJi1TTC7CUU8 hJi4NciHgjJKMjxIfnCFytoqmwODc5EM+83MwcCAYBLh7xU8x6J+mlCQs/2RZ51Nju GvOZpikNOjnyw== From: Chris Li Date: Mon, 28 Jul 2025 01:24:32 -0700 Subject: [PATCH RFC 02/25] PCI/LUO: Add struct dev_liveupdate 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: <20250728-luo-pci-v1-2-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Introduce struct dev_liveupdate and add it to struct device. Use the new struct to track a device's liveupdate states. - requested: The device is requested for a live update. - depended: One of the child devices is requested for live update. When the device is requested, the dev->lu.requested will set to 1. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 3 +++ include/linux/dev_liveupdate.h | 35 +++++++++++++++++++++++++++++++++++ include/linux/device.h | 6 ++++++ 3 files changed, 44 insertions(+) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 86b4f3a2fb44781c6e323ba029db510450556fa9..1c69adf412255c8ee5bc6db588f= f04b1642e8e19 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -6,8 +6,11 @@ */ =20 #define pr_fmt(fmt) "PCI liveupdate: " fmt +#define dev_fmt(fmt) "PCI liveupdate: " fmt =20 +#include #include +#include "pci.h" =20 #define PCI_SUBSYSTEM_NAME "pci" =20 diff --git a/include/linux/dev_liveupdate.h b/include/linux/dev_liveupdate.h new file mode 100644 index 0000000000000000000000000000000000000000..057407c030b0872bfa8cd666e6f= fc305f7aa4083 --- /dev/null +++ b/include/linux/dev_liveupdate.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright (c) 2025, Google LLC. + * Pasha Tatashin + * Chris Li + */ +#ifndef _LINUX_DEV_LIVEUPDATE_H +#define _LINUX_DEV_LIVEUPDATE_H + +#include + +#ifdef CONFIG_LIVEUPDATE + +/** + * struct dev_liveupdate - Device state for live update operations + * @lu_next: List head for linking the device into live update + * related lists (e.g., a list of devices participating + * in a live update sequence). + * @requested: Set if a live update has been requested for this + * device (i.e. device will participate in live update). + * @depended: Set if the device participtate the live update due to + * one of its child device is requested in live update. + * + * This structure holds the state information required for performing + * live update operations on a device. It is embedded within a struct devi= ce. + */ +struct dev_liveupdate { + struct list_head lu_next; + bool requested:1; + bool depended:1; +}; + +#endif /* CONFIG_LIVEUPDATE */ +#endif /* _LINUX_DEV_LIVEUPDATE_H */ diff --git a/include/linux/device.h b/include/linux/device.h index 4940db137fffff4ceacf819b32433a0f4898b125..4aee7912218865168a73fe4c6d3= a82646b8dd86f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -508,6 +509,7 @@ struct device_physical_location { * @pm_domain: Provide callbacks that are executed during system suspend, * hibernation, system resume and during runtime PM transitions * along with subsystem-level and driver-level callbacks. + * @lu: Live update state. * @em_pd: device's energy model performance domain * @pins: For device pin management. * See Documentation/driver-api/pin-control.rst for details. @@ -603,6 +605,10 @@ struct device { struct dev_pm_info power; struct dev_pm_domain *pm_domain; =20 +#ifdef CONFIG_LIVEUPDATE + struct dev_liveupdate lu; +#endif + #ifdef CONFIG_ENERGY_MODEL struct em_perf_domain *em_pd; #endif --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 D98D523A9B0; Mon, 28 Jul 2025 08:24:49 +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=1753691090; cv=none; b=DyXklksXH4/v77eCsP+UE2P3zF0nDb/QkDNVf3d3MuAYzMpCzvrvo1n97fS09BXk3vjyjz+Hja2oEJogB0VIgO2XEgi2QmC9O2BXXCv9jP9ZFSi0ATOBU6aR5v3f20624dBYmLBkX78aEjyOqljgl0PZq7XQDT+DZmiN2n71p6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691090; c=relaxed/simple; bh=Jir/gBpBJ+r5ifaYxD/nIOTUYFdwjI6k89o91CyXUoU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ntJtZFvluyDK7inu4zG3e3G4V7UyFvVKfF+qM+KzC/N9BpEL+BAuz2dNQiu+egy0aPftawZtC63H7RF4fZyHjAu7plA3ipyJRETyi9zwHenMTHers6kXMOs0X8+JFJ/zfOrZYHbZE7StpVxXv3YBSkXGIVKC1kMXVKZCmRoSKVc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Nc5D9WAx; 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="Nc5D9WAx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DF8C5C4CEE7; Mon, 28 Jul 2025 08:24:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691089; bh=Jir/gBpBJ+r5ifaYxD/nIOTUYFdwjI6k89o91CyXUoU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Nc5D9WAxsEQ1kxwiN4/sxOCQGAw/DJBzQ9nib+P4Ert+MKa3yOGu2zI3wYWaJkFoM fsKsqpNDYHqVnYyEejOr1RHmFCgTf4M/3Y+d3pqXfGd2XYPkKidMIZZzp6DwioE+nS 0PPbj2LyIzVPQE6CTFFjDBym7j9BqI4nuNohvRI5vtn43q34qGfdOcaJ0Pb3FYZs66 M8EDzMd7IuGsVhGMzYjlWH69dzWttb9YPPIrs5+VKO+kXKXKrWxWpjOSMDLOC+AYqC RSXuJ+tWWuMZ+8IWGG6tICGR02M2SIRK4UrHQ7RjjX96C33WvwyKeZx40UiWoNpFUS pkKxj5Jt0QFsA== From: Chris Li Date: Mon, 28 Jul 2025 01:24:33 -0700 Subject: [PATCH RFC 03/25] PCI/LUO: Create requested liveupdate device list 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: <20250728-luo-pci-v1-3-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 In the PCI subsystem prepare callback, create the requested device list as per the following rules: - If the device is liveupdate requested, then the parent device will also be added to the list as "depended". - If a SR-IOV VF device is liveupdate requested, then its corresponding PF device will also be added to the list as "depended". The list of PCI root bus and its children bus lists form a tree of all PCI buses. The tree is walked in postorder traversal, so that the device on the child bus can mark the parent bridge as "depended". Notice that the VF is always created after PF is created. Walk the pci_bus->devices in the reverse order so that the VF can mark the PF as "depended". After the postorder traversal of the bus tree then reverse order enumerates the devices in the bus, all device marks either requested or depended will be added to the requested device list. This list of devices will be used in the next change to forward the liveupdate call back into individual devices. Note that collect_liveupdate_devices() returns the number of devices it added to request_devices. This will be used in a subsequent commit so that the PCI subsystem can calculate what size folio to allocate for its save state. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 81 ++++++++++++++++++++++++++++++++++++++= ++++ drivers/pci/pcie/portdrv.c | 1 + drivers/pci/probe.c | 4 ++- include/linux/dev_liveupdate.h | 4 +++ include/linux/device.h | 9 +++++ 5 files changed, 98 insertions(+), 1 deletion(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 1c69adf412255c8ee5bc6db588ff04b1642e8e19..73cf13f58382d62969844ae6dd6= 160b1a77f844b 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -14,9 +14,90 @@ =20 #define PCI_SUBSYSTEM_NAME "pci" =20 +static void stack_push_buses(struct list_head *stack, struct list_head *bu= ses) +{ + struct pci_bus *bus; + + list_for_each_entry(bus, buses, node) + list_move_tail(&bus->dev.lu.lu_next, stack); +} + +static void requested_devices_add(struct device *dev, struct list_head *he= ad) +{ + dev_info(dev, "collect liveupdate device:%s%s\n", + dev->lu.depended ? " [depended]" : "", + dev->lu.requested ? " [requested]" : ""); + list_move_tail(&dev->lu.lu_next, head); +} + +static int collect_bus_devices_reverse(struct pci_bus *bus, struct list_he= ad *head) +{ + struct pci_dev *pdev; + int count =3D 0; + + list_for_each_entry_reverse(pdev, &bus->devices, bus_list) { + if (pdev->dev.lu.requested || pdev->dev.lu.depended) { + if (pdev->is_virtfn) + pdev->physfn->dev.lu.depended =3D 1; + if (pdev->dev.parent) + pdev->dev.parent->lu.depended =3D 1; + requested_devices_add(&pdev->dev, head); + count++; + } + } + return count; +} + +static int build_liveupdate_devices(struct list_head *head) +{ + LIST_HEAD(bus_stack); + int count =3D 0; + + stack_push_buses(&bus_stack, &pci_root_buses); + + while (!list_empty(&bus_stack)) { + struct device *busdev; + struct pci_bus *bus; + + busdev =3D list_last_entry(&bus_stack, struct device, lu.lu_next); + bus =3D to_pci_bus(busdev); + if (!busdev->lu.visited && !list_empty(&bus->children)) { + stack_push_buses(&bus_stack, &bus->children); + busdev->lu.visited =3D 1; + continue; + } + + count +=3D collect_bus_devices_reverse(bus, head); + busdev->lu.visited =3D 0; + list_del_init(&busdev->lu.lu_next); + } + return count; +} + +static void cleanup_liveupdate_devices(struct list_head *head) +{ + struct device *d, *n; + + list_for_each_entry_safe(d, n, head, lu.lu_next) { + d->lu.depended =3D 0; + list_del_init(&d->lu.lu_next); + } +} + static int pci_liveupdate_prepare(void *arg, u64 *data) { + LIST_HEAD(requested_devices); + pr_info("prepare data[%llx]\n", *data); + + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + + build_liveupdate_devices(&requested_devices); + cleanup_liveupdate_devices(&requested_devices); + + up_write(&pci_bus_sem); + pci_unlock_rescan_remove(); return 0; } =20 diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c index e8318fd5f6ed537a1b236a3a0f054161d5710abd..0e9ef387182856771d857181d88= f376632b46f0d 100644 --- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -304,6 +304,7 @@ static int pcie_device_init(struct pci_dev *pdev, int s= ervice, int irq) device =3D &pcie->device; device->bus =3D &pcie_port_bus_type; device->release =3D release_pcie_device; /* callback to free pcie dev */ + dev_liveupdate_init(device); dev_set_name(device, "%s:pcie%03x", pci_name(pdev), get_descriptor_id(pci_pcie_type(pdev), service)); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4b8693ec9e4c67fc1655e0057b3b96b4098e6630..dddd7ebc03d1a6e6ee456e0bf02= ab9833a819509 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -614,6 +614,7 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *pa= rent) INIT_LIST_HEAD(&b->devices); INIT_LIST_HEAD(&b->slots); INIT_LIST_HEAD(&b->resources); + dev_liveupdate_init(&b->dev); b->max_bus_speed =3D PCI_SPEED_UNKNOWN; b->cur_bus_speed =3D PCI_SPEED_UNKNOWN; #ifdef CONFIG_PCI_DOMAINS_GENERIC @@ -1985,6 +1986,7 @@ int pci_setup_device(struct pci_dev *dev) dev->sysdata =3D dev->bus->sysdata; dev->dev.parent =3D dev->bus->bridge; dev->dev.bus =3D &pci_bus_type; + dev_liveupdate_init(&dev->dev); dev->hdr_type =3D hdr_type & 0x7f; dev->multifunction =3D !!(hdr_type & 0x80); dev->error_state =3D pci_channel_io_normal; @@ -3184,7 +3186,7 @@ struct pci_bus *pci_create_root_bus(struct device *pa= rent, int bus, return NULL; =20 bridge->dev.parent =3D parent; - + dev_liveupdate_init(&bridge->dev); list_splice_init(resources, &bridge->windows); bridge->sysdata =3D sysdata; bridge->busnr =3D bus; diff --git a/include/linux/dev_liveupdate.h b/include/linux/dev_liveupdate.h index 057407c030b0872bfa8cd666e6ffc305f7aa4083..6b45452c8f1420b59ed3ce954a1= 623fd472045f4 100644 --- a/include/linux/dev_liveupdate.h +++ b/include/linux/dev_liveupdate.h @@ -21,6 +21,9 @@ * device (i.e. device will participate in live update). * @depended: Set if the device participtate the live update due to * one of its child device is requested in live update. + * @visited: Only used by the bus devices when travese the PCI buses + * to build the liveupdate devices list. Set if the child + * buses have been pushed into the pending stack. * * This structure holds the state information required for performing * live update operations on a device. It is embedded within a struct devi= ce. @@ -29,6 +32,7 @@ struct dev_liveupdate { struct list_head lu_next; bool requested:1; bool depended:1; + bool visited:1; }; =20 #endif /* CONFIG_LIVEUPDATE */ diff --git a/include/linux/device.h b/include/linux/device.h index 4aee7912218865168a73fe4c6d3a82646b8dd86f..e0b35c723239f1254a3b6152f43= 3e0412cd3fb34 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1174,4 +1174,13 @@ void device_link_wait_removal(void); #define MODULE_ALIAS_CHARDEV_MAJOR(major) \ MODULE_ALIAS("char-major-" __stringify(major) "-*") =20 +#ifdef CONFIG_LIVEUPDATE +static inline void dev_liveupdate_init(struct device *dev) +{ + INIT_LIST_HEAD(&dev->lu.lu_next); +} +#else +static inline void dev_liveupdate_init(struct device *dev) {} +#endif + #endif /* _DEVICE_H_ */ --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 8FE5A24A043; Mon, 28 Jul 2025 08:24:50 +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=1753691090; cv=none; b=E8ALDuvJogG/oD0Keeern79BBfAlyCvPR1ylquC2AoseSoafmM07Lg+Inan6yRQznlhBHZPJxfSSbCGx8BRKCuWp7FPTvsB4o2Ur4LEg8gnG19eZ14+hTuOkJHjjoxofDsB6fCDwkyI/nt0o4p4RFtvs8WhfLJlTxMnkwtgc3S8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691090; c=relaxed/simple; bh=Yp7Dx/zpSRrfUohmSFNkydmfJAH1FJCS0FCAc+5W4kk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ckTPhEAYDqZwA5B06hYzVTmsE5yWhwmLWFnXbENHuTOiNtL1bzSTSCrz8/IChmixFPuMQ33AMDbLgOYCamFEsFpjrfzny7Zvlw9bKcNmOhRVI7aWyBUhwYbCHZ8DU5sze0hyFtYQwF1Zkm1iGqkhwrFCuIGd1PYbE9HFWKQuqRY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KIX4K+Xu; 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="KIX4K+Xu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8DA68C4CEFA; Mon, 28 Jul 2025 08:24:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691090; bh=Yp7Dx/zpSRrfUohmSFNkydmfJAH1FJCS0FCAc+5W4kk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=KIX4K+XuZutHG4pYS3IKoTcURUglKGG/sSmXAQOI+x4mO1v3uN2zNjeuAjEphJC9X LqmQkF3owQvww33RRcAy8DqcehH0EMjO13SyxeLQXDhW8rw6cD2XD4VX3Zzjl5m2j3 BK2OGiBH4xzHpNnkS1/yQoUbiD1GhA9xywM7XOMsIqT/TkANVetSr+weCD6FXt9ElG ox3SD9fFzGa5HTWKSBnhZU9MJki4qTMPIv3rsvbZ9DH2bAl9/x9zM3Wn9S9kF4unUs crb4tkKMJn8Muv6yKRVzt3lwblBpsHu3RZPbMjQpKK8EexU/58K8NWLCSHJzZQDHFZ ZiD+FEY7BlYCA== From: Chris Li Date: Mon, 28 Jul 2025 01:24:34 -0700 Subject: [PATCH RFC 04/25] PCI/LUO: Forward prepare()/freeze()/cancel() callbacks to driver 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: <20250728-luo-pci-v1-4-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 After the list of preserved devices is constructed, the PCI subsystem can now forward the liveupdate request to the driver. The PCI subsystem saves and restores a u64 data from LUO callback. For each device, the PCI subsystem preserve a "dev_state" struct, which contains the path (domain + bus + devfn) and a per device u64 data. The device driver will use such a u64 data area to store the device driver state. The device live update callback looks very similar to the LUO subsystem callback, with the "void *arg" change to "struct device *dev". In the prepare callback, the PCI subsystem allocates then preserves a folio big enough to hold all requested device state (struct pci_dev_ser) in an array and the count. The PCI sub system will just forward the liveupdate call back with u64 data point to the u64 field of the device state array. If some device fails the prepare callback, all previous devices that already successfully finished the prepare call back will get the cancel call back to clean up the saved state. That clean up is the special case that not the full list will be walked. In other live update callbacks, all the devices in the preserved device list will get the callback with their own u64 data field. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 203 +++++++++++++++++++++++++++++++++++++= ++-- include/linux/dev_liveupdate.h | 23 +++++ include/linux/device/driver.h | 6 ++ 3 files changed, 223 insertions(+), 9 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 73cf13f58382d62969844ae6dd6160b1a77f844b..bbff9b314f99185dfe8941b711c= df0db16b1ed8a 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -9,11 +9,25 @@ #define dev_fmt(fmt) "PCI liveupdate: " fmt =20 #include +#include #include #include "pci.h" =20 #define PCI_SUBSYSTEM_NAME "pci" =20 +static LIST_HEAD(preserved_devices); + +struct pci_dev_ser { + u32 path; /* domain + bus + slot + fn */ + u8 requested; + u64 driver_data; /* driver data */ +}; + +struct pci_ser { + u32 count; + struct pci_dev_ser devs[]; +}; + static void stack_push_buses(struct list_head *stack, struct list_head *bu= ses) { struct pci_bus *bus; @@ -74,42 +88,213 @@ static int build_liveupdate_devices(struct list_head *= head) return count; } =20 +static void dev_cleanup_liveupdate(struct device *dev) +{ + dev->lu.depended =3D 0; + list_del_init(&dev->lu.lu_next); +} + static void cleanup_liveupdate_devices(struct list_head *head) { struct device *d, *n; =20 - list_for_each_entry_safe(d, n, head, lu.lu_next) { - d->lu.depended =3D 0; - list_del_init(&d->lu.lu_next); + list_for_each_entry_safe(d, n, head, lu.lu_next) + dev_cleanup_liveupdate(d); +} + +static void cleanup_liveupdate_state(struct pci_ser *pci_state) +{ + struct folio *folio =3D virt_to_folio(pci_state); + + kho_unpreserve_folio(folio); + folio_put(folio); +} + +static void pci_call_cancel(struct pci_ser *pci_state) +{ + struct pci_dev_ser *si =3D pci_state->devs; + struct device *dev, *next; + + list_for_each_entry_safe(dev, next, &preserved_devices, lu.lu_next) { + struct pci_dev_ser *s =3D si++; + + if (!dev->driver) + panic("PCI liveupdate cancel: %s has no driver", dev_name(dev)); + if (!dev->driver->lu) + panic("PCI liveupdate cancel: %s driver %s does not support liveupdate", + dev_name(dev), dev->driver->name ? : "(null name)"); + if (dev->driver->lu->cancel) + dev->driver->lu->cancel(dev, s->driver_data); + dev_cleanup_liveupdate(dev); } } =20 -static int pci_liveupdate_prepare(void *arg, u64 *data) +static int pci_get_device_path(struct pci_dev *pdev) +{ + return (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev); +} + +static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s) +{ + struct pci_dev *pdev =3D to_pci_dev(dev); + + s->path =3D pci_get_device_path(pdev); + s->requested =3D dev->lu.requested; + return 0; +} + +static int pci_call_prepare(struct pci_ser *pci_state, + struct list_head *devices) +{ + struct pci_dev_ser *pdev_state_current =3D pci_state->devs; + struct device *dev, *next; + int ret; + char *reason; + + list_for_each_entry_safe(dev, next, devices, lu.lu_next) { + struct pci_dev_ser *s =3D pdev_state_current++; + + if (!dev->driver) { + reason =3D "no driver"; + ret =3D -ENOENT; + goto cancel; + } + if (!dev->driver->lu) { + reason =3D "driver does not support liveupdate"; + ret =3D -EPERM; + goto cancel; + } + ret =3D pci_save_device_state(dev, s); + if (ret) { + reason =3D "save device state failed"; + goto cancel; + } + if (dev->driver->lu->prepare) { + ret =3D dev->driver->lu->prepare(dev, &s->driver_data); + if (ret) { + reason =3D "prepare() failed"; + goto cancel; + } + } + list_move_tail(&dev->lu.lu_next, &preserved_devices); + } + return 0; + +cancel: + dev_err(dev, "luo prepare failed %d (%s)\n", ret, reason); + pci_call_cancel(pci_state); + return ret; +} + +static int __pci_liveupdate_prepare(void *arg, u64 *data) { LIST_HEAD(requested_devices); + struct pci_ser *pci_state; + int ret; + int count =3D build_liveupdate_devices(&requested_devices); + int size =3D sizeof(*pci_state) + sizeof(pci_state->devs[0]) * count; + int order =3D get_order(size); + struct folio *folio; =20 - pr_info("prepare data[%llx]\n", *data); + folio =3D folio_alloc(GFP_KERNEL | __GFP_ZERO, order); + if (!folio) { + ret =3D -ENOMEM; + goto cleanup_device; + } =20 - pci_lock_rescan_remove(); - down_write(&pci_bus_sem); + pci_state =3D folio_address(folio); + pci_state->count =3D count; + + ret =3D kho_preserve_folio(folio); + if (ret) { + pr_err("liveupdate_preserve_folio failed\n"); + goto release_folio; + } + + ret =3D pci_call_prepare(pci_state, &requested_devices); + if (ret) + goto unpreserve; =20 - build_liveupdate_devices(&requested_devices); + *data =3D __pa(pci_state); + pr_info("prepare data[%llx]\n", *data); + return 0; + +unpreserve: + kho_unpreserve_folio(folio); +release_folio: + folio_put(folio); +cleanup_device: cleanup_liveupdate_devices(&requested_devices); + return ret; +} =20 +static int pci_liveupdate_prepare(void *arg, u64 *data) +{ + int ret; + + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + ret =3D __pci_liveupdate_prepare(arg, data); up_write(&pci_bus_sem); pci_unlock_rescan_remove(); + return ret; +} + +static int pci_call_freeze(struct pci_ser *pci_state, struct list_head *de= vlist) +{ + struct pci_dev_ser *n =3D pci_state->devs; + struct device *dev; + int ret =3D 0; + + list_for_each_entry(dev, devlist, lu.lu_next) { + struct pci_dev_ser *s =3D n++; + + if (!dev->driver) { + if (!dev->parent) + continue; + panic("PCI liveupdate freeze: %s has no driver", dev_name(dev)); + } + if (!dev->driver->lu->freeze) + continue; + ret =3D dev->driver->lu->freeze(dev, &s->driver_data); + if (ret) { + dev_err(dev, "luo freeze failed %d\n", ret); + pci_call_cancel(pci_state); + return ret; + } + } return 0; } =20 static int pci_liveupdate_freeze(void *arg, u64 *data) { + struct pci_ser *pci_state =3D phys_to_virt(*data); + int ret; + pr_info("freeze data[%llx]\n", *data); - return 0; + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + + ret =3D pci_call_freeze(pci_state, &preserved_devices); + + up_write(&pci_bus_sem); + pci_unlock_rescan_remove(); + return ret; } =20 static void pci_liveupdate_cancel(void *arg, u64 data) { + struct pci_ser *pci_state =3D phys_to_virt(data); + pr_info("cancel data[%llx]\n", data); + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + + pci_call_cancel(pci_state); + cleanup_liveupdate_state(pci_state); + + up_write(&pci_bus_sem); + pci_unlock_rescan_remove(); } =20 static void pci_liveupdate_finish(void *arg, u64 data) diff --git a/include/linux/dev_liveupdate.h b/include/linux/dev_liveupdate.h index 6b45452c8f1420b59ed3ce954a1623fd472045f4..fa664976f9f5e90b8a5a17cfbed= 8bd2fdc87b7a1 100644 --- a/include/linux/dev_liveupdate.h +++ b/include/linux/dev_liveupdate.h @@ -12,6 +12,8 @@ =20 #ifdef CONFIG_LIVEUPDATE =20 +struct device; + /** * struct dev_liveupdate - Device state for live update operations * @lu_next: List head for linking the device into live update @@ -35,5 +37,26 @@ struct dev_liveupdate { bool visited:1; }; =20 +/** + * struct dev_liveupdate_ops - Live Update callback functions + * @prepare: Prepare device for the upcoming state transition. Driver = and + * buses should save the necessary device state. + * @freeze: A final notification before the system jumps to the new k= ernel. + * Called from reboot() syscall. + * @cancel: Cancel the live update process. Driver should clean + * up any saved state if necessary. + * @finish: The system has completed a transition. Drivers and buses = should + * have already restored the previously saved device state. + * Clean-up any saved state or reset unreclaimed device. + * + * This structure is used by drivers and buses to hold the callback from L= UO. + */ +struct dev_liveupdate_ops { + int (*prepare)(struct device *dev, u64 *data); + int (*freeze)(struct device *dev, u64 *data); + void (*cancel)(struct device *dev, u64 data); + void (*finish)(struct device *dev, u64 data); +}; + #endif /* CONFIG_LIVEUPDATE */ #endif /* _LINUX_DEV_LIVEUPDATE_H */ diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index cd8e0f0a634be9ea63ff22e89d66ada3b1a9eaf2..b2ba469cc3065a412f02230c62e= 811af19c4d2c6 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -19,6 +19,7 @@ #include #include #include +#include =20 /** * enum probe_type - device driver probe type to try @@ -80,6 +81,8 @@ enum probe_type { * it is bound to the driver. * @pm: Power management operations of the device which matched * this driver. + * @lu: Live update callbacks, notify device of the live + * update state, and allow preserve device across reboot. * @coredump: Called when sysfs entry is written to. The device driver * is expected to call the dev_coredump API resulting in a * uevent. @@ -116,6 +119,9 @@ struct device_driver { const struct attribute_group **dev_groups; =20 const struct dev_pm_ops *pm; +#ifdef CONFIG_LIVEUPDATE + const struct dev_liveupdate_ops *lu; +#endif void (*coredump) (struct device *dev); =20 struct driver_private *p; --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 262F3252287; Mon, 28 Jul 2025 08:24:50 +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=1753691091; cv=none; b=d2/GDMXxMZm6Zpb95Nd5ymhxWzDd+63GE5yM1NXBO+1CZjw/ZPX49tVspnppAeVRRRzDa6RyBTk5fmaDMEkwMHFXs/3UNKO6ewlsYpNGc/Jd3GcSXwj0P6LajK/BFCqD6EpDTPGYwn41qZzW4xslDuk6uO2KEL9cVL7/snlGWms= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691091; c=relaxed/simple; bh=ehX+ClWrm6r3guFg3n2UP/1LZJ/hCv0T3nDP4k8F0p4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Bfm9mRFCuGNH5Sns5LM4YazK9qq6Dtn20Epa161WrgQqXaHYE/0JCDzWCWmX8g50tqh2kqJntElKxQHfI2oNgrf9zTfqn/D2ktjoPEY8dB1jejROfKnR4lhW+vfy1x91uyirnywt6lZ7T3sThR23Ez9kG8NUrlDvRbPl23XOdq0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KSQv/uhL; 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="KSQv/uhL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3BD9EC4CEF7; Mon, 28 Jul 2025 08:24:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691090; bh=ehX+ClWrm6r3guFg3n2UP/1LZJ/hCv0T3nDP4k8F0p4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=KSQv/uhLz+jOZM3kwa0blh/ktTYj04XQaja89gis5f6TxT9uIoPIGGODuaKrHkCWV HvnsZYhV3Y8lZfm7bPiFewzmdt4i3C//LyuJjaF5Cl5d/FssUGacfpyk4gP80p9ZVO r+8A3a4VH/V0XGYNEM3KZLwRVdYSIUGoJkSDCe+ncuZeoR7q8mA6FG9yfMPsjNX5Yl vVHBhbogwtAvFk6uE+PuTpzEQ4M7XwtL/rpxpPGEIjwh2ubf96NjrLX5hJxTODWQ3E PXwbxL96zu2azu+Bs767BBTe+3b4dxHnSz3akxPnOqi6+s1g1uY9TyhFn8H93s85Ip q/zNyFfbWljRQ== From: Chris Li Date: Mon, 28 Jul 2025 01:24:35 -0700 Subject: [PATCH RFC 05/25] PCI/LUO: Restore state at PCI enumeration 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: <20250728-luo-pci-v1-5-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Add a PCI device saved state member to indicate the device is requested vs depended. Restore the PCI subsystem saved state folio during PCI enumeration. When a new PCI device is created, restore the per device state pointer into the dev->lu.dev_state if the device is found in the saved devices array, by matching the device path. Also restore the dev->lu.requested or dev->lu.depended base on the saved "requested" field. Add such devices to the "probed_devices" list. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 54 ++++++++++++++++++++++++++++++++++++++= ++++ drivers/pci/pci.h | 6 +++++ drivers/pci/probe.c | 2 ++ include/linux/dev_liveupdate.h | 2 ++ 4 files changed, 64 insertions(+) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index bbff9b314f99185dfe8941b711cdf0db16b1ed8a..4d13071f5edd6520adb64003262= f08d1f79e26c4 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -16,6 +16,7 @@ #define PCI_SUBSYSTEM_NAME "pci" =20 static LIST_HEAD(preserved_devices); +static LIST_HEAD(probe_devices); =20 struct pci_dev_ser { u32 path; /* domain + bus + slot + fn */ @@ -91,6 +92,7 @@ static int build_liveupdate_devices(struct list_head *hea= d) static void dev_cleanup_liveupdate(struct device *dev) { dev->lu.depended =3D 0; + dev->lu.dev_state =3D NULL; list_del_init(&dev->lu.lu_next); } =20 @@ -310,6 +312,58 @@ struct liveupdate_subsystem pci_liveupdate_ops =3D { .name =3D PCI_SUBSYSTEM_NAME, }; =20 +static struct pci_ser *pci_state_get(void) +{ + static struct pci_ser *pci_state; + struct folio *folio; + phys_addr_t data =3D 0; + int ret; + + if (pci_state) + return pci_state; + + ret =3D liveupdate_get_subsystem_data(&pci_liveupdate_ops, &data); + if (ret || !data) + panic("PCI liveupdate: get subsystem data: [%llx] ret: %d", data, ret); + + folio =3D kho_restore_folio(data); + if (!folio) + panic("PCI liveupdate: restore folio from %llx failed", data); + + /* Cache the value for future callers. */ + pci_state =3D folio_address(folio); + return pci_state; +} + +static void pci_dev_do_restore(struct pci_dev *dev, struct pci_dev_ser *s) +{ + dev->dev.lu.dev_state =3D s; + if (s->requested) + dev->dev.lu.requested =3D 1; + else + dev->dev.lu.depended =3D 1; + pci_info(dev, "liveupdate restore [%s] data: [%llx]\n", + s->requested ? "requested" : "depended", + s->driver_data); + list_move_tail(&dev->dev.lu.lu_next, &probe_devices); +} + +void pci_liveupdate_restore(struct pci_dev *dev) +{ + int path; + struct pci_dev_ser *s, *end; + + if (!liveupdate_state_updated()) + return; + + path =3D pci_get_device_path(dev); + s =3D pci_state_get()->devs; + end =3D s + pci_state_get()->count; + for (; s < end; s++) + if (s->path =3D=3D path) + return pci_dev_do_restore(dev, s); +} + static int __init pci_liveupdate_init(void) { int ret; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 12215ee72afb682b669c0e3a582b5379828e70c4..c9a7383753949994e031dc36292= 0286a475fe2ab 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1159,4 +1159,10 @@ static inline int pci_msix_write_tph_tag(struct pci_= dev *pdev, unsigned int inde (PCI_CONF1_ADDRESS(bus, dev, func, reg) | \ PCI_CONF1_EXT_REG(reg)) =20 +#ifdef CONFIG_LIVEUPDATE +void pci_liveupdate_restore(struct pci_dev *dev); +#else +static inline void pci_liveupdate_restore(struct pci_dev *dev) {} +#endif + #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index dddd7ebc03d1a6e6ee456e0bf02ab9833a819509..a0605af1a699cd07b0989717280= 3dcba1d2da9f9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2017,6 +2017,8 @@ int pci_setup_device(struct pci_dev *dev) if (pci_early_dump) early_dump_pci_device(dev); =20 + pci_liveupdate_restore(dev); + /* Need to have dev->class ready */ dev->cfg_size =3D pci_cfg_space_size(dev); =20 diff --git a/include/linux/dev_liveupdate.h b/include/linux/dev_liveupdate.h index fa664976f9f5e90b8a5a17cfbed8bd2fdc87b7a1..dc65e2b2d92c02bf15440b6745c= 62cd748721eef 100644 --- a/include/linux/dev_liveupdate.h +++ b/include/linux/dev_liveupdate.h @@ -19,6 +19,7 @@ struct device; * @lu_next: List head for linking the device into live update * related lists (e.g., a list of devices participating * in a live update sequence). + * @dev_state: Set to the device state at restore. * @requested: Set if a live update has been requested for this * device (i.e. device will participate in live update). * @depended: Set if the device participtate the live update due to @@ -32,6 +33,7 @@ struct device; */ struct dev_liveupdate { struct list_head lu_next; + void *dev_state; bool requested:1; bool depended:1; bool visited:1; --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 D76EC221704; Mon, 28 Jul 2025 08:24: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=1753691091; cv=none; b=lSs/1oYWGeVB5djK5Jeyck0pgkwGJyS3JM2EW4vNDJjkBwQqXy3mkwJd8LbTyBEX0E/mDA1HlwFDQnPx2+tdFy2gO0KsryEihBL7XEC8Qkf5s/Q/QPxW85ShQr5V2OW2zQ8YWFjZPdisAyhHUv/N+hPshAzYw3RLogMcSINDDw8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691091; c=relaxed/simple; bh=d9HRv7PUvjY03stbX6fDE0y5GmiBxZpYjtU9wtF6fII=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SY4RcVYPZjRW/Ho6zOhmpWj5U8wYRKWAQGRVb3zbOIf5KND+iIzuAgRIE4od/+UMoaPt714Mt9zGhclb/ITfdBnzLao3wsOWWaJGxO3zB4eHNwI7drqEGmsjatrHI38WU85uTNaDIn996XpeCNISWj68LGw5HulTsiDqp7y5Hq8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eDySgVrJ; 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="eDySgVrJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DDA47C4CEF9; Mon, 28 Jul 2025 08:24:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691091; bh=d9HRv7PUvjY03stbX6fDE0y5GmiBxZpYjtU9wtF6fII=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=eDySgVrJrlOfO/IOg+RLe1vXwr/cjqZeeeqU9LRTiM3NxD9JCOLYa3mGF5W9UBlz4 sAr5+HvrbfxmNrwn1EJO7O0/74CkWeD0l0qbwwlTcPrQE9WfEJWODyGzr1mOJPeHXq 88lsa11iMtWs5ZYKPfVDkj5sa9lQV2rmj4F13oLrddjzsOIKL3osRJqE5DL7qj6pEP cufg2WXWM9xb1A4jY8bBiImDaQ2I6p0z7yApjsrrFRVr+6wd4UfqWEQJhiewDbP4Yv +rjitiD6qcS4lHYujSC58InAYC78F7B8gQDFXF8LDQN9tMuPG+DjcaxN9QNuhvOm/A bbzCK02bIer/Q== From: Chris Li Date: Mon, 28 Jul 2025 01:24:36 -0700 Subject: [PATCH RFC 06/25] PCI/LUO: Forward finish callbacks to drivers 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: <20250728-luo-pci-v1-6-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 When PCI receives the LUO finish callback. The PCI subsystem forwards the finish callback to the driver with restored dev->lu.dev_state->data. Tested: In qemu, request a virtio net device as requested. Perform luo prepare then kexec. Verify the new kernel boot up dmesg shows the requested device has per device live update state restored. Perform liveupdate finish and see the device finish callback gets invoked. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 4d13071f5edd6520adb64003262f08d1f79e26c4..6b85673f4ec20add7e49b04dc44= f1bcd868adbdc 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -268,6 +268,29 @@ static int pci_call_freeze(struct pci_ser *pci_state, = struct list_head *devlist) return 0; } =20 +static void pci_call_finish(struct list_head *devlist) +{ + struct device *dev; + + pci_lock_rescan_remove(); + down_write(&pci_bus_sem); + + list_for_each_entry(dev, devlist, lu.lu_next) { + struct pci_dev_ser *s =3D dev->lu.dev_state; + + if (!dev->driver) + panic("PCI luo finish: dev %s does not have driver", dev_name(dev)); + if (!dev->driver->lu) + panic("PCI luo finish: dev %s does not support liveupdate", + dev_name(dev)); + if (!dev->driver->lu->finish) + continue; + dev->driver->lu->finish(dev, s->driver_data); + } + up_write(&pci_bus_sem); + pci_unlock_rescan_remove(); +} + static int pci_liveupdate_freeze(void *arg, u64 *data) { struct pci_ser *pci_state =3D phys_to_virt(*data); @@ -301,7 +324,12 @@ static void pci_liveupdate_cancel(void *arg, u64 data) =20 static void pci_liveupdate_finish(void *arg, u64 data) { + struct pci_ser *pci_state =3D phys_to_virt(data); + pr_info("finish data[%llx]\n", data); + pci_call_finish(&probe_devices); + cleanup_liveupdate_devices(&probe_devices); + cleanup_liveupdate_state(pci_state); } =20 struct liveupdate_subsystem pci_liveupdate_ops =3D { --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 8CC61254AE1; Mon, 28 Jul 2025 08:24:52 +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=1753691092; cv=none; b=qCXLwKrNld0/m0PU8Y0kZE7skLnLoIeS2uikR4VA247t6hvzW2scwcyQpjUy/89JH1J/BMJgrLmotafjRgVz8IFnUUBkTrWCSwqHhWWZTBRTAsn3lDkJUo4CnVmcC31G34b6yNH5tIZMsyCnqm81+xjkl5siWBmfSkqDjoTKluI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691092; c=relaxed/simple; bh=ORuVCAuJLsqUOqfM75E4PnbYm0689SwSZA5Lo3dCJQo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=meqvunEA2FolR9nFlA7dPp6gGzJ7RvFShKupRTXJ8SUpDdJ7lvF3eyUnILtoGHrzWADOm83uy2hmQpbRt84bUmvQiWKkxnMp4ZdGBJ2Goj475SpTVqR9sbzPTuB5wowSZxrL7slegiuoM/L4ffjZMzwN0sx9Y8AFUXc6nFB+GCQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mTyjVyhn; 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="mTyjVyhn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 89A13C4CEF8; Mon, 28 Jul 2025 08:24:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691092; bh=ORuVCAuJLsqUOqfM75E4PnbYm0689SwSZA5Lo3dCJQo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=mTyjVyhnjMaES1Jh0AVnzfoQzrRcUQsQ76PhOOxxH29O61lhDBwImYMgKefL567rs dmqdwf4nR5god7ABWtNFCbRlUmtdYwvVUrhxSPXYA67rKbOS+/28CQFwN/CmmhQ6tY UAIo7cN1GET/DZq0NeirfVckjEnPxL8uPwioa8FmaYimNuiZAUM6MHcuKZ/534gR37 sKkWOkedfww79TVKuLxbLZ2utI4vZUWWH8TzRY0JeXbMubw47kEby38V/I7nlwRWeB PSDoHxdjDwYwIMIjSfXPLYGfye1MJvyrOxngIwebLP7XchH4ukELZb8HmYwyUdIXsp xJIGq3YXMfbUQ== From: Chris Li Date: Mon, 28 Jul 2025 01:24:37 -0700 Subject: [PATCH RFC 07/25] PCI/LUO: Save and restore driver name 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: <20250728-luo-pci-v1-7-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Save the PCI driver name into "struct pci_dev_ser" during the PCI prepare callback. After kexec, use driver_set_override() to ensure the device is bound only to the saved driver. Clear the override after the finish callback. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 36 ++++++++++++++++++++++++++++++++++-- drivers/pci/pci.h | 2 ++ drivers/pci/probe.c | 2 ++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 6b85673f4ec20add7e49b04dc44f1bcd868adbdc..189827c6111b2c00ebb24404a20= 5cde3f75d33c3 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -21,6 +21,7 @@ static LIST_HEAD(probe_devices); struct pci_dev_ser { u32 path; /* domain + bus + slot + fn */ u8 requested; + char driver_name[63]; u64 driver_data; /* driver data */ }; =20 @@ -91,6 +92,10 @@ static int build_liveupdate_devices(struct list_head *he= ad) =20 static void dev_cleanup_liveupdate(struct device *dev) { + struct pci_dev *pdev =3D to_pci_dev(dev); + + if (liveupdate_state_updated()) + WARN_ON(driver_set_override(dev, &pdev->driver_override, "", 0)); dev->lu.depended =3D 0; dev->lu.dev_state =3D NULL; list_del_init(&dev->lu.lu_next); @@ -139,7 +144,13 @@ static int pci_get_device_path(struct pci_dev *pdev) static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s) { struct pci_dev *pdev =3D to_pci_dev(dev); + const char *name =3D dev->driver->name; =20 + if (!name) + return -ENXIO; + if (strlen(name) > sizeof(s->driver_name) - 1) + return -ENOSPC; + strscpy(s->driver_name, name, sizeof(s->driver_name)); s->path =3D pci_get_device_path(pdev); s->requested =3D dev->lu.requested; return 0; @@ -370,9 +381,9 @@ static void pci_dev_do_restore(struct pci_dev *dev, str= uct pci_dev_ser *s) dev->dev.lu.requested =3D 1; else dev->dev.lu.depended =3D 1; - pci_info(dev, "liveupdate restore [%s] data: [%llx]\n", + pci_info(dev, "liveupdate restore [%s] driver: %s data: [%llx]\n", s->requested ? "requested" : "depended", - s->driver_data); + s->driver_name, s->driver_data); list_move_tail(&dev->dev.lu.lu_next, &probe_devices); } =20 @@ -392,6 +403,27 @@ void pci_liveupdate_restore(struct pci_dev *dev) return pci_dev_do_restore(dev, s); } =20 +void pci_liveupdate_override_driver(struct pci_dev *dev) +{ + struct pci_dev_ser *s =3D dev->dev.lu.dev_state; + int ret; + int len; + + if (!s) + return; + + len =3D strlen(s->driver_name); + if (!len) + return; + + ret =3D driver_set_override(&dev->dev, + &dev->driver_override, + s->driver_name, len); + if (ret) + panic("PCI Liveupdate override driver failed: %s", s->driver_name); +} + + static int __init pci_liveupdate_init(void) { int ret; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index c9a7383753949994e031dc362920286a475fe2ab..b79a18c5e948980fe2ef3f0a10e= 0d795b1eee6d7 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1161,8 +1161,10 @@ static inline int pci_msix_write_tph_tag(struct pci_= dev *pdev, unsigned int inde =20 #ifdef CONFIG_LIVEUPDATE void pci_liveupdate_restore(struct pci_dev *dev); +void pci_liveupdate_override_driver(struct pci_dev *dev); #else static inline void pci_liveupdate_restore(struct pci_dev *dev) {} +static inline void pci_liveupdate_override_driver(struct pci_dev *dev) {} #endif =20 #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a0605af1a699cd07b09897172803dcba1d2da9f9..e41a1bef2083aa9184fd1c894d5= de964f19d5c01 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2714,6 +2714,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_b= us *bus) /* Set up MSI IRQ domain */ pci_set_msi_domain(dev); =20 + pci_liveupdate_override_driver(dev); + /* Notifier could use PCI capabilities */ ret =3D device_add(&dev->dev); WARN_ON(ret < 0); --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 26AD225524D; Mon, 28 Jul 2025 08:24:52 +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=1753691093; cv=none; b=Fg5JHzLIfAEHidiomhZ30N5UYVmf2KohNNcMwsiGLznG76c4rPS5fZhhaL/5PptaNxH/dB7wK1F7jizAPuVIyJ05uip09IfRPL0v2hStCKTwruX4NUF9Ps3dSGrd5iDl6FsSaDNOAmfb67wJDtYYeh1A8fpf6iKMW7VXGjdo3vk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691093; c=relaxed/simple; bh=5MJjhbKurh9H3wo8pggfA7BuVWDa3XXOmJlG/RO2c/E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CyyooCDdHcpiqClnBmHmR2DK5AoSEWiGUWjNEoM68zkFOM0hBWfln0ns8uc7NT0JEVWKSM1LYs6GHIssggWhc+2BZG9J1zbt71NIIfbfKvJlIOwkZ6zpLCQp9SCHx6i04uXmKMouy5P2aM/KSI1eSTorVu4uAo63eFyWIPAMt2I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WQX56eWj; 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="WQX56eWj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 36133C4CEFC; Mon, 28 Jul 2025 08:24:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691092; bh=5MJjhbKurh9H3wo8pggfA7BuVWDa3XXOmJlG/RO2c/E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=WQX56eWjBRHu/4oZURg5khPQ9g81kL/wxaBS5BnhTuCxGb7JINyxKFzzuOwVaehYM f2WF1u+wFE6XF7hE6cHNlzk2vk+VbRp7OlwN7HPD2xyl0DPSmWozeHMTf6AO0rSMyR AmVUXW/KD+BXCREtvieJPY01XZtHT8zHhtwSp0COVPmsAbqO9tTLNPR7m6wadWjAO4 wg+lulwCMzGb1bBZ3aQsHI6K5KlB6QdFsLojJlnoHA2RYmDqaEdJIXquYi8U30BLx5 /WVAtxfGPyW4Sdw2ICl+Xm93/w3QSo38vTpxmngh81ayk1+VOtK/jzwy+m3h0/gJIJ QzBgC+UAa0ATg== From: Chris Li Date: Mon, 28 Jul 2025 01:24:38 -0700 Subject: [PATCH RFC 08/25] PCI/LUO: Add liveupdate to pcieport driver 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: <20250728-luo-pci-v1-8-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 The PCIe port driver is the driver bound to the PCI-PCI bridge. The PCIe port device is depended on by its PCI children devices. Add the empty liveupdate callback to the pcieport driver to indicate this driver supports liveupdate. Otherwise it can fail the liveupdate operation if the PCI-PCI bridge is depended.. Signed-off-by: Chris Li --- drivers/pci/pcie/portdrv.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c index 0e9ef387182856771d857181d88f376632b46f0d..fd43c1ebfb9d2852fbc460b0390= dd7fb016226d2 100644 --- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -789,6 +789,15 @@ static const struct pci_error_handlers pcie_portdrv_er= r_handler =3D { .mmio_enabled =3D pcie_portdrv_mmio_enabled, }; =20 +#ifdef CONFIG_LIVEUPDATE + +/* + * Empty pcie_port_lu_ops to indicate this driver support liveupdate. + */ +static struct dev_liveupdate_ops pcie_port_lu_ops; + +#endif /* CONFIG_LIVEUPDATE */ + static struct pci_driver pcie_portdriver =3D { .name =3D "pcieport", .id_table =3D port_pci_ids, @@ -802,6 +811,9 @@ static struct pci_driver pcie_portdriver =3D { .driver_managed_dma =3D true, =20 .driver.pm =3D PCIE_PORTDRV_PM_OPS, +#ifdef CONFIG_LIVEUPDATE + .driver.lu =3D &pcie_port_lu_ops, +#endif }; =20 static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d) --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 55B052571B6; Mon, 28 Jul 2025 08:24:53 +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=1753691094; cv=none; b=h1/TVcRSYdMmPjcqRKdTh3vQ64ql+nQ/JNxXqrnty9gcfzfzqiww6ZRvbFVRouf1g6vR7hwmr0vk224LHonH+TdaqFlEXqE8SoSKhZ+Vj88/uBzvQOw5yOjmw2E9XrljDPpt3YC1JTUKa5abmTz+sq8cW4lTQWXz2hh39jYiki4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691094; c=relaxed/simple; bh=SSBSnIZwzPjnbh6MWdhzmwYgVOcK5tJIU9ImdOnDn3w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Jvij9V1R46hHLYbgRyw7wl/+1Uk6Ht5XQfZrcNlDXgOcp9PfdkwNww8Flkhoi7TxBDCJTq5x5rsKV259TIyGPEgYczKHl2x84l2lQvDB8eWxIIucfxwzNekiDPqMS+e39p8T+gwIO/JzSYEd8GjSlfKNl2EtJRXkvu2HsIN9fXo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Of7BI/Rk; 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="Of7BI/Rk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D5C54C4CEF7; Mon, 28 Jul 2025 08:24:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691093; bh=SSBSnIZwzPjnbh6MWdhzmwYgVOcK5tJIU9ImdOnDn3w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Of7BI/RkQYaIgLCVa9V/emCUtRYj2XHsWymGSL8JRMrDu9WPihoF/NpokIynJ2JQT NIUAFZ/xHM06qOtXTPIA1Vt8NRkk/Dd8OXqdqsdgslbpJ6epVViRi23mQJ28D4ZLZi /TwYNNMYpHEzHYrn4jQ4uOWEGMgVTphOBqH+ZuTdBkKd+NqZEyXTtxOAv2atAi+jUH GcapBKbUh1acHQEMK7QHkONqa2pigg6Dws91tOZUTDYyxDVXjChL75D1KGsjPtaRIw 1iRPn9K0gKdVGLcijgskVwB63crazZv0aEXbunudIhF5dX4Ycxb+ukmkrFYPl5s2or BbzWpUdKJhJbg== From: Chris Li Date: Mon, 28 Jul 2025 01:24:39 -0700 Subject: [PATCH RFC 09/25] PCI/LUO: Save SR-IOV number of VF 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: <20250728-luo-pci-v1-9-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 During the PCI prepare callback, save the SR-IOV number if the device is a physical function. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 189827c6111b2c00ebb24404a205cde3f75d33c3..09faba99e9218b443f66060db51= 42208e22c7dd5 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -21,6 +21,7 @@ static LIST_HEAD(probe_devices); struct pci_dev_ser { u32 path; /* domain + bus + slot + fn */ u8 requested; + u16 num_vfs; char driver_name[63]; u64 driver_data; /* driver data */ }; @@ -153,6 +154,8 @@ static int pci_save_device_state(struct device *dev, st= ruct pci_dev_ser *s) strscpy(s->driver_name, name, sizeof(s->driver_name)); s->path =3D pci_get_device_path(pdev); s->requested =3D dev->lu.requested; + if (pdev->sriov && pdev->is_physfn) + s->num_vfs =3D pdev->sriov->num_VFs; return 0; } =20 @@ -381,9 +384,9 @@ static void pci_dev_do_restore(struct pci_dev *dev, str= uct pci_dev_ser *s) dev->dev.lu.requested =3D 1; else dev->dev.lu.depended =3D 1; - pci_info(dev, "liveupdate restore [%s] driver: %s data: [%llx]\n", + pci_info(dev, "liveupdate restore [%s] driver: %s data: [%llx] num_vfs: %= d\n", s->requested ? "requested" : "depended", - s->driver_name, s->driver_data); + s->driver_name, s->driver_data, s->num_vfs); list_move_tail(&dev->dev.lu.lu_next, &probe_devices); } =20 --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 55BC42571B9; Mon, 28 Jul 2025 08:24:54 +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=1753691094; cv=none; b=XfjSYHUzvmiJKegTJTk/ISeA1YVD40Z757uOhxFuuAN3Dh8bTiK2QRLJvNr7CuebNWl898g7NHavpZo+7DFfJsH50BW+DdNcPZKvPKtnJPCq0XYCk40hsjWtAWCaHpPAHtySkqtlF1pDygJlJzpvmY/1gwZXfLbItYC3O8C925s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691094; c=relaxed/simple; bh=/sFaBdMjGwDl1mH7fe9xS4pA+fmlg0Igj7ajJY841K4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mqy3yjbQXG+TXodL/6p7aUYZYDBbrRJC+KhgljK0kjP9ppaCIABvdIhZS8KfxbSj+iNRsiUntnDQg0tko7vUnNggsdlp6uPsHjCuF5dAVyCyYlyorkJLXqPCLSpJQ9g2enHD3iEOl3V3N8q1YF3N4LACqnecZAv8Y3Eth6H+gvU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uL73lvVE; 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="uL73lvVE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 843D8C113D0; Mon, 28 Jul 2025 08:24:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691094; bh=/sFaBdMjGwDl1mH7fe9xS4pA+fmlg0Igj7ajJY841K4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=uL73lvVE05TLPb6h14bdYg1Bk1bcCIF9oiU/MhYnakKrXSttNuYvhdFO9ZFp3HRpS HGCV9rY6kCXv58vGPETGfLERZyz5Ld9/U6ZTiv6iSZXXT2C3c8NevQ2ubT4nnRoxc9 MsN1GiN1QjYIfQmQZwznIXhGwuzd6V9Ic9Pc4okk2hAurMATW9rSiiiPRCwfj2zeGg lrwLx9XNfY+6XvC9qKGFtd6zKac7ydScnqBIY0SivFtZKQSEDJDXgf1YoxvmqO4GQO /18VHjnDDoHrzNmqx8n0j+jjXjUvzjUTk4DN1+JxIem31wbGrmRX0UBm4rlDLDbfLa 891VWBBMRneVA== From: Chris Li Date: Mon, 28 Jul 2025 01:24:40 -0700 Subject: [PATCH RFC 10/25] PCI/LUO: Add pci_liveupdate_get_driver_data() 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: <20250728-luo-pci-v1-10-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Similar to liveupdate_get_subsystem_data(), the PCI subsystem provide pci_liveupdate_get_driver_data() for the driver to receive the driver data during new kernel boot up, in the liveupdate updated state. This function =C2=A0will return an error on any other liveupdate state. For example, vfio-pci will use this API in probe() to access the liveupdate state from the previous kernel. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 15 +++++++++++++++ include/linux/pci.h | 9 +++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 09faba99e9218b443f66060db5142208e22c7dd5..f84c0a455f7055b9b64051b1253= 68fb0f9e6144f 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -406,6 +406,21 @@ void pci_liveupdate_restore(struct pci_dev *dev) return pci_dev_do_restore(dev, s); } =20 +int pci_liveupdate_get_driver_data(struct pci_dev *pdev, u64 *data) +{ + struct dev_liveupdate *lu =3D &pdev->dev.lu; + struct pci_dev_ser *s =3D lu->dev_state; + + if (!liveupdate_state_updated()) + return -EINVAL; + + if (!lu->dev_state) + return -ENOENT; + + *data =3D s->driver_data; + return 0; +} + void pci_liveupdate_override_driver(struct pci_dev *dev) { struct pci_dev_ser *s =3D dev->dev.lu.dev_state; diff --git a/include/linux/pci.h b/include/linux/pci.h index 05e68f35f39238f8b9ce08df97b384d1c1e89bbe..50296bb04aaa7f2bbd2260f8ec4= 670533e019e38 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2767,4 +2767,13 @@ void pci_uevent_ers(struct pci_dev *pdev, enum pci_= ers_result err_type); WARN_ONCE(condition, "%s %s: " fmt, \ dev_driver_string(&(pdev)->dev), pci_name(pdev), ##arg) =20 +#ifdef CONFIG_LIVEUPDATE +int pci_liveupdate_get_driver_data(struct pci_dev *pdev, u64 *data); +#else +static inline int pci_liveupdate_get_driver_data(struct pci_dev *pdev, + u64 *data) +{ + return 0; +} +#endif #endif /* LINUX_PCI_H */ --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 D12712580F3; Mon, 28 Jul 2025 08:24:54 +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=1753691094; cv=none; b=e+qh/WrsPhArLS6w5iFgxzq6zv6v73E6IxfUCImp8Y26eshle+LAlUVc9sYslX8BJpKtHclmqdBIR3JZNba5p52PBfMLJBqcQKk3oVZ1cHbEyg7K8i/3avxr1ByGkwxAZjUtqCkupGC+j1bepZbQl1A4I6rK8jJ2seJeiK+29GY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691094; c=relaxed/simple; bh=9pT7auVR6FAltHXHR5et0YHF+AalsZ3feMtnFd9sQdM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=C83Zua4+FsY13LAAHklIKNxzrDGRCPhhi6T1laQrAlPajtFi9xUTjcOgIInBHwm+Q6N7f5qMGY2myv7jvbpBsFrZQ2wzZ21TWH7uKpxtmCfF/lixTg0N3RfVg/yB2ub6lj9F//3CPWhfpGayr3NEi8Km7q+54g3GByT7H3pBPfs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Te9cLWBh; 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="Te9cLWBh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 30E68C4CEF8; Mon, 28 Jul 2025 08:24:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691094; bh=9pT7auVR6FAltHXHR5et0YHF+AalsZ3feMtnFd9sQdM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Te9cLWBhiy6rREo9AL32h61LkBX2ll6ENb8FEHGmx958YLvwYrdnQPWVm91ESDTLr PxLToLiWJB0NHo9sZZwh+1Ic0yIDnOzToI3ZzEAHedmWBRp/1+xO8s3T4PHD822v5P SymgEhj/FrrRMXf9qbeoREmcB7YStz7YIfRg7wjsZ2jZOlY/lSfkKfsiQ/2oXuL5RO fyh7yl9B7PriipNKsCrb0OzZ0YUO4dsjJRAX8yvl0IfxSLKBr0f6dzk+gXAEhk3jDa MdlYYfsVGqdlRwNkBIGcaNhYAPBiSVbw1vMPU+N5o7EBZEiP4aPIiPqq5PxI15rytg c0YEjb9LHYjeg== From: Chris Li Date: Mon, 28 Jul 2025 01:24:41 -0700 Subject: [PATCH RFC 11/25] PCI: pci-lu-stub: Add a stub driver for Live Update testing 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: <20250728-luo-pci-v1-11-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Introduce a new driver, pci-lu-stub, that can be bound to any PCI device and used to test the PCI subsystem support for Live Update. This driver gives developers a way to opt-in a device for Live Update and driver interaction with the PCI subsystem. This driver is only intended for testing purposes. In the future this driver can be extended to test other scenarios (such as failing prepare() on purpose). Signed-off-by: David Matlack Signed-off-by: Chris Li --- drivers/pci/Kconfig | 10 ++++ drivers/pci/Makefile | 1 + drivers/pci/pci-lu-stub.c | 139 ++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 150 insertions(+) diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 9c0e4aaf4e8cb7fecd9f80ac6289b8d854ce03aa..37e44782fa35c64c2eba6a0f694= 2d44d8003a499 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -327,3 +327,13 @@ source "drivers/pci/switch/Kconfig" source "drivers/pci/pwrctrl/Kconfig" =20 endif + +config PCI_LU_STUB + tristate "PCI Live Update Stub Driver" + depends on LIVEUPDATE + help + Say Y or M here if you want to enable support for the Live Update stub + driver. This driver can be used to test the PCI subsystem support for + Live Updates. + + When in doubt, say N. diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index aa1bac7aed7d12c641a6b55e56176fb3cdde4c91..061e98d0411a951573e1996c61c= e5a98f2775e53 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) +=3D of_property.o obj-$(CONFIG_PCI_NPEM) +=3D npem.o obj-$(CONFIG_PCIE_TPH) +=3D tph.o obj-$(CONFIG_LIVEUPDATE) +=3D liveupdate.o +obj-$(CONFIG_PCI_LU_STUB) +=3D pci-lu-stub.o =20 # Endpoint library must be initialized before its users obj-$(CONFIG_PCI_ENDPOINT) +=3D endpoint/ diff --git a/drivers/pci/pci-lu-stub.c b/drivers/pci/pci-lu-stub.c new file mode 100644 index 0000000000000000000000000000000000000000..ea8142dcb250d31cbf817df9571= 57bc4ec3a876d --- /dev/null +++ b/drivers/pci/pci-lu-stub.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +struct pci_lu_stub_ser { + u16 dev_id; +} __packed; + +static const struct pci_device_id pci_lu_stub_id_table[] =3D { + /* Allow binding to any device but only via driver_override. */ + { PCI_DEVICE_DRIVER_OVERRIDE(PCI_ANY_ID, PCI_ANY_ID, 1) }, + {}, +}; + +static int validate_folio(struct pci_dev *dev, struct folio *folio) +{ + const struct pci_lu_stub_ser *ser =3D folio_address(folio); + + if (folio_order(folio) !=3D get_order(sizeof(*ser))) { + pci_err(dev, "Restored folio has unexpected order %u\n", folio_order(fol= io)); + return -ERANGE; + } + + if (ser->dev_id !=3D pci_dev_id(dev)) { + pci_err(dev, "Restored folio contains unexpected dev_id: 0x%x\n", ser->d= ev_id); + return -EINVAL; + } + + return 0; +} + +static int pci_lu_stub_probe(struct pci_dev *dev, const struct pci_device_= id *id) +{ + struct folio *folio; + u64 data; + int ret; + + if (liveupdate_state_normal()) { + pci_info(dev, "Marking device as liveupdate requested\n"); + dev->dev.lu.requested =3D 1; + return 0; + } + + if (!liveupdate_state_updated()) { + pci_err(dev, "Unable to handle probe() outside of normal and updated sta= tes.\n"); + return -EOPNOTSUPP; + } + + ret =3D pci_liveupdate_get_driver_data(dev, &data); + if (ret) { + pci_err(dev, "Failed to get driver data for device (%d)\n", ret); + return ret; + } + + pci_info(dev, "%s(): data: 0x%llx\n", __func__, data); + + folio =3D kho_restore_folio(data); + if (!folio) { + pci_err(dev, "Failed to restore folio at 0x%llx.\n", data); + return -ENOENT; + } + + return validate_folio(dev, folio); +} + +static void pci_lu_stub_remove(struct pci_dev *dev) +{ + WARN_ON(!liveupdate_state_normal()); + dev->dev.lu.requested =3D 0; +} + +static int pci_lu_stub_prepare(struct device *dev, u64 *data) +{ + struct pci_lu_stub_ser *ser; + struct folio *folio; + int ret; + + folio =3D folio_alloc(GFP_KERNEL | __GFP_ZERO, get_order(sizeof(*ser))); + if (!folio) + return -ENOMEM; + + ret =3D kho_preserve_folio(folio); + if (ret) { + dev_err(dev, "Failed to preserve folio (%d)\n", ret); + folio_put(folio); + return ret; + } + + ser =3D folio_address(folio); + ser->dev_id =3D pci_dev_id(to_pci_dev(dev)); + + *data =3D virt_to_phys(ser); + dev_info(dev, "%s(): data: 0x%llx\n", __func__, *data); + return 0; +} + +static int pci_lu_stub_freeze(struct device *dev, u64 *data) +{ + struct folio *folio =3D pfn_folio(PHYS_PFN(*data)); + + dev_info(dev, "%s(): data: 0x%llx\n", __func__, *data); + return validate_folio(to_pci_dev(dev), folio); +} + +static void pci_lu_stub_finish(struct device *dev, u64 data) +{ + struct folio *folio =3D pfn_folio(PHYS_PFN(data)); + + dev_info(dev, "%s(): data: 0x%llx\n", __func__, data); + WARN_ON(validate_folio(to_pci_dev(dev), folio)); + folio_put(folio); +} + +static void pci_lu_stub_cancel(struct device *dev, u64 data) +{ + dev_info(dev, "%s(): data: 0x%llx\n", __func__, data); + pci_lu_stub_finish(dev, data); +} + +static struct dev_liveupdate_ops liveupdate_ops =3D { + .prepare =3D pci_lu_stub_prepare, + .freeze =3D pci_lu_stub_freeze, + .finish =3D pci_lu_stub_finish, + .cancel =3D pci_lu_stub_cancel, +}; + +static struct pci_driver pci_lu_stub_driver =3D { + .name =3D "pci-lu-stub", + .id_table =3D pci_lu_stub_id_table, + .probe =3D pci_lu_stub_probe, + .remove =3D pci_lu_stub_remove, + .driver.lu =3D &liveupdate_ops, +}; + +module_pci_driver(pci_lu_stub_driver); +MODULE_LICENSE("GPL"); --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 6C114234963; Mon, 28 Jul 2025 08:24:55 +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=1753691096; cv=none; b=hOiHewC97BLOZvNNKp2CCOvSyeROpJ1UlmBMIWrnOUSR19xXp+fiNXOudcH0AyUXCW0uQOOFytp7wzr6FxjZa8c1UxS1fiQwyo6r9q/gD3hsMVYwl1QHPiSe0o5f1JFHxEobjweli0YXrBSPBsNEmanInXI4KW/RsOELZ9YJoqs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691096; c=relaxed/simple; bh=l4iu4ChzVc1nL+CJ6QgQYIFZyBLZHTAfyN3HW/ZgUxE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=a57bVUk4nKPzU9UYPBUHwte5rOHc5AEGxL/2yQn9AV5LGvjbtzohzoueKLf8cpTUBmlHTs8jAOTORgnNVHfsdlbpjh1BafRgCIZyUY31PDGB6b/oqF7tRsXk56P+lDJLMiVmDoNRx0EqCRdfUQ05w9YtogZ4Bn+p8u5Glcfigl8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RHcUc9RN; 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="RHcUc9RN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D0386C4CEF7; Mon, 28 Jul 2025 08:24:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691095; bh=l4iu4ChzVc1nL+CJ6QgQYIFZyBLZHTAfyN3HW/ZgUxE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=RHcUc9RNmIM7SGOQ09D5XqF5Fk1blrKHwZ5aXGJeFz1mpQJF/ExVQFrTrwC6clY04 /ZwpzEr/QF4poEkRKLUjqJ2Fz6IP2IaFVI3OpRUtoYpWU1EWoIVWGNHXxYNvsM1kVq l8REnH0LWg5hCpVkJtOPr6i1CzvrC2OSW/YVO4JywD7eJNC33vj0EHIgRBa4EidKuu 8dqnZL9GQRvO1OhwD+GacyW3SdVifvxO4MWQJUMi6M4bk9rBnl4CuK2rG0xtSJVRtV kT7s1dCSL3R242G+EC1SlMVfhbzgveNpUJFYW22iOKPsBSyjRUgw6KSOl03CJlYppS g7ABIiMAuboxA== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:42 -0700 Subject: [PATCH RFC 12/25] PCI/LUO: Save struct pci_dev info during prepare phase 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: <20250728-luo-pci-v1-12-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu Some fields in the struct pci_dev are mutable during kernel execution, and the runtime values cannot be re-construct from reading the PCI config space registers again. Therefore, for the next kernel, we need to save those fields for liveupdate during the prepare phase. Those values are expected to be restored in the boot up time of the next kernel. The struct pci_dev_ser is packed for making sure the field offsets are consistent across the kernel images before and after liveupdate. We would like to save one more field for PCI resources, which has type struct resource. It contains pointers so needs extra handlings in the coming patches. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 22 ++++++++++++++-------- drivers/pci/pci.h | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index f84c0a455f7055b9b64051b125368fb0f9e6144f..6b1c14d70fd16b0919ca22faae7= 88069f3743708 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -18,14 +18,6 @@ static LIST_HEAD(preserved_devices); static LIST_HEAD(probe_devices); =20 -struct pci_dev_ser { - u32 path; /* domain + bus + slot + fn */ - u8 requested; - u16 num_vfs; - char driver_name[63]; - u64 driver_data; /* driver data */ -}; - struct pci_ser { u32 count; struct pci_dev_ser devs[]; @@ -156,6 +148,20 @@ static int pci_save_device_state(struct device *dev, s= truct pci_dev_ser *s) s->requested =3D dev->lu.requested; if (pdev->sriov && pdev->is_physfn) s->num_vfs =3D pdev->sriov->num_VFs; + + s->devfn =3D pdev->devfn; + s->current_state =3D pdev->current_state; + s->pm_cap =3D pdev->pm_cap; + s->broken_intx_masking =3D pdev->broken_intx_masking; + s->pme_poll =3D pdev->pme_poll; + s->no_d3cold =3D pdev->no_d3cold; + s->wakeup_prepared =3D pdev->wakeup_prepared; + s->skip_bus_pm =3D pdev->skip_bus_pm; + s->ignore_hotplug =3D pdev->ignore_hotplug; + s->hotplug_user_indicators =3D pdev->hotplug_user_indicators; + s->pref_window =3D pdev->pref_window; + s->pref_64_window =3D pdev->pref_64_window; + return 0; } =20 diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index b79a18c5e948980fe2ef3f0a10e0d795b1eee6d7..2ef12745ee05960878d8d3fe0cd= f136f69c8d408 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -489,6 +489,28 @@ struct pci_sriov { bool drivers_autoprobe; /* Auto probing of VFs by driver */ }; =20 +struct pci_dev_ser { + u32 path; /* domain + bus + slot + fn */ + u8 requested; + u16 num_vfs; + char driver_name[63]; + u64 driver_data; /* driver data */ + + /* Saved fields from struct pci_dev */ + u32 devfn; + u32 current_state; + u8 pm_cap; + u32 broken_intx_masking:1; + u32 pme_poll:1; + u32 no_d3cold:1; + u32 wakeup_prepared:1; + u32 skip_bus_pm:1; + u32 ignore_hotplug:1; + u32 hotplug_user_indicators:1; + u32 pref_window:1; + u32 pref_64_window:1; +} __packed; + #ifdef CONFIG_PCI_DOE void pci_doe_init(struct pci_dev *pdev); void pci_doe_destroy(struct pci_dev *pdev); --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 6C17825B1E0; Mon, 28 Jul 2025 08:24:56 +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=1753691096; cv=none; b=V5p1E9bKWKQXf3n8VMVbgllKU+Bpm3CzzdOZX/jw6xcdS4V2rxJ12chHnH+CbrtnZA4m04k6hy0KQ0JJj0oZXOANY3YDhSfDtYk7GfWZzyFu7HUfPpnJFqheGm7wBLmVfMFEDlthyZ8hH05ydOmguu076C7rDKzns+AMT5LIGiE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691096; c=relaxed/simple; bh=QcznKEuszye5dtHBV31dISysk6MANWZ4HW7p32rLwHk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EoA26RnXgOlg/MHR4G1wDdP1gxgoQ8pnRhl9SwvODRmPI9ei62FvqtPahxxfjjRUt0g40PJiH3YrlPltA8RLs1tTd6nSiQ89TE6Fh/nOewhwFYX2OhORlbZPI3lVpjEcikvAuyX6xeHkZrhMDMxrnZajaY4KadKEyqVLkb2tQ4A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZqxJCwnw; 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="ZqxJCwnw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7B8AFC4CEE7; Mon, 28 Jul 2025 08:24:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691096; bh=QcznKEuszye5dtHBV31dISysk6MANWZ4HW7p32rLwHk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ZqxJCwnwJUY279kA8YTDm6LWaHcSToHBvaWJMS+C1bqK0Hligu9ydLD5XJ1hEePfV 32WO9WiV92M2ZIyN/5kLS4ZeF6EGqvxqP2XzgNFywdiQikjfRGoS3aimADNQd1h76y XI63NBPTKXCcw94tFr7RdcFNACh7OFck4/E//zVQISMtIUJ7gyEn30VewikS9Cscos 9xP9yzlS7cPXj0c3Y4LWjJrd3MezqV17JStnlCP6zLJHfCG3yzVS8XAElMYpVnMF6P KxLB05ZUp2hYjCxcgGyYJAuHJtFSN2Sgp88hjCdiGsTJd9NUtj2uoh87XZx+Ybox8j +Exj7kMpyjjtg== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:43 -0700 Subject: [PATCH RFC 13/25] PCI/LUO: Check the device function numbers in restoration 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: <20250728-luo-pci-v1-13-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu After liveupdate reboot, the device BDF shouldn't be changed from the previous kernel. If this happens, the saved LUO device state cannot be used, and panic the kernel. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 6b1c14d70fd16b0919ca22faae788069f3743708..ec2d7917441ceb4e3d7cd8becae= 41ca215cba7c3 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -393,6 +393,15 @@ static void pci_dev_do_restore(struct pci_dev *dev, st= ruct pci_dev_ser *s) pci_info(dev, "liveupdate restore [%s] driver: %s data: [%llx] num_vfs: %= d\n", s->requested ? "requested" : "depended", s->driver_name, s->driver_data, s->num_vfs); + + /* + * The devfn got changed since reboot. We cannot restore device + * info preserved by liveupdate + */ + if (s->devfn !=3D dev->devfn) + panic("%s: Device and function numbers are changed from 0x%40x to 0x%40x= \n", + __func__, s->devfn, dev->devfn); + list_move_tail(&dev->dev.lu.lu_next, &probe_devices); } =20 --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 C386725BEF4; Mon, 28 Jul 2025 08:24:56 +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=1753691096; cv=none; b=EN/aqVAA9Cx0B1/DZRp79p+btBAKc6+h40EUbr8UT/WTv/cwZ37uaHlbzydqRuPMPu+7RZFdKKFTcUqEIoOMa8FJ83099UNniytVy76cLCOR7KErppF8F4Zt8wByJmqEBn5I7642A21fjQxjFD5gI2k0NRcrmPSg0ZwTGRCVan8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691096; c=relaxed/simple; bh=ntoNAe91hdDCVcAE2wDcbgw/KJoIhDh1uXZzqA+NeMM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JOPmqLQdxw7jEH4qo5reY3pqS08hNSdpkAG0F8OtT7je/SBmNZfdeY/dIMdENZ1e74z9TCxuKEw356KZFUfhUAI1LO5bJYjWBDunWQADNQygk8F+Z+RFKvgZ1SbmreLb3xG222MXvB+kFSi6D0uwdhQiNRy6kju3qZgnYEqYTm8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ror61mKj; 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="Ror61mKj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 27B6BC4CEFA; Mon, 28 Jul 2025 08:24:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691096; bh=ntoNAe91hdDCVcAE2wDcbgw/KJoIhDh1uXZzqA+NeMM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Ror61mKjJFeOIwGzExpoggoeiQwwGVlnKKtMP1sgpNCIAnEc+Um4F6zkie2s+8OhU L/wL+JvolmD/g5yDhv0DqEYrR78iWKnhj6BLpjf+q7/FIgaw07+BRILphTquaSmggv M6ylcG08B/uRcY/aGH04yb5KWARNOtksQ1EPQzP9M/nOC8h8v72cc0FLXx1ue8uINM pxPVb/UVnHNLvi6lQJ5MYxeqYJ4TCVUbXvaBFSczB5uwvyK5rfafs3QTfbIEVQOadq MVrMcHWz7VAQIA59TOeMIceieXH6VwLHgQcoSJfqBGVcAwfvl+CSBFGpaQDEj9eqC0 B6fobIGlwKmaA== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:44 -0700 Subject: [PATCH RFC 14/25] PCI/LUO: Restore power state of a PCI device 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: <20250728-luo-pci-v1-14-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu From the liveupdate saved PCI device state, restore the device power state. The `pci_dev->current_state` is a cached power state. If the device driver calls `pci_enable_device()`, this value can be modified from reading the PMCSR register (see `pci_enable_device_flags()`). In the future patches when a driver tries to enable the PCI device after liveupdate, we should check the device power state at that moment with the saved value. Tested: QEMU liveupdate boot test. Trigger the liveupdate to the `finish` phase. Signed-off-by: Chris Li --- drivers/pci/pci.h | 6 ++++++ drivers/pci/probe.c | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 2ef12745ee05960878d8d3fe0cdf136f69c8d408..a8acc986a5aac808ec64395d7d9= 46ee036270f5b 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1182,9 +1182,15 @@ static inline int pci_msix_write_tph_tag(struct pci_= dev *pdev, unsigned int inde PCI_CONF1_EXT_REG(reg)) =20 #ifdef CONFIG_LIVEUPDATE +#define PCI_SER_GET(__pci_dev, __var, __def) \ + (__pci_dev->dev.lu.dev_state) ? \ + ((struct pci_dev_ser *)__pci_dev->dev.lu.dev_state)->__var : __def + void pci_liveupdate_restore(struct pci_dev *dev); void pci_liveupdate_override_driver(struct pci_dev *dev); #else +#define PCI_SER_GET(__dev, __var, __def) __def + static inline void pci_liveupdate_restore(struct pci_dev *dev) {} static inline void pci_liveupdate_override_driver(struct pci_dev *dev) {} #endif diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e41a1bef2083aa9184fd1c894d5de964f19d5c01..7dd2cf9f9e110636f8998df22a3= 33638cce25e6b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2030,8 +2030,12 @@ int pci_setup_device(struct pci_dev *dev) if (pci_is_pcie(dev)) dev->supported_speeds =3D pcie_get_supported_speeds(dev); =20 - /* "Unknown power state" */ - dev->current_state =3D PCI_UNKNOWN; + /* + * Restore the power state from liveupdate saved state. + * If we are not booted from liveupdate, default + * "Unknown power state". + */ + dev->current_state =3D PCI_SER_GET(dev, current_state, PCI_UNKNOWN); =20 /* Early fixups, before probing the BARs */ pci_fixup_device(pci_fixup_early, dev); --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 792792571B6; Mon, 28 Jul 2025 08:24:57 +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=1753691097; cv=none; b=hdj8ILzf3eQMuZWQdySNO0tbpp3Wnr8Vi5bdPPLKQXNH2QPATujsRtaM1dLrNNZRvhpz/co/fbSC5cgTXdpPmshOtANPcvNgxa8QYVC4xVwi/F9PRPfX2SrfEdBLGHh5ZsWXVCxcJ3Clb8IlMG6YdrZhJHSkqeRJj8i8BYJgJCA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691097; c=relaxed/simple; bh=G2koSOZg+2R0yt5dOjcepoL7O+CiOzL6QTB1hbD4l0A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=E8pwWrxM42UHs95qzKVGMegACQxhb4ocllhilllFrSoej0C9pPM5Fomw8mNzJMT4zsZ6Uz9G1O7VGeVSS2ahRsHWpbMXR5Q2NKZOkneGu2mPP9gkt9TQ+D1DPCatHLkHQbswnuu+MP1xbI1HpQAgBnYP1jKbxxBl+EDiisg2KZU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OEtkOZ2F; 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="OEtkOZ2F" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C72B3C4CEE7; Mon, 28 Jul 2025 08:24:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691097; bh=G2koSOZg+2R0yt5dOjcepoL7O+CiOzL6QTB1hbD4l0A=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=OEtkOZ2FwFBhE3FpI3rixW89UsRw6p/YPMu8EmS3ux/8imDcLPkJgIKYx7mCGCGn5 eXv+SHV2Ek+6CNsOG6K3PPrWX1q7iWyl4vMDAHHmoLnefcBdXEf4Fi3mLmRyDn3g8s lYYb/WxjMttg+LtZMPkiiQuYdaW3mkqkvXlXybpHWWed3NMQNGedMkPv8Xz3fnv6ZY DBurotQZGbMZTEhTawD8IN7wQvWA/DkKcwRCX+pLYnnUOKR843bF7Yp5OkBahB8Tvp inR1dnuy2e39lcYSGWJIVMob3YcBRmBDdJpHLa78iSmQId6UsaRp+vcPW/ATebNn1C Bfu8UJUVMTTww== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:45 -0700 Subject: [PATCH RFC 15/25] PCI/LUO: Restore PM related fields 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: <20250728-luo-pci-v1-15-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu - pm_cap Restore the liveupdate saved `pm_cap` during the PCI Power Management initialization. - skip_bus_pm flag: The flag skip_bus_pm is used in the PM suspend and resume operations. Therefore we restore this flag for the device in the PM init before all the operations. - wakeup_prepared flag: Restores the wakeup_prepared flag during the PM initialization. Tested: QEMU VM boot test. Signed-off-by: Chris Li --- drivers/pci/pci.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9e42090fb108920995ebe34bd2535a0e23fef7fd..e0e730f7bb3932567815c390088= 088bd5c56f11e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3209,13 +3209,14 @@ void pci_pm_init(struct pci_dev *dev) u16 pmc; =20 device_enable_async_suspend(&dev->dev); - dev->wakeup_prepared =3D false; =20 dev->pm_cap =3D 0; dev->pme_support =3D 0; =20 - /* find PCI PM capability in list */ - pm =3D pci_find_capability(dev, PCI_CAP_ID_PM); + /* Restore PM related fields after live update or find PM capability */ + pm =3D PCI_SER_GET(dev, pm_cap, pci_find_capability(dev, PCI_CAP_ID_PM)); + dev->wakeup_prepared =3D PCI_SER_GET(dev, wakeup_prepared, false); + dev->skip_bus_pm =3D PCI_SER_GET(dev, skip_bus_pm, dev->skip_bus_pm); if (!pm) goto poweron; /* Check device's ability to generate PME# */ --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 1F80F25DB1C; Mon, 28 Jul 2025 08:24:58 +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=1753691098; cv=none; b=aCfCcQxOPci1Yx6KtS8zk1Rp0obUhJBN1mMLOK4GIEKULAQ7ZmbG5v1LxbZufQFcDMwW5pKhY/pPVKIbxGcGI4mbU5UWvQO1s1jvSqMRhhI1Ik0uLTTgXIQxLIy2DS75tHHPhUwQJg+jmVjoqZgfSzl8G17Uvgu44ZEjGRD3wcY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691098; c=relaxed/simple; bh=5C9Pr2eXeTa+JJsCGkVhE97Ue0QvTrQypy6NAqhUBow=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qhuUNE4QFsGKSpLCkAzDilaCCaHNVlbGiNzA8Y5qC3WQCy2kcHYwILSId2VEiMeprjiRLz5NeSCCztOcHEPTbu19b6E4UXT7yaHkh0RkedDOcb20fOh0RfdGZ/B0dRoFs1dHsxLX3t43+GD1x5oD7sGtIUKW4a4uUQYsLtIqhyw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sG7bzTNI; 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="sG7bzTNI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 72E85C4CEF8; Mon, 28 Jul 2025 08:24:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691098; bh=5C9Pr2eXeTa+JJsCGkVhE97Ue0QvTrQypy6NAqhUBow=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=sG7bzTNIWDrzalHZWBXzEuko67k3yvGI5OSZxkemHiMszIgNdlh9ylOBy+US81QZA kLXBYz0HXG+3LE6BhSUnLyHlKs9euhblf0bY9SFMOhkmDDx31O0Llur8dFd1xSjMYw Zch/F3LAUScFGya7LQvZYF9o0LBa/tQ27kH5RDKwVBt07Z4QwdsrXIGmYPCpPx6sPq AumBAPqLMR9wJD4Qzw807GmAvGx1bYMYuS4s1xXzzcNxSy3NdJii7ukkYpqNUrI0S+ +lI1c5rJzIx6TQWkLmFJjHKAQbeWi6laNCnjdv2qvtm+ZhndpDhDpq3Bs2OJohR7Ck Nt1m+8pSidf7A== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:46 -0700 Subject: [PATCH RFC 16/25] PCI/LUO: Restore the pme_poll flag 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: <20250728-luo-pci-v1-16-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu Restore the pci_dev pme_poll flag from liveupdate. If the restored flag is false, the device is in an active state (was not being PME polled before liveupdate reboot), we do not touch the PCI PME register of the device. Tested: QEMU VM liveupdate reboot, put liveupdate in to finish phase. Signed-off-by: Chris Li --- drivers/pci/pci.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e0e730f7bb3932567815c390088088bd5c56f11e..46fb80dbca590c251fcad3bf2f0= 11a16f6898810 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3263,8 +3263,17 @@ void pci_pm_init(struct pci_dev *dev) * let the user space enable it to wake up the system as needed. */ device_set_wakeup_capable(&dev->dev, true); - /* Disable the PME# generation functionality */ - pci_pme_active(dev, false); + + dev->pme_poll =3D PCI_SER_GET(dev, pme_poll, true); + /* + * If the restored pme_poll is false, do not + * set disable to pci_pme_active(), as the device should be in + * an active state, we do not update the device's + * PCI_PM_CTRL_PME_ENABLE flag and disable the PME# generation + * functionality + */ + if (dev->pme_poll) + pci_pme_active(dev, false); } =20 pci_read_config_word(dev, PCI_STATUS, &status); --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 0DE0A260583; Mon, 28 Jul 2025 08:24:58 +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=1753691099; cv=none; b=GHAgVZGkyE+TIr2O9b+9F87idD4sJhNV2Z+CWpqyXXLwvXDyg2g2laDjUsZMiemFp9E/n+YGZmnTFKKjmYLdXwgycCDuEh4J5gSIcLL6eqYqCeQ8D2b2Gp6B4MhBwcvHs1ecTSINImmQWBbLEI2fX9XPbb1luRzOaAynUBZhqEA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691099; c=relaxed/simple; bh=xXa2Ur7OfAmDJDEohmixjhF6aazj1qpqn2Wkg4V9Nnw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EmiP8F/58oxg9tlro5j3Y6oHw0uTJe6I5Hru8eVxjdOFzRlA+DOh27WyjqCtRkI715nctlpUMaLLS4EMhdyRYj4SFX8vIo8Ww4fDv9eLryic1R2dmSCCNadKr4u7qAoMLEUqTkQXCbcz7nccyc0xfm0hnoWSopIaFWGJ4+YnDbY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=G+MA3y3c; 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="G+MA3y3c" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 20B3BC113CF; Mon, 28 Jul 2025 08:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691098; bh=xXa2Ur7OfAmDJDEohmixjhF6aazj1qpqn2Wkg4V9Nnw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=G+MA3y3cVypLaiGLcLbATR3gQzX85CCve8BJXS/VmDZbKCqq2k+xKD9JmpjDmBmXN syDlQd8Ks6Zs2ueCDDfxk1VJvjfY0flOXd609+5RXGVBfMiGCc2q63DJMUfFn3KQjO oic9+rOboUZ+kQ/GBGQjymC0uvnDZsli8fhQiyoPoXQsAHEgxJuU5NeDmEktq9XG17 uYok2zJHpHIW8UvMkokGsAeD2uUtXwNh9nBv84m7pGciENrNCCwStuMc0hWpZJZukp SJQSdBauzUrH+EvXd6zlj6GnUd5nxUMPOuk2Lktqj7qNeGs9C+msXk2UTzZhAuDqQj y5+rjLbpusRow== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:47 -0700 Subject: [PATCH RFC 17/25] PCI/LUO: Restore the no_d3cold flag 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: <20250728-luo-pci-v1-17-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu When the PCI bus adds a device, restore the saved no_d3cold flag before the bus does the D3 checking for the bridge. This tells the bridge the current D3cold availability of the device. Tested: QEMU VM boot test. Signed-off-by: Chris Li --- drivers/pci/bus.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 69048869ef1c378454f86091ddb2b59a3c3d53ec..e9c7a6dc643d3534755e4ef5218= fb6f90d5dcd65 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -353,6 +353,11 @@ void pci_bus_add_device(struct pci_dev *dev) of_pci_make_dev_node(dev); pci_create_sysfs_dev_files(dev); pci_proc_attach_device(dev); + /* + * Restore the no_d3cold flag for the device before we start to update + * the D3 state for the bridge. + */ + dev->no_d3cold =3D PCI_SER_GET(dev, no_d3cold, dev->no_d3cold); pci_bridge_d3_update(dev); =20 /* --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 C1C47262FC5; Mon, 28 Jul 2025 08:24:59 +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=1753691099; cv=none; b=ZfhVl4bJ6Wdth9aFHeT7Jiu0cYlK/pDRs2O/anUZMiKE5laxrtElOA3j/lmQXWHYu9Z0gqxUOJwl5Zu4p8YmOsfPCWf0Ux9sqn1DDi0ulbwHxd8ueCLpTUSXaEs0femmoPf4SbQ8R46Uu9ibtawjlYOgivv6Nz2kmTdppdYm5Ak= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691099; c=relaxed/simple; bh=+nVQSt29qRaiE2vOTxUXEh0dQ0wcmiDUnQlsU5hBKZM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qFtlwnSbXVD/lboZovSJ4npoWYGpJI2SCyom4VhYqAzbOD7VHKRdAikqM5vz/KPUNHGLK8WkX+KlDID7/sQJMoSZK8pJtuRgdi4QIwmvb2Ysd4pImrjj8+ZNSICKPMZ/qRl69gAqF8x8srIAYmYcGpuQfUnIdFXJaGM/jPovbMw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GTlK3blO; 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="GTlK3blO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C2504C4CEF7; Mon, 28 Jul 2025 08:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691099; bh=+nVQSt29qRaiE2vOTxUXEh0dQ0wcmiDUnQlsU5hBKZM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=GTlK3blOKnK+Q1VyGzIXv3UQNSpkRhDLaWigCNBWBd+sfn5ACT1z35OLxZnOJJ8AV vlSwN0kgpUPDtKkCqs61FfuFbasSJMIzdPD7NuXRho7ulp+hE70qeKhUuDdFxWf331 x/WlNt9ycdXioMdrnllghMpcQH/T3OxEbT1+oILaGJxe8tpjiSWXKnLQUoHLuBuzZJ DqskcG5VZmdJfOWb4NlmIVQaZBwamH7l/DxcReY9QEjL/spptKgMOq+nhJWsArYkar WJgmGHDK2FTdzP4JKyqS2mZJ8jk22w+LaGYeXFv0u23xpcFtrGN+GYOe76qKnUnZGW Y6e+iE0lklqKQ== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:48 -0700 Subject: [PATCH RFC 18/25] PCI/LUO: Restore pci_dev fields during probe 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: <20250728-luo-pci-v1-18-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu - pci_intx_mask_broken flag: This is a flag showing the PCI_COMMAND_INTX_DISABLE writability. Some devices PCI_COMMAND_INTX_DISABLE register is not writable, and this flag is used to report this capability. This flag is also updated in the driver/pci/quirks.c for fixing some devices, but those flags are static as the checking and udpating are being done for each device model, so we only restore the flag value from liveupdate in the PCI device setup. - pref_window and pref_64_window flags: Restore the pref_window and pref_64_window flags for a bridge device. These flags are managed by the function `pci_read_bridge_windows()` during the PCI device setup. Since we cannot write the PCI_PREF memory after a liveupdate reboot, so we restore the saved state from liveupdate. It is expected the following patches will skip the bridge device Pref window test in a liveupdate boot. - hotplug_user_indicators flags: Restore the hotplug_user_indicators flag for a PCI device. This flag is for managing platform-specific indicators, so during setting up the PCI device, restore this information from the Liveupdate. For the flag usage, see more in 576243b3f9ea. - ignore_hotplug flag: The flag ignore_hotplug is managed by the function `pci_ignore_hotplug()`, which is used by PCI drivers during a suspend operation. We restore this flag when a PCI device is setting up, to preserve the device state. Tested: QEMU VM boot test Signed-off-by: Chris Li --- drivers/pci/probe.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 7dd2cf9f9e110636f8998df22a333638cce25e6b..d8b80e1c4fb35289208d7c953fb= 5c1e137a5c1a8 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2059,7 +2059,24 @@ int pci_setup_device(struct pci_dev *dev) } } =20 - dev->broken_intx_masking =3D pci_intx_mask_broken(dev); + /* + * Restore PCI device fields: + * - Broken INTx masking and can't be used + * - Ignore hotplug events + * - Have the SlotCtl indicators controlled exclusively by user sysfs + * - Pref mem window availiblity of a bridge device + * - Pref mem window is 64-bit + */ + dev->broken_intx_masking =3D PCI_SER_GET(dev, broken_intx_masking, + pci_intx_mask_broken(dev)); + dev->ignore_hotplug =3D PCI_SER_GET(dev, ignore_hotplug, + dev->ignore_hotplug); + dev->hotplug_user_indicators =3D PCI_SER_GET(dev, hotplug_user_indicators, + dev->hotplug_user_indicators); + dev->pref_window =3D PCI_SER_GET(dev, pref_window, + dev->pref_window); + dev->pref_64_window =3D PCI_SER_GET(dev, pref_64_window, + dev->pref_64_window); =20 switch (dev->hdr_type) { /* header type */ case PCI_HEADER_TYPE_NORMAL: /* standard header */ --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 5E65F25F96D; Mon, 28 Jul 2025 08:25:00 +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=1753691100; cv=none; b=RBD371joOq1+cu2BBloHQolU7vKyDAMAik6UlRryN4aCbcJthVl1BkTbyAmKZHLSAHZmwkQ0Gl6mL4YPwKsCUu471K44pLy+avqYCr+J2gV3XYMfVHTC9vvMrj/NvDX8OfnbYycik94YrTEHhqw30bbWMurAVCkmiRSbe9QeFWQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691100; c=relaxed/simple; bh=juCljX7oHTMXLTvjtJv/ixWHfPDAWKS0NAoRAc5DtFc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=C7mcSAXbMCB2/02hYpYenL+/rQ0KGc4hcXBJbXM25QHBBTex68is0lPXBORD0Q/Ik6RUU583FCT1y+ZfRgYQm+FnCrDscx3d2BA8xBR2J7CdINcN5WFvMjC6ljoUfKfx3cK0vIrVFEk0OCSs0JYDToAT4J08RuSe7E82ZQdjyps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SITaB+tS; 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="SITaB+tS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6E1C1C4CEF9; Mon, 28 Jul 2025 08:24:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691100; bh=juCljX7oHTMXLTvjtJv/ixWHfPDAWKS0NAoRAc5DtFc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=SITaB+tSQu01TEAH8k5m46jzeXHXflq47YJ+VHQNx/d8JCBiAfxLkHs0MCjnWDRcu 1eybZESHcc28/Jjxjga/ms7TolsMNMD8rdGAGcnZ1HFuu8Y63WhBC8owgldFPhH+7y VZkJYXbMsjVbxEJjHcCNZgUb2lziBu7CuaouozpvdYzr8Z34dA9LBYo4XaOG2Z40AJ 7jy3vcChu4jnmLWH4+3DgZddNwBOjKmiBlzqXP+dmbmL3UU8bcF7N09PR8tbG9m5r7 PcQSNQ/Zd6oQA+Tr429+d6vudwySn4p97oJLgXfF7rhJopXQ94lmEesEYZa2velpCQ icNkaqL1hwWrw== From: Chris Li Date: Mon, 28 Jul 2025 01:24:49 -0700 Subject: [PATCH RFC 19/25] PCI/LUO: Track liveupdate buses 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: <20250728-luo-pci-v1-19-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 Add the bus state to PCI state, after the devs[] array. Currently for each bus only save the domain and bus number. Tested: In QEMU, perform liveupdate prepare. Check dmesg for "collect liveupdate bus" matching to the liveupdate device's bus. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 68 ++++++++++++++++++++++++++++++++++++++++----= ---- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index ec2d7917441ceb4e3d7cd8becae41ca215cba7c3..bc2c166ef494fd0b38cc05500bf= 0817c0f50fd95 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -16,11 +16,20 @@ #define PCI_SUBSYSTEM_NAME "pci" =20 static LIST_HEAD(preserved_devices); +static LIST_HEAD(preserved_buses); static LIST_HEAD(probe_devices); +static LIST_HEAD(probe_buses); + +struct pci_bus_ser { + u16 domain; + u8 number; +}; =20 struct pci_ser { - u32 count; + u32 dev_count; + u32 bus_count; struct pci_dev_ser devs[]; + /* struct pci_bus_ser buses[] */ }; =20 static void stack_push_buses(struct list_head *stack, struct list_head *bu= ses) @@ -39,7 +48,7 @@ static void requested_devices_add(struct device *dev, str= uct list_head *head) list_move_tail(&dev->lu.lu_next, head); } =20 -static int collect_bus_devices_reverse(struct pci_bus *bus, struct list_he= ad *head) +static int collect_buses_and_devices(struct pci_bus *bus, struct list_head= *head) { struct pci_dev *pdev; int count =3D 0; @@ -54,6 +63,13 @@ static int collect_bus_devices_reverse(struct pci_bus *b= us, struct list_head *he count++; } } + if (count || bus->dev.lu.depended) { + if (bus->parent) + bus->parent->dev.lu.depended =3D 1; + dev_info(&bus->dev, "collect liveupdate bus %s\n", + dev_name(&bus->dev)); + list_move_tail(&bus->dev.lu.lu_next, &preserved_buses); + } return count; } =20 @@ -76,9 +92,11 @@ static int build_liveupdate_devices(struct list_head *he= ad) continue; } =20 - count +=3D collect_bus_devices_reverse(bus, head); - busdev->lu.visited =3D 0; + /* Pop from bus_stack */ list_del_init(&busdev->lu.lu_next); + + count +=3D collect_buses_and_devices(bus, head); + busdev->lu.visited =3D 0; } return count; } @@ -102,6 +120,16 @@ static void cleanup_liveupdate_devices(struct list_hea= d *head) dev_cleanup_liveupdate(d); } =20 +static void cleanup_liveupdate_buses(struct list_head *head) +{ + struct device *b, *n; + + list_for_each_entry_safe(b, n, head, lu.lu_next) { + b->lu.depended =3D 0; + list_del_init(&b->lu.lu_next); + } +} + static void cleanup_liveupdate_state(struct pci_ser *pci_state) { struct folio *folio =3D virt_to_folio(pci_state); @@ -165,16 +193,24 @@ static int pci_save_device_state(struct device *dev, = struct pci_dev_ser *s) return 0; } =20 +static void pci_save_bus_state(struct pci_bus *bus, struct pci_bus_ser *s) +{ + s->number =3D bus->number; + s->domain =3D pci_domain_nr(bus); +} + static int pci_call_prepare(struct pci_ser *pci_state, struct list_head *devices) { - struct pci_dev_ser *pdev_state_current =3D pci_state->devs; + struct pci_dev_ser *dev_state =3D pci_state->devs; + struct pci_bus_ser *bus_state =3D (struct pci_bus_ser *) + (dev_state + pci_state->dev_count); struct device *dev, *next; int ret; char *reason; =20 list_for_each_entry_safe(dev, next, devices, lu.lu_next) { - struct pci_dev_ser *s =3D pdev_state_current++; + struct pci_dev_ser *s =3D dev_state++; =20 if (!dev->driver) { reason =3D "no driver"; @@ -200,6 +236,8 @@ static int pci_call_prepare(struct pci_ser *pci_state, } list_move_tail(&dev->lu.lu_next, &preserved_devices); } + list_for_each_entry(dev, &preserved_buses, lu.lu_next) + pci_save_bus_state(to_pci_bus(dev), bus_state++); return 0; =20 cancel: @@ -213,8 +251,10 @@ static int __pci_liveupdate_prepare(void *arg, u64 *da= ta) LIST_HEAD(requested_devices); struct pci_ser *pci_state; int ret; - int count =3D build_liveupdate_devices(&requested_devices); - int size =3D sizeof(*pci_state) + sizeof(pci_state->devs[0]) * count; + int devcnt =3D build_liveupdate_devices(&requested_devices); + int buscnt =3D list_count_nodes(&preserved_buses); + int size =3D sizeof(*pci_state) + sizeof(pci_state->devs[0]) * devcnt + + sizeof(struct pci_bus_ser) * buscnt; int order =3D get_order(size); struct folio *folio; =20 @@ -225,7 +265,8 @@ static int __pci_liveupdate_prepare(void *arg, u64 *dat= a) } =20 pci_state =3D folio_address(folio); - pci_state->count =3D count; + pci_state->dev_count =3D devcnt; + pci_state->bus_count =3D buscnt; =20 ret =3D kho_preserve_folio(folio); if (ret) { @@ -247,6 +288,7 @@ static int __pci_liveupdate_prepare(void *arg, u64 *dat= a) folio_put(folio); cleanup_device: cleanup_liveupdate_devices(&requested_devices); + cleanup_liveupdate_buses(&preserved_buses); return ret; } =20 @@ -336,6 +378,7 @@ static void pci_liveupdate_cancel(void *arg, u64 data) down_write(&pci_bus_sem); =20 pci_call_cancel(pci_state); + cleanup_liveupdate_buses(&preserved_buses); cleanup_liveupdate_state(pci_state); =20 up_write(&pci_bus_sem); @@ -349,6 +392,7 @@ static void pci_liveupdate_finish(void *arg, u64 data) pr_info("finish data[%llx]\n", data); pci_call_finish(&probe_devices); cleanup_liveupdate_devices(&probe_devices); + cleanup_liveupdate_buses(&probe_buses); cleanup_liveupdate_state(pci_state); } =20 @@ -408,14 +452,16 @@ static void pci_dev_do_restore(struct pci_dev *dev, s= truct pci_dev_ser *s) void pci_liveupdate_restore(struct pci_dev *dev) { int path; + struct pci_ser *pci_state; struct pci_dev_ser *s, *end; =20 if (!liveupdate_state_updated()) return; =20 path =3D pci_get_device_path(dev); - s =3D pci_state_get()->devs; - end =3D s + pci_state_get()->count; + pci_state =3D pci_state_get(); + s =3D pci_state->devs; + end =3D s + pci_state->dev_count; for (; s < end; s++) if (s->path =3D=3D path) return pci_dev_do_restore(dev, s); --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 C6561263C69; Mon, 28 Jul 2025 08:25:00 +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=1753691100; cv=none; b=rnd2oIhotiNwNvx3L5dR9Sw75e+VnTArNawimCeYCFQCAxK6yD0emLRc5aA8LwmD1Wk0ZuJlhwbjRZum37FVubTTV1bKmsuaBQCH4iuFQSc042kjQojmcMPZUg+8tF5QXygnLtyTTn0U0YwJEj6spV0woAEJ94ocOteyG3Bke9U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691100; c=relaxed/simple; bh=RjQ9lLOR+hqYsdRtALB8u/DoMGz57ed2p6m/XA4z51M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Jrheq7u5D3ABT494diiJMrxa8ltd7C4EIKcdDwQKKHNf46KkQGWk/B9o6WXDmFGAJenxtaK/FqqLUGf1qxu/iolItVkBKo6HBNgXvae2JVXCizcvTJ9+52Jf79JqbTfOMXR3saTEK2luXqnPGTBlM5taZ3kj7lgCrbGgRJ0BWxo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oLlR69pm; 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="oLlR69pm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1B243C4CEF7; Mon, 28 Jul 2025 08:25:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691100; bh=RjQ9lLOR+hqYsdRtALB8u/DoMGz57ed2p6m/XA4z51M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=oLlR69pmP3SQeDZGMr749Syy24vgZydvIfXbHoj1wzhIihnJ4nOFUu5ksoMab+95b 66r4qIR5wFVPCwIpIYaS5iohWMrk7LUiyX5B9wm1BjZ34yjyTkYTkuiecAfc6Cg16x BgbM4buzW036gj5F8gk6xyg/Z0W+mgXFv3c63TFhk2jEY8MuIJOSncjTjBEN35R7am yIqrjsc7QQ4dXGpqztvF5jXSKJEbaynmxRn0NpYxdEHgf7LV6RTU5NHC2qBfgUTfY1 xApAJpIoI2usKRc57c6d0V1CI5dskEY6HXSSO0rZjquZUf6TE0h0+BSphVJfoCSfgJ YtPI+YURtzP1g== From: Chris Li Date: Mon, 28 Jul 2025 01:24:50 -0700 Subject: [PATCH RFC 20/25] PCI/LUO: Avoid write to liveupdate devices at boot 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: <20250728-luo-pci-v1-20-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 The liveupdate devices are already initialized by the kernel before the kexec. During the kexec the device is still running. Avoid write to the liveupdate devices during the new kernel boot up. Signed-off-by: Chris Li --- drivers/pci/ats.c | 7 ++-- drivers/pci/iov.c | 58 ++++++++++++++++++------------ drivers/pci/msi/msi.c | 32 ++++++++++++----- drivers/pci/msi/pcidev_msi.c | 4 +-- drivers/pci/pci-acpi.c | 3 ++ drivers/pci/pci.c | 85 +++++++++++++++++++++++++++++-----------= ---- drivers/pci/pci.h | 9 ++++- drivers/pci/pcie/aspm.c | 7 ++-- drivers/pci/pcie/pme.c | 11 ++++-- drivers/pci/probe.c | 43 +++++++++++++++------- drivers/pci/setup-bus.c | 10 +++++- 11 files changed, 184 insertions(+), 85 deletions(-) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index ec6c8dbdc5e9c9959e822e016ab301bf483713a5..284f43c82593903058dee58ce64= b82bad8aed710 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -75,7 +75,9 @@ int pci_prepare_ats(struct pci_dev *dev, int ps) =20 dev->ats_stu =3D ps; ctrl =3D PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU); - pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); + + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); return 0; } EXPORT_SYMBOL_GPL(pci_prepare_ats); @@ -114,7 +116,8 @@ int pci_enable_ats(struct pci_dev *dev, int ps) dev->ats_stu =3D ps; ctrl |=3D PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU); } - pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); =20 dev->ats_enabled =3D 1; return 0; diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 10693b5d7eb66bbbfb9b70ffe6e89eb89c8dc3a3..df27bcf840d9fc0dbce29810e28= 8c1c2b74a70c9 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -85,7 +85,8 @@ static inline void pci_iov_set_numvfs(struct pci_dev *dev= , int nr_virtfn) { struct pci_sriov *iov =3D dev->sriov; =20 - pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn); pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &iov->offset); pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &iov->stride); } @@ -694,10 +695,12 @@ static int sriov_enable(struct pci_dev *dev, int nr_v= irtfn) =20 pci_iov_set_numvfs(dev, nr_virtfn); iov->ctrl |=3D PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; - pci_cfg_access_lock(dev); - pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); - msleep(100); - pci_cfg_access_unlock(dev); + if (!pci_lu_adopt(dev)) { + pci_cfg_access_lock(dev); + pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); + msleep(100); + pci_cfg_access_unlock(dev); + } =20 rc =3D sriov_add_vfs(dev, initial); if (rc) @@ -710,10 +713,12 @@ static int sriov_enable(struct pci_dev *dev, int nr_v= irtfn) =20 err_pcibios: iov->ctrl &=3D ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); - pci_cfg_access_lock(dev); - pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); - ssleep(1); - pci_cfg_access_unlock(dev); + if (!pci_lu_adopt(dev)) { + pci_cfg_access_lock(dev); + pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); + ssleep(1); + pci_cfg_access_unlock(dev); + } =20 pcibios_sriov_disable(dev); =20 @@ -741,11 +746,13 @@ static void sriov_disable(struct pci_dev *dev) return; =20 sriov_del_vfs(dev); - iov->ctrl &=3D ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); - pci_cfg_access_lock(dev); - pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); - ssleep(1); - pci_cfg_access_unlock(dev); + if (!pci_lu_adopt(dev)) { + iov->ctrl &=3D ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); + pci_cfg_access_lock(dev); + pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); + ssleep(1); + pci_cfg_access_unlock(dev); + } =20 pcibios_sriov_disable(dev); =20 @@ -770,7 +777,7 @@ static int sriov_init(struct pci_dev *dev, int pos) u32 sriovbars[PCI_SRIOV_NUM_BARS]; =20 pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl); - if (ctrl & PCI_SRIOV_CTRL_VFE) { + if (!pci_lu_adopt(dev) && ctrl & PCI_SRIOV_CTRL_VFE) { pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, 0); ssleep(1); } @@ -785,7 +792,8 @@ static int sriov_init(struct pci_dev *dev, int pos) ctrl |=3D PCI_SRIOV_CTRL_ARI; =20 found: - pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); =20 pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total); if (!total) @@ -798,7 +806,8 @@ static int sriov_init(struct pci_dev *dev, int pos) return -EIO; =20 pgsz &=3D ~(pgsz - 1); - pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz); + if (!pci_lu_adopt(dev)) + pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz); =20 iov =3D kzalloc(sizeof(*iov), GFP_KERNEL); if (!iov) @@ -904,14 +913,17 @@ static void sriov_restore_state(struct pci_dev *dev) */ ctrl &=3D ~PCI_SRIOV_CTRL_ARI; ctrl |=3D iov->ctrl & PCI_SRIOV_CTRL_ARI; - pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, ctrl); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, ctrl); =20 for (i =3D 0; i < PCI_SRIOV_NUM_BARS; i++) pci_update_resource(dev, i + PCI_IOV_RESOURCES); =20 - pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); + if (!pci_lu_adopt(dev)) + pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); pci_iov_set_numvfs(dev, iov->num_VFs); - pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); if (iov->ctrl & PCI_SRIOV_CTRL_VFE) msleep(100); } @@ -1013,10 +1025,12 @@ void pci_iov_update_resource(struct pci_dev *dev, i= nt resno) new |=3D res->flags & ~PCI_BASE_ADDRESS_MEM_MASK; =20 reg =3D iov->pos + PCI_SRIOV_BAR + 4 * vf_bar; - pci_write_config_dword(dev, reg, new); + if (!pci_lu_adopt(dev)) + pci_write_config_dword(dev, reg, new); if (res->flags & IORESOURCE_MEM_64) { new =3D region.start >> 16 >> 16; - pci_write_config_dword(dev, reg + 4, new); + if (!pci_lu_adopt(dev)) + pci_write_config_dword(dev, reg + 4, new); } } =20 diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c index 6ede55a7c5e652c80b51b10e58f0290eb6556430..7c40fde1ba0f89ad1d72064ac9e= 80696faeab426 100644 --- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -113,7 +113,8 @@ static int pci_setup_msi_context(struct pci_dev *dev) =20 void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 set) { - raw_spinlock_t *lock =3D &to_pci_dev(desc->dev)->msi_lock; + struct pci_dev *pci_dev =3D to_pci_dev(desc->dev); + raw_spinlock_t *lock =3D &pci_dev->msi_lock; unsigned long flags; =20 if (!desc->pci.msi_attrib.can_mask) @@ -122,8 +123,9 @@ void pci_msi_update_mask(struct msi_desc *desc, u32 cle= ar, u32 set) raw_spin_lock_irqsave(lock, flags); desc->pci.msi_mask &=3D ~clear; desc->pci.msi_mask |=3D set; - pci_write_config_dword(msi_desc_to_pci_dev(desc), desc->pci.mask_pos, - desc->pci.msi_mask); + if (!pci_lu_adopt(pci_dev)) + pci_write_config_dword(pci_dev, desc->pci.mask_pos, + desc->pci.msi_mask); raw_spin_unlock_irqrestore(lock, flags); } =20 @@ -190,6 +192,9 @@ static inline void pci_write_msg_msi(struct pci_dev *de= v, struct msi_desc *desc, int pos =3D dev->msi_cap; u16 msgctl; =20 + if (pci_lu_adopt(dev)) + return; + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); msgctl &=3D ~PCI_MSI_FLAGS_QSIZE; msgctl |=3D FIELD_PREP(PCI_MSI_FLAGS_QSIZE, desc->pci.msi_attrib.multiple= ); @@ -214,6 +219,8 @@ static inline void pci_write_msg_msix(struct msi_desc *= desc, struct msi_msg *msg =20 if (desc->pci.msi_attrib.is_virtual) return; + if (pci_lu_adopt(to_pci_dev(desc->dev))) + return; /* * The specification mandates that the entry is masked * when the message is modified: @@ -279,7 +286,8 @@ static void pci_msi_set_enable(struct pci_dev *dev, int= enable) control &=3D ~PCI_MSI_FLAGS_ENABLE; if (enable) control |=3D PCI_MSI_FLAGS_ENABLE; - pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); } =20 static int msi_setup_msi_desc(struct pci_dev *dev, int nvec, @@ -553,6 +561,7 @@ static void pci_msix_clear_and_set_ctrl(struct pci_dev = *dev, u16 clear, u16 set) { u16 ctrl; =20 + BUG_ON(pci_lu_adopt(dev)); pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl); ctrl &=3D ~clear; ctrl |=3D set; @@ -720,8 +729,9 @@ static int msix_capability_init(struct pci_dev *dev, st= ruct msix_entry *entries, * registers can be accessed. Mask all the vectors to prevent * interrupts coming in before they're fully set up. */ - pci_msix_clear_and_set_ctrl(dev, 0, PCI_MSIX_FLAGS_MASKALL | - PCI_MSIX_FLAGS_ENABLE); + if (!pci_lu_adopt(dev)) + pci_msix_clear_and_set_ctrl(dev, 0, PCI_MSIX_FLAGS_MASKALL | + PCI_MSIX_FLAGS_ENABLE); =20 /* Mark it enabled so setup functions can query it */ dev->msix_enabled =3D 1; @@ -753,14 +763,16 @@ static int msix_capability_init(struct pci_dev *dev, = struct msix_entry *entries, */ msix_mask_all(dev->msix_base, tsize); } - pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); + if (!pci_lu_adopt(dev)) + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); =20 pcibios_free_irq(dev); return 0; =20 out_disable: dev->msix_enabled =3D 0; - pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_= ENABLE, 0); + if (!pci_lu_adopt(dev)) + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS= _ENABLE, 0); =20 return ret; } @@ -864,6 +876,7 @@ void __pci_restore_msix_state(struct pci_dev *dev) if (!dev->msix_enabled) return; =20 + BUG_ON(pci_lu_adopt(dev)); /* route the table */ pci_intx_for_msi(dev, 0); pci_msix_clear_and_set_ctrl(dev, 0, @@ -898,7 +911,8 @@ void pci_msix_shutdown(struct pci_dev *dev) msi_for_each_desc(desc, &dev->dev, MSI_DESC_ALL) pci_msix_mask(desc); =20 - pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0); + if (!pci_lu_adopt(dev)) + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0); pci_intx_for_msi(dev, 1); dev->msix_enabled =3D 0; pcibios_alloc_irq(dev); diff --git a/drivers/pci/msi/pcidev_msi.c b/drivers/pci/msi/pcidev_msi.c index 5520aff53b5670e70311c63f0f358228bf03c309..f9f682a84a05ef47ff4d85e7d0e= 724cc7c2f5cdc 100644 --- a/drivers/pci/msi/pcidev_msi.c +++ b/drivers/pci/msi/pcidev_msi.c @@ -18,7 +18,7 @@ void pci_msi_init(struct pci_dev *dev) return; =20 pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl); - if (ctrl & PCI_MSI_FLAGS_ENABLE) { + if (!pci_lu_adopt(dev) && ctrl & PCI_MSI_FLAGS_ENABLE) { pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, ctrl & ~PCI_MSI_FLAGS_ENABLE); } @@ -36,7 +36,7 @@ void pci_msix_init(struct pci_dev *dev) return; =20 pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl); - if (ctrl & PCI_MSIX_FLAGS_ENABLE) { + if (!pci_lu_adopt(dev) && ctrl & PCI_MSIX_FLAGS_ENABLE) { pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, ctrl & ~PCI_MSIX_FLAGS_ENABLE); } diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index af370628e58393aa0cbdf6d283b3afe33e5effb5..b9e42a1352c87443dd5c4ee9f03= bc8a0d343d714 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -172,6 +172,9 @@ static void program_hpx_type0(struct pci_dev *dev, stru= ct hpx_type0 *hpx) hpx =3D &pci_default_type0; } =20 + if (pci_lu_adopt(dev)) + return; + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpx->cache_line_size); pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpx->latency_timer); pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 46fb80dbca590c251fcad3bf2f011a16f6898810..c1cc723f979ae881cf07ad06e1f= a0d472e8b89c6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -218,7 +218,7 @@ int pci_status_get_and_clear_errors(struct pci_dev *pde= v) return -EIO; =20 status &=3D PCI_STATUS_ERROR_BITS; - if (status) + if (status && !pci_lu_adopt(pdev)) pci_write_config_word(pdev, PCI_STATUS, status); =20 return status; @@ -628,7 +628,7 @@ u64 pci_get_dsn(struct pci_dev *dev) int pos; =20 pos =3D pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DSN); - if (!pos) + if (!pos && !pci_lu_adopt(dev)) return 0; =20 /* @@ -1103,7 +1103,8 @@ static void pci_enable_acs(struct pci_dev *dev) ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC)); __pci_config_acs(dev, &caps, config_acs_param, 0, 0); =20 - pci_write_config_word(dev, pos + PCI_ACS_CTRL, caps.ctrl); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, pos + PCI_ACS_CTRL, caps.ctrl); } =20 /** @@ -1394,7 +1395,8 @@ int pci_power_up(struct pci_dev *dev) * Force the entire word to 0. This doesn't affect PME_Status, disables * PME_En, and sets PowerState to 0. */ - pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, 0); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, 0); =20 /* Mandatory transition delays; see PCI PM 1.2. */ if (state =3D=3D PCI_D3hot) @@ -1552,7 +1554,8 @@ static int pci_set_low_power_state(struct pci_dev *de= v, pci_power_t state, bool pmcsr |=3D state; =20 /* Enter specified state */ - pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); =20 /* Mandatory power management transition delays; see PCI PM 1.2. */ if (state =3D=3D PCI_D3hot) @@ -1781,7 +1784,8 @@ static void pci_restore_pcix_state(struct pci_dev *de= v) return; cap =3D (u16 *)&save_state->cap.data[0]; =20 - pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]); } =20 /** @@ -2090,7 +2094,7 @@ static int do_pci_enable_device(struct pci_dev *dev, = int bars) pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin) { pci_read_config_word(dev, PCI_COMMAND, &cmd); - if (cmd & PCI_COMMAND_INTX_DISABLE) + if (!pci_lu_adopt(dev) && cmd & PCI_COMMAND_INTX_DISABLE) pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_INTX_DISABLE); } @@ -2248,7 +2252,8 @@ static void do_pci_disable_device(struct pci_dev *dev) pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &=3D ~PCI_COMMAND_MASTER; - pci_write_config_word(dev, PCI_COMMAND, pci_command); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_COMMAND, pci_command); } =20 pcibios_disable_device(dev); @@ -2369,7 +2374,8 @@ bool pci_check_pme_status(struct pci_dev *dev) ret =3D true; } =20 - pci_write_config_word(dev, pmcsr_pos, pmcsr); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, pmcsr_pos, pmcsr); =20 return ret; } @@ -2484,7 +2490,8 @@ static void __pci_pme_active(struct pci_dev *dev, boo= l enable) if (!enable) pmcsr &=3D ~PCI_PM_CTRL_PME_ENABLE; =20 - pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); } =20 /** @@ -2506,7 +2513,8 @@ void pci_pme_restore(struct pci_dev *dev) pmcsr &=3D ~PCI_PM_CTRL_PME_ENABLE; pmcsr |=3D PCI_PM_CTRL_PME_STATUS; } - pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); } =20 /** @@ -3587,12 +3595,14 @@ void pci_configure_ari(struct pci_dev *dev) return; =20 if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) { - pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, - PCI_EXP_DEVCTL2_ARI); + if (!pci_lu_adopt(dev)) + pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, + PCI_EXP_DEVCTL2_ARI); bridge->ari_enabled =3D 1; } else { - pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2, - PCI_EXP_DEVCTL2_ARI); + if (!pci_lu_adopt(dev)) + pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2, + PCI_EXP_DEVCTL2_ARI); bridge->ari_enabled =3D 0; } } @@ -4286,7 +4296,8 @@ static void __pci_set_master(struct pci_dev *dev, boo= l enable) if (cmd !=3D old_cmd) { pci_dbg(dev, "%s bus mastering\n", enable ? "enabling" : "disabling"); - pci_write_config_word(dev, PCI_COMMAND, cmd); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_COMMAND, cmd); } dev->is_busmaster =3D enable; } @@ -4416,7 +4427,8 @@ int pci_set_mwi(struct pci_dev *dev) if (!(cmd & PCI_COMMAND_INVALIDATE)) { pci_dbg(dev, "enabling Mem-Wr-Inval\n"); cmd |=3D PCI_COMMAND_INVALIDATE; - pci_write_config_word(dev, PCI_COMMAND, cmd); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0; #endif @@ -4456,7 +4468,8 @@ void pci_clear_mwi(struct pci_dev *dev) pci_read_config_word(dev, PCI_COMMAND, &cmd); if (cmd & PCI_COMMAND_INVALIDATE) { cmd &=3D ~PCI_COMMAND_INVALIDATE; - pci_write_config_word(dev, PCI_COMMAND, cmd); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_COMMAND, cmd); } #endif } @@ -4475,7 +4488,8 @@ void pci_disable_parity(struct pci_dev *dev) pci_read_config_word(dev, PCI_COMMAND, &cmd); if (cmd & PCI_COMMAND_PARITY) { cmd &=3D ~PCI_COMMAND_PARITY; - pci_write_config_word(dev, PCI_COMMAND, cmd); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_COMMAND, cmd); } } =20 @@ -4500,7 +4514,8 @@ void pci_intx(struct pci_dev *pdev, int enable) if (new =3D=3D pci_command) return; =20 - pci_write_config_word(pdev, PCI_COMMAND, new); + if (!pci_lu_adopt(pdev)) + pci_write_config_word(pdev, PCI_COMMAND, new); } EXPORT_SYMBOL_GPL(pci_intx); =20 @@ -4648,12 +4663,14 @@ static int pci_pm_reset(struct pci_dev *dev, bool p= robe) =20 csr &=3D ~PCI_PM_CTRL_STATE_MASK; csr |=3D PCI_D3hot; - pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); pci_dev_d3_sleep(dev); =20 csr &=3D ~PCI_PM_CTRL_STATE_MASK; csr |=3D PCI_D0; - pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); pci_dev_d3_sleep(dev); =20 return pci_dev_wait(dev, "PM D3hot->D0", PCIE_RESET_READY_POLL_MS); @@ -4959,6 +4976,7 @@ void pci_reset_secondary_bus(struct pci_dev *dev) { u16 ctrl; =20 + BUG_ON(pci_lu_adopt(dev)); pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl); ctrl |=3D PCI_BRIDGE_CTL_BUS_RESET; pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); @@ -5186,7 +5204,8 @@ static void pci_dev_save_and_disable(struct pci_dev *= dev) * DMA from the device including MSI/MSI-X interrupts. For PCI 2.3 * compliant devices, INTx-disable prevents legacy interrupts. */ - pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); } =20 static void pci_dev_restore(struct pci_dev *dev) @@ -5897,8 +5916,9 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) =20 cmd &=3D ~PCI_X_CMD_MAX_READ; cmd |=3D FIELD_PREP(PCI_X_CMD_MAX_READ, v); - if (pci_write_config_word(dev, cap + PCI_X_CMD, cmd)) - return -EIO; + if (!pci_lu_adopt(dev)) + if (pci_write_config_word(dev, cap + PCI_X_CMD, cmd)) + return -EIO; } return 0; } @@ -5960,6 +5980,8 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) } } =20 + if (pci_lu_adopt(dev)) + return 0; ret =3D pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_READRQ, v); =20 @@ -6004,6 +6026,8 @@ int pcie_set_mps(struct pci_dev *dev, int mps) return -EINVAL; v =3D FIELD_PREP(PCI_EXP_DEVCTL_PAYLOAD, v); =20 + if (pci_lu_adopt(dev)) + return 0; ret =3D pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_PAYLOAD, v); =20 @@ -6304,7 +6328,8 @@ int pci_set_vga_state(struct pci_dev *dev, bool decod= e, cmd |=3D command_bits; else cmd &=3D ~command_bits; - pci_write_config_word(dev, PCI_COMMAND, cmd); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_COMMAND, cmd); } =20 if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE)) @@ -6320,8 +6345,9 @@ int pci_set_vga_state(struct pci_dev *dev, bool decod= e, cmd |=3D PCI_BRIDGE_CTL_VGA; else cmd &=3D ~PCI_BRIDGE_CTL_VGA; - pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, - cmd); + if (!pci_lu_adopt(bridge)) + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, + cmd); } bus =3D bus->parent; } @@ -6621,7 +6647,8 @@ void pci_reassigndev_resource_alignment(struct pci_de= v *dev) =20 pci_read_config_word(dev, PCI_COMMAND, &command); command &=3D ~PCI_COMMAND_MEMORY; - pci_write_config_word(dev, PCI_COMMAND, command); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_COMMAND, command); =20 for (i =3D 0; i <=3D PCI_ROM_RESOURCE; i++) pci_request_resource_alignment(dev, i, align, resize); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index a8acc986a5aac808ec64395d7d946ee036270f5b..bd198227ae3cf687f4ddae76c2f= 53125681ca91d 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1188,11 +1188,18 @@ static inline int pci_msix_write_tph_tag(struct pci= _dev *pdev, unsigned int inde =20 void pci_liveupdate_restore(struct pci_dev *dev); void pci_liveupdate_override_driver(struct pci_dev *dev); +static inline struct pci_dev_ser *pci_lu_adopt(struct pci_dev *dev) +{ + return dev->dev.lu.requested ? dev->dev.lu.dev_state : NULL; +} #else #define PCI_SER_GET(__dev, __var, __def) __def =20 static inline void pci_liveupdate_restore(struct pci_dev *dev) {} static inline void pci_liveupdate_override_driver(struct pci_dev *dev) {} +static inline struct pci_dev_ser *pci_lu_adopt(struct pci_dev *dev) +{ + return NULL; +} #endif - #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 29fcb0689a918f9cb123691e1680de5a1af2c115..61f9a443f6ad2bad57d3fc5958e= 8855117f79598 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -788,7 +788,7 @@ static void aspm_l1ss_init(struct pcie_link_state *link) aspm_calc_l12_info(link, parent_l1ss_cap, child_l1ss_cap); } =20 -static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) +static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist= , bool lu_restore) { struct pci_dev *child =3D link->downstream, *parent =3D link->pdev; u32 parent_lnkcap, child_lnkcap; @@ -812,7 +812,8 @@ static void pcie_aspm_cap_init(struct pcie_link_state *= link, int blacklist) return; =20 /* Configure common clock before checking latencies */ - pcie_aspm_configure_common_clock(link); + if (!lu_restore) + pcie_aspm_configure_common_clock(link); =20 /* * Re-read upstream/downstream components' register state after @@ -1130,7 +1131,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) * upstream links also because capable state of them can be * update through pcie_aspm_cap_init(). */ - pcie_aspm_cap_init(link, blacklist); + pcie_aspm_cap_init(link, blacklist, pci_lu_adopt(pdev)); =20 /* Setup initial Clock PM state */ pcie_clkpm_cap_init(link, blacklist); diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index a2daebd9806cd7273ee331406201402a758bd7b8..da093a5ba7ee1f9d20652c71e8e= 78662fdab176c 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -53,6 +53,8 @@ struct pcie_pme_service_data { */ void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) { + if (pci_lu_adopt(dev)) + return; if (enable) pcie_capability_set_word(dev, PCI_EXP_RTCTL, PCI_EXP_RTCTL_PMEIE); @@ -344,8 +346,10 @@ static int pcie_pme_probe(struct pcie_device *srv) data->srv =3D srv; set_service_data(srv, data); =20 - pcie_pme_interrupt_enable(port, false); - pcie_clear_root_pme_status(port); + if (!pci_lu_adopt(port)) { + pcie_pme_interrupt_enable(port, false); + pcie_clear_root_pme_status(port); + } =20 ret =3D request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv); if (ret) { @@ -356,7 +360,8 @@ static int pcie_pme_probe(struct pcie_device *srv) pci_info(port, "Signaling with IRQ %d\n", srv->irq); =20 pcie_pme_mark_devices(port); - pcie_pme_interrupt_enable(port, true); + if (!pci_lu_adopt(port)) + pcie_pme_interrupt_enable(port, true); return 0; } =20 diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index d8b80e1c4fb35289208d7c953fb5c1e137a5c1a8..5c30d1d52a96b17a92794756cab= 5db0972548267 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -358,7 +358,7 @@ static __always_inline void pci_read_bases(struct pci_d= ev *dev, return; =20 /* No printks while decoding is disabled! */ - if (!dev->mmio_always_on) { + if (!pci_lu_adopt(dev) && !dev->mmio_always_on) { pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); if (orig_cmd & PCI_COMMAND_DECODE_ENABLE) { pci_write_config_word(dev, PCI_COMMAND, @@ -366,11 +366,13 @@ static __always_inline void pci_read_bases(struct pci= _dev *dev, } } =20 - __pci_size_stdbars(dev, howmany, PCI_BASE_ADDRESS_0, stdbars); - if (rom) - __pci_size_rom(dev, rom, &rombar); + if (!pci_lu_adopt(dev)) { + __pci_size_stdbars(dev, howmany, PCI_BASE_ADDRESS_0, stdbars); + if (rom) + __pci_size_rom(dev, rom, &rombar); + } =20 - if (!dev->mmio_always_on && + if (!pci_lu_adopt(dev) && !dev->mmio_always_on && (orig_cmd & PCI_COMMAND_DECODE_ENABLE)) pci_write_config_word(dev, PCI_COMMAND, orig_cmd); =20 @@ -1269,8 +1271,9 @@ static void pci_enable_rrs_sv(struct pci_dev *pdev) /* Enable Configuration RRS Software Visibility if supported */ pcie_capability_read_word(pdev, PCI_EXP_RTCAP, &root_cap); if (root_cap & PCI_EXP_RTCAP_RRS_SV) { - pcie_capability_set_word(pdev, PCI_EXP_RTCTL, - PCI_EXP_RTCTL_RRS_SVE); + if (!pci_lu_adopt(pdev)) + pcie_capability_set_word(pdev, PCI_EXP_RTCTL, + PCI_EXP_RTCTL_RRS_SVE); pdev->config_rrs_sv =3D 1; } } @@ -1384,8 +1387,9 @@ static int pci_scan_bridge_extend(struct pci_bus *bus= , struct pci_dev *dev, * bus errors in some architectures. */ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl); - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, - bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, + bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); =20 if ((secondary || subordinate) && !pcibios_assign_all_busses() && !is_cardbus && !broken) { @@ -1404,6 +1408,10 @@ static int pci_scan_bridge_extend(struct pci_bus *bu= s, struct pci_dev *dev, * more than one bridge. The second case can happen with * the i450NX chipset. */ + if (pci_lu_adopt(dev)) { + /* Verify bus number here */ + } + child =3D pci_find_bus(pci_domain_nr(bus), secondary); if (!child) { child =3D pci_add_new_bus(bus, dev, secondary); @@ -1558,7 +1566,8 @@ static int pci_scan_bridge_extend(struct pci_bus *bus= , struct pci_dev *dev, /* Clear errors in the Secondary Status Register */ pci_write_config_word(dev, PCI_SEC_STATUS, 0xffff); =20 - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); + if (!pci_lu_adopt(dev)) + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); =20 pm_runtime_put(&dev->dev); =20 @@ -2035,7 +2044,10 @@ int pci_setup_device(struct pci_dev *dev) * If we are not booted from liveupdate, default * "Unknown power state". */ - dev->current_state =3D PCI_SER_GET(dev, current_state, PCI_UNKNOWN); + if (pci_lu_adopt(dev)) + dev->current_state =3D 0; /* FIXME */ + else + dev->current_state =3D PCI_SER_GET(dev, current_state, PCI_UNKNOWN); =20 /* Early fixups, before probing the BARs */ pci_fixup_device(pci_fixup_early, dev); @@ -2075,7 +2087,8 @@ int pci_setup_device(struct pci_dev *dev) dev->hotplug_user_indicators); dev->pref_window =3D PCI_SER_GET(dev, pref_window, dev->pref_window); - dev->pref_64_window =3D PCI_SER_GET(dev, pref_64_window, + if (!pci_lu_adopt(dev)) + dev->pref_64_window =3D PCI_SER_GET(dev, pref_64_window, dev->pref_64_window); =20 switch (dev->hdr_type) { /* header type */ @@ -2269,6 +2282,10 @@ int pci_configure_extended_tags(struct pci_dev *dev,= void *ign) if (!host) return 0; =20 + + if (pci_lu_adopt(dev)) + return 0; + /* * If some device in the hierarchy doesn't handle Extended Tags * correctly, make sure they're disabled. @@ -2373,7 +2390,7 @@ static void pci_configure_serr(struct pci_dev *dev) * endpoint unless SERR# forwarding is enabled. */ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &control); - if (!(control & PCI_BRIDGE_CTL_SERR)) { + if (!pci_lu_adopt(dev) && !(control & PCI_BRIDGE_CTL_SERR)) { control |=3D PCI_BRIDGE_CTL_SERR; pci_write_config_word(dev, PCI_BRIDGE_CONTROL, control); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 07c3d021a47ec794aaae13e1c12a667cfb47cb45..276a62c6957218c0c89d8881b1a= 4d6f6d419dacf 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -706,6 +706,9 @@ static void pci_setup_bridge_io(struct pci_dev *bridge) io_upper16 =3D 0; l =3D 0x00f0; } + + if (pci_lu_adopt(bridge)) + return; /* Temporarily disable the I/O range before updating PCI_IO_BASE */ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff); /* Update lower 16 bits of I/O base/limit */ @@ -732,6 +735,8 @@ static void pci_setup_bridge_mmio(struct pci_dev *bridg= e) } else { l =3D 0x0000fff0; } + if (pci_lu_adopt(bridge)) + return; pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); } =20 @@ -765,6 +770,8 @@ static void pci_setup_bridge_mmio_pref(struct pci_dev *= bridge) } else { l =3D 0x0000fff0; } + if (pci_lu_adopt(bridge)) + return; pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); =20 /* Set the upper 32 bits of PREF base & limit */ @@ -787,7 +794,8 @@ static void __pci_setup_bridge(struct pci_bus *bus, uns= igned long type) if (type & IORESOURCE_PREFETCH) pci_setup_bridge_mmio_pref(bridge); =20 - pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); + if (!pci_lu_adopt(bridge)) + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); } =20 void __weak pcibios_setup_bridge(struct pci_bus *bus, unsigned long type) --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 74164263F5E; Mon, 28 Jul 2025 08:25:01 +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=1753691101; cv=none; b=C5u6gmq9XM7k0jnbobKyrvw3KQVOnJVVa436b/X+pafEZfB3dyzp2RrfDGNp83A26JIbzqkkQAbPyO7lSgC4RJLBLyJvTj+CibxIzcYzGSUZZmN7pqZhjId35IY+Mt4J1X3IeHl0H6Uwp0xrKhzWuebZQS2RBRAZA5gfKp99Eac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691101; c=relaxed/simple; bh=li5Q22e4feDbcXIQrk3wPzRkb+BbXFeCCERNZ9GWjto=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hTSQr3eybmEHDb5vlkN1+s7FagXch6raMhanz9mbfdxkmEfJzozMZAl+Kt+y0+0IccdZ8m+THGzw69EXpZD0ixFUY/LCyxY5LK1xOWJKEkjuyBNHMVS1BhemtSonizLOcupvRp94mqegdDNgzgayr+qHxyy0jDjNXzWPpqp8tjw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VpxQqHVd; 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="VpxQqHVd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C8B06C4CEE7; Mon, 28 Jul 2025 08:25:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691101; bh=li5Q22e4feDbcXIQrk3wPzRkb+BbXFeCCERNZ9GWjto=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=VpxQqHVdeNn9dKW35pGt9VhlI0tG1Y97OEeSuRy8RRA0NBGtHVnh8HBhrfCKZCOOQ fAqX0ZZi9IK6e3EjbxDB4ASIcYeNlI1rWTV604Kku9rtAVY4tl4kPwSYAdyKpMqf4G 30+CZRGImjxpi56PFtyQEKO402lBTnZtsqAIP+SiYQEpzZ2xs2PCKAY+sTHkRVyJVr 3mDw+KfQ4wV6BqIFI2h7cjk4viJiP48QFeCL/CmPETm6m8XiRvA0SEfxzkHgeU4Cle nt2Pyc707ui+8tvZ4bQdW8BQud6xCXp+Y+Bor6pDABD06WNqYrDR0g2R56If+l2y4D dtRRNeweMXZ2w== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:51 -0700 Subject: [PATCH RFC 21/25] PCI/LUO: Save and restore the PCI resource 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: <20250728-luo-pci-v1-21-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu Preserve the resource array in pci_dev, in pci_dev_ser with an array of `struct pci_resource_ser`. This array save all resource regions claimed by a PCI device in the LUO prepare phase. When a PCI device is setting up after a liveupdate reboot, normally it read/write the PCI BARs for probing the available resource regions, with pci_read_bases() function. We check if liveupdate is enabled and the preserved resource is preserved. If it does, we restore the resource data structure instead of accessing the hardware. Tested: - QEMU VM boot test. Save and restore a pf-test driver. Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 52 ++++++++++++++++++++++++++++++++++++++++++++= +++- drivers/pci/pci.h | 17 ++++++++++++++++ drivers/pci/probe.c | 18 ++++++++++++++--- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index bc2c166ef494fd0b38cc05500bf0817c0f50fd95..7fda7e4d409adce6bf92ef7af11= 67f7bda302c7e 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -166,10 +166,12 @@ static int pci_save_device_state(struct device *dev, = struct pci_dev_ser *s) { struct pci_dev *pdev =3D to_pci_dev(dev); const char *name =3D dev->driver->name; + int i; =20 if (!name) return -ENXIO; - if (strlen(name) > sizeof(s->driver_name) - 1) + if ((strlen(name) > sizeof(s->driver_name) - 1) || + (strlen(name) > sizeof(s->resource[0].name) - 1)) return -ENOSPC; strscpy(s->driver_name, name, sizeof(s->driver_name)); s->path =3D pci_get_device_path(pdev); @@ -190,6 +192,28 @@ static int pci_save_device_state(struct device *dev, s= truct pci_dev_ser *s) s->pref_window =3D pdev->pref_window; s->pref_64_window =3D pdev->pref_64_window; =20 + /* + * Per PCIe r4.0, sec 9.3.4.1.11, the VF BARs are all RO Zero, + * no need to preserve the resource. + */ + if (pdev->is_virtfn) + return 0; + + for (i =3D 0; i < DEVICE_COUNT_RESOURCE; i++) { + /* This resource region is not claimed by this device, skip. */ + if ((pdev->resource[i].name =3D=3D NULL) || + (strlen(pdev->resource[i].name) =3D=3D 0)) + continue; + + s->resource[i].start =3D pdev->resource[i].start; + s->resource[i].end =3D pdev->resource[i].end; + s->resource[i].flags =3D pdev->resource[i].flags; + s->resource[i].desc =3D pdev->resource[i].desc; + + strscpy((char *)s->resource[i].name, pci_name(pdev), + sizeof(s->resource[i].name)); + } + return 0; } =20 @@ -502,6 +526,32 @@ void pci_liveupdate_override_driver(struct pci_dev *de= v) panic("PCI Liveupdate override driver failed: %s", s->driver_name); } =20 +int pci_liveupdate_reclaim_resource(struct pci_dev *dev) +{ + const char *name =3D pci_name(dev); + int i; + + if (!dev->dev.lu.dev_state) + return -EINVAL; + + if (dev->is_virtfn) + return 0; + + for (i =3D 0; i < DEVICE_COUNT_RESOURCE; i++) { + /* This resource region was not claimed, skip. */ + if (strncmp(PCI_SER_GET(dev, resource[i].name, ""), name, + strlen(name)) !=3D 0) + continue; + + dev->resource[i].start =3D PCI_SER_GET(dev, resource[i].start, 0); + dev->resource[i].end =3D PCI_SER_GET(dev, resource[i].end, 0); + dev->resource[i].name =3D pci_name(dev); + dev->resource[i].flags =3D PCI_SER_GET(dev, resource[i].flags, 0); + dev->resource[i].desc =3D PCI_SER_GET(dev, resource[i].desc, 0); + } + + return 0; +} =20 static int __init pci_liveupdate_init(void) { diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index bd198227ae3cf687f4ddae76c2f53125681ca91d..7af32edb128faef9c5e2665ca50= 55374f7fd30ea 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -489,6 +489,19 @@ struct pci_sriov { bool drivers_autoprobe; /* Auto probing of VFs by driver */ }; =20 +#define PCI_RESOURCE_SER_NAME_SIZE 64 +struct pci_resource_ser { + u64 start; + u64 end; + const char name[PCI_RESOURCE_SER_NAME_SIZE]; + u64 flags; + u64 desc; + /* + * The PCI resource is not nested. We do not need to preserve + * the parent, sibling, child pointers in the original struct resource. + */ +} __packed; + struct pci_dev_ser { u32 path; /* domain + bus + slot + fn */ u8 requested; @@ -509,6 +522,7 @@ struct pci_dev_ser { u32 hotplug_user_indicators:1; u32 pref_window:1; u32 pref_64_window:1; + struct pci_resource_ser resource[DEVICE_COUNT_RESOURCE]; } __packed; =20 #ifdef CONFIG_PCI_DOE @@ -1192,6 +1206,7 @@ static inline struct pci_dev_ser *pci_lu_adopt(struct= pci_dev *dev) { return dev->dev.lu.requested ? dev->dev.lu.dev_state : NULL; } +int pci_liveupdate_reclaim_resource(struct pci_dev *dev); #else #define PCI_SER_GET(__dev, __var, __def) __def =20 @@ -1201,5 +1216,7 @@ static inline struct pci_dev_ser *pci_lu_adopt(struct= pci_dev *dev) { return NULL; } +static inline int pci_liveupdate_reclaim_resource( + struct pci_dev *dev) { return -ENXIO; } #endif #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5c30d1d52a96b17a92794756cab5db0972548267..a101a44956821e5e81c6b063e6a= ab7db49a4cf7f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2096,7 +2096,13 @@ int pci_setup_device(struct pci_dev *dev) if (class =3D=3D PCI_CLASS_BRIDGE_PCI) goto bad; pci_read_irq(dev); - pci_read_bases(dev, PCI_STD_NUM_BARS, PCI_ROM_ADDRESS); + + /* + * If we can reclaim the resource from liveupdate preserved data, + * do not access the hardware. + */ + if (pci_liveupdate_reclaim_resource(dev) < 0) + pci_read_bases(dev, PCI_STD_NUM_BARS, PCI_ROM_ADDRESS); =20 pci_subsystem_ids(dev, &dev->subsystem_vendor, &dev->subsystem_device); =20 @@ -2152,7 +2158,10 @@ int pci_setup_device(struct pci_dev *dev) */ pci_read_irq(dev); dev->transparent =3D ((dev->class & 0xff) =3D=3D 1); - pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); + + if (pci_liveupdate_reclaim_resource(dev) < 0) + pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); + pci_read_bridge_windows(dev); set_pcie_hotplug_bridge(dev); pos =3D pci_find_capability(dev, PCI_CAP_ID_SSVID); @@ -2166,7 +2175,10 @@ int pci_setup_device(struct pci_dev *dev) if (class !=3D PCI_CLASS_BRIDGE_CARDBUS) goto bad; pci_read_irq(dev); - pci_read_bases(dev, 1, 0); + + if (pci_liveupdate_reclaim_resource(dev) < 0) + pci_read_bases(dev, 1, 0); + pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_ve= ndor); pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device); break; --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:28 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 1DE9A264638; Mon, 28 Jul 2025 08:25:02 +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=1753691102; cv=none; b=nBSfjq7Lm+nWve54j/rVPycBDuS2FwrPqbxXmhwrKArepX5yfrfLg+gbo7lNwzqk2rEiAz6gLACC8ZvU7A6F0XxO6TzSeF9a/PzK9kSrmwTkpjTQSqEkLeLLRvi/j8I7KF5F6IIt5eIebOzoQCszs4KKzI/4nmhVWoarspjPibk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691102; c=relaxed/simple; bh=903NuybbYnxSHrFX0vEqTNoJB/Kj4NeieaFb+MTU0mk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=COZD//JHkFJkO9t4DRLexT0wUih+hGkQLwRbcNAdYjm8gzrr9zz3NyBDrd3sPZBOwSXBmP1Gn3eHOuYBHslCOotuAQa1vTcCvxhyzKgxNwfgxd2aRAsCSLGv8hFf9SL5EoAESer/wJlmh3mLat2Geo1HenlRNOFHovmeHncxRAI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aZdrC8Fv; 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="aZdrC8Fv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7552BC4CEFB; Mon, 28 Jul 2025 08:25:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691102; bh=903NuybbYnxSHrFX0vEqTNoJB/Kj4NeieaFb+MTU0mk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=aZdrC8Fv2tLqZr6YNNoEx/xvn92aW1MWReV4sFxFXCZEVUtmr2l7GNztDWakURsZ2 ahVRaUdvhp8zJ0e2W3UOdEyNBePFaReCM6nw6X4bTRzQ1dLZu675I6V6QEbNPjBmbx h9+dxjQAZAGvgkKRJ9P6qRzCaLTnoUAU6nOvl7JPnvQ0+7DMy+SWfXk1cjfgf9vnz8 U4NGTuiDBIkD6K0Xok/FUeWuo8YAMM+x2G07pII3/v8IMDkWZkum8r5LAZZieyxMUT 0M6ZUemexwzcPAs/cbqx8JPL+ayQ02auqmBFMAPJ2H8bLoZy8tqQnqtXurJwsyhDoj yms/YAh4F4N1g== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:52 -0700 Subject: [PATCH RFC 22/25] PCI/LUO: Save PCI bus and host bridge states 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: <20250728-luo-pci-v1-22-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu In the LUO prepare phase, saves the PCI bus and host bridge states. For a PCI bus, save the domain and bus numbers. Save the bridge types. Save the upstream bus domain and bus numbers so we can verify the relationship in the later restoration phase. If the current bridge is a host bridge, save also the PCI bridge resource. This is not needed by other PCI bridges as the resource is already preserved by its associated struct pci_dev. Tested: - QEMU VM boot test, preserve device with pci-lu-stub Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 60 +++++++++++++++++++++++++++++++++++++++++---= ---- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index 7fda7e4d409adce6bf92ef7af1167f7bda302c7e..be22af7a2db3a9bb06d8e100603= a59f11b7fa5f8 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -20,9 +20,20 @@ static LIST_HEAD(preserved_buses); static LIST_HEAD(probe_devices); static LIST_HEAD(probe_buses); =20 +enum pci_bus_ser_bridge_type { + PCI_BUS_SER_NULL_BRIDGE, /* virtual bus */ + PCI_BUS_SER_PCI_HOST_BRIDGE, + PCI_BUS_SER_PCI_BRIDGE, +}; + struct pci_bus_ser { u16 domain; u8 number; + u16 parent_domain; + u8 parent_number; + enum pci_bus_ser_bridge_type bridge_type; + /* For a root bus, saves the host bridge PCI bridge resource */ + struct pci_resource_ser resource[PCI_BRIDGE_RESOURCE_NUM]; }; =20 struct pci_ser { @@ -162,6 +173,16 @@ static int pci_get_device_path(struct pci_dev *pdev) return (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev); } =20 +static void save_device_resource(struct pci_resource_ser *dest, + struct resource *src) +{ + strscpy((char *)dest->name, src->name, sizeof(dest->name)); + dest->start =3D src->start; + dest->end =3D src->end; + dest->flags =3D src->flags; + dest->desc =3D src->desc; +} + static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s) { struct pci_dev *pdev =3D to_pci_dev(dev); @@ -205,13 +226,7 @@ static int pci_save_device_state(struct device *dev, s= truct pci_dev_ser *s) (strlen(pdev->resource[i].name) =3D=3D 0)) continue; =20 - s->resource[i].start =3D pdev->resource[i].start; - s->resource[i].end =3D pdev->resource[i].end; - s->resource[i].flags =3D pdev->resource[i].flags; - s->resource[i].desc =3D pdev->resource[i].desc; - - strscpy((char *)s->resource[i].name, pci_name(pdev), - sizeof(s->resource[i].name)); + save_device_resource(s->resource + i, pdev->resource + i); } =20 return 0; @@ -219,8 +234,37 @@ static int pci_save_device_state(struct device *dev, s= truct pci_dev_ser *s) =20 static void pci_save_bus_state(struct pci_bus *bus, struct pci_bus_ser *s) { - s->number =3D bus->number; + int i; + s->domain =3D pci_domain_nr(bus); + s->number =3D bus->number; + if (bus->parent) { + s->parent_domain =3D pci_domain_nr(bus->parent); + s->parent_number =3D bus->parent->number; + } + + /* This bus is a virtual bus if no physical bridge is being referred. */ + if (!bus->bridge) { + s->bridge_type =3D PCI_BUS_SER_NULL_BRIDGE; + return; + } + + if (!pci_is_root_bus(bus)) { + s->bridge_type =3D PCI_BUS_SER_PCI_BRIDGE; + return; + } + + /* This bridge is a PCI host bridge. Saves its resource. */ + for (i =3D 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { + /* This resource region is not claimed, skip. */ + if ((bus->resource[i] =3D=3D NULL) || + (bus->resource[i]->name =3D=3D NULL) || + (strlen(bus->resource[i]->name) =3D=3D 0)) + continue; + + save_device_resource(s->resource + i, bus->resource[i]); + } + s->bridge_type =3D PCI_BUS_SER_PCI_HOST_BRIDGE; } =20 static int pci_call_prepare(struct pci_ser *pci_state, --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:29 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 0BE132652BD; Mon, 28 Jul 2025 08:25:02 +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=1753691103; cv=none; b=nP61zWO7Xkr5IzTiNAFdUwbPLbwWAAhTXwXQjaCGTYW7sz/A7GvWXxAM9y7NXbzJF5uVhaHeAmqSuNFBqlqkMrH5WADxG21H/cbmoY7C/lhGdzxgKHgzSc9Xx5jg40WSiNME2GWsZJwA+3YUdkJ56WL+PBSrlopuR1JRotxHZ+Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691103; c=relaxed/simple; bh=LRhBZ85o77YrbZBA8G2KDhGK7PyUYIQNe7/MgVZxEpA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Rf5gQHi4+1HSYQvkAN/hqeF1LG5902aVPVuVWX1BDA9AaHWyhG9s7QsV2q6DhjRXSG83PHeRmQDrV7Xjmf84Tyk20QZ2nHLUC5JTa3Gt2N07lqNGlPHGJZA6hXByvIjiIY71wtK/sBf9+iInL/SPSWu9Chu4z500v7xh2uAaLVY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Um6HWGYn; 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="Um6HWGYn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 22398C4CEFA; Mon, 28 Jul 2025 08:25:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691102; bh=LRhBZ85o77YrbZBA8G2KDhGK7PyUYIQNe7/MgVZxEpA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Um6HWGYnXC8m4qLyKp7uH5NnjfodshSZ1YA039nEFBDiIY4Tk/Aqb1RutElNqP7pl wcgL0XKZXdjKYWFuUxW5nD22mqkqL6UFevyrqbegG36Ais0CJcjAcJdkdJAbqXNMow LDs97p8KNXsL4mXaT9jZnFy8MTeuPwSjekKt/7BY6WWG4t/VJeJifVGSDBapcSy25u Uj6+AGiI8ucrIApbUhk15Nfc3Uo1r3gbDWaAHJbd3yiwmNx6uN8r8cpD9t/f7Cq5Hy PJR6H1BoiGkR9a+ARPWz3DfNtIO5aUH4u00RbLNY4Ic4lLKJTF6DszeiEqs9x4w3x+ WRXYQp0jCfGnw== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:53 -0700 Subject: [PATCH RFC 23/25] PCI/LUO: Check the PCI bus state after restoration 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: <20250728-luo-pci-v1-23-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: Jason Miu After the LUO reboot, check if the bus topology assoicated with the current PCI device is matching with the bus states saved in LUO. We like to verify: - The domain and bus numbers. - The parent bus domain and number. - The bus type, which can be PCI-PCI bridge, host bridge, or virtual bus. - PCI bridge resource of host bridge, as different from PCI-PCI bridge which the resource is restorated from the PCI bridge device, we check if the host bridge resource is changed from the last boot. Tested: - QEMU VM liveupdate boot test with pci-lu-stub Signed-off-by: Chris Li --- drivers/pci/liveupdate.c | 123 ++++++++++++++++++++++++++++++++++++++++++-= ---- 1 file changed, 110 insertions(+), 13 deletions(-) diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c index be22af7a2db3a9bb06d8e100603a59f11b7fa5f8..739de5f655dba04024c9cf8db2b= f6ea5e136cf5f 100644 --- a/drivers/pci/liveupdate.c +++ b/drivers/pci/liveupdate.c @@ -43,6 +43,45 @@ struct pci_ser { /* struct pci_bus_ser buses[] */ }; =20 +static struct pci_bus_ser *get_saved_pci_bus_state(struct pci_ser *state, + u16 domain, u8 number) +{ + int i; + struct pci_bus_ser *bus_state =3D + (struct pci_bus_ser *)(state->devs + state->dev_count); + + for (i =3D 0; i < state->bus_count; i++, bus_state++) { + if (bus_state->domain =3D=3D domain && + bus_state->number =3D=3D number) + return bus_state; + } + + return NULL; +} + +static enum pci_bus_ser_bridge_type get_bus_ser_bridge_type(struct pci_bus= *bus) +{ + /* This bus is a virtual bus if no physical bridge is being referred. */ + if (!bus->bridge) + return PCI_BUS_SER_NULL_BRIDGE; + + return pci_is_root_bus(bus) ? + PCI_BUS_SER_PCI_HOST_BRIDGE : PCI_BUS_SER_PCI_BRIDGE; +} + +static char *bus_ser_bridge_type_to_string(enum pci_bus_ser_bridge_type bt) +{ + switch (bt) { + case PCI_BUS_SER_NULL_BRIDGE: + return "PCI_BUS_SER_NULL_BRIDGE"; + case PCI_BUS_SER_PCI_BRIDGE: + return "PCI_BUS_SER_PCI_BRIDGE"; + case PCI_BUS_SER_PCI_HOST_BRIDGE: + return "PCI_BUS_SER_PCI_HOST_BRIDGE"; + } + return "PCI_BUS_SER_INVALID"; +} + static void stack_push_buses(struct list_head *stack, struct list_head *bu= ses) { struct pci_bus *bus; @@ -183,6 +222,71 @@ static void save_device_resource(struct pci_resource_s= er *dest, dest->desc =3D src->desc; } =20 +static void check_saved_bus_state(struct pci_dev *dev, struct pci_ser *pci= _state) +{ + int i; + const struct resource *res; + const struct pci_resource_ser *saved_res; + const struct pci_bus_ser *bus_state =3D + get_saved_pci_bus_state(pci_state, + pci_domain_nr(dev->bus), + dev->bus->number); + struct pci_bus *bus =3D dev->bus; + + if (!bus_state) { + panic("The bus of PCI device %s was not preserved by Liveupdate", + pci_name(dev)); + } + + if (get_bus_ser_bridge_type(bus) !=3D bus_state->bridge_type) { + panic("The bus (%04x:%02x) bridge type (%s) of PCI device (%s) is change= d. " + "Liveupdate preserved %s", + pci_domain_nr(bus), bus->number, + bus_ser_bridge_type_to_string(get_bus_ser_bridge_type(bus)), + pci_name(dev), + bus_ser_bridge_type_to_string(bus_state->bridge_type)); + } + + if (bus->parent) { + if (pci_domain_nr(bus->parent) !=3D bus_state->parent_domain || + bus->parent->number !=3D bus_state->parent_number) { + panic("The parent bus (%04x:%02x) of PCI device (%s) is changed. " + "Liveupdate preserved %04x:%02x", + pci_domain_nr(bus->parent), bus->parent->number, + pci_name(dev), + bus_state->parent_domain, bus_state->parent_number); + } + + /* Checkings of PCI-PCI bridge and Virtual bus ends. */ + return; + } + + /* This is a host bridge device */ + for (i =3D 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { + + res =3D bus->resource[i]; + if (res =3D=3D NULL || + res->name =3D=3D NULL || + strlen(res->name) =3D=3D 0) + continue; + + /* check its PCI bridge resource */ + saved_res =3D &bus_state->resource[i]; + if (res->start !=3D saved_res->start || + res->end !=3D saved_res->end || + res->flags !=3D saved_res->flags || + res->desc !=3D saved_res->desc || + strncmp(res->name, saved_res->name, sizeof(saved_res->name)) !=3D 0)= { + panic("Host bridge resource %pr is changed. " + "Liveupdate preserved " + "[mem 0x%016llx-0x%016llx flags 0x%016llx desc 0x%016llx name %s]= ", + res, + saved_res->start, saved_res->end, + saved_res->flags, saved_res->desc, saved_res->name); + } + } +} + static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s) { struct pci_dev *pdev =3D to_pci_dev(dev); @@ -238,22 +342,13 @@ static void pci_save_bus_state(struct pci_bus *bus, s= truct pci_bus_ser *s) =20 s->domain =3D pci_domain_nr(bus); s->number =3D bus->number; + s->bridge_type =3D get_bus_ser_bridge_type(bus); + if (bus->parent) { s->parent_domain =3D pci_domain_nr(bus->parent); s->parent_number =3D bus->parent->number; } =20 - /* This bus is a virtual bus if no physical bridge is being referred. */ - if (!bus->bridge) { - s->bridge_type =3D PCI_BUS_SER_NULL_BRIDGE; - return; - } - - if (!pci_is_root_bus(bus)) { - s->bridge_type =3D PCI_BUS_SER_PCI_BRIDGE; - return; - } - /* This bridge is a PCI host bridge. Saves its resource. */ for (i =3D 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { /* This resource region is not claimed, skip. */ @@ -264,7 +359,6 @@ static void pci_save_bus_state(struct pci_bus *bus, str= uct pci_bus_ser *s) =20 save_device_resource(s->resource + i, bus->resource[i]); } - s->bridge_type =3D PCI_BUS_SER_PCI_HOST_BRIDGE; } =20 static int pci_call_prepare(struct pci_ser *pci_state, @@ -531,8 +625,11 @@ void pci_liveupdate_restore(struct pci_dev *dev) s =3D pci_state->devs; end =3D s + pci_state->dev_count; for (; s < end; s++) - if (s->path =3D=3D path) + if (s->path =3D=3D path) { + /* If the bus state checking fails, kernel panics */ + check_saved_bus_state(dev, pci_state); return pci_dev_do_restore(dev, s); + } } =20 int pci_liveupdate_get_driver_data(struct pci_dev *pdev, u64 *data) --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:29 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 73E0F26563F; Mon, 28 Jul 2025 08:25:03 +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=1753691103; cv=none; b=h/m3PqtB3zZsw6IxnMxA9mJhgxtz/SCqdJAk05vIxWnLJwGqaBa8vwHuF2cxdRWTe/9M9d7QXhC1JEjfB0IZmNOBYbrg/HiY0OvNhVEtIKV1n04+uQVxDrCZH3imF+wdFi3PjaoLkF6l4bdKtFLDEcL5LBx247yzUl+gYryVdDY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691103; c=relaxed/simple; bh=sv3oWelMOQyMoFDHjlmqzXOzxi5DPs/X9scDkrB3vWs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sAhvUHb5jHwt3EbTQhKt1DnzUHgtq4ec9XrtmoQrYl1Vkqs2G6KhgELA3f2gEW2KU1EANRXmvM/aZB0Yzimm/lxygAaUkvs5SAluj15I2MVxKGp195itfb7D4k652aw4dzn5y0tUj+JRu6t4Twc5uCedy06/2HpJzxzwmxI3nRU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kDlIrPep; 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="kDlIrPep" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4DD8C4CEF7; Mon, 28 Jul 2025 08:25:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691103; bh=sv3oWelMOQyMoFDHjlmqzXOzxi5DPs/X9scDkrB3vWs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kDlIrPepMU5jvgXNzzNAsZ1eSZzHIUMm5Bef1gYbocK8QkaVlM/6jXkoxRH76HcC8 clW8mIExNRGa6/2qp5cux+WfNZ5N701CPHAru6hYhYhyRUzP2ogkL7n4+JhNU5URgZ +P2lkA553nlaGy4x92Buyx6I8uRZd9pnPRkuCxMfHeKT4iJYFUok0R//+kYvwKt2kV ToP/J/ksWQO0wS0+eh8swQxQ/I0GgusKYA6Fsce3WqmN3iyDH/8fHX8uMnu8AaxycQ 4h0Gu/kWonmoixpxUQq1XX7ugpXSEqpaCzCEb/izTzlnOBPJW/ZwnBZGwONM4Mus23 oeABf1ub7eKBA== From: Chris Li Date: Mon, 28 Jul 2025 01:24:54 -0700 Subject: [PATCH RFC 24/25] PCI: pci-lu-pf-stub: Add a PF stub driver for Live Update testing 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: <20250728-luo-pci-v1-24-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 The pci-lu-stub driver will always request device in probe(). However if the PF driver might be add the liveupdate device list due to "depended" bit rather than "requested" bit. Create the pci-lu-stub-pf driver base on the pci-lu-stuf driver, it will not request the device at probe(). For PF device, also restore the number of VFs at probe(). Signed-off-by: Chris Li --- drivers/pci/pci-lu-stub.c | 85 +++++++++++++++++++++++++++++++++++++++++++= +--- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci-lu-stub.c b/drivers/pci/pci-lu-stub.c index ea8142dcb250d31cbf817df957157bc4ec3a876d..ff6230102b83ff3ad646c23b79d= 4e1b6de58b43f 100644 --- a/drivers/pci/pci-lu-stub.c +++ b/drivers/pci/pci-lu-stub.c @@ -5,6 +5,8 @@ #include #include =20 +#include "pci.h" + struct pci_lu_stub_ser { u16 dev_id; } __packed; @@ -32,15 +34,47 @@ static int validate_folio(struct pci_dev *dev, struct f= olio *folio) return 0; } =20 -static int pci_lu_stub_probe(struct pci_dev *dev, const struct pci_device_= id *id) +static bool is_pf_driver(struct pci_dev *dev) +{ + return pci_get_drvdata(dev); +} + +static int check_lu_flags(struct pci_dev *dev, bool is_pf) +{ + struct dev_liveupdate *lu =3D &dev->dev.lu; + bool expect_requested =3D !is_pf; + bool expect_depended =3D is_pf; + + if (lu->requested !=3D expect_requested) { + pci_err(dev, "Device requested bit %d not match expected %d\n", + lu->requested, expect_requested); + return -EINVAL; + } + + if (lu->depended !=3D expect_depended) { + pci_err(dev, "Device requested bit %d not match expected %d\n", + lu->depended, expect_depended); + return -EINVAL; + } + return 0; +} + +static int __pci_lu_stub_probe(struct pci_dev *dev, const struct pci_devic= e_id *id, + bool is_pf) { struct folio *folio; u64 data; int ret; + int vfs; + struct dev_liveupdate *lu =3D &dev->dev.lu; + struct pci_dev_ser *s; =20 + pci_set_drvdata(dev, (void *)(intptr_t) is_pf); if (liveupdate_state_normal()) { - pci_info(dev, "Marking device as liveupdate requested\n"); - dev->dev.lu.requested =3D 1; + if (!is_pf) { + pci_info(dev, "Marking device as liveupdate requested\n"); + lu->requested =3D 1; + } return 0; } =20 @@ -49,6 +83,10 @@ static int pci_lu_stub_probe(struct pci_dev *dev, const = struct pci_device_id *id return -EOPNOTSUPP; } =20 + ret =3D check_lu_flags(dev, is_pf); + if (ret) + return ret; + ret =3D pci_liveupdate_get_driver_data(dev, &data); if (ret) { pci_err(dev, "Failed to get driver data for device (%d)\n", ret); @@ -63,7 +101,31 @@ static int pci_lu_stub_probe(struct pci_dev *dev, const= struct pci_device_id *id return -ENOENT; } =20 - return validate_folio(dev, folio); + ret =3D validate_folio(dev, folio); + if (ret) + return ret; + + s =3D lu->dev_state; + vfs =3D s->num_vfs; + if (dev->is_physfn && vfs) { + ret =3D pci_sriov_configure_simple(dev, vfs); + if (vfs !=3D ret) { + pci_err(dev, "Failed to restore num VFs %d got %d\n", + vfs, ret); + return (ret < 0) ? ret : -EAGAIN; + } + } + return 0; +} + +static int pci_lu_stub_probe(struct pci_dev *dev, const struct pci_device_= id *id) +{ + return __pci_lu_stub_probe(dev, id, false); +} + +static int pci_lu_stub_pf_probe(struct pci_dev *dev, const struct pci_devi= ce_id *id) +{ + return __pci_lu_stub_probe(dev, id, true); } =20 static void pci_lu_stub_remove(struct pci_dev *dev) @@ -74,10 +136,15 @@ static void pci_lu_stub_remove(struct pci_dev *dev) =20 static int pci_lu_stub_prepare(struct device *dev, u64 *data) { + struct pci_dev *pdev =3D to_pci_dev(dev); struct pci_lu_stub_ser *ser; struct folio *folio; int ret; =20 + ret =3D check_lu_flags(pdev, is_pf_driver(pdev)); + if (ret) + return ret; + folio =3D folio_alloc(GFP_KERNEL | __GFP_ZERO, get_order(sizeof(*ser))); if (!folio) return -ENOMEM; @@ -135,5 +202,15 @@ static struct pci_driver pci_lu_stub_driver =3D { .driver.lu =3D &liveupdate_ops, }; =20 +static struct pci_driver pci_lu_stub_pf_driver =3D { + .name =3D "pci-lu-stub-pf", + .id_table =3D pci_lu_stub_id_table, + .probe =3D pci_lu_stub_pf_probe, + .remove =3D pci_lu_stub_remove, + .sriov_configure =3D pci_sriov_configure_simple, + .driver.lu =3D &liveupdate_ops, +}; + module_pci_driver(pci_lu_stub_driver); +module_pci_driver(pci_lu_stub_pf_driver); MODULE_LICENSE("GPL"); --=20 2.50.1.487.gc89ff58d15-goog From nobody Sun Oct 5 23:38:29 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 1D5C2266581; Mon, 28 Jul 2025 08:25:04 +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=1753691104; cv=none; b=WdCvvAgMo2NEWx8IwVUYFFK9J5h+b3pz8oL7FMJGdBDF8FxeZNnzJ7NYRYEPfEKqDPzCoZrXmdEvjI7uehfd43L//yExMgx2UvT4SakCtuN42y0NRlnP6xuOUcNShBTqELu8kSZ1h11BnkuIVt4TIXs6lWnFuJX3XMekAxIcZVI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753691104; c=relaxed/simple; bh=3vcIBee/NbsvEu80GFPtvaNBMX//h7roLKyHUYZ6P1c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UszJr5q479JR7mVqs7RNQ07kz4hp/+ZPxF7w/z9lp1cSNoakOhOkVXoChojImFU7BBYnSzjlm8bmGttW4r8uQZSGgOtAR5RSaBYDBkCBtVxHxPNOhhke5j7Mc8sLgTZ7wqp8L68MuKmKrLHkyglZLnhWRNfFb4TRIefXl542euk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mz29zVDR; 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="mz29zVDR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 71D1BC4CEE7; Mon, 28 Jul 2025 08:25:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753691104; bh=3vcIBee/NbsvEu80GFPtvaNBMX//h7roLKyHUYZ6P1c=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=mz29zVDRT8liVIK8t1ESFDAN2IRTTIukTWs75GH8BWCt2F2vEfkPVXkwiIe51qLbh w4WPMdfQfuBndExKcVFjpoOkMJCZG7WsfeluFPGwYZoDfT9j876pLJSbxji/1zNsd9 U5g9pgg4K/aNFsngP3s7pZI3fZixnZ5zIvA/a1T0P+XssZBoCasqk2oR7iFWTmyB8d TS0BZQEat3oRiMwx0T2J4cnlxNxTZBufZKYaxtQIuI07SlXsFD/qy73Y/aFzqufFh+ 60k8+YVDowgzieP3HJgDvNj1odFWrVwaLM9Lq0XobcypLlE7gdF17NNhc5pBYy8GNi ptC54BXElc+5A== From: chrisl@kernel.org Date: Mon, 28 Jul 2025 01:24:55 -0700 Subject: [PATCH RFC 25/25] PCI/LUO: Clean up PCI_SER_GET() 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: <20250728-luo-pci-v1-25-955b078dd653@kernel.org> References: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> In-Reply-To: <20250728-luo-pci-v1-0-955b078dd653@kernel.org> To: Bjorn Helgaas , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , Len Brown Cc: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, David Matlack , Pasha Tatashin , Jason Miu , Vipin Sharma , Saeed Mahameed , Adithya Jayachandran , Parav Pandit , William Tu , Mike Rapoport , Chris Li , Jason Gunthorpe , Leon Romanovsky X-Mailer: b4 0.14.2 From: David Matlack Refactor PCI_SER_GET() to be more readable by storing the pointer to struct pci_dev_ser in an intermediate variable and adding a helper function to_pci_dev_ser(). Change pci_lu_adopt() to return a boolean since it is only used to check if a device has preserved state. Opportunistically fix the formatting on the static inline prototype of pci_liveupdate_reclaim_resource() as well. No functional change intended. Signed-off-by: David Matlack Signed-off-by: Chris Li --- drivers/pci/pci.h | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 7af32edb128faef9c5e2665ca5055374f7fd30ea..d092cea96dc22cca5d3526c720c= fb8b330c47683 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1196,27 +1196,37 @@ static inline int pci_msix_write_tph_tag(struct pci= _dev *pdev, unsigned int inde PCI_CONF1_EXT_REG(reg)) =20 #ifdef CONFIG_LIVEUPDATE -#define PCI_SER_GET(__pci_dev, __var, __def) \ - (__pci_dev->dev.lu.dev_state) ? \ - ((struct pci_dev_ser *)__pci_dev->dev.lu.dev_state)->__var : __def - void pci_liveupdate_restore(struct pci_dev *dev); void pci_liveupdate_override_driver(struct pci_dev *dev); -static inline struct pci_dev_ser *pci_lu_adopt(struct pci_dev *dev) +static inline struct pci_dev_ser *to_pci_dev_ser(struct pci_dev *dev) +{ + return dev->dev.lu.dev_state; +} +static inline bool pci_lu_adopt(struct pci_dev *dev) { - return dev->dev.lu.requested ? dev->dev.lu.dev_state : NULL; + return dev->dev.lu.requested && to_pci_dev_ser(dev); } int pci_liveupdate_reclaim_resource(struct pci_dev *dev); #else -#define PCI_SER_GET(__dev, __var, __def) __def - static inline void pci_liveupdate_restore(struct pci_dev *dev) {} static inline void pci_liveupdate_override_driver(struct pci_dev *dev) {} -static inline struct pci_dev_ser *pci_lu_adopt(struct pci_dev *dev) +static inline struct pci_dev_ser *to_pci_dev_ser(struct pci_dev *dev) { return NULL; } -static inline int pci_liveupdate_reclaim_resource( - struct pci_dev *dev) { return -ENXIO; } +static inline bool pci_lu_adopt(struct pci_dev *dev) +{ + return false; +} +static inline int pci_liveupdate_reclaim_resource(struct pci_dev *dev) +{ + return -ENXIO; +} #endif + +#define PCI_SER_GET(__pci_dev, __field, __default) ({ \ + struct pci_dev_ser *__ser =3D to_pci_dev_ser(__pci_dev); \ + \ + __ser ? __ser->__field : __default; \ +}) #endif /* DRIVERS_PCI_H */ --=20 2.50.1.487.gc89ff58d15-goog