[haiku-commits] r41401 - haiku/trunk/src/system/kernel/arch/x86

  • From: mmlr@xxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 9 May 2011 18:46:18 +0200 (CEST)

Author: mmlr
Date: 2011-05-09 18:46:18 +0200 (Mon, 09 May 2011)
New Revision: 41401
Changeset: https://dev.haiku-os.org/changeset/41401

Modified:
   haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp
   haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp
   haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h
Log:
* 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.


Modified: haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp 2011-05-09 15:38:18 UTC 
(rev 41400)
+++ haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp 2011-05-09 16:46:18 UTC 
(rev 41401)
@@ -664,7 +664,15 @@
                return;
        }
 
-       status = enable_irq_routing(acpiModule, table);
+       sLevelTriggeredInterrupts = 0;
+       sIOAPICMaxRedirectionEntry
+               = ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT)
+                       & IO_APIC_MAX_REDIRECTION_ENTRY_MASK);
+
+       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
@@ -672,13 +680,6 @@
                return;
        }
 
-       sLevelTriggeredInterrupts = 0;
-       sIOAPICMaxRedirectionEntry
-               = ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT)
-                       & IO_APIC_MAX_REDIRECTION_ENTRY_MASK);
-
-       TRACE(("ioapic has %lu entries\n", sIOAPICMaxRedirectionEntry + 1));
-
        // use the boot CPU as the target for all interrupts
        uint64 targetAPIC = args->arch_args.cpu_apic_id[0];
 

Modified: haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp        
2011-05-09 15:38:18 UTC (rev 41400)
+++ haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp        
2011-05-09 16:46:18 UTC (rev 41401)
@@ -32,6 +32,7 @@
 
 // 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 @@
 
 
 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 @@
                  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 @@
                        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 @@
        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 @@
 
                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 @@
 
 
 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 @@
 
 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 @@
 
 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 @@
                                }
 
                                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 @@
                                }
 
                                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;

Modified: haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h  2011-05-09 
15:38:18 UTC (rev 41400)
+++ haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h  2011-05-09 
16:46:18 UTC (rev 41401)
@@ -61,7 +61,7 @@
 
 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 @@
 
 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


Other related posts:

  • » [haiku-commits] r41401 - haiku/trunk/src/system/kernel/arch/x86 - mmlr