40b0b3f8fb2d8 (Thomas Gleixner 2019-06-03 07:44:46 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * lib/bitmap.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) * Helper functions for bitmap.h.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) */
c13656b904b61 (Bartosz Golaszewski 2021-03-15 10:13:55 +0100 6)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) #include <linux/bitmap.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) #include <linux/bitops.h>
50af5ead3b44c (Paul Gortmaker 2012-01-20 18:35:53 -0500 9) #include <linux/bug.h>
c13656b904b61 (Bartosz Golaszewski 2021-03-15 10:13:55 +0100 10) #include <linux/ctype.h>
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 11) #include <linux/device.h>
c13656b904b61 (Bartosz Golaszewski 2021-03-15 10:13:55 +0100 12) #include <linux/errno.h>
c13656b904b61 (Bartosz Golaszewski 2021-03-15 10:13:55 +0100 13) #include <linux/export.h>
e52bc7c28ac9f (David Decotigny 2016-02-19 09:23:59 -0500 14) #include <linux/kernel.h>
ce1091d471107 (Rasmus Villemoes 2018-10-30 15:05:14 -0700 15) #include <linux/mm.h>
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 16) #include <linux/slab.h>
e52bc7c28ac9f (David Decotigny 2016-02-19 09:23:59 -0500 17) #include <linux/string.h>
c13656b904b61 (Bartosz Golaszewski 2021-03-15 10:13:55 +0100 18) #include <linux/thread_info.h>
13d4ea097d18b (Andy Lutomirski 2016-07-14 13:22:57 -0700 19) #include <linux/uaccess.h>
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 20)
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 21) #include <asm/page.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 23) #include "kstrtox.h"
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 24)
7d7363e403ce9 (Randy Dunlap 2017-10-16 16:32:51 -0700 25) /**
7d7363e403ce9 (Randy Dunlap 2017-10-16 16:32:51 -0700 26) * DOC: bitmap introduction
7d7363e403ce9 (Randy Dunlap 2017-10-16 16:32:51 -0700 27) *
197d6c1dde4e1 (Randy Dunlap 2020-10-15 20:10:45 -0700 28) * bitmaps provide an array of bits, implemented using an
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) * array of unsigned longs. The number of valid bits in a
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30) * given bitmap does _not_ need to be an exact multiple of
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) * BITS_PER_LONG.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) * The possible unused bits in the last, partially used word
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) * of a bitmap are 'don't care'. The implementation makes
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) * no particular effort to keep them zero. It ensures that
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) * their value will not affect the results of any operation.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37) * The bitmap operations that return Boolean (bitmap_empty,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 38) * for example) or scalar (bitmap_weight, for example) results
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39) * carefully filter out these unused bits from impacting their
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40) * results.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42) * The byte ordering of bitmaps is more natural on little
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 43) * endian architectures. See the big-endian headers
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 44) * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) * for the best explanations of this ordering.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) int __bitmap_equal(const unsigned long *bitmap1,
5e068069319a9 (Rasmus Villemoes 2014-08-06 16:09:53 -0700 49) const unsigned long *bitmap2, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50) {
5e068069319a9 (Rasmus Villemoes 2014-08-06 16:09:53 -0700 51) unsigned int k, lim = bits/BITS_PER_LONG;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52) for (k = 0; k < lim; ++k)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 53) if (bitmap1[k] != bitmap2[k])
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 55)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56) if (bits % BITS_PER_LONG)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 57) if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 58) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 59)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) EXPORT_SYMBOL(__bitmap_equal);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 63)
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 64) bool __bitmap_or_equal(const unsigned long *bitmap1,
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 65) const unsigned long *bitmap2,
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 66) const unsigned long *bitmap3,
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 67) unsigned int bits)
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 68) {
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 69) unsigned int k, lim = bits / BITS_PER_LONG;
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 70) unsigned long tmp;
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 71)
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 72) for (k = 0; k < lim; ++k) {
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 73) if ((bitmap1[k] | bitmap2[k]) != bitmap3[k])
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 74) return false;
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 75) }
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 76)
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 77) if (!(bits % BITS_PER_LONG))
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 78) return true;
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 79)
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 80) tmp = (bitmap1[k] | bitmap2[k]) ^ bitmap3[k];
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 81) return (tmp & BITMAP_LAST_WORD_MASK(bits)) == 0;
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 82) }
b9fa6442f7043 (Thomas Gleixner 2019-07-22 20:47:24 +0200 83)
3d6684f4e6a46 (Rasmus Villemoes 2014-08-06 16:09:55 -0700 84) void __bitmap_complement(unsigned long *dst, const unsigned long *src, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 85) {
ca1250bbd4e0b (Yury Norov 2018-06-07 17:10:41 -0700 86) unsigned int k, lim = BITS_TO_LONGS(bits);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 87) for (k = 0; k < lim; ++k)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 88) dst[k] = ~src[k];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 89) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 90) EXPORT_SYMBOL(__bitmap_complement);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 91)
72fd4a35a8243 (Robert P. J. Day 2007-02-10 01:45:59 -0800 92) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 93) * __bitmap_shift_right - logical right shift of the bits in a bitmap
05fb6bf0b2955 (Randy Dunlap 2007-02-28 20:12:13 -0800 94) * @dst : destination bitmap
05fb6bf0b2955 (Randy Dunlap 2007-02-28 20:12:13 -0800 95) * @src : source bitmap
05fb6bf0b2955 (Randy Dunlap 2007-02-28 20:12:13 -0800 96) * @shift : shift by this many bits
2fbad29917c98 (Rasmus Villemoes 2015-02-13 14:36:02 -0800 97) * @nbits : bitmap size, in bits
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 98) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 99) * Shifting right (dividing) means moving bits in the MS -> LS bit
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 100) * direction. Zeros are fed into the vacated MS positions and the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 101) * LS bits shifted off the bottom are lost.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 102) */
2fbad29917c98 (Rasmus Villemoes 2015-02-13 14:36:02 -0800 103) void __bitmap_shift_right(unsigned long *dst, const unsigned long *src,
2fbad29917c98 (Rasmus Villemoes 2015-02-13 14:36:02 -0800 104) unsigned shift, unsigned nbits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 105) {
cfac1d080a005 (Rasmus Villemoes 2015-02-13 14:36:10 -0800 106) unsigned k, lim = BITS_TO_LONGS(nbits);
2fbad29917c98 (Rasmus Villemoes 2015-02-13 14:36:02 -0800 107) unsigned off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
cfac1d080a005 (Rasmus Villemoes 2015-02-13 14:36:10 -0800 108) unsigned long mask = BITMAP_LAST_WORD_MASK(nbits);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 109) for (k = 0; off + k < lim; ++k) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 110) unsigned long upper, lower;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 111)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 112) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 113) * If shift is not word aligned, take lower rem bits of
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 114) * word above and make them the top rem bits of result.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 115) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 116) if (!rem || off + k + 1 >= lim)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 117) upper = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 118) else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 119) upper = src[off + k + 1];
cfac1d080a005 (Rasmus Villemoes 2015-02-13 14:36:10 -0800 120) if (off + k + 1 == lim - 1)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 121) upper &= mask;
9d8a6b2a02c5f (Rasmus Villemoes 2015-02-13 14:36:05 -0800 122) upper <<= (BITS_PER_LONG - rem);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 123) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 124) lower = src[off + k];
cfac1d080a005 (Rasmus Villemoes 2015-02-13 14:36:10 -0800 125) if (off + k == lim - 1)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 126) lower &= mask;
9d8a6b2a02c5f (Rasmus Villemoes 2015-02-13 14:36:05 -0800 127) lower >>= rem;
9d8a6b2a02c5f (Rasmus Villemoes 2015-02-13 14:36:05 -0800 128) dst[k] = lower | upper;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 129) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 130) if (off)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 131) memset(&dst[lim - off], 0, off*sizeof(unsigned long));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 132) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 133) EXPORT_SYMBOL(__bitmap_shift_right);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 134)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 135)
72fd4a35a8243 (Robert P. J. Day 2007-02-10 01:45:59 -0800 136) /**
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 137) * __bitmap_shift_left - logical left shift of the bits in a bitmap
05fb6bf0b2955 (Randy Dunlap 2007-02-28 20:12:13 -0800 138) * @dst : destination bitmap
05fb6bf0b2955 (Randy Dunlap 2007-02-28 20:12:13 -0800 139) * @src : source bitmap
05fb6bf0b2955 (Randy Dunlap 2007-02-28 20:12:13 -0800 140) * @shift : shift by this many bits
dba94c2553da1 (Rasmus Villemoes 2015-02-13 14:36:13 -0800 141) * @nbits : bitmap size, in bits
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 142) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 143) * Shifting left (multiplying) means moving bits in the LS -> MS
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 144) * direction. Zeros are fed into the vacated LS bit positions
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 145) * and those MS bits shifted off the top are lost.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 146) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 147)
dba94c2553da1 (Rasmus Villemoes 2015-02-13 14:36:13 -0800 148) void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
dba94c2553da1 (Rasmus Villemoes 2015-02-13 14:36:13 -0800 149) unsigned int shift, unsigned int nbits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 150) {
dba94c2553da1 (Rasmus Villemoes 2015-02-13 14:36:13 -0800 151) int k;
7f590657937f1 (Rasmus Villemoes 2015-02-13 14:36:19 -0800 152) unsigned int lim = BITS_TO_LONGS(nbits);
dba94c2553da1 (Rasmus Villemoes 2015-02-13 14:36:13 -0800 153) unsigned int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 154) for (k = lim - off - 1; k >= 0; --k) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 155) unsigned long upper, lower;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 156)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 158) * If shift is not word aligned, take upper rem bits of
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 159) * word below and make them the bottom rem bits of result.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 161) if (rem && k > 0)
6d874eca65956 (Rasmus Villemoes 2015-02-13 14:36:16 -0800 162) lower = src[k - 1] >> (BITS_PER_LONG - rem);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 163) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 164) lower = 0;
7f590657937f1 (Rasmus Villemoes 2015-02-13 14:36:19 -0800 165) upper = src[k] << rem;
6d874eca65956 (Rasmus Villemoes 2015-02-13 14:36:16 -0800 166) dst[k + off] = lower | upper;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168) if (off)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 169) memset(dst, 0, off*sizeof(unsigned long));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 170) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 171) EXPORT_SYMBOL(__bitmap_shift_left);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 172)
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 173) /**
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 174) * bitmap_cut() - remove bit region from bitmap and right shift remaining bits
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 175) * @dst: destination bitmap, might overlap with src
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 176) * @src: source bitmap
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 177) * @first: start bit of region to be removed
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 178) * @cut: number of bits to remove
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 179) * @nbits: bitmap size, in bits
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 180) *
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 181) * Set the n-th bit of @dst iff the n-th bit of @src is set and
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 182) * n is less than @first, or the m-th bit of @src is set for any
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 183) * m such that @first <= n < nbits, and m = n + @cut.
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 184) *
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 185) * In pictures, example for a big-endian 32-bit architecture:
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 186) *
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 187) * The @src bitmap is::
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 188) *
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 189) * 31 63
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 190) * | |
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 191) * 10000000 11000001 11110010 00010101 10000000 11000001 01110010 00010101
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 192) * | | | |
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 193) * 16 14 0 32
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 194) *
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 195) * if @cut is 3, and @first is 14, bits 14-16 in @src are cut and @dst is::
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 196) *
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 197) * 31 63
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 198) * | |
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 199) * 10110000 00011000 00110010 00010101 00010000 00011000 00101110 01000010
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 200) * | | |
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 201) * 14 (bit 17 0 32
4642289b5f660 (Mauro Carvalho Chehab 2020-04-14 18:48:59 +0200 202) * from @src)
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 203) *
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 204) * Note that @dst and @src might overlap partially or entirely.
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 205) *
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 206) * This is implemented in the obvious way, with a shift and carry
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 207) * step for each moved bit. Optimisation is left as an exercise
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 208) * for the compiler.
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 209) */
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 210) void bitmap_cut(unsigned long *dst, const unsigned long *src,
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 211) unsigned int first, unsigned int cut, unsigned int nbits)
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 212) {
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 213) unsigned int len = BITS_TO_LONGS(nbits);
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 214) unsigned long keep = 0, carry;
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 215) int i;
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 216)
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 217) if (first % BITS_PER_LONG) {
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 218) keep = src[first / BITS_PER_LONG] &
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 219) (~0UL >> (BITS_PER_LONG - first % BITS_PER_LONG));
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 220) }
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 221)
5959f829a93c1 (Stefano Brivio 2020-08-11 18:34:29 -0700 222) memmove(dst, src, len * sizeof(*dst));
5959f829a93c1 (Stefano Brivio 2020-08-11 18:34:29 -0700 223)
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 224) while (cut--) {
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 225) for (i = first / BITS_PER_LONG; i < len; i++) {
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 226) if (i < len - 1)
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 227) carry = dst[i + 1] & 1UL;
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 228) else
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 229) carry = 0;
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 230)
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 231) dst[i] = (dst[i] >> 1) | (carry << (BITS_PER_LONG - 1));
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 232) }
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 233) }
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 234)
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 235) dst[first / BITS_PER_LONG] &= ~0UL << (first % BITS_PER_LONG);
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 236) dst[first / BITS_PER_LONG] |= keep;
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 237) }
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 238) EXPORT_SYMBOL(bitmap_cut);
2092767168f06 (Stefano Brivio 2020-01-22 00:17:54 +0100 239)
f4b0373b26567 (Linus Torvalds 2009-08-21 09:26:15 -0700 240) int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 241) const unsigned long *bitmap2, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) {
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 243) unsigned int k;
7e5f97d1927f4 (Rasmus Villemoes 2014-08-06 16:10:22 -0700 244) unsigned int lim = bits/BITS_PER_LONG;
f4b0373b26567 (Linus Torvalds 2009-08-21 09:26:15 -0700 245) unsigned long result = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 246)
7e5f97d1927f4 (Rasmus Villemoes 2014-08-06 16:10:22 -0700 247) for (k = 0; k < lim; k++)
f4b0373b26567 (Linus Torvalds 2009-08-21 09:26:15 -0700 248) result |= (dst[k] = bitmap1[k] & bitmap2[k]);
7e5f97d1927f4 (Rasmus Villemoes 2014-08-06 16:10:22 -0700 249) if (bits % BITS_PER_LONG)
7e5f97d1927f4 (Rasmus Villemoes 2014-08-06 16:10:22 -0700 250) result |= (dst[k] = bitmap1[k] & bitmap2[k] &
7e5f97d1927f4 (Rasmus Villemoes 2014-08-06 16:10:22 -0700 251) BITMAP_LAST_WORD_MASK(bits));
f4b0373b26567 (Linus Torvalds 2009-08-21 09:26:15 -0700 252) return result != 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 253) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 254) EXPORT_SYMBOL(__bitmap_and);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 255)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 256) void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 257) const unsigned long *bitmap2, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 258) {
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 259) unsigned int k;
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 260) unsigned int nr = BITS_TO_LONGS(bits);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 261)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 262) for (k = 0; k < nr; k++)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 263) dst[k] = bitmap1[k] | bitmap2[k];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 264) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 265) EXPORT_SYMBOL(__bitmap_or);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 266)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 267) void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 268) const unsigned long *bitmap2, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 269) {
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 270) unsigned int k;
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 271) unsigned int nr = BITS_TO_LONGS(bits);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 272)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 273) for (k = 0; k < nr; k++)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 274) dst[k] = bitmap1[k] ^ bitmap2[k];
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 275) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) EXPORT_SYMBOL(__bitmap_xor);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277)
f4b0373b26567 (Linus Torvalds 2009-08-21 09:26:15 -0700 278) int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 279) const unsigned long *bitmap2, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 280) {
2f9305eb31097 (Rasmus Villemoes 2014-08-06 16:09:59 -0700 281) unsigned int k;
74e765319084b (Rasmus Villemoes 2014-08-06 16:10:24 -0700 282) unsigned int lim = bits/BITS_PER_LONG;
f4b0373b26567 (Linus Torvalds 2009-08-21 09:26:15 -0700 283) unsigned long result = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 284)
74e765319084b (Rasmus Villemoes 2014-08-06 16:10:24 -0700 285) for (k = 0; k < lim; k++)
f4b0373b26567 (Linus Torvalds 2009-08-21 09:26:15 -0700 286) result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
74e765319084b (Rasmus Villemoes 2014-08-06 16:10:24 -0700 287) if (bits % BITS_PER_LONG)
74e765319084b (Rasmus Villemoes 2014-08-06 16:10:24 -0700 288) result |= (dst[k] = bitmap1[k] & ~bitmap2[k] &
74e765319084b (Rasmus Villemoes 2014-08-06 16:10:24 -0700 289) BITMAP_LAST_WORD_MASK(bits));
f4b0373b26567 (Linus Torvalds 2009-08-21 09:26:15 -0700 290) return result != 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 291) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 292) EXPORT_SYMBOL(__bitmap_andnot);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293)
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 294) void __bitmap_replace(unsigned long *dst,
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 295) const unsigned long *old, const unsigned long *new,
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 296) const unsigned long *mask, unsigned int nbits)
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 297) {
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 298) unsigned int k;
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 299) unsigned int nr = BITS_TO_LONGS(nbits);
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 300)
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 301) for (k = 0; k < nr; k++)
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 302) dst[k] = (old[k] & ~mask[k]) | (new[k] & mask[k]);
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 303) }
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 304) EXPORT_SYMBOL(__bitmap_replace);
30544ed5de431 (Andy Shevchenko 2019-12-04 16:53:26 -0800 305)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 306) int __bitmap_intersects(const unsigned long *bitmap1,
6dfe9799c2a03 (Rasmus Villemoes 2014-08-06 16:10:01 -0700 307) const unsigned long *bitmap2, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308) {
6dfe9799c2a03 (Rasmus Villemoes 2014-08-06 16:10:01 -0700 309) unsigned int k, lim = bits/BITS_PER_LONG;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 310) for (k = 0; k < lim; ++k)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 311) if (bitmap1[k] & bitmap2[k])
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 312) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 313)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 314) if (bits % BITS_PER_LONG)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 315) if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 316) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 317) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 318) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 319) EXPORT_SYMBOL(__bitmap_intersects);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 320)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 321) int __bitmap_subset(const unsigned long *bitmap1,
5be20213e8555 (Rasmus Villemoes 2014-08-06 16:10:03 -0700 322) const unsigned long *bitmap2, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 323) {
5be20213e8555 (Rasmus Villemoes 2014-08-06 16:10:03 -0700 324) unsigned int k, lim = bits/BITS_PER_LONG;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 325) for (k = 0; k < lim; ++k)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 326) if (bitmap1[k] & ~bitmap2[k])
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 327) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 328)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 329) if (bits % BITS_PER_LONG)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 330) if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 331) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 332) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 333) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 334) EXPORT_SYMBOL(__bitmap_subset);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 335)
877d9f3b63ac2 (Rasmus Villemoes 2014-08-06 16:10:05 -0700 336) int __bitmap_weight(const unsigned long *bitmap, unsigned int bits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 337) {
877d9f3b63ac2 (Rasmus Villemoes 2014-08-06 16:10:05 -0700 338) unsigned int k, lim = bits/BITS_PER_LONG;
877d9f3b63ac2 (Rasmus Villemoes 2014-08-06 16:10:05 -0700 339) int w = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 340)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 341) for (k = 0; k < lim; k++)
37d54111c133b (Akinobu Mita 2006-03-26 01:39:56 -0800 342) w += hweight_long(bitmap[k]);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 343)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 344) if (bits % BITS_PER_LONG)
37d54111c133b (Akinobu Mita 2006-03-26 01:39:56 -0800 345) w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 346)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 347) return w;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 348) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 349) EXPORT_SYMBOL(__bitmap_weight);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 350)
e5af323c9badd (Matthew Wilcox 2017-07-10 15:51:29 -0700 351) void __bitmap_set(unsigned long *map, unsigned int start, int len)
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 352) {
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 353) unsigned long *p = map + BIT_WORD(start);
fb5ac54263ef3 (Rasmus Villemoes 2014-08-06 16:10:07 -0700 354) const unsigned int size = start + len;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 355) int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 356) unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 357)
fb5ac54263ef3 (Rasmus Villemoes 2014-08-06 16:10:07 -0700 358) while (len - bits_to_set >= 0) {
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 359) *p |= mask_to_set;
fb5ac54263ef3 (Rasmus Villemoes 2014-08-06 16:10:07 -0700 360) len -= bits_to_set;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 361) bits_to_set = BITS_PER_LONG;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 362) mask_to_set = ~0UL;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 363) p++;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 364) }
fb5ac54263ef3 (Rasmus Villemoes 2014-08-06 16:10:07 -0700 365) if (len) {
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 366) mask_to_set &= BITMAP_LAST_WORD_MASK(size);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 367) *p |= mask_to_set;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 368) }
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 369) }
e5af323c9badd (Matthew Wilcox 2017-07-10 15:51:29 -0700 370) EXPORT_SYMBOL(__bitmap_set);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 371)
e5af323c9badd (Matthew Wilcox 2017-07-10 15:51:29 -0700 372) void __bitmap_clear(unsigned long *map, unsigned int start, int len)
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 373) {
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 374) unsigned long *p = map + BIT_WORD(start);
154f5e38f30f2 (Rasmus Villemoes 2014-08-06 16:10:10 -0700 375) const unsigned int size = start + len;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 376) int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 377) unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 378)
154f5e38f30f2 (Rasmus Villemoes 2014-08-06 16:10:10 -0700 379) while (len - bits_to_clear >= 0) {
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 380) *p &= ~mask_to_clear;
154f5e38f30f2 (Rasmus Villemoes 2014-08-06 16:10:10 -0700 381) len -= bits_to_clear;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 382) bits_to_clear = BITS_PER_LONG;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 383) mask_to_clear = ~0UL;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 384) p++;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 385) }
154f5e38f30f2 (Rasmus Villemoes 2014-08-06 16:10:10 -0700 386) if (len) {
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 387) mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 388) *p &= ~mask_to_clear;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 389) }
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 390) }
e5af323c9badd (Matthew Wilcox 2017-07-10 15:51:29 -0700 391) EXPORT_SYMBOL(__bitmap_clear);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 392)
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 393) /**
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 394) * bitmap_find_next_zero_area_off - find a contiguous aligned zero area
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 395) * @map: The address to base the search on
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 396) * @size: The bitmap size in bits
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 397) * @start: The bitnumber to start searching at
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 398) * @nr: The number of zeroed bits we're looking for
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 399) * @align_mask: Alignment mask for zero area
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 400) * @align_offset: Alignment offset for zero area.
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 401) *
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 402) * The @align_mask should be one less than a power of 2; the effect is that
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 403) * the bit offset of all zero areas this function finds plus @align_offset
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 404) * is multiple of that power of 2.
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 405) */
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 406) unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 407) unsigned long size,
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 408) unsigned long start,
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 409) unsigned int nr,
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 410) unsigned long align_mask,
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 411) unsigned long align_offset)
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 412) {
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 413) unsigned long index, end, i;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 414) again:
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 415) index = find_next_zero_bit(map, size, start);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 416)
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 417) /* Align allocation */
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 418) index = __ALIGN_MASK(index + align_offset, align_mask) - align_offset;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 419)
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 420) end = index + nr;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 421) if (end > size)
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 422) return end;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 423) i = find_next_bit(map, end, index);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 424) if (i < end) {
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 425) start = i + 1;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 426) goto again;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 427) }
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 428) return index;
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 429) }
5e19b013f55a8 (Michal Nazarewicz 2014-12-12 16:54:45 -0800 430) EXPORT_SYMBOL(bitmap_find_next_zero_area_off);
c1a2a962a2ad1 (Akinobu Mita 2009-12-15 16:48:25 -0800 431)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 432) /*
6d49e352ae9ae (Nadia Yvette Chambers 2012-12-06 10:39:54 +0100 433) * Bitmap printing & parsing functions: first version by Nadia Yvette Chambers,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 434) * second version by Paul Jackson, third by Joe Korty.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 435) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 436)
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 437) /**
9a86e2bad0b9f (Ben Hutchings 2010-03-05 13:43:17 -0800 438) * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 439) *
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 440) * @ubuf: pointer to user buffer containing string.
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 441) * @ulen: buffer size in bytes. If string is smaller than this
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 442) * then it must be terminated with a \0.
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 443) * @maskp: pointer to bitmap array that will contain result.
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 444) * @nmaskbits: size of bitmap, in bits.
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 445) */
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 446) int bitmap_parse_user(const char __user *ubuf,
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 447) unsigned int ulen, unsigned long *maskp,
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 448) int nmaskbits)
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 449) {
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 450) char *buf;
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 451) int ret;
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 452)
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 453) buf = memdup_user_nul(ubuf, ulen);
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 454) if (IS_ERR(buf))
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 455) return PTR_ERR(buf);
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 456)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 457) ret = bitmap_parse(buf, UINT_MAX, maskp, nmaskbits);
b9c321fd87b61 (H Hartley Sweeten 2011-10-31 17:12:32 -0700 458)
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 459) kfree(buf);
e66eda0615c87 (Yury Norov 2020-02-03 17:37:31 -0800 460) return ret;
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 461) }
01a3ee2b203e5 (Reinette Chatre 2006-10-11 01:21:55 -0700 462) EXPORT_SYMBOL(bitmap_parse_user);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 463)
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 464) /**
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 465) * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 466) * @list: indicates whether the bitmap must be list
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 467) * @buf: page aligned buffer into which string is placed
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 468) * @maskp: pointer to bitmap to convert
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 469) * @nmaskbits: size of bitmap, in bits
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 470) *
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 471) * Output format is a comma-separated list of decimal numbers and
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 472) * ranges if list is specified or hex digits grouped into comma-separated
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 473) * sets of 8 digits/set. Returns the number of characters written to buf.
9cf79d115f0d1 (Sudeep Holla 2015-06-25 15:02:17 -0700 474) *
ce1091d471107 (Rasmus Villemoes 2018-10-30 15:05:14 -0700 475) * It is assumed that @buf is a pointer into a PAGE_SIZE, page-aligned
ce1091d471107 (Rasmus Villemoes 2018-10-30 15:05:14 -0700 476) * area and that sufficient storage remains at @buf to accommodate the
ce1091d471107 (Rasmus Villemoes 2018-10-30 15:05:14 -0700 477) * bitmap_print_to_pagebuf() output. Returns the number of characters
ce1091d471107 (Rasmus Villemoes 2018-10-30 15:05:14 -0700 478) * actually printed to @buf, excluding terminating '\0'.
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 479) */
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 480) int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp,
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 481) int nmaskbits)
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 482) {
ce1091d471107 (Rasmus Villemoes 2018-10-30 15:05:14 -0700 483) ptrdiff_t len = PAGE_SIZE - offset_in_page(buf);
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 484)
8ec3d76863d8b (Rasmus Villemoes 2018-10-30 15:05:18 -0700 485) return list ? scnprintf(buf, len, "%*pbl\n", nmaskbits, maskp) :
8ec3d76863d8b (Rasmus Villemoes 2018-10-30 15:05:18 -0700 486) scnprintf(buf, len, "%*pb\n", nmaskbits, maskp);
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 487) }
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 488) EXPORT_SYMBOL(bitmap_print_to_pagebuf);
5aaba36318e59 (Sudeep Holla 2014-09-30 14:48:22 +0100 489)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 490) /*
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 491) * Region 9-38:4/10 describes the following bitmap structure:
9d7a3366b7028 (Paul Gortmaker 2021-02-21 03:08:23 -0500 492) * 0 9 12 18 38 N
9d7a3366b7028 (Paul Gortmaker 2021-02-21 03:08:23 -0500 493) * .........****......****......****..................
9d7a3366b7028 (Paul Gortmaker 2021-02-21 03:08:23 -0500 494) * ^ ^ ^ ^ ^
9d7a3366b7028 (Paul Gortmaker 2021-02-21 03:08:23 -0500 495) * start off group_len end nbits
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 496) */
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 497) struct region {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 498) unsigned int start;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 499) unsigned int off;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 500) unsigned int group_len;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 501) unsigned int end;
9d7a3366b7028 (Paul Gortmaker 2021-02-21 03:08:23 -0500 502) unsigned int nbits;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 503) };
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 504)
f3c869caef648 (Paul Gortmaker 2021-02-21 03:08:24 -0500 505) static void bitmap_set_region(const struct region *r, unsigned long *bitmap)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 506) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 507) unsigned int start;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 508)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 509) for (start = r->start; start <= r->end; start += r->group_len)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 510) bitmap_set(bitmap, start, min(r->end - start + 1, r->off));
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 511) }
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 512)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 513) static int bitmap_check_region(const struct region *r)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 514) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 515) if (r->start > r->end || r->group_len == 0 || r->off > r->group_len)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 516) return -EINVAL;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 517)
f3c869caef648 (Paul Gortmaker 2021-02-21 03:08:24 -0500 518) if (r->end >= r->nbits)
f3c869caef648 (Paul Gortmaker 2021-02-21 03:08:24 -0500 519) return -ERANGE;
f3c869caef648 (Paul Gortmaker 2021-02-21 03:08:24 -0500 520)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 521) return 0;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 522) }
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 523)
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 524) static const char *bitmap_getnum(const char *str, unsigned int *num,
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 525) unsigned int lastbit)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 526) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 527) unsigned long long n;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 528) unsigned int len;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 529)
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 530) if (str[0] == 'N') {
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 531) *num = lastbit;
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 532) return str + 1;
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 533) }
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 534)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 535) len = _parse_integer(str, 10, &n);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 536) if (!len)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 537) return ERR_PTR(-EINVAL);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 538) if (len & KSTRTOX_OVERFLOW || n != (unsigned int)n)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 539) return ERR_PTR(-EOVERFLOW);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 540)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 541) *num = n;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 542) return str + len;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 543) }
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 544)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 545) static inline bool end_of_str(char c)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 546) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 547) return c == '\0' || c == '\n';
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 548) }
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 549)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 550) static inline bool __end_of_region(char c)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 551) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 552) return isspace(c) || c == ',';
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 553) }
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 554)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 555) static inline bool end_of_region(char c)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 556) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 557) return __end_of_region(c) || end_of_str(c);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 558) }
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 559)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 560) /*
20607434113b8 (Randy Dunlap 2020-03-30 17:22:11 -0700 561) * The format allows commas and whitespaces at the beginning
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 562) * of the region.
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 563) */
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 564) static const char *bitmap_find_region(const char *str)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 565) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 566) while (__end_of_region(*str))
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 567) str++;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 568)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 569) return end_of_str(*str) ? NULL : str;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 570) }
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 571)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 572) static const char *bitmap_find_region_reverse(const char *start, const char *end)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 573) {
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 574) while (start <= end && __end_of_region(*end))
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 575) end--;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 576)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 577) return end;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 578) }
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 579)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 580) static const char *bitmap_parse_region(const char *str, struct region *r)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 581) {
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 582) unsigned int lastbit = r->nbits - 1;
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 583)
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 584) str = bitmap_getnum(str, &r->start, lastbit);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 585) if (IS_ERR(str))
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 586) return str;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 587)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 588) if (end_of_region(*str))
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 589) goto no_end;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 590)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 591) if (*str != '-')
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 592) return ERR_PTR(-EINVAL);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 593)
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 594) str = bitmap_getnum(str + 1, &r->end, lastbit);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 595) if (IS_ERR(str))
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 596) return str;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 597)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 598) if (end_of_region(*str))
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 599) goto no_pattern;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 600)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 601) if (*str != ':')
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 602) return ERR_PTR(-EINVAL);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 603)
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 604) str = bitmap_getnum(str + 1, &r->off, lastbit);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 605) if (IS_ERR(str))
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 606) return str;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 607)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 608) if (*str != '/')
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 609) return ERR_PTR(-EINVAL);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 610)
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 611) return bitmap_getnum(str + 1, &r->group_len, lastbit);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 612)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 613) no_end:
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 614) r->end = r->start;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 615) no_pattern:
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 616) r->off = r->end + 1;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 617) r->group_len = r->end + 1;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 618)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 619) return end_of_str(*str) ? NULL : str;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 620) }
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 621)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 622) /**
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 623) * bitmap_parselist - convert list format ASCII string to bitmap
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 624) * @buf: read user string from this buffer; must be terminated
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 625) * with a \0 or \n.
6e1907ffdc694 (Randy Dunlap 2006-06-25 05:48:57 -0700 626) * @maskp: write resulting mask here
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 627) * @nmaskbits: number of bits in mask to be written
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 628) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 629) * Input format is a comma-separated list of decimal numbers and
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 630) * ranges. Consecutively set bits are shown as two hyphen-separated
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 631) * decimal numbers, the smallest and largest bit numbers set in
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 632) * the range.
2d13e6ca429c0 (Noam Camus 2016-10-11 13:51:35 -0700 633) * Optionally each range can be postfixed to denote that only parts of it
2d13e6ca429c0 (Noam Camus 2016-10-11 13:51:35 -0700 634) * should be set. The range will divided to groups of specific size.
2d13e6ca429c0 (Noam Camus 2016-10-11 13:51:35 -0700 635) * From each group will be used only defined amount of bits.
2d13e6ca429c0 (Noam Camus 2016-10-11 13:51:35 -0700 636) * Syntax: range:used_size/group_size
2d13e6ca429c0 (Noam Camus 2016-10-11 13:51:35 -0700 637) * Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 638) * The value 'N' can be used as a dynamically substituted token for the
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 639) * maximum allowed value; i.e (nmaskbits - 1). Keep in mind that it is
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 640) * dynamic, so if system changes cause the bitmap width to change, such
2c4885d24e649 (Paul Gortmaker 2021-02-21 03:08:25 -0500 641) * as more cores in a CPU list, then any ranges using N will also change.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 642) *
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 643) * Returns: 0 on success, -errno on invalid input strings. Error values:
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 644) *
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 645) * - ``-EINVAL``: wrong region format
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 646) * - ``-EINVAL``: invalid character in string
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 647) * - ``-ERANGE``: bit number specified too large for mask
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 648) * - ``-EOVERFLOW``: integer overflow in the input parameters
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 649) */
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 650) int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 651) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 652) struct region r;
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 653) long ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 654)
9d7a3366b7028 (Paul Gortmaker 2021-02-21 03:08:23 -0500 655) r.nbits = nmaskbits;
9d7a3366b7028 (Paul Gortmaker 2021-02-21 03:08:23 -0500 656) bitmap_zero(maskp, r.nbits);
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 657)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 658) while (buf) {
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 659) buf = bitmap_find_region(buf);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 660) if (buf == NULL)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 661) return 0;
2d13e6ca429c0 (Noam Camus 2016-10-11 13:51:35 -0700 662)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 663) buf = bitmap_parse_region(buf, &r);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 664) if (IS_ERR(buf))
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 665) return PTR_ERR(buf);
2d13e6ca429c0 (Noam Camus 2016-10-11 13:51:35 -0700 666)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 667) ret = bitmap_check_region(&r);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 668) if (ret)
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 669) return ret;
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 670)
f3c869caef648 (Paul Gortmaker 2021-02-21 03:08:24 -0500 671) bitmap_set_region(&r, maskp);
e371c481d89cd (Yury Norov 2019-05-14 15:43:14 -0700 672) }
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 673)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 674) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 675) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 676) EXPORT_SYMBOL(bitmap_parselist);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 677)
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 678)
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 679) /**
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 680) * bitmap_parselist_user()
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 681) *
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 682) * @ubuf: pointer to user buffer containing string.
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 683) * @ulen: buffer size in bytes. If string is smaller than this
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 684) * then it must be terminated with a \0.
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 685) * @maskp: pointer to bitmap array that will contain result.
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 686) * @nmaskbits: size of bitmap, in bits.
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 687) *
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 688) * Wrapper for bitmap_parselist(), providing it with user buffer.
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 689) */
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 690) int bitmap_parselist_user(const char __user *ubuf,
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 691) unsigned int ulen, unsigned long *maskp,
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 692) int nmaskbits)
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 693) {
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 694) char *buf;
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 695) int ret;
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 696)
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 697) buf = memdup_user_nul(ubuf, ulen);
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 698) if (IS_ERR(buf))
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 699) return PTR_ERR(buf);
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 700)
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 701) ret = bitmap_parselist(buf, maskp, nmaskbits);
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 702)
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 703) kfree(buf);
281327c99bcaa (Yury Norov 2019-05-14 15:43:11 -0700 704) return ret;
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 705) }
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 706) EXPORT_SYMBOL(bitmap_parselist_user);
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 707)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 708) static const char *bitmap_get_x32_reverse(const char *start,
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 709) const char *end, u32 *num)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 710) {
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 711) u32 ret = 0;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 712) int c, i;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 713)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 714) for (i = 0; i < 32; i += 4) {
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 715) c = hex_to_bin(*end--);
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 716) if (c < 0)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 717) return ERR_PTR(-EINVAL);
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 718)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 719) ret |= c << i;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 720)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 721) if (start > end || __end_of_region(*end))
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 722) goto out;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 723) }
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 724)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 725) if (hex_to_bin(*end--) >= 0)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 726) return ERR_PTR(-EOVERFLOW);
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 727) out:
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 728) *num = ret;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 729) return end;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 730) }
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 731)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 732) /**
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 733) * bitmap_parse - convert an ASCII hex string into a bitmap.
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 734) * @start: pointer to buffer containing string.
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 735) * @buflen: buffer size in bytes. If string is smaller than this
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 736) * then it must be terminated with a \0 or \n. In that case,
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 737) * UINT_MAX may be provided instead of string length.
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 738) * @maskp: pointer to bitmap array that will contain result.
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 739) * @nmaskbits: size of bitmap, in bits.
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 740) *
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 741) * Commas group hex digits into chunks. Each chunk defines exactly 32
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 742) * bits of the resultant bitmask. No chunk may specify a value larger
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 743) * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 744) * then leading 0-bits are prepended. %-EINVAL is returned for illegal
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 745) * characters. Grouping such as "1,,5", ",44", "," or "" is allowed.
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 746) * Leading, embedded and trailing whitespace accepted.
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 747) */
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 748) int bitmap_parse(const char *start, unsigned int buflen,
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 749) unsigned long *maskp, int nmaskbits)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 750) {
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 751) const char *end = strnchrnul(start, buflen, '\n') - 1;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 752) int chunks = BITS_TO_U32(nmaskbits);
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 753) u32 *bitmap = (u32 *)maskp;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 754) int unset_bit;
81c4f4d924d5d (Alexander Gordeev 2020-06-10 18:41:41 -0700 755) int chunk;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 756)
81c4f4d924d5d (Alexander Gordeev 2020-06-10 18:41:41 -0700 757) for (chunk = 0; ; chunk++) {
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 758) end = bitmap_find_region_reverse(start, end);
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 759) if (start > end)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 760) break;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 761)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 762) if (!chunks--)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 763) return -EOVERFLOW;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 764)
81c4f4d924d5d (Alexander Gordeev 2020-06-10 18:41:41 -0700 765) #if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN)
81c4f4d924d5d (Alexander Gordeev 2020-06-10 18:41:41 -0700 766) end = bitmap_get_x32_reverse(start, end, &bitmap[chunk ^ 1]);
81c4f4d924d5d (Alexander Gordeev 2020-06-10 18:41:41 -0700 767) #else
81c4f4d924d5d (Alexander Gordeev 2020-06-10 18:41:41 -0700 768) end = bitmap_get_x32_reverse(start, end, &bitmap[chunk]);
81c4f4d924d5d (Alexander Gordeev 2020-06-10 18:41:41 -0700 769) #endif
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 770) if (IS_ERR(end))
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 771) return PTR_ERR(end);
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 772) }
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 773)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 774) unset_bit = (BITS_TO_U32(nmaskbits) - chunks) * 32;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 775) if (unset_bit < nmaskbits) {
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 776) bitmap_clear(maskp, unset_bit, nmaskbits - unset_bit);
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 777) return 0;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 778) }
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 779)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 780) if (find_next_bit(maskp, unset_bit, nmaskbits) != unset_bit)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 781) return -EOVERFLOW;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 782)
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 783) return 0;
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 784) }
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 785) EXPORT_SYMBOL(bitmap_parse);
2d6261583be00 (Yury Norov 2020-02-03 17:37:34 -0800 786)
4b060420a5960 (Mike Travis 2011-05-24 17:13:12 -0700 787)
cdc90a1871d6e (Rasmus Villemoes 2019-05-14 15:42:43 -0700 788) #ifdef CONFIG_NUMA
72fd4a35a8243 (Robert P. J. Day 2007-02-10 01:45:59 -0800 789) /**
9a86e2bad0b9f (Ben Hutchings 2010-03-05 13:43:17 -0800 790) * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 791) * @buf: pointer to a bitmap
df1d80a9eb16d (Rasmus Villemoes 2015-02-12 15:02:07 -0800 792) * @pos: a bit position in @buf (0 <= @pos < @nbits)
df1d80a9eb16d (Rasmus Villemoes 2015-02-12 15:02:07 -0800 793) * @nbits: number of valid bit positions in @buf
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 794) *
df1d80a9eb16d (Rasmus Villemoes 2015-02-12 15:02:07 -0800 795) * Map the bit at position @pos in @buf (of length @nbits) to the
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 796) * ordinal of which set bit it is. If it is not set or if @pos
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 797) * is not a valid bit position, map to -1.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 798) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 799) * If for example, just bits 4 through 7 are set in @buf, then @pos
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 800) * values 4 through 7 will get mapped to 0 through 3, respectively,
a855174878f06 (Rasmus Villemoes 2014-08-06 16:10:14 -0700 801) * and other @pos values will get mapped to -1. When @pos value 7
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 802) * gets mapped to (returns) @ord value 3 in this example, that means
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 803) * that bit 7 is the 3rd (starting with 0th) set bit in @buf.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 804) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 805) * The bit positions 0 through @bits are valid positions in @buf.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 806) */
df1d80a9eb16d (Rasmus Villemoes 2015-02-12 15:02:07 -0800 807) static int bitmap_pos_to_ord(const unsigned long *buf, unsigned int pos, unsigned int nbits)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 808) {
df1d80a9eb16d (Rasmus Villemoes 2015-02-12 15:02:07 -0800 809) if (pos >= nbits || !test_bit(pos, buf))
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 810) return -1;
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 811)
df1d80a9eb16d (Rasmus Villemoes 2015-02-12 15:02:07 -0800 812) return __bitmap_weight(buf, pos);
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 813) }
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 814)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 815) /**
9a86e2bad0b9f (Ben Hutchings 2010-03-05 13:43:17 -0800 816) * bitmap_ord_to_pos - find position of n-th set bit in bitmap
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 817) * @buf: pointer to bitmap
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 818) * @ord: ordinal bit position (n-th set bit, n >= 0)
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 819) * @nbits: number of valid bit positions in @buf
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 820) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 821) * Map the ordinal offset of bit @ord in @buf to its position in @buf.
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 822) * Value of @ord should be in range 0 <= @ord < weight(buf). If @ord
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 823) * >= weight(buf), returns @nbits.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 824) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 825) * If for example, just bits 4 through 7 are set in @buf, then @ord
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 826) * values 0 through 3 will get mapped to 4 through 7, respectively,
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 827) * and all other @ord values returns @nbits. When @ord value 3
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 828) * gets mapped to (returns) @pos value 7 in this example, that means
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 829) * that the 3rd set bit (starting with 0th) is at position 7 in @buf.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 830) *
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 831) * The bit positions 0 through @nbits-1 are valid positions in @buf.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 832) */
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 833) unsigned int bitmap_ord_to_pos(const unsigned long *buf, unsigned int ord, unsigned int nbits)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 834) {
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 835) unsigned int pos;
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 836)
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 837) for (pos = find_first_bit(buf, nbits);
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 838) pos < nbits && ord;
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 839) pos = find_next_bit(buf, nbits, pos + 1))
f6a1f5db8d7a7 (Rasmus Villemoes 2015-02-12 15:02:10 -0800 840) ord--;
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 841)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 842) return pos;
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 843) }
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 844)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 845) /**
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 846) * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 847) * @dst: remapped result
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 848) * @src: subset to be remapped
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 849) * @old: defines domain of map
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 850) * @new: defines range of map
9814ec135dedb (Rasmus Villemoes 2015-02-12 15:02:13 -0800 851) * @nbits: number of bits in each of these bitmaps
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 852) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 853) * Let @old and @new define a mapping of bit positions, such that
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 854) * whatever position is held by the n-th set bit in @old is mapped
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 855) * to the n-th set bit in @new. In the more general case, allowing
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 856) * for the possibility that the weight 'w' of @new is less than the
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 857) * weight of @old, map the position of the n-th set bit in @old to
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 858) * the position of the m-th set bit in @new, where m == n % w.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 859) *
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 860) * If either of the @old and @new bitmaps are empty, or if @src and
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 861) * @dst point to the same location, then this routine copies @src
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 862) * to @dst.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 863) *
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 864) * The positions of unset bits in @old are mapped to themselves
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 865) * (the identify map).
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 866) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 867) * Apply the above specified mapping to @src, placing the result in
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 868) * @dst, clearing any bits previously set in @dst.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 869) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 870) * For example, lets say that @old has bits 4 through 7 set, and
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 871) * @new has bits 12 through 15 set. This defines the mapping of bit
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 872) * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 873) * bit positions unchanged. So if say @src comes into this routine
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 874) * with bits 1, 5 and 7 set, then @dst should leave with bits 1,
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 875) * 13 and 15 set.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 876) */
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 877) void bitmap_remap(unsigned long *dst, const unsigned long *src,
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 878) const unsigned long *old, const unsigned long *new,
9814ec135dedb (Rasmus Villemoes 2015-02-12 15:02:13 -0800 879) unsigned int nbits)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 880) {
9814ec135dedb (Rasmus Villemoes 2015-02-12 15:02:13 -0800 881) unsigned int oldbit, w;
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 882)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 883) if (dst == src) /* following doesn't handle inplace remaps */
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 884) return;
9814ec135dedb (Rasmus Villemoes 2015-02-12 15:02:13 -0800 885) bitmap_zero(dst, nbits);
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 886)
9814ec135dedb (Rasmus Villemoes 2015-02-12 15:02:13 -0800 887) w = bitmap_weight(new, nbits);
9814ec135dedb (Rasmus Villemoes 2015-02-12 15:02:13 -0800 888) for_each_set_bit(oldbit, src, nbits) {
9814ec135dedb (Rasmus Villemoes 2015-02-12 15:02:13 -0800 889) int n = bitmap_pos_to_ord(old, oldbit, nbits);
08564fb7ab9ea (Akinobu Mita 2010-03-05 13:43:18 -0800 890)
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 891) if (n < 0 || w == 0)
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 892) set_bit(oldbit, dst); /* identity map */
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 893) else
9814ec135dedb (Rasmus Villemoes 2015-02-12 15:02:13 -0800 894) set_bit(bitmap_ord_to_pos(new, n % w, nbits), dst);
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 895) }
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 896) }
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 897)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 898) /**
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 899) * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit
6e1907ffdc694 (Randy Dunlap 2006-06-25 05:48:57 -0700 900) * @oldbit: bit position to be mapped
6e1907ffdc694 (Randy Dunlap 2006-06-25 05:48:57 -0700 901) * @old: defines domain of map
6e1907ffdc694 (Randy Dunlap 2006-06-25 05:48:57 -0700 902) * @new: defines range of map
6e1907ffdc694 (Randy Dunlap 2006-06-25 05:48:57 -0700 903) * @bits: number of bits in each of these bitmaps
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 904) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 905) * Let @old and @new define a mapping of bit positions, such that
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 906) * whatever position is held by the n-th set bit in @old is mapped
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 907) * to the n-th set bit in @new. In the more general case, allowing
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 908) * for the possibility that the weight 'w' of @new is less than the
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 909) * weight of @old, map the position of the n-th set bit in @old to
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 910) * the position of the m-th set bit in @new, where m == n % w.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 911) *
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 912) * The positions of unset bits in @old are mapped to themselves
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 913) * (the identify map).
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 914) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 915) * Apply the above specified mapping to bit position @oldbit, returning
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 916) * the new bit position.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 917) *
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 918) * For example, lets say that @old has bits 4 through 7 set, and
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 919) * @new has bits 12 through 15 set. This defines the mapping of bit
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 920) * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 921) * bit positions unchanged. So if say @oldbit is 5, then this routine
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 922) * returns 13.
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 923) */
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 924) int bitmap_bitremap(int oldbit, const unsigned long *old,
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 925) const unsigned long *new, int bits)
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 926) {
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 927) int w = bitmap_weight(new, bits);
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 928) int n = bitmap_pos_to_ord(old, oldbit, bits);
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 929) if (n < 0 || w == 0)
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 930) return oldbit;
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 931) else
96b7f34143c2c (Paul Jackson 2006-01-08 01:01:46 -0800 932) return bitmap_ord_to_pos(new, n % w, bits);
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 933) }
fb5eeeee44edb (Paul Jackson 2005-10-30 15:02:33 -0800 934)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 935) /**
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 936) * bitmap_onto - translate one bitmap relative to another
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 937) * @dst: resulting translated bitmap
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 938) * @orig: original untranslated bitmap
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 939) * @relmap: bitmap relative to which translated
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 940) * @bits: number of bits in each of these bitmaps
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 941) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 942) * Set the n-th bit of @dst iff there exists some m such that the
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 943) * n-th bit of @relmap is set, the m-th bit of @orig is set, and
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 944) * the n-th bit of @relmap is also the m-th _set_ bit of @relmap.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 945) * (If you understood the previous sentence the first time your
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 946) * read it, you're overqualified for your current job.)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 947) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 948) * In other words, @orig is mapped onto (surjectively) @dst,
da3dae54e4ff0 (Masanari Iida 2014-09-09 01:27:23 +0900 949) * using the map { <n, m> | the n-th bit of @relmap is the
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 950) * m-th set bit of @relmap }.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 951) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 952) * Any set bits in @orig above bit number W, where W is the
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 953) * weight of (number of set bits in) @relmap are mapped nowhere.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 954) * In particular, if for all bits m set in @orig, m >= W, then
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 955) * @dst will end up empty. In situations where the possibility
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 956) * of such an empty result is not desired, one way to avoid it is
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 957) * to use the bitmap_fold() operator, below, to first fold the
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 958) * @orig bitmap over itself so that all its set bits x are in the
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 959) * range 0 <= x < W. The bitmap_fold() operator does this by
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 960) * setting the bit (m % W) in @dst, for each bit (m) set in @orig.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 961) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 962) * Example [1] for bitmap_onto():
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 963) * Let's say @relmap has bits 30-39 set, and @orig has bits
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 964) * 1, 3, 5, 7, 9 and 11 set. Then on return from this routine,
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 965) * @dst will have bits 31, 33, 35, 37 and 39 set.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 966) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 967) * When bit 0 is set in @orig, it means turn on the bit in
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 968) * @dst corresponding to whatever is the first bit (if any)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 969) * that is turned on in @relmap. Since bit 0 was off in the
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 970) * above example, we leave off that bit (bit 30) in @dst.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 971) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 972) * When bit 1 is set in @orig (as in the above example), it
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 973) * means turn on the bit in @dst corresponding to whatever
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 974) * is the second bit that is turned on in @relmap. The second
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 975) * bit in @relmap that was turned on in the above example was
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 976) * bit 31, so we turned on bit 31 in @dst.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 977) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 978) * Similarly, we turned on bits 33, 35, 37 and 39 in @dst,
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 979) * because they were the 4th, 6th, 8th and 10th set bits
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 980) * set in @relmap, and the 4th, 6th, 8th and 10th bits of
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 981) * @orig (i.e. bits 3, 5, 7 and 9) were also set.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 982) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 983) * When bit 11 is set in @orig, it means turn on the bit in
25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 984) * @dst corresponding to whatever is the twelfth bit that is
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 985) * turned on in @relmap. In the above example, there were
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 986) * only ten bits turned on in @relmap (30..39), so that bit
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 987) * 11 was set in @orig had no affect on @dst.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 988) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 989) * Example [2] for bitmap_fold() + bitmap_onto():
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 990) * Let's say @relmap has these ten bits set::
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 991) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 992) * 40 41 42 43 45 48 53 61 74 95
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 993) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 994) * (for the curious, that's 40 plus the first ten terms of the
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 995) * Fibonacci sequence.)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 996) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 997) * Further lets say we use the following code, invoking
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 998) * bitmap_fold() then bitmap_onto, as suggested above to
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 999) * avoid the possibility of an empty @dst result::
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1000) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1001) * unsigned long *tmp; // a temporary bitmap's bits
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1002) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1003) * bitmap_fold(tmp, orig, bitmap_weight(relmap, bits), bits);
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1004) * bitmap_onto(dst, tmp, relmap, bits);
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1005) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1006) * Then this table shows what various values of @dst would be, for
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1007) * various @orig's. I list the zero-based positions of each set bit.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1008) * The tmp column shows the intermediate result, as computed by
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1009) * using bitmap_fold() to fold the @orig bitmap modulo ten
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 1010) * (the weight of @relmap):
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1011) *
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 1012) * =============== ============== =================
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1013) * @orig tmp @dst
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1014) * 0 0 40
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1015) * 1 1 41
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1016) * 9 9 95
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 1017) * 10 0 40 [#f1]_
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1018) * 1 3 5 7 1 3 5 7 41 43 48 61
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1019) * 0 1 2 3 4 0 1 2 3 4 40 41 42 43 45
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1020) * 0 9 18 27 0 9 8 7 40 61 74 95
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1021) * 0 10 20 30 0 40
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1022) * 0 11 22 33 0 1 2 3 40 41 42 43
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1023) * 0 12 24 36 0 2 4 6 40 42 45 53
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 1024) * 78 102 211 1 2 8 41 42 74 [#f1]_
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 1025) * =============== ============== =================
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 1026) *
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 1027) * .. [#f1]
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1028) *
40bf19a8d9af9 (Mauro Carvalho Chehab 2017-03-30 17:11:35 -0300 1029) * For these marked lines, if we hadn't first done bitmap_fold()
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1030) * into tmp, then the @dst result would have been empty.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1031) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1032) * If either of @orig or @relmap is empty (no set bits), then @dst
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1033) * will be returned empty.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1034) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1035) * If (as explained above) the only set bits in @orig are in positions
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1036) * m where m >= W, (where W is the weight of @relmap) then @dst will
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1037) * once again be returned empty.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1038) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1039) * All bits in @dst not set by the above rule are cleared.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1040) */
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1041) void bitmap_onto(unsigned long *dst, const unsigned long *orig,
eb56988378816 (Rasmus Villemoes 2015-02-12 15:02:01 -0800 1042) const unsigned long *relmap, unsigned int bits)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1043) {
eb56988378816 (Rasmus Villemoes 2015-02-12 15:02:01 -0800 1044) unsigned int n, m; /* same meaning as in above comment */
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1045)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1046) if (dst == orig) /* following doesn't handle inplace mappings */
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1047) return;
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1048) bitmap_zero(dst, bits);
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1049)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1050) /*
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1051) * The following code is a more efficient, but less
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1052) * obvious, equivalent to the loop:
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1053) * for (m = 0; m < bitmap_weight(relmap, bits); m++) {
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1054) * n = bitmap_ord_to_pos(orig, m, bits);
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1055) * if (test_bit(m, orig))
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1056) * set_bit(n, dst);
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1057) * }
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1058) */
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1059)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1060) m = 0;
08564fb7ab9ea (Akinobu Mita 2010-03-05 13:43:18 -0800 1061) for_each_set_bit(n, relmap, bits) {
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1062) /* m == bitmap_pos_to_ord(relmap, n, bits) */
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1063) if (test_bit(m, orig))
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1064) set_bit(n, dst);
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1065) m++;
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1066) }
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1067) }
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1068)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1069) /**
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1070) * bitmap_fold - fold larger bitmap into smaller, modulo specified size
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1071) * @dst: resulting smaller bitmap
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1072) * @orig: original larger bitmap
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1073) * @sz: specified size
b26ad5836c3a0 (Rasmus Villemoes 2015-02-12 15:02:04 -0800 1074) * @nbits: number of bits in each of these bitmaps
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1075) *
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1076) * For each bit oldbit in @orig, set bit oldbit mod @sz in @dst.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1077) * Clear all other bits in @dst. See further the comment and
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1078) * Example [2] for bitmap_onto() for why and how to use this.
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1079) */
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1080) void bitmap_fold(unsigned long *dst, const unsigned long *orig,
b26ad5836c3a0 (Rasmus Villemoes 2015-02-12 15:02:04 -0800 1081) unsigned int sz, unsigned int nbits)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1082) {
b26ad5836c3a0 (Rasmus Villemoes 2015-02-12 15:02:04 -0800 1083) unsigned int oldbit;
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1084)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1085) if (dst == orig) /* following doesn't handle inplace mappings */
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1086) return;
b26ad5836c3a0 (Rasmus Villemoes 2015-02-12 15:02:04 -0800 1087) bitmap_zero(dst, nbits);
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1088)
b26ad5836c3a0 (Rasmus Villemoes 2015-02-12 15:02:04 -0800 1089) for_each_set_bit(oldbit, orig, nbits)
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1090) set_bit(oldbit % sz, dst);
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1091) }
cdc90a1871d6e (Rasmus Villemoes 2019-05-14 15:42:43 -0700 1092) #endif /* CONFIG_NUMA */
7ea931c9fc80c (Paul Jackson 2008-04-28 02:12:29 -0700 1093)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1094) /*
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1095) * Common code for bitmap_*_region() routines.
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1096) * bitmap: array of unsigned longs corresponding to the bitmap
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1097) * pos: the beginning of the region
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1098) * order: region size (log base 2 of number of bits)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1099) * reg_op: operation(s) to perform on that region of bitmap
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1100) *
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1101) * Can set, verify and/or release a region of bits in a bitmap,
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1102) * depending on which combination of REG_OP_* flag bits is set.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1103) *
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1104) * A region of a bitmap is a sequence of bits in the bitmap, of
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1105) * some size '1 << order' (a power of two), aligned to that same
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1106) * '1 << order' power of two.
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1107) *
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1108) * Returns 1 if REG_OP_ISFREE succeeds (region is all zero bits).
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1109) * Returns 0 in all other cases and reg_ops.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1110) */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1111)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1112) enum {
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1113) REG_OP_ISFREE, /* true if region is all zero bits */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1114) REG_OP_ALLOC, /* set all bits in region */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1115) REG_OP_RELEASE, /* clear all bits in region */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1116) };
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1117)
9279d3286e107 (Rasmus Villemoes 2014-08-06 16:10:16 -0700 1118) static int __reg_op(unsigned long *bitmap, unsigned int pos, int order, int reg_op)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1119) {
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1120) int nbits_reg; /* number of bits in region */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1121) int index; /* index first long of region in bitmap */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1122) int offset; /* bit offset region in bitmap[index] */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1123) int nlongs_reg; /* num longs spanned by region in bitmap */
74373c6acc524 (Paul Mundt 2006-03-24 03:15:45 -0800 1124) int nbitsinlong; /* num bits of region in each spanned long */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1125) unsigned long mask; /* bitmask for one long of region */
74373c6acc524 (Paul Mundt 2006-03-24 03:15:45 -0800 1126) int i; /* scans bitmap by longs */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1127) int ret = 0; /* return value */
74373c6acc524 (Paul Mundt 2006-03-24 03:15:45 -0800 1128)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1129) /*
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1130) * Either nlongs_reg == 1 (for small orders that fit in one long)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1131) * or (offset == 0 && mask == ~0UL) (for larger multiword orders.)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1132) */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1133) nbits_reg = 1 << order;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1134) index = pos / BITS_PER_LONG;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1135) offset = pos - (index * BITS_PER_LONG);
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1136) nlongs_reg = BITS_TO_LONGS(nbits_reg);
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1137) nbitsinlong = min(nbits_reg, BITS_PER_LONG);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1138)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1139) /*
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1140) * Can't do "mask = (1UL << nbitsinlong) - 1", as that
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1141) * overflows if nbitsinlong == BITS_PER_LONG.
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1142) */
74373c6acc524 (Paul Mundt 2006-03-24 03:15:45 -0800 1143) mask = (1UL << (nbitsinlong - 1));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1144) mask += mask - 1;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1145) mask <<= offset;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1146)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1147) switch (reg_op) {
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1148) case REG_OP_ISFREE:
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1149) for (i = 0; i < nlongs_reg; i++) {
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1150) if (bitmap[index + i] & mask)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1151) goto done;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1152) }
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1153) ret = 1; /* all bits in region free (zero) */
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1154) break;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1155)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1156) case REG_OP_ALLOC:
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1157) for (i = 0; i < nlongs_reg; i++)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1158) bitmap[index + i] |= mask;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1159) break;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1160)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1161) case REG_OP_RELEASE:
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1162) for (i = 0; i < nlongs_reg; i++)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1163) bitmap[index + i] &= ~mask;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1164) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1165) }
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1166) done:
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1167) return ret;
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1168) }
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1169)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1170) /**
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1171) * bitmap_find_free_region - find a contiguous aligned mem region
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1172) * @bitmap: array of unsigned longs corresponding to the bitmap
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1173) * @bits: number of bits in the bitmap
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1174) * @order: region size (log base 2 of number of bits) to find
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1175) *
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1176) * Find a region of free (zero) bits in a @bitmap of @bits bits and
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1177) * allocate them (set them to one). Only consider regions of length
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1178) * a power (@order) of two, aligned to that power of two, which
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1179) * makes the search algorithm much faster.
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1180) *
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1181) * Return the bit offset in bitmap of the allocated region,
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1182) * or -errno on failure.
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1183) */
9279d3286e107 (Rasmus Villemoes 2014-08-06 16:10:16 -0700 1184) int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order)
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1185) {
9279d3286e107 (Rasmus Villemoes 2014-08-06 16:10:16 -0700 1186) unsigned int pos, end; /* scans bitmap by regions of size order */
aa8e4fc68d802 (Linus Torvalds 2009-03-12 19:32:51 -0700 1187)
9279d3286e107 (Rasmus Villemoes 2014-08-06 16:10:16 -0700 1188) for (pos = 0 ; (end = pos + (1U << order)) <= bits; pos = end) {
aa8e4fc68d802 (Linus Torvalds 2009-03-12 19:32:51 -0700 1189) if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
aa8e4fc68d802 (Linus Torvalds 2009-03-12 19:32:51 -0700 1190) continue;
aa8e4fc68d802 (Linus Torvalds 2009-03-12 19:32:51 -0700 1191) __reg_op(bitmap, pos, order, REG_OP_ALLOC);
aa8e4fc68d802 (Linus Torvalds 2009-03-12 19:32:51 -0700 1192) return pos;
aa8e4fc68d802 (Linus Torvalds 2009-03-12 19:32:51 -0700 1193) }
aa8e4fc68d802 (Linus Torvalds 2009-03-12 19:32:51 -0700 1194) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1195) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1196) EXPORT_SYMBOL(bitmap_find_free_region);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1197)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1198) /**
87e2480258633 (Paul Jackson 2006-03-24 03:15:44 -0800 1199) * bitmap_release_region - release allocated bitmap region
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1200) * @bitmap: array of unsigned longs corresponding to the bitmap
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1201) * @pos: beginning of bit region to release
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1202) * @order: region size (log base 2 of number of bits) to release
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1203) *
72fd4a35a8243 (Robert P. J. Day 2007-02-10 01:45:59 -0800 1204) * This is the complement to __bitmap_find_free_region() and releases
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1205) * the found region (by clearing it in the bitmap).
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1206) *
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1207) * No return value.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1208) */
9279d3286e107 (Rasmus Villemoes 2014-08-06 16:10:16 -0700 1209) void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1210) {
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1211) __reg_op(bitmap, pos, order, REG_OP_RELEASE);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1212) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1213) EXPORT_SYMBOL(bitmap_release_region);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1214)
87e2480258633 (Paul Jackson 2006-03-24 03:15:44 -0800 1215) /**
87e2480258633 (Paul Jackson 2006-03-24 03:15:44 -0800 1216) * bitmap_allocate_region - allocate bitmap region
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1217) * @bitmap: array of unsigned longs corresponding to the bitmap
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1218) * @pos: beginning of bit region to allocate
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1219) * @order: region size (log base 2 of number of bits) to allocate
87e2480258633 (Paul Jackson 2006-03-24 03:15:44 -0800 1220) *
87e2480258633 (Paul Jackson 2006-03-24 03:15:44 -0800 1221) * Allocate (set bits in) a specified region of a bitmap.
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1222) *
6e1907ffdc694 (Randy Dunlap 2006-06-25 05:48:57 -0700 1223) * Return 0 on success, or %-EBUSY if specified region wasn't
87e2480258633 (Paul Jackson 2006-03-24 03:15:44 -0800 1224) * free (not all bits were zero).
87e2480258633 (Paul Jackson 2006-03-24 03:15:44 -0800 1225) */
9279d3286e107 (Rasmus Villemoes 2014-08-06 16:10:16 -0700 1226) int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1227) {
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1228) if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
3cf64b933c90b (Paul Jackson 2006-03-24 03:15:46 -0800 1229) return -EBUSY;
2ac521d3325a2 (Rasmus Villemoes 2014-08-06 16:10:18 -0700 1230) return __reg_op(bitmap, pos, order, REG_OP_ALLOC);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1231) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1232) EXPORT_SYMBOL(bitmap_allocate_region);
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1233)
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1234) /**
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1235) * bitmap_copy_le - copy a bitmap, putting the bits into little-endian order.
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1236) * @dst: destination buffer
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1237) * @src: bitmap to copy
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1238) * @nbits: number of bits in the bitmap
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1239) *
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1240) * Require nbits % BITS_PER_LONG == 0.
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1241) */
e8f24278329dc (Rasmus Villemoes 2015-02-13 14:36:00 -0800 1242) #ifdef __BIG_ENDIAN
9b6c2d2e2ba52 (Rasmus Villemoes 2015-02-13 14:35:57 -0800 1243) void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits)
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1244) {
9b6c2d2e2ba52 (Rasmus Villemoes 2015-02-13 14:35:57 -0800 1245) unsigned int i;
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1246)
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1247) for (i = 0; i < nbits/BITS_PER_LONG; i++) {
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1248) if (BITS_PER_LONG == 64)
9b6c2d2e2ba52 (Rasmus Villemoes 2015-02-13 14:35:57 -0800 1249) dst[i] = cpu_to_le64(src[i]);
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1250) else
9b6c2d2e2ba52 (Rasmus Villemoes 2015-02-13 14:35:57 -0800 1251) dst[i] = cpu_to_le32(src[i]);
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1252) }
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1253) }
ccbe329bcd879 (David Vrabel 2008-09-17 16:34:03 +0100 1254) EXPORT_SYMBOL(bitmap_copy_le);
e8f24278329dc (Rasmus Villemoes 2015-02-13 14:36:00 -0800 1255) #endif
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1256)
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1257) unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags)
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1258) {
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1259) return kmalloc_array(BITS_TO_LONGS(nbits), sizeof(unsigned long),
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1260) flags);
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1261) }
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1262) EXPORT_SYMBOL(bitmap_alloc);
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1263)
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1264) unsigned long *bitmap_zalloc(unsigned int nbits, gfp_t flags)
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1265) {
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1266) return bitmap_alloc(nbits, flags | __GFP_ZERO);
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1267) }
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1268) EXPORT_SYMBOL(bitmap_zalloc);
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1269)
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1270) void bitmap_free(const unsigned long *bitmap)
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1271) {
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1272) kfree(bitmap);
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1273) }
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1274) EXPORT_SYMBOL(bitmap_free);
c42b65e363ce9 (Andy Shevchenko 2018-08-01 15:42:56 -0700 1275)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1276) static void devm_bitmap_free(void *data)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1277) {
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1278) unsigned long *bitmap = data;
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1279)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1280) bitmap_free(bitmap);
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1281) }
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1282)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1283) unsigned long *devm_bitmap_alloc(struct device *dev,
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1284) unsigned int nbits, gfp_t flags)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1285) {
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1286) unsigned long *bitmap;
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1287) int ret;
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1288)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1289) bitmap = bitmap_alloc(nbits, flags);
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1290) if (!bitmap)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1291) return NULL;
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1292)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1293) ret = devm_add_action_or_reset(dev, devm_bitmap_free, bitmap);
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1294) if (ret)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1295) return NULL;
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1296)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1297) return bitmap;
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1298) }
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1299) EXPORT_SYMBOL_GPL(devm_bitmap_alloc);
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1300)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1301) unsigned long *devm_bitmap_zalloc(struct device *dev,
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1302) unsigned int nbits, gfp_t flags)
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1303) {
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1304) return devm_bitmap_alloc(dev, nbits, flags | __GFP_ZERO);
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1305) }
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1306) EXPORT_SYMBOL_GPL(devm_bitmap_zalloc);
e829c2e474485 (Bartosz Golaszewski 2021-03-15 10:13:56 +0100 1307)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1308) #if BITS_PER_LONG == 64
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1309) /**
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1310) * bitmap_from_arr32 - copy the contents of u32 array of bits to bitmap
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1311) * @bitmap: array of unsigned longs, the destination bitmap
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1312) * @buf: array of u32 (in host byte order), the source bitmap
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1313) * @nbits: number of bits in @bitmap
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1314) */
ccf7a6d457a8b (Andy Shevchenko 2018-08-21 21:56:59 -0700 1315) void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf, unsigned int nbits)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1316) {
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1317) unsigned int i, halfwords;
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1318)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1319) halfwords = DIV_ROUND_UP(nbits, 32);
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1320) for (i = 0; i < halfwords; i++) {
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1321) bitmap[i/2] = (unsigned long) buf[i];
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1322) if (++i < halfwords)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1323) bitmap[i/2] |= ((unsigned long) buf[i]) << 32;
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1324) }
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1325)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1326) /* Clear tail bits in last word beyond nbits. */
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1327) if (nbits % BITS_PER_LONG)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1328) bitmap[(halfwords - 1) / 2] &= BITMAP_LAST_WORD_MASK(nbits);
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1329) }
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1330) EXPORT_SYMBOL(bitmap_from_arr32);
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1331)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1332) /**
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1333) * bitmap_to_arr32 - copy the contents of bitmap to a u32 array of bits
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1334) * @buf: array of u32 (in host byte order), the dest bitmap
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1335) * @bitmap: array of unsigned longs, the source bitmap
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1336) * @nbits: number of bits in @bitmap
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1337) */
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1338) void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap, unsigned int nbits)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1339) {
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1340) unsigned int i, halfwords;
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1341)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1342) halfwords = DIV_ROUND_UP(nbits, 32);
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1343) for (i = 0; i < halfwords; i++) {
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1344) buf[i] = (u32) (bitmap[i/2] & UINT_MAX);
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1345) if (++i < halfwords)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1346) buf[i] = (u32) (bitmap[i/2] >> 32);
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1347) }
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1348)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1349) /* Clear tail bits in last element of array beyond nbits. */
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1350) if (nbits % BITS_PER_LONG)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1351) buf[halfwords - 1] &= (u32) (UINT_MAX >> ((-nbits) & 31));
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1352) }
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1353) EXPORT_SYMBOL(bitmap_to_arr32);
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1354)
c724f193619c8 (Yury Norov 2018-02-06 15:38:02 -0800 1355) #endif