[PATCH 2/2] PCI: Replace pci_dev->broken_parity_status with accessors
From: Maurice Hieronymus <hidden>
Date: 2026-07-11 15:21:44
Also in:
linux-edac, linux-pci, linux-scsi, lkml, rust-for-linux, xen-devel
Subsystem:
edac-core, pci subsystem, the rest · Maintainers:
Borislav Petkov, Tony Luck, Bjorn Helgaas, Linus Torvalds
`broken_parity_status` shares a C bitfield word in `struct pci_dev` with many other bits. `broken_parity_status_store()` writes it from sysfs at any time without taking any lock, so userspace can make it race with every other writer of the same word, e.g. `pci_set_master()` from a runtime PM resume path, and updates of neighboring bits can be lost. Move the bit into the `flags` bitmap modified with atomic bitops, using the accessor pattern introduced by the previous commit. Signed-off-by: Maurice Hieronymus <redacted> --- drivers/edac/edac_pci_sysfs.c | 4 ++-- drivers/pci/pci-sysfs.c | 4 ++-- include/linux/pci.h | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index 9f437f648e4e..fadc61235f1f 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c@@ -554,7 +554,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) /* check the status reg for errors on boards NOT marked as broken * if broken, we cannot trust any of the status bits */ - if (status && !dev->broken_parity_status) { + if (status && !pci_dev_broken_parity_status(dev)) { if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) { edac_printk(KERN_CRIT, EDAC_PCI, "Signaled System Error on %s\n",
@@ -593,7 +593,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) /* check the secondary status reg for errors, * on NOT broken boards */ - if (status && !dev->broken_parity_status) { + if (status && !pci_dev_broken_parity_status(dev)) { if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) { edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " "Signaled System Error on %s\n",
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 5ec0b245a69b..5e094d1e23e3 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c@@ -80,7 +80,7 @@ static ssize_t broken_parity_status_show(struct device *dev, char *buf) { struct pci_dev *pdev = to_pci_dev(dev); - return sysfs_emit(buf, "%u\n", pdev->broken_parity_status); + return sysfs_emit(buf, "%u\n", pci_dev_broken_parity_status(pdev)); } static ssize_t broken_parity_status_store(struct device *dev,
@@ -93,7 +93,7 @@ static ssize_t broken_parity_status_store(struct device *dev, if (kstrtoul(buf, 0, &val) < 0) return -EINVAL; - pdev->broken_parity_status = !!val; + pci_dev_assign_broken_parity_status(pdev, val); return count; }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9964646bdd46..fdcd9b1b7371 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h@@ -347,10 +347,13 @@ struct rcec_ea; * bookkeeping state, maintained by pci_set_master(), * pci_clear_master() and pci_disable_device(); modifying it * does not itself change the hardware state. + * @PCI_DEV_FLAG_BROKEN_PARITY_STATUS: Device generates false positive + * parity errors; set via sysfs. * @PCI_DEV_FLAG_COUNT: Number of defined struct_pci_dev_flags. */ enum struct_pci_dev_flags { PCI_DEV_FLAG_BUSMASTER = 0, + PCI_DEV_FLAG_BROKEN_PARITY_STATUS = 1, PCI_DEV_FLAG_COUNT };
@@ -482,7 +485,6 @@ struct pci_dev { unsigned int no_msi:1; /* May not use MSI */ unsigned int block_cfg_access:1; /* Config space access blocked */ - unsigned int broken_parity_status:1; /* Generates false positive parity */ unsigned int irq_reroute_variant:2; /* Needs IRQ rerouting variant */ unsigned int msi_enabled:1; unsigned int msix_enabled:1;
@@ -626,6 +628,7 @@ static inline void pci_dev_assign_##accessor_name(struct pci_dev *pdev, bool val } __create_pci_dev_flag_accessors(busmaster, PCI_DEV_FLAG_BUSMASTER); +__create_pci_dev_flag_accessors(broken_parity_status, PCI_DEV_FLAG_BROKEN_PARITY_STATUS); #undef __create_pci_dev_flag_accessors
--
2.51.2