drivers/interrupt_controller: Get the IOAPIC RTEs dynamically
The fixed number of 24 RTEs is a legacy thing, and long gone by now.
IOAPICs expose the maximum number of RTEs they have via the version
register, so let's use it.
This avoids to manually tweak a Kconfig option (which is now removed)
and fixes the RTE number for all x86 targets relevantly.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
diff --git a/drivers/interrupt_controller/Kconfig.loapic b/drivers/interrupt_controller/Kconfig.loapic
index 251b6b0..61dfe60 100644
--- a/drivers/interrupt_controller/Kconfig.loapic
+++ b/drivers/interrupt_controller/Kconfig.loapic
@@ -49,17 +49,6 @@
This option signifies that the target has an IO-APIC device. This
capability allows IO-APIC-dependent code to be included.
-config IOAPIC_NUM_RTES
- int "Number of Redirection Table Entries available"
- default 24
- depends on IOAPIC
- help
- This option indicates the maximum number of Redirection Table Entries
- (RTEs) (one per IRQ available to the IO-APIC) made available to the
- kernel, regardless of the number provided by the hardware itself. For
- most efficient usage of memory, it should match the number of IRQ lines
- needed by devices connected to the IO-APIC.
-
config IOAPIC_MASK_RTE
bool "Mask out RTE entries on boot"
default y
diff --git a/drivers/interrupt_controller/intc_ioapic.c b/drivers/interrupt_controller/intc_ioapic.c
index 1269ba3..f324681 100644
--- a/drivers/interrupt_controller/intc_ioapic.c
+++ b/drivers/interrupt_controller/intc_ioapic.c
@@ -67,13 +67,6 @@
DEVICE_MMIO_TOPLEVEL_STATIC(ioapic_regs, DT_DRV_INST(0));
#define IOAPIC_REG DEVICE_MMIO_TOPLEVEL_GET(ioapic_regs)
-#define BITS_PER_IRQ 4
-#define IOAPIC_BITFIELD_HI_LO 0
-#define IOAPIC_BITFIELD_LVL_EDGE 1
-#define IOAPIC_BITFIELD_ENBL_DSBL 2
-#define IOAPIC_BITFIELD_DELIV_MODE 3
-#define BIT_POS_FOR_IRQ_OPTION(irq, option) ((irq) * BITS_PER_IRQ + (option))
-#define SUSPEND_BITS_REQD (ROUND_UP((CONFIG_IOAPIC_NUM_RTES * BITS_PER_IRQ), 32))
/*
* Destination field (bits[56:63]) defines a set of processors, which is
@@ -92,10 +85,27 @@
*/
#define DEFAULT_RTE_DEST (0xFF << 24)
+static uint32_t ioapic_rtes;
+
#ifdef CONFIG_PM_DEVICE
#include <power/power.h>
+
+#define BITS_PER_IRQ 4
+#define IOAPIC_BITFIELD_HI_LO 0
+#define IOAPIC_BITFIELD_LVL_EDGE 1
+#define IOAPIC_BITFIELD_ENBL_DSBL 2
+#define IOAPIC_BITFIELD_DELIV_MODE 3
+
+#define BIT_POS_FOR_IRQ_OPTION(irq, option) ((irq) * BITS_PER_IRQ + (option))
+
+/* Allocating up to 256 irq bits bufffer for RTEs, RTEs are dynamically found
+ * so let's just assume the maximum, it's only 128 bytes in total.
+ */
+#define SUSPEND_BITS_REQD (ROUND_UP((256 * BITS_PER_IRQ), 32))
+
uint32_t ioapic_suspend_buf[SUSPEND_BITS_REQD / 32] = {0};
static uint32_t ioapic_device_power_state = DEVICE_PM_ACTIVE_STATE;
+
#endif
static uint32_t __IoApicGet(int32_t offset);
@@ -126,23 +136,18 @@
DEVICE_MMIO_TOPLEVEL_MAP(ioapic_regs, K_MEM_CACHE_NONE);
+ /* Reading MRE: this will give the number of RTEs available */
+ ioapic_rtes = ((__IoApicGet(IOAPIC_VERS) &
+ IOAPIC_MRE_MASK) >> IOAPIC_MRE_POS) + 1;
+
#ifdef CONFIG_IOAPIC_MASK_RTE
int32_t ix; /* redirection table index */
uint32_t rteValue; /* value to copy into redirection table entry */
- /*
- * The platform must set the Kconfig option IOAPIC_NUM_RTES to indicate
- * the number of redirection table entries supported by the IOAPIC.
- *
- * Note: The number of actual IRQs supported by the IOAPIC can be
- * determined at runtime by computing:
- *
- * ((__IoApicGet(IOAPIC_VERS) & IOAPIC_MRE_MASK) >> 16) + 1
- */
rteValue = IOAPIC_EDGE | IOAPIC_HIGH | IOAPIC_FIXED | IOAPIC_INT_MASK |
IOAPIC_LOGICAL | 0 /* dummy vector */;
- for (ix = 0; ix < CONFIG_IOAPIC_NUM_RTES; ix++) {
+ for (ix = 0; ix < ioapic_rtes; ix++) {
ioApicRedSetHi(ix, DEFAULT_RTE_DEST);
ioApicRedSetLo(ix, rteValue);
}
@@ -150,6 +155,11 @@
return 0;
}
+uint32_t z_ioapic_num_rtes(void)
+{
+ return ioapic_rtes;
+}
+
/**
*
* @brief Enable a specified APIC interrupt input line
@@ -244,7 +254,7 @@
ARG_UNUSED(port);
(void)memset(ioapic_suspend_buf, 0, (SUSPEND_BITS_REQD >> 3));
- for (irq = 0; irq < CONFIG_IOAPIC_NUM_RTES; irq++) {
+ for (irq = 0; irq < ioapic_rtes; irq++) {
/*
* The following check is to figure out the registered
* IRQ lines, so as to limit ourselves to saving the
@@ -267,7 +277,7 @@
ARG_UNUSED(port);
- for (irq = 0; irq < CONFIG_IOAPIC_NUM_RTES; irq++) {
+ for (irq = 0; irq < ioapic_rtes; irq++) {
if (_irq_to_interrupt_vector[irq]) {
/* Get the saved flags */
flags = restore_flags(irq);
diff --git a/drivers/interrupt_controller/intc_ioapic_priv.h b/drivers/interrupt_controller/intc_ioapic_priv.h
index ea56d9d..e675ea6 100644
--- a/drivers/interrupt_controller/intc_ioapic_priv.h
+++ b/drivers/interrupt_controller/intc_ioapic_priv.h
@@ -33,13 +33,10 @@
/* Version register bits */
#define IOAPIC_MRE_MASK 0x00ff0000 /* Max Red. entry mask */
+#define IOAPIC_MRE_POS 16
#define IOAPIC_PRQ 0x00008000 /* this has IRQ reg */
#define IOAPIC_VERSION 0x000000ff /* version number */
-/* Redirection table entry number */
-
-#define MAX_REDTABLE_ENTRIES 24
-
/* Redirection table entry bits: upper 32 bit */
#define IOAPIC_DESTINATION 0xff000000
diff --git a/drivers/interrupt_controller/intc_loapic.c b/drivers/interrupt_controller/intc_loapic.c
index 527c7bf..7fe2e4f 100644
--- a/drivers/interrupt_controller/intc_loapic.c
+++ b/drivers/interrupt_controller/intc_loapic.c
@@ -20,6 +20,7 @@
#include <drivers/interrupt_controller/loapic.h> /* public API declarations */
#include <device.h>
#include <drivers/interrupt_controller/sysapic.h>
+#include <drivers/interrupt_controller/ioapic.h>
/* Local APIC Version Register Bits */
@@ -192,6 +193,12 @@
return 0;
}
+
+uint32_t z_loapic_irq_base(void)
+{
+ return z_ioapic_num_rtes();
+}
+
/**
*
* @brief Set the vector field in the specified RTE
@@ -344,7 +351,7 @@
for (loapic_irq = 0; loapic_irq < LOAPIC_IRQ_COUNT; loapic_irq++) {
- if (_irq_to_interrupt_vector[LOAPIC_IRQ_BASE + loapic_irq]) {
+ if (_irq_to_interrupt_vector[z_loapic_irq_base() + loapic_irq]) {
/* Since vector numbers are already present in RAM/ROM,
* We save only the mask bits here.
@@ -374,10 +381,11 @@
for (loapic_irq = 0; loapic_irq < LOAPIC_IRQ_COUNT; loapic_irq++) {
- if (_irq_to_interrupt_vector[LOAPIC_IRQ_BASE + loapic_irq]) {
+ if (_irq_to_interrupt_vector[z_loapic_irq_base() + loapic_irq]) {
/* Configure vector and enable the required ones*/
z_loapic_int_vec_set(loapic_irq,
- _irq_to_interrupt_vector[LOAPIC_IRQ_BASE + loapic_irq]);
+ _irq_to_interrupt_vector[z_loapic_irq_base() +
+ loapic_irq]);
if (sys_bitfield_test_bit((mem_addr_t) loapic_suspend_buf,
loapic_irq)) {
diff --git a/drivers/interrupt_controller/intc_system_apic.c b/drivers/interrupt_controller/intc_system_apic.c
index 7c3d833..82fd55d 100644
--- a/drivers/interrupt_controller/intc_system_apic.c
+++ b/drivers/interrupt_controller/intc_system_apic.c
@@ -18,8 +18,8 @@
#include <drivers/interrupt_controller/sysapic.h>
#include <irq.h>
-#define IS_IOAPIC_IRQ(irq) (irq < LOAPIC_IRQ_BASE)
-#define HARDWARE_IRQ_LIMIT ((LOAPIC_IRQ_BASE + LOAPIC_IRQ_COUNT) - 1)
+#define IS_IOAPIC_IRQ(irq) (irq < z_loapic_irq_base())
+#define HARDWARE_IRQ_LIMIT ((z_loapic_irq_base() + LOAPIC_IRQ_COUNT) - 1)
/**
*
@@ -33,7 +33,7 @@
*
* The Galileo board virtualizes IRQs as follows:
*
- * - The first CONFIG_IOAPIC_NUM_RTES IRQs are provided by the IOAPIC so the
+ * - The first z_ioapic_num_rtes() IRQs are provided by the IOAPIC so the
* IOAPIC is programmed for these IRQs
* - The remaining IRQs are provided by the LOAPIC and hence the LOAPIC is
* programmed.
@@ -51,7 +51,7 @@
if (IS_IOAPIC_IRQ(irq)) {
z_ioapic_irq_set(irq, vector, flags);
} else {
- z_loapic_int_vec_set(irq - LOAPIC_IRQ_BASE, vector);
+ z_loapic_int_vec_set(irq - z_loapic_irq_base(), vector);
}
}
@@ -77,7 +77,7 @@
if (IS_IOAPIC_IRQ(irq)) {
z_ioapic_irq_enable(irq);
} else {
- z_loapic_irq_enable(irq - LOAPIC_IRQ_BASE);
+ z_loapic_irq_enable(irq - z_loapic_irq_base());
}
}
@@ -97,6 +97,6 @@
if (IS_IOAPIC_IRQ(irq)) {
z_ioapic_irq_disable(irq);
} else {
- z_loapic_irq_disable(irq - LOAPIC_IRQ_BASE);
+ z_loapic_irq_disable(irq - z_loapic_irq_base());
}
}