Re: [PATCH v2 2/5] platform/x86/amd/pmc: Delay suspend for some Lenovo Laptops
From: Daniel Gibson
Date: Mon May 11 2026 - 20:45:18 EST
On 11.05.26 14:24, Ilpo Järvinen wrote:
> On Sat, 9 May 2026, Daniel Gibson wrote:
>
>> Some IdeaPad Slim 3 devices and similar with AMD CPUs have a
>> nonfunctional keyboard and lid switch after s2idle.
>> It helps to delay suspend by 2.5 seconds so the EC has some time
>> to do whatever it needs to get done before suspend - unfortunately
>> at least on my 16ABR8 waking it with a timer (wakealarm) still
>> triggers the issue, but at least normal resume via keypress or
>> lid works fine.
>>
>> This issue has been reported for many different devices, this patch
>> has been tested with the Zen3-based IdeaPad Slim 3 16ABR8 (82XR)
>> and the Zen3+-based IdeaPad Slim 3 14ARP10 (83K6).
>>
>> Reported-by: Sindre Henriksen <sindrehenriksen93@xxxxxxxxx>
>> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221383
>
> Cc: stable@xxxxxxxxxxxxxxx
>
> would be warranted for this.
Same for the next patch introducing the module parameter?
I already got one report from someone using the parameter that their
laptop is affected (will include it in the next version of patches).
I fear there are more - Lenovos naming schemes are wild...
So I think it would be quite useful to get it to people using stable
kernels as well
>
>> Tested-by: Sindre Henriksen <sindrehenriksen93@xxxxxxxxx>
>> Suggested-by: Mario Limonciello (AMD) <superm1@xxxxxxxxxx>
>> Reviewed-by: Mario Limonciello (AMD) <superm1@xxxxxxxxxx>
>> Signed-off-by: Daniel Gibson <daniel@xxxxxxxxx>
>> ---
>> drivers/platform/x86/amd/pmc/pmc-quirks.c | 31 +++++++++++++++++++++++
>> drivers/platform/x86/amd/pmc/pmc.c | 24 +++++++++++++++++-
>> drivers/platform/x86/amd/pmc/pmc.h | 1 +
>> 3 files changed, 55 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/platform/x86/amd/pmc/pmc-quirks.c b/drivers/platform/x86/amd/pmc/pmc-quirks.c
>> index 24506e342943..842a8f442fb5 100644
>> --- a/drivers/platform/x86/amd/pmc/pmc-quirks.c
>> +++ b/drivers/platform/x86/amd/pmc/pmc-quirks.c
>> @@ -18,6 +18,7 @@
>> struct quirk_entry {
>> u32 s2idle_bug_mmio;
>> bool spurious_8042;
>> + bool need_suspend_delay;
>> };
>>
>> static struct quirk_entry quirk_s2idle_bug = {
>> @@ -33,6 +34,10 @@ static struct quirk_entry quirk_s2idle_spurious_8042 = {
>> .spurious_8042 = true,
>> };
>>
>> +static struct quirk_entry quirk_s2idle_need_suspend_delay = {
>> + .need_suspend_delay = true,
>> +};
>> +
>> static const struct dmi_system_id fwbug_list[] = {
>> {
>> .ident = "L14 Gen2 AMD",
>> @@ -203,6 +208,27 @@ static const struct dmi_system_id fwbug_list[] = {
>> DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"),
>> }
>> },
>> + /* https://bugzilla.kernel.org/show_bug.cgi?id=221383 */
>> + {
>> + .ident = "Zen3-based IdeaPad Slim and similar",
>> + .driver_data = &quirk_s2idle_need_suspend_delay,
>> + .matches = {
>> + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
>> + /*
>> + * Note: there are also some Zen2-based 82X* devices that
>> + * need different quirks, they're already handled above
>> + */
>> + DMI_MATCH(DMI_PRODUCT_NAME, "82X"),
>> + }
>> + },
>> + {
>> + .ident = "Zen3+-based IdeaPad Slim and similar",
>> + .driver_data = &quirk_s2idle_need_suspend_delay,
>> + .matches = {
>> + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
>> + DMI_MATCH(DMI_PRODUCT_NAME, "83K"),
>> + }
>> + },
>> /* https://bugzilla.kernel.org/show_bug.cgi?id=221273 */
>> {
>> .ident = "Thinkpad L14 Gen3",
>> @@ -356,6 +382,11 @@ void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
>> amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio);
>> }
>>
>> +bool amd_pmc_quirk_need_suspend_delay(struct amd_pmc_dev *dev)
>> +{
>> + return dev->quirks && dev->quirks->need_suspend_delay;
>> +}
>> +
>> void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
>> {
>> const struct dmi_system_id *dmi_id;
>> diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c
>> index 2b9e5730170a..6bafd8661d68 100644
>> --- a/drivers/platform/x86/amd/pmc/pmc.c
>> +++ b/drivers/platform/x86/amd/pmc/pmc.c
>> @@ -611,6 +611,27 @@ static bool amd_pmc_intermediate_wakeup_need_delay(struct amd_pmc_dev *pdev)
>> return get_metrics_table(pdev, &table) == 0 && table.s0i3_last_entry_status;
>> }
>>
>> +static bool amd_pmc_want_suspend_delay(struct amd_pmc_dev *pdev)
>> +{
>> + /*
>> + * Some Lenovo Laptops (like different IdeaPad 3 Slims) need some
>> + * me-time before sleeping or they get uncooperative after waking
>> + * up and don't send events for keyboard and lid switch anymore.
>> + *
>> + * Unfortunately this doesn't entirely fix the problem: It can still
>> + * happen when resuming with a timer (wakealarm), but at least the
>> + * more common usecases (wakeup by opening lid or pressing a key)
>> + * work fine with this workaround.
>> + *
>> + * See https://bugzilla.kernel.org/show_bug.cgi?id=221383
>> + */
>> + if (!disable_workarounds && amd_pmc_quirk_need_suspend_delay(pdev)) {
>> + dev_info(pdev->dev, "Delaying suspend by 2.5s to avoid platform bug\n");
>> + return true;
>> + }
>> + return false;
>> +}
>> +
>> static void amd_pmc_s2idle_prepare(void)
>> {
>> struct amd_pmc_dev *pdev = &pmc;
>> @@ -647,7 +668,8 @@ static void amd_pmc_s2idle_check(void)
>> struct amd_pmc_dev *pdev = &pmc;
>> int rc;
>>
>> - if (amd_pmc_intermediate_wakeup_need_delay(pdev))
>> + if (amd_pmc_intermediate_wakeup_need_delay(pdev) ||
>> + amd_pmc_want_suspend_delay(pdev))
>
> Thanks, this looks much cleaner. :-)
>
> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx>
Thanks!
>
>> msleep(2500);
>>
>> /* Dump the IdleMask before we add to the STB */
>> diff --git a/drivers/platform/x86/amd/pmc/pmc.h b/drivers/platform/x86/amd/pmc/pmc.h
>> index fe3f53eb5955..f5257e47b8c4 100644
>> --- a/drivers/platform/x86/amd/pmc/pmc.h
>> +++ b/drivers/platform/x86/amd/pmc/pmc.h
>> @@ -147,6 +147,7 @@ enum amd_pmc_def {
>> };
>>
>> void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev);
>> +bool amd_pmc_quirk_need_suspend_delay(struct amd_pmc_dev *dev);
>> void amd_pmc_quirks_init(struct amd_pmc_dev *dev);
>> void amd_mp2_stb_init(struct amd_pmc_dev *dev);
>> void amd_mp2_stb_deinit(struct amd_pmc_dev *dev);
>>
>