mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: ACPI Devel Maling List <linux-acpi@vger.kernel.org>
Cc: LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH 11/12] ACPI: Take power resource initialization errors into account
Date: Fri, 04 Jan 2013 01:09:28 +0100	[thread overview]
Message-ID: <1384429.2N9kZZfmJU@vostro.rjw.lan> (raw)
In-Reply-To: <1418767.4KIZOTK1lk@vostro.rjw.lan>

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Some ACPI power resource initialization errors, like memory
allocation errors, are not taken into account appropriately in some
cases, which may lead to a device having an incomplete list of power
resources that one of its power states depends on, for one example.

Rework the power resource initialization and namespace scanning code
so that power resource initialization errors are treated more
seriously.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/internal.h |    7 ++---
 drivers/acpi/power.c    |   44 +++++++++++++++++++++----------------
 drivers/acpi/scan.c     |   57 +++++++++++++++++++++---------------------------
 3 files changed, 53 insertions(+), 55 deletions(-)

Index: linux/drivers/acpi/internal.h
===================================================================
--- linux.orig/drivers/acpi/internal.h
+++ linux/drivers/acpi/internal.h
@@ -51,10 +51,9 @@ void acpi_free_ids(struct acpi_device *d
    -------------------------------------------------------------------------- */
 int acpi_power_init(void);
 void acpi_power_resources_list_free(struct list_head *list);
-acpi_status acpi_extract_power_resources(union acpi_object *package,
-					 unsigned int start,
-					 struct list_head *list);
-void acpi_add_power_resource(acpi_handle handle);
+int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
+				 struct list_head *list);
+int acpi_add_power_resource(acpi_handle handle);
 void acpi_power_add_remove_device(struct acpi_device *adev, bool add);
 int acpi_device_sleep_wake(struct acpi_device *dev,
                            int enable, int sleep_state, int dev_state);
Index: linux/drivers/acpi/power.c
===================================================================
--- linux.orig/drivers/acpi/power.c
+++ linux/drivers/acpi/power.c
@@ -97,18 +97,18 @@ struct acpi_power_resource *acpi_power_g
 	return container_of(device, struct acpi_power_resource, device);
 }
 
-static void acpi_power_resources_list_add(acpi_handle handle,
-					  struct list_head *list)
+static int acpi_power_resources_list_add(acpi_handle handle,
+					 struct list_head *list)
 {
 	struct acpi_power_resource *resource = acpi_power_get_context(handle);
 	struct acpi_power_resource_entry *entry;
 
 	if (!resource || !list)
-		return;
+		return -EINVAL;
 
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
-		return;
+		return -ENOMEM;
 
 	entry->resource = resource;
 	if (!list_empty(list)) {
@@ -117,10 +117,11 @@ static void acpi_power_resources_list_ad
 		list_for_each_entry(e, list, node)
 			if (e->resource->order > resource->order) {
 				list_add_tail(&entry->node, &e->node);
-				return;
+				return 0;
 			}
 	}
 	list_add_tail(&entry->node, list);
+	return 0;
 }
 
 void acpi_power_resources_list_free(struct list_head *list)
@@ -133,33 +134,37 @@ void acpi_power_resources_list_free(stru
 	}
 }
 
-acpi_status acpi_extract_power_resources(union acpi_object *package,
-					 unsigned int start,
-					 struct list_head *list)
+int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
+				 struct list_head *list)
 {
-	acpi_status status = AE_OK;
 	unsigned int i;
+	int err = 0;
 
 	for (i = start; i < package->package.count; i++) {
 		union acpi_object *element = &package->package.elements[i];
 		acpi_handle rhandle;
 
 		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
-			status = AE_BAD_DATA;
+			err = -ENODATA;
 			break;
 		}
 		rhandle = element->reference.handle;
 		if (!rhandle) {
-			status = AE_NULL_ENTRY;
+			err = -ENODEV;
 			break;
 		}
-		acpi_add_power_resource(rhandle);
-		acpi_power_resources_list_add(rhandle, list);
+		err = acpi_add_power_resource(rhandle);
+		if (err)
+			break;
+
+		err = acpi_power_resources_list_add(rhandle, list);
+		if (err)
+			break;
 	}
-	if (ACPI_FAILURE(status))
+	if (err)
 		acpi_power_resources_list_free(list);
 
-	return status;
+	return err;
 }
 
 static int acpi_power_get_state(acpi_handle handle, int *state)
@@ -662,7 +667,7 @@ static void acpi_release_power_resource(
 	kfree(resource);
 }
 
-void acpi_add_power_resource(acpi_handle handle)
+int acpi_add_power_resource(acpi_handle handle)
 {
 	struct acpi_power_resource *resource;
 	struct acpi_device *device = NULL;
@@ -673,11 +678,11 @@ void acpi_add_power_resource(acpi_handle
 
 	acpi_bus_get_device(handle, &device);
 	if (device)
-		return;
+		return 0;
 
 	resource = kzalloc(sizeof(*resource), GFP_KERNEL);
 	if (!resource)
-		return;
+		return -ENOMEM;
 
 	device = &resource->device;
 	acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
@@ -712,10 +717,11 @@ void acpi_add_power_resource(acpi_handle
 	mutex_lock(&power_resource_list_lock);
 	list_add(&resource->list_node, &acpi_power_resource_list);
 	mutex_unlock(&power_resource_list_lock);
-	return;
+	return 0;
 
  err:
 	acpi_release_power_resource(&device->dev);
+	return result;
 }
 
 #ifdef CONFIG_ACPI_SLEEP
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -896,17 +896,17 @@ void acpi_bus_data_handler(acpi_handle h
 	return;
 }
 
-static acpi_status
-acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
-					     struct acpi_device_wakeup *wakeup)
+static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
+					struct acpi_device_wakeup *wakeup)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *package = NULL;
 	union acpi_object *element = NULL;
 	acpi_status status;
+	int err = -ENODATA;
 
 	if (!wakeup)
-		return AE_BAD_PARAMETER;
+		return -EINVAL;
 
 	INIT_LIST_HEAD(&wakeup->resources);
 
@@ -914,29 +914,25 @@ acpi_bus_extract_wakeup_device_power_pac
 	status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer);
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
-		return status;
+		return err;
 	}
 
 	package = (union acpi_object *)buffer.pointer;
 
-	if (!package || (package->package.count < 2)) {
-		status = AE_BAD_DATA;
+	if (!package || package->package.count < 2)
 		goto out;
-	}
 
 	element = &(package->package.elements[0]);
-	if (!element) {
-		status = AE_BAD_DATA;
+	if (!element)
 		goto out;
-	}
+
 	if (element->type == ACPI_TYPE_PACKAGE) {
 		if ((element->package.count < 2) ||
 		    (element->package.elements[0].type !=
 		     ACPI_TYPE_LOCAL_REFERENCE)
-		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) {
-			status = AE_BAD_DATA;
+		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER))
 			goto out;
-		}
+
 		wakeup->gpe_device =
 		    element->package.elements[0].reference.handle;
 		wakeup->gpe_number =
@@ -945,27 +941,24 @@ acpi_bus_extract_wakeup_device_power_pac
 		wakeup->gpe_device = NULL;
 		wakeup->gpe_number = element->integer.value;
 	} else {
-		status = AE_BAD_DATA;
 		goto out;
 	}
 
 	element = &(package->package.elements[1]);
-	if (element->type != ACPI_TYPE_INTEGER) {
-		status = AE_BAD_DATA;
+	if (element->type != ACPI_TYPE_INTEGER)
 		goto out;
-	}
+
 	wakeup->sleep_state = element->integer.value;
 
-	status = acpi_extract_power_resources(package, 2, &wakeup->resources);
-	if (ACPI_FAILURE(status))
+	err = acpi_extract_power_resources(package, 2, &wakeup->resources);
+	if (err)
 		goto out;
 
 	acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number);
 
  out:
 	kfree(buffer.pointer);
-
-	return status;
+	return err;
 }
 
 static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
@@ -1005,17 +998,17 @@ static void acpi_bus_get_wakeup_device_f
 {
 	acpi_handle temp;
 	acpi_status status = 0;
-	int psw_error;
+	int err;
 
 	/* Presence of _PRW indicates wake capable */
 	status = acpi_get_handle(device->handle, "_PRW", &temp);
 	if (ACPI_FAILURE(status))
 		return;
 
-	status = acpi_bus_extract_wakeup_device_power_package(device->handle,
-							      &device->wakeup);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
+	err = acpi_bus_extract_wakeup_device_power_package(device->handle,
+							   &device->wakeup);
+	if (err) {
+		dev_err(&device->dev, "_PRW evaluation error: %d\n", err);
 		return;
 	}
 
@@ -1028,8 +1021,8 @@ static void acpi_bus_get_wakeup_device_f
 	 * So it is necessary to call _DSW object first. Only when it is not
 	 * present will the _PSW object used.
 	 */
-	psw_error = acpi_device_sleep_wake(device, 0, 0, 0);
-	if (psw_error)
+	err = acpi_device_sleep_wake(device, 0, 0, 0);
+	if (err)
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				"error in _DSW or _PSW evaluation\n"));
 }
@@ -1052,9 +1045,9 @@ static void acpi_bus_init_power_state(st
 		if (buffer.length && package
 		    && package->type == ACPI_TYPE_PACKAGE
 		    && package->package.count) {
-			status = acpi_extract_power_resources(package, 0,
-							      &ps->resources);
-			if (ACPI_SUCCESS(status))
+			int err = acpi_extract_power_resources(package, 0,
+							       &ps->resources);
+			if (!err)
 				device->power.flags.power_resources = 1;
 		}
 		ACPI_FREE(buffer.pointer);


  parent reply	other threads:[~2013-01-04  0:07 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-03 23:16 [PATCH 0/12] ACPI: Rework the handling of power resources Rafael J. Wysocki
2013-01-04  0:01 ` [PATCH 1/12] ACPI / PM: Rework the handling of devices depending on " Rafael J. Wysocki
2013-01-04  0:02 ` [PATCH 2/12] ACPI / scan: More straightforward preparation of ACPI device objects Rafael J. Wysocki
2013-01-04  0:03 ` [PATCH 3/12] ACPI / scan: Treat power resources in a special way Rafael J. Wysocki
2013-01-04  0:03 ` [PATCH 4/12] ACPI: Drop power resources driver Rafael J. Wysocki
2013-01-04  0:04 ` [PATCH 5/12] ACPI: Do not use device power states of power resources Rafael J. Wysocki
2013-01-04  0:05 ` [PATCH 6/12] ACPI / PM: Take order attribute of power resources into account Rafael J. Wysocki
2013-01-04  0:06 ` [PATCH 7/12] ACPI / PM: Take order attribute of wakeup " Rafael J. Wysocki
2013-01-04  0:07 ` [PATCH 8/12] ACPI / scan: Move power state initialization to a separate routine Rafael J. Wysocki
2013-01-04  0:07 ` [PATCH 9/12] ACPI / scan: Remove unnecessary initialization of local variables Rafael J. Wysocki
2013-01-04  0:08 ` [PATCH 10/12] ACPI / scan: Consolidate extraction of power resources lists Rafael J. Wysocki
2013-01-04  0:09 ` Rafael J. Wysocki [this message]
2013-01-04  0:10 ` [PATCH 12/12] ACPI: Use system level attribute of wakeup power resources Rafael J. Wysocki
2013-01-11 21:57 ` [PATCH 0/12] ACPI: Rework the handling of " Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1384429.2N9kZZfmJU@vostro.rjw.lan \
    --to=rjw@sisk.pl \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®