Skip to contentSkip to conversation

Save SMBIOS Type 9 System Slots during DMI Scan

PATCH In review Jordan Hargrave 4 participants 5 messages Nov 28, 2015 – Feb 10, 2016

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v3 1/1 Save SMBIOS Type 9 System Slots during DMI Scan

commit fdf6d7e7cf448b9482062d73a48895afaf38a458

Author: Jordan Hargrave <[email protected]>
Date:   Fri Nov 27 20:39:59 2015 -0600

Fix spacing
Check invalid slot entry according to spec

commit 8a7fe87241b93c72cfd6ef818a680a2c7fc2f1c7

Author: Jordan Hargrave <[email protected]>
Date:   Thu Nov 26 15:57:24 2015 -0600

Save SMBIOS Type 9 System Slots during DMI Scan

PCI address of onboard devices is currently saved but not for slots.

Cleaned up some code, verify clean patch

PCI address of onboard devices is currently saved but not for slots.

Cleaned up some code, verify clean patch

---
 drivers/firmware/dmi_scan.c | 53 +++++++++++++++++++++++++++++++--------------
 include/linux/dmi.h         |  1 +
 2 files changed, 38 insertions(+), 16 deletions(-)
drivers/firmware/dmi_scan.c +37 -16
index ac1ce4a..c6b2828 100644
@@ -321,26 +321,30 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
 	list_add_tail(&dev->list, &dmi_devices);
 }
 
-static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
-					int devfn, const char *name)
+static void __init dmi_save_dev_pciaddr(int instance, int segment, int bus,
+					int devfn, const char *name, int type)
 {
-	struct dmi_dev_onboard *onboard_dev;
+	struct dmi_dev_onboard *dev;
 
-	onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1);
-	if (!onboard_dev)
+	/* Ignore invalid values */
+	if ((bus == 0 && devfn == 0) || (bus == 0xFF && devfn == 0xFF))
 		return;
 
-	onboard_dev->instance = instance;
-	onboard_dev->segment = segment;
-	onboard_dev->bus = bus;
-	onboard_dev->devfn = devfn;
+	dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
+	if (!dev)
+		return;
 
-	strcpy((char *)&onboard_dev[1], name);
-	onboard_dev->dev.type = DMI_DEV_TYPE_DEV_ONBOARD;
-	onboard_dev->dev.name = (char *)&onboard_dev[1];
-	onboard_dev->dev.device_data = onboard_dev;
+	dev->instance = instance;
+	dev->segment = segment;
+	dev->bus = bus;
+	dev->devfn = devfn;
 
-	list_add(&onboard_dev->dev.list, &dmi_devices);
+	strcpy((char *)&dev[1], name);
+	dev->dev.type = type;
+	dev->dev.name = (char *)&dev[1];
+	dev->dev.device_data = dev;
+
+	list_add(&dev->dev.list, &dmi_devices);
 }
 
 static void __init dmi_save_extended_devices(const struct dmi_header *dm)
@@ -351,11 +355,25 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
 	if ((*d & 0x80) == 0)
 		return;
 
-	dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5),
-			     dmi_string_nosave(dm, *(d-1)));
+	dmi_save_dev_pciaddr(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5),
+			     dmi_string_nosave(dm, *(d-1)),
+			     DMI_DEV_TYPE_DEV_ONBOARD);
 	dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
 }
 
+static void __init dmi_save_system_slot(const struct dmi_header *dm)
+{
+	const u8 *d = (u8 *)dm;
+
+	/* Need SMBIOS 2.6+ structure */
+	if (dm->length < 0x11)
+		return;
+	dmi_save_dev_pciaddr(*(u16 *)(d + 0x9), *(u16 *)(d + 0xD),
+			     *(d + 0xF), *(d + 0x10),
+			     dmi_string_nosave(dm, *(d + 0x4)),
+			     DMI_DEV_TYPE_DEV_SLOT);
+}
+
 static void __init count_mem_devices(const struct dmi_header *dm, void *v)
 {
 	if (dm->type != DMI_ENTRY_MEM_DEVICE)
@@ -426,6 +444,9 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
 		dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);
 		dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
 		break;
+	case 9:		/* System Slots */
+	       dmi_save_system_slot(dm);
+	       break;
 	case 10:	/* Onboard Devices Information */
 		dmi_save_devices(dm);
 		break;
include/linux/dmi.h +1 -0
index 5055ac3..5e9c74c 100644
@@ -22,6 +22,7 @@ enum dmi_device_type {
 	DMI_DEV_TYPE_IPMI = -1,
 	DMI_DEV_TYPE_OEM_STRING = -2,
 	DMI_DEV_TYPE_DEV_ONBOARD = -3,
+	DMI_DEV_TYPE_DEV_SLOT = -4,
 };
 
 enum dmi_entry_type {
Signature · 6 lines
1.9.1


---
 drivers/firmware/dmi_scan.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/firmware/dmi_scan.c +4 -3
index c6b2828..6abba82 100644
@@ -327,7 +327,8 @@ static void __init dmi_save_dev_pciaddr(int instance, int segment, int bus,
 	struct dmi_dev_onboard *dev;
 
 	/* Ignore invalid values */
-	if ((bus == 0 && devfn == 0) || (bus == 0xFF && devfn == 0xFF))
+	if (type == DMI_DEV_TYPE_DEV_SLOT &&
+	    segment == 0xFFFF && bus == 0xFF && devfn == 0xFF)
 		return;
 
 	dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
@@ -445,8 +446,8 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
 		dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
 		break;
 	case 9:		/* System Slots */
-	       dmi_save_system_slot(dm);
-	       break;
+		dmi_save_system_slot(dm);
+		break;
 	case 10:	/* Onboard Devices Information */
 		dmi_save_devices(dm);
 		break;
Signature · 1 line
1.9.1
#1 lore raw

Hi Jordan,

Quoted 19 lines · Jordan Hargrave

commit fdf6d7e7cf448b9482062d73a48895afaf38a458

Author: Jordan Hargrave <[email protected]>
Date:   Fri Nov 27 20:39:59 2015 -0600

Fix spacing
Check invalid slot entry according to spec

commit 8a7fe87241b93c72cfd6ef818a680a2c7fc2f1c7

Author: Jordan Hargrave <[email protected]>
Date:   Thu Nov 26 15:57:24 2015 -0600

Save SMBIOS Type 9 System Slots during DMI Scan

PCI address of onboard devices is currently saved but not for slots.

Cleaned up some code, verify clean patch

PCI address of onboard devices is currently saved but not for slots.

Quoted 8 lines

Cleaned up some code, verify clean patch

---
 drivers/firmware/dmi_scan.c | 53 +++++++++++++++++++++++++++++++--------------
 include/linux/dmi.h         |  1 +
 2 files changed, 38 insertions(+), 16 deletions(-)

(...)

Format is awful but result is correct. Next time please rebase cleanly your patch. For this time I'll do it, I must adjust it due to my own patches anyway. So consider it applied.

Thanks,

Signature · 2 lines
Jean Delvare
SUSE L3 Support
#2 lore raw

PATCH 1/1 Create pci slot files for SMBIOS Type 9 entries

In reply to Jordan Hargrave

The following diff builds on the "[PATCHv3] Save SMBIOS Type 9 System Slots"

This will create a /sys/bus/pci/slots/XXX file for each Type 9 entry. This will be used for systemd enumeration of NICs.

---
 arch/x86/pci/common.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)
arch/x86/pci/common.c +17 -0
index eccd4d9..fc5bc49 100644
@@ -173,6 +173,23 @@ void pcibios_fixup_bus(struct pci_bus *b)
 
 void pcibios_add_bus(struct pci_bus *bus)
 {
+	const struct dmi_device *dmi;
+	struct dmi_dev_onboard *dslot;
+
+	dmi = NULL;
+	while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEV_SLOT,
+				      NULL, dmi)) != NULL) {
+		dslot = dmi->device_data;
+		if (dslot->segment == pci_domain_nr(bus) &&
+		    dslot->bus == bus->number) {
+			dev_info(&bus->dev, "Found SMBIOS Slot %s\n",
+				 dslot->dev.name);
+			pci_create_slot(bus, dslot->devfn,
+					dslot->dev.name,
+					NULL);
+		}
+	}
+
 	acpi_pci_add_bus(bus);
 }
 
Signature · 1 line
1.7.1
#3 lore raw

Re: [PATCH] Create pci slot files for SMBIOS Type 9 entries

reproduce:

Hi,

[auto build test ERROR on pci/next]
[also build test ERROR on v4.5-rc3 next-20160209]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Jordan_Hargrave-Dell-com/Create-pci-slot-files-for-SMBIOS-Type-9-entries/20160210-070842
base:   https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next
config: x86_64-randconfig-x013-201606 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

In file included from include/uapi/linux/stddef.h:1:0,

                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/uapi/linux/capability.h:16,
                    from include/linux/capability.h:15,
                    from include/linux/sched.h:15,
                    from arch/x86/pci/common.c:7:
   arch/x86/pci/common.c: In function 'pcibios_add_bus':
>> arch/x86/pci/common.c:182:12: error: dereferencing pointer to incomplete type 'struct dmi_dev_onboard'
      if (dslot->segment == pci_domain_nr(bus) &&
               ^
   include/linux/compiler.h:147:28: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                               ^
>> arch/x86/pci/common.c:182:3: note: in expansion of macro 'if'
      if (dslot->segment == pci_domain_nr(bus) &&
      ^

vim +182 arch/x86/pci/common.c

     1	/*
     2	 *	Low-Level PCI Support for PC
     3	 *
     4	 *	(c) 1999--2000 Martin Mares <[email protected]>
     5	 */
     6	
   > 7	#include <linux/sched.h>
     8	#include <linux/pci.h>
     9	#include <linux/pci-acpi.h>
    10	#include <linux/ioport.h>
    11	#include <linux/init.h>
    12	#include <linux/dmi.h>
    13	#include <linux/slab.h>
    14	
    15	#include <asm/acpi.h>
    16	#include <asm/segment.h>
    17	#include <asm/io.h>
    18	#include <asm/smp.h>
    19	#include <asm/pci_x86.h>
    20	#include <asm/setup.h>
    21	
    22	unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
    23					PCI_PROBE_MMCONF;
    24	
    25	unsigned int pci_early_dump_regs;
    26	static int pci_bf_sort;
    27	static int smbios_type_b1_flag;
    28	int pci_routeirq;
    29	int noioapicquirk;
    30	#ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS
    31	int noioapicreroute = 0;
    32	#else
    33	int noioapicreroute = 1;
    34	#endif
    35	int pcibios_last_bus = -1;
    36	unsigned long pirq_table_addr;
    37	const struct pci_raw_ops *__read_mostly raw_pci_ops;
    38	const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
    39	
    40	int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
    41							int reg, int len, u32 *val)
    42	{
    43		if (domain == 0 && reg < 256 && raw_pci_ops)
    44			return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
    45		if (raw_pci_ext_ops)
    46			return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
    47		return -EINVAL;
    48	}
    49	
    50	int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
    51							int reg, int len, u32 val)
    52	{
    53		if (domain == 0 && reg < 256 && raw_pci_ops)
    54			return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
    55		if (raw_pci_ext_ops)
    56			return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
    57		return -EINVAL;
    58	}
    59	
    60	static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
    61	{
    62		return raw_pci_read(pci_domain_nr(bus), bus->number,
    63					 devfn, where, size, value);
    64	}
    65	
    66	static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
    67	{
    68		return raw_pci_write(pci_domain_nr(bus), bus->number,
    69					  devfn, where, size, value);
    70	}
    71	
    72	struct pci_ops pci_root_ops = {
    73		.read = pci_read,
    74		.write = pci_write,
    75	};
    76	
    77	/*
    78	 * This interrupt-safe spinlock protects all accesses to PCI
    79	 * configuration space.
    80	 */
    81	DEFINE_RAW_SPINLOCK(pci_config_lock);
    82	
    83	static int __init can_skip_ioresource_align(const struct dmi_system_id *d)
    84	{
    85		pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
    86		printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
    87		return 0;
    88	}
    89	
    90	static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __initconst = {
    91	/*
    92	 * Systems where PCI IO resource ISA alignment can be skipped
    93	 * when the ISA enable bit in the bridge control is not set
    94	 */
    95		{
    96			.callback = can_skip_ioresource_align,
    97			.ident = "IBM System x3800",
    98			.matches = {
    99				DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
   100				DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
   101			},
   102		},
   103		{
   104			.callback = can_skip_ioresource_align,
   105			.ident = "IBM System x3850",
   106			.matches = {
   107				DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
   108				DMI_MATCH(DMI_PRODUCT_NAME, "x3850"),
   109			},
   110		},
   111		{
   112			.callback = can_skip_ioresource_align,
   113			.ident = "IBM System x3950",
   114			.matches = {
   115				DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
   116				DMI_MATCH(DMI_PRODUCT_NAME, "x3950"),
   117			},
   118		},
   119		{}
   120	};
   121	
   122	void __init dmi_check_skip_isa_align(void)
   123	{
   124		dmi_check_system(can_skip_pciprobe_dmi_table);
   125	}
   126	
   127	static void pcibios_fixup_device_resources(struct pci_dev *dev)
   128	{
   129		struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
   130		struct resource *bar_r;
   131		int bar;
   132	
   133		if (pci_probe & PCI_NOASSIGN_BARS) {
   134			/*
   135			* If the BIOS did not assign the BAR, zero out the
   136			* resource so the kernel doesn't attmept to assign
   137			* it later on in pci_assign_unassigned_resources
   138			*/
   139			for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) {
   140				bar_r = &dev->resource[bar];
   141				if (bar_r->start == 0 && bar_r->end != 0) {
   142					bar_r->flags = 0;
   143					bar_r->end = 0;
   144				}
   145			}
   146		}
   147	
   148		if (pci_probe & PCI_NOASSIGN_ROMS) {
   149			if (rom_r->parent)
   150				return;
   151			if (rom_r->start) {
   152				/* we deal with BIOS assigned ROM later */
   153				return;
   154			}
   155			rom_r->start = rom_r->end = rom_r->flags = 0;
   156		}
   157	}
   158	
   159	/*
   160	 *  Called after each bus is probed, but before its children
   161	 *  are examined.
   162	 */
   163	
   164	void pcibios_fixup_bus(struct pci_bus *b)
   165	{
   166		struct pci_dev *dev;
   167	
   168		pci_read_bridge_bases(b);
   169		list_for_each_entry(dev, &b->devices, bus_list)
   170			pcibios_fixup_device_resources(dev);
   171	}
   172	
   173	void pcibios_add_bus(struct pci_bus *bus)
   174	{
   175		const struct dmi_device *dmi;
   176		struct dmi_dev_onboard *dslot;
   177	
   178		dmi = NULL;
   179		while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEV_SLOT,
   180					      NULL, dmi)) != NULL) {
   181			dslot = dmi->device_data;
 > 182			if (dslot->segment == pci_domain_nr(bus) &&

183 dslot->bus == bus->number) {
184 dev_info(&bus->dev, "Found SMBIOS Slot %s\n",
185 dslot->dev.name);

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#4 lore raw

PATCH 1/1 Create pci slot files for SMBIOS Type 9 entries

In reply to [email protected]

The following diff builds on the "[PATCHv3] Save SMBIOS Type 9 System Slots"

This will create a /sys/bus/pci/slots/XXX file for each Type 9 entry. This will be used for systemd enumeration of NICs.

---
 arch/x86/pci/common.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)
arch/x86/pci/common.c +17 -0
index eccd4d9..fc5bc49 100644
@@ -173,6 +173,23 @@ void pcibios_fixup_bus(struct pci_bus *b)
 
 void pcibios_add_bus(struct pci_bus *bus)
 {
+       const struct dmi_device *dmi;
+       struct dmi_dev_onboard *dslot;
+
+       dmi = NULL;
+       while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEV_SLOT,
+                                     NULL, dmi)) != NULL) {
+               dslot = dmi->device_data;
+               if (dslot->segment == pci_domain_nr(bus) &&
+                   dslot->bus == bus->number) {
+                       dev_info(&bus->dev, "Found SMBIOS Slot %s\n",
+                                dslot->dev.name);
+                       pci_create_slot(bus, dslot->devfn,
+                                       dslot->dev.name,
+                                       NULL);
+               }
+       }
+
        acpi_pci_add_bus(bus);
 }
 

--
1.7.1