git: a64357f31b7c - stable/14 - acpi_pci: Add quirk for PSTAT_PME-before-detach
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 01 Apr 2025 17:46:17 UTC
The branch stable/14 has been updated by cperciva:
URL: https://cgit.FreeBSD.org/src/commit/?id=a64357f31b7c798452e7aca4e6ec34c2842a4fc1
commit a64357f31b7c798452e7aca4e6ec34c2842a4fc1
Author: Colin Percival <cperciva@FreeBSD.org>
AuthorDate: 2025-02-27 00:31:08 +0000
Commit: Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2025-04-01 17:43:58 +0000
acpi_pci: Add quirk for PSTAT_PME-before-detach
In order to signal to Graviton [123] systems that a device is ready
to be "ejected" (after a detach request is made via the EC2 API) we
need to set PCIM_PSTAT_PME to 1 and PCIM_PSTAT_PMEENABLE to 0. We are
not aware of any rationale for this requirement beyond "another OS
kernel happens to do this", i.e. this is effectively bug-for-bug
compatibility.
Arguably this should be done by the ACPI _EJ0 method on these systems,
but it is not.
Create a new ACPI_Q_CLEAR_PME_ON_DETACH quirk and set it in EC2 AMIs,
and add the PCI register write to acpi_pci_device_notify_handler when
that quirk is set.
Reviewed by: jhb
MFC after: 1 month
Sponsored by: Amazon
Differential Revision: https://reviews.freebsd.org/D49146
(cherry picked from commit d70bac252d30adec4feba0c866dabe2c16a756d9)
---
release/tools/ec2.conf | 7 +++++--
sys/dev/acpica/acpi_pci.c | 9 +++++++++
sys/dev/acpica/acpivar.h | 3 +++
3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/release/tools/ec2.conf b/release/tools/ec2.conf
index 1fe44118fd3e..21ea56d109ca 100644
--- a/release/tools/ec2.conf
+++ b/release/tools/ec2.conf
@@ -65,8 +65,11 @@ ec2_common() {
# Graviton 1 through Graviton 4 have a bug in their ACPI where they
# mark the PL061's pins as needing to be configured in PullUp mode
- # (in fact the PL061 has no pullup/pulldown resistors).
- echo 'debug.acpi.quirks="8"' >> ${DESTDIR}/boot/loader.conf
+ # (in fact the PL061 has no pullup/pulldown resistors). Graviton 1
+ # through Graviton 3 have non-functional PCI _EJ0 and need a value
+ # written to the PCI power status register in order to eject a
+ # device.
+ echo 'debug.acpi.quirks="24"' >> ${DESTDIR}/boot/loader.conf
# Load the kernel module for the Amazon "Elastic Network Adapter"
echo 'if_ena_load="YES"' >> ${DESTDIR}/boot/loader.conf
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index 6411af02ee58..97704111839b 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -391,6 +391,8 @@ acpi_pci_device_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
{
device_t child, dev;
ACPI_STATUS status;
+ int pmc;
+ uint16_t pmstat;
int error;
dev = context;
@@ -416,6 +418,13 @@ acpi_pci_device_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
device_get_nameunit(child), error);
return;
}
+ if ((acpi_quirks & ACPI_Q_CLEAR_PME_ON_DETACH) &&
+ (pci_find_cap(child, PCIY_PMG, &pmc) == 0)) {
+ pmstat = pci_read_config(child, pmc + PCIR_POWER_STATUS, 2);
+ pmstat &= ~PCIM_PSTAT_PMEENABLE;
+ pmstat |= PCIM_PSTAT_PME;
+ pci_write_config(child, pmc + PCIR_POWER_STATUS, pmstat, 2);
+ }
status = acpi_SetInteger(h, "_EJ0", 1);
if (ACPI_FAILURE(status)) {
bus_topo_unlock();
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index 668d0b51a1f3..830764434f48 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -230,6 +230,8 @@ extern struct mtx acpi_mutex;
* compatible flag and ignoring overrides that redirect IRQ 0 to pin 2.
* ACPI_Q_AEI_NOPULL: Specifies that _AEI objects incorrectly designate pins
* as "PullUp" and they should be treated as "NoPull" instead.
+ * ACPI_Q_CLEAR_PME_ON_DETACH: Specifies that PCIM_PSTAT_(PME & ~PMEENABLE)
+ * should be written to the power status register as part of ACPI Eject.
*/
extern int acpi_quirks;
#define ACPI_Q_OK 0
@@ -237,6 +239,7 @@ extern int acpi_quirks;
#define ACPI_Q_TIMER (1 << 1)
#define ACPI_Q_MADT_IRQ0 (1 << 2)
#define ACPI_Q_AEI_NOPULL (1 << 3)
+#define ACPI_Q_CLEAR_PME_ON_DETACH (1 << 4)
#if defined(__amd64__) || defined(__i386__)
/*