git: a1330a71d20d - main - acpi: Handle multiple interrupts
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 19 Nov 2024 17:47:01 UTC
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=a1330a71d20d862eb9d930d87245f23ee4853527 commit a1330a71d20d862eb9d930d87245f23ee4853527 Author: Andrew Turner <andrew@FreeBSD.org> AuthorDate: 2024-11-18 15:29:42 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2024-11-19 17:14:42 +0000 acpi: Handle multiple interrupts When multiple IRQs are specified in a single resource then we only check the first. Change this to check all interrupts for the value we expect to find. Without this we may still enable the interrupt, but it can have the wrong polatiry or trigger. This can cause an interrupt storm if the interrupt was configured with a level trigger when it should have been an edge. PR: 282241 Reported by: trasz Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D47487 --- sys/dev/acpica/acpi_resource.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c index 1257ed30cc65..8c5a3ed57f32 100644 --- a/sys/dev/acpica/acpi_resource.c +++ b/sys/dev/acpica/acpi_resource.c @@ -72,19 +72,33 @@ acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context) { struct lookup_irq_request *req; size_t len; - u_int irqnum, irq, trig, pol; + u_int irqnum, trig, pol; + bool found; + + found = false; + req = (struct lookup_irq_request *)context; switch (res->Type) { case ACPI_RESOURCE_TYPE_IRQ: irqnum = res->Data.Irq.InterruptCount; - irq = res->Data.Irq.Interrupts[0]; + for (int i = 0; i < irqnum; i++) { + if (res->Data.Irq.Interrupts[i] == req->irq) { + found = true; + break; + } + } len = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ); trig = res->Data.Irq.Triggering; pol = res->Data.Irq.Polarity; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: irqnum = res->Data.ExtendedIrq.InterruptCount; - irq = res->Data.ExtendedIrq.Interrupts[0]; + for (int i = 0; i < irqnum; i++) { + if (res->Data.ExtendedIrq.Interrupts[i] == req->irq) { + found = true; + break; + } + } len = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ); trig = res->Data.ExtendedIrq.Triggering; pol = res->Data.ExtendedIrq.Polarity; @@ -92,18 +106,13 @@ acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context) default: return (AE_OK); } - if (irqnum != 1) + if (!found) return (AE_OK); - req = (struct lookup_irq_request *)context; if (req->checkrid) { if (req->counter != req->rid) { req->counter++; return (AE_OK); } - KASSERT(irq == req->irq, ("IRQ resources do not match")); - } else { - if (req->irq != irq) - return (AE_OK); } req->found = 1; req->pol = pol;