diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index 55ea1db749a1..c4ff6b538233 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci +++ b/Documentation/ABI/testing/sysfs-bus-pci @@ -244,10 +244,16 @@ Contact: Narendra K , linux-bugs@dell.com Description: Reading this attribute will provide the firmware given name (SMBIOS type 41 string or ACPI _DSM string) of - the PCI device. The attribute will be created only - if the firmware has given a name to the PCI device. - ACPI _DSM string name will be given priority if the - system firmware provides SMBIOS type 41 string also. + the PCI device. The attribute will be created only if the + firmware naming mechanism is implemented for the device: + a SMBIOS type 41 record with a non-empty reference + designation, or a Device Name _DSM that returns the name + as a string or a buffer. The value read is empty when the + firmware implements the _DSM but gives the device no name, + which per PCI Firmware r3.3, sec 4.6.7 the firmware reports + as a NULL string. ACPI _DSM string name will be given + priority if the system firmware provides SMBIOS type 41 + string also. Users: Userspace applications interested in knowing the firmware assigned name of the PCI device. diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index 5b08f50653a3..abb941530c56 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c @@ -230,11 +230,42 @@ static umode_t acpi_attr_is_visible(struct kobject *kobj, struct attribute *a, int n) { struct device *dev = kobj_to_dev(kobj); + union acpi_object *obj, *tmp; + umode_t mode = 0; if (!device_has_acpi_name(dev)) return 0; - return a->mode; + /* + * The bitmap from _DSM function 0 only advertises function 7, + * and whether the returned object can be parsed is a separate + * question. Evaluate it and expose each attribute only if the + * element it exports has one of the types the read path + * accepts, mirroring the checks in dsm_get_label(). + */ + obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &pci_acpi_dsm_guid, 0x2, + DSM_PCI_DEVICE_NAME, NULL); + if (!obj) + return 0; + + if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 2) + goto out; + + tmp = obj->package.elements; + if (tmp[0].type != ACPI_TYPE_INTEGER) + goto out; + + if (a == &dev_attr_acpi_index.attr) + mode = a->mode; + else if (a == &dev_attr_label.attr && + (tmp[1].type == ACPI_TYPE_STRING || + tmp[1].type == ACPI_TYPE_BUFFER)) + mode = a->mode; + +out: + ACPI_FREE(obj); + + return mode; } const struct attribute_group pci_dev_acpi_attr_group = {