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