git: 4ba4cfaf9f29 - stable/14 - acpi: Narrow workaround for broken interrupt settings on x86
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 22 Jul 2024 20:59:19 UTC
The branch stable/14 has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=4ba4cfaf9f2991fea0d438e915df8b681a47facf
commit 4ba4cfaf9f2991fea0d438e915df8b681a47facf
Author: John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2024-07-15 19:13:08 +0000
Commit: John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-07-22 19:54:14 +0000
acpi: Narrow workaround for broken interrupt settings on x86
Commit 9a7bf07ccdc1 from 2016 introduced a workaround for some broken
BIOSes that specified active-lo instead of active-hi polarity for ISA
IRQs for UARTs. The workaround assumed that edge-sensitive ISA IRQs
on x86 should always be active-hi. However, some recent AMD systems
actually use active-lo edge-sensitive ISA IRQs (and not just for
UARTs, but also for the keyboard and PS/2 mouse devices) and the
override causes interrupts to be dropped resulting in boot time hangs,
non-working keyboards, etc.
Add a hw.acpi.override_isa_irq_polarity tunable (readable as a sysctl
post-boot) to control this quirk. It can be set to 1 to force enable
the override and 0 to disable it. The log of original message
mentions an Intel motherboard as the sample case, so default the
tunable to 1 on systems with an Intel CPU and 0 otherwise.
Special thanks to Matthias Lanter <freebsd@lanter-it.ch> for tracking
down boot time issues on recent AMD systems to mismatched interrupt
polarity.
PR: 270707
Reported by: aixdroix_OSS@protonmail.com, Michael Dexter
Reported by: mfw_burn@pm.me, Hannes Hfauswedell <h2+fbsdports@fsfe.org>
Reported by: Matthias Lanter <freebsd@lanter-it.ch>
Reported by: William Bulley <web@umich.edu>
Reviewed by: imp, emaste
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D45554
(cherry picked from commit 0a34d050ae8ea14feddd3d2a62fd2f612613b2c5)
---
share/man/man4/acpi.4 | 8 +++++++-
sys/dev/acpica/acpi.c | 19 +++++++++++++++++++
sys/dev/acpica/acpi_resource.c | 11 ++++-------
sys/dev/acpica/acpivar.h | 12 ++++++++++++
4 files changed, 42 insertions(+), 8 deletions(-)
diff --git a/share/man/man4/acpi.4 b/share/man/man4/acpi.4
index 434e97d529f5..cdad3ceeedfc 100644
--- a/share/man/man4/acpi.4
+++ b/share/man/man4/acpi.4
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 12, 2021
+.Dd July 15, 2024
.Dt ACPI 4
.Os
.Sh NAME
@@ -256,6 +256,12 @@ is a valid list of two interfaces
.Qq Li FreeBSD
and
.Qq Li Linux .
+.It Va hw.acpi.hw.acpi.override_isa_irq_polarity (x86)
+Forces active-lo polarity for edge-triggered ISA interrupts.
+Some older systems incorrectly specify active-lo polarity for ISA
+interrupts and this override fixes those systems.
+This override is enabled by default on systems with Intel CPUs,
+but can be enabled or disabled by setting the tunable explicitly.
.It Va hw.acpi.reset_video
Enables calling the VESA reset BIOS vector on the resume path.
This can fix some graphics cards that have problems such as LCD white-out
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 0894f4464162..71b19067707b 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -55,6 +55,8 @@
#if defined(__i386__) || defined(__amd64__)
#include <machine/clock.h>
#include <machine/pci_cfgreg.h>
+#include <x86/cputypes.h>
+#include <x86/x86_var.h>
#endif
#include <machine/resource.h>
#include <machine/bus.h>
@@ -289,6 +291,10 @@ int acpi_susp_bounce;
SYSCTL_INT(_debug_acpi, OID_AUTO, suspend_bounce, CTLFLAG_RW,
&acpi_susp_bounce, 0, "Don't actually suspend, just test devices.");
+#if defined(__amd64__) || defined(__i386__)
+int acpi_override_isa_irq_polarity;
+#endif
+
/*
* ACPI standard UUID for Device Specific Data Package
* "Device Properties UUID for _DSD" Rev. 2.0
@@ -601,6 +607,19 @@ acpi_attach(device_t dev)
OID_AUTO, "handle_reboot", CTLFLAG_RW,
&sc->acpi_handle_reboot, 0, "Use ACPI Reset Register to reboot");
+#if defined(__amd64__) || defined(__i386__)
+ /*
+ * Enable workaround for incorrect ISA IRQ polarity by default on
+ * systems with Intel CPUs.
+ */
+ if (cpu_vendor_id == CPU_VENDOR_INTEL)
+ acpi_override_isa_irq_polarity = 1;
+ SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
+ OID_AUTO, "override_isa_irq_polarity", CTLFLAG_RDTUN,
+ &acpi_override_isa_irq_polarity, 0,
+ "Force active-hi polarity for edge-triggered ISA IRQs");
+#endif
+
/*
* Default to 1 second before sleeping to give some machines time to
* stabilize.
diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c
index e17b891d7974..8d81d61989a8 100644
--- a/sys/dev/acpica/acpi_resource.c
+++ b/sys/dev/acpica/acpi_resource.c
@@ -159,14 +159,11 @@ acpi_config_intr(device_t dev, ACPI_RESOURCE *res)
}
#if defined(__amd64__) || defined(__i386__)
- /*
- * XXX: Certain BIOSes have buggy AML that specify an IRQ that is
- * edge-sensitive and active-lo. However, edge-sensitive IRQs
- * should be active-hi. Force IRQs with an ISA IRQ value to be
- * active-hi instead.
- */
- if (irq < 16 && trig == ACPI_EDGE_SENSITIVE && pol == ACPI_ACTIVE_LOW)
+ if (irq < 16 && trig == ACPI_EDGE_SENSITIVE && pol == ACPI_ACTIVE_LOW &&
+ acpi_override_isa_irq_polarity) {
+ device_printf(dev, "forcing active-hi polarity for IRQ %u\n", irq);
pol = ACPI_ACTIVE_HIGH;
+ }
#endif
BUS_CONFIG_INTR(dev, irq, (trig == ACPI_EDGE_SENSITIVE) ?
INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index bb969821b945..afb0a6909e1a 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -231,6 +231,18 @@ extern int acpi_quirks;
#define ACPI_Q_TIMER (1 << 1)
#define ACPI_Q_MADT_IRQ0 (1 << 2)
+#if defined(__amd64__) || defined(__i386__)
+/*
+ * Certain Intel BIOSes have buggy AML that specify an IRQ that is
+ * edge-sensitive and active-lo. Normally, edge-sensitive IRQs should
+ * be active-hi. If this value is non-zero, edge-sensitive ISA IRQs
+ * are forced to be active-hi instead. At least some AMD systems use
+ * active-lo edge-sensitive ISA IRQs, so this setting is only enabled
+ * by default on systems with Intel CPUs.
+ */
+extern int acpi_override_isa_irq_polarity;
+#endif
+
/*
* Plug and play information for device matching. Matching table format
* is compatible with ids parameter of ACPI_ID_PROBE bus method.