Re: [RFC] platform/x86: hp-wmi: make hp_wmi_perform_query() work with certain devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Bedant,

Thank you for the update.  I applied your patch (zero_if_sup) and ran
the driver on several Zbook and Elitebook notebooks.  With exception
of getting error 0x05 once when executing HPWMI_HARDWARE_QUERY (0x04)
while loading, all other functions remain unaffected and working fine.
No other errors were reported.   I don't feel comfortable with setting
args->insize to some arbitrary value.  It will introduce more problems
that it will solve.   Patching the driver with zero_if_sup definition
is the best option to ensure support on Omen, Zbooks, and EliteBooks
alike.   BTW, I received confirmation from another community member
and also confirmed the patch resolves HPWMI_FAN GET/SET calls in an
OMEN Laptop 15-ek0xxx.  If you are ok with it, I will submit a patch
for the insize buffer size of 128 bytes and you can proceed to submit
zero_if_sup patch.

Let me know if you are ok to proceed in this manner.

Regards,

Jorge


On Tue, Jun 7, 2022 at 1:38 PM Bedant Patnaik <bedant.patnaik@xxxxxxxxx> wrote:
>
> Hello Jorge,
>
> The patch you provided fixes the insize buffer issue on an Omen 15 2020
> AMD.
>
> The zero sized Field creation issue however, still persists. I could
> not think of a better way of handling it than to check if the BIOS
> throws an error if the insize parameter != 0 and to use insize = 0 only
> if it did.
>
> I looked through the DSDT some more. It seems that all commandtypes
> (when used with the HPWMI_READ command, do not actually make use of the
> Field DAIN that is created, except for the HPWMI_FAN_SPEED_GET_QUERY
> commandtype (used with HPWMI_GM command), which seems to access the
> created Field. Since the only call to this command uses insize = sizeof
> (char) (meaning it is never called with insize = 0), I think we can get
> away with setting args->insize to some arbitrary value, say 1, if 0 is
> passed as insize, since the Field is never accessed anyway. This
> "solution" however, relies too much on the firmware.
>
> Your input is welcome. Thank you for your time.
>
> On Tue, 2022-06-07 at 13:11 -0500, Jorge Lopez wrote:
> > Dropped other participants by accident.  Please see my comments
> > below.
> >
> > The original code created an insize buffer size of 128 bytes
> > regardless if the WMI call required a smaller buffer or not.  This
> > particular behavior occurs in older BIOS and reproduced in OMEN
> > laptops.  Newer BIOS handles  buffer sizes properly and meets the
> > latest specification requirements.  This is the reason why testing
> > with a dynamically allocated buffer did not uncover any failures with
> > the test systems at hand.
> > One additional point was considered.  The purpose for introducing
> > dynamically allocated buffers was primarily to support WMI calls that
> > required buffers size bigger than 128 bytes.  The decision  was made
> > to separate those WMI calls to a separate driver and implement the
> > new
> > firmware-attribute framework.
> >
> > The current review request title is  "[PATCH] Revert "platform/x86:
> > hp-wmi: Changing bios_args.data to be dynamically allocated"
> >
> > I am testing a cleaner solution to submit instead of  reverting the
> > changes to hp_wmi_perform_query method.  The changes were made and
> > tested on business notebooks without any issues.  I will submit a new
> > patch as soon as I get the test results from a  community member who
> > owns an Omen 15 system.
> >
> > The proposed patch which I am pending test results, it is as follows
> >
> > diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-
> > wmi.c
> > index 0e9a25b56e0e..7bcfa07cc6ab 100644
> > --- a/drivers/platform/x86/hp-wmi.c
> > +++ b/drivers/platform/x86/hp-wmi.c
> > @@ -292,12 +292,14 @@ static int hp_wmi_perform_query(int query, enum
> > hp_wmi_command command,
> >   struct bios_args *args = NULL;
> >   int mid, actual_outsize, ret;
> >   size_t bios_args_size;
> > + int actual_insize;
> >
> >   mid = encode_outsize_for_pvsz(outsize);
> >   if (WARN_ON(mid < 0))
> >   return mid;
> >
> > - bios_args_size = struct_size(args, data, insize);
> > + actual_insize = max(insize, 128);
> > + bios_args_size = struct_size(args, data, actual_insize);
> >   args = kmalloc(bios_args_size, GFP_KERNEL);
> >   if (!args)
> >   return -ENOMEM;
> > -----
> >
> > This code eliminates the 0x05 error codes across the other WMI calls.
> > Unfortunately, I do not have an Omen system to complete the tests.
> >
> > zero_insize_support() seems ok for Omen platforms but don't know if
> > it
> > may cause errors on newer notebooks.  I will run the patch locally
> > and
> > will update the results.
> > Bedant if it possible, can you apply the changes described earlier
> > and
> > let me know if it fixes Omen notebook issues?
> >
> >
> > Regards,
> >
> > Jorge.
> >
> > On Tue, Jun 7, 2022 at 12:25 PM Hans de Goede <hdegoede@xxxxxxxxxx>
> > wrote:
> > >
> > > Hi,
> > >
> > > It looks like you accidentally dropped all the other folks on the
> > > Cc,
> > > please use reply-to-all. I've re-added those folks now.
> > >
> > > On 6/7/22 18:00, Jorge Lopez wrote:
> > > > Hi Hans
> > > >
> > > >
> > > > On Tue, Jun 7, 2022 at 8:35 AM Hans de Goede
> > > > <hdegoede@xxxxxxxxxx> wrote:
> > > > >
> > > > >
> > > > > Hi Bedant,
> > > > >
> > > > > Adding Jorge from HP to the To: list.
> > > > >
> > > > > On 6/7/22 15:24, Bedant Patnaik wrote:
> > > > > > 4b4967cbd2685f313411e6facf915fb2ae01d796 ("platform/x86: hp-
> > > > > > wmi: Changing bios_args.data to be dynamically...")
> > > > > > broke WMI queries on some devices where the ACPI method HWMC
> > > > > > unconditionally attempts to create Fields beyond the buffer
> > > > > > if the buffer is too small, this breaks essential features
> > > > > > such as power profiles:
> > > > > >         CreateByteField (Arg1, 0x10, D008)
> > > > > >         CreateByteField (Arg1, 0x11, D009)
> > > > > >         CreateByteField (Arg1, 0x12, D010)
> > > > > >         CreateDWordField (Arg1, 0x10, D032)
> > > > > >         CreateField (Arg1, 0x80, 0x0400, D128)
> > > > > > In cases where args->data had zero length, ACPI BIOS Error
> > > > > > (bug): AE_AML_BUFFER_LIMIT, Field [D008] at bit
> > > > > > offset/length 128/8 exceeds size of target Buffer (128 bits)
> > > > > > (20211217/dsopcode-198) was obtained.
> > > > > > Fix: allocate at least 128 bytes for args->data
> > > > > >
> > > > > > be9d73e64957bbd31ee9a0d11adc0f720974c558 ("platform/x86: hp-
> > > > > > wmi: Fix 0x05 error code reported by several WMI calls")
> > > > > > and 12b19f14a21a2ee6348825d95b642ef2cd16794f ("platform/x86:
> > > > > > hp-wmi: Fix hp_wmi_read_int() reporting error (0x05)")
> > > > > > caused ACPI BIOS Error (bug): Attempt to CreateField of
> > > > > > length zero (20211217/dsopcode-133) because of the ACPI
> > > > > > method HWMC, which unconditionally creates a Field of size
> > > > > > (insize*8) bits:
> > > > > >       CreateField (Arg1, 0x80, (Local5 * 0x08), DAIN)
> > > > > > In cases where args->insize = 0, the Field size is 0,
> > > > > > resulting in an error.
> > > > > > Fix: use zero insize only if 0x5 error code is returned
> > > > > >
> > > > > > Tested on Omen 15 AMD (2020) board ID: 8786.
> > > > >
> > > > > Thank you for looking into this. The alloc at least
> > > > > 128 bytes part for args->data looks good and likely is a better
> > > > > fix then the revert of 4b4967cbd2685f3 which Jorge has
> > > > > submitted.
> > > > >
> > > > > I'm not 100% sure about the zero_insize_support() thingie
> > > > > though.
> > > > >
> > > > > Looking at the original fix and then trying to get things
> > > > > to work on all models with some requiring insize==0 and
> > > > > otheres requiring insize!=0 I guess this also makes sense...
> > > > >
> > > > > Jorge, any remarks on this patch?
> > > > >
> > > >
> > > > The original code created an insize buffer size of 128 bytes
> > > > regardless if the WMI call required a smaller buffer or not.
> > > > This
> > > > particular behavior occurs in older BIOS and reproduced in OMEN
> > > > laptops.  Newer BIOS handles  buffer sizes properly and meets the
> > > > latest specification requirements.  This is the reason why
> > > > testing
> > > > with a dynamically allocated buffer did not uncover any failures
> > > > with
> > > > the test systems at hand.
> > > > One additional point was considered.  The purpose for introducing
> > > > dynamically allocated buffers was primarily to support WMI calls
> > > > that
> > > > required buffers size bigger than 128 bytes.  The decision  was
> > > > made
> > > > to separate those WMI calls to a separate driver and implement
> > > > the new
> > > > firmware-attribute framework.
> > > >
> > > > The current review request title is  "[PATCH] Revert
> > > > "platform/x86:
> > > > hp-wmi: Changing bios_args.data to be dynamically allocated"
> > > >
> > > > I am testing a cleaner solution to submit instead of  reverting
> > > > the
> > > > changes to hp_wmi_perform_query method.  The changes were made
> > > > and
> > > > tested on business notebooks without any issues.  I will submit a
> > > > new
> > > > patch as soon as I get the test results from a  community member
> > > > who
> > > > owns an Omen 15 system.
> > >
> > > Right, notice the RFC this thread is a reply to already contains
> > > a cleaner version and has been tested on a HP Omen laptop already.
> > >
> > > The already tested cleaner fix from this RFC is:
> > >
> > > --- a/drivers/platform/x86/hp-wmi.c
> > > +++ b/drivers/platform/x86/hp-wmi.c
> > > @@ -297,8 +299,8 @@  static int hp_wmi_perform_query(int query,
> > > enum hp_wmi_command command,
> > >         if (WARN_ON(mid < 0))
> > >                 return mid;
> > >
> > > -       bios_args_size = struct_size(args, data, insize);
> > > -       args = kmalloc(bios_args_size, GFP_KERNEL);
> > > +       bios_args_size = max(struct_size(args, data, insize),
> > > struct_size(args, data, 128));
> > > +       args = kzalloc(bios_args_size, GFP_KERNEL);
> > >         if (!args)
> > >                 return -ENOMEM;
> > >
> > >
> > > Which seems a better (more future proof) solution then your revert.
> > >
> > > Jorge, my main question from my previous email really is what you
> > > make of the zero_if_sup() changes / part of this RFC. Which are
> > > necessary because some older ACPI tables don't like it when
> > > args->insize is set to 0, which it is after your:
> > >
> > > be9d73e64957bbd31ee9a0d11adc0f720974c558 ("platform/x86: hp-wmi:
> > > Fix 0x05 error code reported by several WMI calls")
> > > 12b19f14a21a2ee6348825d95b642ef2cd16794f ("platform/x86: hp-wmi:
> > > Fix hp_wmi_read_int() reporting error (0x05)")
> > >
> > > commits. For details see the original commit msg from this RFC:
> > > https://patchwork.kernel.org/project/platform-driver-x86/patch/20220607132428.7221-1-bedant.patnaik@xxxxxxxxx/
> > >
> > > Even if we go with the revert you submitted that only fixes
> > > the passing buffers < 128 bytes issue and not this other issue.
> > >
> > > I had to take a good look at it, but after doing that I do believe
> > > that the proposed zero_if_sup() changes make sense.
> > >
> > > Bedant, can you split your original RFC into 2 patches please,
> > > one for each separate of the two (128 bytes buf-size,
> > > resp. zero_if_sup()) fixes which you are doing ?
> > >
> > > Regards,
> > >
> > > Hans
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > > >
> > > > Regards,
> > > >
> > > > Jorge.
> > > >
> > > >
> > > >
> > > > > Regards,
> > > > >
> > > > > Hans
> > > > >
> > > > > >
> > > > > > Signed-off-by: Bedant Patnaik <bedant.patnaik@xxxxxxxxx>
> > > > > > Cc: markgross@xxxxxxxxxx
> > > > > > Cc: platform-driver-x86@xxxxxxxxxxxxxxx
> > > > > >
> > > > > > ---
> > > > > >  drivers/platform/x86/hp-wmi.c | 29 ++++++++++++++++++-------
> > > > > > ----
> > > > > >  1 file changed, 18 insertions(+), 11 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/platform/x86/hp-wmi.c
> > > > > > b/drivers/platform/x86/hp-wmi.c
> > > > > > index 667f94bba..3ef385f14 100644
> > > > > > --- a/drivers/platform/x86/hp-wmi.c
> > > > > > +++ b/drivers/platform/x86/hp-wmi.c
> > > > > > @@ -38,6 +38,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-
> > > > > > 3D44E2C707E4");
> > > > > >  #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-
> > > > > > ACCDC67EF61C"
> > > > > >  #define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-
> > > > > > 3D44E2C707E4"
> > > > > >  #define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95
> > > > > > +#define zero_if_sup(tmp) (zero_insize_support?0:sizeof(tmp))
> > > > > > // use when zero insize is required
> > > > > >
> > > > > >  /* DMI board names of devices that should use the omen
> > > > > > specific path for
> > > > > >   * thermal profiles.
> > > > > > @@ -175,7 +176,7 @@ enum hp_thermal_profile_omen_v1 {
> > > > > >  enum hp_thermal_profile {
> > > > > >       HP_THERMAL_PROFILE_PERFORMANCE  = 0x00,
> > > > > >       HP_THERMAL_PROFILE_DEFAULT              = 0x01,
> > > > > > -     HP_THERMAL_PROFILE_COOL                 = 0x02
> > > > > > +     HP_THERMAL_PROFILE_COOL                 = 0x02,
> > > > > >  };
> > > > > >
> > > > > >  #define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) !=
> > > > > > HPWMI_POWER_FW_OR_HW)
> > > > > > @@ -220,6 +221,7 @@ static struct input_dev
> > > > > > *hp_wmi_input_dev;
> > > > > >  static struct platform_device *hp_wmi_platform_dev;
> > > > > >  static struct platform_profile_handler
> > > > > > platform_profile_handler;
> > > > > >  static bool platform_profile_support;
> > > > > > +static bool zero_insize_support;
> > > > > >
> > > > > >  static struct rfkill *wifi_rfkill;
> > > > > >  static struct rfkill *bluetooth_rfkill;
> > > > > > @@ -297,8 +299,8 @@ static int hp_wmi_perform_query(int
> > > > > > query, enum hp_wmi_command command,
> > > > > >       if (WARN_ON(mid < 0))
> > > > > >               return mid;
> > > > > >
> > > > > > -     bios_args_size = struct_size(args, data, insize);
> > > > > > -     args = kmalloc(bios_args_size, GFP_KERNEL);
> > > > > > +     bios_args_size = max(struct_size(args, data, insize),
> > > > > > struct_size(args, data, 128));
> > > > > > +     args = kzalloc(bios_args_size, GFP_KERNEL);
> > > > > >       if (!args)
> > > > > >               return -ENOMEM;
> > > > > >
> > > > > > @@ -374,7 +376,7 @@ static int hp_wmi_read_int(int query)
> > > > > >       int val = 0, ret;
> > > > > >
> > > > > >       ret = hp_wmi_perform_query(query, HPWMI_READ, &val,
> > > > > > -                                0, sizeof(val));
> > > > > > +                                zero_if_sup(val),
> > > > > > sizeof(val));
> > > > > >
> > > > > >       if (ret)
> > > > > >               return ret < 0 ? ret : -EINVAL;
> > > > > > @@ -410,7 +412,8 @@ static int hp_wmi_get_tablet_mode(void)
> > > > > >               return -ENODEV;
> > > > > >
> > > > > >       ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE,
> > > > > > HPWMI_READ,
> > > > > > -                                system_device_mode, 0,
> > > > > > sizeof(system_device_mode));
> > > > > > +                                system_device_mode,
> > > > > > zero_if_sup(system_device_mode),
> > > > > > +                                sizeof(system_device_mode));
> > > > > >       if (ret < 0)
> > > > > >               return ret;
> > > > > >
> > > > > > @@ -497,7 +500,7 @@ static int hp_wmi_fan_speed_max_get(void)
> > > > > >       int val = 0, ret;
> > > > > >
> > > > > >       ret =
> > > > > > hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_GET_QUERY, HPWMI_GM,
> > > > > > -                                &val, 0, sizeof(val));
> > > > > > +                                &val, zero_if_sup(val),
> > > > > > sizeof(val));
> > > > > >
> > > > > >       if (ret)
> > > > > >               return ret < 0 ? ret : -EINVAL;
> > > > > > @@ -509,7 +512,7 @@ static int __init
> > > > > > hp_wmi_bios_2008_later(void)
> > > > > >  {
> > > > > >       int state = 0;
> > > > > >       int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY,
> > > > > > HPWMI_READ, &state,
> > > > > > -                                    0, sizeof(state));
> > > > > > +                                    zero_if_sup(state),
> > > > > > sizeof(state));
> > > > > >       if (!ret)
> > > > > >               return 1;
> > > > > >
> > > > > > @@ -520,7 +523,7 @@ static int __init
> > > > > > hp_wmi_bios_2009_later(void)
> > > > > >  {
> > > > > >       u8 state[128];
> > > > > >       int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY,
> > > > > > HPWMI_READ, &state,
> > > > > > -                                    0, sizeof(state));
> > > > > > +                                    zero_if_sup(state),
> > > > > > sizeof(state));
> > > > > >       if (!ret)
> > > > > >               return 1;
> > > > > >
> > > > > > @@ -598,7 +601,7 @@ static int hp_wmi_rfkill2_refresh(void)
> > > > > >       int err, i;
> > > > > >
> > > > > >       err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY,
> > > > > > HPWMI_READ, &state,
> > > > > > -                                0, sizeof(state));
> > > > > > +                                zero_if_sup(state),
> > > > > > sizeof(state));
> > > > > >       if (err)
> > > > > >               return err;
> > > > > >
> > > > > > @@ -1007,7 +1010,7 @@ static int __init
> > > > > > hp_wmi_rfkill2_setup(struct platform_device *device)
> > > > > >       int err, i;
> > > > > >
> > > > > >       err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY,
> > > > > > HPWMI_READ, &state,
> > > > > > -                                0, sizeof(state));
> > > > > > +                                zero_if_sup(state),
> > > > > > sizeof(state));
> > > > > >       if (err)
> > > > > >               return err < 0 ? err : -EINVAL;
> > > > > >
> > > > > > @@ -1483,11 +1486,15 @@ static int __init hp_wmi_init(void)
> > > > > >  {
> > > > > >       int event_capable = wmi_has_guid(HPWMI_EVENT_GUID);
> > > > > >       int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
> > > > > > -     int err;
> > > > > > +     int err, tmp = 0;
> > > > > >
> > > > > >       if (!bios_capable && !event_capable)
> > > > > >               return -ENODEV;
> > > > > >
> > > > > > +     if (hp_wmi_perform_query(HPWMI_HARDWARE_QUERY,
> > > > > > HPWMI_READ, &tmp,
> > > > > > +                              sizeof(tmp), sizeof(tmp)) ==
> > > > > > HPWMI_RET_INVALID_PARAMETERS)
> > > > > > +             zero_insize_support = true;
> > > > > > +
> > > > > >       if (event_capable) {
> > > > > >               err = hp_wmi_input_setup();
> > > > > >               if (err)
> > > > >
> > > >
> > >
>



[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux