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>
This commit is contained in:
parent
b1f548645c
commit
414cbd1e3d
|
@ -35,13 +35,15 @@ struct airq_iv {
|
|||
unsigned int *data; /* 32 bit value associated with each bit */
|
||||
unsigned long bits; /* Number of bits in the vector */
|
||||
unsigned long end; /* Number of highest allocated bit + 1 */
|
||||
unsigned long flags; /* Allocation flags */
|
||||
spinlock_t lock; /* Lock to protect alloc & free */
|
||||
};
|
||||
|
||||
#define AIRQ_IV_ALLOC 1 /* Use an allocation bit mask */
|
||||
#define AIRQ_IV_BITLOCK 2 /* Allocate the lock bit mask */
|
||||
#define AIRQ_IV_PTR 4 /* Allocate the ptr array */
|
||||
#define AIRQ_IV_DATA 8 /* Allocate the data array */
|
||||
#define AIRQ_IV_ALLOC 1 /* Use an allocation bit mask */
|
||||
#define AIRQ_IV_BITLOCK 2 /* Allocate the lock bit mask */
|
||||
#define AIRQ_IV_PTR 4 /* Allocate the ptr array */
|
||||
#define AIRQ_IV_DATA 8 /* Allocate the data array */
|
||||
#define AIRQ_IV_CACHELINE 16 /* Cacheline alignment for the vector */
|
||||
|
||||
struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags);
|
||||
void airq_iv_release(struct airq_iv *iv);
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
static DEFINE_SPINLOCK(airq_lists_lock);
|
||||
static struct hlist_head airq_lists[MAX_ISC+1];
|
||||
|
||||
static struct kmem_cache *airq_iv_cache;
|
||||
|
||||
/**
|
||||
* register_adapter_interrupt() - register adapter interrupt handler
|
||||
* @airq: pointer to adapter interrupt descriptor
|
||||
|
@ -129,10 +131,21 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags)
|
|||
if (!iv)
|
||||
goto out;
|
||||
iv->bits = bits;
|
||||
iv->flags = flags;
|
||||
size = BITS_TO_LONGS(bits) * sizeof(unsigned long);
|
||||
iv->vector = kzalloc(size, GFP_KERNEL);
|
||||
if (!iv->vector)
|
||||
goto out_free;
|
||||
|
||||
if (flags & AIRQ_IV_CACHELINE) {
|
||||
if ((cache_line_size() * BITS_PER_BYTE) < bits)
|
||||
goto out_free;
|
||||
|
||||
iv->vector = kmem_cache_zalloc(airq_iv_cache, GFP_KERNEL);
|
||||
if (!iv->vector)
|
||||
goto out_free;
|
||||
} else {
|
||||
iv->vector = kzalloc(size, GFP_KERNEL);
|
||||
if (!iv->vector)
|
||||
goto out_free;
|
||||
}
|
||||
if (flags & AIRQ_IV_ALLOC) {
|
||||
iv->avail = kmalloc(size, GFP_KERNEL);
|
||||
if (!iv->avail)
|
||||
|
@ -165,7 +178,10 @@ struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags)
|
|||
kfree(iv->ptr);
|
||||
kfree(iv->bitlock);
|
||||
kfree(iv->avail);
|
||||
kfree(iv->vector);
|
||||
if (iv->flags & AIRQ_IV_CACHELINE)
|
||||
kmem_cache_free(airq_iv_cache, iv->vector);
|
||||
else
|
||||
kfree(iv->vector);
|
||||
kfree(iv);
|
||||
out:
|
||||
return NULL;
|
||||
|
@ -181,7 +197,10 @@ void airq_iv_release(struct airq_iv *iv)
|
|||
kfree(iv->data);
|
||||
kfree(iv->ptr);
|
||||
kfree(iv->bitlock);
|
||||
kfree(iv->vector);
|
||||
if (iv->flags & AIRQ_IV_CACHELINE)
|
||||
kmem_cache_free(airq_iv_cache, iv->vector);
|
||||
else
|
||||
kfree(iv->vector);
|
||||
kfree(iv->avail);
|
||||
kfree(iv);
|
||||
}
|
||||
|
@ -275,3 +294,13 @@ unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start,
|
|||
return bit;
|
||||
}
|
||||
EXPORT_SYMBOL(airq_iv_scan);
|
||||
|
||||
static int __init airq_init(void)
|
||||
{
|
||||
airq_iv_cache = kmem_cache_create("airq_iv_cache", cache_line_size(),
|
||||
cache_line_size(), 0, NULL);
|
||||
if (!airq_iv_cache)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(airq_init);
|
||||
|
|
Loading…
Reference in New Issue