diff mbox series

[V3] acpi/method: check _PS3 exists when _PS0 is present

Message ID 20200427230548.280929-1-alex.hung@canonical.com
State Accepted
Headers show
Series [V3] acpi/method: check _PS3 exists when _PS0 is present | expand

Commit Message

Alex Hung April 27, 2020, 11:05 p.m. UTC
7.3 Device Power Management Objects in ACPI spec requires methods for
setting devices to D0 and D3 to be present at least when _PSx or _PRx
is supported.

Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Alex Hung <alex.hung@canonical.com>
---

[V2] fix incorrect alignment in comments
[V3] change strcpy to strdup

 src/acpi/method/method.c | 51 +++++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 21 deletions(-)

Comments

Colin Ian King April 27, 2020, 11:13 p.m. UTC | #1
On 28/04/2020 00:05, Alex Hung wrote:
> 7.3 Device Power Management Objects in ACPI spec requires methods for
> setting devices to D0 and D3 to be present at least when _PSx or _PRx
> is supported.
> 
> Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
> Signed-off-by: Alex Hung <alex.hung@canonical.com>
> ---
> 
> [V2] fix incorrect alignment in comments
> [V3] change strcpy to strdup
> 
>  src/acpi/method/method.c | 51 +++++++++++++++++++++++-----------------
>  1 file changed, 30 insertions(+), 21 deletions(-)
> 
> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
> index 48001d7b..d903b994 100644
> --- a/src/acpi/method/method.c
> +++ b/src/acpi/method/method.c
> @@ -1535,34 +1535,43 @@ static int method_test_PRW(fwts_framework *fw)
>  		"_PRW", NULL, 0, method_test_PRW_return, NULL);
>  }
>  
> -static int method_test_PS0(fwts_framework *fw)
> +static void method_test_PS0_return(
> +	fwts_framework *fw,
> +	char *name,
> +	ACPI_BUFFER *buf,
> +	ACPI_OBJECT *obj,
> +	void *private)
>  {
> -	/*
> -	 *  iASL (ACPICA commit 6922796cfdfca041fdb96dc9e3918cbc7f43d830)
> -	 *  checks that one of _PS1, _PS2, _PS3 must exist if _PS0 exists.
> -	 */
> -	if (fwts_acpi_object_exists("_PS0") != NULL) {
> -		bool ok = false;
> -		int i;
> +	ACPI_HANDLE handle;
> +	ACPI_STATUS status;
> +	char *ps3path;
>  
> -		for (i = 1; i < 4; i++) {
> -			char name[6];
> +	/* Check _PS3 according to ACPI spec:
> +	 * If any ACPI Object that controls power (_PSx or _PRx, where x = 0, 1, 2,
> +	 * or 3) exists, then methods to set the device into D0 and D3 device
> +	 * states (at least) must be present.
> +	 */
> +	ps3path = (char*) strdup(name);
> +	if (ps3path) {
> +		strcpy(ps3path, name);
> +		ps3path[strlen(name) - 1] = '3';
>  
> -			snprintf(name, sizeof(name), "_PS%1d", i);
> -			if (fwts_acpi_object_exists(name) != NULL) {
> -				ok = true;
> -				break;
> -			}
> -		}
> -		if (!ok) {
> +		status = AcpiGetHandle(NULL, ps3path, &handle);
> +		if (status == AE_NOT_FOUND) {
>  			fwts_failed(fw, LOG_LEVEL_HIGH, "Method_PS0",
> -				"_PS0 requires that one of the _PS1, _PS2, _PS3 "
> -				"control methods must also exist, however, "
> -				"none were found.");
> +			"%s requires _PS3 control methods but "
> +			"it was not found.", name);
>  		}
> +		free(ps3path);
>  	}
> +
> +	fwts_method_test_NULL_return(fw, name, buf, obj, private);
> +}
> +
> +static int method_test_PS0(fwts_framework *fw)
> +{
>  	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PS0",
> -		 NULL, 0, fwts_method_test_NULL_return, "_PS0");
> +		NULL, 0, method_test_PS0_return, NULL);
>  }
>  
>  static int method_test_PS1(fwts_framework *fw)
> 

Acked-by: Colin Ian King <colin.king@canonical.com>
Ivan Hu April 30, 2020, 7:16 a.m. UTC | #2
On 4/28/20 7:05 AM, Alex Hung wrote:
> 7.3 Device Power Management Objects in ACPI spec requires methods for
> setting devices to D0 and D3 to be present at least when _PSx or _PRx
> is supported.
> 
> Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
> Signed-off-by: Alex Hung <alex.hung@canonical.com>
> ---
> 
> [V2] fix incorrect alignment in comments
> [V3] change strcpy to strdup
> 
>  src/acpi/method/method.c | 51 +++++++++++++++++++++++-----------------
>  1 file changed, 30 insertions(+), 21 deletions(-)
> 
> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
> index 48001d7b..d903b994 100644
> --- a/src/acpi/method/method.c
> +++ b/src/acpi/method/method.c
> @@ -1535,34 +1535,43 @@ static int method_test_PRW(fwts_framework *fw)
>  		"_PRW", NULL, 0, method_test_PRW_return, NULL);
>  }
>  
> -static int method_test_PS0(fwts_framework *fw)
> +static void method_test_PS0_return(
> +	fwts_framework *fw,
> +	char *name,
> +	ACPI_BUFFER *buf,
> +	ACPI_OBJECT *obj,
> +	void *private)
>  {
> -	/*
> -	 *  iASL (ACPICA commit 6922796cfdfca041fdb96dc9e3918cbc7f43d830)
> -	 *  checks that one of _PS1, _PS2, _PS3 must exist if _PS0 exists.
> -	 */
> -	if (fwts_acpi_object_exists("_PS0") != NULL) {
> -		bool ok = false;
> -		int i;
> +	ACPI_HANDLE handle;
> +	ACPI_STATUS status;
> +	char *ps3path;
>  
> -		for (i = 1; i < 4; i++) {
> -			char name[6];
> +	/* Check _PS3 according to ACPI spec:
> +	 * If any ACPI Object that controls power (_PSx or _PRx, where x = 0, 1, 2,
> +	 * or 3) exists, then methods to set the device into D0 and D3 device
> +	 * states (at least) must be present.
> +	 */
> +	ps3path = (char*) strdup(name);
> +	if (ps3path) {
> +		strcpy(ps3path, name);
> +		ps3path[strlen(name) - 1] = '3';
>  
> -			snprintf(name, sizeof(name), "_PS%1d", i);
> -			if (fwts_acpi_object_exists(name) != NULL) {
> -				ok = true;
> -				break;
> -			}
> -		}
> -		if (!ok) {
> +		status = AcpiGetHandle(NULL, ps3path, &handle);
> +		if (status == AE_NOT_FOUND) {
>  			fwts_failed(fw, LOG_LEVEL_HIGH, "Method_PS0",
> -				"_PS0 requires that one of the _PS1, _PS2, _PS3 "
> -				"control methods must also exist, however, "
> -				"none were found.");
> +			"%s requires _PS3 control methods but "
> +			"it was not found.", name);
>  		}
> +		free(ps3path);
>  	}
> +
> +	fwts_method_test_NULL_return(fw, name, buf, obj, private);
> +}
> +
> +static int method_test_PS0(fwts_framework *fw)
> +{
>  	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PS0",
> -		 NULL, 0, fwts_method_test_NULL_return, "_PS0");
> +		NULL, 0, method_test_PS0_return, NULL);
>  }
>  
>  static int method_test_PS1(fwts_framework *fw)
> 

Acked-by: Ivan Hu <ivan.hu@canonical.com>
diff mbox series

Patch

diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
index 48001d7b..d903b994 100644
--- a/src/acpi/method/method.c
+++ b/src/acpi/method/method.c
@@ -1535,34 +1535,43 @@  static int method_test_PRW(fwts_framework *fw)
 		"_PRW", NULL, 0, method_test_PRW_return, NULL);
 }
 
-static int method_test_PS0(fwts_framework *fw)
+static void method_test_PS0_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
-	/*
-	 *  iASL (ACPICA commit 6922796cfdfca041fdb96dc9e3918cbc7f43d830)
-	 *  checks that one of _PS1, _PS2, _PS3 must exist if _PS0 exists.
-	 */
-	if (fwts_acpi_object_exists("_PS0") != NULL) {
-		bool ok = false;
-		int i;
+	ACPI_HANDLE handle;
+	ACPI_STATUS status;
+	char *ps3path;
 
-		for (i = 1; i < 4; i++) {
-			char name[6];
+	/* Check _PS3 according to ACPI spec:
+	 * If any ACPI Object that controls power (_PSx or _PRx, where x = 0, 1, 2,
+	 * or 3) exists, then methods to set the device into D0 and D3 device
+	 * states (at least) must be present.
+	 */
+	ps3path = (char*) strdup(name);
+	if (ps3path) {
+		strcpy(ps3path, name);
+		ps3path[strlen(name) - 1] = '3';
 
-			snprintf(name, sizeof(name), "_PS%1d", i);
-			if (fwts_acpi_object_exists(name) != NULL) {
-				ok = true;
-				break;
-			}
-		}
-		if (!ok) {
+		status = AcpiGetHandle(NULL, ps3path, &handle);
+		if (status == AE_NOT_FOUND) {
 			fwts_failed(fw, LOG_LEVEL_HIGH, "Method_PS0",
-				"_PS0 requires that one of the _PS1, _PS2, _PS3 "
-				"control methods must also exist, however, "
-				"none were found.");
+			"%s requires _PS3 control methods but "
+			"it was not found.", name);
 		}
+		free(ps3path);
 	}
+
+	fwts_method_test_NULL_return(fw, name, buf, obj, private);
+}
+
+static int method_test_PS0(fwts_framework *fw)
+{
 	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PS0",
-		 NULL, 0, fwts_method_test_NULL_return, "_PS0");
+		NULL, 0, method_test_PS0_return, NULL);
 }
 
 static int method_test_PS1(fwts_framework *fw)