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:
@@ -651,7 +651,8 @@ ioapic_init(kernel_args* args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
IRQRoutingTable table;
|
IRQRoutingTable table;
|
||||||
status = read_irq_routing_table(acpiModule, &table);
|
status = read_irq_routing_table(acpiModule, &table,
|
||||||
|
sIOAPICMaxRedirectionEntry + 1);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
dprintf("reading IRQ routing table failed, not configuring ioapic.\n");
|
dprintf("reading IRQ routing table failed, not configuring ioapic.\n");
|
||||||
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);
|
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);
|
||||||
|
|||||||
@@ -254,6 +254,11 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
|||||||
uint16 bestIRQUsage = UINT16_MAX;
|
uint16 bestIRQUsage = UINT16_MAX;
|
||||||
for (int j = 0; j < link->possible_irqs.Count(); j++) {
|
for (int j = 0; j < link->possible_irqs.Count(); j++) {
|
||||||
irq_descriptor& possibleIRQ = link->possible_irqs.ElementAt(j);
|
irq_descriptor& possibleIRQ = link->possible_irqs.ElementAt(j);
|
||||||
|
if (possibleIRQ.irq >= maxIRQCount) {
|
||||||
|
// we can't address this pin
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (possibleIRQ.irq < kMaxISAInterrupts
|
if (possibleIRQ.irq < kMaxISAInterrupts
|
||||||
&& (validForPCI & (1 << possibleIRQ.irq)) == 0) {
|
&& (validForPCI & (1 << possibleIRQ.irq)) == 0) {
|
||||||
// better avoid that if possible
|
// 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
|
// pick that one and update the counts
|
||||||
irq_descriptor& chosenDescriptor
|
irq_descriptor& chosenDescriptor
|
||||||
= link->possible_irqs.ElementAt(bestIRQIndex);
|
= 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();
|
irqUsage[chosenDescriptor.irq] += link->used_by.Count();
|
||||||
|
|
||||||
status_t status = set_current_irq(acpi, link->handle, chosenDescriptor);
|
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,
|
read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
||||||
acpi_handle device, const pci_address& parentAddress,
|
acpi_handle device, const pci_address& parentAddress,
|
||||||
IRQRoutingTable* table, bool rootBridge)
|
IRQRoutingTable* table, bool rootBridge, uint32 maxIRQCount)
|
||||||
{
|
{
|
||||||
acpi_data buffer;
|
acpi_data buffer;
|
||||||
buffer.pointer = NULL;
|
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);
|
status_t status = acpi->get_irq_routing_table(device, &buffer);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
// simply not a bridge
|
// simply not a bridge
|
||||||
return;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("found irq routing table\n");
|
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);
|
pciAddress.device, pciAddress.function, PCI_secondary_bus, 1);
|
||||||
if (secondaryBus == 255) {
|
if (secondaryBus == 255) {
|
||||||
// The bus below this bridge is inactive, nothing to do.
|
// 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.
|
// 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,"
|
dprintf("invalid secondary bus %u on primary bus %u,"
|
||||||
" can't configure irq routing of devices below\n",
|
" can't configure irq routing of devices below\n",
|
||||||
secondaryBus, parentAddress.bus);
|
secondaryBus, parentAddress.bus);
|
||||||
return;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything below is now on the secondary bus.
|
// 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;
|
irq_routing_entry irqEntry;
|
||||||
status = handle_routing_table_entry(acpi, pci, acpiTable, pciAddress,
|
status = handle_routing_table_entry(acpi, pci, acpiTable, pciAddress,
|
||||||
irqEntry);
|
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);
|
table->PushBack(irqEntry);
|
||||||
|
}
|
||||||
|
|
||||||
acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable
|
acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable
|
||||||
+ acpiTable->Length);
|
+ acpiTable->Length);
|
||||||
@@ -434,9 +453,10 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
acpi_data pathBuffer;
|
acpi_data pathBuffer;
|
||||||
pathBuffer.pointer = NULL;
|
pathBuffer.pointer = NULL;
|
||||||
pathBuffer.length = ACPI_ALLOCATE_BUFFER;
|
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");
|
dprintf("failed to resolve handle to path\n");
|
||||||
return;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
char childName[255];
|
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);
|
status = acpi->get_handle(NULL, childName, &childHandle);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
dprintf("failed to get handle to child \"%s\"\n", childName);
|
dprintf("failed to get handle to child \"%s\"\n", childName);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("recursing down to child \"%s\"\n", childName);
|
TRACE("recursing down to child \"%s\"\n", childName);
|
||||||
read_irq_routing_table_recursive(acpi, pci, childHandle, pciAddress,
|
status = read_irq_routing_table_recursive(acpi, pci, childHandle,
|
||||||
table, false);
|
pciAddress, table, false, maxIRQCount);
|
||||||
|
if (status != B_OK)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pathBuffer.pointer);
|
free(pathBuffer.pointer);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
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];
|
char rootPciName[255];
|
||||||
acpi_handle rootPciHandle;
|
acpi_handle rootPciHandle;
|
||||||
@@ -494,10 +518,14 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_irq_routing_table_recursive(acpi, pci, rootPciHandle, rootPciAddress,
|
status = read_irq_routing_table_recursive(acpi, pci, rootPciHandle,
|
||||||
table, true);
|
rootPciAddress, table, true, maxIRQCount);
|
||||||
|
|
||||||
put_module(B_PCI_MODULE_NAME);
|
put_module(B_PCI_MODULE_NAME);
|
||||||
|
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
return table->Count() > 0 ? B_OK : B_ERROR;
|
return table->Count() > 0 ? B_OK : B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ void print_irq_descriptor(irq_descriptor* descriptor);
|
|||||||
void print_irq_routing_table(IRQRoutingTable* table);
|
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,
|
status_t enable_irq_routing(acpi_module_info* acpi,
|
||||||
IRQRoutingTable& routingTable, uint32 maxIRQCount);
|
IRQRoutingTable& routingTable, uint32 maxIRQCount);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user