genirq/matrix: Dynamic bitmap allocation
authorBjörn Töpel <bjorn@rivosinc.com>
Thu, 22 Feb 2024 09:39:58 +0000 (15:09 +0530)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 23 Feb 2024 09:18:44 +0000 (10:18 +0100)
A future user of the matrix allocator, does not know the size of the matrix
bitmaps at compile time.

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

Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240222094006.1030709-11-apatel@ventanamicro.com
arch/x86/include/asm/hw_irq.h
kernel/irq/matrix.c

index b02c3cd3c0f6564ad374602995c08d9082942744..edebf1020e0497ff0d424fc7b35c450cbd34e164 100644 (file)
@@ -16,8 +16,6 @@
 
 #include <asm/irq_vectors.h>
 
-#define IRQ_MATRIX_BITS                NR_VECTORS
-
 #ifndef __ASSEMBLY__
 
 #include <linux/percpu.h>
index 75d0ae490e29cd8b956fd1ecf7b5a5e99d883611..8f222d1cccecaef7bc079d3af73819ee275c8c29 100644 (file)
@@ -8,8 +8,6 @@
 #include <linux/cpu.h>
 #include <linux/irq.h>
 
-#define IRQ_MATRIX_SIZE        (BITS_TO_LONGS(IRQ_MATRIX_BITS))
-
 struct cpumap {
        unsigned int            available;
        unsigned int            allocated;
@@ -17,8 +15,8 @@ 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           *managed_map;
+       unsigned long           alloc_map[];
 };
 
 struct irq_matrix {
@@ -32,8 +30,8 @@ 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           *system_map;
+       unsigned long           scratch_map[];
 };
 
 #define CREATE_TRACE_POINTS
@@ -50,24 +48,32 @@ __init struct irq_matrix *irq_alloc_matrix(unsigned int matrix_bits,
                                           unsigned int alloc_start,
                                           unsigned int alloc_end)
 {
+       unsigned int cpu, matrix_size = BITS_TO_LONGS(matrix_bits);
        struct irq_matrix *m;
 
-       if (matrix_bits > IRQ_MATRIX_BITS)
-               return NULL;
-
-       m = kzalloc(sizeof(*m), GFP_KERNEL);
+       m = kzalloc(struct_size(m, scratch_map, matrix_size * 2), GFP_KERNEL);
        if (!m)
                return NULL;
 
+       m->system_map = &m->scratch_map[matrix_size];
+
        m->matrix_bits = matrix_bits;
        m->alloc_start = alloc_start;
        m->alloc_end = alloc_end;
        m->alloc_size = alloc_end - alloc_start;
-       m->maps = alloc_percpu(*m->maps);
+       m->maps = __alloc_percpu(struct_size(m->maps, alloc_map, matrix_size * 2),
+                                __alignof__(*m->maps));
        if (!m->maps) {
                kfree(m);
                return NULL;
        }
+
+       for_each_possible_cpu(cpu) {
+               struct cpumap *cm = per_cpu_ptr(m->maps, cpu);
+
+               cm->managed_map = &cm->alloc_map[matrix_size];
+       }
+
        return m;
 }