* Balance the IRQs amongst the possible ones. A simple usage counter, filled by
hardwired GSIs and updated on configuring the link devices, is used for that. This doesn't guarantee optimal results as some link devices may not be configurable to some IRQs and we might fill up their slots this way. Most of the time this should be good enough though. * Take the BIOS assigned IRQ white list into account when assigning IRQs in the ISA range and avoid assigning to non white listed IRQs. Quite probably it'd be ok to use all of the IRQs present in the possible IRQ list, but let's play it safe... * Also white listed are the IRQs that were set on the link device before reconfiguration. * Some cleanup, use references instead of pointers where applicable. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41401 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
35ce82238f
commit
80c4e0ced0
@ -664,14 +664,6 @@ ioapic_init(kernel_args* args)
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);
|
||||
return;
|
||||
}
|
||||
|
||||
sLevelTriggeredInterrupts = 0;
|
||||
sIOAPICMaxRedirectionEntry
|
||||
= ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT)
|
||||
@ -679,6 +671,15 @@ ioapic_init(kernel_args* args)
|
||||
|
||||
TRACE(("ioapic has %lu entries\n", sIOAPICMaxRedirectionEntry + 1));
|
||||
|
||||
status = enable_irq_routing(acpiModule, table,
|
||||
sIOAPICMaxRedirectionEntry + 1);
|
||||
if (status != B_OK) {
|
||||
panic("failed to enable IRQ routing");
|
||||
// if it failed early on it might still work in PIC mode
|
||||
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);
|
||||
return;
|
||||
}
|
||||
|
||||
// use the boot CPU as the target for all interrupts
|
||||
uint64 targetAPIC = args->arch_args.cpu_apic_id[0];
|
||||
|
||||
|
@ -32,6 +32,7 @@ const char* kACPIPciExpressRootName = "PNP0A08";
|
||||
|
||||
// TODO: as per PCI 3.0, the PCI module hardcodes it in various places as well.
|
||||
static const uint8 kMaxPCIFunctionCount = 8;
|
||||
static const uint8 kMaxISAInterrupts = 16;
|
||||
|
||||
irq_descriptor::irq_descriptor()
|
||||
:
|
||||
@ -162,7 +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)
|
||||
configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
||||
uint32 maxIRQCount)
|
||||
{
|
||||
/*
|
||||
Before configuring the link devices we have to take a few things into
|
||||
@ -181,12 +183,27 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable)
|
||||
interrupt_line IRQs as stored in the bios_irq field.
|
||||
*/
|
||||
|
||||
uint16 validForPCI = 0; // only applies to the ISA IRQs
|
||||
uint16 irqUsage[maxIRQCount];
|
||||
memset(irqUsage, 0, sizeof(irqUsage));
|
||||
|
||||
// find all unique link devices and resolve their possible IRQs
|
||||
Vector<link_device*> links;
|
||||
for (int i = 0; i < routingTable.Count(); i++) {
|
||||
irq_routing_entry& irqEntry = routingTable.ElementAt(i);
|
||||
if (irqEntry.source == NULL)
|
||||
|
||||
if (irqEntry.bios_irq != 0 && irqEntry.bios_irq != 255) {
|
||||
if (irqEntry.bios_irq < kMaxISAInterrupts)
|
||||
validForPCI |= (1 << irqEntry.bios_irq);
|
||||
}
|
||||
|
||||
if (irqEntry.source == NULL) {
|
||||
// populate all hardwired GSI entries into our map
|
||||
irqUsage[irqEntry.irq]++;
|
||||
if (irqEntry.irq < kMaxISAInterrupts)
|
||||
validForPCI |= (1 << irqEntry.irq);
|
||||
continue;
|
||||
}
|
||||
|
||||
link_device* link = NULL;
|
||||
for (int j = 0; j < links.Count(); j++) {
|
||||
@ -217,6 +234,15 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = read_current_irq(acpi, link->handle, link->current_irq);
|
||||
if (status != B_OK) {
|
||||
panic("failed to read current irq of link device");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (link->current_irq.irq < kMaxISAInterrupts)
|
||||
validForPCI |= (1 << link->current_irq.irq);
|
||||
|
||||
link->used_by.PushBack(&irqEntry);
|
||||
links.PushBack(link);
|
||||
}
|
||||
@ -227,11 +253,28 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable)
|
||||
for (int i = 0; i < links.Count(); i++) {
|
||||
link_device* link = links.ElementAt(i);
|
||||
|
||||
link->chosen_irq_index = 0;
|
||||
irq_descriptor& irqDescriptor
|
||||
= link->possible_irqs.ElementAt(link->chosen_irq_index);
|
||||
int bestIRQIndex = 0;
|
||||
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 < kMaxISAInterrupts
|
||||
&& (validForPCI & (1 << possibleIRQ.irq)) == 0) {
|
||||
// better avoid that if possible
|
||||
continue;
|
||||
}
|
||||
|
||||
status_t status = set_current_irq(acpi, link->handle, &irqDescriptor);
|
||||
if (irqUsage[possibleIRQ.irq] < bestIRQUsage) {
|
||||
bestIRQIndex = j;
|
||||
bestIRQUsage = irqUsage[possibleIRQ.irq];
|
||||
}
|
||||
}
|
||||
|
||||
// pick that one and update the counts
|
||||
irq_descriptor& chosenDescriptor
|
||||
= link->possible_irqs.ElementAt(bestIRQIndex);
|
||||
irqUsage[chosenDescriptor.irq]++;
|
||||
|
||||
status_t status = set_current_irq(acpi, link->handle, chosenDescriptor);
|
||||
if (status != B_OK) {
|
||||
panic("failed to set irq on link device");
|
||||
return status;
|
||||
@ -239,9 +282,9 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable)
|
||||
|
||||
for (int j = 0; j < link->used_by.Count(); j++) {
|
||||
irq_routing_entry* irqEntry = link->used_by.ElementAt(j);
|
||||
irqEntry->irq = irqDescriptor.irq;
|
||||
irqEntry->polarity = irqDescriptor.polarity;
|
||||
irqEntry->trigger_mode = irqDescriptor.trigger_mode;
|
||||
irqEntry->irq = chosenDescriptor.irq;
|
||||
irqEntry->polarity = chosenDescriptor.polarity;
|
||||
irqEntry->trigger_mode = chosenDescriptor.trigger_mode;
|
||||
}
|
||||
|
||||
delete link;
|
||||
@ -463,10 +506,11 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table)
|
||||
|
||||
|
||||
status_t
|
||||
enable_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable)
|
||||
enable_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
||||
uint32 maxIRQCount)
|
||||
{
|
||||
// configure the link devices; also resolves GSIs for link based entries
|
||||
status_t status = configure_link_devices(acpi, routingTable);
|
||||
status_t status = configure_link_devices(acpi, routingTable, maxIRQCount);
|
||||
if (status != B_OK) {
|
||||
panic("failed to configure link devices");
|
||||
return status;
|
||||
@ -634,9 +678,9 @@ read_irq_descriptor(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)
|
||||
{
|
||||
return read_irq_descriptor(acpi, device, true, descriptor, NULL);
|
||||
return read_irq_descriptor(acpi, device, true, &descriptor, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -650,7 +694,7 @@ read_possible_irqs(acpi_module_info* acpi, acpi_handle device,
|
||||
|
||||
status_t
|
||||
set_current_irq(acpi_module_info* acpi, acpi_handle device,
|
||||
const irq_descriptor* descriptor)
|
||||
const irq_descriptor& descriptor)
|
||||
{
|
||||
acpi_data buffer;
|
||||
buffer.pointer = NULL;
|
||||
@ -675,12 +719,12 @@ set_current_irq(acpi_module_info* acpi, acpi_handle device,
|
||||
}
|
||||
|
||||
irq.Triggering
|
||||
= descriptor->trigger_mode == B_LEVEL_TRIGGERED ? 0 : 1;
|
||||
= descriptor.trigger_mode == B_LEVEL_TRIGGERED ? 0 : 1;
|
||||
irq.Polarity
|
||||
= descriptor->polarity == B_HIGH_ACTIVE_POLARITY ? 0 : 1;
|
||||
irq.Sharable = descriptor->shareable ? 0 : 1;
|
||||
= descriptor.polarity == B_HIGH_ACTIVE_POLARITY ? 0 : 1;
|
||||
irq.Sharable = descriptor.shareable ? 0 : 1;
|
||||
irq.InterruptCount = 1;
|
||||
irq.Interrupts[0] = descriptor->irq;
|
||||
irq.Interrupts[0] = descriptor.irq;
|
||||
|
||||
irqWritten = true;
|
||||
break;
|
||||
@ -695,12 +739,12 @@ set_current_irq(acpi_module_info* acpi, acpi_handle device,
|
||||
}
|
||||
|
||||
irq.Triggering
|
||||
= descriptor->trigger_mode == B_LEVEL_TRIGGERED ? 0 : 1;
|
||||
= descriptor.trigger_mode == B_LEVEL_TRIGGERED ? 0 : 1;
|
||||
irq.Polarity
|
||||
= descriptor->polarity == B_HIGH_ACTIVE_POLARITY ? 0 : 1;
|
||||
irq.Sharable = descriptor->shareable ? 0 : 1;
|
||||
= descriptor.polarity == B_HIGH_ACTIVE_POLARITY ? 0 : 1;
|
||||
irq.Sharable = descriptor.shareable ? 0 : 1;
|
||||
irq.InterruptCount = 1;
|
||||
irq.Interrupts[0] = descriptor->irq;
|
||||
irq.Interrupts[0] = descriptor.irq;
|
||||
|
||||
irqWritten = true;
|
||||
break;
|
||||
|
@ -61,7 +61,7 @@ struct pci_address {
|
||||
|
||||
struct link_device {
|
||||
acpi_handle handle;
|
||||
uint32 chosen_irq_index;
|
||||
irq_descriptor current_irq;
|
||||
Vector<irq_descriptor> possible_irqs;
|
||||
Vector<irq_routing_entry*> used_by;
|
||||
};
|
||||
@ -73,14 +73,14 @@ void print_irq_routing_table(IRQRoutingTable* table);
|
||||
|
||||
status_t read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table);
|
||||
status_t enable_irq_routing(acpi_module_info* acpi,
|
||||
IRQRoutingTable& routingTable);
|
||||
IRQRoutingTable& routingTable, uint32 maxIRQCount);
|
||||
|
||||
status_t read_current_irq(acpi_module_info* acpi, acpi_handle device,
|
||||
irq_descriptor* descriptor);
|
||||
irq_descriptor& descriptor);
|
||||
status_t read_possible_irqs(acpi_module_info* acpi, acpi_handle device,
|
||||
irq_descriptor_list& descriptorList);
|
||||
|
||||
status_t set_current_irq(acpi_module_info* acpi, acpi_handle device,
|
||||
const irq_descriptor* descriptor);
|
||||
const irq_descriptor& descriptor);
|
||||
|
||||
#endif // IRQ_ROUTING_TABLE_H
|
||||
|
Loading…
Reference in New Issue
Block a user