ACPI / PCI: Fix sysfs acpi_index and label errors
Fix errors in handling "device label" _DSM return values. If _DSM returns a Unicode string, the ACPI type is ACPI_TYPE_BUFFER, not ACPI_TYPE_STRING. Fix dsm_label_utf16s_to_utf8s() to convert UTF-16 from acpi_object->buffer instead of acpi_object->string. Prior to v3.14, we accepted Unicode labels (ACPI_TYPE_BUFFER return values). But after1d0fcef732
, we accepted only ASCII (ACPI_TYPE_STRING) (and we incorrectly tried to convert those ASCII labels from UTF-16 to UTF-8). Rejecting Unicode labels made us return -EPERM when reading sysfs "acpi_index" or "label" files, which in turn caused on-board network interfaces on a Dell PowerEdge E420 to be renamed (by udev net_id internal) from eno1/eno2 to enp2s0f0/enp2s0f1. Fix this by accepting either ACPI_TYPE_STRING (and treating it as ASCII) or ACPI_TYPE_BUFFER (and converting from UTF-16 to UTF-8). [bhelgaas: changelog] Fixes:1d0fcef732
("ACPI / PCI: replace open-coded _DSM code with helper functions") Signed-off-by: Simone Gotti <simone.gotti@gmail.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Jiang Liu <jiang.liu@linux.intel.com> CC: stable@vger.kernel.org # v3.14+
This commit is contained in:
parent
7f105d3118
commit
dcfa9be838
|
@ -161,8 +161,8 @@ enum acpi_attr_enum {
|
|||
static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
|
||||
{
|
||||
int len;
|
||||
len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer,
|
||||
obj->string.length,
|
||||
len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer,
|
||||
obj->buffer.length,
|
||||
UTF16_LITTLE_ENDIAN,
|
||||
buf, PAGE_SIZE);
|
||||
buf[len] = '\n';
|
||||
|
@ -187,16 +187,22 @@ static int dsm_get_label(struct device *dev, char *buf,
|
|||
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_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)
|
||||
if (attr == ACPI_ATTR_INDEX_SHOW) {
|
||||
scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value);
|
||||
else if (attr == ACPI_ATTR_LABEL_SHOW)
|
||||
dsm_label_utf16s_to_utf8s(tmp + 1, buf);
|
||||
} else if (attr == ACPI_ATTR_LABEL_SHOW) {
|
||||
if (tmp[1].type == ACPI_TYPE_STRING)
|
||||
scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
tmp[1].string.pointer);
|
||||
else if (tmp[1].type == ACPI_TYPE_BUFFER)
|
||||
dsm_label_utf16s_to_utf8s(tmp + 1, buf);
|
||||
}
|
||||
len = strlen(buf) > 0 ? strlen(buf) : -1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue