From nobody Mon Oct 6 01:22:08 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