summaryrefslogtreecommitdiffstats
path: root/bsps/sparc/leon3/start/eirq.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-07-02 10:00:08 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-07-09 15:29:04 +0200
commitc7b3df3f516e0dbf032ad480ba5204de0e4d2bd6 (patch)
tree13fcc02bce02e94d1515768477d5a3708540a6a9 /bsps/sparc/leon3/start/eirq.c
parentbsp/imx: Fix SMP start (diff)
downloadrtems-c7b3df3f516e0dbf032ad480ba5204de0e4d2bd6.tar.bz2
bsps/sparc: Improve interrupt affinity support
Fully support the interrupt extension API to set/get the interrupt affinity. Remove LEON3_irq_to_cpu which defined the interrupt to processor mapping in a BSP-specific way. Update #3269.
Diffstat (limited to 'bsps/sparc/leon3/start/eirq.c')
-rw-r--r--bsps/sparc/leon3/start/eirq.c133
1 files changed, 117 insertions, 16 deletions
diff --git a/bsps/sparc/leon3/start/eirq.c b/bsps/sparc/leon3/start/eirq.c
index e3ae5b1a4d..84e81a90a4 100644
--- a/bsps/sparc/leon3/start/eirq.c
+++ b/bsps/sparc/leon3/start/eirq.c
@@ -1,6 +1,8 @@
/*
* GRLIB/LEON3 extended interrupt controller
*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
@@ -39,42 +41,141 @@ bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
return vector <= BSP_INTERRUPT_VECTOR_MAX_STD;
}
-void bsp_interrupt_set_affinity(
- rtems_vector_number vector,
- const Processor_mask *affinity
-)
+#if defined(RTEMS_SMP)
+Processor_mask leon3_interrupt_affinities[BSP_INTERRUPT_VECTOR_MAX_STD + 1];
+#endif
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+#if defined(RTEMS_SMP)
+ Processor_mask affinity;
+ size_t i;
+
+ _Processor_mask_From_index(&affinity, rtems_scheduler_get_processor());
+
+ for (i = 0; i < RTEMS_ARRAY_SIZE(leon3_interrupt_affinities); ++i) {
+ leon3_interrupt_affinities[i] = affinity;
+ }
+#endif
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#if defined(RTEMS_SMP)
+static void leon3_interrupt_vector_enable(rtems_vector_number vector)
{
- uint32_t unmasked = 0;
- uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
uint32_t cpu_index;
+ uint32_t cpu_count;
+ Processor_mask affinity;
+ uint32_t bit;
+ uint32_t unmasked;
+
+ cpu_count = rtems_scheduler_get_processor_maximum();
+ affinity = leon3_interrupt_affinities[vector];
+ bit = 1U << vector;
+ unmasked = 0;
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
- if (_Processor_mask_Is_set(affinity, cpu_index)) {
- BSP_Cpu_Unmask_interrupt(vector, cpu_index);
+ uint32_t mask;
+
+ mask = LEON3_IrqCtrl_Regs->mask[cpu_index];
+
+ if (_Processor_mask_Is_set(&affinity, cpu_index)) {
++unmasked;
+ mask |= bit;
+ } else {
+ mask &= ~bit;
}
+
+ LEON3_IrqCtrl_Regs->mask[cpu_index] = mask;
}
if (unmasked > 1) {
- LEON_Enable_interrupt_broadcast(vector);
+ LEON3_IrqCtrl_Regs->bcast |= bit;
} else {
- LEON_Disable_interrupt_broadcast(vector);
+ LEON3_IrqCtrl_Regs->bcast &= ~bit;
}
}
+#endif
-void bsp_interrupt_get_affinity(
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+#if defined(RTEMS_SMP)
+ rtems_interrupt_lock_context lock_context;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ LEON3_IRQCTRL_ACQUIRE(&lock_context);
+ leon3_interrupt_vector_enable(vector);
+ LEON3_IRQCTRL_RELEASE(&lock_context);
+#else
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ BSP_Cpu_Unmask_interrupt(vector, _LEON3_Get_current_processor());
+#endif
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+#if defined(RTEMS_SMP)
+ rtems_interrupt_lock_context lock_context;
+ uint32_t bit;
+ uint32_t cpu_index;
+ uint32_t cpu_count;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ bit = 1U << vector;
+ cpu_count = rtems_scheduler_get_processor_maximum();
+
+ LEON3_IRQCTRL_ACQUIRE(&lock_context);
+
+ for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
+ LEON3_IrqCtrl_Regs->mask[cpu_index] &= ~bit;
+ }
+
+ LEON3_IrqCtrl_Regs->bcast &= ~bit;
+
+ LEON3_IRQCTRL_RELEASE(&lock_context);
+#else
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ BSP_Cpu_Mask_interrupt(vector, _LEON3_Get_current_processor());
+#endif
+}
+
+#if defined(RTEMS_SMP)
+void bsp_interrupt_set_affinity(
rtems_vector_number vector,
- Processor_mask *affinity
+ const Processor_mask *affinity
)
{
- uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
+ rtems_interrupt_lock_context lock_context;
+ uint32_t cpu_count;
uint32_t cpu_index;
+ uint32_t bit;
+
+ cpu_count = rtems_scheduler_get_processor_maximum();
+ bit = 1U << vector;
- _Processor_mask_Zero(affinity);
+ LEON3_IRQCTRL_ACQUIRE(&lock_context);
+ leon3_interrupt_affinities[vector] = *affinity;
+ /*
+ * If the interrupt is enabled on at least one processor, then re-enable it
+ * using the new affinity.
+ */
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
- if (!BSP_Cpu_Is_interrupt_masked(vector, cpu_index)) {
- _Processor_mask_Set(affinity, cpu_index);
+ if ((LEON3_IrqCtrl_Regs->mask[cpu_index] & bit) != 0) {
+ leon3_interrupt_vector_enable(vector);
+ break;
}
}
+
+ LEON3_IRQCTRL_RELEASE(&lock_context);
+}
+
+void bsp_interrupt_get_affinity(
+ rtems_vector_number vector,
+ Processor_mask *affinity
+)
+{
+ *affinity = leon3_interrupt_affinities[vector];
}
+#endif