183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter/*
283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter *  drivers/s390/cio/idset.c
383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter *
483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter *    Copyright IBM Corp. 2007
583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter */
783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
8883e512c99fc398d1b2b5e8e92b6bacff2551756Michael Ernst#include <linux/vmalloc.h>
91977f032722c27ee3730284582fd3991ad9ac81bJiri Slaby#include <linux/bitops.h>
1083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter#include "idset.h"
1183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter#include "css.h"
1283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
1383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterstruct idset {
1483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	int num_ssid;
1583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	int num_id;
1683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	unsigned long bitmap[0];
1783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter};
1883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
1983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterstatic inline unsigned long bitmap_size(int num_ssid, int num_id)
2083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
2183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	return __BITOPS_WORDS(num_ssid * num_id) * sizeof(unsigned long);
2283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
2383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
2483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterstatic struct idset *idset_new(int num_ssid, int num_id)
2583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
2683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	struct idset *set;
2783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
28883e512c99fc398d1b2b5e8e92b6bacff2551756Michael Ernst	set = vmalloc(sizeof(struct idset) + bitmap_size(num_ssid, num_id));
2983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	if (set) {
3083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter		set->num_ssid = num_ssid;
3183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter		set->num_id = num_id;
32883e512c99fc398d1b2b5e8e92b6bacff2551756Michael Ernst		memset(set->bitmap, 0, bitmap_size(num_ssid, num_id));
3383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	}
3483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	return set;
3583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
3683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
3783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleitervoid idset_free(struct idset *set)
3883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
39883e512c99fc398d1b2b5e8e92b6bacff2551756Michael Ernst	vfree(set);
4083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
4183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
4283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleitervoid idset_clear(struct idset *set)
4383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
4483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	memset(set->bitmap, 0, bitmap_size(set->num_ssid, set->num_id));
4583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
4683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
4783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleitervoid idset_fill(struct idset *set)
4883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
4983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	memset(set->bitmap, 0xff, bitmap_size(set->num_ssid, set->num_id));
5083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
5183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
5283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterstatic inline void idset_add(struct idset *set, int ssid, int id)
5383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
5483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	set_bit(ssid * set->num_id + id, set->bitmap);
5583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
5683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
5783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterstatic inline void idset_del(struct idset *set, int ssid, int id)
5883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
5983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	clear_bit(ssid * set->num_id + id, set->bitmap);
6083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
6183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
6283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterstatic inline int idset_contains(struct idset *set, int ssid, int id)
6383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
6483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	return test_bit(ssid * set->num_id + id, set->bitmap);
6583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
6683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
6783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterstatic inline int idset_get_first(struct idset *set, int *ssid, int *id)
6883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
6983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	int bitnum;
7083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
7183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id);
7283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	if (bitnum >= set->num_ssid * set->num_id)
7383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter		return 0;
7483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	*ssid = bitnum / set->num_id;
7583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	*id = bitnum % set->num_id;
7683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	return 1;
7783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
7883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
7983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterstruct idset *idset_sch_new(void)
8083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
81b0a285d31bd475fdd4312e457288be558b705e55Sebastian Ott	return idset_new(max_ssid + 1, __MAX_SUBCHANNEL + 1);
8283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
8383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
8483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleitervoid idset_sch_add(struct idset *set, struct subchannel_id schid)
8583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
8683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	idset_add(set, schid.ssid, schid.sch_no);
8783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
8883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
8983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleitervoid idset_sch_del(struct idset *set, struct subchannel_id schid)
9083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
9183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	idset_del(set, schid.ssid, schid.sch_no);
9283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
9383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
9483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterint idset_sch_contains(struct idset *set, struct subchannel_id schid)
9583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
9683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	return idset_contains(set, schid.ssid, schid.sch_no);
9783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
9883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
9983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiterint idset_sch_get_first(struct idset *set, struct subchannel_id *schid)
10083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter{
10183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	int ssid = 0;
10283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	int id = 0;
10383b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	int rc;
10483b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter
10583b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	rc = idset_get_first(set, &ssid, &id);
10683b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	if (rc) {
10783b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter		init_subchannel_id(schid);
10883b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter		schid->ssid = ssid;
10983b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter		schid->sch_no = id;
11083b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	}
11183b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter	return rc;
11283b3370c79b91b9be3f6540c3c914e689134b45fPeter Oberparleiter}
113255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott
114255305536c1b56ad09590f1400fb2c788265e34eSebastian Ottint idset_is_empty(struct idset *set)
115255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott{
116255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott	int bitnum;
117255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott
118255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott	bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id);
119255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott	if (bitnum >= set->num_ssid * set->num_id)
120255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott		return 1;
121255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott	return 0;
122255305536c1b56ad09590f1400fb2c788265e34eSebastian Ott}
123703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott
124703e5c9993639284bc0a8929b6de362424df7019Sebastian Ottvoid idset_add_set(struct idset *to, struct idset *from)
125703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott{
126703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott	unsigned long i, len;
127703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott
128703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott	len = min(__BITOPS_WORDS(to->num_ssid * to->num_id),
129703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott		  __BITOPS_WORDS(from->num_ssid * from->num_id));
130703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott	for (i = 0; i < len ; i++)
131703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott		to->bitmap[i] |= from->bitmap[i];
132703e5c9993639284bc0a8929b6de362424df7019Sebastian Ott}
133