Commit fbcb4a57 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Andy Shevchenko

platform/x86: hp-wmi: Correctly determine method id in WMI calls

The WMI queries are performed by evaluating the WMPV() method from ACPI
DSDT tables, and it takes three arguments: instance index, method id and
input data (buffer).

Currently the method id is hard-coded to 0x3 in hp_wmi_perform_query()
which means that it will perform WMI calls that expect an output data of
size 0x80 (128). The output size is usually OK for the WMI queries we
perform, however it would be better to pick the correct one before
evaluating the WMI method.

Which correct method id to choose can be figured out by looking at the
following ASL code from WVPI() method:

...
Name (PVSZ, Package (0x05)
            {
            Zero,
            0x04,
            0x80,
            0x0400,
            0x1000
            })
Store (Zero, Local0)
If (LAnd (LGreaterEqual (Arg1, One), LLessEqual (Arg1, 0x05)))
{
    Store (DerefOf (Index (PVSZ, Subtract (Arg1, One))), Local0)
}
...

Arg1 is the method id and PVSZ is the package used to index the
corresponding output size; 1 -> 0, 2 -> 4, 3 -> 128, 4 -> 1024, 5 ->
4096.

This patch maps the output size passed in hp_wmi_perform_query() to the
correct method id before evaluating the WMI method.
Signed-off-by: default avatarPaulo Alcantara <pcacjr@zytor.com>
Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
parent c801603e
...@@ -188,6 +188,22 @@ struct rfkill2_device { ...@@ -188,6 +188,22 @@ struct rfkill2_device {
static int rfkill2_count; static int rfkill2_count;
static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
/* map output size to the corresponding WMI method id */
static inline int encode_outsize_for_pvsz(int outsize)
{
if (outsize > 4096)
return -EINVAL;
if (outsize > 1024)
return 5;
if (outsize > 128)
return 4;
if (outsize > 4)
return 3;
if (outsize > 0)
return 2;
return 1;
}
/* /*
* hp_wmi_perform_query * hp_wmi_perform_query
* *
...@@ -211,6 +227,7 @@ static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; ...@@ -211,6 +227,7 @@ static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
static int hp_wmi_perform_query(int query, enum hp_wmi_command command, static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
void *buffer, int insize, int outsize) void *buffer, int insize, int outsize)
{ {
int mid;
struct bios_return *bios_return; struct bios_return *bios_return;
int actual_outsize; int actual_outsize;
union acpi_object *obj; union acpi_object *obj;
...@@ -225,11 +242,15 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, ...@@ -225,11 +242,15 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
int ret = 0; int ret = 0;
mid = encode_outsize_for_pvsz(outsize);
if (WARN_ON(mid < 0))
return mid;
if (WARN_ON(insize > sizeof(args.data))) if (WARN_ON(insize > sizeof(args.data)))
return -EINVAL; return -EINVAL;
memcpy(&args.data, buffer, insize); memcpy(&args.data, buffer, insize);
wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output); wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
obj = output.pointer; obj = output.pointer;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment