@@ -103,6 +103,7 @@ struct plic_stats {
103
103
};
104
104
105
105
struct plic_data {
106
+ struct k_spinlock lock ;
106
107
107
108
#ifdef CONFIG_PLIC_SHELL_IRQ_COUNT
108
109
struct plic_stats stats ;
@@ -279,11 +280,13 @@ static void plic_irq_enable_set_state(uint32_t irq, bool enable)
279
280
*/
280
281
void riscv_plic_irq_enable (uint32_t irq )
281
282
{
282
- uint32_t key = irq_lock ();
283
+ const struct device * dev = get_plic_dev_from_irq (irq );
284
+ struct plic_data * data = dev -> data ;
285
+ k_spinlock_key_t key = k_spin_lock (& data -> lock );
283
286
284
287
plic_irq_enable_set_state (irq , true);
285
288
286
- irq_unlock ( key );
289
+ k_spin_unlock ( & data -> lock , key );
287
290
}
288
291
289
292
/**
@@ -298,47 +301,58 @@ void riscv_plic_irq_enable(uint32_t irq)
298
301
*/
299
302
void riscv_plic_irq_disable (uint32_t irq )
300
303
{
301
- uint32_t key = irq_lock ();
304
+ const struct device * dev = get_plic_dev_from_irq (irq );
305
+ struct plic_data * data = dev -> data ;
306
+ k_spinlock_key_t key = k_spin_lock (& data -> lock );
302
307
303
308
plic_irq_enable_set_state (irq , false);
304
309
305
- irq_unlock ( key );
310
+ k_spin_unlock ( & data -> lock , key );
306
311
}
307
312
308
- /**
309
- * @brief Check if a riscv PLIC-specific interrupt line is enabled
310
- *
311
- * This routine checks if a RISCV PLIC-specific interrupt line is enabled.
312
- * @param irq IRQ number to check
313
- *
314
- * @return 1 or 0
315
- */
316
- int riscv_plic_irq_is_enabled (uint32_t irq )
313
+ /* Check if the local IRQ of a PLIC instance is enabled */
314
+ static int local_irq_is_enabled (const struct device * dev , uint32_t local_irq )
317
315
{
318
- const struct device * dev = get_plic_dev_from_irq (irq );
319
- const uint32_t local_irq = irq_from_level_2 (irq );
320
316
uint32_t bit_position = local_irq & PLIC_REG_MASK ;
321
- uint32_t en_value ;
322
317
int is_enabled = IS_ENABLED (CONFIG_PLIC_IRQ_AFFINITY ) ? 0 : 1 ;
323
- uint32_t key = irq_lock ();
324
318
325
319
for (uint32_t cpu_num = 0 ; cpu_num < arch_num_cpus (); cpu_num ++ ) {
326
320
mem_addr_t en_addr =
327
321
get_context_en_addr (dev , cpu_num ) + local_irq_to_reg_offset (local_irq );
322
+ uint32_t en_value = sys_read32 (en_addr );
328
323
329
- en_value = sys_read32 (en_addr );
330
324
if (IS_ENABLED (CONFIG_PLIC_IRQ_AFFINITY )) {
331
325
is_enabled |= !!(en_value & BIT (bit_position ));
332
326
} else {
333
327
is_enabled &= !!(en_value & BIT (bit_position ));
334
328
}
335
329
}
336
330
337
- irq_unlock (key );
338
-
339
331
return is_enabled ;
340
332
}
341
333
334
+ /**
335
+ * @brief Check if a riscv PLIC-specific interrupt line is enabled
336
+ *
337
+ * This routine checks if a RISCV PLIC-specific interrupt line is enabled.
338
+ * @param irq IRQ number to check
339
+ *
340
+ * @return 1 or 0
341
+ */
342
+ int riscv_plic_irq_is_enabled (uint32_t irq )
343
+ {
344
+ const struct device * dev = get_plic_dev_from_irq (irq );
345
+ struct plic_data * data = dev -> data ;
346
+ const uint32_t local_irq = irq_from_level_2 (irq );
347
+ int ret = 0 ;
348
+
349
+ K_SPINLOCK (& data -> lock ) {
350
+ ret = local_irq_is_enabled (dev , local_irq );
351
+ }
352
+
353
+ return ret ;
354
+ }
355
+
342
356
/**
343
357
* @brief Set priority of a riscv PLIC-specific interrupt line
344
358
*
@@ -413,9 +427,10 @@ const struct device *riscv_plic_get_dev(void)
413
427
int riscv_plic_irq_set_affinity (uint32_t irq , uint32_t cpumask )
414
428
{
415
429
const struct device * dev = get_plic_dev_from_irq (irq );
416
- const struct plic_data * data = dev -> data ;
430
+ struct plic_data * data = dev -> data ;
417
431
__maybe_unused const struct plic_config * config = dev -> config ;
418
432
const uint32_t local_irq = irq_from_level_2 (irq );
433
+ k_spinlock_key_t key ;
419
434
420
435
if (local_irq >= config -> nr_irqs ) {
421
436
__ASSERT (false, "overflow: irq %d, local_irq %d" , irq , local_irq );
@@ -427,17 +442,15 @@ int riscv_plic_irq_set_affinity(uint32_t irq, uint32_t cpumask)
427
442
return - EINVAL ;
428
443
}
429
444
430
- uint32_t key = irq_lock ();
431
-
445
+ key = k_spin_lock (& data -> lock );
432
446
/* Updated irq_cpumask for next time setting plic enable register */
433
447
data -> irq_cpumask [local_irq ] = (plic_cpumask_t )cpumask ;
434
448
435
449
/* If irq is enabled, apply the new irq affinity */
436
- if (riscv_plic_irq_is_enabled ( irq )) {
437
- riscv_plic_irq_enable (irq );
450
+ if (local_irq_is_enabled ( dev , local_irq )) {
451
+ plic_irq_enable_set_state (irq , true );
438
452
}
439
-
440
- irq_unlock (key );
453
+ k_spin_unlock (& data -> lock , key );
441
454
442
455
return 0 ;
443
456
}
0 commit comments