From nobody Fri Jun 19 09:05:20 2026 Received: from relay11.grserver.gr (relay11.grserver.gr [78.46.171.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6749314A9E; Sat, 25 Apr 2026 21:57:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=78.46.171.57 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154274; cv=none; b=AGMJyM+XM5JtGew6cdOVp9WsSE4x+yUID7WU7m9mQq9Ey+z2S7JdDhy8Qv86Y+H+pMQGEwA9VsuEGwLWeV11L9rSYSMMiBfRiMTY5iDD7o//NPxivXbZjewOQ64aAbbVn+sGckFWgu329syW3lY8DCaANKOD+l8T7yVGono2H0U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154274; c=relaxed/simple; bh=EpydV7q2mfrmOZU7jN46dDgUUkxps2DyhS44AShRAEs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CA0R3dFWWPYmpw4aOT45ycD6f98BJMTGDD5shTDItM5e4R55an1zTtCyedwvA2Q2RJLxCUClYaqKxww3bZPlWl1iM6lOISdS2ZjIOqTNiqd9rTdKhIc13DfyEkR5US297SiNaHIZQJmiRWC2E75nEICm3MzFhPNAKemObf0nBlQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=FIGxODws; arc=none smtp.client-ip=78.46.171.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="FIGxODws" Received: from relay11 (localhost.localdomain [127.0.0.1]) by relay11.grserver.gr (Proxmox) with ESMTP id C6310C181B; Sun, 26 Apr 2026 00:57:43 +0300 (EEST) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay11.grserver.gr (Proxmox) with ESMTPS id 23F6FC1771; Sun, 26 Apr 2026 00:57:43 +0300 (EEST) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id 060BB1FD484; Sun, 26 Apr 2026 00:57:41 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154262; bh=sJF1A95p1ylS9ELqAjl8fFgYptloxRu1AkVOOBlZajA=; h=From:To:Subject; b=FIGxODwsIOS45A24+tRAA+MGjW15Te4tscGOsjJnORnjx/749OrE/gblcBeBFmKKb XlsGbZ/r01Lh9ghO3cHRYEKn58+drTMM8Mww3oaZu9TRkF15YaSi+x1XhvDCVDTyHR LgA7yF8yhyYFOxM6XZp6/mAueIz5RokHdOCPDlFuiDefnxn1M+DxEhnPAGMLMtNwT+ VQK8yy/HUJXxapdroNPbngwfMaGUYsbxEwXOt0XzkWUmgX+igCTgRaC3Yq4ZAcYBm3 e/8DQgCDOzU4L0n0vD9dDzFrvqm5EfmCTxGFzteVWufthPecTxjoi53jxibQNO30pF o0SXqrKzoaP5w== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 01/10] acpi/x86: s2idle: Rename LPS0 constants so they mirror their function Date: Sat, 25 Apr 2026 23:57:25 +0200 Message-ID: <20260425215734.14116-2-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715426274.3677691.9873735536126217914@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" The LPS0 3/4 constants are part of a firmware notification called "Display on/off", in which the device enters a "Screen Off" state. The LPS0 7/8 constants are part of a firmware notification in which a Windows modern standby computer enters a "sleep" state where the CPU may still be active and maintain the radios. However, currently, the values are named as "Screen on/off" and "MS entry/exit", where Modern Standby is abbreviated as "MS". Therefore, perform a minor rename so that the values match their function. Then, fix the debug message to say that it executes notifications instead of entering states as it is otherwise confusing. Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- drivers/acpi/x86/s2idle.c | 84 +++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index b6b1dd76a06b..61a044b59776 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -43,20 +43,20 @@ static const struct acpi_device_id lps0_device_ids[] = =3D { #define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66" =20 #define ACPI_LPS0_GET_DEVICE_CONSTRAINTS 1 -#define ACPI_LPS0_SCREEN_OFF 3 -#define ACPI_LPS0_SCREEN_ON 4 +#define ACPI_LPS0_DISPLAY_OFF 3 +#define ACPI_LPS0_DISPLAY_ON 4 #define ACPI_LPS0_ENTRY 5 #define ACPI_LPS0_EXIT 6 -#define ACPI_LPS0_MS_ENTRY 7 -#define ACPI_LPS0_MS_EXIT 8 -#define ACPI_MS_TURN_ON_DISPLAY 9 +#define ACPI_LPS0_SLEEP_ENTRY 7 +#define ACPI_LPS0_SLEEP_EXIT 8 +#define ACPI_LPS0_TURN_ON_DISPLAY 9 =20 /* AMD */ #define ACPI_LPS0_DSM_UUID_AMD "e3f32452-febc-43ce-9039-932122d37721" #define ACPI_LPS0_ENTRY_AMD 2 #define ACPI_LPS0_EXIT_AMD 3 -#define ACPI_LPS0_SCREEN_OFF_AMD 4 -#define ACPI_LPS0_SCREEN_ON_AMD 5 +#define ACPI_LPS0_DISPLAY_OFF_AMD 4 +#define ACPI_LPS0_DISPLAY_ON_AMD 5 =20 static acpi_handle lps0_device_handle; static guid_t lps0_dsm_guid; @@ -343,27 +343,27 @@ static const char *acpi_sleep_dsm_state_to_str(unsign= ed int state) { if (lps0_dsm_func_mask_microsoft || !acpi_s2idle_vendor_amd()) { switch (state) { - case ACPI_LPS0_SCREEN_OFF: - return "screen off"; - case ACPI_LPS0_SCREEN_ON: - return "screen on"; + case ACPI_LPS0_DISPLAY_OFF: + return "display off"; + case ACPI_LPS0_DISPLAY_ON: + return "display on"; case ACPI_LPS0_ENTRY: return "lps0 entry"; case ACPI_LPS0_EXIT: return "lps0 exit"; - case ACPI_LPS0_MS_ENTRY: - return "lps0 ms entry"; - case ACPI_LPS0_MS_EXIT: - return "lps0 ms exit"; - case ACPI_MS_TURN_ON_DISPLAY: - return "lps0 ms turn on display"; + case ACPI_LPS0_SLEEP_ENTRY: + return "sleep entry"; + case ACPI_LPS0_SLEEP_EXIT: + return "sleep exit"; + case ACPI_LPS0_TURN_ON_DISPLAY: + return "turn on display"; } } else { switch (state) { - case ACPI_LPS0_SCREEN_ON_AMD: - return "screen on"; - case ACPI_LPS0_SCREEN_OFF_AMD: - return "screen off"; + case ACPI_LPS0_DISPLAY_ON_AMD: + return "display on"; + case ACPI_LPS0_DISPLAY_OFF_AMD: + return "display off"; case ACPI_LPS0_ENTRY_AMD: return "lps0 entry"; case ACPI_LPS0_EXIT_AMD: @@ -388,7 +388,7 @@ static void acpi_sleep_run_lps0_dsm(unsigned int func, = unsigned int func_mask, g lps0_dsm_state =3D func; if (pm_debug_messages_on) { acpi_handle_info(lps0_device_handle, - "%s transitioned to state %s\n", + "%s executed notification %s\n", out_obj ? "Successfully" : "Failed to", acpi_sleep_dsm_state_to_str(lps0_dsm_state)); } @@ -545,16 +545,17 @@ static int acpi_s2idle_prepare_late_lps0(void) if (check_lps0_constraints) lpi_check_constraints(); =20 - /* Screen off */ + /* Display off */ if (lps0_dsm_func_mask > 0) acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ? - ACPI_LPS0_SCREEN_OFF_AMD : - ACPI_LPS0_SCREEN_OFF, + ACPI_LPS0_DISPLAY_OFF_AMD : + ACPI_LPS0_DISPLAY_OFF, lps0_dsm_func_mask, lps0_dsm_guid); =20 if (lps0_dsm_func_mask_microsoft > 0) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF, - lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_OFF, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); =20 /* LPS0 entry */ if (lps0_dsm_func_mask > 0 && acpi_s2idle_vendor_amd()) @@ -563,10 +564,12 @@ static int acpi_s2idle_prepare_late_lps0(void) =20 if (lps0_dsm_func_mask_microsoft > 0) { /* Modern Standby entry */ - acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY, - lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_ENTRY, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY, - lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); } =20 if (lps0_dsm_func_mask > 0 && !acpi_s2idle_vendor_amd()) @@ -616,21 +619,24 @@ static void acpi_s2idle_restore_early_lps0(void) acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT, lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); /* Intent to turn on display */ - acpi_sleep_run_lps0_dsm(ACPI_MS_TURN_ON_DISPLAY, - lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_TURN_ON_DISPLAY, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); /* Modern Standby exit */ - acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT, - lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_EXIT, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); } =20 - /* Screen on */ + /* Display on */ if (lps0_dsm_func_mask_microsoft > 0) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON, - lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_ON, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); if (lps0_dsm_func_mask > 0) acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ? - ACPI_LPS0_SCREEN_ON_AMD : - ACPI_LPS0_SCREEN_ON, + ACPI_LPS0_DISPLAY_ON_AMD : + ACPI_LPS0_DISPLAY_ON, lps0_dsm_func_mask, lps0_dsm_guid); } =20 --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay15.grserver.gr (relay15.grserver.gr [46.62.234.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B00B3624CB; Sat, 25 Apr 2026 21:57:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.62.234.254 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154274; cv=none; b=FsE5/SLj9h48CArPsUAoKOphYRYapVNUPkj9+bios2+eScRhx9xzCHG3LNj37AmxYGZU/50rO3EI6dySUxZlPo28yieVVg2vpAIeNZ4hHdaE6PbNGCEJMHFLDTxmFLvxUF7EJonZvA2QWH1i8H2UicM/vJpIS7O294NWcjlEVeg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154274; c=relaxed/simple; bh=hFG/4D6D/v24vwJZVdlI1C34PrQRR0Igdzc9eIh0Ss0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DC+6zOG4kprMk3iL2OCD3muQ+g0oHSXE9E3cgToqY+QHORNfzGD29OkYFzeKzuduCDfVcRPmyO7LHJ6yuV78AMgflzotVCphfZQDJvzzbsq7SPx3YU5TPJG4isYu5L+WJcqAGYEyKf/xm/XVUaR5JlZNf/G0/uFINATwWp86/Hs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=DmhXjzq/; arc=none smtp.client-ip=46.62.234.254 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="DmhXjzq/" Received: from relay15 (localhost [127.0.0.1]) by relay15.grserver.gr (Proxmox) with ESMTP id 16BA440507; Sat, 25 Apr 2026 21:57:45 +0000 (UTC) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay15.grserver.gr (Proxmox) with ESMTPS id 51D7B407D3; Sat, 25 Apr 2026 21:57:44 +0000 (UTC) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id 15C8A1FD48B; Sun, 26 Apr 2026 00:57:43 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154263; bh=OHWCQmUJKPeq0NthTR9w3ifOIUDymX5i/+sG3RtrMmc=; h=From:To:Subject; b=DmhXjzq/OZv46cHbT/XXGm3RbB35GmRMRqrCnagvhSFe1lxf+iosbpo3S/LWwr3kw XeUY3868gwvwV6zmr3iuWItXgfgEjdI1uAXRsdfDSwURHs42ni5ohRMcymXnC28bjI qKNGzB5T5aG0H8KhmSGQ7FKpznBii+KbDtgQE5kyzfhg91nZmM1FTEwopT3Ouw43ac 8b9Vv3LLzjsKc161f8MAUHxUchTG3kcSaubsZlNfIb6PuPsyLNKi/8BJysjQf/GLoC HD0eQn1F+HTwUwsZCe5POduVK0hWQKV628KbBGq1EL0LPtzCVpA8AetHCv+IUaeBy1 Bq93MYJ2hzz/Q== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 02/10] acpi/x86: s2idle: Move Modern Standby calls to s2idle begin/end Date: Sat, 25 Apr 2026 23:57:26 +0200 Message-ID: <20260425215734.14116-3-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715426378.3677768.8424112739099184786@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" In Windows, the modern standby calls for sleep entry/exit and display on/off happen while the kernel device subsystems are active and the device is asleep. Currently, in the Linux kernel they happen in prepare_late, after e.g. the USB subsystem has turned off. This disimilarity causes obscure issues in certain devices that use these calls to turn off peripherals that should not be active during modern standby, e.g. handheld controllers, and RGB. Therefore, move these calls to _begin(), and _end() to match Windows. Particularly for _end(), introduce a acpi_s2idle_end_lps0() function to wrap acpi_s2idle_end(), matching the structure introduced with acpi_s2idle_begin_lps0(). Of note is that unlike the ACPI ABI of LPS0, there is no device power state requirement before entering sleep/screen off, therefore it is appropriate to move these calls to _begin(), before s2idle suspend. Link: https://learn.microsoft.com/en-us/windows-hardware/design/device-expe= riences/modern-standby-states Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- drivers/acpi/x86/s2idle.c | 63 +++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index 61a044b59776..f5aefba8b191 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -517,8 +517,10 @@ static struct acpi_scan_handler lps0_handler =3D { =20 static int acpi_s2idle_begin_lps0(void) { - if (lps0_device_handle && !sleep_no_lps0 && check_lps0_constraints && - !lpi_constraints_table) { + if (!lps0_device_handle || sleep_no_lps0) + return acpi_s2idle_begin(); + + if (check_lps0_constraints && !lpi_constraints_table) { if (acpi_s2idle_vendor_amd()) lpi_device_get_constraints_amd(); else @@ -532,6 +534,24 @@ static int acpi_s2idle_begin_lps0(void) lpi_constraints_table =3D ERR_PTR(-ENODATA); } =20 + /* Display off */ + if (lps0_dsm_func_mask > 0) + acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ? + ACPI_LPS0_DISPLAY_OFF_AMD : + ACPI_LPS0_DISPLAY_OFF, + lps0_dsm_func_mask, lps0_dsm_guid); + + if (lps0_dsm_func_mask_microsoft > 0) + acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_OFF, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); + + /* Modern Standby entry */ + if (lps0_dsm_func_mask_microsoft > 0) + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_ENTRY, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); + return acpi_s2idle_begin(); } =20 @@ -545,36 +565,17 @@ static int acpi_s2idle_prepare_late_lps0(void) if (check_lps0_constraints) lpi_check_constraints(); =20 - /* Display off */ + /* LPS0 entry */ if (lps0_dsm_func_mask > 0) acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ? - ACPI_LPS0_DISPLAY_OFF_AMD : - ACPI_LPS0_DISPLAY_OFF, + ACPI_LPS0_ENTRY_AMD : + ACPI_LPS0_ENTRY, lps0_dsm_func_mask, lps0_dsm_guid); =20 if (lps0_dsm_func_mask_microsoft > 0) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_OFF, - lps0_dsm_func_mask_microsoft, - lps0_dsm_guid_microsoft); - - /* LPS0 entry */ - if (lps0_dsm_func_mask > 0 && acpi_s2idle_vendor_amd()) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD, - lps0_dsm_func_mask, lps0_dsm_guid); - - if (lps0_dsm_func_mask_microsoft > 0) { - /* Modern Standby entry */ - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_ENTRY, - lps0_dsm_func_mask_microsoft, - lps0_dsm_guid_microsoft); acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY, lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); - } - - if (lps0_dsm_func_mask > 0 && !acpi_s2idle_vendor_amd()) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY, - lps0_dsm_func_mask, lps0_dsm_guid); =20 list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) { if (handler->prepare) @@ -615,9 +616,19 @@ static void acpi_s2idle_restore_early_lps0(void) ACPI_LPS0_EXIT, lps0_dsm_func_mask, lps0_dsm_guid); =20 - if (lps0_dsm_func_mask_microsoft > 0) { + if (lps0_dsm_func_mask_microsoft > 0) acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT, lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); +} + +static void acpi_s2idle_end_lps0(void) +{ + acpi_s2idle_end(); + + if (!lps0_device_handle || sleep_no_lps0) + return; + + if (lps0_dsm_func_mask_microsoft > 0) { /* Intent to turn on display */ acpi_sleep_run_lps0_dsm(ACPI_LPS0_TURN_ON_DISPLAY, lps0_dsm_func_mask_microsoft, @@ -648,7 +659,7 @@ static const struct platform_s2idle_ops acpi_s2idle_ops= _lps0 =3D { .wake =3D acpi_s2idle_wake, .restore_early =3D acpi_s2idle_restore_early_lps0, .restore =3D acpi_s2idle_restore, - .end =3D acpi_s2idle_end, + .end =3D acpi_s2idle_end_lps0, }; =20 void __init acpi_s2idle_setup(void) --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay12.grserver.gr (relay12.grserver.gr [88.99.38.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA53C2E040D; Sat, 25 Apr 2026 22:05:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=88.99.38.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154723; cv=none; b=GUTEJiQiOpm1Nu2QZW2/NnxYLZISpKOzXda7jWwqZ+Ud0hcwDDsx1RbHH5IgScfHsxf+Bffq3HnGbu6RcSJ6P7u5tG23zHBdKnm7RjpdTPeOhTn6CprV3nKCjR+AiJq7NsprTBj9vyWSQ+VdlaTFg9Z37rL5//TXyiaf0Rf6s1I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154723; c=relaxed/simple; bh=y1SuYU0Q0WNNvUkbuphHCJbSi2MtZr1sZT1WkQngKwo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=poa1oO5a3Hfm8oNHTPLXhq/oHpt0tBUoIvJUIwtE4SANmjmcrktUl9AOFSkIH0M4X3lC+UXD1zN0SR+CfdNTMpSZBqwJysFt8YVw/MbmIhGJhrSu3PSnc464gY8QTK/rPNSPLUcV3WsyNAt6xuwLkD0O4RrdVgj4zqX9MU/nUQY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=RRtG9cHH; arc=none smtp.client-ip=88.99.38.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="RRtG9cHH" Received: from relay12 (localhost [127.0.0.1]) by relay12.grserver.gr (Proxmox) with ESMTP id C4A22BC0B4; Sun, 26 Apr 2026 00:57:45 +0300 (EEST) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay12.grserver.gr (Proxmox) with ESMTPS id 55A3ABC081; Sun, 26 Apr 2026 00:57:45 +0300 (EEST) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id 2A3681FD3FD; Sun, 26 Apr 2026 00:57:44 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154265; bh=lbSloGeEDYG886uDWQJIpyuZd2CkaLS35LXOgIJRno0=; h=From:To:Subject; b=RRtG9cHHPYZY1CWjAevgEMSEE1oTlSfZOeeyic1CD0nSC6ql0HrMPK8uJwCnnw/ug KSqa5qwJuD2HKGcoJmLOiagsVl+TjG/aJMpws1oS/jvUzpMMmgp1RAau/b+206y2wA d+SGT8hkoGIiiHZURKkmCbwwYQyyu+Ci/fMWWRrQmWNfvCnbZgTW8mGCJ9DySkM1ej x/O32eyJmxTIkeVdfSQcc6QReTFwpf69dAJ/vydRw8QH7J5f58aZynzIAhHWdALiRX LVJ/mQUhwEGmevcwqzC28aTAQM9dRgECxZ9gHmJRbeuTTYoY6BDt55dRH7EJ3SSFtg kWysleHbIWilA== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 03/10] acpi/x86: s2idle: Add support for adding a delay after begin MS calls Date: Sat, 25 Apr 2026 23:57:27 +0200 Message-ID: <20260425215734.14116-4-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715426490.3677825.2518839464906311984@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" Certain platform/USB devices interact with Modern Standby firmware notifications. This is particularly true with Asus, where the keyboards are wired up to turn off their backlight during the Display Off notification using a predetermined delay. While for Asus Keyboards this does not cause an issue, it does manifest in ROG Ally devices, where the controller waits for the animation to complete before saving its state. In Windows, this is not a problem, because there is an ample delay after these calls and before LPS0, typically seconds to minutes. Therefore, introduce a delay quirk after these calls, to ensure affected devices have time to uninitialize, and attach it to acpi_s2idle_dev_ops so it can be consumed by device drivers. Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- drivers/acpi/x86/s2idle.c | 11 +++++++++++ include/linux/acpi.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index f5aefba8b191..8b48f999e0e9 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -16,6 +16,7 @@ */ =20 #include +#include #include #include #include @@ -517,6 +518,9 @@ static struct acpi_scan_handler lps0_handler =3D { =20 static int acpi_s2idle_begin_lps0(void) { + struct acpi_s2idle_dev_ops *handler; + int delay =3D 0; + if (!lps0_device_handle || sleep_no_lps0) return acpi_s2idle_begin(); =20 @@ -552,6 +556,13 @@ static int acpi_s2idle_begin_lps0(void) lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); =20 + list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) { + if (handler->begin_delay && handler->begin_delay > delay) + delay =3D handler->begin_delay; + } + if (delay > 0) + msleep(delay); + return acpi_s2idle_begin(); } =20 diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d2f0bed7a06..a416e5c5798a 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1154,6 +1154,7 @@ struct acpi_s2idle_dev_ops { void (*prepare)(void); void (*check)(void); void (*restore)(void); + int begin_delay; }; #if defined(CONFIG_SUSPEND) && defined(CONFIG_X86) int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg); --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay11.grserver.gr (relay11.grserver.gr [78.46.171.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 689F8364021; Sat, 25 Apr 2026 21:57:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=78.46.171.57 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154275; cv=none; b=tUg7mhTofpraYrQ+oAsrjeU4S5bqBibgbH1yNauY1h6AUPeOrZPUY6GnHfEcnXppvOdS/y6U988PLEGxS5eYry3r5Gt6/Wphv/NYZ3/uwloiqdDiPtrsTvnzVta5oSlXM3zwo108UQnNNLC/PWBXsdH3TS1R5fOl4R71jZLX+YM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154275; c=relaxed/simple; bh=YD2uJqjynXYZ5kbG6NjfdGBit/uYJrRq5xHZ4pUB8D0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=srVPJdCS24hOOZ8Jn/Mbx5iTTDNcisfcBKS17yFNsPbluoCME14LjdnN46r1/0MC5KqB+mAizZHYvkOTp12zcixqtN7Il8AkWX3JYukscYG0gUCTFTp9Go4eRKkKOCUXkzW2GXABjtJqkAc5M7iNNNBaywFuvHJ1ka1MkN67t2k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=kBndYnJk; arc=none smtp.client-ip=78.46.171.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="kBndYnJk" Received: from relay11 (localhost.localdomain [127.0.0.1]) by relay11.grserver.gr (Proxmox) with ESMTP id 42A33C1839; Sun, 26 Apr 2026 00:57:47 +0300 (EEST) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay11.grserver.gr (Proxmox) with ESMTPS id B83CFC1818; Sun, 26 Apr 2026 00:57:46 +0300 (EEST) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id 62BFD1FD3F5; Sun, 26 Apr 2026 00:57:45 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154266; bh=6NFWgb50ety8JDzGpmqrkBu/w2C6asiylhwI3zG12Rk=; h=From:To:Subject; b=kBndYnJkN6qwxdvEJhg8LQnadxoaYt+QzAYvyOb0QX3OaTUv1WqHyf6GbTyySHyKD dolMQLhUV7OcKVQFF838kENTKlixV3WxwYIARVmWIC5jvS02Uf+BD88D6zW8Bho3bi hfbv04hYTeGDMJUSRTzwrXCPmsFqzCrbaPDuKnRrYY8UQ/ogWpx/ukLuMblkcCcwNl Je8qbhLPDgLhWZTzutsLYryeNJAbtxSKqp2N2wLc7eG1nRqPp7HI0lWGnmb/7ZCYX3 nxKYBs354vOJfbTV0DFBREVwPTdUMYCMSTnpC2nDoM0iTPHKTG1Rf8f8W+mHmWZSLc EkCoRR/LdCYLA== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 04/10] platform/x86: asus-wmi: add s2idle begin delay for Ally devices Date: Sat, 25 Apr 2026 23:57:28 +0200 Message-ID: <20260425215734.14116-5-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715426636.3678028.7224113446620385481@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" Asus ROG Ally devices have a small fade animation during their suspend sequence. This animation is triggered by the Display Off firmware notification. After it, they power off, disconnect, and save their state. Without a delay after that notification, if the device is placed into D3, it causes it to reboot during resume, or particularly for original Allies, also leave the xpad device connected, causing spurious wakeups when a gamepad button is pressed and higher standby drain. Therefore, introduce a small delay quirk and bind it to an s2idle dev ops device. Place this quirk in the asus-wmi driver, as the USB gamepad disconnects, making it hard to place in hid-asus, and to allow for proper functionality when the hid-asus driver is blacklisted. Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- drivers/platform/x86/asus-nb-wmi.c | 40 ++++++++++++++++++++++++++++++ drivers/platform/x86/asus-wmi.c | 12 +++++++++ drivers/platform/x86/asus-wmi.h | 14 +++++++++++ 3 files changed, 66 insertions(+) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus= -nb-wmi.c index b4677c5bba5b..da963f3a17b1 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -155,6 +155,10 @@ static struct quirk_entry quirk_asus_z13 =3D { .tablet_switch_mode =3D asus_wmi_kbd_dock_devid, }; =20 +static struct quirk_entry quirk_ally =3D { + .lps0_begin_delay =3D 500, +}; + static int dmi_matched(const struct dmi_system_id *dmi) { pr_info("Identified laptop model '%s'\n", dmi->ident); @@ -553,6 +557,42 @@ static const struct dmi_system_id asus_quirks[] =3D { }, .driver_data =3D &quirk_asus_z13, }, + { + .callback =3D dmi_matched, + .ident =3D "ASUS ROG Ally", + .matches =3D { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "RC71L"), + }, + .driver_data =3D (void *)&quirk_ally, + }, + { + .callback =3D dmi_matched, + .ident =3D "ASUS ROG Ally X", + .matches =3D { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "RC72L"), + }, + .driver_data =3D (void *)&quirk_ally, + }, + { + .callback =3D dmi_matched, + .ident =3D "ASUS ROG Xbox Ally", + .matches =3D { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "RC73Y"), + }, + .driver_data =3D (void *)&quirk_ally, + }, + { + .callback =3D dmi_matched, + .ident =3D "ASUS ROG Xbox Ally X", + .matches =3D { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "RC73X"), + }, + .driver_data =3D (void *)&quirk_ally, + }, {}, }; =20 diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wm= i.c index 7c0915e097ba..3316415abbdf 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -337,6 +337,8 @@ struct asus_wmi { struct asus_wmi_debug debug; =20 struct asus_wmi_driver *driver; + + struct acpi_s2idle_dev_ops s2idle_dev_ops; }; =20 /* Global to allow setting externally without requiring driver data */ @@ -5030,6 +5032,12 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_platform; =20 + if (asus->driver->quirks->lps0_begin_delay) { + asus->s2idle_dev_ops.begin_delay =3D + asus->driver->quirks->lps0_begin_delay; + acpi_register_lps0_dev(&asus->s2idle_dev_ops); + } + if (use_ally_mcu_hack =3D=3D ASUS_WMI_ALLY_MCU_HACK_INIT) { if (acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) && dmi_check_system(asus_rog_ally_device)) @@ -5184,6 +5192,8 @@ static int asus_wmi_add(struct platform_device *pdev) fail_custom_fan_curve: fail_platform_profile_setup: fail_fan_boost_mode: + if (asus->driver->quirks->lps0_begin_delay) + acpi_unregister_lps0_dev(&asus->s2idle_dev_ops); fail_platform: kfree(asus); return err; @@ -5207,6 +5217,8 @@ static void asus_wmi_remove(struct platform_device *d= evice) asus_fan_set_auto(asus); throttle_thermal_policy_set_default(asus); asus_wmi_battery_exit(asus); + if (asus->driver->quirks->lps0_begin_delay) + acpi_unregister_lps0_dev(&asus->s2idle_dev_ops); =20 kfree(asus); } diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wm= i.h index 5cd4392b964e..2a8c51d39bf8 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -52,6 +52,20 @@ struct quirk_entry { */ int no_display_toggle; u32 xusb2pr; + /* + * Ally devices uninitialize after the display off DSM of modern + * stanby, after a predetermined fade animation on their RGB. + * If the USB subsystem puts the controller into D3 before that, + * it loses its state and (i) for original allies, it leaves the + * xpad device connected, causing spurious wake-ups and higher + * power draw, (ii) for newer allies using the adaptive protocol + * causes the controller to reboot on resume if mcu_powersave is + * false. Therefore, allow adding a delay for the affected devices. + * (if MCU powersave is true the controller always reboots, but + * this also causes an unwelcome 5-7s delay on resume, this issue + * is present on all firmwares) + */ + int lps0_begin_delay; }; =20 struct asus_wmi_driver { --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay11.grserver.gr (relay11.grserver.gr [78.46.171.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 517D5367F31; Sat, 25 Apr 2026 21:57:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=78.46.171.57 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154277; cv=none; b=I7u7h92ewbfTEiyCZS7NSzu8zYnI7fcAIeC1Uy5XlwyKLTT4b+fe694PX4q7zx37+vbXlIXmptBXdoqOouXKos1AiDwFJ7Qf0pTAbFtA91giC/sKyDfEgawyQTpUb0LFtw5lL9uCJV63uWldKzqN+S9zG+GKsF4p5YDDDBR3k3g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154277; c=relaxed/simple; bh=HDbMsjjfAVTsdkAUn6AS5IvI6hGr+GB1VWC06XnjbiE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tfQCXJIt04r4GGFcJZq90awNoccerntuKGJGVHYBnyZXSsCvAIkB/ou7wAjdIL8u3Oi4Fzj7dURHmEPJ5mj7MXMYRieXeKsZpAr7/hCpB1l04+V1Ty+o9XN2ir4gZnCtCeWouBkbWVaFbdkq/b6ZSUt6eVLPX+qSTu6PTCbUPMI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=HRK0Zspz; arc=none smtp.client-ip=78.46.171.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="HRK0Zspz" Received: from relay11 (localhost.localdomain [127.0.0.1]) by relay11.grserver.gr (Proxmox) with ESMTP id 61D7CC1847; Sun, 26 Apr 2026 00:57:48 +0300 (EEST) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay11.grserver.gr (Proxmox) with ESMTPS id D156EC1818; Sun, 26 Apr 2026 00:57:47 +0300 (EEST) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id B32731FD47E; Sun, 26 Apr 2026 00:57:46 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154267; bh=kCFKuOwTOpvO8wuwF8nH541CkPemBPYvdRJlmy2rGcs=; h=From:To:Subject; b=HRK0ZspzgqZ22KvMHLAgbtezshiYtRouTs0dm6gU/7gHHT2c+mkjzwrbJz5sCLVeM OLyUooagqhplyYGbw8NMJfw73/kLhxiR7X1SkhLuLVeYw7yvzHNb9Gc7fAvSKSbYmt azU7yDGwZ48GvUpbPzetSLMi7NhY+QvtmbfF711FsOsxHSSBpNSPLMZphC6Lx9aQLD 7Bvi56rI/MMy1mwEs1CffYhG+hcx8MxxZcq8f1kZFk/WPIKqkqaKtOKA9WedEk/0Pq PIHjkopaJ0HKreGOd2D04i2VTWMre1Pcebx2jES98AoOS6FS9RurhoMRFHQtEYawrC hauOLzSb9qB2g== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 05/10] HID: asus: remove quirk handling for Ally devices Date: Sat, 25 Apr 2026 23:57:29 +0200 Message-ID: <20260425215734.14116-6-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715426746.3678080.17843960859623243697@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" Ally device controllers had suspend issues due to the faulty s2idle ordering present in the kernel, causing a failure to resume. These issues were partially addressed with a firmware update, leading to the introduction of a version check in this driver. However, after fixing the call ordering in s2idle and adding a small delay particularly for Ally devices, the controller for these devices is universally fixed for all firmware versions, including the spurious resume bug requiring set_ally_mcu_powersave(True) for the controller to function correctly on newer firmwares. Therefore, remove the check and cleanup the driver. Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- drivers/hid/hid-asus.c | 113 ++--------------------------------------- 1 file changed, 4 insertions(+), 109 deletions(-) diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index bc93b27f9b13..2d2fe72a3d5b 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -53,10 +53,6 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); #define FEATURE_KBD_LED_REPORT_ID1 0x5d #define FEATURE_KBD_LED_REPORT_ID2 0x5e =20 -#define ROG_ALLY_REPORT_SIZE 64 -#define ROG_ALLY_X_MIN_MCU 313 -#define ROG_ALLY_MIN_MCU 319 - /* Spurious HID codes sent by QUIRK_ROG_NKEY_KEYBOARD devices */ #define ASUS_SPURIOUS_CODE_0XEA 0xea #define ASUS_SPURIOUS_CODE_0XEC 0xec @@ -99,9 +95,8 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); #define QUIRK_MEDION_E1239T BIT(10) #define QUIRK_ROG_NKEY_KEYBOARD BIT(11) #define QUIRK_ROG_CLAYMORE_II_KEYBOARD BIT(12) -#define QUIRK_ROG_ALLY_XPAD BIT(13) -#define QUIRK_HID_FN_LOCK BIT(14) -#define QUIRK_ROG_NKEY_ID1ID2_INIT BIT(15) +#define QUIRK_HID_FN_LOCK BIT(13) +#define QUIRK_ROG_NKEY_ID1ID2_INIT BIT(14) =20 #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ QUIRK_NO_INIT_REPORTS | \ @@ -631,102 +626,9 @@ static void asus_kbd_backlight_work(struct work_struc= t *work) hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret); } =20 -/* - * We don't care about any other part of the string except the version sec= tion. - * Example strings: FGA80100.RC72LA.312_T01, FGA80100.RC71LS.318_T01 - * The bytes "5a 05 03 31 00 1a 13" and possibly more come before the vers= ion - * string, and there may be additional bytes after the version string such= as - * "75 00 74 00 65 00" or a postfix such as "_T01" - */ -static int mcu_parse_version_string(const u8 *response, size_t response_si= ze) -{ - const u8 *end =3D response + response_size; - const u8 *p =3D response; - int dots, err, version; - char buf[4]; - - dots =3D 0; - while (p < end && dots < 2) { - if (*p++ =3D=3D '.') - dots++; - } - - if (dots !=3D 2 || p >=3D end || (p + 3) >=3D end) - return -EINVAL; - - memcpy(buf, p, 3); - buf[3] =3D '\0'; - - err =3D kstrtoint(buf, 10, &version); - if (err || version < 0) - return -EINVAL; - - return version; -} - -static int mcu_request_version(struct hid_device *hdev) -{ - u8 *response __free(kfree) =3D kzalloc(ROG_ALLY_REPORT_SIZE, GFP_KERNEL); - const u8 request[] =3D { 0x5a, 0x05, 0x03, 0x31, 0x00, 0x20 }; - int ret; - - if (!response) - return -ENOMEM; - - ret =3D asus_kbd_set_report(hdev, request, sizeof(request)); - if (ret < 0) - return ret; - - ret =3D hid_hw_raw_request(hdev, FEATURE_REPORT_ID, response, - ROG_ALLY_REPORT_SIZE, HID_FEATURE_REPORT, - HID_REQ_GET_REPORT); - if (ret < 0) - return ret; - - ret =3D mcu_parse_version_string(response, ROG_ALLY_REPORT_SIZE); - if (ret < 0) { - pr_err("Failed to parse MCU version: %d\n", ret); - print_hex_dump(KERN_ERR, "MCU: ", DUMP_PREFIX_NONE, - 16, 1, response, ROG_ALLY_REPORT_SIZE, false); - } - - return ret; -} - -static void validate_mcu_fw_version(struct hid_device *hdev, int idProduct) -{ - int min_version, version; - - version =3D mcu_request_version(hdev); - if (version < 0) - return; - - switch (idProduct) { - case USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY: - min_version =3D ROG_ALLY_MIN_MCU; - break; - case USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X: - min_version =3D ROG_ALLY_X_MIN_MCU; - break; - default: - min_version =3D 0; - } - - if (version < min_version) { - hid_warn(hdev, - "The MCU firmware version must be %d or greater to avoid issues with su= spend.\n", - min_version); - } else { - set_ally_mcu_hack(ASUS_WMI_ALLY_MCU_HACK_DISABLED); - set_ally_mcu_powersave(true); - } -} - static int asus_kbd_register_leds(struct hid_device *hdev) { struct asus_drvdata *drvdata =3D hid_get_drvdata(hdev); - struct usb_interface *intf; - struct usb_device *udev; unsigned char kbd_func; int ret; =20 @@ -754,13 +656,6 @@ static int asus_kbd_register_leds(struct hid_device *h= dev) return ret; } =20 - if (drvdata->quirks & QUIRK_ROG_ALLY_XPAD) { - intf =3D to_usb_interface(hdev->dev.parent); - udev =3D interface_to_usbdev(intf); - validate_mcu_fw_version(hdev, - le16_to_cpu(udev->descriptor.idProduct)); - } - drvdata->kbd_backlight =3D devm_kzalloc(&hdev->dev, sizeof(struct asus_kbd_leds), GFP_KERNEL); @@ -1493,10 +1388,10 @@ static const struct hid_device_id asus_devices[] = =3D { QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY), - QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD= }, + QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD}, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X), - QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD= }, + QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_XGM_2022), }, --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay11.grserver.gr (relay11.grserver.gr [78.46.171.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E67E23624BA; Sat, 25 Apr 2026 21:57:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=78.46.171.57 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154275; cv=none; b=kYai4W5OxYo8fsLvTo51vjqBFlD0Ef3iBdJb87dR5HvsMMPRqOmXq7HR4Wox83/ALtwQeg+a+4rOVwQdNWNIt8TLXJ+bLCnBlBwPxMobFVNDlD62HMeDacVX9D3rDDQpvSn+vxekiEyNNB4uxzM13uMZIPDTgfqcv7qPxE0JAKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154275; c=relaxed/simple; bh=HiJCzb9okeo00q1x6tCFqB+QDJUhLSUHehqK4oLogZg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M0lWXx1+gmPZTvRniW5HJJ6fZxXz0giBUsOu7F/TdfjCO2U61AfxK+2GvEBRAjiESs1VuNnrByg20gjxUTRE+gvQUaRYU1rYTuUH1Gi4OCsCzjesYsZwV3zGmJLHauS6WWtLFC35yLBVQjstV8CRWskpM8tx9kGtqGBFHtQ03wQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=XIFHl8Rl; arc=none smtp.client-ip=78.46.171.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="XIFHl8Rl" Received: from relay11 (localhost.localdomain [127.0.0.1]) by relay11.grserver.gr (Proxmox) with ESMTP id B8E77C186F; Sun, 26 Apr 2026 00:57:49 +0300 (EEST) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay11.grserver.gr (Proxmox) with ESMTPS id 05D0AC1834; Sun, 26 Apr 2026 00:57:49 +0300 (EEST) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id D31FC1FD3FD; Sun, 26 Apr 2026 00:57:47 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154268; bh=UT6tSU5gvSv2Y7sPiVe/IObxyHQxW4gU9ixTtrKvIac=; h=From:To:Subject; b=XIFHl8RlAw1yLFZZTUrIOtt3dkMMxtmVpXVYDn88hGhHddAipWD9YzGOTaxPvvtWb jCUhW5yechbzpD8ddzm4hMNyjU9IoBMKHP6QbdWT4dsc64iYGAOoPl9aSpftJy0kdI ko3p6jCqHm+QOsxSb5ZxG7qGAoFreezEkF8Doj96RbCcR5uiKoJfoC+2RLGNQaDHZ1 ScuYzwkqONcqYC9pmDStLcSDG+zwW3Qq5vuisGeTA2jemJ4UTQCPYjMPTH/r3qMiCm THUZVpCobMWzQ2nWt7iYYiswnitYVug/chWbiAUFwiQQd/q9mYzo+fSoo7VASBXEnw AdUXlpR3WRmiQ== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 06/10] platform/x86: asus-wmi: Remove Ally s2idle resume fixes Date: Sat, 25 Apr 2026 23:57:30 +0200 Message-ID: <20260425215734.14116-7-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715426860.3678178.697834581548293844@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" Ally device controllers had suspend issues due to the faulty s2idle ordering present in the kernel, causing a failure to resume. These issues were partially addressed with a firmware update, leading to the introduction of a version check in hid-asus and accompanying calls in this driver. However, after fixing the call ordering in s2idle and adding a small delay particularly for Ally devices, the controller for these devices is universally fixed for all firmware versions, including the spurious resume bug requiring set_ally_mcu_powersave(True) for the controller to function correctly on newer firmwares. Therefore, remove the calls, suspend quirks with CSEE duplicate calling (it was always called by s2idle through the Display Off _DSM but ignored while the USB subsystem was down and these calls took place), and cleanup the driver. Noteworthy is that we no longer force mcu_powersave to be on boot. This way, the user's choice in e.g. Windows or from userspace software is respected. Downstream distributions that care about the additional power draw in lieu of the significant additional delay in resume introduced by the setting can enable it with a udev rule (the canonical handling for this functionality). Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- drivers/platform/x86/asus-wmi.c | 124 --------------------- include/linux/platform_data/x86/asus-wmi.h | 8 -- 2 files changed, 132 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wm= i.c index 3316415abbdf..70c725ca0edd 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -140,33 +140,10 @@ module_param(fnlock_default, bool, 0444); #define ASUS_MINI_LED_2024_STRONG 0x01 #define ASUS_MINI_LED_2024_OFF 0x02 =20 -#define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE" -/* - * The period required to wait after screen off/on/s2idle.check in MS. - * Time here greatly impacts the wake behaviour. Used in suspend/wake. - */ -#define ASUS_USB0_PWR_EC0_CSEE_WAIT 600 -#define ASUS_USB0_PWR_EC0_CSEE_OFF 0xB7 -#define ASUS_USB0_PWR_EC0_CSEE_ON 0xB8 - static const char * const ashs_ids[] =3D { "ATK4001", "ATK4002", NULL }; =20 static int throttle_thermal_policy_write(struct asus_wmi *); =20 -static const struct dmi_system_id asus_rog_ally_device[] =3D { - { - .matches =3D { - DMI_MATCH(DMI_BOARD_NAME, "RC71L"), - }, - }, - { - .matches =3D { - DMI_MATCH(DMI_BOARD_NAME, "RC72L"), - }, - }, - { }, -}; - static bool ashs_present(void) { int i =3D 0; @@ -341,9 +318,6 @@ struct asus_wmi { struct acpi_s2idle_dev_ops s2idle_dev_ops; }; =20 -/* Global to allow setting externally without requiring driver data */ -static enum asus_ally_mcu_hack use_ally_mcu_hack =3D ASUS_WMI_ALLY_MCU_HAC= K_INIT; - #if IS_ENABLED(CONFIG_ASUS_WMI_DEPRECATED_ATTRS) static void asus_wmi_show_deprecated(void) { @@ -1436,43 +1410,6 @@ static DEVICE_ATTR_RW(nv_temp_target); =20 /* Ally MCU Powersave ****************************************************= ****/ =20 -/* - * The HID driver needs to check MCU version and set this to false if the = MCU FW - * version is >=3D the minimum requirements. New FW do not need the hacks. - */ -void set_ally_mcu_hack(enum asus_ally_mcu_hack status) -{ - use_ally_mcu_hack =3D status; - pr_debug("%s Ally MCU suspend quirk\n", - status =3D=3D ASUS_WMI_ALLY_MCU_HACK_ENABLED ? "Enabled" : "Disabled"); -} -EXPORT_SYMBOL_NS_GPL(set_ally_mcu_hack, "ASUS_WMI"); - -/* - * mcu_powersave should be enabled always, as it is fixed in MCU FW versio= ns: - * - v313 for Ally X - * - v319 for Ally 1 - * The HID driver checks MCU versions and so should set this if requiremen= ts match - */ -void set_ally_mcu_powersave(bool enabled) -{ - int result, err; - - err =3D asus_wmi_set_devstate(ASUS_WMI_DEVID_MCU_POWERSAVE, enabled, &res= ult); - if (err) { - pr_warn("Failed to set MCU powersave: %d\n", err); - return; - } - if (result > 1) { - pr_warn("Failed to set MCU powersave (result): 0x%x\n", result); - return; - } - - pr_debug("%s MCU Powersave\n", - enabled ? "Enabled" : "Disabled"); -} -EXPORT_SYMBOL_NS_GPL(set_ally_mcu_powersave, "ASUS_WMI"); - #if IS_ENABLED(CONFIG_ASUS_WMI_DEPRECATED_ATTRS) static ssize_t mcu_powersave_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -5038,21 +4975,6 @@ static int asus_wmi_add(struct platform_device *pdev) acpi_register_lps0_dev(&asus->s2idle_dev_ops); } =20 - if (use_ally_mcu_hack =3D=3D ASUS_WMI_ALLY_MCU_HACK_INIT) { - if (acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) - && dmi_check_system(asus_rog_ally_device)) - use_ally_mcu_hack =3D ASUS_WMI_ALLY_MCU_HACK_ENABLED; - if (dmi_match(DMI_BOARD_NAME, "RC71")) { - /* - * These steps ensure the device is in a valid good state, this is - * especially important for the Ally 1 after a reboot. - */ - acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, - ASUS_USB0_PWR_EC0_CSEE_ON); - msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); - } - } - /* ensure defaults for tunables */ #if IS_ENABLED(CONFIG_ASUS_WMI_DEPRECATED_ATTRS) asus->ppt_pl2_sppt =3D 5; @@ -5306,51 +5228,10 @@ static int asus_hotk_restore(struct device *device) return 0; } =20 -static int asus_hotk_prepare(struct device *device) -{ - if (use_ally_mcu_hack =3D=3D ASUS_WMI_ALLY_MCU_HACK_ENABLED) { - acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, - ASUS_USB0_PWR_EC0_CSEE_OFF); - msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); - } - return 0; -} - -#if defined(CONFIG_SUSPEND) -static void asus_ally_s2idle_restore(void) -{ - if (use_ally_mcu_hack =3D=3D ASUS_WMI_ALLY_MCU_HACK_ENABLED) { - acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, - ASUS_USB0_PWR_EC0_CSEE_ON); - msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); - } -} - -/* Use only for Ally devices due to the wake_on_ac */ -static struct acpi_s2idle_dev_ops asus_ally_s2idle_dev_ops =3D { - .restore =3D asus_ally_s2idle_restore, -}; - -static void asus_s2idle_check_register(void) -{ - if (acpi_register_lps0_dev(&asus_ally_s2idle_dev_ops)) - pr_warn("failed to register LPS0 sleep handler in asus-wmi\n"); -} - -static void asus_s2idle_check_unregister(void) -{ - acpi_unregister_lps0_dev(&asus_ally_s2idle_dev_ops); -} -#else -static void asus_s2idle_check_register(void) {} -static void asus_s2idle_check_unregister(void) {} -#endif /* CONFIG_SUSPEND */ - static const struct dev_pm_ops asus_pm_ops =3D { .thaw =3D asus_hotk_thaw, .restore =3D asus_hotk_restore, .resume =3D asus_hotk_resume, - .prepare =3D asus_hotk_prepare, }; =20 /* Registration **********************************************************= *****/ @@ -5377,11 +5258,7 @@ static int asus_wmi_probe(struct platform_device *pd= ev) return ret; } =20 - asus_s2idle_check_register(); - ret =3D asus_wmi_add(pdev); - if (ret) - asus_s2idle_check_unregister(); =20 return ret; } @@ -5418,7 +5295,6 @@ EXPORT_SYMBOL_GPL(asus_wmi_register_driver); void asus_wmi_unregister_driver(struct asus_wmi_driver *driver) { guard(mutex)(®ister_mutex); - asus_s2idle_check_unregister(); =20 platform_device_unregister(driver->platform_device); platform_driver_unregister(&driver->platform_driver); diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/pla= tform_data/x86/asus-wmi.h index 554f41b827e1..938a27c6f66e 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -188,8 +188,6 @@ enum asus_hid_event { #define ASUS_EV_MAX_BRIGHTNESS 3 =20 #if IS_REACHABLE(CONFIG_ASUS_WMI) -void set_ally_mcu_hack(enum asus_ally_mcu_hack status); -void set_ally_mcu_powersave(bool enabled); int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval); int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval); int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retva= l); @@ -197,12 +195,6 @@ int asus_hid_register_listener(struct asus_hid_listene= r *cdev); void asus_hid_unregister_listener(struct asus_hid_listener *cdev); int asus_hid_event(enum asus_hid_event event); #else -static inline void set_ally_mcu_hack(enum asus_ally_mcu_hack status) -{ -} -static inline void set_ally_mcu_powersave(bool enabled) -{ -} static inline int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *r= etval) { return -ENODEV; --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay11.grserver.gr (relay11.grserver.gr [78.46.171.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6BB9B3624BC; Sat, 25 Apr 2026 21:57:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=78.46.171.57 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154275; cv=none; b=RDmHjTDaKI2pNsCIpYgI4oE1BWvQjjhP71y2/I/LDPnLwKRl8d0nEg/rq59O6VYkRouEBpWYJD+Mnq96y5yLOh2iW9ezuHzYL7rBe10FbzUL1a4hu7hj2LFnkk3yv9zXK3XUREtbkBNC1Ynvf7/rvGJuTAEeyn58JPHdBFhRwDs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154275; c=relaxed/simple; bh=AP89DkESuwydEd7J0wae54cCZMvXIyheVKlao9Qrhgs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iqJV+BnCYunoCzsO8KBBATMz1Y9Cc9elrigoW82vqB35XRaXuO8bqRLFDa3AQEEM6Yb+an0OHhTaPtCDZe7s8BNa1YcpoxVZgwATrNmYfCeiK+iOHeUUvbl5aNvkU506EpBpCQwYtpymmBlgkoF1EbK5M7ZCvgKs+QnAp3/Gqo0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=cpYsQhvU; arc=none smtp.client-ip=78.46.171.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="cpYsQhvU" Received: from relay11 (localhost.localdomain [127.0.0.1]) by relay11.grserver.gr (Proxmox) with ESMTP id BA180C1878; Sun, 26 Apr 2026 00:57:50 +0300 (EEST) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay11.grserver.gr (Proxmox) with ESMTPS id 3BD53C1848; Sun, 26 Apr 2026 00:57:50 +0300 (EEST) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id ED8CE1FD47E; Sun, 26 Apr 2026 00:57:48 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154269; bh=N4qEeycmmz0KE5x0LMZMn4VfPN7YU/1xc0CRVvTcA4c=; h=From:To:Subject; b=cpYsQhvU5eEA1YnmYyhu0hkUeYL1KwGspF+Jynri2yThhfyQQunWD9PTDY5B9UMmo /TmAqKKSP3Iv869Pq/tM/OVgYKcZo32FM5feLTNAM5vXgsZc/iHa8qP2Rony0tT7au y484MLKqJu4i4PoTKDx3H89SLsa1HRtUNowipXUPW85XfO4PJF0730b47OiO2MJJ+e u9Yk7m4ouUD7BJaQ9ssZfwXiWu7vAYtUm0ynVgL23X1lJsQr7x6vUS7TJIQU6VFDpj yczwxTCSuhAHwkV3578SXmCt8Z4DOpe5Q2FI/8FfQJewuf+YzgTmoogADjoSvvAH7+ eO9vXa1cP9zpQ== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 07/10] Documentation: Add documentation for the new sysfs hints class Date: Sat, 25 Apr 2026 23:57:31 +0200 Message-ID: <20260425215734.14116-8-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715426979.3678271.16250783409712348661@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" The new sysfs hints class allows adding standardized hints to inform devices of the host state. The initial hint added is the idle hint, which allows userspace to inform devices of the host's idle state based on user interaction (e.g., inactive). Add the documentation for the new class and the currently available activity hint. Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- Documentation/ABI/testing/sysfs-class-hint | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-hint diff --git a/Documentation/ABI/testing/sysfs-class-hint b/Documentation/ABI= /testing/sysfs-class-hint new file mode 100644 index 000000000000..9d6ec956ebb4 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-hint @@ -0,0 +1,78 @@ +What: /sys/class/hint/*/name +Date: June 2026 +KernelVersion: 7.2 +Description: Name of the class device given by the driver. + + RO + +What: /sys/class/hint/*/idle_choices +Date: June 2026 +KernelVersion: 7.2 +Description: If the device supports idle states, this file contains + space-separated list of idle states supported for this device. + These states can be used to modify the runtime appearance of the + device (e.g., turn off the fan for snooze, turn off the keyboard + backlight for inactive) in response to user activity and host + state. Userspace can keep track of the idle state of the host + and inform devices with idle hint support of the current state. + + The following idle states are supported: + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D + active The user is actively interacting with the host. + The device appearance is unchanged and normal. + inactive The user has stopped interacting with the + host and triggered an inactivity timer (e.g., + lockscreen timeout) and the host displays + (if any) are off. The device may choose to + change its appearance (e.g. turn off its + backlight) or suspend if it is user facing + (e.g., handheld controller). + snooze The host enters a "dark resume" state where the + host should look like it is suspended. In + response, platform devices may turn off the + device fan, pulse the power light, or lower + the thermal envelope of the device. + resume While in the snooze state, userspace has decided + to prepare for user interaction while remaining + in snooze (e.g., user pressed a keyboard + button). If the device lowered its thermal + envelope for the snooze state, it can use this + hint to restore the normal thermal envelope and + lower the time to interaction. + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D + + Reference the following diagram for userspace implementations: + + <-> <-> <-> + -> /\ + + Where Suspend is the normal suspend path (e.g., s2idle). Devices + may support a subset of these idle states (e.g., only active and + inactive). In this case, userspace should report the closest + supported idle state that's higher than the target one. + + Examples: + 1) Device supports inactive and active: + If the desired state is snooze, choose inactive + 2) Device supports snooze and active: + If the desired state is inactive, choose active + 3) Device does not support resume: + If the desired state is resume, stay in snooze + + RO + +What: /sys/class/hint/*/idle +Date: June 2026 +KernelVersion: 7.2 +Description: Reading this file gives the current selected idle hint for + this device. Writing this file with one of the strings from + idle_choices changes the idle state to the new value. + + Depending on the device, certain transition combinations may + be disallowed. Specifically, devices can choose to reject + entering resume from a state other than snooze and re-entering + snooze from resume. In this case, the device rejects the change + with -EINVAL. + + RW --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay11.grserver.gr (relay11.grserver.gr [78.46.171.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 989D3373BEB; Sat, 25 Apr 2026 21:57:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=78.46.171.57 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154278; cv=none; b=eZSqV/CRxK9aGs/b2JocQECt9xe+PQZLE3j+1CPJwuwK0NcXnGRVg9QEJ47eGs5oNo9Ld5eZcGTyE8CySyPSV30brIZ0jW01fPRRQL+UV5bqmF+ZwA/2MBQYLk3gkO2U2bdYb2398x2sXozw6gyYIxqLpmptlWes+GCCsOI40rw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154278; c=relaxed/simple; bh=lj6qRce3XGPqnFdGjaPABbYz1BCY+7k6AN6GQM/aaPQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UgnB+z3AjtiU2yIzIIoGl0YJncuB6mBAmwF/N6dnRNdZ8LAc5MNMyP5/T9y7N5CfpRgzHr3ZHI+1sjRsC3C33NeGu1BuHEncaW1lwJOzAWwR3t4uY8HLRhPAhVa0VL+A0Y+UPam/JuGG7bvMj6vEQdeow1CRnzdiy9++QhwGxNg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=nQYUJCl/; arc=none smtp.client-ip=78.46.171.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="nQYUJCl/" Received: from relay11 (localhost.localdomain [127.0.0.1]) by relay11.grserver.gr (Proxmox) with ESMTP id 43E14C184A; Sun, 26 Apr 2026 00:57:52 +0300 (EEST) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay11.grserver.gr (Proxmox) with ESMTPS id 5C8EEC184D; Sun, 26 Apr 2026 00:57:51 +0300 (EEST) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id 34FDB1FD3FD; Sun, 26 Apr 2026 00:57:50 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154271; bh=CZYXTvGrngAfz96+uQlwavAvoJjrJQLYDMFcnTwfgjA=; h=From:To:Subject; b=nQYUJCl/ln31o1fIfxqm0XAwwANRhbuEX2+SG0fcRPH2z8CA0Z+CyoUWVB9qayxKL dyzGXupNsUq82jChl0S2dXOpiFdSsjOjIhcMuC/0n4S/O2R0HEikDaY1/XZ8/PMR18 1cHLdzaWoY1rbxy9+Qw9cjii4jNLs9XkuTAXHn/bmIfSl3NBkmxj2D1f4uz/6hW6g5 kdYbQYuyvqzurd3j1ouieGM4BAwH+1JbZb0q4fZkgUE1jQ4LIEycwne7fYWN/6TBAy aVnyR2Qy8mzFEBL6xDVqYBRCBHhZEl/EKGc5edmKAw+JuqCcicUxZcKpozU2ianeAu KI3L1r94N6xaQ== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 08/10] hint: Add hint class ABI for devices to receive updates on host activity Date: Sat, 25 Apr 2026 23:57:32 +0200 Message-ID: <20260425215734.14116-9-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715427095.3678339.13048950894727413804@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" The s2idle device requires the ability for userspace to inform of its idleness state (e.g., inactive, active, snooze) which is used to update device appearance (e.g., turn off keyboard backlight). Ideally, we would want to extend this ability to non-ACPI/non-X86 devices and drivers, e.g. memory mapped ECs, to be able to use this activity hint to for example turn off their backlight. Moreover, to prevent adding new ABIs, we would also like the ability to add new types of hints in the future. Therefore, introduce a /sys/class/hint sysfs interface, with {idle, idle_choices} to allow userspace to inform devices of its current idleness. The initial ABI for class hint makes {idle, idle_choices} optional, which allows for future hint additions that are unrelated without forcing the implementation of the idle hint. Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- MAINTAINERS | 8 ++ drivers/base/Kconfig | 3 + drivers/base/Makefile | 1 + drivers/base/hint.c | 283 ++++++++++++++++++++++++++++++++++++++++++ include/linux/hint.h | 38 ++++++ 5 files changed, 333 insertions(+) create mode 100644 drivers/base/hint.c create mode 100644 include/linux/hint.h diff --git a/MAINTAINERS b/MAINTAINERS index d1cc0e12fe1f..12712b628449 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7324,6 +7324,14 @@ F: drivers/devfreq/event/ F: include/dt-bindings/pmu/exynos_ppmu.h F: include/linux/devfreq-event.h =20 +DEVICE HINTS +M: Antheas Kapenekakis +L: driver-core@lists.linux.dev +S: Maintained +F: Documentation/ABI/testing/sysfs-class-hint +F: drivers/base/hint.c +F: include/linux/hint.h + DEVICE I/O & IRQ [RUST] M: Danilo Krummrich M: Alice Ryhl diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 1786d87b29e2..c5316e8f98d0 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -222,6 +222,9 @@ config DMA_FENCE_TRACE lockup related problems for dma-buffers shared across multiple devices. =20 +config HINT + bool + config GENERIC_ARCH_TOPOLOGY bool help diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 8074a10183dc..27557351fa20 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_GENERIC_MSI_IRQ) +=3D platform-msi.o obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) +=3D arch_topology.o obj-$(CONFIG_GENERIC_ARCH_NUMA) +=3D arch_numa.o obj-$(CONFIG_ACPI) +=3D physical_location.o +obj-$(CONFIG_HINT) +=3D hint.o =20 obj-y +=3D test/ =20 diff --git a/drivers/base/hint.c b/drivers/base/hint.c new file mode 100644 index 000000000000..0be4116d68cc --- /dev/null +++ b/drivers/base/hint.c @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* Hint sysfs interface */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +struct hint_handler { + const char *name; + struct device dev; + int minor; + struct mutex lock; /* Prevents parallel calls to class device. */ + unsigned long idle_choices[BITS_TO_LONGS(HINT_IDLE_LAST)]; + enum hint_idle_option idle; + const struct hint_ops *ops; +}; + +#define to_hint_handler(d) (container_of(d, struct hint_handler, dev)) + +static const char * const hint_idle_names[] =3D { + [HINT_IDLE_SNOOZE] =3D "snooze", + [HINT_IDLE_RESUME] =3D "resume", + [HINT_IDLE_INACTIVE] =3D "inactive", + [HINT_IDLE_ACTIVE] =3D "active", +}; +static_assert(ARRAY_SIZE(hint_idle_names) =3D=3D HINT_IDLE_LAST); + +static ssize_t name_show(struct device *dev, struct device_attribute *attr= , char *buf) +{ + struct hint_handler *handler =3D to_hint_handler(dev); + + return sysfs_emit(buf, "%s\n", handler->name); +} +static DEVICE_ATTR_RO(name); + +static ssize_t idle_choices_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hint_handler *handler =3D to_hint_handler(dev); + int i, len =3D 0; + + for_each_set_bit(i, handler->idle_choices, HINT_IDLE_LAST) { + if (len =3D=3D 0) + len +=3D sysfs_emit_at(buf, len, "%s", hint_idle_names[i]); + else + len +=3D sysfs_emit_at(buf, len, " %s", hint_idle_names[i]); + } + len +=3D sysfs_emit_at(buf, len, "\n"); + + return len; +} +static DEVICE_ATTR_RO(idle_choices); + +static ssize_t idle_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + enum hint_idle_option idle =3D HINT_IDLE_LAST; + struct hint_handler *handler =3D to_hint_handler(dev); + int err; + + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &handler->lock) { + if (!handler->ops->idle_get) + return handler->idle; + + err =3D handler->ops->idle_get(dev, &idle); + if (err) + return err; + + if (WARN_ON(idle >=3D HINT_IDLE_LAST)) + return -EINVAL; + } + + return sysfs_emit(buf, "%s\n", hint_idle_names[idle]); +} + +static ssize_t idle_store(struct device *dev, struct device_attribute *att= r, + const char *buf, size_t count) +{ + struct hint_handler *handler =3D to_hint_handler(dev); + int index, ret; + + index =3D sysfs_match_string(hint_idle_names, buf); + if (index < 0) + return -EINVAL; + + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &handler->lock) { + if (!test_bit(index, handler->idle_choices)) + return -EOPNOTSUPP; + + if (handler->ops->idle_set) { + ret =3D handler->ops->idle_set(dev, index); + if (ret) + return ret; + } + handler->idle =3D index; + } + + return count; +} +static DEVICE_ATTR_RW(idle); + +static umode_t hint_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev =3D kobj_to_dev(kobj); + struct hint_handler *handler =3D to_hint_handler(dev); + + if ((attr =3D=3D &dev_attr_idle.attr || + attr =3D=3D &dev_attr_idle_choices.attr) && + bitmap_empty(handler->idle_choices, HINT_IDLE_LAST)) + return 0; + + return attr->mode; +} + +static struct attribute *hint_attrs[] =3D { + &dev_attr_name.attr, + &dev_attr_idle_choices.attr, + &dev_attr_idle.attr, + NULL +}; + +static const struct attribute_group hint_group =3D { + .attrs =3D hint_attrs, + .is_visible =3D hint_attr_is_visible, +}; + +static const struct attribute_group *hint_groups[] =3D { + &hint_group, + NULL, +}; + +static void hint_device_release(struct device *dev) +{ + struct hint_handler *handler =3D to_hint_handler(dev); + + kfree(handler); +} + +static const struct class hint_class =3D { + .name =3D "hint", + .dev_groups =3D hint_groups, + .dev_release =3D hint_device_release, +}; + +/** + * hint_register - Creates and registers a hint class device + * @dev: Parent device + * @name: Name of the class device + * @drvdata: Driver data that will be attached to the class device + * @ops: Hint probes and getters/setters + * + * Return: pointer to the new class device on success, ERR_PTR on failure + */ +struct device *hint_register(struct device *dev, const char *name, + void *drvdata, + const struct hint_ops *ops) +{ + struct device *adev; + int minor, err; + + /* Sanity check */ + if (WARN_ON_ONCE(!dev || !name || !ops)) + return ERR_PTR(-EINVAL); + + struct hint_handler *handler __free(kfree) =3D kzalloc_obj(*handler); + if (!handler) + return ERR_PTR(-ENOMEM); + + /* + * Hint probes + */ + + if (ops->idle_probe) { + err =3D ops->idle_probe(drvdata, handler->idle_choices); + if (err) { + dev_err(dev, "idle state hint probe failed\n"); + return ERR_PTR(err); + } + handler->idle =3D + find_first_bit(handler->idle_choices, HINT_IDLE_LAST); + } + + /* create class interface for handler */ + handler->name =3D name; + handler->ops =3D ops; + handler->minor =3D minor; + handler->dev.class =3D &hint_class; + handler->dev.parent =3D dev; + mutex_init(&handler->lock); + dev_set_drvdata(&handler->dev, drvdata); + dev_set_name(&handler->dev, name, handler->minor); + + adev =3D &no_free_ptr(handler)->dev; + err =3D device_register(adev); + if (err) { + put_device(adev); + return ERR_PTR(err); + } + + return adev; +} +EXPORT_SYMBOL_GPL(hint_register); + +/** + * hint_remove - Unregisters a hint class device + * @dev: Class device + */ +void hint_remove(struct device *dev) +{ + struct hint_handler *handler; + + if (IS_ERR_OR_NULL(dev)) + return; + + handler =3D to_hint_handler(dev); + + guard(mutex)(&handler->lock); + + device_unregister(&handler->dev); +} +EXPORT_SYMBOL_GPL(hint_remove); + +static void devm_hint_release(struct device *dev, void *res) +{ + struct device **adev =3D res; + + hint_remove(*adev); +} + +/** + * devm_hint_register - Device managed version of hint_register + * @dev: Parent device + * @name: Name of the class device + * @drvdata: Driver data that will be attached to the class device + * @ops: Activity operations + * + * Return: pointer to the new class device on success, ERR_PTR on failure + */ +struct device *devm_hint_register(struct device *dev, const char *name, + void *drvdata, const struct hint_ops *ops) +{ + struct device *adev; + struct device **dr; + + dr =3D devres_alloc(devm_hint_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + adev =3D hint_register(dev, name, drvdata, ops); + if (IS_ERR(adev)) { + devres_free(dr); + return adev; + } + + *dr =3D adev; + devres_add(dev, dr); + + return adev; +} +EXPORT_SYMBOL_GPL(devm_hint_register); + +static int __init hint_init(void) +{ + return class_register(&hint_class); +} + +/* + * Required for s2idle to be able to register hints. + * module_init() would run after it tries to register the device. + */ +postcore_initcall(hint_init); + +MODULE_AUTHOR("Antheas Kapenekakis "); +MODULE_DESCRIPTION("Activity sysfs interface"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/hint.h b/include/linux/hint.h new file mode 100644 index 000000000000..56686691442c --- /dev/null +++ b/include/linux/hint.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Device hints sysfs interface + */ + +#ifndef _HINT_H_ +#define _HINT_H_ + +#include +#include + +enum hint_idle_option { + HINT_IDLE_ACTIVE, + HINT_IDLE_INACTIVE, + HINT_IDLE_SNOOZE, + HINT_IDLE_RESUME, + HINT_IDLE_LAST, /*must always be last */ +}; + +/** + * struct hint_ops - hint probes and get/set operations + * @idle_probe: Callback to setup idle hints available to the device. + * @idle_get: Will be called when showing the current idle hint in sysfs. + * @idle_set: Will be called when storing a new idle hint in sysfs. + */ +struct hint_ops { + int (*idle_probe)(void *drvdata, unsigned long *choices); + int (*idle_get)(struct device *dev, enum hint_idle_option *idle); + int (*idle_set)(struct device *dev, enum hint_idle_option idle); +}; + +struct device *hint_register(struct device *dev, const char *name, + void *drvdata, const struct hint_ops *ops); +void hint_remove(struct device *dev); +struct device *devm_hint_register(struct device *dev, const char *name, + void *drvdata, const struct hint_ops *ops); + +#endif /*_HINT_H_*/ --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay14.grserver.gr (relay14.grserver.gr [157.180.73.62]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8AE15372664; Sat, 25 Apr 2026 21:58:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=157.180.73.62 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154285; cv=none; b=ABzAiSwP88GXnYv6D52jz07UkcCBjENfrD8kIHER37m/QJcqkRmsr3gFr6UXTnp33dosWR7cHBtuojnixsC124x5KgFjg6nPHVcYpYcAa2UXOC3V/a7FvbhEF8EWGdG+KrPo0DxyxLLIte9U2uMJ0MdUCYOnveV3zyfhONOQ208= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154285; c=relaxed/simple; bh=vVC+6cEYtxb7gqifqa0c+6H57bwcrwtW76mDTsXp5XE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OzXWBR3K6Wld4IUvCh+g4msnq8BHqO7Z4o42XMd9K0DUjAlZ6f7jFkzllZBCBj0RDju31bHSD7NKiyvMKnC1ptEKOpnQ1ue2D6KP0W45gtELQIDGz05ZGeuQ03TLPwd6p5rlg+kWUdGmfEQu9rptBcHJxKnfq7zGk7BGBNaWMmk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=ojGcwztk; arc=none smtp.client-ip=157.180.73.62 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="ojGcwztk" Received: from relay14 (localhost [127.0.0.1]) by relay14.grserver.gr (Proxmox) with ESMTP id C9BF440741; Sat, 25 Apr 2026 21:57:53 +0000 (UTC) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay14.grserver.gr (Proxmox) with ESMTPS id A8970402E9; Sat, 25 Apr 2026 21:57:52 +0000 (UTC) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id 6C2BD1FD47E; Sun, 26 Apr 2026 00:57:51 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154272; bh=VDnSj6l9qWHOv14nX7xw1TlanZttqCNOtiOgraz8eL0=; h=From:To:Subject; b=ojGcwztkxYvjv8/R/NTlBKORQJe7LABAhp1JHdmlfFQHwoRBShWclaUleElSEQNip ec0nfWez5M30kJnEfZOVc/zzv2i5SRdXWwk84qYJfppV0wP3nMY3haviTmJhLes90Z qzmTEr/sIiDFFOpqnJETUJ/dUZgUE5ZQZfsMalZW81vJ5wW4aQqmNaXvpUvlXv9VBy LRRp2s4ASuWh4fRxhl4t+ML6igyZjXZZVdzs7jSLMypY9s+l2+gauEyIlYc3mzvMX7 ea87VWtK/IPkzoZi+LEcyWzTs9mpzw++sajILsKxXGzVVoAefDs/trGLvSHAvreBfq DDc7WWrd88J6g== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 09/10] acpi/x86: s2idle: Listen to idle hints to perform MS transitions Date: Sat, 25 Apr 2026 23:57:33 +0200 Message-ID: <20260425215734.14116-10-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715427215.3678391.3356729107738629691@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" Modern Standby capable devices allow controlling their appearance by userspace to appear inactive or asleep while the system is still running. Expose these states to userspace as idle hints, so userspace can leverage "dark resume" states to perform background tasks while the system appears asleep. If userspace is not idle-aware, transition to snooze and back to active as part of the normal begin() and end() callbacks, so that normal functionality (e.g., pulsing the power light) is maintained. In addition, in case we have fired the intent to turn display on notification and are in the resume idle state, the transition to s2idle is undefined behavior. Therefore, momentarily transition to active and back to snooze and emit an error, instead of bailing. Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- drivers/acpi/Kconfig | 1 + drivers/acpi/x86/s2idle.c | 226 +++++++++++++++++++++++++++++++------- 2 files changed, 186 insertions(+), 41 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 6f4b545f7377..08622ace9c67 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -14,6 +14,7 @@ menuconfig ACPI select NLS select CRC32 select FIRMWARE_TABLE + select HINT if X86 && SUSPEND # s2idle idle hint default y if X86 help Advanced Configuration and Power Interface (ACPI) support for=20 diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index 8b48f999e0e9..357d6f9406dc 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -19,6 +19,7 @@ #include #include #include +#include #include =20 #include "../sleep.h" @@ -67,6 +68,9 @@ static guid_t lps0_dsm_guid_microsoft; static int lps0_dsm_func_mask_microsoft; static int lps0_dsm_state; =20 +static enum hint_idle_option current_idle =3D HINT_IDLE_ACTIVE; +static enum hint_idle_option presuspend_idle =3D HINT_IDLE_ACTIVE; + /* Device constraint entry structure */ struct lpi_device_info { char *name; @@ -439,9 +443,171 @@ static const struct acpi_device_id amd_hid_ids[] =3D { {} }; =20 +static int acpi_s2idle_idle_probe(void *drvdata, unsigned long *choices) +{ + if (!lps0_device_handle || sleep_no_lps0) + return 0; + + if (lps0_dsm_func_mask_microsoft > 0) { + *choices |=3D BIT(HINT_IDLE_ACTIVE); + if (lps0_dsm_func_mask_microsoft & + (1 << ACPI_LPS0_DISPLAY_OFF | 1 << ACPI_LPS0_DISPLAY_ON)) + *choices |=3D BIT(HINT_IDLE_INACTIVE); + if (lps0_dsm_func_mask_microsoft & + (1 << ACPI_LPS0_SLEEP_ENTRY | 1 << ACPI_LPS0_SLEEP_EXIT)) + *choices |=3D BIT(HINT_IDLE_SNOOZE); + if (lps0_dsm_func_mask_microsoft & + (1 << ACPI_LPS0_TURN_ON_DISPLAY)) + *choices |=3D BIT(HINT_IDLE_RESUME); + } + + if (lps0_dsm_func_mask > 0) { + *choices |=3D BIT(HINT_IDLE_ACTIVE); + if (acpi_s2idle_vendor_amd()) { + if (lps0_dsm_func_mask & + (1 << ACPI_LPS0_DISPLAY_OFF_AMD | + 1 << ACPI_LPS0_DISPLAY_ON_AMD)) + *choices |=3D BIT(HINT_IDLE_INACTIVE); + } else { + if (lps0_dsm_func_mask & (1 << ACPI_LPS0_DISPLAY_OFF | + 1 << ACPI_LPS0_DISPLAY_ON)) + *choices |=3D BIT(HINT_IDLE_INACTIVE); + } + } + + return 0; +} + +static int acpi_s2idle_idle_get(struct device *dev, enum hint_idle_option = *idle) +{ + *idle =3D current_idle; + return 0; +} + +static int acpi_s2idle_idle_set(struct device *dev, enum hint_idle_option = idle) +{ + if (idle >=3D HINT_IDLE_LAST) + return -EINVAL; + + if (idle =3D=3D current_idle) + return 0; + + acpi_handle_debug(lps0_device_handle, + "Idle state transition from %d to %d\n", + current_idle, idle); + + /* Resume can only be entered if we are on the snooze state. */ + if (idle =3D=3D HINT_IDLE_RESUME) { + if (current_idle !=3D HINT_IDLE_SNOOZE) + return -EINVAL; + + if (lps0_dsm_func_mask_microsoft > 0) + acpi_sleep_run_lps0_dsm(ACPI_LPS0_TURN_ON_DISPLAY, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); + + current_idle =3D HINT_IDLE_RESUME; + return 0; + } + + /* + * The system should not be able to re-enter snooze from resume as it + * is undefined behavior. As part of setting the idle to "Resume", + * userspace promised a transition to "Inactive" or "Active". + */ + if (current_idle =3D=3D HINT_IDLE_RESUME && + idle =3D=3D HINT_IDLE_SNOOZE) + return -EINVAL; + + /* + * When leaving snooze, always fire the resume notification first if + * the device supports it. This is to counteract buggy firmware + * (e.g., Lenovo) that expects the resume notification to fire always. + */ + if (current_idle =3D=3D HINT_IDLE_SNOOZE && idle < current_idle && + lps0_dsm_func_mask_microsoft > 0) { + acpi_sleep_run_lps0_dsm(ACPI_LPS0_TURN_ON_DISPLAY, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); + } + + /* Resume is the Snooze state logic-wise. */ + if (current_idle =3D=3D HINT_IDLE_RESUME) + current_idle =3D HINT_IDLE_SNOOZE; + + if (current_idle < idle) { + for (; current_idle < idle; current_idle++) { + switch (current_idle + 1) { + case HINT_IDLE_INACTIVE: + if (lps0_dsm_func_mask > 0) + acpi_sleep_run_lps0_dsm( + acpi_s2idle_vendor_amd() ? + ACPI_LPS0_DISPLAY_OFF_AMD : + ACPI_LPS0_DISPLAY_OFF, + lps0_dsm_func_mask, + lps0_dsm_guid); + + if (lps0_dsm_func_mask_microsoft > 0) + acpi_sleep_run_lps0_dsm( + ACPI_LPS0_DISPLAY_OFF, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); + break; + case HINT_IDLE_SNOOZE: + if (lps0_dsm_func_mask_microsoft > 0) + acpi_sleep_run_lps0_dsm( + ACPI_LPS0_SLEEP_ENTRY, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); + break; + default: + break; + } + } + } else if (current_idle > idle) { + for (; current_idle > idle; current_idle--) { + switch (current_idle) { + case HINT_IDLE_INACTIVE: + if (lps0_dsm_func_mask > 0) + acpi_sleep_run_lps0_dsm( + acpi_s2idle_vendor_amd() ? + ACPI_LPS0_DISPLAY_ON_AMD : + ACPI_LPS0_DISPLAY_ON, + lps0_dsm_func_mask, + lps0_dsm_guid); + if (lps0_dsm_func_mask_microsoft > 0) + acpi_sleep_run_lps0_dsm( + ACPI_LPS0_DISPLAY_ON, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); + break; + case HINT_IDLE_SNOOZE: + if (lps0_dsm_func_mask_microsoft > 0) + acpi_sleep_run_lps0_dsm( + ACPI_LPS0_SLEEP_EXIT, + lps0_dsm_func_mask_microsoft, + lps0_dsm_guid_microsoft); + break; + default: + break; + } + } + } + + return 0; +} + +static struct hint_ops acpi_s2idle_hint_ops =3D { + .idle_probe =3D acpi_s2idle_idle_probe, + .idle_get =3D acpi_s2idle_idle_get, + .idle_set =3D acpi_s2idle_idle_set, +}; + static int lps0_device_attach(struct acpi_device *adev, const struct acpi_device_id *not_used) { + struct device *hdev; + if (lps0_device_handle) return 0; =20 @@ -508,6 +674,15 @@ static int lps0_device_attach(struct acpi_device *adev, */ acpi_ec_mark_gpe_for_wake(); =20 + /* + * Add idle hint handler to lps0_device_handle. + */ + hdev =3D devm_hint_register(&adev->dev, "s2idle", NULL, + &acpi_s2idle_hint_ops); + if (IS_ERR(hdev)) + acpi_handle_err(adev->handle, + "Failed to register idle hint device\n"); + return 0; } =20 @@ -538,23 +713,14 @@ static int acpi_s2idle_begin_lps0(void) lpi_constraints_table =3D ERR_PTR(-ENODATA); } =20 - /* Display off */ - if (lps0_dsm_func_mask > 0) - acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ? - ACPI_LPS0_DISPLAY_OFF_AMD : - ACPI_LPS0_DISPLAY_OFF, - lps0_dsm_func_mask, lps0_dsm_guid); - - if (lps0_dsm_func_mask_microsoft > 0) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_OFF, - lps0_dsm_func_mask_microsoft, - lps0_dsm_guid_microsoft); - - /* Modern Standby entry */ - if (lps0_dsm_func_mask_microsoft > 0) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_ENTRY, - lps0_dsm_func_mask_microsoft, - lps0_dsm_guid_microsoft); + presuspend_idle =3D current_idle; + if (current_idle =3D=3D HINT_IDLE_RESUME) { + acpi_handle_err( + lps0_device_handle, + "Unexpected idle state: Resume. Transitioning to active and back.\n"); + acpi_s2idle_idle_set(NULL, HINT_IDLE_ACTIVE); + } + acpi_s2idle_idle_set(NULL, HINT_IDLE_SNOOZE); =20 list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) { if (handler->begin_delay && handler->begin_delay > delay) @@ -636,30 +802,8 @@ static void acpi_s2idle_end_lps0(void) { acpi_s2idle_end(); =20 - if (!lps0_device_handle || sleep_no_lps0) - return; - - if (lps0_dsm_func_mask_microsoft > 0) { - /* Intent to turn on display */ - acpi_sleep_run_lps0_dsm(ACPI_LPS0_TURN_ON_DISPLAY, - lps0_dsm_func_mask_microsoft, - lps0_dsm_guid_microsoft); - /* Modern Standby exit */ - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_EXIT, - lps0_dsm_func_mask_microsoft, - lps0_dsm_guid_microsoft); - } - - /* Display on */ - if (lps0_dsm_func_mask_microsoft > 0) - acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_ON, - lps0_dsm_func_mask_microsoft, - lps0_dsm_guid_microsoft); - if (lps0_dsm_func_mask > 0) - acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ? - ACPI_LPS0_DISPLAY_ON_AMD : - ACPI_LPS0_DISPLAY_ON, - lps0_dsm_func_mask, lps0_dsm_guid); + if (lps0_device_handle && !sleep_no_lps0) + acpi_s2idle_idle_set(NULL, presuspend_idle); } =20 static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 =3D { --=20 2.53.0 From nobody Fri Jun 19 09:05:20 2026 Received: from relay15.grserver.gr (relay15.grserver.gr [46.62.234.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EED2436E47F; Sat, 25 Apr 2026 21:57:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.62.234.254 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154277; cv=none; b=XfdRcNjCHqBhjeDWME/VvTEataPrLAzsxx2kT7z9YuvOj+Ws7OIXdfSuVb4UrzsdDXPeaNNgf6YE3DL879b4s4BeO6dihOu9B/E+SKatVOMkQRDZaL9fCkqXh/j6hkr5kxOi5mfZXIBRuAC9AhkBOAfvCaUtyuNFthFVuaQqXoY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777154277; c=relaxed/simple; bh=rnM4kr+xfytfhGnxhf5OAD59qQ5Iw/Q4eFOqnpG5ty4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IIDORy3380MWi0Z7PLnBg9CMvL1mwNSXA9qKZwo8HmKiwE5V6vlE97dN215TJSNi4jSSTGDZ0XhRibik8C3TZ9glUOXcVBlu/Fg2sr1jStbCqKk+eYiEtk3n3HWy9UlEm30e8Tc0ebQmmNRxeZfzDiYj49lRNUYfNQy2jbbKe4k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=jfLS9Rmg; arc=none smtp.client-ip=46.62.234.254 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="jfLS9Rmg" Received: from relay15 (localhost [127.0.0.1]) by relay15.grserver.gr (Proxmox) with ESMTP id 48DAF407DF; Sat, 25 Apr 2026 21:57:54 +0000 (UTC) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay15.grserver.gr (Proxmox) with ESMTPS id C7F1E407D3; Sat, 25 Apr 2026 21:57:53 +0000 (UTC) Received: from antheas-z13 (unknown [IPv6:2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1]) by linux3247.grserver.gr (Postfix) with ESMTPSA id 887721FD3FD; Sun, 26 Apr 2026 00:57:52 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1777154273; bh=1cCY77CgxDb6pnSiiRkFPzyB1zIP5mxrDh80kv/GOaE=; h=From:To:Subject; b=jfLS9RmgCDzbgMoFn5yUWuDgmZjI1FOWHzYE8uieoiUQSyjExZMIZYOwMjHnbme4t TeQXpkmBTr3X4BkhaRG0osO1epHj9GqtXkSKnTsY71fQeEqFuEw+FX0FPpnxky9d7e i0JL5zCc1DIgjjdbsBNCSas1cLsi8TwPkhQ0JgBaSxC7FFOLayzyQWJmqiTCvpZ3B+ ukr0LUpLiHF6Osl9ZqFAUj9DBhTj447hiHmKwtGoAalRqwlT1mXnMF5OnBIudgCFYZ QtZ1QgJDtBHwMoFe/qXu2R761VEX32FgM1j2v9C/WToCNwxCXH5pNVn3eY4dUocGDK dmOPk6stoPjYA== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c5:43c3:0:378a:d3f6:f8b0:bed1) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: dmitry.osipenko@collabora.com Cc: bob.beckett@collabora.com, bookeldor@gmail.com, hadess@hadess.net, jaap@haitsma.org, kernel@collabora.com, lennart@poettering.net, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, lkml@antheas.dev, mccann@jhu.edu, rafael@kernel.org, richard@hughsie.com, sebastian.reichel@collabora.com, superm1@kernel.org, systemd-devel@lists.freedesktop.org, xaver.hugl@gmail.com Subject: [RFC v2 10/10] acpi/x86: s2idle: Subtract delay from last DSM fire in begin delay Date: Sat, 25 Apr 2026 23:57:34 +0200 Message-ID: <20260425215734.14116-11-lkml@antheas.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260425215734.14116-1-lkml@antheas.dev> References: <20260425215734.14116-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <177715427328.3678454.9608862315811293747@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" Certain devices require a small delay to settle prior to suspend after the last DSM firmware notification. Since that notification can now be fired by userspace, subtract the elapsed time since the last DSM call to lower or skip the begin quirk delay. Signed-off-by: Antheas Kapenekakis Tested-by: Dmitry Osipenko --- drivers/acpi/x86/s2idle.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index 357d6f9406dc..06f08b5a21fd 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -70,6 +70,7 @@ static int lps0_dsm_state; =20 static enum hint_idle_option current_idle =3D HINT_IDLE_ACTIVE; static enum hint_idle_option presuspend_idle =3D HINT_IDLE_ACTIVE; +static unsigned long idle_transition_jiffies; =20 /* Device constraint entry structure */ struct lpi_device_info { @@ -507,6 +508,7 @@ static int acpi_s2idle_idle_set(struct device *dev, enu= m hint_idle_option idle) lps0_dsm_guid_microsoft); =20 current_idle =3D HINT_IDLE_RESUME; + idle_transition_jiffies =3D jiffies; return 0; } =20 @@ -594,6 +596,7 @@ static int acpi_s2idle_idle_set(struct device *dev, enu= m hint_idle_option idle) } } =20 + idle_transition_jiffies =3D jiffies; return 0; } =20 @@ -694,6 +697,7 @@ static struct acpi_scan_handler lps0_handler =3D { static int acpi_s2idle_begin_lps0(void) { struct acpi_s2idle_dev_ops *handler; + unsigned int elapsed; int delay =3D 0; =20 if (!lps0_device_handle || sleep_no_lps0) @@ -726,8 +730,15 @@ static int acpi_s2idle_begin_lps0(void) if (handler->begin_delay && handler->begin_delay > delay) delay =3D handler->begin_delay; } - if (delay > 0) - msleep(delay); + if (delay > 0) { + elapsed =3D jiffies_to_msecs(jiffies - idle_transition_jiffies); + if (delay > elapsed) { + msleep(delay - elapsed); + acpi_handle_debug(lps0_device_handle, + "Waited %d ms for begin quirk\n", + delay - elapsed); + } + } =20 return acpi_s2idle_begin(); } --=20 2.53.0