* 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:
@@ -650,16 +650,6 @@ ioapic_init(kernel_args* args)
|
|||||||
// aren't different routings based on it this is non-fatal
|
// 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;
|
sLevelTriggeredInterrupts = 0;
|
||||||
sIOAPICMaxRedirectionEntry
|
sIOAPICMaxRedirectionEntry
|
||||||
= ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT)
|
= ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT)
|
||||||
@@ -667,8 +657,19 @@ ioapic_init(kernel_args* args)
|
|||||||
|
|
||||||
TRACE(("ioapic has %lu entries\n", sIOAPICMaxRedirectionEntry + 1));
|
TRACE(("ioapic has %lu entries\n", sIOAPICMaxRedirectionEntry + 1));
|
||||||
|
|
||||||
status = enable_irq_routing(acpiModule, table,
|
IRQRoutingTable table;
|
||||||
|
status = prepare_irq_routing(acpiModule, table,
|
||||||
sIOAPICMaxRedirectionEntry + 1);
|
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) {
|
if (status != B_OK) {
|
||||||
panic("failed to enable IRQ routing");
|
panic("failed to enable IRQ routing");
|
||||||
// if it failed early on it might still work in PIC mode
|
// 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);
|
ioapic_write_64(IO_APIC_REDIRECTION_TABLE + 2 * i, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_irq_routing_table(&table);
|
|
||||||
|
|
||||||
// configure io apic interrupts from PCI routing table
|
// configure io apic interrupts from PCI routing table
|
||||||
for (int i = 0; i < table.Count(); i++) {
|
for (int i = 0; i < table.Count(); i++) {
|
||||||
irq_routing_entry& entry = table.ElementAt(i);
|
irq_routing_entry& entry = table.ElementAt(i);
|
||||||
|
|||||||
@@ -163,8 +163,8 @@ fill_pci_info_for_entry(pci_module_info* pci, irq_routing_entry& entry)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
choose_link_device_configurations(acpi_module_info* acpi,
|
||||||
uint32 maxIRQCount)
|
IRQRoutingTable& routingTable, uint32 maxIRQCount)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Before configuring the link devices we have to take a few things into
|
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
|
irq_descriptor& chosenDescriptor
|
||||||
= link->possible_irqs.ElementAt(bestIRQIndex);
|
= link->possible_irqs.ElementAt(bestIRQIndex);
|
||||||
if (chosenDescriptor.irq >= maxIRQCount) {
|
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);
|
chosenDescriptor.irq, maxIRQCount);
|
||||||
return B_ERROR;
|
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);
|
|
||||||
if (status != B_OK) {
|
|
||||||
panic("failed to set irq on link device");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < link->used_by.Count(); j++) {
|
for (int j = 0; j < link->used_by.Count(); j++) {
|
||||||
irq_routing_entry* irqEntry = link->used_by.ElementAt(j);
|
irq_routing_entry* irqEntry = link->used_by.ElementAt(j);
|
||||||
|
irqEntry->needs_configuration = j == 0; // only configure once
|
||||||
irqEntry->irq = chosenDescriptor.irq;
|
irqEntry->irq = chosenDescriptor.irq;
|
||||||
irqEntry->polarity = chosenDescriptor.polarity;
|
irqEntry->polarity = chosenDescriptor.polarity;
|
||||||
irqEntry->trigger_mode = chosenDescriptor.trigger_mode;
|
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
|
static status_t
|
||||||
evaluate_integer(acpi_module_info* acpi, acpi_handle handle,
|
evaluate_integer(acpi_module_info* acpi, acpi_handle handle,
|
||||||
const char* method, uint64& value)
|
const char* method, uint64& value)
|
||||||
@@ -368,8 +389,8 @@ handle_routing_table_entry(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (noSource) {
|
if (noSource) {
|
||||||
// fill in the GSI and config; link based entries will be resolved at
|
// fill in the GSI and config
|
||||||
// link configuration time
|
irqEntry.needs_configuration = false;
|
||||||
irqEntry.irq = irqEntry.source_index;
|
irqEntry.irq = irqEntry.source_index;
|
||||||
irqEntry.polarity = B_LOW_ACTIVE_POLARITY;
|
irqEntry.polarity = B_LOW_ACTIVE_POLARITY;
|
||||||
irqEntry.trigger_mode = B_LEVEL_TRIGGERED;
|
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
|
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, uint32 maxIRQCount)
|
IRQRoutingTable& table, bool rootBridge, uint32 maxIRQCount)
|
||||||
{
|
{
|
||||||
acpi_data buffer;
|
acpi_data buffer;
|
||||||
buffer.pointer = NULL;
|
buffer.pointer = NULL;
|
||||||
@@ -440,7 +461,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
table->PushBack(irqEntry);
|
table.PushBack(irqEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable
|
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
|
static status_t
|
||||||
read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table,
|
read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
|
||||||
uint32 maxIRQCount)
|
uint32 maxIRQCount)
|
||||||
{
|
{
|
||||||
char rootPciName[255];
|
char rootPciName[255];
|
||||||
@@ -526,16 +547,28 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table,
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
return table->Count() > 0 ? B_OK : B_ERROR;
|
return table.Count() > 0 ? B_OK : B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
enable_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
||||||
uint32 maxIRQCount)
|
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
|
// 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) {
|
if (status != B_OK) {
|
||||||
panic("failed to configure link devices");
|
panic("failed to configure link devices");
|
||||||
return status;
|
return status;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ struct irq_routing_entry {
|
|||||||
|
|
||||||
acpi_handle source;
|
acpi_handle source;
|
||||||
uint32 source_index;
|
uint32 source_index;
|
||||||
|
bool needs_configuration;
|
||||||
|
|
||||||
// PCI bus_manager connection
|
// PCI bus_manager connection
|
||||||
uint8 pci_bus;
|
uint8 pci_bus;
|
||||||
@@ -71,10 +72,10 @@ 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 prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& table,
|
||||||
uint32 maxIRQCount);
|
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);
|
||||||
|
|
||||||
status_t read_current_irq(acpi_module_info* acpi, acpi_handle device,
|
status_t read_current_irq(acpi_module_info* acpi, acpi_handle device,
|
||||||
irq_descriptor& descriptor);
|
irq_descriptor& descriptor);
|
||||||
|
|||||||
Reference in New Issue
Block a user