PCI/sysfs: Expose PCI device serial number

Add a single sysfs read-only interface for reading PCI device serial
numbers from userspace in a programmatic way. This device attribute uses
the same hexadecimal 1-byte dashed formatting as lspci serial number
capability output. If a device doesn't support the serial number
capability, the serial_number sysfs attribute will not be visible.

Signed-off-by: Matthew Wood <thepacketgeek@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Mario Limonciello <superm1@kernel.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Link: https://patch.msgid.link/20250917125815.722952-2-thepacketgeek@gmail.com
This commit is contained in:
Matthew Wood 2025-09-17 05:58:14 -07:00 committed by Bjorn Helgaas
parent fac679df75
commit cf6ee09b09
2 changed files with 30 additions and 0 deletions

View file

@ -612,3 +612,12 @@ Description:
# ls doe_features
0001:01 0001:02 doe_discovery
What: /sys/bus/pci/devices/.../serial_number
Date: December 2025
Contact: Matthew Wood <thepacketgeek@gmail.com>
Description:
This is visible only for PCI devices that support the serial
number extended capability. The file is read only and due to
the possible sensitivity of accessible serial numbers, admin
only.

View file

@ -30,6 +30,7 @@
#include <linux/msi.h>
#include <linux/of.h>
#include <linux/aperture.h>
#include <linux/unaligned.h>
#include "pci.h"
#ifndef ARCH_PCI_DEV_GROUPS
@ -694,6 +695,22 @@ static ssize_t boot_vga_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(boot_vga);
static ssize_t serial_number_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
u64 dsn;
u8 bytes[8];
dsn = pci_get_dsn(pci_dev);
if (!dsn)
return -EIO;
put_unaligned_be64(dsn, bytes);
return sysfs_emit(buf, "%8phD\n", bytes);
}
static DEVICE_ATTR_ADMIN_RO(serial_number);
static ssize_t pci_read_config(struct file *filp, struct kobject *kobj,
const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
@ -1698,6 +1715,7 @@ late_initcall(pci_sysfs_init);
static struct attribute *pci_dev_dev_attrs[] = {
&dev_attr_boot_vga.attr,
&dev_attr_serial_number.attr,
NULL,
};
@ -1710,6 +1728,9 @@ static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
if (a == &dev_attr_boot_vga.attr && pci_is_vga(pdev))
return a->mode;
if (a == &dev_attr_serial_number.attr && pci_get_dsn(pdev))
return a->mode;
return 0;
}