From: Mike Lothian <mike@fireburn.co.uk>
To: amd-gfx@lists.freedesktop.org, alexander.deucher@amd.com,
christian.koenig@amd.com
Cc: superm1@kernel.org, dri-devel@lists.freedesktop.org,
linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] drm/amdgpu: handle broken dGPU hotplug GPE on ASUS ROG Strix G513QY
Date: Thu, 29 Oct 2026 15:14:22 +0000 [thread overview]
Message-ID: <20261029151422.56791-3-mike@fireburn.co.uk> (raw)
In-Reply-To: <20261029151422.56791-1-mike@fireburn.co.uk>
The AMD CPM D3cold table on the G513QY (BIOS 335) handles the dGPU
hotplug GPE with:
Method (_L05) { Notify (\_SB.PCI0.GPP0.VGA, 0x81) }
On this board the Navi 22 sits behind its on-package PCIe switch, so
the dGPU node is \_SB.PCI0.GPP0.SWUS.SWDS.VGA_ and every hotplug on the
USB-C DP alt mode port while the dGPU is in D3cold logs:
ACPI BIOS Error (bug): Could not resolve symbol [\_SB.PCI0.GPP0.VGA], AE_NOT_FOUND
ACPI Error: Aborting method \_GPE._L05 due to previous error (AE_NOT_FOUND)
ACPI Error: AE_NOT_FOUND, while evaluating GPE method [_L05]
The notify is lost, the dGPU stays powered off and the external
displays stay dark. Masking the GPE (acpi_mask_gpe=0x05), the usual
workaround, removes the errors but also the hotplug.
On boards listed in a DMI table, and only when the notify target does
not resolve, install a handler for the GPE in place of the _Lxx method.
It requests a runtime resume of the dGPU, which re-detects all links and
sends a hotplug event, and re-arms the level-triggered GPE from a
delayed work so it cannot storm while the dGPU powers up. If the
firmware is fixed, or the path is supplied by an SSDT override, the
firmware method is left in charge.
Other boards using the same CPM table may need adding to the list.
Link: https://forum.endeavouros.com/t/boots-into-black-screen-unresponsive-amd/49430
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 103 ++++++++++++++++++++++-
2 files changed, 105 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index deb63122828d..d8a7fea8be9a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -642,6 +642,9 @@ struct amdgpu_device {
bool accel_working;
struct notifier_block acpi_nb;
bool acpi_dgpu_notify;
+ bool acpi_hpd_gpe_installed;
+ u32 acpi_hpd_gpe;
+ struct delayed_work acpi_hpd_gpe_work;
struct notifier_block pm_nb;
struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS];
struct debugfs_blob_wrapper debugfs_vbios_blob;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index a4041f90b374..182791f4cc86 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -25,6 +25,7 @@
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/backlight.h>
+#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/xarray.h>
#include <linux/power_supply.h>
@@ -1297,6 +1298,103 @@ static void amdgpu_acpi_dgpu_notify(acpi_handle handle, u32 event, void *data)
pm_request_resume(adev->dev);
}
+/*
+ * Some AMD CPM D3cold tables handle the dGPU hotplug GPE with
+ * Notify(\_SB.PCI0.GPP0.VGA, 0x81), but on boards where the dGPU sits behind
+ * an on-package PCIe switch the node is \_SB.PCI0.GPP0.SWUS.SWDS.VGA_, so the
+ * _Lxx method aborts with AE_NOT_FOUND and the dGPU is never woken. On those
+ * boards take over the GPE and do what the notify would have done.
+ */
+struct amdgpu_acpi_hpd_gpe_quirk {
+ const char *notify_path;
+ u32 gpe;
+};
+
+static const struct amdgpu_acpi_hpd_gpe_quirk g513qy_hpd_gpe = {
+ .notify_path = "\\_SB.PCI0.GPP0.VGA",
+ .gpe = 0x05,
+};
+
+static const struct dmi_system_id amdgpu_acpi_hpd_gpe_quirks[] = {
+ {
+ .ident = "ASUS ROG Strix G513QY",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "G513QY"),
+ },
+ .driver_data = (void *)&g513qy_hpd_gpe,
+ },
+ {}
+};
+
+/* GPE handlers run in interrupt context; the GPE stays disabled until the work re-arms it */
+static u32 amdgpu_acpi_hpd_gpe_handler(acpi_handle gpe_device, u32 gpe, void *data)
+{
+ struct amdgpu_device *adev = data;
+
+ pm_request_resume(adev->dev);
+ schedule_delayed_work(&adev->acpi_hpd_gpe_work, msecs_to_jiffies(500));
+
+ return 0;
+}
+
+/*
+ * Re-arm after a delay: the GPE is level triggered and may stay asserted
+ * while the dGPU powers up, so this bounds the rate at which it refires.
+ */
+static void amdgpu_acpi_hpd_gpe_work(struct work_struct *work)
+{
+ struct amdgpu_device *adev =
+ container_of(work, struct amdgpu_device, acpi_hpd_gpe_work.work);
+
+ acpi_finish_gpe(NULL, adev->acpi_hpd_gpe);
+}
+
+static void amdgpu_acpi_hpd_gpe_init(struct amdgpu_device *adev)
+{
+ const struct amdgpu_acpi_hpd_gpe_quirk *quirk;
+ const struct dmi_system_id *id;
+ acpi_handle handle;
+
+ id = dmi_first_match(amdgpu_acpi_hpd_gpe_quirks);
+ if (!id)
+ return;
+ quirk = id->driver_data;
+
+ /* Firmware (or a table override) already provides the notify target */
+ if (ACPI_SUCCESS(acpi_get_handle(NULL, quirk->notify_path, &handle)))
+ return;
+
+ adev->acpi_hpd_gpe = quirk->gpe;
+ INIT_DELAYED_WORK(&adev->acpi_hpd_gpe_work, amdgpu_acpi_hpd_gpe_work);
+ if (ACPI_FAILURE(acpi_install_gpe_handler(NULL, quirk->gpe,
+ ACPI_GPE_LEVEL_TRIGGERED,
+ amdgpu_acpi_hpd_gpe_handler,
+ adev)))
+ return;
+ if (ACPI_FAILURE(acpi_enable_gpe(NULL, quirk->gpe))) {
+ acpi_remove_gpe_handler(NULL, quirk->gpe,
+ amdgpu_acpi_hpd_gpe_handler);
+ return;
+ }
+
+ adev->acpi_hpd_gpe_installed = true;
+ dev_info(adev->dev, "handling dGPU hotplug GPE 0x%02x (%s missing)\n",
+ quirk->gpe, quirk->notify_path);
+}
+
+static void amdgpu_acpi_hpd_gpe_fini(struct amdgpu_device *adev)
+{
+ if (!adev->acpi_hpd_gpe_installed)
+ return;
+
+ acpi_disable_gpe(NULL, adev->acpi_hpd_gpe);
+ cancel_delayed_work_sync(&adev->acpi_hpd_gpe_work);
+ acpi_remove_gpe_handler(NULL, adev->acpi_hpd_gpe,
+ amdgpu_acpi_hpd_gpe_handler);
+ adev->acpi_hpd_gpe_installed = false;
+}
+
/* Call all ACPI methods here */
/**
* amdgpu_acpi_init - init driver acpi support
@@ -1343,12 +1441,14 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
register_acpi_notifier(&adev->acpi_nb);
if (!(adev->flags & AMD_IS_APU) && ACPI_COMPANION(adev->dev) &&
- adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO)
+ adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO) {
adev->acpi_dgpu_notify =
!acpi_dev_install_notify_handler(ACPI_COMPANION(adev->dev),
ACPI_DEVICE_NOTIFY,
amdgpu_acpi_dgpu_notify,
adev);
+ amdgpu_acpi_hpd_gpe_init(adev);
+ }
return 0;
}
@@ -1369,6 +1469,7 @@ void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps)
*/
void amdgpu_acpi_fini(struct amdgpu_device *adev)
{
+ amdgpu_acpi_hpd_gpe_fini(adev);
if (adev->acpi_dgpu_notify) {
acpi_dev_remove_notify_handler(ACPI_COMPANION(adev->dev),
ACPI_DEVICE_NOTIFY,
--
2.56.0
next prev parent reply other threads:[~2026-10-29 15:14 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 15:14 [PATCH 0/2] drm/amdgpu: wake a powered-off dGPU on a dock hotplug notify Mike Lothian
2026-10-29 15:14 ` [PATCH 1/2] drm/amdgpu: runtime resume dGPU on ACPI notify from its own node Mike Lothian
2026-10-29 15:20 ` Mario Limonciello
2026-10-29 16:05 ` Alex Deucher
2026-10-29 15:14 ` Mike Lothian [this message]
2026-10-29 15:24 ` [PATCH 2/2] drm/amdgpu: handle broken dGPU hotplug GPE on ASUS ROG Strix G513QY Mario Limonciello
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261029151422.56791-3-mike@fireburn.co.uk \
--to=mike@fireburn.co.uk \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=superm1@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®