Skip to content

Commit 65e6c98

Browse files
committed
[PIC] Make a new flags for affinity post
Some affinity config for PIC is not support if current CPU is not startup, but RT-Thread SMP is startup after the devices init in `main` thread. This patch add a thread(lower level of priority for `main`) to reconfig the affinity of all PIRQs if they have configed affinities. There is a new flags for PIC to set a special property for affinity post. Signed-off-by: GuEe-GUI <[email protected]>
1 parent 1a15146 commit 65e6c98

File tree

6 files changed

+88
-12
lines changed

6 files changed

+88
-12
lines changed

components/drivers/include/drivers/pic.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct rt_pic
4040

4141
rt_list_t list;
4242

43-
struct rt_pic_ops *ops;
43+
const struct rt_pic_ops *ops;
4444

4545
void *priv_data;
4646
void *user_data;
@@ -79,6 +79,7 @@ struct rt_pic_ops
7979
rt_err_t (*irq_parse)(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq);
8080

8181
#define RT_PIC_F_IRQ_ROUTING RT_BIT(0) /* Routing ISR when cascade */
82+
#define RT_PIC_F_AFFINITY_POST RT_BIT(1) /* Affinity is valid after CPUs post */
8283
rt_ubase_t flags;
8384
};
8485

@@ -91,6 +92,10 @@ struct rt_pic_isr
9192
struct rt_irq_desc action;
9293
};
9394

95+
#define RT_IRQ_AFFINITY_DECLARE(name) RT_BITMAP_DECLARE(name, RT_CPUS_NR)
96+
#define RT_IRQ_AFFINITY_SET(affinity, cpuid) rt_bitmap_set_bit(affinity, cpuid)
97+
#define RT_IRQ_AFFINITY_CLEAR(affinity, cpuid) rt_bitmap_clear_bit(affinity, cpuid)
98+
9499
#ifdef RT_USING_PIC_STATISTICS
95100
struct rt_pic_irq_statistics
96101
{
@@ -117,7 +122,7 @@ struct rt_pic_irq
117122
rt_uint32_t mode;
118123

119124
rt_uint32_t priority;
120-
RT_BITMAP_DECLARE(affinity, RT_CPUS_NR);
125+
RT_IRQ_AFFINITY_DECLARE(affinity);
121126

122127
rt_list_t list;
123128
rt_list_t children_nodes;

components/drivers/pic/pic-gic-common.c

+8
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,11 @@ void gic_common_cpu_config(void *base, int nr, void (*sync_access)(void *), void
173173
sync_access(data);
174174
}
175175
}
176+
177+
void gic_fill_ppi_affinity(bitmap_t *affinity)
178+
{
179+
for (int cpuid = 0; cpuid < RT_CPUS_NR; ++cpuid)
180+
{
181+
bitmap_set_bit(affinity, cpuid);
182+
}
183+
}

components/drivers/pic/pic-gic-common.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#define GIC_SGI_NR 16
1818

19-
#define GICD_INT_DEF_PRI 0xa0
19+
#define GICD_INT_DEF_PRI 0xa0U
2020
#define GICD_INT_DEF_PRI_X4 \
2121
( \
2222
(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 (*
4343
void gic_common_dist_config(void *base, int max_irqs, void (*sync_access)(void *), void *data);
4444
void gic_common_cpu_config(void *base, int nr, void (*sync_access)(void *), void *data);
4545

46+
void gic_fill_ppi_affinity(bitmap_t *affinity);
47+
4648
#ifdef RT_PIC_ARM_GIC_V2M
4749
rt_err_t gicv2m_ofw_probe(struct rt_ofw_node *ic_np, const struct rt_ofw_node_id *id);
4850
#endif

components/drivers/pic/pic-gicv2.c

+14-3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ static void gicv2_dist_init(struct gicv2 *gic)
6666
rt_uint32_t i;
6767
rt_uint32_t cpumask = gicv2_cpumask_map(gic);
6868

69+
_init_cpu_id = rt_hw_cpu_id();
70+
6971
gic->max_irq = HWREG32(base + GIC_DIST_TYPE) & 0x1f;
7072
gic->max_irq = (gic->max_irq + 1) * 32;
7173

@@ -102,7 +104,7 @@ static void gicv2_cpu_init(struct gicv2 *gic)
102104
rt_uint32_t cpumask;
103105
void *base = gic->cpu_base;
104106
rt_uint32_t config = GICC_ENABLE;
105-
int cpu_id = _init_cpu_id = rt_hw_cpu_id();
107+
int cpu_id = rt_hw_cpu_id();
106108

107109
cpumask = gicv2_cpumask_map(gic);
108110
_gicv2_cpumask_map[cpu_id] = cpumask;
@@ -278,7 +280,15 @@ static int gicv2_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
278280
{
279281
pirq->mode = mode;
280282
pirq->priority = GICD_INT_DEF_PRI;
281-
rt_bitmap_set_bit(pirq->affinity, _init_cpu_id);
283+
284+
if (hwirq < 32)
285+
{
286+
gic_fill_ppi_affinity(pirq->affinity);
287+
}
288+
else
289+
{
290+
bitmap_set_bit(pirq->affinity, _init_cpu_id);
291+
}
282292

283293
irq = rt_pic_config_irq(pic, irq_index, hwirq);
284294

@@ -326,7 +336,7 @@ static rt_err_t gicv2_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *arg
326336
return err;
327337
}
328338

329-
static struct rt_pic_ops gicv2_ops =
339+
const static struct rt_pic_ops gicv2_ops =
330340
{
331341
.name = "GICv2",
332342
.irq_init = gicv2_irq_init,
@@ -340,6 +350,7 @@ static struct rt_pic_ops gicv2_ops =
340350
.irq_send_ipi = gicv2_irq_send_ipi,
341351
.irq_map = gicv2_irq_map,
342352
.irq_parse = gicv2_irq_parse,
353+
.flags = RT_PIC_F_AFFINITY_POST,
343354
};
344355

345356
static rt_bool_t gicv2_handler(void *data)

components/drivers/pic/pic-gicv3.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,9 @@ static int gicv3_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
622622

623623
switch (gicv3_hwirq_type(hwirq))
624624
{
625+
case PPI_TYPE:
626+
gic_fill_ppi_affinity(pirq->affinity);
627+
break;
625628
case SPI_TYPE:
626629
case ESPI_TYPE:
627630
pirq->priority = GICD_INT_DEF_PRI;
@@ -701,7 +704,7 @@ static rt_err_t gicv3_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *arg
701704
return err;
702705
}
703706

704-
static struct rt_pic_ops gicv3_ops =
707+
const static struct rt_pic_ops gicv3_ops =
705708
{
706709
.name = "GICv3",
707710
.irq_init = gicv3_irq_init,
@@ -715,6 +718,7 @@ static struct rt_pic_ops gicv3_ops =
715718
.irq_send_ipi = gicv3_irq_send_ipi,
716719
.irq_map = gicv3_irq_map,
717720
.irq_parse = gicv3_irq_parse,
721+
.flags = RT_PIC_F_AFFINITY_POST,
718722
};
719723

720724
static rt_bool_t gicv3_handler(void *data)

components/drivers/pic/pic.c

+51-5
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,17 @@ static void config_pirq(struct rt_pic *pic, struct rt_pic_irq *pirq, int irq, in
192192
int rt_pic_config_ipi(struct rt_pic *pic, int ipi_index, int hwirq)
193193
{
194194
int ipi = ipi_index;
195+
struct rt_pic_irq *pirq;
195196

196197
if (pic && ipi < RT_ARRAY_SIZE(_ipi_hash) && hwirq >= 0 && pic->ops->irq_send_ipi)
197198
{
198-
config_pirq(pic, &_pirq_hash[ipi], ipi, hwirq);
199+
pirq = &_pirq_hash[ipi];
200+
config_pirq(pic, pirq, ipi, hwirq);
201+
202+
for (int cpuid = 0; cpuid < RT_CPUS_NR; ++cpuid)
203+
{
204+
bitmap_set_bit(pirq->affinity, cpuid);
205+
}
199206

200207
LOG_D("%s config %s %d to hwirq %d", pic->ops->name, "ipi", ipi, hwirq);
201208
}
@@ -404,7 +411,7 @@ rt_err_t rt_pic_detach_irq(int irq, void *uid)
404411
}
405412
else
406413
{
407-
struct rt_pic_isr *next_isr = rt_list_entry(isr->list.next, struct rt_pic_isr, list);
414+
struct rt_pic_isr *next_isr = rt_list_first_entry(&isr->list, struct rt_pic_isr, list);
408415

409416
rt_list_remove(&next_isr->list);
410417

@@ -518,9 +525,6 @@ rt_err_t rt_pic_handle_isr(struct rt_pic_irq *pirq)
518525
pirq->stat.current_irq_begin[rt_hw_cpu_id()] = ts.tv_sec * (1000UL * 1000 * 1000) + ts.tv_nsec;
519526
#endif
520527

521-
/* Corrected irq affinity */
522-
rt_bitmap_set_bit(pirq->affinity, rt_hw_cpu_id());
523-
524528
handler_nodes = &pirq->isr.list;
525529
action = &pirq->isr.action;
526530

@@ -593,6 +597,48 @@ rt_weak rt_err_t rt_pic_user_extends(struct rt_pic *pic)
593597
return -RT_ENOSYS;
594598
}
595599

600+
static void pic_fixup_runner(void *param)
601+
{
602+
/* Fixup system PIC setting */
603+
struct rt_pic_irq *pirq, *pirq_end;
604+
605+
pirq = &_pirq_hash[RT_ARRAY_SIZE(_ipi_hash)];
606+
pirq_end = &_pirq_hash[RT_ARRAY_SIZE(_pirq_hash)];
607+
608+
for (; pirq < pirq_end; ++pirq)
609+
{
610+
if (!pirq->pic)
611+
{
612+
continue;
613+
}
614+
615+
/* Only fixup who no bind to CPU#0 */
616+
if (!bitmap_test_bit(pirq->affinity, 0) &&
617+
pirq->pic->ops->flags & RT_PIC_F_AFFINITY_POST)
618+
{
619+
rt_pic_irq_set_affinity(pirq->irq, pirq->affinity);
620+
}
621+
}
622+
}
623+
624+
static int pic_fixup_prepare(void)
625+
{
626+
rt_thread_t tid;
627+
628+
/*
629+
* We assume that the SMP startup has been confirmed (system is working)
630+
* to be complete after the "main" thread finishes.
631+
*/
632+
tid = rt_thread_create("pic", pic_fixup_runner, RT_NULL,
633+
RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY + 1, 20);
634+
RT_ASSERT(tid != RT_NULL);
635+
636+
rt_thread_startup(tid);
637+
638+
return 0;
639+
}
640+
INIT_PREV_EXPORT(pic_fixup_prepare);
641+
596642
rt_err_t rt_pic_irq_init(void)
597643
{
598644
rt_err_t err = RT_EOK;

0 commit comments

Comments
 (0)