diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-12 23:45:52 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-12 23:45:52 +0100 |
commit | fbb9c10d40f88011ac72f855c97e3bdd981026a9 (patch) | |
tree | 255b3c21fd859004310bfad0a829ea4392d4851b /drivers/pci/pci-label.c | |
parent | Merge branch 'acpica' (diff) | |
parent | ACPI / extlog: replace open-coded _DSM code with helper functions (diff) | |
download | linux-fbb9c10d40f88011ac72f855c97e3bdd981026a9.tar.xz linux-fbb9c10d40f88011ac72f855c97e3bdd981026a9.zip |
Merge branch 'acpi-dsm'
* acpi-dsm:
ACPI / extlog: replace open-coded _DSM code with helper functions
ACPI / nouveau: replace open-coded _DSM code with helper functions
nouveau / ACPI: fix memory leak in ACPI _DSM related code
ACPI / i915: replace open-coded _DSM code with helper functions
ACPI / i2c-hid: replace open-coded _DSM code with helper functions
ACPI / TPM: detect PPI features by checking availability of _DSM functions
ACPI / TPM: replace open-coded _DSM code with helper functions
ACPI / TPM: match node name instead of full path when searching for TPM device
PCI / pci-label: treat PCI label with index 0 as valid label
ACPI / PCI: replace open-coded _DSM code with helper functions
PCI / pci-label: release allocated ACPI object on error recovery path
ACPI: introduce helper interfaces for _DSM method
Diffstat (limited to 'drivers/pci/pci-label.c')
-rw-r--r-- | drivers/pci/pci-label.c | 129 |
1 files changed, 37 insertions, 92 deletions
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index dbafcc8ef673..d2d1ceccad4b 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c @@ -186,7 +186,6 @@ static const char device_label_dsm_uuid[] = { }; enum acpi_attr_enum { - ACPI_ATTR_NONE = 0, ACPI_ATTR_LABEL_SHOW, ACPI_ATTR_INDEX_SHOW, }; @@ -194,84 +193,61 @@ 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-> - package.elements[1].string.pointer, - obj->package.elements[1].string.length, + len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer, + obj->string.length, UTF16_LITTLE_ENDIAN, buf, PAGE_SIZE); buf[len] = '\n'; } static int -dsm_get_label(acpi_handle handle, int func, - struct acpi_buffer *output, - char *buf, enum acpi_attr_enum attribute) +dsm_get_label(struct device *dev, char *buf, enum acpi_attr_enum attr) { - 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) + acpi_handle handle; + union acpi_object *obj, *tmp; + int len = -1; + + handle = ACPI_HANDLE(dev); + if (!handle) 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 (attribute == ACPI_ATTR_INDEX_SHOW) - scnprintf(buf, PAGE_SIZE, "%llu\n", - obj->package.elements[0].integer.value); - else if (attribute == ACPI_ATTR_LABEL_SHOW) - dsm_label_utf16s_to_utf8s(obj, buf); - kfree(output->pointer); - return strlen(buf); - } - kfree(output->pointer); - return len; - break; - default: - kfree(output->pointer); + obj = acpi_evaluate_dsm(handle, device_label_dsm_uuid, 0x2, + DEVICE_LABEL_DSM, NULL); + if (!obj) + return -1; + + 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) { + /* + * 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) + scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value); + else if (attr == ACPI_ATTR_LABEL_SHOW) + dsm_label_utf16s_to_utf8s(tmp + 1, buf); + len = strlen(buf) > 0 ? strlen(buf) : -1; } - return -1; + + ACPI_FREE(obj); + + return len; } static bool device_has_dsm(struct device *dev) { acpi_handle handle; - struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; handle = ACPI_HANDLE(dev); - if (!handle) - return FALSE; + return false; - if (dsm_get_label(handle, DEVICE_LABEL_DSM, &output, NULL, - ACPI_ATTR_NONE) > 0) - return TRUE; - - return FALSE; + return !!acpi_check_dsm(handle, device_label_dsm_uuid, 0x2, + 1 << DEVICE_LABEL_DSM); } static umode_t @@ -290,44 +266,13 @@ acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n) static ssize_t acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_handle handle; - int length; - - handle = ACPI_HANDLE(dev); - - if (!handle) - return -1; - - length = dsm_get_label(handle, DEVICE_LABEL_DSM, - &output, buf, ACPI_ATTR_LABEL_SHOW); - - if (length < 1) - return -1; - - return length; + return dsm_get_label(dev, buf, ACPI_ATTR_LABEL_SHOW); } static ssize_t acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_handle handle; - int length; - - handle = ACPI_HANDLE(dev); - - if (!handle) - return -1; - - length = dsm_get_label(handle, DEVICE_LABEL_DSM, - &output, buf, ACPI_ATTR_INDEX_SHOW); - - if (length < 0) - return -1; - - return length; - + return dsm_get_label(dev, buf, ACPI_ATTR_INDEX_SHOW); } static struct device_attribute acpi_attr_label = { |