Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/airq: provide cacheline aligned ivs

Provide the ability to create cachesize aligned interrupt vectors.
These will be used for per-CPU interrupt vectors.

Signed-off-by: Sebastian Ott <sebott@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Sebastian Ott and committed by
Martin Schwidefsky
414cbd1e b1f54864

+40 -9
+6 -4
arch/s390/include/asm/airq.h
··· 35 35 unsigned int *data; /* 32 bit value associated with each bit */ 36 36 unsigned long bits; /* Number of bits in the vector */ 37 37 unsigned long end; /* Number of highest allocated bit + 1 */ 38 + unsigned long flags; /* Allocation flags */ 38 39 spinlock_t lock; /* Lock to protect alloc & free */ 39 40 }; 40 41 41 - #define AIRQ_IV_ALLOC 1 /* Use an allocation bit mask */ 42 - #define AIRQ_IV_BITLOCK 2 /* Allocate the lock bit mask */ 43 - #define AIRQ_IV_PTR 4 /* Allocate the ptr array */ 44 - #define AIRQ_IV_DATA 8 /* Allocate the data array */ 42 + #define AIRQ_IV_ALLOC 1 /* Use an allocation bit mask */ 43 + #define AIRQ_IV_BITLOCK 2 /* Allocate the lock bit mask */ 44 + #define AIRQ_IV_PTR 4 /* Allocate the ptr array */ 45 + #define AIRQ_IV_DATA 8 /* Allocate the data array */ 46 + #define AIRQ_IV_CACHELINE 16 /* Cacheline alignment for the vector */ 45 47 46 48 struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags); 47 49 void airq_iv_release(struct airq_iv *iv);
+34 -5
drivers/s390/cio/airq.c
··· 27 27 static DEFINE_SPINLOCK(airq_lists_lock); 28 28 static struct hlist_head airq_lists[MAX_ISC+1]; 29 29 30 + static struct kmem_cache *airq_iv_cache; 31 + 30 32 /** 31 33 * register_adapter_interrupt() - register adapter interrupt handler 32 34 * @airq: pointer to adapter interrupt descriptor ··· 131 129 if (!iv) 132 130 goto out; 133 131 iv->bits = bits; 132 + iv->flags = flags; 134 133 size = BITS_TO_LONGS(bits) * sizeof(unsigned long); 135 - iv->vector = kzalloc(size, GFP_KERNEL); 136 - if (!iv->vector) 137 - goto out_free; 134 + 135 + if (flags & AIRQ_IV_CACHELINE) { 136 + if ((cache_line_size() * BITS_PER_BYTE) < bits) 137 + goto out_free; 138 + 139 + iv->vector = kmem_cache_zalloc(airq_iv_cache, GFP_KERNEL); 140 + if (!iv->vector) 141 + goto out_free; 142 + } else { 143 + iv->vector = kzalloc(size, GFP_KERNEL); 144 + if (!iv->vector) 145 + goto out_free; 146 + } 138 147 if (flags & AIRQ_IV_ALLOC) { 139 148 iv->avail = kmalloc(size, GFP_KERNEL); 140 149 if (!iv->avail) ··· 178 165 kfree(iv->ptr); 179 166 kfree(iv->bitlock); 180 167 kfree(iv->avail); 181 - kfree(iv->vector); 168 + if (iv->flags & AIRQ_IV_CACHELINE) 169 + kmem_cache_free(airq_iv_cache, iv->vector); 170 + else 171 + kfree(iv->vector); 182 172 kfree(iv); 183 173 out: 184 174 return NULL; ··· 197 181 kfree(iv->data); 198 182 kfree(iv->ptr); 199 183 kfree(iv->bitlock); 200 - kfree(iv->vector); 184 + if (iv->flags & AIRQ_IV_CACHELINE) 185 + kmem_cache_free(airq_iv_cache, iv->vector); 186 + else 187 + kfree(iv->vector); 201 188 kfree(iv->avail); 202 189 kfree(iv); 203 190 } ··· 294 275 return bit; 295 276 } 296 277 EXPORT_SYMBOL(airq_iv_scan); 278 + 279 + static int __init airq_init(void) 280 + { 281 + airq_iv_cache = kmem_cache_create("airq_iv_cache", cache_line_size(), 282 + cache_line_size(), 0, NULL); 283 + if (!airq_iv_cache) 284 + return -ENOMEM; 285 + return 0; 286 + } 287 + subsys_initcall(airq_init);