Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[firefly-linux-kernel-4.4.55.git] / lib / bitmap.c
index 324ea9eab8c1c6f2abbe6daf546370f0cdbafa5b..d456f4c15a9f999eb49d00485840ad61fcb3fbae 100644 (file)
@@ -104,18 +104,18 @@ EXPORT_SYMBOL(__bitmap_complement);
  *   @dst : destination bitmap
  *   @src : source bitmap
  *   @shift : shift by this many bits
- *   @bits : bitmap size, in bits
+ *   @nbits : bitmap size, in bits
  *
  * Shifting right (dividing) means moving bits in the MS -> LS bit
  * direction.  Zeros are fed into the vacated MS positions and the
  * LS bits shifted off the bottom are lost.
  */
-void __bitmap_shift_right(unsigned long *dst,
-                       const unsigned long *src, int shift, int bits)
+void __bitmap_shift_right(unsigned long *dst, const unsigned long *src,
+                       unsigned shift, unsigned nbits)
 {
-       int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
-       int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
-       unsigned long mask = (1UL << left) - 1;
+       unsigned k, lim = BITS_TO_LONGS(nbits);
+       unsigned off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
+       unsigned long mask = BITMAP_LAST_WORD_MASK(nbits);
        for (k = 0; off + k < lim; ++k) {
                unsigned long upper, lower;
 
@@ -127,17 +127,15 @@ void __bitmap_shift_right(unsigned long *dst,
                        upper = 0;
                else {
                        upper = src[off + k + 1];
-                       if (off + k + 1 == lim - 1 && left)
+                       if (off + k + 1 == lim - 1)
                                upper &= mask;
+                       upper <<= (BITS_PER_LONG - rem);
                }
                lower = src[off + k];
-               if (left && off + k == lim - 1)
+               if (off + k == lim - 1)
                        lower &= mask;
-               dst[k] = lower >> rem;
-               if (rem)
-                       dst[k] |= upper << (BITS_PER_LONG - rem);
-               if (left && k == lim - 1)
-                       dst[k] &= mask;
+               lower >>= rem;
+               dst[k] = lower | upper;
        }
        if (off)
                memset(&dst[lim - off], 0, off*sizeof(unsigned long));
@@ -150,18 +148,19 @@ EXPORT_SYMBOL(__bitmap_shift_right);
  *   @dst : destination bitmap
  *   @src : source bitmap
  *   @shift : shift by this many bits
- *   @bits : bitmap size, in bits
+ *   @nbits : bitmap size, in bits
  *
  * Shifting left (multiplying) means moving bits in the LS -> MS
  * direction.  Zeros are fed into the vacated LS bit positions
  * and those MS bits shifted off the top are lost.
  */
 
-void __bitmap_shift_left(unsigned long *dst,
-                       const unsigned long *src, int shift, int bits)
+void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
+                       unsigned int shift, unsigned int nbits)
 {
-       int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
-       int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
+       int k;
+       unsigned int lim = BITS_TO_LONGS(nbits);
+       unsigned int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
        for (k = lim - off - 1; k >= 0; --k) {
                unsigned long upper, lower;
 
@@ -170,17 +169,11 @@ void __bitmap_shift_left(unsigned long *dst,
                 * word below and make them the bottom rem bits of result.
                 */
                if (rem && k > 0)
-                       lower = src[k - 1];
+                       lower = src[k - 1] >> (BITS_PER_LONG - rem);
                else
                        lower = 0;
-               upper = src[k];
-               if (left && k == lim - 1)
-                       upper &= (1UL << left) - 1;
-               dst[k + off] = upper << rem;
-               if (rem)
-                       dst[k + off] |= lower >> (BITS_PER_LONG - rem);
-               if (left && k + off == lim - 1)
-                       dst[k + off] &= (1UL << left) - 1;
+               upper = src[k] << rem;
+               dst[k + off] = lower | upper;
        }
        if (off)
                memset(dst, 0, off*sizeof(unsigned long));
@@ -376,45 +369,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area_off);
 #define nbits_to_hold_value(val)       fls(val)
 #define BASEDEC 10             /* fancier cpuset lists input in decimal */
 
-/**
- * bitmap_scnprintf - convert bitmap to an ASCII hex string.
- * @buf: byte buffer into which string is placed
- * @buflen: reserved size of @buf, in bytes
- * @maskp: pointer to bitmap to convert
- * @nmaskbits: size of bitmap, in bits
- *
- * Exactly @nmaskbits bits are displayed.  Hex digits are grouped into
- * comma-separated sets of eight digits per set.  Returns the number of
- * characters which were written to *buf, excluding the trailing \0.
- */
-int bitmap_scnprintf(char *buf, unsigned int buflen,
-       const unsigned long *maskp, int nmaskbits)
-{
-       int i, word, bit, len = 0;
-       unsigned long val;
-       const char *sep = "";
-       int chunksz;
-       u32 chunkmask;
-
-       chunksz = nmaskbits & (CHUNKSZ - 1);
-       if (chunksz == 0)
-               chunksz = CHUNKSZ;
-
-       i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
-       for (; i >= 0; i -= CHUNKSZ) {
-               chunkmask = ((1ULL << chunksz) - 1);
-               word = i / BITS_PER_LONG;
-               bit = i % BITS_PER_LONG;
-               val = (maskp[word] >> bit) & chunkmask;
-               len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
-                       (chunksz+3)/4, val);
-               chunksz = CHUNKSZ;
-               sep = ",";
-       }
-       return len;
-}
-EXPORT_SYMBOL(bitmap_scnprintf);
-
 /**
  * __bitmap_parse - convert an ASCII hex string into a bitmap.
  * @buf: pointer to buffer containing string.
@@ -528,65 +482,6 @@ int bitmap_parse_user(const char __user *ubuf,
 }
 EXPORT_SYMBOL(bitmap_parse_user);
 
-/*
- * bscnl_emit(buf, buflen, rbot, rtop, bp)
- *
- * Helper routine for bitmap_scnlistprintf().  Write decimal number
- * or range to buf, suppressing output past buf+buflen, with optional
- * comma-prefix.  Return len of what was written to *buf, excluding the
- * trailing \0.
- */
-static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
-{
-       if (len > 0)
-               len += scnprintf(buf + len, buflen - len, ",");
-       if (rbot == rtop)
-               len += scnprintf(buf + len, buflen - len, "%d", rbot);
-       else
-               len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
-       return len;
-}
-
-/**
- * bitmap_scnlistprintf - convert bitmap to list format ASCII string
- * @buf: byte buffer into which string is placed
- * @buflen: reserved size of @buf, in bytes
- * @maskp: pointer to bitmap to convert
- * @nmaskbits: size of bitmap, in bits
- *
- * Output format is a comma-separated list of decimal numbers and
- * ranges.  Consecutively set bits are shown as two hyphen-separated
- * decimal numbers, the smallest and largest bit numbers set in
- * the range.  Output format is compatible with the format
- * accepted as input by bitmap_parselist().
- *
- * The return value is the number of characters which were written to *buf
- * excluding the trailing '\0', as per ISO C99's scnprintf.
- */
-int bitmap_scnlistprintf(char *buf, unsigned int buflen,
-       const unsigned long *maskp, int nmaskbits)
-{
-       int len = 0;
-       /* current bit is 'cur', most recently seen range is [rbot, rtop] */
-       int cur, rbot, rtop;
-
-       if (buflen == 0)
-               return 0;
-       buf[0] = 0;
-
-       rbot = cur = find_first_bit(maskp, nmaskbits);
-       while (cur < nmaskbits) {
-               rtop = cur;
-               cur = find_next_bit(maskp, nmaskbits, cur+1);
-               if (cur >= nmaskbits || cur > rtop + 1) {
-                       len = bscnl_emit(buf, buflen, rbot, rtop, len);
-                       rbot = cur;
-               }
-       }
-       return len;
-}
-EXPORT_SYMBOL(bitmap_scnlistprintf);
-
 /**
  * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string
  * @list: indicates whether the bitmap must be list
@@ -605,8 +500,8 @@ int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp,
        int n = 0;
 
        if (len > 1) {
-               n = list ? bitmap_scnlistprintf(buf, len, maskp, nmaskbits) :
-                          bitmap_scnprintf(buf, len, maskp, nmaskbits);
+               n = list ? scnprintf(buf, len, "%*pbl", nmaskbits, maskp) :
+                          scnprintf(buf, len, "%*pb", nmaskbits, maskp);
                buf[n++] = '\n';
                buf[n] = '\0';
        }
@@ -744,10 +639,10 @@ EXPORT_SYMBOL(bitmap_parselist_user);
 /**
  * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
  *     @buf: pointer to a bitmap
- *     @pos: a bit position in @buf (0 <= @pos < @bits)
- *     @bits: number of valid bit positions in @buf
+ *     @pos: a bit position in @buf (0 <= @pos < @nbits)
+ *     @nbits: number of valid bit positions in @buf
  *
- * Map the bit at position @pos in @buf (of length @bits) to the
+ * Map the bit at position @pos in @buf (of length @nbits) to the
  * ordinal of which set bit it is.  If it is not set or if @pos
  * is not a valid bit position, map to -1.
  *
@@ -759,56 +654,40 @@ EXPORT_SYMBOL(bitmap_parselist_user);
  *
  * The bit positions 0 through @bits are valid positions in @buf.
  */
-static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
+static int bitmap_pos_to_ord(const unsigned long *buf, unsigned int pos, unsigned int nbits)
 {
-       int i, ord;
-
-       if (pos < 0 || pos >= bits || !test_bit(pos, buf))
+       if (pos >= nbits || !test_bit(pos, buf))
                return -1;
 
-       i = find_first_bit(buf, bits);
-       ord = 0;
-       while (i < pos) {
-               i = find_next_bit(buf, bits, i + 1);
-               ord++;
-       }
-       BUG_ON(i != pos);
-
-       return ord;
+       return __bitmap_weight(buf, pos);
 }
 
 /**
  * bitmap_ord_to_pos - find position of n-th set bit in bitmap
  *     @buf: pointer to bitmap
  *     @ord: ordinal bit position (n-th set bit, n >= 0)
- *     @bits: number of valid bit positions in @buf
+ *     @nbits: number of valid bit positions in @buf
  *
  * Map the ordinal offset of bit @ord in @buf to its position in @buf.
- * Value of @ord should be in range 0 <= @ord < weight(buf), else
- * results are undefined.
+ * Value of @ord should be in range 0 <= @ord < weight(buf). If @ord
+ * >= weight(buf), returns @nbits.
  *
  * If for example, just bits 4 through 7 are set in @buf, then @ord
  * values 0 through 3 will get mapped to 4 through 7, respectively,
- * and all other @ord values return undefined values.  When @ord value 3
+ * and all other @ord values returns @nbits.  When @ord value 3
  * gets mapped to (returns) @pos value 7 in this example, that means
  * that the 3rd set bit (starting with 0th) is at position 7 in @buf.
  *
- * The bit positions 0 through @bits are valid positions in @buf.
+ * The bit positions 0 through @nbits-1 are valid positions in @buf.
  */
-int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
+unsigned int bitmap_ord_to_pos(const unsigned long *buf, unsigned int ord, unsigned int nbits)
 {
-       int pos = 0;
-
-       if (ord >= 0 && ord < bits) {
-               int i;
+       unsigned int pos;
 
-               for (i = find_first_bit(buf, bits);
-                    i < bits && ord > 0;
-                    i = find_next_bit(buf, bits, i + 1))
-                       ord--;
-               if (i < bits && ord == 0)
-                       pos = i;
-       }
+       for (pos = find_first_bit(buf, nbits);
+            pos < nbits && ord;
+            pos = find_next_bit(buf, nbits, pos + 1))
+               ord--;
 
        return pos;
 }
@@ -819,7 +698,7 @@ int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
  *     @src: subset to be remapped
  *     @old: defines domain of map
  *     @new: defines range of map
- *     @bits: number of bits in each of these bitmaps
+ *     @nbits: number of bits in each of these bitmaps
  *
  * Let @old and @new define a mapping of bit positions, such that
  * whatever position is held by the n-th set bit in @old is mapped
@@ -847,22 +726,22 @@ int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
  */
 void bitmap_remap(unsigned long *dst, const unsigned long *src,
                const unsigned long *old, const unsigned long *new,
-               int bits)
+               unsigned int nbits)
 {
-       int oldbit, w;
+       unsigned int oldbit, w;
 
        if (dst == src)         /* following doesn't handle inplace remaps */
                return;
-       bitmap_zero(dst, bits);
+       bitmap_zero(dst, nbits);
 
-       w = bitmap_weight(new, bits);
-       for_each_set_bit(oldbit, src, bits) {
-               int n = bitmap_pos_to_ord(old, oldbit, bits);
+       w = bitmap_weight(new, nbits);
+       for_each_set_bit(oldbit, src, nbits) {
+               int n = bitmap_pos_to_ord(old, oldbit, nbits);
 
                if (n < 0 || w == 0)
                        set_bit(oldbit, dst);   /* identity map */
                else
-                       set_bit(bitmap_ord_to_pos(new, n % w, bits), dst);
+                       set_bit(bitmap_ord_to_pos(new, n % w, nbits), dst);
        }
 }
 EXPORT_SYMBOL(bitmap_remap);
@@ -1006,9 +885,9 @@ EXPORT_SYMBOL(bitmap_bitremap);
  * All bits in @dst not set by the above rule are cleared.
  */
 void bitmap_onto(unsigned long *dst, const unsigned long *orig,
-                       const unsigned long *relmap, int bits)
+                       const unsigned long *relmap, unsigned int bits)
 {
-       int n, m;               /* same meaning as in above comment */
+       unsigned int n, m;      /* same meaning as in above comment */
 
        if (dst == orig)        /* following doesn't handle inplace mappings */
                return;
@@ -1039,22 +918,22 @@ EXPORT_SYMBOL(bitmap_onto);
  *     @dst: resulting smaller bitmap
  *     @orig: original larger bitmap
  *     @sz: specified size
- *     @bits: number of bits in each of these bitmaps
+ *     @nbits: number of bits in each of these bitmaps
  *
  * For each bit oldbit in @orig, set bit oldbit mod @sz in @dst.
  * Clear all other bits in @dst.  See further the comment and
  * Example [2] for bitmap_onto() for why and how to use this.
  */
 void bitmap_fold(unsigned long *dst, const unsigned long *orig,
-                       int sz, int bits)
+                       unsigned int sz, unsigned int nbits)
 {
-       int oldbit;
+       unsigned int oldbit;
 
        if (dst == orig)        /* following doesn't handle inplace mappings */
                return;
-       bitmap_zero(dst, bits);
+       bitmap_zero(dst, nbits);
 
-       for_each_set_bit(oldbit, orig, bits)
+       for_each_set_bit(oldbit, orig, nbits)
                set_bit(oldbit % sz, dst);
 }
 EXPORT_SYMBOL(bitmap_fold);
@@ -1207,16 +1086,17 @@ EXPORT_SYMBOL(bitmap_allocate_region);
  *
  * Require nbits % BITS_PER_LONG == 0.
  */
-void bitmap_copy_le(void *dst, const unsigned long *src, int nbits)
+#ifdef __BIG_ENDIAN
+void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits)
 {
-       unsigned long *d = dst;
-       int i;
+       unsigned int i;
 
        for (i = 0; i < nbits/BITS_PER_LONG; i++) {
                if (BITS_PER_LONG == 64)
-                       d[i] = cpu_to_le64(src[i]);
+                       dst[i] = cpu_to_le64(src[i]);
                else
-                       d[i] = cpu_to_le32(src[i]);
+                       dst[i] = cpu_to_le32(src[i]);
        }
 }
 EXPORT_SYMBOL(bitmap_copy_le);
+#endif