diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bitmap.c | 61 | ||||
-rw-r--r-- | lib/vsprintf.c | 94 |
2 files changed, 96 insertions, 59 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index a13c7f4e325a..e85040ba1f22 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
@@ -383,28 +383,7 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area_off); | |||
383 | int bitmap_scnprintf(char *buf, unsigned int buflen, | 383 | int bitmap_scnprintf(char *buf, unsigned int buflen, |
384 | const unsigned long *maskp, int nmaskbits) | 384 | const unsigned long *maskp, int nmaskbits) |
385 | { | 385 | { |
386 | int i, word, bit, len = 0; | 386 | return scnprintf(buf, buflen, "%*pb", nmaskbits, maskp); |
387 | unsigned long val; | ||
388 | const char *sep = ""; | ||
389 | int chunksz; | ||
390 | u32 chunkmask; | ||
391 | |||
392 | chunksz = nmaskbits & (CHUNKSZ - 1); | ||
393 | if (chunksz == 0) | ||
394 | chunksz = CHUNKSZ; | ||
395 | |||
396 | i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ; | ||
397 | for (; i >= 0; i -= CHUNKSZ) { | ||
398 | chunkmask = ((1ULL << chunksz) - 1); | ||
399 | word = i / BITS_PER_LONG; | ||
400 | bit = i % BITS_PER_LONG; | ||
401 | val = (maskp[word] >> bit) & chunkmask; | ||
402 | len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep, | ||
403 | (chunksz+3)/4, val); | ||
404 | chunksz = CHUNKSZ; | ||
405 | sep = ","; | ||
406 | } | ||
407 | return len; | ||
408 | } | 387 | } |
409 | EXPORT_SYMBOL(bitmap_scnprintf); | 388 | EXPORT_SYMBOL(bitmap_scnprintf); |
410 | 389 | ||
@@ -521,25 +500,6 @@ int bitmap_parse_user(const char __user *ubuf, | |||
521 | } | 500 | } |
522 | EXPORT_SYMBOL(bitmap_parse_user); | 501 | EXPORT_SYMBOL(bitmap_parse_user); |
523 | 502 | ||
524 | /* | ||
525 | * bscnl_emit(buf, buflen, rbot, rtop, bp) | ||
526 | * | ||
527 | * Helper routine for bitmap_scnlistprintf(). Write decimal number | ||
528 | * or range to buf, suppressing output past buf+buflen, with optional | ||
529 | * comma-prefix. Return len of what was written to *buf, excluding the | ||
530 | * trailing \0. | ||
531 | */ | ||
532 | static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len) | ||
533 | { | ||
534 | if (len > 0) | ||
535 | len += scnprintf(buf + len, buflen - len, ","); | ||
536 | if (rbot == rtop) | ||
537 | len += scnprintf(buf + len, buflen - len, "%d", rbot); | ||
538 | else | ||
539 | len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop); | ||
540 | return len; | ||
541 | } | ||
542 | |||
543 | /** | 503 | /** |
544 | * bitmap_scnlistprintf - convert bitmap to list format ASCII string | 504 | * bitmap_scnlistprintf - convert bitmap to list format ASCII string |
545 | * @buf: byte buffer into which string is placed | 505 | * @buf: byte buffer into which string is placed |
@@ -559,24 +519,7 @@ static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len) | |||
559 | int bitmap_scnlistprintf(char *buf, unsigned int buflen, | 519 | int bitmap_scnlistprintf(char *buf, unsigned int buflen, |
560 | const unsigned long *maskp, int nmaskbits) | 520 | const unsigned long *maskp, int nmaskbits) |
561 | { | 521 | { |
562 | int len = 0; | 522 | return scnprintf(buf, buflen, "%*pbl", nmaskbits, maskp); |
563 | /* current bit is 'cur', most recently seen range is [rbot, rtop] */ | ||
564 | int cur, rbot, rtop; | ||
565 | |||
566 | if (buflen == 0) | ||
567 | return 0; | ||
568 | buf[0] = 0; | ||
569 | |||
570 | rbot = cur = find_first_bit(maskp, nmaskbits); | ||
571 | while (cur < nmaskbits) { | ||
572 | rtop = cur; | ||
573 | cur = find_next_bit(maskp, nmaskbits, cur+1); | ||
574 | if (cur >= nmaskbits || cur > rtop + 1) { | ||
575 | len = bscnl_emit(buf, buflen, rbot, rtop, len); | ||
576 | rbot = cur; | ||
577 | } | ||
578 | } | ||
579 | return len; | ||
580 | } | 523 | } |
581 | EXPORT_SYMBOL(bitmap_scnlistprintf); | 524 | EXPORT_SYMBOL(bitmap_scnlistprintf); |
582 | 525 | ||
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 602d2081e713..b235c96167d3 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -794,6 +794,87 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | |||
794 | } | 794 | } |
795 | 795 | ||
796 | static noinline_for_stack | 796 | static noinline_for_stack |
797 | char *bitmap_string(char *buf, char *end, unsigned long *bitmap, | ||
798 | struct printf_spec spec, const char *fmt) | ||
799 | { | ||
800 | const int CHUNKSZ = 32; | ||
801 | int nr_bits = max_t(int, spec.field_width, 0); | ||
802 | int i, chunksz; | ||
803 | bool first = true; | ||
804 | |||
805 | /* reused to print numbers */ | ||
806 | spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 }; | ||
807 | |||
808 | chunksz = nr_bits & (CHUNKSZ - 1); | ||
809 | if (chunksz == 0) | ||
810 | chunksz = CHUNKSZ; | ||
811 | |||
812 | i = ALIGN(nr_bits, CHUNKSZ) - CHUNKSZ; | ||
813 | for (; i >= 0; i -= CHUNKSZ) { | ||
814 | u32 chunkmask, val; | ||
815 | int word, bit; | ||
816 | |||
817 | chunkmask = ((1ULL << chunksz) - 1); | ||
818 | word = i / BITS_PER_LONG; | ||
819 | bit = i % BITS_PER_LONG; | ||
820 | val = (bitmap[word] >> bit) & chunkmask; | ||
821 | |||
822 | if (!first) { | ||
823 | if (buf < end) | ||
824 | *buf = ','; | ||
825 | buf++; | ||
826 | } | ||
827 | first = false; | ||
828 | |||
829 | spec.field_width = DIV_ROUND_UP(chunksz, 4); | ||
830 | buf = number(buf, end, val, spec); | ||
831 | |||
832 | chunksz = CHUNKSZ; | ||
833 | } | ||
834 | return buf; | ||
835 | } | ||
836 | |||
837 | static noinline_for_stack | ||
838 | char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, | ||
839 | struct printf_spec spec, const char *fmt) | ||
840 | { | ||
841 | int nr_bits = max_t(int, spec.field_width, 0); | ||
842 | /* current bit is 'cur', most recently seen range is [rbot, rtop] */ | ||
843 | int cur, rbot, rtop; | ||
844 | bool first = true; | ||
845 | |||
846 | /* reused to print numbers */ | ||
847 | spec = (struct printf_spec){ .base = 10 }; | ||
848 | |||
849 | rbot = cur = find_first_bit(bitmap, nr_bits); | ||
850 | while (cur < nr_bits) { | ||
851 | rtop = cur; | ||
852 | cur = find_next_bit(bitmap, nr_bits, cur + 1); | ||
853 | if (cur < nr_bits && cur <= rtop + 1) | ||
854 | continue; | ||
855 | |||
856 | if (!first) { | ||
857 | if (buf < end) | ||
858 | *buf = ','; | ||
859 | buf++; | ||
860 | } | ||
861 | first = false; | ||
862 | |||
863 | buf = number(buf, end, rbot, spec); | ||
864 | if (rbot < rtop) { | ||
865 | if (buf < end) | ||
866 | *buf = '-'; | ||
867 | buf++; | ||
868 | |||
869 | buf = number(buf, end, rtop, spec); | ||
870 | } | ||
871 | |||
872 | rbot = cur; | ||
873 | } | ||
874 | return buf; | ||
875 | } | ||
876 | |||
877 | static noinline_for_stack | ||
797 | char *mac_address_string(char *buf, char *end, u8 *addr, | 878 | char *mac_address_string(char *buf, char *end, u8 *addr, |
798 | struct printf_spec spec, const char *fmt) | 879 | struct printf_spec spec, const char *fmt) |
799 | { | 880 | { |
@@ -1258,6 +1339,10 @@ int kptr_restrict __read_mostly; | |||
1258 | * - 'B' For backtraced symbolic direct pointers with offset | 1339 | * - 'B' For backtraced symbolic direct pointers with offset |
1259 | * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] | 1340 | * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] |
1260 | * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] | 1341 | * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] |
1342 | * - 'b[l]' For a bitmap, the number of bits is determined by the field | ||
1343 | * width which must be explicitly specified either as part of the | ||
1344 | * format string '%32b[l]' or through '%*b[l]', [l] selects | ||
1345 | * range-list format instead of hex format | ||
1261 | * - 'M' For a 6-byte MAC address, it prints the address in the | 1346 | * - 'M' For a 6-byte MAC address, it prints the address in the |
1262 | * usual colon-separated hex notation | 1347 | * usual colon-separated hex notation |
1263 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons | 1348 | * - '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, | |||
1354 | return resource_string(buf, end, ptr, spec, fmt); | 1439 | return resource_string(buf, end, ptr, spec, fmt); |
1355 | case 'h': | 1440 | case 'h': |
1356 | return hex_string(buf, end, ptr, spec, fmt); | 1441 | return hex_string(buf, end, ptr, spec, fmt); |
1442 | case 'b': | ||
1443 | switch (fmt[1]) { | ||
1444 | case 'l': | ||
1445 | return bitmap_list_string(buf, end, ptr, spec, fmt); | ||
1446 | default: | ||
1447 | return bitmap_string(buf, end, ptr, spec, fmt); | ||
1448 | } | ||
1357 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ | 1449 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ |
1358 | case 'm': /* Contiguous: 000102030405 */ | 1450 | case 'm': /* Contiguous: 000102030405 */ |
1359 | /* [mM]F (FDDI) */ | 1451 | /* [mM]F (FDDI) */ |
@@ -1689,6 +1781,8 @@ qualifier: | |||
1689 | * %pB output the name of a backtrace symbol with its offset | 1781 | * %pB output the name of a backtrace symbol with its offset |
1690 | * %pR output the address range in a struct resource with decoded flags | 1782 | * %pR output the address range in a struct resource with decoded flags |
1691 | * %pr output the address range in a struct resource with raw flags | 1783 | * %pr output the address range in a struct resource with raw flags |
1784 | * %pb output the bitmap with field width as the number of bits | ||
1785 | * %pbl output the bitmap as range list with field width as the number of bits | ||
1692 | * %pM output a 6-byte MAC address with colons | 1786 | * %pM output a 6-byte MAC address with colons |
1693 | * %pMR output a 6-byte MAC address with colons in reversed order | 1787 | * %pMR output a 6-byte MAC address with colons in reversed order |
1694 | * %pMF output a 6-byte MAC address with dashes | 1788 | * %pMF output a 6-byte MAC address with dashes |