1c9dd0b48SHans Petter Selasky /*
2c9dd0b48SHans Petter Selasky * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
3c9dd0b48SHans Petter Selasky * All rights reserved.
4c9dd0b48SHans Petter Selasky *
5c9dd0b48SHans Petter Selasky * Redistribution and use in source and binary forms, with or without
6c9dd0b48SHans Petter Selasky * modification, are permitted provided that the following conditions
7c9dd0b48SHans Petter Selasky * are met:
8c9dd0b48SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright
9c9dd0b48SHans Petter Selasky * notice unmodified, this list of conditions, and the following
10c9dd0b48SHans Petter Selasky * disclaimer.
11c9dd0b48SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright
12c9dd0b48SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the
13c9dd0b48SHans Petter Selasky * documentation and/or other materials provided with the distribution.
14c9dd0b48SHans Petter Selasky *
15c9dd0b48SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16c9dd0b48SHans Petter Selasky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17c9dd0b48SHans Petter Selasky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18c9dd0b48SHans Petter Selasky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19c9dd0b48SHans Petter Selasky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20c9dd0b48SHans Petter Selasky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21c9dd0b48SHans Petter Selasky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22c9dd0b48SHans Petter Selasky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23c9dd0b48SHans Petter Selasky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24c9dd0b48SHans Petter Selasky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25c9dd0b48SHans Petter Selasky */
26c9dd0b48SHans Petter Selasky
27307f78f3SVladimir Kondratyev #ifndef _LINUXKPI_LINUX_BITMAP_H_
28307f78f3SVladimir Kondratyev #define _LINUXKPI_LINUX_BITMAP_H_
29c9dd0b48SHans Petter Selasky
30c9dd0b48SHans Petter Selasky #include <linux/bitops.h>
31ce03b301SEmmanuel Vadot #include <linux/slab.h>
32c9dd0b48SHans Petter Selasky
33c9dd0b48SHans Petter Selasky static inline void
bitmap_zero(unsigned long * addr,const unsigned int size)34c9dd0b48SHans Petter Selasky bitmap_zero(unsigned long *addr, const unsigned int size)
35c9dd0b48SHans Petter Selasky {
36c9dd0b48SHans Petter Selasky memset(addr, 0, BITS_TO_LONGS(size) * sizeof(long));
37c9dd0b48SHans Petter Selasky }
38c9dd0b48SHans Petter Selasky
39c9dd0b48SHans Petter Selasky static inline void
bitmap_fill(unsigned long * addr,const unsigned int size)40c9dd0b48SHans Petter Selasky bitmap_fill(unsigned long *addr, const unsigned int size)
41c9dd0b48SHans Petter Selasky {
42c9dd0b48SHans Petter Selasky const unsigned int tail = size & (BITS_PER_LONG - 1);
43c9dd0b48SHans Petter Selasky
44c9dd0b48SHans Petter Selasky memset(addr, 0xff, BIT_WORD(size) * sizeof(long));
45c9dd0b48SHans Petter Selasky
46c9dd0b48SHans Petter Selasky if (tail)
47c9dd0b48SHans Petter Selasky addr[BIT_WORD(size)] = BITMAP_LAST_WORD_MASK(tail);
48c9dd0b48SHans Petter Selasky }
49c9dd0b48SHans Petter Selasky
50c9dd0b48SHans Petter Selasky static inline int
bitmap_full(unsigned long * addr,const unsigned int size)51c9dd0b48SHans Petter Selasky bitmap_full(unsigned long *addr, const unsigned int size)
52c9dd0b48SHans Petter Selasky {
53c9dd0b48SHans Petter Selasky const unsigned int end = BIT_WORD(size);
54c9dd0b48SHans Petter Selasky const unsigned int tail = size & (BITS_PER_LONG - 1);
55c9dd0b48SHans Petter Selasky unsigned int i;
56c9dd0b48SHans Petter Selasky
57c9dd0b48SHans Petter Selasky for (i = 0; i != end; i++) {
58c9dd0b48SHans Petter Selasky if (addr[i] != ~0UL)
59c9dd0b48SHans Petter Selasky return (0);
60c9dd0b48SHans Petter Selasky }
61c9dd0b48SHans Petter Selasky
62c9dd0b48SHans Petter Selasky if (tail) {
63c9dd0b48SHans Petter Selasky const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
64c9dd0b48SHans Petter Selasky
65c9dd0b48SHans Petter Selasky if ((addr[end] & mask) != mask)
66c9dd0b48SHans Petter Selasky return (0);
67c9dd0b48SHans Petter Selasky }
68c9dd0b48SHans Petter Selasky return (1);
69c9dd0b48SHans Petter Selasky }
70c9dd0b48SHans Petter Selasky
71c9dd0b48SHans Petter Selasky static inline int
bitmap_empty(unsigned long * addr,const unsigned int size)72c9dd0b48SHans Petter Selasky bitmap_empty(unsigned long *addr, const unsigned int size)
73c9dd0b48SHans Petter Selasky {
74c9dd0b48SHans Petter Selasky const unsigned int end = BIT_WORD(size);
75c9dd0b48SHans Petter Selasky const unsigned int tail = size & (BITS_PER_LONG - 1);
76c9dd0b48SHans Petter Selasky unsigned int i;
77c9dd0b48SHans Petter Selasky
78c9dd0b48SHans Petter Selasky for (i = 0; i != end; i++) {
79c9dd0b48SHans Petter Selasky if (addr[i] != 0)
80c9dd0b48SHans Petter Selasky return (0);
81c9dd0b48SHans Petter Selasky }
82c9dd0b48SHans Petter Selasky
83c9dd0b48SHans Petter Selasky if (tail) {
84c9dd0b48SHans Petter Selasky const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
85c9dd0b48SHans Petter Selasky
86c9dd0b48SHans Petter Selasky if ((addr[end] & mask) != 0)
87c9dd0b48SHans Petter Selasky return (0);
88c9dd0b48SHans Petter Selasky }
89c9dd0b48SHans Petter Selasky return (1);
90c9dd0b48SHans Petter Selasky }
91c9dd0b48SHans Petter Selasky
92c9dd0b48SHans Petter Selasky static inline void
bitmap_set(unsigned long * map,unsigned int start,int nr)93c9dd0b48SHans Petter Selasky bitmap_set(unsigned long *map, unsigned int start, int nr)
94c9dd0b48SHans Petter Selasky {
95c9dd0b48SHans Petter Selasky const unsigned int size = start + nr;
96c9dd0b48SHans Petter Selasky int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
97c9dd0b48SHans Petter Selasky unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
98c9dd0b48SHans Petter Selasky
99c9dd0b48SHans Petter Selasky map += BIT_WORD(start);
100c9dd0b48SHans Petter Selasky
101c9dd0b48SHans Petter Selasky while (nr - bits_to_set >= 0) {
102c9dd0b48SHans Petter Selasky *map |= mask_to_set;
103c9dd0b48SHans Petter Selasky nr -= bits_to_set;
104c9dd0b48SHans Petter Selasky bits_to_set = BITS_PER_LONG;
105c9dd0b48SHans Petter Selasky mask_to_set = ~0UL;
106c9dd0b48SHans Petter Selasky map++;
107c9dd0b48SHans Petter Selasky }
108c9dd0b48SHans Petter Selasky
109c9dd0b48SHans Petter Selasky if (nr) {
110c9dd0b48SHans Petter Selasky mask_to_set &= BITMAP_LAST_WORD_MASK(size);
111c9dd0b48SHans Petter Selasky *map |= mask_to_set;
112c9dd0b48SHans Petter Selasky }
113c9dd0b48SHans Petter Selasky }
114c9dd0b48SHans Petter Selasky
115c9dd0b48SHans Petter Selasky static inline void
bitmap_clear(unsigned long * map,unsigned int start,int nr)116c9dd0b48SHans Petter Selasky bitmap_clear(unsigned long *map, unsigned int start, int nr)
117c9dd0b48SHans Petter Selasky {
118c9dd0b48SHans Petter Selasky const unsigned int size = start + nr;
119c9dd0b48SHans Petter Selasky int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
120c9dd0b48SHans Petter Selasky unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
121c9dd0b48SHans Petter Selasky
122c9dd0b48SHans Petter Selasky map += BIT_WORD(start);
123c9dd0b48SHans Petter Selasky
124c9dd0b48SHans Petter Selasky while (nr - bits_to_clear >= 0) {
125c9dd0b48SHans Petter Selasky *map &= ~mask_to_clear;
126c9dd0b48SHans Petter Selasky nr -= bits_to_clear;
127c9dd0b48SHans Petter Selasky bits_to_clear = BITS_PER_LONG;
128c9dd0b48SHans Petter Selasky mask_to_clear = ~0UL;
129c9dd0b48SHans Petter Selasky map++;
130c9dd0b48SHans Petter Selasky }
131c9dd0b48SHans Petter Selasky
132c9dd0b48SHans Petter Selasky if (nr) {
133c9dd0b48SHans Petter Selasky mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
134c9dd0b48SHans Petter Selasky *map &= ~mask_to_clear;
135c9dd0b48SHans Petter Selasky }
136c9dd0b48SHans Petter Selasky }
137c9dd0b48SHans Petter Selasky
138c9dd0b48SHans Petter Selasky static inline unsigned int
bitmap_find_next_zero_area_off(const unsigned long * map,const unsigned int size,unsigned int start,unsigned int nr,unsigned int align_mask,unsigned int align_offset)139c9dd0b48SHans Petter Selasky bitmap_find_next_zero_area_off(const unsigned long *map,
140c9dd0b48SHans Petter Selasky const unsigned int size, unsigned int start,
141c9dd0b48SHans Petter Selasky unsigned int nr, unsigned int align_mask,
142c9dd0b48SHans Petter Selasky unsigned int align_offset)
143c9dd0b48SHans Petter Selasky {
144c9dd0b48SHans Petter Selasky unsigned int index;
145c9dd0b48SHans Petter Selasky unsigned int end;
146c9dd0b48SHans Petter Selasky unsigned int i;
147c9dd0b48SHans Petter Selasky
148c9dd0b48SHans Petter Selasky retry:
149c9dd0b48SHans Petter Selasky index = find_next_zero_bit(map, size, start);
150c9dd0b48SHans Petter Selasky
151c9dd0b48SHans Petter Selasky index = (((index + align_offset) + align_mask) & ~align_mask) - align_offset;
152c9dd0b48SHans Petter Selasky
153c9dd0b48SHans Petter Selasky end = index + nr;
154c9dd0b48SHans Petter Selasky if (end > size)
155c9dd0b48SHans Petter Selasky return (end);
156c9dd0b48SHans Petter Selasky
157c9dd0b48SHans Petter Selasky i = find_next_bit(map, end, index);
158c9dd0b48SHans Petter Selasky if (i < end) {
159c9dd0b48SHans Petter Selasky start = i + 1;
160c9dd0b48SHans Petter Selasky goto retry;
161c9dd0b48SHans Petter Selasky }
162c9dd0b48SHans Petter Selasky return (index);
163c9dd0b48SHans Petter Selasky }
164c9dd0b48SHans Petter Selasky
165c9dd0b48SHans Petter Selasky static inline unsigned int
bitmap_find_next_zero_area(const unsigned long * map,const unsigned int size,unsigned int start,unsigned int nr,unsigned int align_mask)166c9dd0b48SHans Petter Selasky bitmap_find_next_zero_area(const unsigned long *map,
167c9dd0b48SHans Petter Selasky const unsigned int size, unsigned int start,
168c9dd0b48SHans Petter Selasky unsigned int nr, unsigned int align_mask)
169c9dd0b48SHans Petter Selasky {
170c9dd0b48SHans Petter Selasky return (bitmap_find_next_zero_area_off(map, size,
171c9dd0b48SHans Petter Selasky start, nr, align_mask, 0));
172c9dd0b48SHans Petter Selasky }
173c9dd0b48SHans Petter Selasky
174c9dd0b48SHans Petter Selasky static inline int
bitmap_find_free_region(unsigned long * bitmap,int bits,int order)175c9dd0b48SHans Petter Selasky bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
176c9dd0b48SHans Petter Selasky {
177c9dd0b48SHans Petter Selasky int pos;
178c9dd0b48SHans Petter Selasky int end;
179c9dd0b48SHans Petter Selasky
180c9dd0b48SHans Petter Selasky for (pos = 0; (end = pos + (1 << order)) <= bits; pos = end) {
181c9dd0b48SHans Petter Selasky if (!linux_reg_op(bitmap, pos, order, REG_OP_ISFREE))
182c9dd0b48SHans Petter Selasky continue;
183c9dd0b48SHans Petter Selasky linux_reg_op(bitmap, pos, order, REG_OP_ALLOC);
184c9dd0b48SHans Petter Selasky return (pos);
185c9dd0b48SHans Petter Selasky }
186c9dd0b48SHans Petter Selasky return (-ENOMEM);
187c9dd0b48SHans Petter Selasky }
188c9dd0b48SHans Petter Selasky
189c9dd0b48SHans Petter Selasky static inline int
bitmap_allocate_region(unsigned long * bitmap,int pos,int order)190c9dd0b48SHans Petter Selasky bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
191c9dd0b48SHans Petter Selasky {
192c9dd0b48SHans Petter Selasky if (!linux_reg_op(bitmap, pos, order, REG_OP_ISFREE))
193c9dd0b48SHans Petter Selasky return (-EBUSY);
194c9dd0b48SHans Petter Selasky linux_reg_op(bitmap, pos, order, REG_OP_ALLOC);
195c9dd0b48SHans Petter Selasky return (0);
196c9dd0b48SHans Petter Selasky }
197c9dd0b48SHans Petter Selasky
198c9dd0b48SHans Petter Selasky static inline void
bitmap_release_region(unsigned long * bitmap,int pos,int order)199c9dd0b48SHans Petter Selasky bitmap_release_region(unsigned long *bitmap, int pos, int order)
200c9dd0b48SHans Petter Selasky {
201c9dd0b48SHans Petter Selasky linux_reg_op(bitmap, pos, order, REG_OP_RELEASE);
202c9dd0b48SHans Petter Selasky }
203c9dd0b48SHans Petter Selasky
204c9dd0b48SHans Petter Selasky static inline unsigned int
bitmap_weight(unsigned long * addr,const unsigned int size)205c9dd0b48SHans Petter Selasky bitmap_weight(unsigned long *addr, const unsigned int size)
206c9dd0b48SHans Petter Selasky {
207c9dd0b48SHans Petter Selasky const unsigned int end = BIT_WORD(size);
208c9dd0b48SHans Petter Selasky const unsigned int tail = size & (BITS_PER_LONG - 1);
209c9dd0b48SHans Petter Selasky unsigned int retval = 0;
210c9dd0b48SHans Petter Selasky unsigned int i;
211c9dd0b48SHans Petter Selasky
212c9dd0b48SHans Petter Selasky for (i = 0; i != end; i++)
213c9dd0b48SHans Petter Selasky retval += hweight_long(addr[i]);
214c9dd0b48SHans Petter Selasky
215c9dd0b48SHans Petter Selasky if (tail) {
216c9dd0b48SHans Petter Selasky const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
217c9dd0b48SHans Petter Selasky
218c9dd0b48SHans Petter Selasky retval += hweight_long(addr[end] & mask);
219c9dd0b48SHans Petter Selasky }
220c9dd0b48SHans Petter Selasky return (retval);
221c9dd0b48SHans Petter Selasky }
222c9dd0b48SHans Petter Selasky
223c9dd0b48SHans Petter Selasky static inline int
bitmap_equal(const unsigned long * pa,const unsigned long * pb,unsigned size)224c9dd0b48SHans Petter Selasky bitmap_equal(const unsigned long *pa,
225c9dd0b48SHans Petter Selasky const unsigned long *pb, unsigned size)
226c9dd0b48SHans Petter Selasky {
227c9dd0b48SHans Petter Selasky const unsigned int end = BIT_WORD(size);
228c9dd0b48SHans Petter Selasky const unsigned int tail = size & (BITS_PER_LONG - 1);
229c9dd0b48SHans Petter Selasky unsigned int i;
230c9dd0b48SHans Petter Selasky
231c9dd0b48SHans Petter Selasky for (i = 0; i != end; i++) {
232c9dd0b48SHans Petter Selasky if (pa[i] != pb[i])
233c9dd0b48SHans Petter Selasky return (0);
234c9dd0b48SHans Petter Selasky }
235c9dd0b48SHans Petter Selasky
236c9dd0b48SHans Petter Selasky if (tail) {
237c9dd0b48SHans Petter Selasky const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
238c9dd0b48SHans Petter Selasky
239c9dd0b48SHans Petter Selasky if ((pa[end] ^ pb[end]) & mask)
240c9dd0b48SHans Petter Selasky return (0);
241c9dd0b48SHans Petter Selasky }
242c9dd0b48SHans Petter Selasky return (1);
243c9dd0b48SHans Petter Selasky }
244c9dd0b48SHans Petter Selasky
245127d8cfaSHans Petter Selasky static inline int
bitmap_subset(const unsigned long * pa,const unsigned long * pb,unsigned size)246127d8cfaSHans Petter Selasky bitmap_subset(const unsigned long *pa,
247127d8cfaSHans Petter Selasky const unsigned long *pb, unsigned size)
248127d8cfaSHans Petter Selasky {
249127d8cfaSHans Petter Selasky const unsigned end = BIT_WORD(size);
250127d8cfaSHans Petter Selasky const unsigned tail = size & (BITS_PER_LONG - 1);
251127d8cfaSHans Petter Selasky unsigned i;
252127d8cfaSHans Petter Selasky
253127d8cfaSHans Petter Selasky for (i = 0; i != end; i++) {
254127d8cfaSHans Petter Selasky if (pa[i] & ~pb[i])
255127d8cfaSHans Petter Selasky return (0);
256127d8cfaSHans Petter Selasky }
257127d8cfaSHans Petter Selasky
258127d8cfaSHans Petter Selasky if (tail) {
259127d8cfaSHans Petter Selasky const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
260127d8cfaSHans Petter Selasky
261127d8cfaSHans Petter Selasky if (pa[end] & ~pb[end] & mask)
262127d8cfaSHans Petter Selasky return (0);
263127d8cfaSHans Petter Selasky }
264127d8cfaSHans Petter Selasky return (1);
265127d8cfaSHans Petter Selasky }
266127d8cfaSHans Petter Selasky
2675ae2e6f9SVladimir Kondratyev static inline bool
bitmap_intersects(const unsigned long * pa,const unsigned long * pb,unsigned size)2685ae2e6f9SVladimir Kondratyev bitmap_intersects(const unsigned long *pa, const unsigned long *pb,
2695ae2e6f9SVladimir Kondratyev unsigned size)
2705ae2e6f9SVladimir Kondratyev {
2715ae2e6f9SVladimir Kondratyev const unsigned end = BIT_WORD(size);
2725ae2e6f9SVladimir Kondratyev const unsigned tail = size & (BITS_PER_LONG - 1);
2735ae2e6f9SVladimir Kondratyev unsigned i;
2745ae2e6f9SVladimir Kondratyev
2755ae2e6f9SVladimir Kondratyev for (i = 0; i != end; i++)
2765ae2e6f9SVladimir Kondratyev if (pa[i] & pb[i])
2775ae2e6f9SVladimir Kondratyev return (true);
2785ae2e6f9SVladimir Kondratyev
2795ae2e6f9SVladimir Kondratyev if (tail) {
2805ae2e6f9SVladimir Kondratyev const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
2815ae2e6f9SVladimir Kondratyev
2825ae2e6f9SVladimir Kondratyev if (pa[end] & pb[end] & mask)
2835ae2e6f9SVladimir Kondratyev return (true);
2845ae2e6f9SVladimir Kondratyev }
2855ae2e6f9SVladimir Kondratyev return (false);
2865ae2e6f9SVladimir Kondratyev }
2875ae2e6f9SVladimir Kondratyev
288c9dd0b48SHans Petter Selasky static inline void
bitmap_complement(unsigned long * dst,const unsigned long * src,const unsigned int size)2897ce7605eSHans Petter Selasky bitmap_complement(unsigned long *dst, const unsigned long *src,
2907ce7605eSHans Petter Selasky const unsigned int size)
2917ce7605eSHans Petter Selasky {
2927ce7605eSHans Petter Selasky const unsigned int end = BITS_TO_LONGS(size);
2937ce7605eSHans Petter Selasky unsigned int i;
2947ce7605eSHans Petter Selasky
2957ce7605eSHans Petter Selasky for (i = 0; i != end; i++)
2967ce7605eSHans Petter Selasky dst[i] = ~src[i];
2977ce7605eSHans Petter Selasky }
2987ce7605eSHans Petter Selasky
2997ce7605eSHans Petter Selasky static inline void
bitmap_copy(unsigned long * dst,const unsigned long * src,const unsigned int size)30026a57869SEmmanuel Vadot bitmap_copy(unsigned long *dst, const unsigned long *src,
30126a57869SEmmanuel Vadot const unsigned int size)
30226a57869SEmmanuel Vadot {
30326a57869SEmmanuel Vadot const unsigned int end = BITS_TO_LONGS(size);
30426a57869SEmmanuel Vadot unsigned int i;
30526a57869SEmmanuel Vadot
30626a57869SEmmanuel Vadot for (i = 0; i != end; i++)
30726a57869SEmmanuel Vadot dst[i] = src[i];
30826a57869SEmmanuel Vadot }
30926a57869SEmmanuel Vadot
31026a57869SEmmanuel Vadot static inline void
bitmap_to_arr32(uint32_t * dst,const unsigned long * src,unsigned int size)311e5cf9debSVladimir Kondratyev bitmap_to_arr32(uint32_t *dst, const unsigned long *src, unsigned int size)
312e5cf9debSVladimir Kondratyev {
313e5cf9debSVladimir Kondratyev const unsigned int end = howmany(size, 32);
314e5cf9debSVladimir Kondratyev
315e5cf9debSVladimir Kondratyev #ifdef __LP64__
316e5cf9debSVladimir Kondratyev unsigned int i = 0;
317e5cf9debSVladimir Kondratyev while (i < end) {
318e5cf9debSVladimir Kondratyev dst[i++] = (uint32_t)(*src & UINT_MAX);
319e5cf9debSVladimir Kondratyev if (i < end)
320e5cf9debSVladimir Kondratyev dst[i++] = (uint32_t)(*src >> 32);
321e5cf9debSVladimir Kondratyev src++;
322e5cf9debSVladimir Kondratyev }
323e5cf9debSVladimir Kondratyev #else
32406c844e1SVladimir Kondratyev bitmap_copy((unsigned long *)dst, src, size);
325e5cf9debSVladimir Kondratyev #endif
326e5cf9debSVladimir Kondratyev if ((size % 32) != 0) /* Linux uses BITS_PER_LONG. Seems to be a bug */
327e5cf9debSVladimir Kondratyev dst[end - 1] &= (uint32_t)(UINT_MAX >> (32 - (size % 32)));
328e5cf9debSVladimir Kondratyev }
329e5cf9debSVladimir Kondratyev
330e5cf9debSVladimir Kondratyev static inline void
bitmap_from_arr32(unsigned long * dst,const uint32_t * src,unsigned int size)3315ae2e6f9SVladimir Kondratyev bitmap_from_arr32(unsigned long *dst, const uint32_t *src,
3325ae2e6f9SVladimir Kondratyev unsigned int size)
3335ae2e6f9SVladimir Kondratyev {
3345ae2e6f9SVladimir Kondratyev const unsigned int end = BIT_WORD(size);
3355ae2e6f9SVladimir Kondratyev const unsigned int tail = size & (BITS_PER_LONG - 1);
3365ae2e6f9SVladimir Kondratyev
3375ae2e6f9SVladimir Kondratyev #ifdef __LP64__
3385ae2e6f9SVladimir Kondratyev const unsigned int end32 = howmany(size, 32);
3395ae2e6f9SVladimir Kondratyev unsigned int i = 0;
3405ae2e6f9SVladimir Kondratyev
3415ae2e6f9SVladimir Kondratyev while (i < end32) {
3425ae2e6f9SVladimir Kondratyev dst[i++/2] = (unsigned long) *(src++);
3435ae2e6f9SVladimir Kondratyev if (i < end32)
3445ae2e6f9SVladimir Kondratyev dst[i++/2] |= ((unsigned long) *(src++)) << 32;
3455ae2e6f9SVladimir Kondratyev }
3465ae2e6f9SVladimir Kondratyev #else
347*dbca4424SVladimir Kondratyev bitmap_copy(dst, (const unsigned long *)src, size);
3485ae2e6f9SVladimir Kondratyev #endif
3495ae2e6f9SVladimir Kondratyev if ((size % BITS_PER_LONG) != 0)
3505ae2e6f9SVladimir Kondratyev dst[end] &= BITMAP_LAST_WORD_MASK(tail);
3515ae2e6f9SVladimir Kondratyev }
3525ae2e6f9SVladimir Kondratyev
3535ae2e6f9SVladimir Kondratyev static inline void
bitmap_or(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,const unsigned int size)354c9dd0b48SHans Petter Selasky bitmap_or(unsigned long *dst, const unsigned long *src1,
355c9dd0b48SHans Petter Selasky const unsigned long *src2, const unsigned int size)
356c9dd0b48SHans Petter Selasky {
357c9dd0b48SHans Petter Selasky const unsigned int end = BITS_TO_LONGS(size);
358c9dd0b48SHans Petter Selasky unsigned int i;
359c9dd0b48SHans Petter Selasky
360c9dd0b48SHans Petter Selasky for (i = 0; i != end; i++)
361c9dd0b48SHans Petter Selasky dst[i] = src1[i] | src2[i];
362c9dd0b48SHans Petter Selasky }
363c9dd0b48SHans Petter Selasky
364c9dd0b48SHans Petter Selasky static inline void
bitmap_and(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,const unsigned int size)365c9dd0b48SHans Petter Selasky bitmap_and(unsigned long *dst, const unsigned long *src1,
366c9dd0b48SHans Petter Selasky const unsigned long *src2, const unsigned int size)
367c9dd0b48SHans Petter Selasky {
368c9dd0b48SHans Petter Selasky const unsigned int end = BITS_TO_LONGS(size);
369c9dd0b48SHans Petter Selasky unsigned int i;
370c9dd0b48SHans Petter Selasky
371c9dd0b48SHans Petter Selasky for (i = 0; i != end; i++)
372c9dd0b48SHans Petter Selasky dst[i] = src1[i] & src2[i];
373c9dd0b48SHans Petter Selasky }
374c9dd0b48SHans Petter Selasky
375c9dd0b48SHans Petter Selasky static inline void
bitmap_andnot(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,const unsigned int size)37626a57869SEmmanuel Vadot bitmap_andnot(unsigned long *dst, const unsigned long *src1,
37726a57869SEmmanuel Vadot const unsigned long *src2, const unsigned int size)
37826a57869SEmmanuel Vadot {
37926a57869SEmmanuel Vadot const unsigned int end = BITS_TO_LONGS(size);
38026a57869SEmmanuel Vadot unsigned int i;
38126a57869SEmmanuel Vadot
38226a57869SEmmanuel Vadot for (i = 0; i != end; i++)
38326a57869SEmmanuel Vadot dst[i] = src1[i] & ~src2[i];
38426a57869SEmmanuel Vadot }
38526a57869SEmmanuel Vadot
38626a57869SEmmanuel Vadot static inline void
bitmap_xor(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,const unsigned int size)387c9dd0b48SHans Petter Selasky bitmap_xor(unsigned long *dst, const unsigned long *src1,
388c9dd0b48SHans Petter Selasky const unsigned long *src2, const unsigned int size)
389c9dd0b48SHans Petter Selasky {
390c9dd0b48SHans Petter Selasky const unsigned int end = BITS_TO_LONGS(size);
391c9dd0b48SHans Petter Selasky unsigned int i;
392c9dd0b48SHans Petter Selasky
393c9dd0b48SHans Petter Selasky for (i = 0; i != end; i++)
394c9dd0b48SHans Petter Selasky dst[i] = src1[i] ^ src2[i];
395c9dd0b48SHans Petter Selasky }
396c9dd0b48SHans Petter Selasky
3975ae2e6f9SVladimir Kondratyev static inline void
bitmap_shift_right(unsigned long * dst,const unsigned long * src,unsigned int shift,unsigned int size)3985ae2e6f9SVladimir Kondratyev bitmap_shift_right(unsigned long *dst, const unsigned long *src,
3995ae2e6f9SVladimir Kondratyev unsigned int shift, unsigned int size)
4005ae2e6f9SVladimir Kondratyev {
4015ae2e6f9SVladimir Kondratyev const unsigned int end = BITS_TO_LONGS(size);
4025ae2e6f9SVladimir Kondratyev const unsigned int tail = size & (BITS_PER_LONG - 1);
4035ae2e6f9SVladimir Kondratyev const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
4045ae2e6f9SVladimir Kondratyev const unsigned int off = BIT_WORD(shift);
4055ae2e6f9SVladimir Kondratyev const unsigned int rem = shift & (BITS_PER_LONG - 1);
4065ae2e6f9SVladimir Kondratyev unsigned long left, right;
4075ae2e6f9SVladimir Kondratyev unsigned int i, srcpos;
4085ae2e6f9SVladimir Kondratyev
4095ae2e6f9SVladimir Kondratyev for (i = 0, srcpos = off; srcpos < end; i++, srcpos++) {
4105ae2e6f9SVladimir Kondratyev right = src[srcpos];
4115ae2e6f9SVladimir Kondratyev left = 0;
4125ae2e6f9SVladimir Kondratyev
4135ae2e6f9SVladimir Kondratyev if (srcpos == end - 1)
4145ae2e6f9SVladimir Kondratyev right &= mask;
4155ae2e6f9SVladimir Kondratyev
4165ae2e6f9SVladimir Kondratyev if (rem != 0) {
4175ae2e6f9SVladimir Kondratyev right >>= rem;
4185ae2e6f9SVladimir Kondratyev if (srcpos + 1 < end) {
4195ae2e6f9SVladimir Kondratyev left = src[srcpos + 1];
4205ae2e6f9SVladimir Kondratyev if (srcpos + 1 == end - 1)
4215ae2e6f9SVladimir Kondratyev left &= mask;
4225ae2e6f9SVladimir Kondratyev left <<= (BITS_PER_LONG - rem);
4235ae2e6f9SVladimir Kondratyev }
4245ae2e6f9SVladimir Kondratyev }
4255ae2e6f9SVladimir Kondratyev dst[i] = left | right;
4265ae2e6f9SVladimir Kondratyev }
4275ae2e6f9SVladimir Kondratyev if (off != 0)
4285ae2e6f9SVladimir Kondratyev memset(dst + end - off, 0, off * sizeof(unsigned long));
4295ae2e6f9SVladimir Kondratyev }
4305ae2e6f9SVladimir Kondratyev
4313d84874dSEmmanuel Vadot static inline unsigned long *
bitmap_alloc(unsigned int size,gfp_t flags)4323d84874dSEmmanuel Vadot bitmap_alloc(unsigned int size, gfp_t flags)
4333d84874dSEmmanuel Vadot {
4343d84874dSEmmanuel Vadot return (kmalloc_array(BITS_TO_LONGS(size),
4353d84874dSEmmanuel Vadot sizeof(unsigned long), flags));
4363d84874dSEmmanuel Vadot }
4373d84874dSEmmanuel Vadot
4383d84874dSEmmanuel Vadot static inline unsigned long *
bitmap_zalloc(unsigned int size,gfp_t flags)4393d84874dSEmmanuel Vadot bitmap_zalloc(unsigned int size, gfp_t flags)
4403d84874dSEmmanuel Vadot {
4413d84874dSEmmanuel Vadot return (bitmap_alloc(size, flags | __GFP_ZERO));
4423d84874dSEmmanuel Vadot }
4433d84874dSEmmanuel Vadot
444ce03b301SEmmanuel Vadot static inline void
bitmap_free(const unsigned long * bitmap)445ce03b301SEmmanuel Vadot bitmap_free(const unsigned long *bitmap)
446ce03b301SEmmanuel Vadot {
447ce03b301SEmmanuel Vadot kfree(bitmap);
448ce03b301SEmmanuel Vadot }
449ce03b301SEmmanuel Vadot
450307f78f3SVladimir Kondratyev #endif /* _LINUXKPI_LINUX_BITMAP_H_ */
451