[PIC] Make affinity helper interface (#8995)

* [PIC] Make affinity helper interface

Signed-off-by: GuEe-GUI <2991707448@qq.com>

* [PIC/GIC] Fixup GIC affinity init

GICv2 is not support if current CPU is not startup,
but RT-Thread SMP is startup after the devices init
in the `main` thread.

This patch fixup the cpumask to init once and check
the init status in affinity interface.

Signed-off-by: GuEe-GUI <2991707448@qq.com>

---------

Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
GUI 2024-05-28 09:55:24 +08:00 committed by GitHub
parent f035188094
commit de352aee62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 49 additions and 13 deletions

View File

@ -40,7 +40,7 @@ struct rt_pic
rt_list_t list;
struct rt_pic_ops *ops;
const struct rt_pic_ops *ops;
void *priv_data;
void *user_data;
@ -91,6 +91,10 @@ struct rt_pic_isr
struct rt_irq_desc action;
};
#define RT_IRQ_AFFINITY_DECLARE(name) RT_BITMAP_DECLARE(name, RT_CPUS_NR)
#define RT_IRQ_AFFINITY_SET(affinity, cpuid) rt_bitmap_set_bit(affinity, cpuid)
#define RT_IRQ_AFFINITY_CLEAR(affinity, cpuid) rt_bitmap_clear_bit(affinity, cpuid)
#ifdef RT_USING_PIC_STATISTICS
struct rt_pic_irq_statistics
{
@ -117,7 +121,7 @@ struct rt_pic_irq
rt_uint32_t mode;
rt_uint32_t priority;
RT_BITMAP_DECLARE(affinity, RT_CPUS_NR);
RT_IRQ_AFFINITY_DECLARE(affinity);
rt_list_t list;
rt_list_t children_nodes;

View File

@ -173,3 +173,11 @@ void gic_common_cpu_config(void *base, int nr, void (*sync_access)(void *), void
sync_access(data);
}
}
void gic_fill_ppi_affinity(bitmap_t *affinity)
{
for (int cpuid = 0; cpuid < RT_CPUS_NR; ++cpuid)
{
RT_IRQ_AFFINITY_SET(affinity, cpuid);
}
}

View File

@ -16,7 +16,7 @@
#define GIC_SGI_NR 16
#define GICD_INT_DEF_PRI 0xa0
#define GICD_INT_DEF_PRI 0xa0U
#define GICD_INT_DEF_PRI_X4 \
( \
(GICD_INT_DEF_PRI << 24) | \
@ -43,6 +43,8 @@ rt_err_t gic_common_configure_irq(void *base, int irq, rt_uint32_t mode, void (*
void gic_common_dist_config(void *base, int max_irqs, void (*sync_access)(void *), void *data);
void gic_common_cpu_config(void *base, int nr, void (*sync_access)(void *), void *data);
void gic_fill_ppi_affinity(bitmap_t *affinity);
#ifdef RT_PIC_ARM_GIC_V2M
rt_err_t gicv2m_ofw_probe(struct rt_ofw_node *ic_np, const struct rt_ofw_node_id *id);
#endif

View File

@ -66,6 +66,8 @@ static void gicv2_dist_init(struct gicv2 *gic)
rt_uint32_t i;
rt_uint32_t cpumask = gicv2_cpumask_map(gic);
_init_cpu_id = rt_hw_cpu_id();
gic->max_irq = HWREG32(base + GIC_DIST_TYPE) & 0x1f;
gic->max_irq = (gic->max_irq + 1) * 32;
@ -102,7 +104,7 @@ static void gicv2_cpu_init(struct gicv2 *gic)
rt_uint32_t cpumask;
void *base = gic->cpu_base;
rt_uint32_t config = GICC_ENABLE;
int cpu_id = _init_cpu_id = rt_hw_cpu_id();
int cpu_id = rt_hw_cpu_id();
cpumask = gicv2_cpumask_map(gic);
_gicv2_cpumask_map[cpu_id] = cpumask;
@ -204,6 +206,11 @@ static rt_err_t gicv2_irq_set_affinity(struct rt_pic_irq *pirq, rt_bitmap_t *aff
rt_uint8_t valb = _gicv2_cpumask_map[__rt_ffs(target_list) - 1];
void *io_addr = gic->dist_base + GIC_DIST_TARGET + hwirq;
if (valb == 0xfe)
{
return -RT_EIO;
}
if (needs_rmw_access)
{
/* RMW write byte */
@ -278,7 +285,15 @@ static int gicv2_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
{
pirq->mode = mode;
pirq->priority = GICD_INT_DEF_PRI;
rt_bitmap_set_bit(pirq->affinity, _init_cpu_id);
if (hwirq < 32)
{
gic_fill_ppi_affinity(pirq->affinity);
}
else
{
RT_IRQ_AFFINITY_SET(pirq->affinity, _init_cpu_id);
}
irq = rt_pic_config_irq(pic, irq_index, hwirq);
@ -326,7 +341,7 @@ static rt_err_t gicv2_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *arg
return err;
}
static struct rt_pic_ops gicv2_ops =
const static struct rt_pic_ops gicv2_ops =
{
.name = "GICv2",
.irq_init = gicv2_irq_init,

View File

@ -622,10 +622,13 @@ static int gicv3_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
switch (gicv3_hwirq_type(hwirq))
{
case PPI_TYPE:
gic_fill_ppi_affinity(pirq->affinity);
break;
case SPI_TYPE:
case ESPI_TYPE:
pirq->priority = GICD_INT_DEF_PRI;
rt_bitmap_set_bit(pirq->affinity, _init_cpu_id);
RT_IRQ_AFFINITY_SET(pirq->affinity, _init_cpu_id);
default:
break;
}
@ -701,7 +704,7 @@ static rt_err_t gicv3_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *arg
return err;
}
static struct rt_pic_ops gicv3_ops =
const static struct rt_pic_ops gicv3_ops =
{
.name = "GICv3",
.irq_init = gicv3_irq_init,

View File

@ -192,10 +192,17 @@ static void config_pirq(struct rt_pic *pic, struct rt_pic_irq *pirq, int irq, in
int rt_pic_config_ipi(struct rt_pic *pic, int ipi_index, int hwirq)
{
int ipi = ipi_index;
struct rt_pic_irq *pirq;
if (pic && ipi < RT_ARRAY_SIZE(_ipi_hash) && hwirq >= 0 && pic->ops->irq_send_ipi)
{
config_pirq(pic, &_pirq_hash[ipi], ipi, hwirq);
pirq = &_pirq_hash[ipi];
config_pirq(pic, pirq, ipi, hwirq);
for (int cpuid = 0; cpuid < RT_CPUS_NR; ++cpuid)
{
RT_IRQ_AFFINITY_SET(pirq->affinity, cpuid);
}
LOG_D("%s config %s %d to hwirq %d", pic->ops->name, "ipi", ipi, hwirq);
}
@ -404,7 +411,7 @@ rt_err_t rt_pic_detach_irq(int irq, void *uid)
}
else
{
struct rt_pic_isr *next_isr = rt_list_entry(isr->list.next, struct rt_pic_isr, list);
struct rt_pic_isr *next_isr = rt_list_first_entry(&isr->list, struct rt_pic_isr, list);
rt_list_remove(&next_isr->list);
@ -518,9 +525,6 @@ rt_err_t rt_pic_handle_isr(struct rt_pic_irq *pirq)
pirq->stat.current_irq_begin[rt_hw_cpu_id()] = ts.tv_sec * (1000UL * 1000 * 1000) + ts.tv_nsec;
#endif
/* Corrected irq affinity */
rt_bitmap_set_bit(pirq->affinity, rt_hw_cpu_id());
handler_nodes = &pirq->isr.list;
action = &pirq->isr.action;