]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - lib/vsprintf.c
neigh: Use neigh table index for neigh_packet_xmit
[karo-tx-linux.git] / lib / vsprintf.c
index 602d2081e713c802406e35888b996f6aea05823a..b235c96167d32e80add7999f7833684abd54040b 100644 (file)
@@ -793,6 +793,87 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
        return buf;
 }
 
+static noinline_for_stack
+char *bitmap_string(char *buf, char *end, unsigned long *bitmap,
+                   struct printf_spec spec, const char *fmt)
+{
+       const int CHUNKSZ = 32;
+       int nr_bits = max_t(int, spec.field_width, 0);
+       int i, chunksz;
+       bool first = true;
+
+       /* reused to print numbers */
+       spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 };
+
+       chunksz = nr_bits & (CHUNKSZ - 1);
+       if (chunksz == 0)
+               chunksz = CHUNKSZ;
+
+       i = ALIGN(nr_bits, CHUNKSZ) - CHUNKSZ;
+       for (; i >= 0; i -= CHUNKSZ) {
+               u32 chunkmask, val;
+               int word, bit;
+
+               chunkmask = ((1ULL << chunksz) - 1);
+               word = i / BITS_PER_LONG;
+               bit = i % BITS_PER_LONG;
+               val = (bitmap[word] >> bit) & chunkmask;
+
+               if (!first) {
+                       if (buf < end)
+                               *buf = ',';
+                       buf++;
+               }
+               first = false;
+
+               spec.field_width = DIV_ROUND_UP(chunksz, 4);
+               buf = number(buf, end, val, spec);
+
+               chunksz = CHUNKSZ;
+       }
+       return buf;
+}
+
+static noinline_for_stack
+char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap,
+                        struct printf_spec spec, const char *fmt)
+{
+       int nr_bits = max_t(int, spec.field_width, 0);
+       /* current bit is 'cur', most recently seen range is [rbot, rtop] */
+       int cur, rbot, rtop;
+       bool first = true;
+
+       /* reused to print numbers */
+       spec = (struct printf_spec){ .base = 10 };
+
+       rbot = cur = find_first_bit(bitmap, nr_bits);
+       while (cur < nr_bits) {
+               rtop = cur;
+               cur = find_next_bit(bitmap, nr_bits, cur + 1);
+               if (cur < nr_bits && cur <= rtop + 1)
+                       continue;
+
+               if (!first) {
+                       if (buf < end)
+                               *buf = ',';
+                       buf++;
+               }
+               first = false;
+
+               buf = number(buf, end, rbot, spec);
+               if (rbot < rtop) {
+                       if (buf < end)
+                               *buf = '-';
+                       buf++;
+
+                       buf = number(buf, end, rtop, spec);
+               }
+
+               rbot = cur;
+       }
+       return buf;
+}
+
 static noinline_for_stack
 char *mac_address_string(char *buf, char *end, u8 *addr,
                         struct printf_spec spec, const char *fmt)
@@ -1258,6 +1339,10 @@ int kptr_restrict __read_mostly;
  * - 'B' For backtraced symbolic direct pointers with offset
  * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
  * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
+ * - 'b[l]' For a bitmap, the number of bits is determined by the field
+ *       width which must be explicitly specified either as part of the
+ *       format string '%32b[l]' or through '%*b[l]', [l] selects
+ *       range-list format instead of hex format
  * - 'M' For a 6-byte MAC address, it prints the address in the
  *       usual colon-separated hex notation
  * - 'm' For a 6-byte MAC address, it prints the hex address without colons
@@ -1354,6 +1439,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                return resource_string(buf, end, ptr, spec, fmt);
        case 'h':
                return hex_string(buf, end, ptr, spec, fmt);
+       case 'b':
+               switch (fmt[1]) {
+               case 'l':
+                       return bitmap_list_string(buf, end, ptr, spec, fmt);
+               default:
+                       return bitmap_string(buf, end, ptr, spec, fmt);
+               }
        case 'M':                       /* Colon separated: 00:01:02:03:04:05 */
        case 'm':                       /* Contiguous: 000102030405 */
                                        /* [mM]F (FDDI) */
@@ -1689,6 +1781,8 @@ qualifier:
  * %pB output the name of a backtrace symbol with its offset
  * %pR output the address range in a struct resource with decoded flags
  * %pr output the address range in a struct resource with raw flags
+ * %pb output the bitmap with field width as the number of bits
+ * %pbl output the bitmap as range list with field width as the number of bits
  * %pM output a 6-byte MAC address with colons
  * %pMR output a 6-byte MAC address with colons in reversed order
  * %pMF output a 6-byte MAC address with dashes