* 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
This commit is contained in:
Michael Lotz 2011-05-10 09:59:50 +00:00
parent ad1757252e
commit 9173e3843e
3 changed files with 66 additions and 33 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);