From 9173e3843e8623782de1890aea764f68426b8a63 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 10 May 2011 09:59:50 +0000 Subject: [PATCH] * Choose the desired configuration of the link devices at preparation time already. This allows to detect invalid settings before starting to enable IRQ routing and therefore allows to gracefully fall back to PIC mode on error. * Actually read the number of IO-APIC entries before using that number in routing preparation. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41416 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/arch/x86/arch_int.cpp | 25 ++++--- .../kernel/arch/x86/irq_routing_table.cpp | 69 ++++++++++++++----- .../kernel/arch/x86/irq_routing_table.h | 5 +- 3 files changed, 66 insertions(+), 33 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index eda2cfdba5..e389d02e6e 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -650,16 +650,6 @@ ioapic_init(kernel_args* args) // aren't different routings based on it this is non-fatal } - IRQRoutingTable 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); - // revert to PIC interrupt model just in case - return; - } - sLevelTriggeredInterrupts = 0; sIOAPICMaxRedirectionEntry = ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT) @@ -667,8 +657,19 @@ ioapic_init(kernel_args* args) TRACE(("ioapic has %lu entries\n", sIOAPICMaxRedirectionEntry + 1)); - status = enable_irq_routing(acpiModule, table, + IRQRoutingTable table; + status = prepare_irq_routing(acpiModule, table, sIOAPICMaxRedirectionEntry + 1); + if (status != B_OK) { + dprintf("IRQ routing preparation failed, not configuring ioapic.\n"); + acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC); + // revert to PIC interrupt model just in case + return; + } + + print_irq_routing_table(&table); + + status = enable_irq_routing(acpiModule, table); if (status != B_OK) { panic("failed to enable IRQ routing"); // if it failed early on it might still work in PIC mode @@ -709,8 +710,6 @@ ioapic_init(kernel_args* args) ioapic_write_64(IO_APIC_REDIRECTION_TABLE + 2 * i, entry); } - print_irq_routing_table(&table); - // configure io apic interrupts from PCI routing table for (int i = 0; i < table.Count(); i++) { irq_routing_entry& entry = table.ElementAt(i); diff --git a/src/system/kernel/arch/x86/irq_routing_table.cpp b/src/system/kernel/arch/x86/irq_routing_table.cpp index 3b616a8ce4..ff66b059ce 100644 --- a/src/system/kernel/arch/x86/irq_routing_table.cpp +++ b/src/system/kernel/arch/x86/irq_routing_table.cpp @@ -163,8 +163,8 @@ fill_pci_info_for_entry(pci_module_info* pci, irq_routing_entry& entry) static status_t -configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable, - uint32 maxIRQCount) +choose_link_device_configurations(acpi_module_info* acpi, + IRQRoutingTable& routingTable, uint32 maxIRQCount) { /* Before configuring the link devices we have to take a few things into @@ -275,21 +275,16 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable, irq_descriptor& chosenDescriptor = link->possible_irqs.ElementAt(bestIRQIndex); if (chosenDescriptor.irq >= maxIRQCount) { - panic("chosen irq %u is not addressable (max %lu)", + dprintf("chosen irq %u is not addressable (max %lu)\n", chosenDescriptor.irq, maxIRQCount); return B_ERROR; } irqUsage[chosenDescriptor.irq] += link->used_by.Count(); - status_t status = set_current_irq(acpi, link->handle, chosenDescriptor); - if (status != B_OK) { - panic("failed to set irq on link device"); - return status; - } - for (int j = 0; j < link->used_by.Count(); j++) { irq_routing_entry* irqEntry = link->used_by.ElementAt(j); + irqEntry->needs_configuration = j == 0; // only configure once irqEntry->irq = chosenDescriptor.irq; irqEntry->polarity = chosenDescriptor.polarity; irqEntry->trigger_mode = chosenDescriptor.trigger_mode; @@ -302,6 +297,32 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable, } +static status_t +configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable) +{ + for (int i = 0; i < routingTable.Count(); i++) { + irq_routing_entry& irqEntry = routingTable.ElementAt(i); + if (!irqEntry.needs_configuration) + continue; + + irq_descriptor configuration; + configuration.irq = irqEntry.irq; + configuration.polarity = irqEntry.polarity; + configuration.trigger_mode = irqEntry.trigger_mode; + + status_t status = set_current_irq(acpi, irqEntry.source, configuration); + if (status != B_OK) { + panic("failed to set irq on link device"); + return status; + } + + irqEntry.needs_configuration = false; + } + + return B_OK; +} + + static status_t evaluate_integer(acpi_module_info* acpi, acpi_handle handle, const char* method, uint64& value) @@ -368,8 +389,8 @@ handle_routing_table_entry(acpi_module_info* acpi, pci_module_info* pci, } if (noSource) { - // fill in the GSI and config; link based entries will be resolved at - // link configuration time + // fill in the GSI and config + irqEntry.needs_configuration = false; irqEntry.irq = irqEntry.source_index; irqEntry.polarity = B_LOW_ACTIVE_POLARITY; irqEntry.trigger_mode = B_LEVEL_TRIGGERED; @@ -382,7 +403,7 @@ 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, uint32 maxIRQCount) { acpi_data buffer; buffer.pointer = NULL; @@ -440,7 +461,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, return B_ERROR; } - table->PushBack(irqEntry); + table.PushBack(irqEntry); } acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable @@ -483,8 +504,8 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, } -status_t -read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table, +static status_t +read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table, uint32 maxIRQCount) { char rootPciName[255]; @@ -526,16 +547,28 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table, if (status != B_OK) return status; - return table->Count() > 0 ? B_OK : B_ERROR; + return table.Count() > 0 ? B_OK : B_ERROR; } status_t -enable_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable, +prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable, uint32 maxIRQCount) +{ + status_t status = read_irq_routing_table(acpi, routingTable, maxIRQCount); + if (status != B_OK) + return status; + + // resolve desired configuration of link devices + return choose_link_device_configurations(acpi, routingTable, maxIRQCount); +} + + +status_t +enable_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable) { // configure the link devices; also resolves GSIs for link based entries - status_t status = configure_link_devices(acpi, routingTable, maxIRQCount); + status_t status = configure_link_devices(acpi, routingTable); if (status != B_OK) { panic("failed to configure link devices"); return status; diff --git a/src/system/kernel/arch/x86/irq_routing_table.h b/src/system/kernel/arch/x86/irq_routing_table.h index 01cf7975bd..96d52436d0 100644 --- a/src/system/kernel/arch/x86/irq_routing_table.h +++ b/src/system/kernel/arch/x86/irq_routing_table.h @@ -19,6 +19,7 @@ struct irq_routing_entry { acpi_handle source; uint32 source_index; + bool needs_configuration; // PCI bus_manager connection uint8 pci_bus; @@ -71,10 +72,10 @@ 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 prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& table, uint32 maxIRQCount); status_t enable_irq_routing(acpi_module_info* acpi, - IRQRoutingTable& routingTable, uint32 maxIRQCount); + IRQRoutingTable& routingTable); status_t read_current_irq(acpi_module_info* acpi, acpi_handle device, irq_descriptor& descriptor);