Commit 414cbd1e authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky
Browse files

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: default avatarSebastian Ott <sebott@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent b1f54864
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ 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 */
};

@@ -42,6 +43,7 @@ struct airq_iv {
#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);
+34 −5
Original line number Diff line number Diff line
@@ -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);

	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,6 +178,9 @@ out_free:
	kfree(iv->ptr);
	kfree(iv->bitlock);
	kfree(iv->avail);
	if (iv->flags & AIRQ_IV_CACHELINE)
		kmem_cache_free(airq_iv_cache, iv->vector);
	else
		kfree(iv->vector);
	kfree(iv);
out:
@@ -181,6 +197,9 @@ void airq_iv_release(struct airq_iv *iv)
	kfree(iv->data);
	kfree(iv->ptr);
	kfree(iv->bitlock);
	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);