Add interrupt vector set/get affinity

Close #3071.
This commit is contained in:
Sebastian Huber
2017-07-11 11:54:30 +02:00
parent ccc87c8b9e
commit af207fa9f6
13 changed files with 230 additions and 72 deletions

View File

@@ -153,20 +153,24 @@ rtems_status_code arm_gic_irq_get_priority(
return sc;
}
rtems_status_code arm_gic_irq_set_affinity(
void bsp_interrupt_set_affinity(
rtems_vector_number vector,
uint8_t targets
const Processor_mask *affinity
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
volatile gic_dist *dist = ARM_GIC_DIST;
uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0);
if (bsp_interrupt_is_valid_vector(vector)) {
volatile gic_dist *dist = ARM_GIC_DIST;
gic_id_set_targets(dist, vector, targets);
} else {
sc = RTEMS_INVALID_ID;
}
return sc;
gic_id_set_targets(dist, vector, targets);
}
void bsp_interrupt_get_affinity(
rtems_vector_number vector,
Processor_mask *affinity
)
{
volatile gic_dist *dist = ARM_GIC_DIST;
uint8_t targets = gic_id_get_targets(dist, vector);
_Processor_mask_From_uint32_t(affinity, targets, 0);
}

View File

@@ -58,9 +58,14 @@ rtems_status_code arm_gic_irq_get_priority(
uint8_t *priority
);
rtems_status_code arm_gic_irq_set_affinity(
void bsp_interrupt_set_affinity(
rtems_vector_number vector,
uint8_t targets
const Processor_mask *affinity
);
void bsp_interrupt_get_affinity(
rtems_vector_number vector,
Processor_mask *affinity
);
typedef enum {

View File

@@ -56,12 +56,11 @@ static void qoriq_clock_handler_install(rtems_isr_entry *old_isr)
*old_isr = NULL;
#if defined(RTEMS_MULTIPROCESSING) && !defined(RTEMS_SMP)
sc = qoriq_pic_set_affinity(
CLOCK_INTERRUPT,
ppc_processor_id()
);
if (sc != RTEMS_SUCCESSFUL) {
rtems_fatal_error_occurred(0xdeadbeef);
{
Processor_mask affinity;
_Processor_mask_From_index(&affinity, ppc_processor_id());
bsp_interrupt_set_affinity(CLOCK_INTERRUPT, &affinity);
}
#endif
@@ -133,10 +132,7 @@ static void qoriq_clock_cleanup(void)
qoriq_clock_handler_install(&old_isr)
#define Clock_driver_support_set_interrupt_affinity(online_processors) \
qoriq_pic_set_affinities( \
CLOCK_INTERRUPT, \
_Processor_mask_To_uint32_t(online_processors, 0) \
)
bsp_interrupt_set_affinity(CLOCK_INTERRUPT, online_processors)
#define Clock_driver_support_shutdown_hardware() \
qoriq_clock_cleanup()

View File

@@ -372,14 +372,14 @@ rtems_status_code qoriq_pic_set_priority(
int *old_priority
);
rtems_status_code qoriq_pic_set_affinity(
void bsp_interrupt_set_affinity(
rtems_vector_number vector,
uint32_t processor_index
const Processor_mask *affinity
);
rtems_status_code qoriq_pic_set_affinities(
void bsp_interrupt_get_affinity(
rtems_vector_number vector,
uint32_t processor_affinities
Processor_mask *affinity
);
/** @} */

View File

@@ -147,30 +147,24 @@ rtems_status_code qoriq_pic_set_priority(
return sc;
}
rtems_status_code qoriq_pic_set_affinities(
void bsp_interrupt_set_affinity(
rtems_vector_number vector,
uint32_t processor_affinities
const Processor_mask *affinity
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
if (bsp_interrupt_is_valid_vector(vector)) {
volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
src_cfg->dr = processor_affinities;
} else {
sc = RTEMS_INVALID_ID;
}
return sc;
src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0);
}
rtems_status_code qoriq_pic_set_affinity(
void bsp_interrupt_get_affinity(
rtems_vector_number vector,
uint32_t processor_index
Processor_mask *affinity
)
{
return qoriq_pic_set_affinities(vector, BSP_BIT32(processor_index));
volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
_Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0);
}
static rtems_status_code pic_vector_enable(rtems_vector_number vector, uint32_t msk)

View File

@@ -9,7 +9,7 @@
/*
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
*
* Copyright (c) 2008-2014 embedded brains GmbH.
* Copyright (c) 2008, 2017 embedded brains GmbH.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -573,3 +573,54 @@ bool bsp_interrupt_handler_is_empty(rtems_vector_number vector)
return empty;
}
rtems_status_code rtems_interrupt_set_affinity(
rtems_vector_number vector,
size_t affinity_size,
const cpu_set_t *affinity
)
{
Processor_mask set;
Processor_mask_Copy_status status;
if (!bsp_interrupt_is_valid_vector(vector)) {
return RTEMS_INVALID_ID;
}
status = _Processor_mask_From_cpu_set_t(&set, affinity_size, affinity);
if (status != PROCESSOR_MASK_COPY_LOSSLESS) {
return RTEMS_INVALID_SIZE;
}
#if defined(RTEMS_SMP)
bsp_interrupt_set_affinity(vector, &set);
#endif
return RTEMS_SUCCESSFUL;
}
rtems_status_code rtems_interrupt_get_affinity(
rtems_vector_number vector,
size_t affinity_size,
cpu_set_t *affinity
)
{
Processor_mask set;
Processor_mask_Copy_status status;
if (!bsp_interrupt_is_valid_vector(vector)) {
return RTEMS_INVALID_ID;
}
#if defined(RTEMS_SMP)
bsp_interrupt_get_affinity(vector, &set);
#else
_Processor_mask_From_index(&set, 0);
#endif
status = _Processor_mask_To_cpu_set_t(&set, affinity_size, affinity);
if (status != PROCESSOR_MASK_COPY_LOSSLESS) {
return RTEMS_INVALID_SIZE;
}
return RTEMS_SUCCESSFUL;
}

View File

@@ -18,6 +18,8 @@
#ifndef LIBBSP_ERC32_IRQ_CONFIG_H
#define LIBBSP_ERC32_IRQ_CONFIG_H
#include <rtems.h>
#define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */
#define BSP_INTERRUPT_VECTOR_MIN 0
#define BSP_INTERRUPT_VECTOR_MAX BSP_INTERRUPT_VECTOR_MAX_STD
@@ -25,4 +27,22 @@
/* No extra check is needed */
#undef BSP_INTERRUPT_CUSTOM_VALID_VECTOR
RTEMS_INLINE_ROUTINE void bsp_interrupt_set_affinity(
rtems_vector_number vector,
const Processor_mask *affinity
)
{
(void) vector;
(void) affinity;
}
RTEMS_INLINE_ROUTINE void bsp_interrupt_get_affinity(
rtems_vector_number vector,
Processor_mask *affinity
)
{
(void) vector;
_Processor_mask_From_index( affinity, 0 );
}
#endif /* LIBBSP_ERC32_IRQ_CONFIG_H */

View File

@@ -192,16 +192,7 @@ static void bsp_clock_handler_install(rtems_isr *new)
}
#define Clock_driver_support_set_interrupt_affinity(online_processors) \
do { \
uint32_t cpu_count = _SMP_Processor_count; \
uint32_t cpu_index; \
LEON_Enable_interrupt_broadcast(clkirq); \
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { \
if (_Processor_mask_Is_set(online_processors, cpu_index)) { \
BSP_Cpu_Unmask_interrupt(clkirq, cpu_index); \
} \
} \
} while (0)
bsp_interrupt_set_affinity(clkirq, online_processors)
static void leon3_clock_initialize(void)
{

View File

@@ -41,4 +41,14 @@ static inline bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
LEON3_IrqCtrl_EIrq != 0));
}
void bsp_interrupt_set_affinity(
rtems_vector_number vector,
const Processor_mask *affinity
);
void bsp_interrupt_get_affinity(
rtems_vector_number vector,
Processor_mask *affinity
);
#endif /* LIBBSP_LEON3_IRQ_CONFIG_H */

View File

@@ -11,6 +11,7 @@
*/
#include <leon.h>
#include <bsp/irq.h>
/* GRLIB extended IRQ controller IRQ number */
int LEON3_IrqCtrl_EIrq = -1;
@@ -23,3 +24,43 @@ void leon3_ext_irq_init(void)
LEON3_IrqCtrl_EIrq = (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf;
}
}
void bsp_interrupt_set_affinity(
rtems_vector_number vector,
const Processor_mask *affinity
)
{
uint32_t unmasked = 0;
uint32_t cpu_count = rtems_get_processor_count();
uint32_t cpu_index;
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);
++unmasked;
}
}
if (unmasked > 1) {
LEON_Enable_interrupt_broadcast(vector);
} else {
LEON_Disable_interrupt_broadcast(vector);
}
}
void bsp_interrupt_get_affinity(
rtems_vector_number vector,
Processor_mask *affinity
)
{
uint32_t cpu_count = rtems_get_processor_count();
uint32_t cpu_index;
_Processor_mask_Zero(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);
}
}
}

View File

@@ -22,6 +22,7 @@
#include <bsp/genirq.h>
#include <bsp.h>
#include <bsp/irq.h>
#define DBG(args...)
/*#define DBG(args...) printk(args)*/
@@ -236,24 +237,7 @@ int ambapp_grlib_int_set_affinity
const Processor_mask *cpus
)
{
uint32_t cpu_count = rtems_get_processor_count();
uint32_t cpu_index;
int enabled_cnt = 0;
for (cpu_index = 0; cpu_index < cpu_count; cpu_index++) {
if (_Processor_mask_Is_set(cpus, cpu_index)) {
BSP_Cpu_Unmask_interrupt(irq, cpu_index);
enabled_cnt++;
}
}
/* Propagate the interrupt to all CPUs */
if (enabled_cnt > 1) {
LEON_Enable_interrupt_broadcast(irq);
} else {
LEON_Disable_interrupt_broadcast(irq);
}
bsp_interrupt_set_affinity(irq, cpus);
return DRVMGR_OK;
}
#endif

View File

@@ -203,6 +203,43 @@ rtems_status_code rtems_interrupt_handler_iterate(
void *arg
);
/**
* @brief Sets the processor affinity set of an interrupt vector.
*
* @param[in] vector The interrupt vector number.
* @param[in] affinity_size The storage size of the affinity set.
* @param[in] affinity_set The new processor affinity set for the interrupt
* vector. This pointer must not be @c NULL.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INVALID_ID The vector number is invalid.
* @retval RTEMS_INVALID_SIZE Invalid affinity set size.
* @retval RTEMS_INVALID_NUMBER Invalid processor affinity set.
*/
rtems_status_code rtems_interrupt_set_affinity(
rtems_vector_number vector,
size_t affinity_size,
const cpu_set_t *affinity
);
/**
* @brief Gets the processor affinity set of an interrupt vector.
*
* @param[in] vector The interrupt vector number.
* @param[in] affinity_size The storage size of the affinity set.
* @param[out] affinity_set The current processor affinity set for the
* interrupt vector. This pointer must not be @c NULL.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INVALID_ID The vector number is invalid.
* @retval RTEMS_INVALID_SIZE Invalid affinity set size.
*/
rtems_status_code rtems_interrupt_get_affinity(
rtems_vector_number vector,
size_t affinity_size,
cpu_set_t *affinity
);
/**
* @brief An interrupt server action.
*

View File

@@ -203,6 +203,31 @@ RTEMS_INLINE_ROUTINE uint32_t _Processor_mask_To_uint32_t(
return (uint32_t) (bits >> (32 * (index % _BITSET_BITS) / 32));
}
/**
* @brief Creates a processor set from an unsigned 32-bit integer relative to
* the specified index.
*/
RTEMS_INLINE_ROUTINE void _Processor_mask_From_uint32_t(
Processor_mask *mask,
uint32_t bits,
uint32_t index
)
{
_Processor_mask_Zero( mask );
mask->__bits[ __bitset_words( index ) ] = ((long) bits) << (32 * (index % _BITSET_BITS) / 32);
}
/**
* @brief Creates a processor set from the specified index.
*/
RTEMS_INLINE_ROUTINE void _Processor_mask_From_index(
Processor_mask *mask,
uint32_t index
)
{
BIT_SETOF( CPU_MAXIMUM_PROCESSORS, (int) index, mask );
}
typedef enum {
PROCESSOR_MASK_COPY_LOSSLESS,
PROCESSOR_MASK_COPY_PARTIAL_LOSS,