Provide an interrupt availability check callback instead of a maximum IRQ
number. This accounts for possible gaps in the IO-APIC GSI mappings. Since most of the time there will be only a single IO-APIC the extra overhead is relatively small. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41431 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -167,10 +167,17 @@ ioapic_write_64(struct ioapic& ioapic, uint8 registerSelect, uint64 value)
|
|||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ioapic_is_spurious_interrupt(int32 num)
|
ioapic_is_interrupt_available(int32 gsi)
|
||||||
|
{
|
||||||
|
return find_ioapic(gsi) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ioapic_is_spurious_interrupt(int32 gsi)
|
||||||
{
|
{
|
||||||
// the spurious interrupt vector is initialized to the max value in smp
|
// the spurious interrupt vector is initialized to the max value in smp
|
||||||
return num == 0xff - ARCH_INTERRUPT_BASE;
|
return gsi == 0xff - ARCH_INTERRUPT_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -507,15 +514,9 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this isn't necessarily correct, as they may not be listed in order
|
|
||||||
// of global interrupt base and there may even be gaps!
|
|
||||||
struct ioapic* lastIOAPIC = &sIOAPICs;
|
|
||||||
while (lastIOAPIC->next != NULL)
|
|
||||||
lastIOAPIC = lastIOAPIC->next;
|
|
||||||
|
|
||||||
IRQRoutingTable table;
|
IRQRoutingTable table;
|
||||||
status = prepare_irq_routing(acpiModule, table,
|
status = prepare_irq_routing(acpiModule, table,
|
||||||
lastIOAPIC->global_interrupt_last + 1);
|
&ioapic_is_interrupt_available);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
dprintf("IRQ routing preparation failed, not configuring io-apics\n");
|
dprintf("IRQ routing preparation failed, not configuring io-apics\n");
|
||||||
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);
|
acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC);
|
||||||
|
|||||||
@@ -164,7 +164,8 @@ fill_pci_info_for_entry(pci_module_info* pci, irq_routing_entry& entry)
|
|||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
choose_link_device_configurations(acpi_module_info* acpi,
|
choose_link_device_configurations(acpi_module_info* acpi,
|
||||||
IRQRoutingTable& routingTable, uint32 maxIRQCount)
|
IRQRoutingTable& routingTable,
|
||||||
|
interrupt_available_check_function checkFunction)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
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
|
||||||
@@ -184,7 +185,7 @@ choose_link_device_configurations(acpi_module_info* acpi,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
uint16 validForPCI = 0; // only applies to the ISA IRQs
|
uint16 validForPCI = 0; // only applies to the ISA IRQs
|
||||||
uint16 irqUsage[maxIRQCount];
|
uint16 irqUsage[256];
|
||||||
memset(irqUsage, 0, sizeof(irqUsage));
|
memset(irqUsage, 0, sizeof(irqUsage));
|
||||||
|
|
||||||
// find all unique link devices and resolve their possible IRQs
|
// find all unique link devices and resolve their possible IRQs
|
||||||
@@ -254,7 +255,7 @@ choose_link_device_configurations(acpi_module_info* acpi,
|
|||||||
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) {
|
if (!checkFunction(possibleIRQ.irq)) {
|
||||||
// we can't address this pin
|
// we can't address this pin
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -274,9 +275,8 @@ choose_link_device_configurations(acpi_module_info* acpi,
|
|||||||
// 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) {
|
if (!checkFunction(chosenDescriptor.irq)) {
|
||||||
dprintf("chosen irq %u is not addressable (max %lu)\n",
|
dprintf("chosen irq %u is not addressable\n", chosenDescriptor.irq);
|
||||||
chosenDescriptor.irq, maxIRQCount);
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +403,8 @@ 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,
|
||||||
|
interrupt_available_check_function checkFunction)
|
||||||
{
|
{
|
||||||
acpi_data buffer;
|
acpi_data buffer;
|
||||||
buffer.pointer = NULL;
|
buffer.pointer = NULL;
|
||||||
@@ -454,9 +455,8 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
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) {
|
if (irqEntry.source == NULL && !checkFunction(irqEntry.irq)) {
|
||||||
dprintf("hardwired irq %u not addressable (max %lu)\n",
|
dprintf("hardwired irq %u not addressable\n", irqEntry.irq);
|
||||||
irqEntry.irq, maxIRQCount);
|
|
||||||
free(buffer.pointer);
|
free(buffer.pointer);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
@@ -494,7 +494,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
|
|
||||||
TRACE("recursing down to child \"%s\"\n", childName);
|
TRACE("recursing down to child \"%s\"\n", childName);
|
||||||
status = read_irq_routing_table_recursive(acpi, pci, childHandle,
|
status = read_irq_routing_table_recursive(acpi, pci, childHandle,
|
||||||
pciAddress, table, false, maxIRQCount);
|
pciAddress, table, false, checkFunction);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -506,7 +506,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci,
|
|||||||
|
|
||||||
static 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)
|
interrupt_available_check_function checkFunction)
|
||||||
{
|
{
|
||||||
char rootPciName[255];
|
char rootPciName[255];
|
||||||
acpi_handle rootPciHandle;
|
acpi_handle rootPciHandle;
|
||||||
@@ -540,7 +540,7 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = read_irq_routing_table_recursive(acpi, pci, rootPciHandle,
|
status = read_irq_routing_table_recursive(acpi, pci, rootPciHandle,
|
||||||
rootPciAddress, table, true, maxIRQCount);
|
rootPciAddress, table, true, checkFunction);
|
||||||
|
|
||||||
put_module(B_PCI_MODULE_NAME);
|
put_module(B_PCI_MODULE_NAME);
|
||||||
|
|
||||||
@@ -553,14 +553,14 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable& table,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable,
|
||||||
uint32 maxIRQCount)
|
interrupt_available_check_function checkFunction)
|
||||||
{
|
{
|
||||||
status_t status = read_irq_routing_table(acpi, routingTable, maxIRQCount);
|
status_t status = read_irq_routing_table(acpi, routingTable, checkFunction);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// resolve desired configuration of link devices
|
// resolve desired configuration of link devices
|
||||||
return choose_link_device_configurations(acpi, routingTable, maxIRQCount);
|
return choose_link_device_configurations(acpi, routingTable, checkFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,12 +68,15 @@ struct link_device {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef bool (*interrupt_available_check_function)(int32 globalSystemInterrupt);
|
||||||
|
|
||||||
|
|
||||||
void print_irq_descriptor(const irq_descriptor& descriptor);
|
void print_irq_descriptor(const irq_descriptor& descriptor);
|
||||||
void print_irq_routing_table(const IRQRoutingTable& table);
|
void print_irq_routing_table(const IRQRoutingTable& table);
|
||||||
|
|
||||||
|
|
||||||
status_t prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& table,
|
status_t prepare_irq_routing(acpi_module_info* acpi, IRQRoutingTable& table,
|
||||||
uint32 maxIRQCount);
|
interrupt_available_check_function checkFunction);
|
||||||
status_t enable_irq_routing(acpi_module_info* acpi,
|
status_t enable_irq_routing(acpi_module_info* acpi,
|
||||||
IRQRoutingTable& routingTable);
|
IRQRoutingTable& routingTable);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user