Linux PCI subsystem development
 help / color / mirror / Atom feed
From: Diogo Sousa <diogogsousa@gmail.com>
To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
Cc: Diogo Sousa <diogogsousa@gmail.com>,
	Mario Limonciello <superm1@kernel.org>,
	Vijendar Mukunda <Vijendar.Mukunda@amd.com>,
	David Glushkov <david.glushkov@sntiq.com>,
	linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] PCI: Disable async suspend for AMD rev 0x62 ACP and HD Audio
Date: Fri, 16 Oct 2026 14:50:35 +0100	[thread overview]
Message-ID: <20261016135042.44914-1-diogogsousa@gmail.com> (raw)

On AMD platforms with a revision 0x62 ACP, such as Dragon Range and Fire
Range laptops, the HD Audio controller usually stops responding after
resume from suspend:

  snd_hda_intel 0000:69:00.6: CORB reset timeout#2, CORBRP = 65535

Audio playback then stalls.

The ACP (function 5) and the HD Audio controller (function 6) share an
audio block whose power is gated by the firmware.  In the AMD CPMACPV4
SSDT, the _PS0 method of each function marks the function as present
and then calls a common method that powers the block up only if exactly
one function is present:

  Method (_PS0, 0, NotSerialized)  // ACP; AZAL sets M279 instead
  {
      M278 = One
      M276 ()
  }

  Method (M276, 0, Serialized)
  {
      Acquire (M27E, 0xFFFF)
      If (!(M278 ^ M279))
      {
          Release (M27E)
          Return (Zero)
      }

      // Power up the audio block.
      ...
  }

The presence flags are set outside the lock, and M276 calls a debug
print method before the check, during which the AML interpreter can run
other threads.  So when the PM core resumes both functions in parallel,
both flags can be set before either _PS0 reaches the check.  Both _PS0
methods then skip the power up, each assuming that the other function
did it.  An ACPICA trace of a failing resume shows exactly that: the
M276 call of the ACP sees both flags set and returns early.

Disable async suspend for both functions, so that the PM core never
suspends or resumes them at the same time.

This started with v7.1, which moved these ACPs from the RPL driver to
the YC driver.  With the ACP bound to the RPL driver, test resumes
worked, but it isn't clear why the YC driver makes the race so much
more likely.

Fixes: df4148a5a3cf ("ASoC: Add DMIC support for the AMD RPL platform")
Link: https://github.com/CachyOS/linux-cachyos/issues/950
Assisted-by: LLM
Signed-off-by: Diogo Sousa <diogogsousa@gmail.com>
---
Tested on an ASUS ROG Strix G16 G614FR (Ryzen 9 9955HX3D, BIOS G614FR.317):
without this patch (v7.2.9), every resume from s2idle broke audio; with it,
on top of v7.3-rc7, three resumes in a row worked.

This also covers the MSI Raider A18 HX A9WJG, for which a quirk matching its
subsystem ID was posted:
https://lore.kernel.org/r/20260606204547.11945-1-david.glushkov@sntiq.com

 drivers/pci/quirks.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index de9bbccda21f..d4e4ab3c332e 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1901,12 +1901,44 @@ static void quirk_jmicron_async_suspend(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, 8, quirk_jmicron_async_suspend);
 DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0, quirk_jmicron_async_suspend);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x2362, quirk_jmicron_async_suspend);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x236f, quirk_jmicron_async_suspend);
 
+/*
+ * On AMD platforms with the revision 0x62 ACP (e.g. Dragon Range and Fire
+ * Range), the firmware power gates the ACP (function 5) and HD Audio
+ * (function 6) together.  The _PS0 method of each function marks it as
+ * present and then powers up the shared audio hardware only if the other
+ * function isn't present yet.  The marking isn't done under the lock that
+ * serializes the power up, so if both _PS0 methods run concurrently, they can
+ * both conclude that the hardware is already powered up.  The HD Audio
+ * controller is then left unpowered, with all its registers reading ~0.
+ *
+ * Suspend and resume both functions synchronously, so that the PM core never
+ * transitions them at the same time.
+ */
+static void quirk_amd_acp_hda_async_suspend(struct pci_dev *pdev)
+{
+	struct pci_dev *acp;
+
+	acp = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 5));
+	if (!acp)
+		return;
+
+	if (acp->vendor == PCI_VENDOR_ID_AMD && acp->device == 0x15e2 &&
+	    acp->revision == 0x62) {
+		device_disable_async_suspend(&pdev->dev);
+		pci_info(pdev, "async suspend disabled to avoid ACP/HD Audio power up race\n");
+	}
+
+	pci_dev_put(acp);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e2, quirk_amd_acp_hda_async_suspend);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e3, quirk_amd_acp_hda_async_suspend);
+
 #ifdef CONFIG_X86_IO_APIC
 static void quirk_alder_ioapic(struct pci_dev *pdev)
 {
 	int i;
 
 	if ((pdev->class >> 8) != 0xff00)

base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053
-- 
2.56.0


             reply	other threads:[~2026-10-16 13:51 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-16 13:50 Diogo Sousa [this message]
2026-10-16 13:55 ` [PATCH] PCI: Disable async suspend for AMD rev 0x62 ACP and HD Audio sashiko-bot

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=20261016135042.44914-1-diogogsousa@gmail.com \
    --to=diogogsousa@gmail.com \
    --cc=Vijendar.Mukunda@amd.com \
    --cc=bhelgaas@google.com \
    --cc=david.glushkov@sntiq.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-sound@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