[<prev] [next>] [day] [month] [year] [list]
Message-ID: <814215714.9758748.1736087481257@mail.yahoo.com>
Date: Sun, 5 Jan 2025 14:31:21 +0000 (UTC)
From: Stuart Balfour <sbalfour@....net>
To: "chiu@...lessm.com" <chiu@...lessm.com>,
"luca.stefani.ge1@...il.com" <luca.stefani.ge1@...il.com>,
"corentin.chary@...il.com" <corentin.chary@...il.com>,
"hdegoede@...hat.com" <hdegoede@...hat.com>,
"mgross@...ux.intel.com" <mgross@...ux.intel.com>
Cc:
"acpi4asus-user@...ts.sourceforge.net" <acpi4asus-user@...ts.sourceforge.net>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"platform-driver-x86@...r.kernel.org" <platform-driver-x86@...r.kernel.org>
Subject: asus-wmi fnlock review
On Asus laptops starting about 2019, a new ACPI device id 0x100023 associated
with fnlock was added. The BIOS option "Fn Lock Option [enabled/disabled]" under
advanced tab sets the start up value for the device. When enabled, Fn+ESC
toggles the fnlock mode; when disabled, Fn+ESC has no effect. Two ACPI MethodIds,
one for device_set and one for device_status (DSTS) are defined. Device_status
returns presence bit, external bit (device is set by hardware, not in ACPI) and
status bit (bit 0). Bit 0 is 0 when the option is enabled and 1 when disabled.
The device_set method ignores its argument, does nothing and returns 1 (putative
success).
Asus specifies that fnlock state cannot be read or set directly by WMI. Its
initial (default) setting is by the BIOS, though that does not appear in the GUI.
Thereafter, its state may be toggled by Fn+ESC if enabled. That toggles a hard-
ware line to the EC0 keyboard controller, and issues a WMI event 0x4E
(NOTIFY_FNLOCK_TOGGLE).
The asus-wmi driver has a local boolean which tracks the state of fnlock. The
initial value is ostensibly set from the asus-wmi module_param boolean
fnlock_default (if present), otherwise an assigned default value. Thereafter,
whenever a toggle event is received, it toggles the tracking boolean, then calls
the ACPI device_set method via asus_wmi_fnlock_update() with the boolean as
argument.
There are two problems: 1) if the driver sets the initial fnlock state to other
than the true state set by the BIOS; 2) calling the ACPI device_set method for
device 0x100023 has nil effect. (1) implies that the asus-wmi module option
fnlock_default cannot be effectuated on at least some recent Asus platforms.
(2) means the asus-wmi driver has confounding dummy code associated with ACPI
device 0x100023. The ECO flag bit XKTM that would've been overwritten had the
driver been enabled to set the device state belongs to the BIOS 'Fn Lock Option',
not fnlock. fnlock is not an ACPI device.
There is an overarching conceptual problem: the semantics of device 0x100023,
which is not settable by the WMI, are to communicate the state of the Fn Lock
Option in the BIOS, not the state of fnlock itself, to user space. When we query
the device, we are asking: "does Fn+ESC toggle fnlock mode?" The ineffectual
attempts by the driver to set the device to the actual fnlock state usurp the
defined semantics. Further, this reverse feed to the ACPI is not something
I see for other devices, except in cases where the device state is actually
set synchronously by the ACPI.
In case you don't have access to a relevant platform, here's the ACPI MethodIDs
for device 0x100023 on Asus Proart P16 model H7606WV (BIOS version H7606WV.312,
the latest and only version listed on Asus support site as of 12/20/24):
/* device_status (DSTS) */
If ((IIA0 == 0x00100023))
{
If ((^^PCI0.SBRG.EC0.XKTM == Zero))
{
Return (0x00010002)
}
Else
{
Return (0x00010003)
}
}
/* device_set */
If ((IIA0 == 0x00100023))
{
Return (One)
}
Here's the enigmatic code in asus-wmi.c from kernel version 6.12.6:
#define ASUS_WMI_DEVID_FNLOCK 0x00100023
struct asus_wmi {
...
bool fnlock_locked;
...
}
static bool fnlock_default = true;
module_param(fnlock_default, bool, 0444);
static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus)
{
u32 result;
asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FNLOCK, &result);
return (result & ASUS_WMI_DSTS_PRESENCE_BIT) &&
!(result & ASUS_WMI_FNLOCK_BIOS_DISABLED);
}
static void asus_wmi_fnlock_update(struct asus_wmi *asus)
{
int mode = asus->fnlock_locked;
asus_wmi_set_devstate(ASUS_WMI_DEVID_FNLOCK, mode, NULL);
}
static int asus_wmi_add(struct platform_device *pdev)
{
...
if (asus_wmi_has_fnlock_key(asus)) {
asus->fnlock_locked = fnlock_default;
asus_wmi_fnlock_update(asus);
}
...
}
static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
{
...
if (code == NOTIFY_FNLOCK_TOGGLE) {
asus->fnlock_locked = !asus->fnlock_locked;
asus_wmi_fnlock_update(asus);
return;
}
...
}
Here's a link to the original patch:
https://lore.kernel.org/lkml/20190418064648.25706-1-chiu@endlessm.com/
A later patch added the module_param fnlock_default:
https://lore.kernel.org/lkml/20210323202505.141496-1-luca.stefani.ge1@gmail.com/T/
I'll be addressing this issue as part of a larger update for recent (24H2 and
later) Asus laptop platforms. But I'd prefer the original authors and reviewers,
if they are available, review the situation before we decide what to do.
"If it ain't broke, don't fix it".
Powered by blists - more mailing lists