From dc76258d0132df1d831a5a29758bd448ca9c566e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Tue, 16 Jun 2026 16:31:30 +0000 Subject: [PATCH 1/9] PCI/sysfs: Fix out-of-bounds read in pci_write_legacy_io() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_write_legacy_io() loads 4 bytes from the kernfs write buffer regardless of how many bytes userspace wrote: if (count != 1 && count != 2 && count != 4) return -EINVAL; return pci_legacy_write(bus, off, *(u32 *)buf, count); kernfs_fop_write_iter() allocates the buffer with kmalloc(len + 1), so a 1-byte write to the legacy_io sysfs file allocates 2 bytes and the unconditional u32 load reads up to 2 bytes past the end of the allocation, which KASAN reports as a slab-out-of-bounds read. Similarly, a 2-byte write overreads by 1 byte. Thus, read only the number of bytes requested using get_unaligned_le16() and get_unaligned_le32() for the 2 and 4 byte cases, interpreting the buffer as little-endian to match the byte ordering of PCI I/O port space. The PowerPC implementation previously compensated for the generic code's native-endian 32-bit load by shifting the value into place for the 1 and 2 byte cases. The shifts were only correct on big-endian kernels. On little-endian PowerPC (POWER8 and later), they extracted the wrong bytes, so a 1-byte write wrote an out-of-bounds byte instead of the requested value. On big-endian, the native load also caused out_le16() and out_le32() to reverse the user's bytes on the wire for 2 and 4 byte writes. The little-endian helpers resolve both issues, so the shifts are removed. No changes are needed for the Alpha platform. The legacy_io file is root-only and exists only on Alpha and PowerPC, the two architectures that define HAVE_PCI_LEGACY. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260616163131.2763281-1-kwilczynski@kernel.org Signed-off-by: Krzysztof Wilczyński --- arch/powerpc/kernel/pci-common.c | 9 ++------- drivers/pci/pci-sysfs.c | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 3c4ca90e2ab7..4fc52c21fe5d 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -626,19 +626,14 @@ int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size) return -ENXIO; addr = hose->io_base_virt + port; - /* WARNING: The generic code is idiotic. It gets passed a pointer - * to what can be a 1, 2 or 4 byte quantity and always reads that - * as a u32, which means that we have to correct the location of - * the data read within those 32 bits for size 1 and 2 - */ switch(size) { case 1: - out_8(addr, val >> 24); + out_8(addr, val); return 1; case 2: if (port & 1) return -EINVAL; - out_le16(addr, val >> 16); + out_le16(addr, val); return 2; case 4: if (port & 3) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 5ec0b245a69b..2970ad502b78 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -913,12 +913,24 @@ static ssize_t pci_write_legacy_io(struct file *filp, struct kobject *kobj, char *buf, loff_t off, size_t count) { struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj)); + u32 val; - /* Only support 1, 2 or 4 byte accesses */ - if (count != 1 && count != 2 && count != 4) + /* Only support 1, 2 or 4 byte accesses. */ + switch (count) { + case 1: + val = *(u8 *)buf; + break; + case 2: + val = get_unaligned_le16(buf); + break; + case 4: + val = get_unaligned_le32(buf); + break; + default: return -EINVAL; + } - return pci_legacy_write(bus, off, *(u32 *)buf, count); + return pci_legacy_write(bus, off, val, count); } /** From 5b95212de6dcd7e0275cea7f894fe7226c7d9f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Tue, 16 Jun 2026 16:31:31 +0000 Subject: [PATCH 2/9] PCI/sysfs: Fix read byte order in pci_read_legacy_io() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_read_legacy_io() passes the sysfs buffer directly to pci_legacy_read(): return pci_legacy_read(bus, off, (u32 *)buf, count); The PowerPC implementation stores the result as a native-endian integer: *((u16 *)val) = in_le16(addr); On big-endian PowerPC this stores the bytes in the wrong order, so a 2-byte read of a device register returns different bytes than two 1-byte reads at the same addresses. The same applies to 4-byte reads. On little-endian the native byte order already matches PCI I/O port byte order, so the conversion is a no-op. Thus, let pci_legacy_read() store into a local u32 variable, then copy the I/O port value to the sysfs buffer using put_unaligned_le16() and put_unaligned_le32() for the 2 and 4 byte cases, converting from the native integer to little-endian byte order matching PCI I/O port space. No changes are needed for the Alpha platform. The legacy_io file is root-only and exists only on Alpha and PowerPC, the two architectures that define HAVE_PCI_LEGACY. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260616163131.2763281-2-kwilczynski@kernel.org Signed-off-by: Krzysztof Wilczyński --- drivers/pci/pci-sysfs.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 2970ad502b78..e985a3854f8d 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -888,12 +888,30 @@ static ssize_t pci_read_legacy_io(struct file *filp, struct kobject *kobj, char *buf, loff_t off, size_t count) { struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj)); + u32 val = 0; + int ret; /* Only support 1, 2 or 4 byte accesses */ if (count != 1 && count != 2 && count != 4) return -EINVAL; - return pci_legacy_read(bus, off, (u32 *)buf, count); + ret = pci_legacy_read(bus, off, &val, count); + if (ret < 0) + return ret; + + switch (count) { + case 1: + buf[0] = *(u8 *)&val; + break; + case 2: + put_unaligned_le16(*(u16 *)&val, buf); + break; + case 4: + put_unaligned_le32(val, buf); + break; + } + + return ret; } /** From 651fb94aaf245430590216d497fb8b02dd73d5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Mon, 6 Jul 2026 17:54:23 +0000 Subject: [PATCH 3/9] alpha/PCI: Fix I/O port accessor argument order in pci_legacy_write() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_legacy_write() in arch/alpha/kernel/pci-sysfs.c passes its arguments to outb(), outw() and outl() in the wrong order: outb(port, val); The Alpha I/O accessors in arch/alpha/include/asm/io.h take the value first and the port second: extern void outb(u8 b, unsigned long port); So the port number is written as data to the I/O address taken from the user-supplied value, and the intended write to the requested port never happens. The arguments have been reversed since the file was added, and the function returns the access size regardless, so the caller sees success while the requested port is left untouched. Fixes: 10a0ef39fbd1 ("PCI/alpha: pci sysfs resources") Signed-off-by: Krzysztof Wilczyński Signed-off-by: Bjorn Helgaas Tested-by: Magnus Lindholm Reviewed-by: Magnus Lindholm Acked-by: Magnus Lindholm Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260706175423.98305-1-kwilczynski@kernel.org --- arch/alpha/kernel/pci-sysfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index 94dbc470cd6c..7050f0f7fe3d 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -224,17 +224,17 @@ int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size) switch(size) { case 1: - outb(port, val); + outb(val, port); return 1; case 2: if (port & 1) return -EINVAL; - outw(port, val); + outw(val, port); return 2; case 4: if (port & 3) return -EINVAL; - outl(port, val); + outl(val, port); return 4; } return -EINVAL; From b14b2bab88d7099ab4447560cbe4b40945e5c069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Mon, 20 Jul 2026 20:43:56 +0000 Subject: [PATCH 4/9] PCI/sysfs: Avoid spurious runtime PM wakeup on config space accesses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the boundary checks in pci_read_config() and pci_write_config() reject only offsets beyond the effective configuration space size. An access at an offset exactly equal to that size passes the check, has its length clamped to zero, and then invokes pci_config_pm_runtime_get() and pci_config_pm_runtime_put() around transfer blocks that do nothing. This is a problem because pci_config_pm_runtime_get() synchronously resumes the upstream bridge through pm_runtime_get_sync() and resumes the device itself through pm_runtime_resume() when it is in D3cold, only for the handler to return zero immediately afterwards. Such a spurious wakeup wastes power and adds needless resume latency. The sysfs core already clamps accesses against the attribute size set through the bin_size() callback, which reports either 256 or 4096 bytes. As such, the affected accesses are reads at offset 64 (or 128 for CardBus devices) through files opened without CAP_SYS_ADMIN, and reads and writes at the exact configuration space size on devices where a quirk sets a non-standard size. Reject accesses at the boundary offset as well, so they return early before any runtime PM involvement, matching the procfs implementations in proc_bus_pci_read() and proc_bus_pci_write(). The value returned to userspace at these offsets remains zero, so the change is not visible to userspace. Signed-off-by: Krzysztof Wilczyński [bhelgaas: tweak commit log, order tags] Signed-off-by: Bjorn Helgaas Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260720204356.1501749-1-kwilczynski@kernel.org --- drivers/pci/pci-sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index e985a3854f8d..1be627913a9b 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -718,7 +718,7 @@ static ssize_t pci_read_config(struct file *filp, struct kobject *kobj, else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) size = 128; - if (off > size) + if (off >= size) return 0; if (off + count > size) { size -= off; @@ -799,7 +799,7 @@ static ssize_t pci_write_config(struct file *filp, struct kobject *kobj, add_taint(TAINT_USER, LOCKDEP_STILL_OK); } - if (off > dev->cfg_size) + if (off >= dev->cfg_size) return 0; if (off + count > dev->cfg_size) { size = dev->cfg_size - off; From bad94d3d18c600cfe2c24c17b1825db4b8795e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Mon, 20 Jul 2026 20:46:24 +0000 Subject: [PATCH 5/9] PCI/sysfs: Return -EINVAL for unsupported I/O BAR mmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, mmap() of a resourceN file for an I/O BAR fails with -ENODEV on architectures where arch_can_pci_mmap_io() is 0, such as x86, because the attribute has no mmap callback there and the error comes from the generic kernfs dispatch. This is a side effect of commit e854d8b2a82e ("PCI: Add arch_can_pci_mmap_io() on architectures which can mmap() I/O space"), which removed the mmap callback from the I/O resource attribute on these architectures. Previously the request reached the architecture mmap code and failed with -EINVAL, and the same commit deliberately kept -EINVAL for the identical operation on the procfs interface, so the two PCI userspace interfaces have disagreed ever since. Add a pci_mmap_resource_io_unsupported() callback that returns -EINVAL and use it as the mmap handler of the I/O resource attribute when arch_can_pci_mmap_io() is 0, so the failure is produced deliberately by PCI code, consistent with the procfs interface and with the behaviour before e854d8b2a82e. Architectures where arch_can_pci_mmap_io() is non-zero keep the real pci_mmap_resource_uc() handler and are unaffected. The mmap() fails either way. Only the reported error changes from -ENODEV to -EINVAL. Fixes: e854d8b2a82e ("PCI: Add arch_can_pci_mmap_io() on architectures which can mmap() I/O space") Signed-off-by: Krzysztof Wilczyński Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260720204624.1503794-1-kwilczynski@kernel.org --- drivers/pci/pci-sysfs.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 1be627913a9b..eab14be6fcf1 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1274,7 +1274,16 @@ static loff_t pci_llseek_resource(struct file *filep, .llseek = pci_llseek_resource, \ .mmap = pci_mmap_resource_uc, #else -# define __PCI_RESOURCE_IO_MMAP_ATTRS +static int pci_mmap_resource_io_unsupported(struct file *filp, + struct kobject *kobj, + const struct bin_attribute *attr, + struct vm_area_struct *vma) +{ + return -EINVAL; +} + +# define __PCI_RESOURCE_IO_MMAP_ATTRS \ + .mmap = pci_mmap_resource_io_unsupported, #endif #define pci_dev_resource_io_attr(_bar) \ From 747b9bbbbdfdee51aee2456388f9b94b5086de4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Mon, 20 Jul 2026 21:15:41 +0000 Subject: [PATCH 6/9] PCI/sysfs: Add lockdown checks to legacy I/O and memory handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the legacy I/O and memory sysfs handlers do not check security_locked_down(LOCKDOWN_PCI_ACCESS), leaving the legacy_io and legacy_mem files unprotected when the kernel is locked down. Commit eb627e17727e ("PCI: Lock down BAR access when the kernel is locked down") added the check to pci_write_config(), pci_mmap_resource(), and pci_write_resource_io() to prevent userspace from programming DMA-capable hardware that could be used to modify kernel code, but did not cover the legacy handlers. As a result, root can still write arbitrary I/O ports and map the legacy I/O and memory spaces while the kernel is locked down, which is the same capability the lockdown is meant to remove. Add the same check to pci_write_legacy_io(), pci_mmap_legacy_mem(), and pci_mmap_legacy_io(). These generic handlers cover both architectures that define HAVE_PCI_LEGACY (such as Alpha and PowerPC). Fixes: eb627e17727e ("PCI: Lock down BAR access when the kernel is locked down") Signed-off-by: Krzysztof Wilczyński [bhelgaas: add Link] Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260720211541.1509744-1-kwilczynski@kernel.org --- drivers/pci/pci-sysfs.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index eab14be6fcf1..6b016792e0ad 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -967,6 +967,11 @@ static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj, struct vm_area_struct *vma) { struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj)); + int ret; + + ret = security_locked_down(LOCKDOWN_PCI_ACCESS); + if (ret) + return ret; return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem); } @@ -987,6 +992,11 @@ static int pci_mmap_legacy_io(struct file *filp, struct kobject *kobj, struct vm_area_struct *vma) { struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj)); + int ret; + + ret = security_locked_down(LOCKDOWN_PCI_ACCESS); + if (ret) + return ret; return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io); } @@ -1003,6 +1013,11 @@ static inline umode_t __pci_legacy_is_visible(struct kobject *kobj, bool sparse) { struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj)); + int ret; + + ret = security_locked_down(LOCKDOWN_PCI_ACCESS); + if (ret) + return ret; if (pci_legacy_has_sparse(bus, type) != sparse) return 0; From 7823291ac45cd1f7fb7d975d4529cca269faf5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Tue, 21 Jul 2026 02:04:24 +0000 Subject: [PATCH 7/9] PCI/sysfs: Add pci_ prefix to static PCI resource attribute names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the static binary attributes for the PCI resource files are generated with the names dev_resource_io_attr, dev_resource_uc_attr and dev_resource_wc_attr. The macros that generate these attributes and the arrays that collect them already carry the pci_ prefix, as do the sibling legacy I/O and memory attributes, such as pci_legacy_io_attr. Only the generated variable names lack it. Rename the generated variables to pci_dev_resource_io_attr, pci_dev_resource_uc_attr and pci_dev_resource_wc_attr, and update the attribute pointer arrays to match. While at it, re-align the continuation backslashes in the resource attribute macros to match. No functional changes intended. Signed-off-by: Krzysztof Wilczyński [bhelgaas: shorten pci_dev_resource##_bar##_wc_attr to fit in 80 columns] Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260721020427.1541197-2-kwilczynski@kernel.org --- drivers/pci/pci-sysfs.c | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 6b016792e0ad..91f8f15beaa5 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1284,9 +1284,9 @@ static loff_t pci_llseek_resource(struct file *filep, * attribute, it's not going to work, so override it as well. */ #if arch_can_pci_mmap_io() -# define __PCI_RESOURCE_IO_MMAP_ATTRS \ - .f_mapping = iomem_get_mapping, \ - .llseek = pci_llseek_resource, \ +# define __PCI_RESOURCE_IO_MMAP_ATTRS \ + .f_mapping = iomem_get_mapping, \ + .llseek = pci_llseek_resource, \ .mmap = pci_mmap_resource_uc, #else static int pci_mmap_resource_io_unsupported(struct file *filp, @@ -1302,7 +1302,7 @@ static int pci_mmap_resource_io_unsupported(struct file *filp, #endif #define pci_dev_resource_io_attr(_bar) \ -static const struct bin_attribute dev_resource##_bar##_io_attr = { \ +static const struct bin_attribute pci_dev_resource##_bar##_io_attr = { \ .attr = { .name = "resource" __stringify(_bar), .mode = 0600 }, \ .private = (void *)(unsigned long)(_bar), \ .read = pci_read_resource, \ @@ -1311,7 +1311,7 @@ static const struct bin_attribute dev_resource##_bar##_io_attr = { \ } #define pci_dev_resource_uc_attr(_bar) \ -static const struct bin_attribute dev_resource##_bar##_uc_attr = { \ +static const struct bin_attribute pci_dev_resource##_bar##_uc_attr = { \ .attr = { .name = "resource" __stringify(_bar), .mode = 0600 }, \ .private = (void *)(unsigned long)(_bar), \ .f_mapping = iomem_get_mapping, \ @@ -1319,8 +1319,8 @@ static const struct bin_attribute dev_resource##_bar##_uc_attr = { \ .mmap = pci_mmap_resource_uc, \ } -#define pci_dev_resource_wc_attr(_bar) \ -static const struct bin_attribute dev_resource##_bar##_wc_attr = { \ +#define pci_dev_resource_wc_attr(_bar) \ +static const struct bin_attribute pci_dev_resource##_bar##_wc_attr = { \ .attr = { .name = "resource" __stringify(_bar) "_wc", .mode = 0600 }, \ .private = (void *)(unsigned long)(_bar), \ .f_mapping = iomem_get_mapping, \ @@ -1406,32 +1406,32 @@ pci_dev_resource_wc_attr(4); pci_dev_resource_wc_attr(5); static const struct bin_attribute *const pci_dev_resource_io_attrs[] = { - &dev_resource0_io_attr, - &dev_resource1_io_attr, - &dev_resource2_io_attr, - &dev_resource3_io_attr, - &dev_resource4_io_attr, - &dev_resource5_io_attr, + &pci_dev_resource0_io_attr, + &pci_dev_resource1_io_attr, + &pci_dev_resource2_io_attr, + &pci_dev_resource3_io_attr, + &pci_dev_resource4_io_attr, + &pci_dev_resource5_io_attr, NULL, }; static const struct bin_attribute *const pci_dev_resource_uc_attrs[] = { - &dev_resource0_uc_attr, - &dev_resource1_uc_attr, - &dev_resource2_uc_attr, - &dev_resource3_uc_attr, - &dev_resource4_uc_attr, - &dev_resource5_uc_attr, + &pci_dev_resource0_uc_attr, + &pci_dev_resource1_uc_attr, + &pci_dev_resource2_uc_attr, + &pci_dev_resource3_uc_attr, + &pci_dev_resource4_uc_attr, + &pci_dev_resource5_uc_attr, NULL, }; static const struct bin_attribute *const pci_dev_resource_wc_attrs[] = { - &dev_resource0_wc_attr, - &dev_resource1_wc_attr, - &dev_resource2_wc_attr, - &dev_resource3_wc_attr, - &dev_resource4_wc_attr, - &dev_resource5_wc_attr, + &pci_dev_resource0_wc_attr, + &pci_dev_resource1_wc_attr, + &pci_dev_resource2_wc_attr, + &pci_dev_resource3_wc_attr, + &pci_dev_resource4_wc_attr, + &pci_dev_resource5_wc_attr, NULL, }; From ee2ca844570a7aa6eba48cea29da24455a5f0288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Tue, 21 Jul 2026 02:04:25 +0000 Subject: [PATCH 8/9] alpha/PCI: Make the suffix the first __pci_dev_resource_attr() parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the __pci_dev_resource_attr() helper macro takes the attribute name suffix as its third parameter, even though the suffix is what distinguishes the three attribute variants built on top of it. Additionally, the pci_dev_resource_attr() wrapper passes an empty suffix, and with the suffix placed in the middle of the parameter list its invocation contains two consecutive commas, which checkpatch.pl highlights, as follows: ERROR: space required after that ',' (ctx:VxO) Move the suffix to the front so that the variant selector comes first and the empty argument follows the opening parenthesis, which checkpatch.pl does not complain about. This also matches the parameter order used by the PCI legacy I/O and memory attribute macros introduced in a subsequent change. No functional changes intended. Signed-off-by: Krzysztof Wilczyński Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260721020427.1541197-3-kwilczynski@kernel.org --- arch/alpha/kernel/pci-sysfs.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index 7050f0f7fe3d..67f9822f7626 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -102,25 +102,25 @@ static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj, return pci_mmap_resource(kobj, attr, vma, 0); } -#define __pci_dev_resource_attr(_bar, _name, _suffix, _mmap) \ -static const struct bin_attribute \ -pci_dev_resource##_bar##_suffix##_attr = { \ - .attr = { .name = __stringify(_name), .mode = 0600 }, \ - .private = (void *)(unsigned long)(_bar), \ - .mmap = (_mmap), \ +#define __pci_dev_resource_attr(_suffix, _bar, _name, _mmap) \ +static const struct bin_attribute \ +pci_dev_resource##_bar##_suffix##_attr = { \ + .attr = { .name = __stringify(_name), .mode = 0600 }, \ + .private = (void *)(unsigned long)(_bar), \ + .mmap = (_mmap), \ } -#define pci_dev_resource_attr(_bar) \ - __pci_dev_resource_attr(_bar, resource##_bar,, \ - pci_mmap_resource_dense) +#define pci_dev_resource_attr(_bar) \ + __pci_dev_resource_attr(, _bar, resource##_bar, \ + pci_mmap_resource_dense) #define pci_dev_resource_sparse_attr(_bar) \ - __pci_dev_resource_attr(_bar, resource##_bar##_sparse, _sparse, \ - pci_mmap_resource_sparse) + __pci_dev_resource_attr(_sparse, _bar, resource##_bar##_sparse, \ + pci_mmap_resource_sparse) #define pci_dev_resource_dense_attr(_bar) \ - __pci_dev_resource_attr(_bar, resource##_bar##_dense, _dense, \ - pci_mmap_resource_dense) + __pci_dev_resource_attr(_dense, _bar, resource##_bar##_dense, \ + pci_mmap_resource_dense) static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num) { From 1b7c9855bb686f271f4e356cc01dab788957c5fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Tue, 21 Jul 2026 02:04:26 +0000 Subject: [PATCH 9/9] PCI/sysfs: Add legacy I/O and memory attribute macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the static binary attributes for the PCI legacy I/O port and ISA memory space files (legacy_io, legacy_io_sparse, legacy_mem and legacy_mem_sparse) are open-coded, with each definition repeating the same set of properties and callbacks. Add two macros for declaring such attributes: - pci_legacy_resource_io_attr(), for legacy I/O port space (read/write) - pci_legacy_resource_mem_attr(), for legacy memory space (mmap) Each macro takes the fixed attribute size as a parameter. Then replace the open-coded definitions with the newly added macros. No functional changes intended. Signed-off-by: Krzysztof Wilczyński [bhelgaas: shorten macros to fit in 80 columns] Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260721020427.1541197-4-kwilczynski@kernel.org --- drivers/pci/pci-sysfs.c | 59 +++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 91f8f15beaa5..204980026f97 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -871,6 +871,27 @@ static const struct attribute_group pci_dev_config_attr_group = { }; #ifdef HAVE_PCI_LEGACY + +#define pci_legacy_resource_io_attr(_suffix, _size) \ +static const struct bin_attribute pci_legacy_io##_suffix##_attr = { \ + .attr = { .name = "legacy_io" __stringify(_suffix), .mode = 0600 }, \ + .size = (_size), \ + .read = pci_read_legacy_io, \ + .write = pci_write_legacy_io, \ + .f_mapping = iomem_get_mapping, \ + .llseek = pci_llseek_resource_legacy, \ + .mmap = pci_mmap_legacy_io, \ +} + +#define pci_legacy_resource_mem_attr(_suffix, _size) \ +static const struct bin_attribute pci_legacy_mem##_suffix##_attr = { \ + .attr = { .name = "legacy_mem" __stringify(_suffix), .mode = 0600 }, \ + .size = (_size), \ + .f_mapping = iomem_get_mapping, \ + .llseek = pci_llseek_resource_legacy, \ + .mmap = pci_mmap_legacy_mem, \ +} + /** * pci_read_legacy_io - read byte(s) from legacy I/O port space * @filp: open sysfs file @@ -1059,41 +1080,11 @@ static loff_t pci_llseek_resource_legacy(struct file *filep, return fixed_size_llseek(filep, offset, whence, attr->size); } -static const struct bin_attribute pci_legacy_io_attr = { - .attr = { .name = "legacy_io", .mode = 0600 }, - .size = PCI_LEGACY_IO_SIZE, - .read = pci_read_legacy_io, - .write = pci_write_legacy_io, - .mmap = pci_mmap_legacy_io, - .llseek = pci_llseek_resource_legacy, - .f_mapping = iomem_get_mapping, -}; +pci_legacy_resource_io_attr(, PCI_LEGACY_IO_SIZE); +pci_legacy_resource_io_attr(_sparse, PCI_LEGACY_IO_SIZE << 5); -static const struct bin_attribute pci_legacy_io_sparse_attr = { - .attr = { .name = "legacy_io_sparse", .mode = 0600 }, - .size = PCI_LEGACY_IO_SIZE << 5, - .read = pci_read_legacy_io, - .write = pci_write_legacy_io, - .mmap = pci_mmap_legacy_io, - .llseek = pci_llseek_resource_legacy, - .f_mapping = iomem_get_mapping, -}; - -static const struct bin_attribute pci_legacy_mem_attr = { - .attr = { .name = "legacy_mem", .mode = 0600 }, - .size = PCI_LEGACY_MEM_SIZE, - .mmap = pci_mmap_legacy_mem, - .llseek = pci_llseek_resource_legacy, - .f_mapping = iomem_get_mapping, -}; - -static const struct bin_attribute pci_legacy_mem_sparse_attr = { - .attr = { .name = "legacy_mem_sparse", .mode = 0600 }, - .size = PCI_LEGACY_MEM_SIZE << 5, - .mmap = pci_mmap_legacy_mem, - .llseek = pci_llseek_resource_legacy, - .f_mapping = iomem_get_mapping, -}; +pci_legacy_resource_mem_attr(, PCI_LEGACY_MEM_SIZE); +pci_legacy_resource_mem_attr(_sparse, PCI_LEGACY_MEM_SIZE << 5); static const struct bin_attribute *const pci_legacy_io_attrs[] = { &pci_legacy_io_attr,