Provide an interrupt availability check callback instead of a maximum IRQ

number. This accounts for possible gaps in the IO-APIC GSI mappings. Since most
of the time there will be only a single IO-APIC the extra overhead is relatively
small.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41431 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2011-05-11 08:47:56 +00:00
parent d11e32a807
commit eda743903e
3 changed files with 30 additions and 26 deletions

View File

@ -167,10 +167,17 @@ ioapic_write_64(struct ioapic& ioapic, uint8 registerSelect, uint64 value)
static bool
ioapic_is_spurious_interrupt(int32 num)
ioapic_is_interrupt_available(int32 gsi)
{
return find_ioapic(gsi) != NULL;
}
static bool
ioapic_is_spurious_interrupt(int32 gsi)
{
// the spurious interrupt vector is initialized to the max value in smp
return num == 0xff - ARCH_INTERRUPT_BASE;
return gsi == 0xff - ARCH_INTERRUPT_BASE;
}
@ -507,15 +514,9 @@ ioapic_init(kernel_args* args)
// aren't different routings based on it this is non-fatal
}
// TODO: this isn't necessarily correct, as they may not be listed in order
// of global interrupt base and there may even be gaps!
struct ioapic* lastIOAPIC = &sIOAPICs;
while (lastIOAPIC->next != NULL)
lastIOAPIC = lastIOAPIC->next;
IRQRoutingTable table;
status = prepare_irq_routing(acpiModule, table,
lastIOAPIC->global_interrupt_last + 1);
&ioapic_is_interrupt_available);
if (status != B_OK) {
dprintf("IRQ routing preparation failed, not configuring io-apics\n");
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);

View File

@ -164,7 +164,8 @@ fill_pci_info_for_entry(pci_module_info* pci, irq_routing_entry& entry)
static status_t
choose_link_device_configurations(acpi_module_info* acpi,
IRQRoutingTable& routingTable, uint32 maxIRQCount)
IRQRoutingTable& routingTable,
interrupt_available_check_function checkFunction)
{
/*
Before configuring the link devices we have to take a few things into
@ -184,7 +185,7 @@ choose_link_device_configurations(acpi_module_info* acpi,
*/
uint16 validForPCI = 0; // only applies to the ISA IRQs
uint16 irqUsage[maxIRQCount];
uint16 irqUsage[256];
memset(irqUsage, 0, sizeof(irqUsage));
// find all unique link devices and resolve their possible IRQs
@ -254,7 +255,7 @@ choose_link_device_configurations(acpi_module_info* acpi,
uint16 bestIRQUsage = UINT16_MAX;
for (int j = 0; j < link->possible_irqs.Count(); j++) {
irq_descriptor& possibleIRQ = link->possible_irqs.ElementAt(j);
if (possibleIRQ.irq >= maxIRQCount) {
if (!checkFunction(possibleIRQ.irq)) {
// we can't address this pin
continue;
}
@ -274,9 +275,8 @@ choose_link_device_configurations(acpi_module_info* acpi,
// pick that one and update the counts
irq_descriptor& chosenDescriptor
= link->possible_irqs.ElementAt(bestIRQIndex);
if (chosenDescriptor.irq >= maxIRQCount) {
dprintf("chosen irq %u is not addressable (max %lu)\n",
chosenDescriptor.irq, maxIRQCount);
if (!checkFunction(chosenDescriptor.irq)) {
dprintf("chosen irq %u is not addressable\n", chosenDescriptor.irq);
return B_ERROR;
}
@ -403,7 +403,8 @@ handle_routing_table_entry(acpi_module_info* acpi, pci_module_info* pci,
static status_t
read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
acpi_handle device, const pci_address& parentAddress,
IRQRoutingTable& table, bool rootBridge, uint32 maxIRQCount)
IRQRoutingTable& table, bool rootBridge,
interrupt_available_check_function checkFunction)
{
acpi_data buffer;
buffer.pointer = NULL;
@ -454,9 +455,8 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
status = handle_routing_table_entry(acpi, pci, acpiTable, pciAddress,
irqEntry);
if (status == B_OK) {
if (irqEntry.source == NULL && irqEntry.irq >= maxIRQCount) {
dprintf("hardwired irq %u not addressable (max %lu)\n",
irqEntry.irq, maxIRQCount);
if (irqEntry.source == NULL && !checkFunction(irqEntry.irq)) {
dprintf("hardwired irq %u not addressable\n", irqEntry.irq);
free(buffer.pointer);
return B_ERROR;
}
@ -494,7 +494,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
TRACE("recursing down to child \"%s\"\n", childName);
status = read_irq_routing_table_recursive(acpi, pci, childHandle,
pciAddress, table, false, maxIRQCount);
pciAddress, table, false, checkFunction);
if (status != B_OK)
break;
}
@ -506,7 +506,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
static status_t
read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
uint32 maxIRQCount)
interrupt_available_check_function checkFunction)
{
char rootPciName[255];
acpi_handle rootPciHandle;
@ -540,7 +540,7 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
}
status = read_irq_routing_table_recursive(acpi, pci, rootPciHandle,
rootPciAddress, table, true, maxIRQCount);
rootPciAddress, table, true, checkFunction);
put_module(B_PCI_MODULE_NAME);
@ -553,14 +553,14 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
status_t
prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable,
uint32 maxIRQCount)
interrupt_available_check_function checkFunction)
{
status_t status = read_irq_routing_table(acpi, routingTable, maxIRQCount);
status_t status = read_irq_routing_table(acpi, routingTable, checkFunction);
if (status != B_OK)
return status;
// resolve desired configuration of link devices
return choose_link_device_configurations(acpi, routingTable, maxIRQCount);
return choose_link_device_configurations(acpi, routingTable, checkFunction);
}

View File

@ -68,12 +68,15 @@ struct link_device {
};
typedef bool (*interrupt_available_check_function)(int32 globalSystemInterrupt);
void print_irq_descriptor(const irq_descriptor& descriptor);
void print_irq_routing_table(const IRQRoutingTable& table);
status_t prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& table,
uint32 maxIRQCount);
interrupt_available_check_function checkFunction);
status_t enable_irq_routing(acpi_module_info* acpi,
IRQRoutingTable& routingTable);