sparc: Break up monolithic iommu table/lock into finer graularity pools and lock
[deliverable/linux.git] / lib / vsprintf.c
index b235c96167d32e80add7999f7833684abd54040b..3a1e0843f9a2b31e599a5ef9d33ebd0e81c5a208 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <stdarg.h>
+#include <linux/clk-provider.h>
 #include <linux/module.h>      /* for KSYM_SYMBOL_LEN */
 #include <linux/types.h>
 #include <linux/string.h>
@@ -340,11 +341,11 @@ int num_to_str(char *buf, int size, unsigned long long num)
        return len;
 }
 
-#define ZEROPAD        1               /* pad with zero */
-#define SIGN   2               /* unsigned/signed long */
+#define SIGN   1               /* unsigned/signed, must be 1 */
+#define LEFT   2               /* left justified */
 #define PLUS   4               /* show plus */
 #define SPACE  8               /* space if plus */
-#define LEFT   16              /* left justified */
+#define ZEROPAD        16              /* pad with zero, must be 16 == '0' - ' ' */
 #define SMALL  32              /* use lowercase in hex (must be 32 == 0x20) */
 #define SPECIAL        64              /* prefix hex with "0x", octal with "0" */
 
@@ -383,10 +384,7 @@ static noinline_for_stack
 char *number(char *buf, char *end, unsigned long long num,
             struct printf_spec spec)
 {
-       /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
-       static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
-
-       char tmp[66];
+       char tmp[3 * sizeof(num)];
        char sign;
        char locase;
        int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
@@ -422,12 +420,7 @@ char *number(char *buf, char *end, unsigned long long num,
        /* generate full string in tmp[], in reverse order */
        i = 0;
        if (num < spec.base)
-               tmp[i++] = digits[num] | locase;
-       /* Generic code, for any base:
-       else do {
-               tmp[i++] = (digits[do_div(num,base)] | locase);
-       } while (num != 0);
-       */
+               tmp[i++] = hex_asc_upper[num] | locase;
        else if (spec.base != 10) { /* 8 or 16 */
                int mask = spec.base - 1;
                int shift = 3;
@@ -435,7 +428,7 @@ char *number(char *buf, char *end, unsigned long long num,
                if (spec.base == 16)
                        shift = 4;
                do {
-                       tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
+                       tmp[i++] = (hex_asc_upper[((unsigned char)num) & mask] | locase);
                        num >>= shift;
                } while (num);
        } else { /* base 10 */
@@ -447,7 +440,7 @@ char *number(char *buf, char *end, unsigned long long num,
                spec.precision = i;
        /* leading space padding */
        spec.field_width -= spec.precision;
-       if (!(spec.flags & (ZEROPAD+LEFT))) {
+       if (!(spec.flags & (ZEROPAD | LEFT))) {
                while (--spec.field_width >= 0) {
                        if (buf < end)
                                *buf = ' ';
@@ -475,7 +468,8 @@ char *number(char *buf, char *end, unsigned long long num,
        }
        /* zero or space padding */
        if (!(spec.flags & LEFT)) {
-               char c = (spec.flags & ZEROPAD) ? '0' : ' ';
+               char c = ' ' + (spec.flags & ZEROPAD);
+               BUILD_BUG_ON(' ' + ZEROPAD != '0');
                while (--spec.field_width >= 0) {
                        if (buf < end)
                                *buf = c;
@@ -783,11 +777,19 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
        if (spec.field_width > 0)
                len = min_t(int, spec.field_width, 64);
 
-       for (i = 0; i < len && buf < end - 1; i++) {
-               buf = hex_byte_pack(buf, addr[i]);
+       for (i = 0; i < len; ++i) {
+               if (buf < end)
+                       *buf = hex_asc_hi(addr[i]);
+               ++buf;
+               if (buf < end)
+                       *buf = hex_asc_lo(addr[i]);
+               ++buf;
 
-               if (buf < end && separator && i != len - 1)
-                       *buf++ = separator;
+               if (separator && i != len - 1) {
+                       if (buf < end)
+                               *buf = separator;
+                       ++buf;
+               }
        }
 
        return buf;
@@ -1233,8 +1235,12 @@ char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
 
        len = spec.field_width < 0 ? 1 : spec.field_width;
 
-       /* Ignore the error. We print as many characters as we can */
-       string_escape_mem(addr, len, &buf, end - buf, flags, NULL);
+       /*
+        * string_escape_mem() writes as many characters as it can to
+        * the given buffer, and returns the total size of the output
+        * had the buffer been big enough.
+        */
+       buf += string_escape_mem(addr, len, buf, buf < end ? end - buf : 0, flags, NULL);
 
        return buf;
 }
@@ -1322,6 +1328,30 @@ char *address_val(char *buf, char *end, const void *addr,
        return number(buf, end, num, spec);
 }
 
+static noinline_for_stack
+char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
+           const char *fmt)
+{
+       if (!IS_ENABLED(CONFIG_HAVE_CLK) || !clk)
+               return string(buf, end, NULL, spec);
+
+       switch (fmt[1]) {
+       case 'r':
+               return number(buf, end, clk_get_rate(clk), spec);
+
+       case 'n':
+       default:
+#ifdef CONFIG_COMMON_CLK
+               return string(buf, end, __clk_get_name(clk), spec);
+#else
+               spec.base = 16;
+               spec.field_width = sizeof(unsigned long) * 2 + 2;
+               spec.flags |= SPECIAL | SMALL | ZEROPAD;
+               return number(buf, end, (unsigned long)clk, spec);
+#endif
+       }
+}
+
 int kptr_restrict __read_mostly;
 
 /*
@@ -1404,6 +1434,11 @@ int kptr_restrict __read_mostly;
  *           (default assumed to be phys_addr_t, passed by reference)
  * - 'd[234]' For a dentry name (optionally 2-4 last components)
  * - 'D[234]' Same as 'd' but for a struct file
+ * - 'C' For a clock, it prints the name (Common Clock Framework) or address
+ *       (legacy clock framework) of the clock
+ * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
+ *        (legacy clock framework) of the clock
+ * - 'Cr' For a clock, it prints the current rate of the clock
  *
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
@@ -1548,6 +1583,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                return address_val(buf, end, ptr, spec, fmt);
        case 'd':
                return dentry_name(buf, end, ptr, spec, fmt);
+       case 'C':
+               return clock(buf, end, ptr, spec, fmt);
        case 'D':
                return dentry_name(buf, end,
                                   ((const struct file *)ptr)->f_path.dentry,
@@ -1738,29 +1775,21 @@ qualifier:
        if (spec->qualifier == 'L')
                spec->type = FORMAT_TYPE_LONG_LONG;
        else if (spec->qualifier == 'l') {
-               if (spec->flags & SIGN)
-                       spec->type = FORMAT_TYPE_LONG;
-               else
-                       spec->type = FORMAT_TYPE_ULONG;
+               BUILD_BUG_ON(FORMAT_TYPE_ULONG + SIGN != FORMAT_TYPE_LONG);
+               spec->type = FORMAT_TYPE_ULONG + (spec->flags & SIGN);
        } else if (_tolower(spec->qualifier) == 'z') {
                spec->type = FORMAT_TYPE_SIZE_T;
        } else if (spec->qualifier == 't') {
                spec->type = FORMAT_TYPE_PTRDIFF;
        } else if (spec->qualifier == 'H') {
-               if (spec->flags & SIGN)
-                       spec->type = FORMAT_TYPE_BYTE;
-               else
-                       spec->type = FORMAT_TYPE_UBYTE;
+               BUILD_BUG_ON(FORMAT_TYPE_UBYTE + SIGN != FORMAT_TYPE_BYTE);
+               spec->type = FORMAT_TYPE_UBYTE + (spec->flags & SIGN);
        } else if (spec->qualifier == 'h') {
-               if (spec->flags & SIGN)
-                       spec->type = FORMAT_TYPE_SHORT;
-               else
-                       spec->type = FORMAT_TYPE_USHORT;
+               BUILD_BUG_ON(FORMAT_TYPE_USHORT + SIGN != FORMAT_TYPE_SHORT);
+               spec->type = FORMAT_TYPE_USHORT + (spec->flags & SIGN);
        } else {
-               if (spec->flags & SIGN)
-                       spec->type = FORMAT_TYPE_INT;
-               else
-                       spec->type = FORMAT_TYPE_UINT;
+               BUILD_BUG_ON(FORMAT_TYPE_UINT + SIGN != FORMAT_TYPE_INT);
+               spec->type = FORMAT_TYPE_UINT + (spec->flags & SIGN);
        }
 
        return ++fmt - start;
@@ -1800,6 +1829,11 @@ qualifier:
  * %*pE[achnops] print an escaped buffer
  * %*ph[CDN] a variable-length hex string with a separator (supports up to 64
  *           bytes of the input)
+ * %pC output the name (Common Clock Framework) or address (legacy clock
+ *     framework) of a clock
+ * %pCn output the name (Common Clock Framework) or address (legacy clock
+ *      framework) of a clock
+ * %pCr output the current rate of a clock
  * %n is ignored
  *
  * ** Please update Documentation/printk-formats.txt when making changes **
This page took 0.028679 seconds and 5 git commands to generate.