From bd6dac1119ecb0c0b10fa00d0ceff9715568f0ed Mon Sep 17 00:00:00 2001 From: Michalis Pappas Date: Thu, 14 Sep 2023 12:43:27 +0200 Subject: [PATCH] lib/ukintctlr: Add IRQ allocation Add an IRQ allocation function that will automatically assign from a pool of free IRQs. Notice: Picking individual commits in this PR will break the build. Signed-off-by: Marco Schlumpp Signed-off-by: Michalis Pappas Reviewed-by: Sergiu Moga Approved-by: Razvan Deaconescu GitHub-Closes: #1103 --- lib/ukintctlr/exportsyms.uk | 2 ++ lib/ukintctlr/ukintctlr.c | 51 ++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/ukintctlr/exportsyms.uk b/lib/ukintctlr/exportsyms.uk index 6375a3f5f..632f038d3 100644 --- a/lib/ukintctlr/exportsyms.uk +++ b/lib/ukintctlr/exportsyms.uk @@ -2,6 +2,8 @@ uk_intctlr uk_intctlr_init uk_intctlr_irq_configure uk_intctlr_irq_fdt_xlat +uk_intctlr_irq_alloc +uk_intctlr_irq_free uk_intctlr_irq_handle uk_intctlr_irq_register uk_intctlr_irq_unregister diff --git a/lib/ukintctlr/ukintctlr.c b/lib/ukintctlr/ukintctlr.c index d92ace980..401f14591 100644 --- a/lib/ukintctlr/ukintctlr.c +++ b/lib/ukintctlr/ukintctlr.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -41,13 +42,20 @@ #include #endif /* CONFIG_LIBUKINTCTLR_ISR_ECTX_ASSERTIONS */ -#ifndef UK_INTCTLR_MAX_IRQ +#if !defined(UK_INTCTLR_MAX_IRQ) || \ + !defined(UK_INTCTLR_ALLOCABLE_IRQ_COUNT) || \ + !defined(UK_INTCTLR_FIRST_ALLOCABLE_IRQ) || \ + !defined(UK_INTCTLR_LAST_ALLOCABLE_IRQ) #error "Incomplete definition of uk_intctlr driver limits" #endif #define MAX_IRQ UK_INTCTLR_MAX_IRQ #define MAX_HANDLERS_PER_IRQ CONFIG_LIBUKINTCTLR_MAX_HANDLERS_PER_IRQ +#define ALLOCABLE_IRQ_COUNT UK_INTCTLR_ALLOCABLE_IRQ_COUNT +#define FIRST_ALLOCABLE_IRQ UK_INTCTLR_FIRST_ALLOCABLE_IRQ +#define LAST_ALLOCABLE_IRQ UK_INTCTLR_LAST_ALLOCABLE_IRQ + struct uk_intctlr_desc *uk_intctlr; UK_EVENT(UK_INTCTLR_EVENT_IRQ); @@ -55,6 +63,8 @@ UK_EVENT(UK_INTCTLR_EVENT_IRQ); UK_TRACEPOINT(trace_uk_intctlr_unhandled_irq, "Unhandled irq=%lu\n", unsigned long); +static unsigned long irqs_allocated[UK_BITS_TO_LONGS(ALLOCABLE_IRQ_COUNT)]; + /* IRQ handlers declarations */ struct irq_handler { uk_intctlr_irq_handler_func_t func; @@ -245,6 +255,45 @@ int uk_intctlr_irq_fdt_xlat(const void *fdt, int nodeoffset, __u32 index, return uk_intctlr->ops->fdt_xlat(fdt, nodeoffset, index, irq); } +int uk_intctlr_irq_alloc(unsigned int *irqs, __sz count) +{ + unsigned long start, idx; + + UK_ASSERT(irqs); + + start = uk_bitmap_find_next_zero_area(irqs_allocated, + ALLOCABLE_IRQ_COUNT, 0, + count, 0); + if (start == ALLOCABLE_IRQ_COUNT) + return -ENOSPC; + + uk_bitmap_set(irqs_allocated, start, count); + for (idx = start; idx < (start + count); idx++) { + *irqs = idx + FIRST_ALLOCABLE_IRQ; + irqs++; + } + + return 0; +} + +int uk_intctlr_irq_free(unsigned int *irqs, __sz count) +{ + int rc = 0; + + UK_ASSERT(irqs); + + for (__sz i = 0; i < count; i++) { + UK_ASSERT(irqs[i] >= FIRST_ALLOCABLE_IRQ && + irqs[i] <= LAST_ALLOCABLE_IRQ); + + rc = uk_test_and_clear_bit(irqs[i] - FIRST_ALLOCABLE_IRQ, + irqs_allocated); + UK_ASSERT(rc); + } + + return !rc; +} + int uk_intctlr_init(struct uk_alloc *a __unused) { UK_ASSERT(uk_intctlr); -- 2.39.5