|
@@ -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 **
|