summary refs log tree commit diff
path: root/drivers/pci
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-12 23:45:52 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-12 23:45:52 +0100
commitfbb9c10d40f88011ac72f855c97e3bdd981026a9 (patch)
tree255b3c21fd859004310bfad0a829ea4392d4851b /drivers/pci
parent3e7cc142c1e040fd4629ad34a54b1c5b46dc3dd3 (diff)
parent7ede9f8a1805b26b3141730c9deaea8bc95a64bc (diff)
downloadlinux-fbb9c10d40f88011ac72f855c97e3bdd981026a9.tar.gz
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')
-rw-r--r--drivers/pci/pci-label.c129
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 = {