mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Denis Benato <denis.benato@linux.dev>
To: Antheas Kapenekakis <lkml@antheas.dev>, tarrihmoad@proton.me
Cc: "Corentin Chary" <corentin.chary@gmail.com>,
	"Luke D. Jones" <luke@ljones.dev>,
	"Hans de Goede" <hansg@kernel.org>,
	"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
	"Benjamin Tissoires" <bentiss@kernel.org>,
	"Sercan GOKMEN" <gokmensercan@gmail.com>,
	"Burak Goncu" <burakgon12@gmail.com>,
	"Denis Benato" <benato.denis96@gmail.com>,
	platform-driver-x86@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH] platform/x86: asus-wmi: Ignore kbd backlight read-back on rejected writes
Date: Mon, 9 Nov 2026 02:13:53 +0100	[thread overview]
Message-ID: <725a6890-6460-42d0-8cd8-5aad8a75f3f2@linux.dev> (raw)
In-Reply-To: <CAGwozwENHjfYUJMT5CP_Jvp6fYr54jxrgbrZBKfSH+8K_3wqMA@mail.gmail.com>


On 11/8/26 15:05, Antheas Kapenekakis wrote:
> On Sun, 8 Nov 2026 at 14:44, Moad Tarrih via B4 Relay
> <devnull+tarrihmoad.proton.me@kernel.org> wrote:
>> From: Moad Tarrih <tarrihmoad@proton.me>


Hi Moad!

>> On the ASUS ROG Strix G18 G814FP, the brightness attribute of
>> asus::kbd_backlight always reads 0, and every read breaks the keyboard
>> brightness keys.

Is this from a fully updated machine? Bios especially...

>> The firmware reports the keyboard backlight WMI device as present, but
>> DSTS(0x50021) returns 0x50000 (presence bit set, level 0) whatever level
>> the keyboard shows, and DEVS(0x50021, 0x80..0x83) returns
>> ASUS_WMI_UNSUPPORTED_METHOD for every level. The backlight is driven by
>> hid-asus through its asus-wmi listener instead.
>>
>> Since commit fac55d29581f ("platform/x86: asus-wmi: Add support for
>> multiple kbd led handlers"), kbd_led_get() stores the level it reads in
>> kbd_led_wk, and the brightness key handlers step from kbd_led_wk. Any
>> read of the attribute, for example by a desktop environment or
>> systemd-backlight, therefore resets the stored level to 0, and the next
>> brightness-up press sets the keyboard to the lowest level instead of
>> stepping up:
>>
>>   # echo 3 > /sys/class/leds/asus::kbd_backlight/brightness
>>   (keyboard goes to high)
>>   # cat /sys/class/leds/asus::kbd_backlight/brightness
>>   0
>>   (brightness-up key: keyboard drops to low)
>>
>> systemd-backlight also saves 0 at shutdown, so the level is lost across
>> reboots.
>>
>> Remember when the firmware rejects a write with -ENODEV, and from then
>> on return the stored level from kbd_led_get(), as is already done when
>> the WMI device is not available. The first write is queued right after
>> the LED is registered, so the read-back is only trusted before any
>> level has been set.

I would like to avoid issuing writes that we already know are going
to fail.

I think that if after testing the updated BIOS this problem is still
there the best thing to do is to implement a quirk and match by
model.

ROG laptops are basically all hid-controlled, no idea why that
method returns supported in yours.

A very interesting question would be "is it only FP or all G814 2025 are the same?"

>> The cause was found and this fix written with the help of an AI coding
>> assistant (Claude Code, Claude Opus 5.5). I reviewed the change and
>> tested it on the affected laptop.
>>
>> Fixes: fac55d29581f ("platform/x86: asus-wmi: Add support for multiple kbd led handlers")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Moad Tarrih <tarrihmoad@proton.me>
>> ---
>> Tested on an ASUS ROG Strix G18 (board G814FP, BIOS G814FP.317,
>> keyboard 0b05:19b6) only, on 7.2.14 as a DKMS module. With the patch,
>> the attribute reads back low, medium and high correctly, the brightness
>> keys step from the real level, and the level survives suspend/resume
>> and reboots. Build-tested with W=1 against pdx86 for-next
>> (c339f4010dea): no warnings. checkpatch --strict is clean.
>>
>> Limitation: a machine whose firmware rejects writes but changes the
>> brightness by itself would now report a stale level. I don't know of
>> such a machine.
>>
>> Sercan GOKMEN posted a patch for the same symptom on the B9406CAA:
>> https://lore.kernel.org/platform-driver-x86/20261030-b4-asus-wmi-b9406caa-kbd-readback-v2-1-ca93bb9039f6@gmail.com/
>> On that board writes succeed and only the read-back is constant, so it
>> uses a DMI quirk. The two patches are complementary: the rejected-write
>> check doesn't catch the B9406CAA, and the quirk doesn't catch the
>> G814FP. They touch the same condition in kbd_led_get(), so whichever
>> lands second needs a trivial rebase; I'm happy to rebase onto it.
>>
>> This touches different code from Bartu Alev's pending series
>> '[PATCH 0/2] platform/x86: asus-wmi: fix and unify keyboard brightness
>> key handling' and applies cleanly before or after it.
>>
>> A more general option would be to ignore the WMI read-back whenever a
>> hid-asus listener is registered, since hid-asus drives the backlight on
>> the G814FP. I didn't do that because it could report stale levels on
>> machines where the firmware does change the brightness itself, but I can
>> rework the patch that way if preferred.
>>
>> AI assistance: Claude Code was used over several sessions to trace the
>> read-back path in asus-wmi and hid-asus, run the debugfs DSTS/DEVS
>> probes, write the patch and draft this message. Testing and final
>> review were done by me on the hardware.
> Try to rewrite the commit message in your own words. It is hard to
> follow. This patch adds too much code.
>
> From what you are saying, your device always returns 0. So that is the
> bug. The code already has handling (as you said) for both the case
> reads are bugged and the wmi device is missing.

Hello Antheas,

No: the bug is that the TUF keyboard brightness devid is answering
with the presence bit set, that after removal of said bit becomes 0
for the user/caller.

If that interface cannot be used it shouldn't return the presence
bit (or should return the unsupported feature 0xFFFFFFFE),
and writes are rejected so we know ASUS intention here.

> Therefore, in your case the proper fix is to either piggyback on that
> quirk so that we do not read that device or, if you want to also avoid
> logged errors, introduce a small new quirk that sets kbd_led_avail to
> false and does not initialize a WMI device. The latter is an ideal
> solution though, minor errors in dmesg due to bios misconfiguration
> are common and harmless. The simplest solution for you is to use the
> read quirk.
>
> In both cases, if Sercan's patches are queued, find Ilpo's remote and
> base on that so you get no conflicts
>
> We cannot use a heuristic for when hid-asus is present. The device
> reports a WMI handle. There are devices with multiple aura devices on
> them.

I think we can, but I don't think it's a good idea.

> If it is found that a lot of devices report bogus reads, a potential
> future approach is to remove readback from WMI altogether and always
> use the bios stored value. This allows dropping the read quirk
> altogether.

The bios stored value?

> Best,
> Antheas
>
>> ---
>>  drivers/platform/x86/asus-wmi.c | 24 ++++++++++++++++++++----
>>  1 file changed, 20 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
>> index b33ebdb21aa2..c47ebc1f184a 100644
>> --- a/drivers/platform/x86/asus-wmi.c
>> +++ b/drivers/platform/x86/asus-wmi.c
>> @@ -258,6 +258,7 @@ struct asus_wmi {
>>         struct led_classdev kbd_led;
>>         int kbd_led_wk;
>>         bool kbd_led_notify;
>> +       bool kbd_led_write_rejected;
>>         bool kbd_led_avail;
>>         bool kbd_led_registered;
>>         struct led_classdev lightbar_led;
>> @@ -1724,8 +1725,9 @@ static struct asus_hid_ref asus_ref = {
>>         .listeners = LIST_HEAD_INIT(asus_ref.listeners),
>>         .asus = NULL,
>>         /*
>> -        * Protects .asus, .asus.kbd_led_{wk,notify}, and .listener refs. Other
>> -        * asus variables are read-only after .asus is set.
>> +        * Protects .asus, .asus.kbd_led_{wk,notify,write_rejected}, and
>> +        * .listener refs. Other asus variables are read-only after .asus is
>> +        * set.
>>          *
>>          * The led cdev device is not protected because it calls backlight_get
>>          * during initialization, which would result in a nested lock attempt.
>> @@ -1896,10 +1898,24 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
>>  static void kbd_led_update(struct asus_wmi *asus)
>>  {
>>         int ctrl_param = 0;
>> +       int err;
>>
>>         scoped_guard(spinlock_irqsave, &asus_ref.lock)
>>                 ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
>> -       asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
>> +       err = asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param,
>> +                                   NULL);
>> +
>> +       /*
>> +        * Some firmware reports the device as present but rejects writes,
>> +        * and its read-back does not follow the level set through other
>> +        * paths, such as hid-asus. Stop trusting the read-back once a
>> +        * write has been rejected.
>> +        */
>> +       if (err == -ENODEV) {
>> +               pr_debug("Keyboard backlight write rejected, ignoring read-back\n");
>> +               scoped_guard(spinlock_irqsave, &asus_ref.lock)
>> +                       asus->kbd_led_write_rejected = true;
>> +       }
>>  }
>>
>>  static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
>> @@ -1975,7 +1991,7 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
>>         asus = container_of(led_cdev, struct asus_wmi, kbd_led);
>>
>>         scoped_guard(spinlock_irqsave, &asus_ref.lock) {
>> -               if (!asus->kbd_led_avail)
>> +               if (!asus->kbd_led_avail || asus->kbd_led_write_rejected)
>>                         return asus->kbd_led_wk;
>>         }
>>
>>
>> ---
>> base-commit: c339f4010dea8b0d754f84ace70cd1b089878ef8
>> change-id: 20261108-asus-wmi-kbd-readback-236245e82de8
>>
>> Best regards,
>> --
>> Moad Tarrih <tarrihmoad@proton.me>
>>
>>
>>

      reply	other threads:[~2026-11-09  1:14 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-08 13:43 Moad Tarrih via B4 Relay
2026-11-08 14:05 ` Antheas Kapenekakis
2026-11-09  1:13   ` Denis Benato [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=725a6890-6460-42d0-8cd8-5aad8a75f3f2@linux.dev \
    --to=denis.benato@linux.dev \
    --cc=benato.denis96@gmail.com \
    --cc=bentiss@kernel.org \
    --cc=burakgon12@gmail.com \
    --cc=corentin.chary@gmail.com \
    --cc=gokmensercan@gmail.com \
    --cc=hansg@kernel.org \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lkml@antheas.dev \
    --cc=luke@ljones.dev \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tarrihmoad@proton.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®