We've been exposing slot information in /sys/bus/pci/slots for a long time now (as long as a hotplug driver or slot detection driver like pci_slot is loaded). Let's make life easy for our users and display that information in lspci. If slot entries appear in /sys/bus/pci/slots/, correlate them to PCI devices, and display the information when lspci -v is issued. If no slot entries appear in sysfs (due to no modules loaded), do nothing. Now you'll see sample output like the following: 23:01.1 Class 0c04: Device 10df:fd00 (rev 01) Subsystem: Device 10df:fd00 Physical Slot: 3 Flags: bus master, 66MHz, medium devsel, latency 248, IRQ 60 ... Signed-off-by: Alex Chiang <achiang@xxxxxx> --- There are probably better ways to do this, but this at least gives a rough idea of the desired functionality. The initial hunk near the top of sysfs.c is a whitespace fix that I cleaned up while I was in the file. lib/pci.h | 1 + lib/sysfs.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- lspci.c | 3 +++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/pci.h b/lib/pci.h index 452e1d8..c7db6d5 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -129,6 +129,7 @@ struct pci_dev { pciaddr_t rom_base_addr; /* Expansion ROM base address */ pciaddr_t rom_size; /* Expansion ROM size */ struct pci_cap *first_cap; /* List of capabilities */ + char *phy_slot; /* Physical slot */ /* Fields used internally: */ struct pci_access *access; diff --git a/lib/sysfs.c b/lib/sysfs.c index 6ebabe1..bdef931 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -1,7 +1,7 @@ /* * The PCI Library -- Configuration Access via /sys/bus/pci * - * Copyright (c) 2003 Matthew Wilcox <willy@xxxxxxxxx> + * Copyright (c) 2003 Matthew Wilcox <willy@xxxxxxxxx> * Copyright (c) 1997--2008 Martin Mares <mj@xxxxxx> * * Can be freely distributed and used under the terms of the GNU GPL. @@ -130,6 +130,52 @@ sysfs_get_resources(struct pci_dev *d) fclose(file); } +static void +sysfs_find_slot(struct pci_dev *d) +{ + struct pci_access *a = d->access; + char dirname[1024]; + DIR *dir; + struct dirent *entry; + int n; + + n = snprintf(dirname, sizeof(dirname), "%s/slots", sysfs_name(a)); + if (n < 0 || n >= (int) sizeof(dirname)) + a->error("Directory name too long"); + dir = opendir(dirname); + if (!dir) + a->error("Cannot open %s", dirname); + while ((entry = readdir(dir))) + { + char namebuf[OBJNAMELEN], buf[16]; + FILE *file; + unsigned int dom, bus, dev; + int n = snprintf(namebuf, OBJNAMELEN, "%s/%s/%s", dirname, entry->d_name, "address"); + + /* ".", ".." or a special non-device perhaps */ + if (entry->d_name[0] == '.') + continue; + + if (n < 0 || n >= OBJNAMELEN) + d->access->error("File name too long"); + file = fopen(namebuf, "r"); + if (!file) + a->error("Cannot open %s: %s", namebuf, strerror(errno)); + if (!fgets(buf, sizeof(buf), file)) + break; + if (sscanf(buf, "%x:%x:%x", &dom, &bus, &dev) < 3) + a->error("sysfs_scan: Couldn't parse entry address %s", buf); + if (dom == d->domain && bus == d->bus && dev == d->dev) { + d->phy_slot = pci_malloc(a, strlen(entry->d_name) + 1); + sprintf(d->phy_slot, "%s", entry->d_name); + fclose(file); + break; + } + fclose(file); + } + closedir(dir); +} + static void sysfs_scan(struct pci_access *a) { char dirname[1024]; @@ -162,6 +208,7 @@ static void sysfs_scan(struct pci_access *a) if (!a->buscentric) { sysfs_get_resources(d); + sysfs_find_slot(d); d->irq = sysfs_get_value(d, "irq"); /* * We could read these faster from the config registers, but we want to give diff --git a/lspci.c b/lspci.c index d872c75..4d2e77b 100644 --- a/lspci.c +++ b/lspci.c @@ -685,6 +685,9 @@ show_verbose(struct device *d) return; } + if (p->phy_slot) + printf("\tPhysical Slot: %s\n", p->phy_slot); + if (verbose > 1) { printf("\tControl: I/O%c Mem%c BusMaster%c SpecCycle%c MemWINV%c VGASnoop%c ParErr%c Stepping%c SERR%c FastB2B%c DisINTx%c\n", -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html