Re: [PATCH] platform/x86: huawei-wmi: add ACPI fallback for Fn-lock on newer models
From: Superstes
Date: Mon Jun 22 2026 - 05:43:59 EST
Hi Ilpo,
Just wanted to check on the status of the ACPI Fn-lock patch for newer
Huawei models (v3 posted on 2026-05-25).
Has there been any feedback or blockers I should address?
Thanks for your time!
вт, 26 мая 2026 г. в 14:09, Superstes <2minesweeper2@xxxxxxxxx>:
>
> >> Do you mean you'd want to serialize .probe()s of those devices?
> I don't really know how to fix this by now, I think serializing i2c
> devices initialization can help.
> It should be well tested(booting, waking from sleep\hibernation) to
> confirm that just serializing works, maybe other workarounds should be
> used.
>
> вт, 26 мая 2026 г. в 13:58, Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx>:
> >
> > On Tue, 26 May 2026, Superstes wrote:
> >
> > > >> Thank you for working on this. Could you open an issue and/or send a PR
> > > to https://github.com/aymanbagabas/Huawei-WMI ?
> > > Yes, I can send PR in the next two-three days.
> > > >> This is very specific to the FLMH-XX model. Can you confirm this is the case for
> > > other newer models?No, it is the latest model in the Matebook 14 series, I've just
> > > bought it recently and faced multiple issues, which I try to resolve. I can't found
> > > any information about that issues from another users, but i think that it can be
> > > related with other recent laptop based on Intel Core Ultra processors, it will be
> > > good to have someone with following models:
> > > MateBook Fold (2025)
> > > MateBook X Pro (2024)
> > > MateBook GT 14 (2024)
> > > MateBook D 14 (2024)
> > > >> Wouldn't it be better to put this behavior behind a quirk instead of enforcing it
> > > on the whole module?
> > > I haven't found a better place to make such changes. But you can suggest something.
> > > But I think that my workaround is safe because it calls very specific ACPI objects
> > > and uses default fallbacks.
> > >
> > > By the way, maybe You, or Ilpo knows a good place to implement board specific i2c
> > > acpi fixes? It Looks like there is a race condition situation which leads to
> > > arbitration loss when kernel tries to initialize multiple devices on the i2c bus. To
> > > fix this I've disabled light sensor and made systemd service to remove and enable
> > > the i2c_hid_acpi module, but I haven't found a place where to implement a quirk that
> > > fixes that issue.
> >
> > Do you mean you'd want to serialize .probe()s of those devices?
> >
> > --
> > i.
> >
> > > пн, 25 мая 2026 г. в 23:38, Ayman Bagabas <ayman.bagabas@xxxxxxxxx>:
> > > >
> > > > Newer Huawei laptops (e.g. FLMH-XX / MateBook 14 2024) no longer
> > > support
> > > > the legacy WMI interface for Fn-lock control. Instead, they expose
> > > direct
> > > > ACPI methods \GFRS and \SFRS (Get/Set Fn key Reversal Status) which
> > > > communicate with the EC via registers 0x6B (read) and 0x6C (write).
> > > >
> > > > Add huawei_acpi_fn_lock_get() and huawei_acpi_fn_lock_set() helpers
> > > that
> > > > use acpi_evaluate_object() to call these methods. Both
> > > > huawei_wmi_fn_lock_get() and huawei_wmi_fn_lock_set() now probe for
> > > > \GFRS/\SFRS via acpi_has_method() first and fall back to the legacy WMI
> > > > path if not present.
> > >
> > > Thank you for working on this. Could you open an issue and/or send a PR
> > > to https://github.com/aymanbagabas/Huawei-WMI ?
> > >
> > > >
> > > > Tested on: HUAWEI FLMH-XX (MateBook 14 2024),
> > > > CachyOS (kernel 7.0.9-1-cachyos).
> > > >
> > > > Signed-off-by: Shaposhnikov Daniil <2minesweeper2@xxxxxxxxx>
> > > > ---
> > > > drivers/platform/x86/huawei-wmi.c | 95 +++++++++++++++++++++++++++++++
> > > > 1 file changed, 95 insertions(+)
> > > >
> > > > diff --git a/drivers/platform/x86/huawei-wmi.c
> > > b/drivers/platform/x86/huawei-wmi.c
> > > > index 93cca17fdf58..19cd8f1a8e33 100644
> > > > --- a/drivers/platform/x86/huawei-wmi.c
> > > > +++ b/drivers/platform/x86/huawei-wmi.c
> > > > @@ -527,11 +527,101 @@ static void huawei_wmi_battery_exit(struct
> > > device *dev)
> > > >
> > > > /* Fn lock */
> > > >
> > > > +/*
> > > > + * Newer Huawei models (e.g. HUAWEI FLMH-XX / MateBook 14 2024) use
> > > direct
> > > > + * ACPI methods \GFRS / \SFRS (Get/Set Fn key Reversal Status) to
> > > control
> > > > + * Fn-lock via EC registers 0x6B (read) and 0x6C (write).
> > > > + *
> > > > + * GFRS response buffer layout:
> > > > + * byte[0] = STAT (0 = success)
> > > > + * byte[1] = 0x01 (fn-lock off) or 0x02 (fn-lock on)
> > > > + *
> > > > + * SFRS argument layout (CreateByteField(Arg0, 0x02, FRSR)):
> > > > + * Value is read from byte[2] of the integer argument, so it must be
> > > > + * passed as (value << 16):
> > > > + * (1 << 16) = fn-lock off (writes 0x55 to EC 0x6C)
> > > > + * (2 << 16) = fn-lock on (writes 0x5A to EC 0x6C)
> > > > + */
> > >
> > > This is very specific to the FLMH-XX model. Can you confirm this is the
> > > case for other newer models?
> > >
> > > > +
> > > > +static int huawei_acpi_fn_lock_get(int *on)
> > > > +{
> > > > + union acpi_object acpi_arg, *obj;
> > > > + struct acpi_object_list arg_list = { .count = 1, .pointer =
> > > &acpi_arg };
> > > > + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> > > > + acpi_status status;
> > > > + u8 val;
> > > > +
> > > > + acpi_arg.type = ACPI_TYPE_INTEGER;
> > > > + acpi_arg.integer.value = 0;
> > > > +
> > > > + status = acpi_evaluate_object(NULL, "\\GFRS", &arg_list,
> > > &output);
> > > > + if (ACPI_FAILURE(status))
> > > > + return -EIO;
> > > > +
> > > > + obj = output.pointer;
> > > > + if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length
> > > < 2) {
> > > > + kfree(obj);
> > > > + return -ENODATA;
> > > > + }
> > > > +
> > > > + /* byte[0] = STAT (0 = success), byte[1] = 1 (off) or 2 (on) */
> > > > + if (obj->buffer.pointer[0] != 0) {
> > > > + kfree(obj);
> > > > + return -EIO;
> > > > + }
> > > > +
> > > > + val = obj->buffer.pointer[1];
> > > > + if (val != 1 && val != 2) {
> > > > + kfree(obj);
> > > > + return -ENODATA;
> > > > + }
> > > > +
> > > > + if (on)
> > > > + *on = val - 1; /* 1→0 (off), 2→1 (on) */
> > > > +
> > > > + kfree(obj);
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int huawei_acpi_fn_lock_set(int on)
> > > > +{
> > > > + union acpi_object acpi_arg, *obj;
> > > > + struct acpi_object_list arg_list = { .count = 1, .pointer =
> > > &acpi_arg };
> > > > + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> > > > + acpi_status status;
> > > > + int ret = 0;
> > > > +
> > > > + /*
> > > > + * SFRS reads byte[2] of its argument via CreateByteField(Arg0,
> > > 0x02).
> > > > + * on=0 → FRSR=1 → EC gets 0x55 (fn-lock off)
> > > > + * on=1 → FRSR=2 → EC gets 0x5A (fn-lock on)
> > > > + */
> > > > + acpi_arg.type = ACPI_TYPE_INTEGER;
> > > > + acpi_arg.integer.value = (u64)(on + 1) << 16;
> > > > +
> > > > + status = acpi_evaluate_object(NULL, "\\SFRS", &arg_list,
> > > &output);
> > > > + if (ACPI_FAILURE(status))
> > > > + return -EIO;
> > > > +
> > > > + obj = output.pointer;
> > > > + if (obj && obj->type == ACPI_TYPE_BUFFER &&
> > > > + obj->buffer.length >= 1 && obj->buffer.pointer[0] != 0)
> > > > + ret = -EIO;
> > > > +
> > > > + kfree(obj);
> > > > + return ret;
> > > > +}
> > > > +
> > > > static int huawei_wmi_fn_lock_get(int *on)
> > > > {
> > > > u8 ret[0x100] = { 0 };
> > > > int err, i;
> > > >
> > > > + /* Newer models: use direct ACPI \GFRS method */
> > > > + if (acpi_has_method(NULL, "\\GFRS"))
> > > > + return huawei_acpi_fn_lock_get(on);
> > >
> > > Wouldn't it be better to put this behavior behind a quirk instead
> > > of enforcing it on the whole module? Keep in mind that this is
> > > also used by Honor devices that have the same WMI method.
> > >
> > > > +
> > > > + /* Legacy WMI fallback */
> > > > err = huawei_wmi_cmd(FN_LOCK_GET, ret, 0x100);
> > > > if (err)
> > > > return err;
> > > > @@ -550,6 +640,11 @@ static int huawei_wmi_fn_lock_set(int on)
> > > > {
> > > > union hwmi_arg arg;
> > > >
> > > > + /* Newer models: use direct ACPI \SFRS method */
> > > > + if (acpi_has_method(NULL, "\\SFRS"))
> > > > + return huawei_acpi_fn_lock_set(on);
> > > > +
> > > > + /* Legacy WMI fallback */
> > > > arg.cmd = FN_LOCK_SET;
> > > > arg.args[2] = on + 1; // 0 undefined, 1 off, 2 on.
> > > >
> > > > --
> > > > 2.54.0
> > > >
> > >
> > >
> > >