[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <630bdfc9fc9591178329983a308642dde68136e5.1759312886.git.epetron@amazon.de>
Date: Fri, 3 Oct 2025 09:00:48 +0000
From: Evangelos Petrongonas <epetron@...zon.de>
To: Bjorn Helgaas <bhelgaas@...gle.com>, Alex Williamson
<alex.williamson@...hat.com>, "Rafael J . Wysocki" <rafael@...nel.org>, "Len
Brown" <lenb@...nel.org>
CC: Evangelos Petrongonas <epetron@...zon.de>, Pasha Tatashin
<pasha.tatashin@...een.com>, David Matlack <dmatlack@...gle.com>, "Vipin
Sharma" <vipinsh@...gle.com>, Chris Li <chrisl@...nel.org>, Jason Miu
<jasonmiu@...gle.com>, Pratyush Yadav <pratyush@...nel.org>, "Stanislav
Spassov" <stanspas@...zon.de>, <linux-pci@...r.kernel.org>,
<linux-acpi@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
<nh-open-source@...zon.com>
Subject: [RFC PATCH 12/13] pci: pcsc: introduce persistence versioning
The cacheability of the devices can change, either because registers
need to be removed due to a bug / non-compliant device, or adding more
cacheable registers. The current version does not support the
concept of changing the `is_cacheable` bitmask and in order to do so,
the whole persistence mechanism needs to be disabled, change the bitmask
and reenable it again. This adds maintenance difficulty, as well as
negatively impacting the cache hit rate.
This commit adds a mechanism to handle those changes more efficiently.
A version number is identified and it is stored in the FDT during the
save process in the outgoing kernel. The incoming kernel, if compiled
with a different persistence version, will re-infer the cacheability of
all the saved devices, without touching the `is_cached` or the actual
configuration space saved data. This is safe as all access to the cache
are guarded by the `is_cacheable` bitmask. As a result changing the
cacheability will only change the differing registers, while the rest
of the cache will remain valid.
Signed-off-by: Evangelos Petrongonas <epetron@...zon.de>
---
drivers/pci/pcsc.c | 40 +++++++++++++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/pcsc.c b/drivers/pci/pcsc.c
index 0c4ae73744d6..8ff91ed24a37 100644
--- a/drivers/pci/pcsc.c
+++ b/drivers/pci/pcsc.c
@@ -23,6 +23,9 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
+/* PCSC persistent data version - increment when the cacheability is changed */
+#define PCSC_PERSISTENT_VERSION 1U
+
static bool pcsc_enabled;
static int __init pcsc_enabled_setup(char *str)
{
@@ -818,6 +821,7 @@ static int pcsc_kho_notifier(struct notifier_block *self, unsigned long cmd,
u32 eligible_count = 0;
u32 saved_count = 0;
u32 skipped_count = 0;
+ const u32 version = PCSC_PERSISTENT_VERSION;
switch (cmd) {
case KEXEC_KHO_ABORT:
@@ -853,8 +857,8 @@ static int pcsc_kho_notifier(struct notifier_block *self, unsigned long cmd,
/* Allocate FDT with size calculation (conservative estimates):
* - Per device: node_name(~20) + node_overhead(~12) + da_property(~20)
* = ~52 bytes, round up to 64 for alignment/margin
- * - Fixed overhead: header(40) + root_node(~40) + strings_table(~30)
- * + misc(~32) = ~144 bytes, round up to 256
+ * - Fixed overhead: header(40) + root_node(~48) + strings_table(~30)
+ * + misc(~32) = ~152 bytes, round up to 256
*/
fdt_size = PAGE_ALIGN((eligible_count * 64 + 256));
pcsc_kho_fdt_order = get_order(fdt_size);
@@ -892,6 +896,12 @@ static int pcsc_kho_notifier(struct notifier_block *self, unsigned long cmd,
goto error_cleanup;
}
+ err = fdt_property(fdt, "pv", &version, sizeof(version));
+ if (err) {
+ pr_err("PCSC: Failed to set version property: %d\n", err);
+ goto error_cleanup;
+ }
+
for_each_pci_dev(dev) {
int save_err = pcsc_kho_save_device(dev, fdt);
@@ -960,7 +970,7 @@ static struct notifier_block pcsc_kho_nb = {
};
static bool pcsc_kho_restore_device(struct pci_dev *dev, const void *fdt,
- int node)
+ int node, bool version_mismatch)
{
const struct pcsc_data *preserved_data;
const u64 *data_addr;
@@ -980,6 +990,9 @@ static bool pcsc_kho_restore_device(struct pci_dev *dev, const void *fdt,
dev->pcsc->cached_bitmask = dev->pcsc->data->cached_bitmask;
dev->pcsc->cfg_space = dev->pcsc->data->cfg_space;
+ if (version_mismatch)
+ infer_cacheability(dev);
+
return true;
}
@@ -987,9 +1000,12 @@ static bool pcsc_kho_check_restore(struct pci_dev *dev)
{
phys_addr_t fdt_phys;
const void *fdt;
- int node, err;
+ int node, err, len;
bool restored = false;
+ bool version_mismatch = false;
char node_name[32];
+ const u32 *version_ptr;
+ u32 saved_version;
#ifdef CONFIG_PCSC_STATS
ktime_t start_time, end_time;
u64 duration_ns;
@@ -1007,6 +1023,20 @@ static bool pcsc_kho_check_restore(struct pci_dev *dev)
return false;
}
+ version_ptr = fdt_getprop(fdt, 0, "pv", &len);
+ if (version_ptr && len == sizeof(*version_ptr)) {
+ saved_version = *version_ptr;
+ if (saved_version != PCSC_PERSISTENT_VERSION)
+ version_mismatch = true;
+
+ } else {
+ /* No version found, assume version 0 */
+ pci_info(
+ dev,
+ "PCSC: No version found in restored data. Re-infer Cacheability.\n");
+ version_mismatch = true;
+ }
+
#ifdef CONFIG_PCSC_STATS
start_time = ktime_get();
#endif
@@ -1017,7 +1047,7 @@ static bool pcsc_kho_check_restore(struct pci_dev *dev)
node = fdt_subnode_offset(fdt, 0, node_name);
if (node >= 0)
- restored = pcsc_kho_restore_device(dev, fdt, node);
+ restored = pcsc_kho_restore_device(dev, fdt, node, version_mismatch);
#ifdef CONFIG_PCSC_STATS
if (restored) {
--
2.47.3
Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christian Schlaeger
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597
Powered by blists - more mailing lists