Re: [PATCH V2 1/2] Export firmware assigned labels of network devices to sysfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Greg KH [mailto:greg@xxxxxxxxx] 
> Sent: Friday, May 28, 2010 9:11 PM
> To: K, Narendra
> Cc: netdev@xxxxxxxxxxxxxxx; linux-hotplug@xxxxxxxxxxxxxxx;
> linux-pci@xxxxxxxxxxxxxxx; Domsch, Matt; Hargrave, Jordan; Rose,
> Charles; Nijhawan, Vijay
> Subject: Re: [PATCH 1/2] Export firmware assigned labels of network
> devices to sysfs
> 
Thanks for the comments.

> On Fri, May 28, 2010 at 06:55:21AM -0500, K, Narendra wrote:
> > Please refer to the PCI-SIG Draft ECN
> > "PCIe Device Labeling under Operating Systems Draft ECN" at this link
> -
> > http://www.pcisig.com/specifications/pciexpress/review_zone/.
> > 
> > It would be great to know your views on this ECN. Please let us know
> if you have
> > have any suggestions or changes.
> 
> Note that only members of the PCI-SIG can do this, which pretty much
> rules out any "normal" Linux kernel developer :(
> 
> Care to post a public version of this for us to review?
> > --- /dev/null
> > +++ b/drivers/pci/pci-label.c
> > @@ -0,0 +1,242 @@
> > +/*
> > + * File:       drivers/pci/pci-label.c
> 
> This line is not needed, we know the file name :)
> 
> > + * Purpose:    Export the firmware label associated with a pci
> network interface
> > + * device to sysfs
> > + * Copyright (C) 2010 Dell Inc.
> > + * by Narendra K <Narendra_K@xxxxxxxx>, Jordan Hargrave
> <Jordan_Hargrave@xxxxxxxx>
> > + *
> > + * This code checks if the pci network device has a related ACPI
> _DSM. If
> > + * available, the code calls the _DSM to retrieve the index and
> string and
> > + * exports them to sysfs. If the ACPI _DSM is not available, it falls
> back on
> > + * SMBIOS. SMBIOS defines type 41 for onboard pci devices. This code
> retrieves
> > + * strings associated with the type 41 and exports it to sysfs.
> > + *
> > + * Please see http://linux.dell.com/wiki/index.php/Oss/libnetdevname
> for more
> > + * information.
> > + */
> > +
> > +#include <linux/pci-label.h>
> 
> Why is this file in include/linux/ ?  Who needs it there?  Can't it just
> be in in the drivers/pci/ directory?  Actually all you need is 2
> functions in there, so it could go into the internal pci.h file in that
> directory without a problem, right?
> 

This file is removed and functions are moved to the internal pci.h

> > +
> > +static ssize_t
> > +smbiosname_string_exists(struct device *dev, char *buf)
> > +{
> > +       struct pci_dev *pdev = to_pci_dev(dev);
> > +       const 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);
> > +               }
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static ssize_t
> > +smbiosname_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> > +{
> > +       return smbiosname_string_exists(dev, buf);
> > +}
> > +
> > +struct smbios_attribute smbios_attr_label = {
> > +       .attr = {.name = __stringify(label), .mode = 0444, .owner =
> THIS_MODULE},
> 
> Can't you just put "label" as the name?
> 

This is fixed.

> > +       .show = smbiosname_show,
> > +       .test = smbiosname_string_exists,
> > +};
> > +
> > +static int
> > +pci_create_smbiosname_file(struct pci_dev *pdev)
> > +{
> > +       if (smbios_attr_label.test &&
> smbios_attr_label.test(&pdev->dev, NULL)) {
> > +               sysfs_create_file(&pdev->dev.kobj,
> &smbios_attr_label.attr);
> > +               return 0;
> > +       }
> > +       return -1;
> > +}
> > +
> > +static int
> > +pci_remove_smbiosname_file(struct pci_dev *pdev)
> > +{
> > +       if (smbios_attr_label.test &&
> smbios_attr_label.test(&pdev->dev, NULL)) {
> > +               sysfs_remove_file(&pdev->dev.kobj,
> &smbios_attr_label.attr);
> > +               return 0;
> > +       }
> > +       return -1;
> > +}
> > +
> > +static const char dell_dsm_uuid[] = {
> 
> Um, a dell specific uuid in a generic file?  What happens when we need
> to support another manufacturer?
> 

My understanding of uuid was incorrect. I have renamed it to a more generic
device_label_dsm_uuid and ACPI_DSM_FUNCTION to DEVICE_LABEL_DSM

> > +       0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
> > +       0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
> > +};
> > +
> > +
> > +static int
> > +dsm_get_label(acpi_handle handle, int func,
> > +              struct acpi_buffer *output,
> > +              char *buf, char *attribute)
> > +{
> > +       struct acpi_object_list input;
> > +       union acpi_object params[4];
> > +       union acpi_object *obj;
> > +       int len = 0;
> > +
> > +       int err;
> > +
> > +       input.count = 4;
> > +       input.pointer = params;
> > +       params[0].type = ACPI_TYPE_BUFFER;
> > +       params[0].buffer.length = sizeof(dell_dsm_uuid);
> > +       params[0].buffer.pointer = (char *)dell_dsm_uuid;
> > +       params[1].type = ACPI_TYPE_INTEGER;
> > +       params[1].integer.value = 0x02;
> > +       params[2].type = ACPI_TYPE_INTEGER;
> > +       params[2].integer.value = func;
> > +       params[3].type = ACPI_TYPE_PACKAGE;
> > +       params[3].package.count = 0;
> > +       params[3].package.elements = NULL;
> > +
> > +       err = acpi_evaluate_object(handle, "_DSM", &input, output);
> > +       if (err) {
> > +               printk(KERN_INFO "failed to evaulate _DSM\n");
> > +               return -1;
> > +       }
> > +
> > +       obj = (union acpi_object *)output->pointer;
> > +
> > +       switch (obj->type) {
> > +       case ACPI_TYPE_PACKAGE:
> > +               if (obj->package.count == 2) {
> > +                       len = obj->package.elements[0].integer.value;
> > +                       if (buf) {
> > +                               if (!strncmp(attribute, "index",
> strlen(attribute)))
> > +                                       scnprintf(buf, PAGE_SIZE,
> "%lu\n",
> > +
> obj->package.elements[0].integer.value);
> > +                               else
> > +                                       scnprintf(buf, PAGE_SIZE,
> "%s\n",
> > +
> obj->package.elements[1].string.pointer);
> > +                               kfree(output->pointer);
> > +                               return strlen(buf);
> > +                       }
> > +               }
> > +               kfree(output->pointer);
> > +               return len;
> > +       break;
> > +       default:
> > +               return -1;
> > +       }
> > +}
> > +
> > +static ssize_t
> > +acpi_index_string_exist(struct device *dev, char *buf, char
> *attribute)
> > +{
> > +       struct pci_dev *pdev = to_pci_dev(dev);
> > +
> > +       struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
> > +       acpi_handle handle;
> > +       int length;
> > +       int is_addin_card = 0;
> > +
> > +       if ((pdev->class >> 16) != PCI_BASE_CLASS_NETWORK)
> > +               return -1;
> > +
> > +       handle = DEVICE_ACPI_HANDLE(dev);
> > +
> > +       if (!handle) {
> > +               /*
> > +                * The device is an add-in network controller and does
> have
> > +                * a valid handle. Try until we get the handle for the
> parent
> > +                * bridge
> > +                */
> > +               struct pci_bus *pbus;
> > +               for (pbus = pdev->bus; pbus; pbus = pbus->parent) {
> > +                       handle =
> DEVICE_ACPI_HANDLE(&(pbus->self->dev));
> > +                       if (handle)
> > +                               break;
> > +
> > +               }
> > +       }
> > +
> > +       if ((length = dsm_get_label(handle, DELL_DSM_NETWORK,
> > +                                   &output, buf, attribute)) < 0)
> > +               return -1;
> > +
> > +       return length;
> > +}
> > +
> > +static ssize_t
> > +acpilabel_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> > +{
> > +       return acpi_index_string_exist(dev, buf, "label");
> > +}
> > +
> > +static ssize_t
> > +acpiindex_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> > +{
> > +       return acpi_index_string_exist(dev, buf, "index");
> > +}
> > +
> > +struct acpi_attribute acpi_attr_label = {
> > +       .attr = {.name = __stringify(label), .mode = 0444, .owner =
> THIS_MODULE},
> > +       .show = acpilabel_show,
> > +       .test = acpi_index_string_exist,
> > +};
> > +
> > +struct acpi_attribute acpi_attr_index = {
> > +       .attr = {.name = __stringify(index), .mode = 0444, .owner =
> THIS_MODULE},
> > +       .show = acpiindex_show,
> > +       .test = acpi_index_string_exist,
> > +};
> > +
> > +static int
> > +pci_create_acpi_index_label_files(struct pci_dev *pdev)
> > +{
> > +       if (acpi_attr_label.test && acpi_attr_label.test(&pdev->dev,
> NULL) > 0) {
> > +               sysfs_create_file(&pdev->dev.kobj,
> &acpi_attr_label.attr);
> > +               sysfs_create_file(&pdev->dev.kobj,
> &acpi_attr_index.attr);
> > +               return 0;
> > +       }
> > +       return -1;
> > +}
> > +
> > +static int
> > +pci_remove_acpi_index_label_files(struct pci_dev *pdev)
> > +{
> > +       if (acpi_attr_label.test && acpi_attr_label.test(&pdev->dev,
> NULL) > 0) {
> > +               sysfs_remove_file(&pdev->dev.kobj,
> &acpi_attr_label.attr);
> > +               sysfs_remove_file(&pdev->dev.kobj,
> &acpi_attr_index.attr);
> > +               return 0;
> > +       }
> > +       return -1;
> > +}
> > +
> > +int pci_create_acpi_attr_files(struct pci_dev *pdev)
> > +{
> > +       if (!pci_create_acpi_index_label_files(pdev))
> > +               return 0;
> > +       if (!pci_create_smbiosname_file(pdev))
> > +               return 0;
> > +       return -ENODEV;
> > +}
> > +EXPORT_SYMBOL(pci_create_acpi_attr_files);
> 
> EXPORT_SYMBOL_GPL?
> 
> Wait, why does this need to be exported at all?  What module is ever
> going to call this function?
> 
> > +int pci_remove_acpi_attr_files(struct pci_dev *pdev)
> > +{
> > +       if (!pci_remove_acpi_index_label_files(pdev))
> > +               return 0;
> > +       if (!pci_remove_smbiosname_file(pdev))
> > +               return 0;
> > +       return -ENODEV;
> > +
> > +}
> > +EXPORT_SYMBOL(pci_remove_acpi_attr_files);
> 
> Same here, what module will call this?
> 

These functions need not be exported as they are not called by any module.

> > +++ b/include/linux/pci-label.h
> 
> As discussed above, this whole file does not need to exist.
> 
> > +extern int pci_create_acpi_attr_files(struct pci_dev *pdev);
> > +extern int pci_remove_acpi_attr_files(struct pci_dev *pdev);
> 
> Just put these two functions in the drivers/pci/pci.h file.
> 
Fixed.

In addition to these changes there are a coulple of changes i have done -

1.Removed the check for network devices and evaulate _DSM for any pci device
that has _DSM defined in adherence to the spec.

2.Renamed the functions pci_create,remove-acpi_attr_files to 
pci_create,remove_firmware_label_files.

3.Added checks for conditional compilation of if CONFIG_ACPI || CONFIG_DMI

Note: While testing the patch with CONFIG_ACPI set to no, the compilation
would fail with the below message.

  CC      drivers/pci/pci-label.o
In file included from drivers/pci/pci-label.c:24:
include/linux/pci-acpi.h:39: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ 
before ‘acpi_find_root_bridge_handle’

I had to add make this change to proceed with the compilation. It would be
great to know if i am missing something in the way conditional compilation
is implemented or is it a issue.

---
 include/linux/pci-acpi.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index c8b6473..bc40827 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -36,8 +36,8 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
 					      pbus->number);
 }
 #else
-static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
-{ return NULL; }
+static inline void acpi_find_root_bridge_handle(struct pci_dev *pdev)
+{ }
 #endif
 
 #endif	/* _PCI_ACPI_H_ */


Please find the patch with above suggestions and changes -


From: Narendra K <narendra_k@xxxxxxxx>
Subject: [PATCH V2 1/2] Export firmware assigned labels of pci devices to sysfs

This patch exports the firmware assigned labels of pci devices to
sysfs which could be used by user space.

Signed-off-by: Jordan Hargrave <jordan_hargrave@xxxxxxxx>
Signed-off-by: Narendra K <narendra_k@xxxxxxxx>
---
 drivers/firmware/dmi_scan.c |   24 ++++
 drivers/pci/Makefile        |    2 +-
 drivers/pci/pci-label.c     |  273 +++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci-sysfs.c     |    5 +
 drivers/pci/pci.h           |    2 +
 include/linux/dmi.h         |    9 ++
 6 files changed, 314 insertions(+), 1 deletions(-)
 create mode 100644 drivers/pci/pci-label.c

diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index d464672..7d8439b 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -277,6 +277,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 = (char *)&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;
@@ -285,6 +307,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)));
 }
 
@@ -333,6 +356,7 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
 		break;
 	case 41:	/* Onboard Devices Extended Information */
 		dmi_save_extended_devices(dm);
+		break;
 	}
 }
 
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 0b51857..69c503a 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -4,7 +4,7 @@
 
 obj-y		+= access.o bus.o probe.o remove.o pci.o \
 			pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
-			irq.o vpd.o
+			irq.o vpd.o pci-label.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
 
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
new file mode 100644
index 0000000..b35d48c
--- /dev/null
+++ b/drivers/pci/pci-label.c
@@ -0,0 +1,273 @@
+/*
+ * Purpose: Export the firmware label associated with a pci network interface
+ * device to sysfs
+ * Copyright (C) 2010 Dell Inc.
+ * by Narendra K <Narendra_K@xxxxxxxx>, Jordan Hargrave <Jordan_Hargrave@xxxxxxxx>
+ *
+ * This code checks if the pci network device has a related ACPI _DSM. If
+ * available, the code calls the _DSM to retrieve the index and string and
+ * exports them to sysfs. If the ACPI _DSM is not available, it falls back on
+ * SMBIOS. SMBIOS defines type 41 for onboard pci devices. This code retrieves
+ * strings associated with the type 41 and exports it to sysfs.
+ *
+ * Please see http://linux.dell.com/wiki/index.php/Oss/libnetdevname for more
+ * information.
+ */
+
+#include <linux/dmi.h>
+#include <linux/sysfs.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acpi_bus.h>
+#include "pci.h"
+
+#define	DEVICE_LABEL_DSM	0x07
+
+#if defined CONFIG_DMI
+
+struct smbios_attribute {
+	struct attribute attr;
+	ssize_t (*show) (struct device *dev, char *buf);
+	ssize_t (*test) (struct device *dev, char *buf);
+};
+
+static ssize_t
+smbiosname_string_exists(struct device *dev, char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+  	const 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);
+		}
+	}
+	
+	return 0;
+}
+
+static ssize_t
+smbiosname_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return smbiosname_string_exists(dev, buf);
+}
+
+struct smbios_attribute smbios_attr_label = {
+	.attr = {.name = "label", .mode = 0444, .owner = THIS_MODULE},
+	.show = smbiosname_show,
+	.test = smbiosname_string_exists,
+};
+
+static int 
+pci_create_smbiosname_file(struct pci_dev *pdev)
+{
+	if (smbios_attr_label.test && smbios_attr_label.test(&pdev->dev, NULL)) {
+		sysfs_create_file(&pdev->dev.kobj, &smbios_attr_label.attr);
+		return 0;
+	}
+	return -1;	
+}
+
+static int 
+pci_remove_smbiosname_file(struct pci_dev *pdev)
+{
+	if (smbios_attr_label.test && smbios_attr_label.test(&pdev->dev, NULL)) {
+		sysfs_remove_file(&pdev->dev.kobj, &smbios_attr_label.attr);
+		return 0;
+	}
+	return -1;
+}
+#else
+static inline int 
+pci_create_smbiosname_file(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline int 
+pci_remove_smbiosname_file(struct pci_dev *pdev)
+{
+	return -1;
+}
+#endif
+
+#if defined CONFIG_ACPI
+
+static const char device_label_dsm_uuid[] = {
+	0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
+	0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
+};
+
+struct acpi_attribute {
+	struct attribute attr;
+	ssize_t (*show) (struct device *dev, char *buf);
+	ssize_t (*test) (struct device *dev, char *buf);
+};
+
+static int
+dsm_get_label(acpi_handle handle, int func, 
+              struct acpi_buffer *output, 
+              char *buf, char *attribute)
+{
+	struct acpi_object_list input;
+	union acpi_object params[4];
+	union acpi_object *obj; 
+	int len = 0;
+
+	int err;
+
+	input.count = 4;
+	input.pointer = params;
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = sizeof(device_label_dsm_uuid);
+	params[0].buffer.pointer = (char *)device_label_dsm_uuid;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = 0x02;
+	params[2].type = ACPI_TYPE_INTEGER;
+	params[2].integer.value = func;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
+
+	err = acpi_evaluate_object(handle, "_DSM", &input, output);
+	if (err) 
+		return -1;
+	
+	
+	obj = (union acpi_object *)output->pointer;
+
+	switch (obj->type) {
+	case ACPI_TYPE_PACKAGE:
+		if (obj->package.count != 2) 
+			break;
+		len = obj->package.elements[0].integer.value;
+		if (buf) {
+			if (!strncmp(attribute, "index", strlen(attribute)))
+				scnprintf(buf, PAGE_SIZE, "%lu\n", 
+				obj->package.elements[0].integer.value);
+			else
+				scnprintf(buf, PAGE_SIZE, "%s\n", 
+				obj->package.elements[1].string.pointer);
+			kfree(output->pointer);
+			return strlen(buf);
+		}
+		kfree(output->pointer);
+		return len;
+	break;
+	default:
+		kfree(output->pointer);
+		return -1;
+	}
+}	
+
+static ssize_t
+acpi_index_string_exist(struct device *dev, char *buf, char *attribute)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_handle handle;
+	int length;
+	
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle) 
+		return -1;
+
+	if ((length = dsm_get_label(handle, DEVICE_LABEL_DSM, 
+				    &output, buf, attribute)) < 0)
+		return -1;
+
+	return length;
+}
+	
+static ssize_t
+acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return acpi_index_string_exist(dev, buf, "label");
+}
+
+static ssize_t
+acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return acpi_index_string_exist(dev, buf, "index");
+}
+
+struct acpi_attribute acpi_attr_label = {
+	.attr = {.name = "label", .mode = 0444, .owner = THIS_MODULE},
+	.show = acpilabel_show,
+	.test = acpi_index_string_exist,
+};
+
+struct acpi_attribute acpi_attr_index = {
+	.attr = {.name = "index", .mode = 0444, .owner = THIS_MODULE},
+	.show = acpiindex_show,
+	.test = acpi_index_string_exist,
+};
+
+static int
+pci_create_acpi_index_label_files(struct pci_dev *pdev)
+{
+	if (acpi_attr_label.test && acpi_attr_label.test(&pdev->dev, NULL) > 0) {
+		sysfs_create_file(&pdev->dev.kobj, &acpi_attr_label.attr);
+		sysfs_create_file(&pdev->dev.kobj, &acpi_attr_index.attr);
+		return 0;
+	}
+	return -1;
+}
+
+static int
+pci_remove_acpi_index_label_files(struct pci_dev *pdev)
+{
+	if (acpi_attr_label.test && acpi_attr_label.test(&pdev->dev, NULL) > 0) {
+		sysfs_remove_file(&pdev->dev.kobj, &acpi_attr_label.attr);
+		sysfs_remove_file(&pdev->dev.kobj, &acpi_attr_index.attr);
+		return 0;
+	}
+	return -1;
+}
+#else
+static inline int
+pci_create_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline int
+pci_remove_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return -1;
+}
+#endif
+
+int pci_create_firmware_label_files(struct pci_dev *pdev)
+{
+	if (!pci_create_acpi_index_label_files(pdev))
+		return 0;
+	if (!pci_create_smbiosname_file(pdev))
+		return 0;
+	return -ENODEV;
+}
+
+int pci_remove_firmware_label_files(struct pci_dev *pdev)
+{
+	if (!pci_remove_acpi_index_label_files(pdev))
+		return 0;
+	if (!pci_remove_smbiosname_file(pdev))
+		return 0;
+	return -ENODEV;
+}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index fad9398..4ed517f 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1073,6 +1073,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 	if (retval)
 		goto err_vga_file;
 
+	pci_create_firmware_label_files(pdev);
+
 	return 0;
 
 err_vga_file:
@@ -1140,6 +1142,9 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
 		kfree(pdev->rom_attr);
 	}
+
+	pci_remove_firmware_label_files(pdev);
+
 }
 
 static int __init pci_sysfs_init(void)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4eb10f4..f223283 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -11,6 +11,8 @@
 extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
 extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
+extern int pci_create_firmware_label_files(struct pci_dev *pdev);
+extern int pci_remove_firmware_label_files(struct pci_dev *pdev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
 #ifdef HAVE_PCI_MMAP
 extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index a8a3e1a..cc57c3a 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.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);
-- 
1.6.5.2

With regards,
Narendra K
--
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


[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux