@@ -419,6 +419,11 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev)
return 0;
for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
+ /* if the device does not have an associated smbios string in the smbios table, do not create this attribute */
+ if (!(strcmp(attr_name(bus->dev_attrs[i]), "smbiosname"))) {
+ if (!smbiosname_string_is_valid(dev, NULL))
+ continue;
+ }
error = device_create_file(dev, &bus->dev_attrs[i]);
if (error) {
while (--i >= 0)
@@ -278,6 +278,28 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
list_add_tail(&dev->list, &dmi_devices);
}
+static void __init dmi_save_devslot(int id, int seg, int bus, int devfn, const char *name)
+{
+ struct dmi_devslot *slot;
+
+ slot = dmi_alloc(sizeof(*slot) + strlen(name) + 1);
+ if (!slot) {
+ printk(KERN_ERR "dmi_save_devslot: out of memory.\n");
+ return;
+ }
+ slot->id = id;
+ slot->seg = seg;
+ slot->bus = bus;
+ slot->devfn = devfn;
+
+ strcpy((char *)&slot[1], name);
+ slot->dev.type = DMI_DEV_TYPE_DEVSLOT;
+ slot->dev.name = &slot[1];
+ slot->dev.device_data = slot;
+
+ list_add(&slot->dev.list, &dmi_devices);
+}
+
static void __init dmi_save_extended_devices(const struct dmi_header *dm)
{
const u8 *d = (u8*) dm + 5;
@@ -286,6 +308,7 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
if ((*d & 0x80) == 0)
return;
+ dmi_save_devslot(-1, *(u16 *)(d+2), *(d+4), *(d+5), dmi_string_nosave(dm, *(d-1)));
dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
}
@@ -140,6 +140,41 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
(u8)(pci_dev->class));
}
+#ifdef CONFIG_DMI
+#include <linux/dmi.h>
+ssize_t
+smbiosname_string_is_valid(struct device *dev, char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct dmi_device *dmi;
+ struct dmi_devslot *dslot;
+ int bus;
+ int devfn;
+
+ bus = pdev->bus->number;
+ devfn = pdev->devfn;
+
+ dmi = NULL;
+ while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEVSLOT, NULL, dmi)) != NULL) {
+ dslot = dmi->device_data;
+ if (dslot && dslot->bus == bus && dslot->devfn == devfn) {
+ if (buf)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", dmi->name);
+ return strlen(dmi->name);
+ }
+
+ }
+}
+EXPORT_SYMBOL(smbiosname_string_is_valid);
+
+static ssize_t
+smbiosname_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return smbiosname_string_is_valid(dev, buf);
+
+}
+#endif
+
static ssize_t is_enabled_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
@@ -324,6 +359,9 @@ struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(class),
__ATTR_RO(irq),
__ATTR_RO(local_cpus),
+#ifdef CONFIG_DMI
+ __ATTR_RO(smbiosname),
+#endif
__ATTR_RO(local_cpulist),
__ATTR_RO(modalias),
#ifdef CONFIG_NUMA
@@ -427,6 +427,10 @@ struct device {
void (*release)(struct device *dev);
};
+#ifdef CONFIG_DMI
+extern ssize_t smbiosname_string_is_valid(struct device *, char *);
+#endif
+
/* Get the wakeup routines, which depend on struct device */
#include <linux/pm_wakeup.h>
@@ -20,6 +20,7 @@ enum dmi_device_type {
DMI_DEV_TYPE_SAS,
DMI_DEV_TYPE_IPMI = -1,
DMI_DEV_TYPE_OEM_STRING = -2,
+ DMI_DEV_TYPE_DEVSLOT = -3,
};
struct dmi_header {
@@ -37,6 +38,14 @@ struct dmi_device {
#ifdef CONFIG_DMI
+struct dmi_devslot {
+ struct dmi_device dev;
+ int id;
+ int seg;
+ int bus;
+ int devfn;
+};
+
extern int dmi_check_system(const struct dmi_system_id *list);
const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
extern const char * dmi_get_system_info(int field);