xref: /openbmc/linux/drivers/s390/cio/idset.c (revision 26d0dfbb16fcb17d128a79dc70f3020ea6992af0)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
283b3370cSPeter Oberparleiter /*
3aa92b33cSSebastian Ott  *    Copyright IBM Corp. 2007, 2012
483b3370cSPeter Oberparleiter  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
583b3370cSPeter Oberparleiter  */
683b3370cSPeter Oberparleiter 
7883e512cSMichael Ernst #include <linux/vmalloc.h>
8aa92b33cSSebastian Ott #include <linux/bitmap.h>
91977f032SJiri Slaby #include <linux/bitops.h>
1083b3370cSPeter Oberparleiter #include "idset.h"
1183b3370cSPeter Oberparleiter #include "css.h"
1283b3370cSPeter Oberparleiter 
1383b3370cSPeter Oberparleiter struct idset {
1483b3370cSPeter Oberparleiter 	int num_ssid;
1583b3370cSPeter Oberparleiter 	int num_id;
16fa226f1dSGustavo A. R. Silva 	unsigned long bitmap[];
1783b3370cSPeter Oberparleiter };
1883b3370cSPeter Oberparleiter 
idset_bitmap_size(int num_ssid,int num_id)199805a881SAlexander Lobakin static inline unsigned long idset_bitmap_size(int num_ssid, int num_id)
2083b3370cSPeter Oberparleiter {
21*97a532c3SAlexander Lobakin 	return bitmap_size(size_mul(num_ssid, num_id));
2283b3370cSPeter Oberparleiter }
2383b3370cSPeter Oberparleiter 
idset_new(int num_ssid,int num_id)2483b3370cSPeter Oberparleiter static struct idset *idset_new(int num_ssid, int num_id)
2583b3370cSPeter Oberparleiter {
2683b3370cSPeter Oberparleiter 	struct idset *set;
2783b3370cSPeter Oberparleiter 
289805a881SAlexander Lobakin 	set = vmalloc(sizeof(struct idset) +
299805a881SAlexander Lobakin 		      idset_bitmap_size(num_ssid, num_id));
3083b3370cSPeter Oberparleiter 	if (set) {
3183b3370cSPeter Oberparleiter 		set->num_ssid = num_ssid;
3283b3370cSPeter Oberparleiter 		set->num_id = num_id;
339805a881SAlexander Lobakin 		memset(set->bitmap, 0, idset_bitmap_size(num_ssid, num_id));
3483b3370cSPeter Oberparleiter 	}
3583b3370cSPeter Oberparleiter 	return set;
3683b3370cSPeter Oberparleiter }
3783b3370cSPeter Oberparleiter 
idset_free(struct idset * set)3883b3370cSPeter Oberparleiter void idset_free(struct idset *set)
3983b3370cSPeter Oberparleiter {
40883e512cSMichael Ernst 	vfree(set);
4183b3370cSPeter Oberparleiter }
4283b3370cSPeter Oberparleiter 
idset_fill(struct idset * set)4383b3370cSPeter Oberparleiter void idset_fill(struct idset *set)
4483b3370cSPeter Oberparleiter {
459805a881SAlexander Lobakin 	memset(set->bitmap, 0xff,
469805a881SAlexander Lobakin 	       idset_bitmap_size(set->num_ssid, set->num_id));
4783b3370cSPeter Oberparleiter }
4883b3370cSPeter Oberparleiter 
idset_add(struct idset * set,int ssid,int id)4983b3370cSPeter Oberparleiter static inline void idset_add(struct idset *set, int ssid, int id)
5083b3370cSPeter Oberparleiter {
5183b3370cSPeter Oberparleiter 	set_bit(ssid * set->num_id + id, set->bitmap);
5283b3370cSPeter Oberparleiter }
5383b3370cSPeter Oberparleiter 
idset_del(struct idset * set,int ssid,int id)5483b3370cSPeter Oberparleiter static inline void idset_del(struct idset *set, int ssid, int id)
5583b3370cSPeter Oberparleiter {
5683b3370cSPeter Oberparleiter 	clear_bit(ssid * set->num_id + id, set->bitmap);
5783b3370cSPeter Oberparleiter }
5883b3370cSPeter Oberparleiter 
idset_contains(struct idset * set,int ssid,int id)5983b3370cSPeter Oberparleiter static inline int idset_contains(struct idset *set, int ssid, int id)
6083b3370cSPeter Oberparleiter {
6183b3370cSPeter Oberparleiter 	return test_bit(ssid * set->num_id + id, set->bitmap);
6283b3370cSPeter Oberparleiter }
6383b3370cSPeter Oberparleiter 
idset_sch_new(void)6483b3370cSPeter Oberparleiter struct idset *idset_sch_new(void)
6583b3370cSPeter Oberparleiter {
66b0a285d3SSebastian Ott 	return idset_new(max_ssid + 1, __MAX_SUBCHANNEL + 1);
6783b3370cSPeter Oberparleiter }
6883b3370cSPeter Oberparleiter 
idset_sch_add(struct idset * set,struct subchannel_id schid)6983b3370cSPeter Oberparleiter void idset_sch_add(struct idset *set, struct subchannel_id schid)
7083b3370cSPeter Oberparleiter {
7183b3370cSPeter Oberparleiter 	idset_add(set, schid.ssid, schid.sch_no);
7283b3370cSPeter Oberparleiter }
7383b3370cSPeter Oberparleiter 
idset_sch_del(struct idset * set,struct subchannel_id schid)7483b3370cSPeter Oberparleiter void idset_sch_del(struct idset *set, struct subchannel_id schid)
7583b3370cSPeter Oberparleiter {
7683b3370cSPeter Oberparleiter 	idset_del(set, schid.ssid, schid.sch_no);
7783b3370cSPeter Oberparleiter }
7883b3370cSPeter Oberparleiter 
79cec85466SSebastian Ott /* Clear ids starting from @schid up to end of subchannel set. */
idset_sch_del_subseq(struct idset * set,struct subchannel_id schid)80cec85466SSebastian Ott void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid)
81cec85466SSebastian Ott {
82cec85466SSebastian Ott 	int pos = schid.ssid * set->num_id + schid.sch_no;
83cec85466SSebastian Ott 
84cec85466SSebastian Ott 	bitmap_clear(set->bitmap, pos, set->num_id - schid.sch_no);
85cec85466SSebastian Ott }
86cec85466SSebastian Ott 
idset_sch_contains(struct idset * set,struct subchannel_id schid)8783b3370cSPeter Oberparleiter int idset_sch_contains(struct idset *set, struct subchannel_id schid)
8883b3370cSPeter Oberparleiter {
8983b3370cSPeter Oberparleiter 	return idset_contains(set, schid.ssid, schid.sch_no);
9083b3370cSPeter Oberparleiter }
9183b3370cSPeter Oberparleiter 
idset_is_empty(struct idset * set)9225530553SSebastian Ott int idset_is_empty(struct idset *set)
9325530553SSebastian Ott {
94aa92b33cSSebastian Ott 	return bitmap_empty(set->bitmap, set->num_ssid * set->num_id);
9525530553SSebastian Ott }
96703e5c99SSebastian Ott 
idset_add_set(struct idset * to,struct idset * from)97703e5c99SSebastian Ott void idset_add_set(struct idset *to, struct idset *from)
98703e5c99SSebastian Ott {
997f0bc6c0SSebastian Ott 	int len = min(to->num_ssid * to->num_id, from->num_ssid * from->num_id);
100aa92b33cSSebastian Ott 
101aa92b33cSSebastian Ott 	bitmap_or(to->bitmap, to->bitmap, from->bitmap, len);
102703e5c99SSebastian Ott }
103