mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
PCI/sysfs: Decouple acpi_index from the optional device name element
The "_DSM for Naming a PCI or PCI Express Device Under Operating Systems" (PCI Firmware r3.3, sec 4.6.7) returns a package of two elements: 1) Instance number (mandatory Integer) 2) String name (optional String, null string if not populated) These are exposed as sysfs 'acpi_index' and 'label'. Previously, if the name was malformed, reads of 'acpi_index' failed unnecessarily. Validate each element only for the attribute that exports it. So "acpi_index" now depends on the instance number alone, and "label" reads fail with -EIO when the name element is neither a string nor a buffer. The package elements pointer is read only after the object type has been checked. On platforms with a valid instance number and a malformed name element the "acpi_index" attribute starts returning data. Because udev derives the onboard interface name from "acpi_index", an interface on such a platform may be renamed once, on the first boot after this change. That is the attribute assuming the value the firmware always provided. Link: https://github.com/pciutils/pciutils/issues/175 Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20260814070522.2327975-3-kwilczynski@kernel.org
This commit is contained in:
parent
36f9bd0992
commit
337bdf8531
|
|
@ -157,7 +157,7 @@ static int dsm_get_label(struct device *dev, char *buf,
|
|||
{
|
||||
acpi_handle handle = ACPI_HANDLE(dev);
|
||||
union acpi_object *obj, *tmp;
|
||||
int len = 0;
|
||||
int len;
|
||||
|
||||
if (!handle)
|
||||
return -ENODEV;
|
||||
|
|
@ -167,30 +167,43 @@ static int dsm_get_label(struct device *dev, char *buf,
|
|||
if (!obj)
|
||||
return -EIO;
|
||||
|
||||
tmp = obj->package.elements;
|
||||
if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 &&
|
||||
tmp[0].type == ACPI_TYPE_INTEGER &&
|
||||
(tmp[1].type == ACPI_TYPE_STRING ||
|
||||
tmp[1].type == ACPI_TYPE_BUFFER)) {
|
||||
/*
|
||||
* The second string element is optional even when
|
||||
* this _DSM is implemented; when not implemented,
|
||||
* this entry must return a null string.
|
||||
*/
|
||||
if (attr == ACPI_ATTR_INDEX_SHOW) {
|
||||
len = sysfs_emit(buf, "%llu\n", tmp->integer.value);
|
||||
} else if (attr == ACPI_ATTR_LABEL_SHOW) {
|
||||
if (tmp[1].type == ACPI_TYPE_STRING)
|
||||
len = sysfs_emit(buf, "%s\n",
|
||||
tmp[1].string.pointer);
|
||||
else if (tmp[1].type == ACPI_TYPE_BUFFER)
|
||||
len = dsm_label_utf16s_to_utf8s(tmp + 1, buf);
|
||||
}
|
||||
if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 2) {
|
||||
len = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp = obj->package.elements;
|
||||
if (tmp[0].type != ACPI_TYPE_INTEGER) {
|
||||
len = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (attr == ACPI_ATTR_INDEX_SHOW) {
|
||||
len = sysfs_emit(buf, "%llu\n", tmp[0].integer.value);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Per PCI Firmware r3.3, sec 4.6.7, the device name is optional
|
||||
* even when this _DSM is implemented. When not implemented, this
|
||||
* entry must return a NULL string.
|
||||
*/
|
||||
switch (tmp[1].type) {
|
||||
case ACPI_TYPE_STRING:
|
||||
len = sysfs_emit(buf, "%s\n", tmp[1].string.pointer);
|
||||
break;
|
||||
case ACPI_TYPE_BUFFER:
|
||||
len = dsm_label_utf16s_to_utf8s(&tmp[1], buf);
|
||||
break;
|
||||
default:
|
||||
len = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
ACPI_FREE(obj);
|
||||
|
||||
return len > 0 ? len : -EIO;
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t label_show(struct device *dev, struct device_attribute *attr,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user