[PATCH] genirq/matrix: Dynamic bitmap allocation

From: =3D?UTF-8?q?Bj=3DC3=3DB6rn=3D20T=3DC3=3DB6pel?=3D
Date: Thu Oct 26 2023 - 04:17:21 EST


Some (future) users of the irq matrix allocator, do not know the size
of the bitmaps at compile time.

To avoid wasting memory on unneccesary large bitmaps, size the bitmap
at matrix allocation time.

Signed-off-by: Bj=C3=B6rn T=C3=B6pel <bjorn@xxxxxxxxxxxx>
---
arch/x86/include/asm/hw_irq.h | 2 --
kernel/irq/matrix.c | 33 ++++++++++++++++++++++-----------
2 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 551829884734..dcfaa3812306 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -16,8 +16,6 @@
=20
#include <asm/irq_vectors.h>
=20
-#define IRQ_MATRIX_BITS NR_VECTORS
-
#ifndef __ASSEMBLY__
=20
#include <linux/percpu.h>
diff --git a/kernel/irq/matrix.c b/kernel/irq/matrix.c
index 1698e77645ac..16ce956935ca 100644
--- a/kernel/irq/matrix.c
+++ b/kernel/irq/matrix.c
@@ -8,8 +8,6 @@
#include <linux/cpu.h>
#include <linux/irq.h>
=20
-#define IRQ_MATRIX_SIZE (BITS_TO_LONGS(IRQ_MATRIX_BITS))
-
struct cpumap {
unsigned int available;
unsigned int allocated;
@@ -17,8 +15,9 @@ struct cpumap {
unsigned int managed_allocated;
bool initialized;
bool online;
- unsigned long alloc_map[IRQ_MATRIX_SIZE];
- unsigned long managed_map[IRQ_MATRIX_SIZE];
+ unsigned long *alloc_map;
+ unsigned long *managed_map;
+ unsigned long bitmap_storage[];
};
=20
struct irq_matrix {
@@ -32,8 +31,10 @@ struct irq_matrix {
unsigned int total_allocated;
unsigned int online_maps;
struct cpumap __percpu *maps;
- unsigned long scratch_map[IRQ_MATRIX_SIZE];
- unsigned long system_map[IRQ_MATRIX_SIZE];
+ unsigned long *scratch_map;
+ unsigned long *system_map;
+ unsigned long bitmap_storage[];
+
};
=20
#define CREATE_TRACE_POINTS
@@ -50,24 +51,34 @@ __init struct irq_matrix *irq_alloc_matrix(unsigned int=
matrix_bits,
unsigned int alloc_start,
unsigned int alloc_end)
{
+ unsigned int cpu, matrix_size =3D BITS_TO_LONGS(matrix_bits);
struct irq_matrix *m;
=20
- if (matrix_bits > IRQ_MATRIX_BITS)
- return NULL;
-
- m =3D kzalloc(sizeof(*m), GFP_KERNEL);
+ m =3D kzalloc(struct_size(m, bitmap_storage, matrix_size * 2), GFP_KERNEL=
);
if (!m)
return NULL;
=20
+ m->scratch_map =3D &m->bitmap_storage[0];
+ m->system_map =3D &m->bitmap_storage[matrix_size];
+
m->matrix_bits =3D matrix_bits;
m->alloc_start =3D alloc_start;
m->alloc_end =3D alloc_end;
m->alloc_size =3D alloc_end - alloc_start;
- m->maps =3D alloc_percpu(*m->maps);
+ m->maps =3D __alloc_percpu(struct_size(m->maps, bitmap_storage, matrix_si=
ze * 2),
+ __alignof__(*m->maps));
if (!m->maps) {
kfree(m);
return NULL;
}
+
+ for_each_possible_cpu(cpu){
+ struct cpumap *cm =3D per_cpu_ptr(m->maps, cpu);
+
+ cm->alloc_map =3D &cm->bitmap_storage[0];
+ cm->managed_map =3D &cm->bitmap_storage[matrix_size];
+ }
+
return m;
}
=20

base-commit: 611da07b89fdd53f140d7b33013f255bf0ed8f34
--=20
2.40.1

--8<--


>> The matrix allocator is an excellent fit, modulo multi-MSI. It's battle
>> proven code.
>>
>> > 2) IRQ matrix allocator needs to be support allocator multiple vectors
>> > in power-of-2 which will allow IMSIC driver to support both legacy
>> > MSI and MSI-X. This will involve changing the way best CPU is
>> > found, the way bitmap APIs are used and adding some new APIs
>> > for allocate vectors in power-of-2
>>
>> ...and all the other things multi-MSI requires.
>>
>> > Based on above, I suggest we keep the integration of IRQ matrix
>> > allocator in the IMSIC driver as a separate series which will allow
>> > us to unblock other series (such as AIA ACPI support, power
>> > managment related changes in AIA drivers, etc).
>>
>> I suggest removing the multi-MSI support, and use the matrix allocator.
>> We have something that looks like what x86 has (IMSIC). We have a
>> battle-proven implementation, and helper function. In my view it would
>> be just weird not to piggy-back on that work, and benefit from years of
>> bugfixes/things we haven't thought of.
>>
>> Finally; I don't see that you're handling managed interrupt in the
>> series (Oh, the matrix allocator has support for that! ;-)).
>
> We don't need managed interrupts like x86 does. We are using
> IPI-mux to create multiple virtual IPIs on-top-of single ID and we
> use some of these virtual IPIs for internal managment.

I'm not following here, and what IPI's has to do with managed
interrupts. I'm referring to "IRQD_AFFINITY_MANAGED".

I'm probably missing something?


Bj=C3=B6rn