Commit dcfa9be8 authored by Simone Gotti's avatar Simone Gotti Committed by Bjorn Helgaas

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 after 1d0fcef7, 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: 1d0fcef7 ("ACPI / PCI: replace open-coded _DSM code with helper functions")
Signed-off-by: default avatarSimone Gotti <simone.gotti@gmail.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarJiang Liu <jiang.liu@linux.intel.com>
CC: stable@vger.kernel.org	# v3.14+
parent 7f105d31
...@@ -161,8 +161,8 @@ enum acpi_attr_enum { ...@@ -161,8 +161,8 @@ enum acpi_attr_enum {
static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
{ {
int len; int len;
len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer, len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer,
obj->string.length, obj->buffer.length,
UTF16_LITTLE_ENDIAN, UTF16_LITTLE_ENDIAN,
buf, PAGE_SIZE); buf, PAGE_SIZE);
buf[len] = '\n'; buf[len] = '\n';
...@@ -187,16 +187,22 @@ static int dsm_get_label(struct device *dev, char *buf, ...@@ -187,16 +187,22 @@ static int dsm_get_label(struct device *dev, char *buf,
tmp = obj->package.elements; tmp = obj->package.elements;
if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 && if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 &&
tmp[0].type == ACPI_TYPE_INTEGER && 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 * The second string element is optional even when
* this _DSM is implemented; when not implemented, * this _DSM is implemented; when not implemented,
* this entry must return a null string. * 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); scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value);
else if (attr == ACPI_ATTR_LABEL_SHOW) } 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); dsm_label_utf16s_to_utf8s(tmp + 1, buf);
}
len = strlen(buf) > 0 ? strlen(buf) : -1; len = strlen(buf) > 0 ? strlen(buf) : -1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment