Merge remote-tracking branch 'torvalds/master' into perf/urgent
[linux-2.6-microblaze.git] / lib / bitmap.c
index 27e08c0..74ceb02 100644 (file)
@@ -489,30 +489,25 @@ EXPORT_SYMBOL(bitmap_print_to_pagebuf);
 
 /*
  * Region 9-38:4/10 describes the following bitmap structure:
- * 0      9  12    18                  38
- * .........****......****......****......
- *         ^  ^     ^                   ^
- *      start  off   group_len        end
+ * 0      9  12    18                  38           N
+ * .........****......****......****..................
+ *         ^  ^     ^                   ^           ^
+ *      start  off   group_len        end       nbits
  */
 struct region {
        unsigned int start;
        unsigned int off;
        unsigned int group_len;
        unsigned int end;
+       unsigned int nbits;
 };
 
-static int bitmap_set_region(const struct region *r,
-                               unsigned long *bitmap, int nbits)
+static void bitmap_set_region(const struct region *r, unsigned long *bitmap)
 {
        unsigned int start;
 
-       if (r->end >= nbits)
-               return -ERANGE;
-
        for (start = r->start; start <= r->end; start += r->group_len)
                bitmap_set(bitmap, start, min(r->end - start + 1, r->off));
-
-       return 0;
 }
 
 static int bitmap_check_region(const struct region *r)
@@ -520,14 +515,23 @@ static int bitmap_check_region(const struct region *r)
        if (r->start > r->end || r->group_len == 0 || r->off > r->group_len)
                return -EINVAL;
 
+       if (r->end >= r->nbits)
+               return -ERANGE;
+
        return 0;
 }
 
-static const char *bitmap_getnum(const char *str, unsigned int *num)
+static const char *bitmap_getnum(const char *str, unsigned int *num,
+                                unsigned int lastbit)
 {
        unsigned long long n;
        unsigned int len;
 
+       if (str[0] == 'N') {
+               *num = lastbit;
+               return str + 1;
+       }
+
        len = _parse_integer(str, 10, &n);
        if (!len)
                return ERR_PTR(-EINVAL);
@@ -575,7 +579,9 @@ static const char *bitmap_find_region_reverse(const char *start, const char *end
 
 static const char *bitmap_parse_region(const char *str, struct region *r)
 {
-       str = bitmap_getnum(str, &r->start);
+       unsigned int lastbit = r->nbits - 1;
+
+       str = bitmap_getnum(str, &r->start, lastbit);
        if (IS_ERR(str))
                return str;
 
@@ -585,7 +591,7 @@ static const char *bitmap_parse_region(const char *str, struct region *r)
        if (*str != '-')
                return ERR_PTR(-EINVAL);
 
-       str = bitmap_getnum(str + 1, &r->end);
+       str = bitmap_getnum(str + 1, &r->end, lastbit);
        if (IS_ERR(str))
                return str;
 
@@ -595,14 +601,14 @@ static const char *bitmap_parse_region(const char *str, struct region *r)
        if (*str != ':')
                return ERR_PTR(-EINVAL);
 
-       str = bitmap_getnum(str + 1, &r->off);
+       str = bitmap_getnum(str + 1, &r->off, lastbit);
        if (IS_ERR(str))
                return str;
 
        if (*str != '/')
                return ERR_PTR(-EINVAL);
 
-       return bitmap_getnum(str + 1, &r->group_len);
+       return bitmap_getnum(str + 1, &r->group_len, lastbit);
 
 no_end:
        r->end = r->start;
@@ -629,6 +635,10 @@ no_pattern:
  * From each group will be used only defined amount of bits.
  * Syntax: range:used_size/group_size
  * Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
+ * The value 'N' can be used as a dynamically substituted token for the
+ * maximum allowed value; i.e (nmaskbits - 1).  Keep in mind that it is
+ * dynamic, so if system changes cause the bitmap width to change, such
+ * as more cores in a CPU list, then any ranges using N will also change.
  *
  * Returns: 0 on success, -errno on invalid input strings. Error values:
  *
@@ -642,7 +652,8 @@ int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits)
        struct region r;
        long ret;
 
-       bitmap_zero(maskp, nmaskbits);
+       r.nbits = nmaskbits;
+       bitmap_zero(maskp, r.nbits);
 
        while (buf) {
                buf = bitmap_find_region(buf);
@@ -657,9 +668,7 @@ int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits)
                if (ret)
                        return ret;
 
-               ret = bitmap_set_region(&r, maskp, nmaskbits);
-               if (ret)
-                       return ret;
+               bitmap_set_region(&r, maskp);
        }
 
        return 0;