diff mbox

[RFC] acpi: method: refine _EVT test

Message ID 1438350264-27251-1-git-send-email-alex.hung@canonical.com
State Rejected
Headers show

Commit Message

Alex Hung July 31, 2015, 1:44 p.m. UTC
According to ACPI spec, _EVT's events should be in adjacent _AEI
control method.  This patch also reduces lengthy testing time.

This was modified from a patch from Fan Wu <wufan@codeaurora.org>
Most changes are styles, comments and some small code refactoring.

Signed-off-by: Alex Hung <alex.hung@canonical.com>
---
 src/acpi/method/method.c | 86 ++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 76 insertions(+), 10 deletions(-)

Comments

Colin Ian King July 31, 2015, 2:07 p.m. UTC | #1
On 31/07/15 14:44, Alex Hung wrote:
> According to ACPI spec, _EVT's events should be in adjacent _AEI
> control method.  This patch also reduces lengthy testing time.
> 
> This was modified from a patch from Fan Wu <wufan@codeaurora.org>
> Most changes are styles, comments and some small code refactoring.
> 
> Signed-off-by: Alex Hung <alex.hung@canonical.com>
> ---
>  src/acpi/method/method.c | 86 ++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 76 insertions(+), 10 deletions(-)
> 
> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
> index 638e937..732facc 100644
> --- a/src/acpi/method/method.c
> +++ b/src/acpi/method/method.c
> @@ -27,6 +27,7 @@
>  #include <inttypes.h>
>  #include "fwts_acpi_object_eval.h"
>  
> +
>  /*
>   * ACPI methods + objects used in Linux ACPI driver:
>   *
> @@ -958,21 +959,86 @@ static int method_test_AEI(fwts_framework *fw)
>  		"_AEI", NULL, 0, method_test_AEI_return, NULL);
>  }
>  
> -static int method_test_EVT(fwts_framework *fw)
> +static void check_evt_event (
> +	fwts_framework *fw,
> +	ACPI_RESOURCE_GPIO *gpio)
>  {
>  	ACPI_OBJECT arg[1];
> -	int ret, i;
> +	ACPI_HANDLE evtMethodHandle;
> +	ACPI_STATUS Status;
> +	char Path[256];
> +	uint16_t i;

Style wise, if we can replace Status with status and Path with path as
that is the fwts codeing style.

> +
> +	/* Skip the leading spaces in ResourceSource. */
> +	for (i = 0; i < gpio->ResourceSource.StringLength; i++) {
> +		if (gpio->ResourceSource.StringPtr[i] != ' ')
> +			break;
> +	}
>  
> -	arg[0].Type = ACPI_TYPE_INTEGER;
> -	for (i = 0; i < 65535; i++) {
> -		arg[0].Integer.Value = i;
> -		ret = method_evaluate_method(fw, METHOD_OPTIONAL,
> -			"_EVT", arg, 1, method_test_NULL_return, NULL);
> +	if (i == gpio->ResourceSource.StringLength ) {

                                                  ^
just a minor style issue, can you remove the extraneous white spaces, e.g.
			

> +		fwts_log_warning(fw, "Invalid ResourceSource");
> +		return;
> +	}
>  
> -		if (ret != FWTS_OK)
> -			break;
> +	/* Get the handle of return;the _EVT method. */
> +	sprintf (Path, "%s._EVT", &gpio->ResourceSource.StringPtr[i]);
> +
> +	Status = AcpiGetHandle (NULL, Path, &evtMethodHandle);
> +	if (ACPI_FAILURE(Status)) {
> +		fwts_log_warning(fw, "Failed to find valid handle for EVT method (0x%x), %s",	Status, Path);
..and spaces between ,   Status
> +		return;
>  	}
> -	return ret;
> +
> +	/* Call the _EVT method with all the pins defined for the GpioInt */
> +	for (i = 0; i < gpio->PinTableLength; i++) {
> +		ACPI_OBJECT_LIST  arg_list;
> +
> +		arg[0].Type = ACPI_TYPE_INTEGER;
> +		arg[0].Integer.Value = gpio->PinTable[i];
> +		arg_list.Count   = 1;
> +		arg_list.Pointer = arg;
> +
> +		method_evaluate_found_method(fw, Path, method_test_NULL_return, NULL, &arg_list);
> +	}
> +}
> +
> +static void method_test_EVT_return (
> +	fwts_framework *fw,
> +	char *name,
> +	ACPI_BUFFER *buf,
> +	ACPI_OBJECT *obj,
> +	void *private)
> +{
> +	ACPI_RESOURCE *resource;
> +	ACPI_STATUS   Status;
> +
> +	FWTS_UNUSED(buf);
> +	FWTS_UNUSED(private);
> +
> +	if (method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK)
> +		return;
> +
> +	Status = AcpiBufferToResource( obj->Buffer.Pointer, obj->Buffer.Length, &resource );

clean up white spaces ( obj-> ... resource );


> +	if (ACPI_FAILURE(Status))
> +		return;
> +
> +	do {
> +		if (!resource->Length) {
> +			fwts_log_warning(fw, "Invalid zero length descriptor in resource list\n");
> +			break;
> +		}
> +
> +		if (resource->Type == ACPI_RESOURCE_TYPE_GPIO && resource->Data.Gpio.ConnectionType == ACPI_RESOURCE_GPIO_TYPE_INT)

..this is a really long line..

> +				check_evt_event(fw, &resource->Data.Gpio);
> +
> +		resource = ACPI_NEXT_RESOURCE(resource);
> +	} while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG);
> +}
> +static int method_test_EVT(fwts_framework *fw)
> +{
> +	/* Only test the _EVT method with pins defined in AEI. */
> +	return method_evaluate_method(fw, METHOD_OPTIONAL,
> +		"_AEI", NULL, 0, method_test_EVT_return, NULL);
>  }
>  
>  /*
> 

And can you fix up the regression test now we've got a change in
functionality, I'm seeing:

make check
...
FAIL: fwts-test/method-0001/test-0001.sh
...

Apart from the minor style issues, I'm OK with the changes. I still need
to run it through coverity scan, but I'm over quota on this for fwts
this week. I'll get back and report on this on Monday, so if you can
wait until then I'll let you know if that finds any other issues.

Colin
Alex Hung July 31, 2015, 2:25 p.m. UTC | #2
There is a side-effect on this patch that I'd like to discuss (therefore
RFC in topic).

When I run "sudo make check", it shows an failure as below:

< method          _EVT.
---
> method          _AEI.

As it is the result of below:

method          Test 2 of 180: Test _AEI.
method          SKIPPED: Test 2, Skipping test for non-existant object
method          _AEI.
method
method          Test 3 of 180: Test _EVT (Event Method).
method          SKIPPED: Test 3, Skipping test for non-existant object
method          _AEI.

From function perspective, the patch works fine but it may not look
quite the same as other methods.  Does anyone have any comments?


On 07/31/2015 09:44 PM, Alex Hung wrote:
> According to ACPI spec, _EVT's events should be in adjacent _AEI
> control method.  This patch also reduces lengthy testing time.
> 
> This was modified from a patch from Fan Wu <wufan@codeaurora.org>
> Most changes are styles, comments and some small code refactoring.
> 
> Signed-off-by: Alex Hung <alex.hung@canonical.com>
> ---
>  src/acpi/method/method.c | 86 ++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 76 insertions(+), 10 deletions(-)
> 
> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
> index 638e937..732facc 100644
> --- a/src/acpi/method/method.c
> +++ b/src/acpi/method/method.c
> @@ -27,6 +27,7 @@
>  #include <inttypes.h>
>  #include "fwts_acpi_object_eval.h"
>  
> +
>  /*
>   * ACPI methods + objects used in Linux ACPI driver:
>   *
> @@ -958,21 +959,86 @@ static int method_test_AEI(fwts_framework *fw)
>  		"_AEI", NULL, 0, method_test_AEI_return, NULL);
>  }
>  
> -static int method_test_EVT(fwts_framework *fw)
> +static void check_evt_event (
> +	fwts_framework *fw,
> +	ACPI_RESOURCE_GPIO *gpio)
>  {
>  	ACPI_OBJECT arg[1];
> -	int ret, i;
> +	ACPI_HANDLE evtMethodHandle;
> +	ACPI_STATUS Status;
> +	char Path[256];
> +	uint16_t i;
> +
> +	/* Skip the leading spaces in ResourceSource. */
> +	for (i = 0; i < gpio->ResourceSource.StringLength; i++) {
> +		if (gpio->ResourceSource.StringPtr[i] != ' ')
> +			break;
> +	}
>  
> -	arg[0].Type = ACPI_TYPE_INTEGER;
> -	for (i = 0; i < 65535; i++) {
> -		arg[0].Integer.Value = i;
> -		ret = method_evaluate_method(fw, METHOD_OPTIONAL,
> -			"_EVT", arg, 1, method_test_NULL_return, NULL);
> +	if (i == gpio->ResourceSource.StringLength ) {
> +		fwts_log_warning(fw, "Invalid ResourceSource");
> +		return;
> +	}
>  
> -		if (ret != FWTS_OK)
> -			break;
> +	/* Get the handle of return;the _EVT method. */
> +	sprintf (Path, "%s._EVT", &gpio->ResourceSource.StringPtr[i]);
> +
> +	Status = AcpiGetHandle (NULL, Path, &evtMethodHandle);
> +	if (ACPI_FAILURE(Status)) {
> +		fwts_log_warning(fw, "Failed to find valid handle for EVT method (0x%x), %s",	Status, Path);
> +		return;
>  	}
> -	return ret;
> +
> +	/* Call the _EVT method with all the pins defined for the GpioInt */
> +	for (i = 0; i < gpio->PinTableLength; i++) {
> +		ACPI_OBJECT_LIST  arg_list;
> +
> +		arg[0].Type = ACPI_TYPE_INTEGER;
> +		arg[0].Integer.Value = gpio->PinTable[i];
> +		arg_list.Count   = 1;
> +		arg_list.Pointer = arg;
> +
> +		method_evaluate_found_method(fw, Path, method_test_NULL_return, NULL, &arg_list);
> +	}
> +}
> +
> +static void method_test_EVT_return (
> +	fwts_framework *fw,
> +	char *name,
> +	ACPI_BUFFER *buf,
> +	ACPI_OBJECT *obj,
> +	void *private)
> +{
> +	ACPI_RESOURCE *resource;
> +	ACPI_STATUS   Status;
> +
> +	FWTS_UNUSED(buf);
> +	FWTS_UNUSED(private);
> +
> +	if (method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK)
> +		return;
> +
> +	Status = AcpiBufferToResource( obj->Buffer.Pointer, obj->Buffer.Length, &resource );
> +	if (ACPI_FAILURE(Status))
> +		return;
> +
> +	do {
> +		if (!resource->Length) {
> +			fwts_log_warning(fw, "Invalid zero length descriptor in resource list\n");
> +			break;
> +		}
> +
> +		if (resource->Type == ACPI_RESOURCE_TYPE_GPIO && resource->Data.Gpio.ConnectionType == ACPI_RESOURCE_GPIO_TYPE_INT)
> +				check_evt_event(fw, &resource->Data.Gpio);
> +
> +		resource = ACPI_NEXT_RESOURCE(resource);
> +	} while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG);
> +}
> +static int method_test_EVT(fwts_framework *fw)
> +{
> +	/* Only test the _EVT method with pins defined in AEI. */
> +	return method_evaluate_method(fw, METHOD_OPTIONAL,
> +		"_AEI", NULL, 0, method_test_EVT_return, NULL);
>  }
>  
>  /*
>
Alex Hung July 31, 2015, 2:30 p.m. UTC | #3
Loop in two developers for discussion :).

On Fri, Jul 31, 2015 at 10:25 PM, Alex Hung <alex.hung@canonical.com> wrote:
> There is a side-effect on this patch that I'd like to discuss (therefore
> RFC in topic).
>
> When I run "sudo make check", it shows an failure as below:
>
> < method          _EVT.
> ---
>> method          _AEI.
>
> As it is the result of below:
>
> method          Test 2 of 180: Test _AEI.
> method          SKIPPED: Test 2, Skipping test for non-existant object
> method          _AEI.
> method
> method          Test 3 of 180: Test _EVT (Event Method).
> method          SKIPPED: Test 3, Skipping test for non-existant object
> method          _AEI.
>
> From function perspective, the patch works fine but it may not look
> quite the same as other methods.  Does anyone have any comments?
>
>
> On 07/31/2015 09:44 PM, Alex Hung wrote:
>> According to ACPI spec, _EVT's events should be in adjacent _AEI
>> control method.  This patch also reduces lengthy testing time.
>>
>> This was modified from a patch from Fan Wu <wufan@codeaurora.org>
>> Most changes are styles, comments and some small code refactoring.
>>
>> Signed-off-by: Alex Hung <alex.hung@canonical.com>
>> ---
>>  src/acpi/method/method.c | 86 ++++++++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 76 insertions(+), 10 deletions(-)
>>
>> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
>> index 638e937..732facc 100644
>> --- a/src/acpi/method/method.c
>> +++ b/src/acpi/method/method.c
>> @@ -27,6 +27,7 @@
>>  #include <inttypes.h>
>>  #include "fwts_acpi_object_eval.h"
>>
>> +
>>  /*
>>   * ACPI methods + objects used in Linux ACPI driver:
>>   *
>> @@ -958,21 +959,86 @@ static int method_test_AEI(fwts_framework *fw)
>>               "_AEI", NULL, 0, method_test_AEI_return, NULL);
>>  }
>>
>> -static int method_test_EVT(fwts_framework *fw)
>> +static void check_evt_event (
>> +     fwts_framework *fw,
>> +     ACPI_RESOURCE_GPIO *gpio)
>>  {
>>       ACPI_OBJECT arg[1];
>> -     int ret, i;
>> +     ACPI_HANDLE evtMethodHandle;
>> +     ACPI_STATUS Status;
>> +     char Path[256];
>> +     uint16_t i;
>> +
>> +     /* Skip the leading spaces in ResourceSource. */
>> +     for (i = 0; i < gpio->ResourceSource.StringLength; i++) {
>> +             if (gpio->ResourceSource.StringPtr[i] != ' ')
>> +                     break;
>> +     }
>>
>> -     arg[0].Type = ACPI_TYPE_INTEGER;
>> -     for (i = 0; i < 65535; i++) {
>> -             arg[0].Integer.Value = i;
>> -             ret = method_evaluate_method(fw, METHOD_OPTIONAL,
>> -                     "_EVT", arg, 1, method_test_NULL_return, NULL);
>> +     if (i == gpio->ResourceSource.StringLength ) {
>> +             fwts_log_warning(fw, "Invalid ResourceSource");
>> +             return;
>> +     }
>>
>> -             if (ret != FWTS_OK)
>> -                     break;
>> +     /* Get the handle of return;the _EVT method. */
>> +     sprintf (Path, "%s._EVT", &gpio->ResourceSource.StringPtr[i]);
>> +
>> +     Status = AcpiGetHandle (NULL, Path, &evtMethodHandle);
>> +     if (ACPI_FAILURE(Status)) {
>> +             fwts_log_warning(fw, "Failed to find valid handle for EVT method (0x%x), %s",   Status, Path);
>> +             return;
>>       }
>> -     return ret;
>> +
>> +     /* Call the _EVT method with all the pins defined for the GpioInt */
>> +     for (i = 0; i < gpio->PinTableLength; i++) {
>> +             ACPI_OBJECT_LIST  arg_list;
>> +
>> +             arg[0].Type = ACPI_TYPE_INTEGER;
>> +             arg[0].Integer.Value = gpio->PinTable[i];
>> +             arg_list.Count   = 1;
>> +             arg_list.Pointer = arg;
>> +
>> +             method_evaluate_found_method(fw, Path, method_test_NULL_return, NULL, &arg_list);
>> +     }
>> +}
>> +
>> +static void method_test_EVT_return (
>> +     fwts_framework *fw,
>> +     char *name,
>> +     ACPI_BUFFER *buf,
>> +     ACPI_OBJECT *obj,
>> +     void *private)
>> +{
>> +     ACPI_RESOURCE *resource;
>> +     ACPI_STATUS   Status;
>> +
>> +     FWTS_UNUSED(buf);
>> +     FWTS_UNUSED(private);
>> +
>> +     if (method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK)
>> +             return;
>> +
>> +     Status = AcpiBufferToResource( obj->Buffer.Pointer, obj->Buffer.Length, &resource );
>> +     if (ACPI_FAILURE(Status))
>> +             return;
>> +
>> +     do {
>> +             if (!resource->Length) {
>> +                     fwts_log_warning(fw, "Invalid zero length descriptor in resource list\n");
>> +                     break;
>> +             }
>> +
>> +             if (resource->Type == ACPI_RESOURCE_TYPE_GPIO && resource->Data.Gpio.ConnectionType == ACPI_RESOURCE_GPIO_TYPE_INT)
>> +                             check_evt_event(fw, &resource->Data.Gpio);
>> +
>> +             resource = ACPI_NEXT_RESOURCE(resource);
>> +     } while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG);
>> +}
>> +static int method_test_EVT(fwts_framework *fw)
>> +{
>> +     /* Only test the _EVT method with pins defined in AEI. */
>> +     return method_evaluate_method(fw, METHOD_OPTIONAL,
>> +             "_AEI", NULL, 0, method_test_EVT_return, NULL);
>>  }
>>
>>  /*
>>
>
>
> --
> Cheers,
> Alex Hung
Colin Ian King July 31, 2015, 2:38 p.m. UTC | #4
On 31/07/15 15:25, Alex Hung wrote:
> There is a side-effect on this patch that I'd like to discuss (therefore
> RFC in topic).
> 
> When I run "sudo make check", it shows an failure as below:
> 
> < method          _EVT.
> ---
>> method          _AEI.
> 
> As it is the result of below:
> 
> method          Test 2 of 180: Test _AEI.
> method          SKIPPED: Test 2, Skipping test for non-existant object
> method          _AEI.
> method
> method          Test 3 of 180: Test _EVT (Event Method).
> method          SKIPPED: Test 3, Skipping test for non-existant object
> method          _AEI.
> 
> From function perspective, the patch works fine but it may not look
> quite the same as other methods.  Does anyone have any comments?

The skipping message is a bit confusing. One way around this is to add
an extra bit to the test_type flag in method_evaluate_method() so we can
decided to print messages or not, e.g.

#define METHOD_SILENT           8

...

and in method_evaluate_method() do:

	if (!(test_type & METHOD_SILENT)) {
                /* Manditory not-found test are a failure */
                if (test_type & METHOD_MANDITORY) {
                        fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodNotExist",
                                "Object %s did not exist.", name);
                }

                /* Mobile specific tests on non-mobile platform? */
                if ((test_type & METHOD_MOBILE) &&
(!fadt_mobile_platform)) {
                        fwts_skipped(fw,
                                "Machine is not a mobile platform,
skipping "
                                "test for non-existant mobile platform "
                                "related object %s.", name);
                } else {
                        fwts_skipped(fw,
                                "Skipping test for non-existant object %s.",
                                name);
                }
	}
	return FWTS_NOT_EXIST;

and in then:

static int method_test_EVT(fwts_framework *fw)
{
	int ret;

        /* Only test the _EVT method with pins defined in AEI. */
        ret = method_evaluate_method(fw, METHOD_OPTIONAL |
METHOD_SILENT, "_AEI", NULL, 0, method_test_EVT_return, NULL);

	if (ret == FWTS_NOT_EXIST)
		fwts_skipped(fw,
                      "Skipping test for non-existant object %s.",name);

	return ret;
}

Perhaps that's the simplest way forward.

> 
> 
> On 07/31/2015 09:44 PM, Alex Hung wrote:
>> According to ACPI spec, _EVT's events should be in adjacent _AEI
>> control method.  This patch also reduces lengthy testing time.
>>
>> This was modified from a patch from Fan Wu <wufan@codeaurora.org>
>> Most changes are styles, comments and some small code refactoring.
>>
>> Signed-off-by: Alex Hung <alex.hung@canonical.com>
>> ---
>>  src/acpi/method/method.c | 86 ++++++++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 76 insertions(+), 10 deletions(-)
>>
>> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
>> index 638e937..732facc 100644
>> --- a/src/acpi/method/method.c
>> +++ b/src/acpi/method/method.c
>> @@ -27,6 +27,7 @@
>>  #include <inttypes.h>
>>  #include "fwts_acpi_object_eval.h"
>>  
>> +
>>  /*
>>   * ACPI methods + objects used in Linux ACPI driver:
>>   *
>> @@ -958,21 +959,86 @@ static int method_test_AEI(fwts_framework *fw)
>>  		"_AEI", NULL, 0, method_test_AEI_return, NULL);
>>  }
>>  
>> -static int method_test_EVT(fwts_framework *fw)
>> +static void check_evt_event (
>> +	fwts_framework *fw,
>> +	ACPI_RESOURCE_GPIO *gpio)
>>  {
>>  	ACPI_OBJECT arg[1];
>> -	int ret, i;
>> +	ACPI_HANDLE evtMethodHandle;
>> +	ACPI_STATUS Status;
>> +	char Path[256];
>> +	uint16_t i;
>> +
>> +	/* Skip the leading spaces in ResourceSource. */
>> +	for (i = 0; i < gpio->ResourceSource.StringLength; i++) {
>> +		if (gpio->ResourceSource.StringPtr[i] != ' ')
>> +			break;
>> +	}
>>  
>> -	arg[0].Type = ACPI_TYPE_INTEGER;
>> -	for (i = 0; i < 65535; i++) {
>> -		arg[0].Integer.Value = i;
>> -		ret = method_evaluate_method(fw, METHOD_OPTIONAL,
>> -			"_EVT", arg, 1, method_test_NULL_return, NULL);
>> +	if (i == gpio->ResourceSource.StringLength ) {
>> +		fwts_log_warning(fw, "Invalid ResourceSource");
>> +		return;
>> +	}
>>  
>> -		if (ret != FWTS_OK)
>> -			break;
>> +	/* Get the handle of return;the _EVT method. */
>> +	sprintf (Path, "%s._EVT", &gpio->ResourceSource.StringPtr[i]);
>> +
>> +	Status = AcpiGetHandle (NULL, Path, &evtMethodHandle);
>> +	if (ACPI_FAILURE(Status)) {
>> +		fwts_log_warning(fw, "Failed to find valid handle for EVT method (0x%x), %s",	Status, Path);
>> +		return;
>>  	}
>> -	return ret;
>> +
>> +	/* Call the _EVT method with all the pins defined for the GpioInt */
>> +	for (i = 0; i < gpio->PinTableLength; i++) {
>> +		ACPI_OBJECT_LIST  arg_list;
>> +
>> +		arg[0].Type = ACPI_TYPE_INTEGER;
>> +		arg[0].Integer.Value = gpio->PinTable[i];
>> +		arg_list.Count   = 1;
>> +		arg_list.Pointer = arg;
>> +
>> +		method_evaluate_found_method(fw, Path, method_test_NULL_return, NULL, &arg_list);
>> +	}
>> +}
>> +
>> +static void method_test_EVT_return (
>> +	fwts_framework *fw,
>> +	char *name,
>> +	ACPI_BUFFER *buf,
>> +	ACPI_OBJECT *obj,
>> +	void *private)
>> +{
>> +	ACPI_RESOURCE *resource;
>> +	ACPI_STATUS   Status;
>> +
>> +	FWTS_UNUSED(buf);
>> +	FWTS_UNUSED(private);
>> +
>> +	if (method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK)
>> +		return;
>> +
>> +	Status = AcpiBufferToResource( obj->Buffer.Pointer, obj->Buffer.Length, &resource );
>> +	if (ACPI_FAILURE(Status))
>> +		return;
>> +
>> +	do {
>> +		if (!resource->Length) {
>> +			fwts_log_warning(fw, "Invalid zero length descriptor in resource list\n");
>> +			break;
>> +		}
>> +
>> +		if (resource->Type == ACPI_RESOURCE_TYPE_GPIO && resource->Data.Gpio.ConnectionType == ACPI_RESOURCE_GPIO_TYPE_INT)
>> +				check_evt_event(fw, &resource->Data.Gpio);
>> +
>> +		resource = ACPI_NEXT_RESOURCE(resource);
>> +	} while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG);
>> +}
>> +static int method_test_EVT(fwts_framework *fw)
>> +{
>> +	/* Only test the _EVT method with pins defined in AEI. */
>> +	return method_evaluate_method(fw, METHOD_OPTIONAL,
>> +		"_AEI", NULL, 0, method_test_EVT_return, NULL);
>>  }
>>  
>>  /*
>>
> 
>
Colin Ian King July 31, 2015, 2:39 p.m. UTC | #5
On 31/07/15 14:44, Alex Hung wrote:
> According to ACPI spec, _EVT's events should be in adjacent _AEI
> control method.  This patch also reduces lengthy testing time.
> 
> This was modified from a patch from Fan Wu <wufan@codeaurora.org>
> Most changes are styles, comments and some small code refactoring.
> 
> Signed-off-by: Alex Hung <alex.hung@canonical.com>
> ---
>  src/acpi/method/method.c | 86 ++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 76 insertions(+), 10 deletions(-)
> 
> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
> index 638e937..732facc 100644
> --- a/src/acpi/method/method.c
> +++ b/src/acpi/method/method.c
> @@ -27,6 +27,7 @@
>  #include <inttypes.h>
>  #include "fwts_acpi_object_eval.h"
>  
> +
>  /*
>   * ACPI methods + objects used in Linux ACPI driver:
>   *
> @@ -958,21 +959,86 @@ static int method_test_AEI(fwts_framework *fw)
>  		"_AEI", NULL, 0, method_test_AEI_return, NULL);
>  }
>  
> -static int method_test_EVT(fwts_framework *fw)
> +static void check_evt_event (
> +	fwts_framework *fw,
> +	ACPI_RESOURCE_GPIO *gpio)
>  {
>  	ACPI_OBJECT arg[1];
> -	int ret, i;
> +	ACPI_HANDLE evtMethodHandle;
> +	ACPI_STATUS Status;
> +	char Path[256];
> +	uint16_t i;
> +
> +	/* Skip the leading spaces in ResourceSource. */
> +	for (i = 0; i < gpio->ResourceSource.StringLength; i++) {
> +		if (gpio->ResourceSource.StringPtr[i] != ' ')
> +			break;
> +	}
>  
> -	arg[0].Type = ACPI_TYPE_INTEGER;
> -	for (i = 0; i < 65535; i++) {
> -		arg[0].Integer.Value = i;
> -		ret = method_evaluate_method(fw, METHOD_OPTIONAL,
> -			"_EVT", arg, 1, method_test_NULL_return, NULL);
> +	if (i == gpio->ResourceSource.StringLength ) {
> +		fwts_log_warning(fw, "Invalid ResourceSource");
> +		return;
> +	}
>  
> -		if (ret != FWTS_OK)
> -			break;
> +	/* Get the handle of return;the _EVT method. */
> +	sprintf (Path, "%s._EVT", &gpio->ResourceSource.StringPtr[i]);

snprintf() should always used instead of sprintf() to ensure we don't
get buffer overruns.

> +
> +	Status = AcpiGetHandle (NULL, Path, &evtMethodHandle);
> +	if (ACPI_FAILURE(Status)) {
> +		fwts_log_warning(fw, "Failed to find valid handle for EVT method (0x%x), %s",	Status, Path);
> +		return;
>  	}
> -	return ret;
> +
> +	/* Call the _EVT method with all the pins defined for the GpioInt */
> +	for (i = 0; i < gpio->PinTableLength; i++) {
> +		ACPI_OBJECT_LIST  arg_list;
> +
> +		arg[0].Type = ACPI_TYPE_INTEGER;
> +		arg[0].Integer.Value = gpio->PinTable[i];
> +		arg_list.Count   = 1;
> +		arg_list.Pointer = arg;
> +
> +		method_evaluate_found_method(fw, Path, method_test_NULL_return, NULL, &arg_list);
> +	}
> +}
> +
> +static void method_test_EVT_return (
> +	fwts_framework *fw,
> +	char *name,
> +	ACPI_BUFFER *buf,
> +	ACPI_OBJECT *obj,
> +	void *private)
> +{
> +	ACPI_RESOURCE *resource;
> +	ACPI_STATUS   Status;
> +
> +	FWTS_UNUSED(buf);
> +	FWTS_UNUSED(private);
> +
> +	if (method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK)
> +		return;
> +
> +	Status = AcpiBufferToResource( obj->Buffer.Pointer, obj->Buffer.Length, &resource );
> +	if (ACPI_FAILURE(Status))
> +		return;
> +
> +	do {
> +		if (!resource->Length) {
> +			fwts_log_warning(fw, "Invalid zero length descriptor in resource list\n");
> +			break;
> +		}
> +
> +		if (resource->Type == ACPI_RESOURCE_TYPE_GPIO && resource->Data.Gpio.ConnectionType == ACPI_RESOURCE_GPIO_TYPE_INT)
> +				check_evt_event(fw, &resource->Data.Gpio);
> +
> +		resource = ACPI_NEXT_RESOURCE(resource);
> +	} while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG);
> +}
> +static int method_test_EVT(fwts_framework *fw)
> +{
> +	/* Only test the _EVT method with pins defined in AEI. */
> +	return method_evaluate_method(fw, METHOD_OPTIONAL,
> +		"_AEI", NULL, 0, method_test_EVT_return, NULL);
>  }
>  
>  /*
>
diff mbox

Patch

diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
index 638e937..732facc 100644
--- a/src/acpi/method/method.c
+++ b/src/acpi/method/method.c
@@ -27,6 +27,7 @@ 
 #include <inttypes.h>
 #include "fwts_acpi_object_eval.h"
 
+
 /*
  * ACPI methods + objects used in Linux ACPI driver:
  *
@@ -958,21 +959,86 @@  static int method_test_AEI(fwts_framework *fw)
 		"_AEI", NULL, 0, method_test_AEI_return, NULL);
 }
 
-static int method_test_EVT(fwts_framework *fw)
+static void check_evt_event (
+	fwts_framework *fw,
+	ACPI_RESOURCE_GPIO *gpio)
 {
 	ACPI_OBJECT arg[1];
-	int ret, i;
+	ACPI_HANDLE evtMethodHandle;
+	ACPI_STATUS Status;
+	char Path[256];
+	uint16_t i;
+
+	/* Skip the leading spaces in ResourceSource. */
+	for (i = 0; i < gpio->ResourceSource.StringLength; i++) {
+		if (gpio->ResourceSource.StringPtr[i] != ' ')
+			break;
+	}
 
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	for (i = 0; i < 65535; i++) {
-		arg[0].Integer.Value = i;
-		ret = method_evaluate_method(fw, METHOD_OPTIONAL,
-			"_EVT", arg, 1, method_test_NULL_return, NULL);
+	if (i == gpio->ResourceSource.StringLength ) {
+		fwts_log_warning(fw, "Invalid ResourceSource");
+		return;
+	}
 
-		if (ret != FWTS_OK)
-			break;
+	/* Get the handle of return;the _EVT method. */
+	sprintf (Path, "%s._EVT", &gpio->ResourceSource.StringPtr[i]);
+
+	Status = AcpiGetHandle (NULL, Path, &evtMethodHandle);
+	if (ACPI_FAILURE(Status)) {
+		fwts_log_warning(fw, "Failed to find valid handle for EVT method (0x%x), %s",	Status, Path);
+		return;
 	}
-	return ret;
+
+	/* Call the _EVT method with all the pins defined for the GpioInt */
+	for (i = 0; i < gpio->PinTableLength; i++) {
+		ACPI_OBJECT_LIST  arg_list;
+
+		arg[0].Type = ACPI_TYPE_INTEGER;
+		arg[0].Integer.Value = gpio->PinTable[i];
+		arg_list.Count   = 1;
+		arg_list.Pointer = arg;
+
+		method_evaluate_found_method(fw, Path, method_test_NULL_return, NULL, &arg_list);
+	}
+}
+
+static void method_test_EVT_return (
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
+{
+	ACPI_RESOURCE *resource;
+	ACPI_STATUS   Status;
+
+	FWTS_UNUSED(buf);
+	FWTS_UNUSED(private);
+
+	if (method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK)
+		return;
+
+	Status = AcpiBufferToResource( obj->Buffer.Pointer, obj->Buffer.Length, &resource );
+	if (ACPI_FAILURE(Status))
+		return;
+
+	do {
+		if (!resource->Length) {
+			fwts_log_warning(fw, "Invalid zero length descriptor in resource list\n");
+			break;
+		}
+
+		if (resource->Type == ACPI_RESOURCE_TYPE_GPIO && resource->Data.Gpio.ConnectionType == ACPI_RESOURCE_GPIO_TYPE_INT)
+				check_evt_event(fw, &resource->Data.Gpio);
+
+		resource = ACPI_NEXT_RESOURCE(resource);
+	} while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG);
+}
+static int method_test_EVT(fwts_framework *fw)
+{
+	/* Only test the _EVT method with pins defined in AEI. */
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_AEI", NULL, 0, method_test_EVT_return, NULL);
 }
 
 /*