acpica: rework INTRNG interrupts
On arm64 (where INTRNG is enabled), the interrupts have to be mapped with ACPI_BUS_MAP_INTR() before adding them as resources to devices. The earlier code did the mapping before calling acpi_set_resource(), which bypassed code that checked for PCI link interrupts. To fix this, move the call to map interrupts into acpi_set_resource() and that requires additional work to lookup interrupt properties. The changes here are to: * extend acpi_lookup_irq_handler() to lookup an irq in the ACPI resources * create a helper function acpi_map_intr() which uses the updated acpi_lookup_irq_handler() to look up an irq, and then map it with ACPI_BUS_MAP_INTR() * use acpi_map_intr() in acpi_pcib_route_interrupt() to map pci link interrupts. With these changes, we can drop the ifdefs in acpi_resource.c, and we can also drop the call for mapping interrupts in generic_timer.c Reviewed by: andrew Differential Revision: https://reviews.freebsd.org/D17790
This commit is contained in:
parent
697c57e5c7
commit
d4d6ad3f05
@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#ifdef DEV_ACPI
|
#ifdef DEV_ACPI
|
||||||
#include <contrib/dev/acpica/include/acpi.h>
|
#include <contrib/dev/acpica/include/acpi.h>
|
||||||
#include <dev/acpica/acpivar.h>
|
#include <dev/acpica/acpivar.h>
|
||||||
#include "acpi_bus_if.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GT_CTRL_ENABLE (1 << 0)
|
#define GT_CTRL_ENABLE (1 << 0)
|
||||||
@ -340,8 +339,6 @@ static void
|
|||||||
arm_tmr_acpi_add_irq(device_t parent, device_t dev, int rid, u_int irq)
|
arm_tmr_acpi_add_irq(device_t parent, device_t dev, int rid, u_int irq)
|
||||||
{
|
{
|
||||||
|
|
||||||
irq = ACPI_BUS_MAP_INTR(parent, dev, irq,
|
|
||||||
INTR_TRIGGER_LEVEL, INTR_POLARITY_HIGH);
|
|
||||||
BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, rid, irq, 1);
|
BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, rid, irq, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,6 +1319,13 @@ acpi_set_resource(device_t dev, device_t child, int type, int rid,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef INTRNG
|
||||||
|
/* map with default for now */
|
||||||
|
if (type == SYS_RES_IRQ)
|
||||||
|
start = (rman_res_t)acpi_map_intr(child, (u_int)start,
|
||||||
|
acpi_get_handle(child));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If the resource is already allocated, fail. */
|
/* If the resource is already allocated, fail. */
|
||||||
if (resource_list_busy(rl, type, rid))
|
if (resource_list_busy(rl, type, rid))
|
||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
|
@ -188,6 +188,7 @@ acpi_pcib_route_interrupt(device_t pcib, device_t dev, int pin,
|
|||||||
|
|
||||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
||||||
|
|
||||||
|
lnkdev = NULL;
|
||||||
interrupt = PCI_INVALID_IRQ;
|
interrupt = PCI_INVALID_IRQ;
|
||||||
|
|
||||||
/* ACPI numbers pins 0-3, not 1-4 like the BIOS. */
|
/* ACPI numbers pins 0-3, not 1-4 like the BIOS. */
|
||||||
@ -252,7 +253,12 @@ acpi_pcib_route_interrupt(device_t pcib, device_t dev, int pin,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
ACPI_SERIAL_END(pcib);
|
ACPI_SERIAL_END(pcib);
|
||||||
|
#ifdef INTRNG
|
||||||
|
if (PCI_INTERRUPT_VALID(interrupt)) {
|
||||||
|
interrupt = acpi_map_intr(dev, interrupt, lnkdev);
|
||||||
|
KASSERT(PCI_INTERRUPT_VALID(interrupt), ("mapping fail"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return_VALUE(interrupt);
|
return_VALUE(interrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,10 +55,13 @@ ACPI_MODULE_NAME("RESOURCE")
|
|||||||
|
|
||||||
struct lookup_irq_request {
|
struct lookup_irq_request {
|
||||||
ACPI_RESOURCE *acpi_res;
|
ACPI_RESOURCE *acpi_res;
|
||||||
struct resource *res;
|
u_int irq;
|
||||||
int counter;
|
int counter;
|
||||||
int rid;
|
int rid;
|
||||||
int found;
|
int found;
|
||||||
|
int checkrid;
|
||||||
|
int trig;
|
||||||
|
int pol;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ACPI_STATUS
|
static ACPI_STATUS
|
||||||
@ -66,18 +69,22 @@ acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context)
|
|||||||
{
|
{
|
||||||
struct lookup_irq_request *req;
|
struct lookup_irq_request *req;
|
||||||
size_t len;
|
size_t len;
|
||||||
u_int irqnum, irq;
|
u_int irqnum, irq, trig, pol;
|
||||||
|
|
||||||
switch (res->Type) {
|
switch (res->Type) {
|
||||||
case ACPI_RESOURCE_TYPE_IRQ:
|
case ACPI_RESOURCE_TYPE_IRQ:
|
||||||
irqnum = res->Data.Irq.InterruptCount;
|
irqnum = res->Data.Irq.InterruptCount;
|
||||||
irq = res->Data.Irq.Interrupts[0];
|
irq = res->Data.Irq.Interrupts[0];
|
||||||
len = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
|
len = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
|
||||||
|
trig = res->Data.Irq.Triggering;
|
||||||
|
pol = res->Data.Irq.Polarity;
|
||||||
break;
|
break;
|
||||||
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
|
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
|
||||||
irqnum = res->Data.ExtendedIrq.InterruptCount;
|
irqnum = res->Data.ExtendedIrq.InterruptCount;
|
||||||
irq = res->Data.ExtendedIrq.Interrupts[0];
|
irq = res->Data.ExtendedIrq.Interrupts[0];
|
||||||
len = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
|
len = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
|
||||||
|
trig = res->Data.ExtendedIrq.Triggering;
|
||||||
|
pol = res->Data.ExtendedIrq.Polarity;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return (AE_OK);
|
return (AE_OK);
|
||||||
@ -85,14 +92,21 @@ acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context)
|
|||||||
if (irqnum != 1)
|
if (irqnum != 1)
|
||||||
return (AE_OK);
|
return (AE_OK);
|
||||||
req = (struct lookup_irq_request *)context;
|
req = (struct lookup_irq_request *)context;
|
||||||
if (req->counter != req->rid) {
|
if (req->checkrid) {
|
||||||
req->counter++;
|
if (req->counter != req->rid) {
|
||||||
return (AE_OK);
|
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->found = 1;
|
||||||
KASSERT(irq == rman_get_start(req->res),
|
req->pol = pol;
|
||||||
("IRQ resources do not match"));
|
req->trig = trig;
|
||||||
bcopy(res, req->acpi_res, len);
|
if (req->acpi_res != NULL)
|
||||||
|
bcopy(res, req->acpi_res, len);
|
||||||
return (AE_CTRL_TERMINATE);
|
return (AE_CTRL_TERMINATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,10 +118,11 @@ acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res,
|
|||||||
ACPI_STATUS status;
|
ACPI_STATUS status;
|
||||||
|
|
||||||
req.acpi_res = acpi_res;
|
req.acpi_res = acpi_res;
|
||||||
req.res = res;
|
req.irq = rman_get_start(res);
|
||||||
req.counter = 0;
|
req.counter = 0;
|
||||||
req.rid = rid;
|
req.rid = rid;
|
||||||
req.found = 0;
|
req.found = 0;
|
||||||
|
req.checkrid = 1;
|
||||||
status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
|
status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
|
||||||
acpi_lookup_irq_handler, &req);
|
acpi_lookup_irq_handler, &req);
|
||||||
if (ACPI_SUCCESS(status) && req.found == 0)
|
if (ACPI_SUCCESS(status) && req.found == 0)
|
||||||
@ -155,6 +170,34 @@ acpi_config_intr(device_t dev, ACPI_RESOURCE *res)
|
|||||||
INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
|
INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef INTRNG
|
||||||
|
int
|
||||||
|
acpi_map_intr(device_t dev, u_int irq, ACPI_HANDLE handle)
|
||||||
|
{
|
||||||
|
struct lookup_irq_request req;
|
||||||
|
int trig, pol;
|
||||||
|
|
||||||
|
trig = ACPI_LEVEL_SENSITIVE;
|
||||||
|
pol = ACPI_ACTIVE_HIGH;
|
||||||
|
if (handle != NULL) {
|
||||||
|
req.found = 0;
|
||||||
|
req.acpi_res = NULL;
|
||||||
|
req.irq = irq;
|
||||||
|
req.counter = 0;
|
||||||
|
req.rid = 0;
|
||||||
|
req.checkrid = 0;
|
||||||
|
AcpiWalkResources(handle, "_CRS", acpi_lookup_irq_handler, &req);
|
||||||
|
if (req.found != 0) {
|
||||||
|
trig = req.trig;
|
||||||
|
pol = req.pol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, irq,
|
||||||
|
(trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
|
||||||
|
(pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct acpi_resource_context {
|
struct acpi_resource_context {
|
||||||
struct acpi_parse_resource_set *set;
|
struct acpi_parse_resource_set *set;
|
||||||
device_t dev;
|
device_t dev;
|
||||||
@ -591,13 +634,7 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count,
|
|||||||
if (count != 1)
|
if (count != 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef INTRNG
|
|
||||||
intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq,
|
|
||||||
(trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
|
|
||||||
(pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
|
|
||||||
#else
|
|
||||||
intr = *irq;
|
intr = *irq;
|
||||||
#endif
|
|
||||||
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
|
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,13 +652,7 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count,
|
|||||||
if (count != 1)
|
if (count != 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef INTRNG
|
|
||||||
intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq,
|
|
||||||
(trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
|
|
||||||
(pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
|
|
||||||
#else
|
|
||||||
intr = *irq;
|
intr = *irq;
|
||||||
#endif
|
|
||||||
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
|
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,6 +403,9 @@ extern struct acpi_parse_resource_set acpi_res_parse_set;
|
|||||||
|
|
||||||
int acpi_identify(void);
|
int acpi_identify(void);
|
||||||
void acpi_config_intr(device_t dev, ACPI_RESOURCE *res);
|
void acpi_config_intr(device_t dev, ACPI_RESOURCE *res);
|
||||||
|
#ifdef INTRNG
|
||||||
|
int acpi_map_intr(device_t dev, u_int irq, ACPI_HANDLE handle);
|
||||||
|
#endif
|
||||||
ACPI_STATUS acpi_lookup_irq_resource(device_t dev, int rid,
|
ACPI_STATUS acpi_lookup_irq_resource(device_t dev, int rid,
|
||||||
struct resource *res, ACPI_RESOURCE *acpi_res);
|
struct resource *res, ACPI_RESOURCE *acpi_res);
|
||||||
ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
|
ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
|
||||||
|
Loading…
Reference in New Issue
Block a user