Check hardwired and chosen IRQs against the maximum we can address. Try to fail

gracefully in such cases (resulting in the IO-APIC not being used).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41415 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2011-05-10 09:29:57 +00:00
parent 414f205aee
commit ad1757252e
3 changed files with 46 additions and 16 deletions

View File

@ -651,7 +651,8 @@ ioapic_init(kernel_args* args)
}
IRQRoutingTable table;
status = read_irq_routing_table(acpiModule, &table);
status = read_irq_routing_table(acpiModule, &table,
sIOAPICMaxRedirectionEntry + 1);
if (status != B_OK) {
dprintf("reading IRQ routing table failed, not configuring ioapic.\n");
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);

View File

@ -254,6 +254,11 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable,
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) {
// we can't address this pin
continue;
}
if (possibleIRQ.irq < kMaxISAInterrupts
&& (validForPCI & (1 << possibleIRQ.irq)) == 0) {
// better avoid that if possible
@ -269,6 +274,12 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable,
// pick that one and update the counts
irq_descriptor& chosenDescriptor
= link->possible_irqs.ElementAt(bestIRQIndex);
if (chosenDescriptor.irq >= maxIRQCount) {
panic("chosen irq %u is not addressable (max %lu)",
chosenDescriptor.irq, maxIRQCount);
return B_ERROR;
}
irqUsage[chosenDescriptor.irq] += link->used_by.Count();
status_t status = set_current_irq(acpi, link->handle, chosenDescriptor);
@ -368,10 +379,10 @@ handle_routing_table_entry(acpi_module_info* acpi, pci_module_info* pci,
}
static void
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)
IRQRoutingTable* table, bool rootBridge, uint32 maxIRQCount)
{
acpi_data buffer;
buffer.pointer = NULL;
@ -379,7 +390,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
status_t status = acpi->get_irq_routing_table(device, &buffer);
if (status != B_OK) {
// simply not a bridge
return;
return B_OK;
}
TRACE("found irq routing table\n");
@ -401,7 +412,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
pciAddress.device, pciAddress.function, PCI_secondary_bus, 1);
if (secondaryBus == 255) {
// The bus below this bridge is inactive, nothing to do.
return;
return B_OK;
}
// The secondary bus cannot be the same as the current one.
@ -409,7 +420,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
dprintf("invalid secondary bus %u on primary bus %u,"
" can't configure irq routing of devices below\n",
secondaryBus, parentAddress.bus);
return;
return B_ERROR;
}
// Everything below is now on the secondary bus.
@ -421,8 +432,16 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
irq_routing_entry irqEntry;
status = handle_routing_table_entry(acpi, pci, acpiTable, pciAddress,
irqEntry);
if (status == B_OK)
if (status == B_OK) {
if (irqEntry.source == NULL && irqEntry.irq >= maxIRQCount) {
dprintf("hardwired irq %u not addressable (max %lu)\n",
irqEntry.irq, maxIRQCount);
free(buffer.pointer);
return B_ERROR;
}
table->PushBack(irqEntry);
}
acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable
+ acpiTable->Length);
@ -434,9 +453,10 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
acpi_data pathBuffer;
pathBuffer.pointer = NULL;
pathBuffer.length = ACPI_ALLOCATE_BUFFER;
if (acpi->ns_handle_to_pathname(device, &pathBuffer) != B_OK) {
status = acpi->ns_handle_to_pathname(device, &pathBuffer);
if (status != B_OK) {
dprintf("failed to resolve handle to path\n");
return;
return status;
}
char childName[255];
@ -448,20 +468,24 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
status = acpi->get_handle(NULL, childName, &childHandle);
if (status != B_OK) {
dprintf("failed to get handle to child \"%s\"\n", childName);
continue;
break;
}
TRACE("recursing down to child \"%s\"\n", childName);
read_irq_routing_table_recursive(acpi, pci, childHandle, pciAddress,
table, false);
status = read_irq_routing_table_recursive(acpi, pci, childHandle,
pciAddress, table, false, maxIRQCount);
if (status != B_OK)
break;
}
free(pathBuffer.pointer);
return status;
}
status_t
read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table)
read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table,
uint32 maxIRQCount)
{
char rootPciName[255];
acpi_handle rootPciHandle;
@ -494,10 +518,14 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table)
return status;
}
read_irq_routing_table_recursive(acpi, pci, rootPciHandle, rootPciAddress,
table, true);
status = read_irq_routing_table_recursive(acpi, pci, rootPciHandle,
rootPciAddress, table, true, maxIRQCount);
put_module(B_PCI_MODULE_NAME);
if (status != B_OK)
return status;
return table->Count() > 0 ? B_OK : B_ERROR;
}

View File

@ -71,7 +71,8 @@ void print_irq_descriptor(irq_descriptor* descriptor);
void print_irq_routing_table(IRQRoutingTable* table);
status_t read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table);
status_t read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table,
uint32 maxIRQCount);
status_t enable_irq_routing(acpi_module_info* acpi,
IRQRoutingTable& routingTable, uint32 maxIRQCount);