aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-15 19:39:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-15 19:39:15 -0400
commiteea3a00264cf243a28e4331566ce67b86059339d (patch)
tree487f16389e0dfa32e9caa7604d1274a7dcda8f04 /lib
parente7c82412433a8039616c7314533a0a1c025d99bf (diff)
parente693d73c20ffdb06840c9378f367bad849ac0d5d (diff)
Merge branch 'akpm' (patches from Andrew)
Merge second patchbomb from Andrew Morton: - the rest of MM - various misc bits - add ability to run /sbin/reboot at reboot time - printk/vsprintf changes - fiddle with seq_printf() return value * akpm: (114 commits) parisc: remove use of seq_printf return value lru_cache: remove use of seq_printf return value tracing: remove use of seq_printf return value cgroup: remove use of seq_printf return value proc: remove use of seq_printf return value s390: remove use of seq_printf return value cris fasttimer: remove use of seq_printf return value cris: remove use of seq_printf return value openrisc: remove use of seq_printf return value ARM: plat-pxa: remove use of seq_printf return value nios2: cpuinfo: remove use of seq_printf return value microblaze: mb: remove use of seq_printf return value ipc: remove use of seq_printf return value rtc: remove use of seq_printf return value power: wakeup: remove use of seq_printf return value x86: mtrr: if: remove use of seq_printf return value linux/bitmap.h: improve BITMAP_{LAST,FIRST}_WORD_MASK MAINTAINERS: CREDITS: remove Stefano Brivio from B43 .mailmap: add Ricardo Ribalda CREDITS: add Ricardo Ribalda Delgado ...
Diffstat (limited to 'lib')
-rw-r--r--lib/lru_cache.c9
-rw-r--r--lib/string_helpers.c193
-rw-r--r--lib/test-hexdump.c8
-rw-r--r--lib/test-string_helpers.c40
-rw-r--r--lib/vsprintf.c110
5 files changed, 181 insertions, 179 deletions
diff --git a/lib/lru_cache.c b/lib/lru_cache.c
index 852c81e3ba9a..028f5d996eef 100644
--- a/lib/lru_cache.c
+++ b/lib/lru_cache.c
@@ -247,10 +247,11 @@ size_t lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc)
247 * progress) and "changed", when this in fact lead to an successful 247 * progress) and "changed", when this in fact lead to an successful
248 * update of the cache. 248 * update of the cache.
249 */ 249 */
250 return seq_printf(seq, "\t%s: used:%u/%u " 250 seq_printf(seq, "\t%s: used:%u/%u hits:%lu misses:%lu starving:%lu locked:%lu changed:%lu\n",
251 "hits:%lu misses:%lu starving:%lu locked:%lu changed:%lu\n", 251 lc->name, lc->used, lc->nr_elements,
252 lc->name, lc->used, lc->nr_elements, 252 lc->hits, lc->misses, lc->starving, lc->locked, lc->changed);
253 lc->hits, lc->misses, lc->starving, lc->locked, lc->changed); 253
254 return 0;
254} 255}
255 256
256static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr) 257static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr)
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 8f8c4417f228..1826c7407258 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -239,29 +239,21 @@ int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
239} 239}
240EXPORT_SYMBOL(string_unescape); 240EXPORT_SYMBOL(string_unescape);
241 241
242static int escape_passthrough(unsigned char c, char **dst, size_t *osz) 242static bool escape_passthrough(unsigned char c, char **dst, char *end)
243{ 243{
244 char *out = *dst; 244 char *out = *dst;
245 245
246 if (*osz < 1) 246 if (out < end)
247 return -ENOMEM; 247 *out = c;
248 248 *dst = out + 1;
249 *out++ = c; 249 return true;
250
251 *dst = out;
252 *osz -= 1;
253
254 return 1;
255} 250}
256 251
257static int escape_space(unsigned char c, char **dst, size_t *osz) 252static bool escape_space(unsigned char c, char **dst, char *end)
258{ 253{
259 char *out = *dst; 254 char *out = *dst;
260 unsigned char to; 255 unsigned char to;
261 256
262 if (*osz < 2)
263 return -ENOMEM;
264
265 switch (c) { 257 switch (c) {
266 case '\n': 258 case '\n':
267 to = 'n'; 259 to = 'n';
@@ -279,26 +271,25 @@ static int escape_space(unsigned char c, char **dst, size_t *osz)
279 to = 'f'; 271 to = 'f';
280 break; 272 break;
281 default: 273 default:
282 return 0; 274 return false;
283 } 275 }
284 276
285 *out++ = '\\'; 277 if (out < end)
286 *out++ = to; 278 *out = '\\';
279 ++out;
280 if (out < end)
281 *out = to;
282 ++out;
287 283
288 *dst = out; 284 *dst = out;
289 *osz -= 2; 285 return true;
290
291 return 1;
292} 286}
293 287
294static int escape_special(unsigned char c, char **dst, size_t *osz) 288static bool escape_special(unsigned char c, char **dst, char *end)
295{ 289{
296 char *out = *dst; 290 char *out = *dst;
297 unsigned char to; 291 unsigned char to;
298 292
299 if (*osz < 2)
300 return -ENOMEM;
301
302 switch (c) { 293 switch (c) {
303 case '\\': 294 case '\\':
304 to = '\\'; 295 to = '\\';
@@ -310,71 +301,78 @@ static int escape_special(unsigned char c, char **dst, size_t *osz)
310 to = 'e'; 301 to = 'e';
311 break; 302 break;
312 default: 303 default:
313 return 0; 304 return false;
314 } 305 }
315 306
316 *out++ = '\\'; 307 if (out < end)
317 *out++ = to; 308 *out = '\\';
309 ++out;
310 if (out < end)
311 *out = to;
312 ++out;
318 313
319 *dst = out; 314 *dst = out;
320 *osz -= 2; 315 return true;
321
322 return 1;
323} 316}
324 317
325static int escape_null(unsigned char c, char **dst, size_t *osz) 318static bool escape_null(unsigned char c, char **dst, char *end)
326{ 319{
327 char *out = *dst; 320 char *out = *dst;
328 321
329 if (*osz < 2)
330 return -ENOMEM;
331
332 if (c) 322 if (c)
333 return 0; 323 return false;
334 324
335 *out++ = '\\'; 325 if (out < end)
336 *out++ = '0'; 326 *out = '\\';
327 ++out;
328 if (out < end)
329 *out = '0';
330 ++out;
337 331
338 *dst = out; 332 *dst = out;
339 *osz -= 2; 333 return true;
340
341 return 1;
342} 334}
343 335
344static int escape_octal(unsigned char c, char **dst, size_t *osz) 336static bool escape_octal(unsigned char c, char **dst, char *end)
345{ 337{
346 char *out = *dst; 338 char *out = *dst;
347 339
348 if (*osz < 4) 340 if (out < end)
349 return -ENOMEM; 341 *out = '\\';
350 342 ++out;
351 *out++ = '\\'; 343 if (out < end)
352 *out++ = ((c >> 6) & 0x07) + '0'; 344 *out = ((c >> 6) & 0x07) + '0';
353 *out++ = ((c >> 3) & 0x07) + '0'; 345 ++out;
354 *out++ = ((c >> 0) & 0x07) + '0'; 346 if (out < end)
347 *out = ((c >> 3) & 0x07) + '0';
348 ++out;
349 if (out < end)
350 *out = ((c >> 0) & 0x07) + '0';
351 ++out;
355 352
356 *dst = out; 353 *dst = out;
357 *osz -= 4; 354 return true;
358
359 return 1;
360} 355}
361 356
362static int escape_hex(unsigned char c, char **dst, size_t *osz) 357static bool escape_hex(unsigned char c, char **dst, char *end)
363{ 358{
364 char *out = *dst; 359 char *out = *dst;
365 360
366 if (*osz < 4) 361 if (out < end)
367 return -ENOMEM; 362 *out = '\\';
368 363 ++out;
369 *out++ = '\\'; 364 if (out < end)
370 *out++ = 'x'; 365 *out = 'x';
371 *out++ = hex_asc_hi(c); 366 ++out;
372 *out++ = hex_asc_lo(c); 367 if (out < end)
368 *out = hex_asc_hi(c);
369 ++out;
370 if (out < end)
371 *out = hex_asc_lo(c);
372 ++out;
373 373
374 *dst = out; 374 *dst = out;
375 *osz -= 4; 375 return true;
376
377 return 1;
378} 376}
379 377
380/** 378/**
@@ -426,19 +424,17 @@ static int escape_hex(unsigned char c, char **dst, size_t *osz)
426 * it if needs. 424 * it if needs.
427 * 425 *
428 * Return: 426 * Return:
429 * The amount of the characters processed to the destination buffer, or 427 * The total size of the escaped output that would be generated for
430 * %-ENOMEM if the size of buffer is not enough to put an escaped character is 428 * the given input and flags. To check whether the output was
431 * returned. 429 * truncated, compare the return value to osz. There is room left in
432 * 430 * dst for a '\0' terminator if and only if ret < osz.
433 * Even in the case of error @dst pointer will be updated to point to the byte
434 * after the last processed character.
435 */ 431 */
436int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, 432int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
437 unsigned int flags, const char *esc) 433 unsigned int flags, const char *esc)
438{ 434{
439 char *out = *dst, *p = out; 435 char *p = dst;
436 char *end = p + osz;
440 bool is_dict = esc && *esc; 437 bool is_dict = esc && *esc;
441 int ret = 0;
442 438
443 while (isz--) { 439 while (isz--) {
444 unsigned char c = *src++; 440 unsigned char c = *src++;
@@ -458,55 +454,26 @@ int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz,
458 (is_dict && !strchr(esc, c))) { 454 (is_dict && !strchr(esc, c))) {
459 /* do nothing */ 455 /* do nothing */
460 } else { 456 } else {
461 if (flags & ESCAPE_SPACE) { 457 if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
462 ret = escape_space(c, &p, &osz); 458 continue;
463 if (ret < 0) 459
464 break; 460 if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end))
465 if (ret > 0) 461 continue;
466 continue; 462
467 } 463 if (flags & ESCAPE_NULL && escape_null(c, &p, end))
468 464 continue;
469 if (flags & ESCAPE_SPECIAL) {
470 ret = escape_special(c, &p, &osz);
471 if (ret < 0)
472 break;
473 if (ret > 0)
474 continue;
475 }
476
477 if (flags & ESCAPE_NULL) {
478 ret = escape_null(c, &p, &osz);
479 if (ret < 0)
480 break;
481 if (ret > 0)
482 continue;
483 }
484 465
485 /* ESCAPE_OCTAL and ESCAPE_HEX always go last */ 466 /* ESCAPE_OCTAL and ESCAPE_HEX always go last */
486 if (flags & ESCAPE_OCTAL) { 467 if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
487 ret = escape_octal(c, &p, &osz);
488 if (ret < 0)
489 break;
490 continue; 468 continue;
491 } 469
492 if (flags & ESCAPE_HEX) { 470 if (flags & ESCAPE_HEX && escape_hex(c, &p, end))
493 ret = escape_hex(c, &p, &osz);
494 if (ret < 0)
495 break;
496 continue; 471 continue;
497 }
498 } 472 }
499 473
500 ret = escape_passthrough(c, &p, &osz); 474 escape_passthrough(c, &p, end);
501 if (ret < 0)
502 break;
503 } 475 }
504 476
505 *dst = p; 477 return p - dst;
506
507 if (ret < 0)
508 return ret;
509
510 return p - out;
511} 478}
512EXPORT_SYMBOL(string_escape_mem); 479EXPORT_SYMBOL(string_escape_mem);
diff --git a/lib/test-hexdump.c b/lib/test-hexdump.c
index daf29a390a89..9846ff7428b3 100644
--- a/lib/test-hexdump.c
+++ b/lib/test-hexdump.c
@@ -18,26 +18,26 @@ static const unsigned char data_b[] = {
18 18
19static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C..."; 19static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C...";
20 20
21static const char *test_data_1_le[] __initconst = { 21static const char * const test_data_1_le[] __initconst = {
22 "be", "32", "db", "7b", "0a", "18", "93", "b2", 22 "be", "32", "db", "7b", "0a", "18", "93", "b2",
23 "70", "ba", "c4", "24", "7d", "83", "34", "9b", 23 "70", "ba", "c4", "24", "7d", "83", "34", "9b",
24 "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9", 24 "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9",
25 "4c", "d1", "19", "99", "43", "b1", "af", "0c", 25 "4c", "d1", "19", "99", "43", "b1", "af", "0c",
26}; 26};
27 27
28static const char *test_data_2_le[] __initconst = { 28static const char *test_data_2_le[] __initdata = {
29 "32be", "7bdb", "180a", "b293", 29 "32be", "7bdb", "180a", "b293",
30 "ba70", "24c4", "837d", "9b34", 30 "ba70", "24c4", "837d", "9b34",
31 "9ca6", "ad31", "0f9c", "e9ac", 31 "9ca6", "ad31", "0f9c", "e9ac",
32 "d14c", "9919", "b143", "0caf", 32 "d14c", "9919", "b143", "0caf",
33}; 33};
34 34
35static const char *test_data_4_le[] __initconst = { 35static const char *test_data_4_le[] __initdata = {
36 "7bdb32be", "b293180a", "24c4ba70", "9b34837d", 36 "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
37 "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143", 37 "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
38}; 38};
39 39
40static const char *test_data_8_le[] __initconst = { 40static const char *test_data_8_le[] __initdata = {
41 "b293180a7bdb32be", "9b34837d24c4ba70", 41 "b293180a7bdb32be", "9b34837d24c4ba70",
42 "e9ac0f9cad319ca6", "0cafb1439919d14c", 42 "e9ac0f9cad319ca6", "0cafb1439919d14c",
43}; 43};
diff --git a/lib/test-string_helpers.c b/lib/test-string_helpers.c
index ab0d30e1e18f..8e376efd88a4 100644
--- a/lib/test-string_helpers.c
+++ b/lib/test-string_helpers.c
@@ -260,16 +260,28 @@ static __init const char *test_string_find_match(const struct test_string_2 *s2,
260 return NULL; 260 return NULL;
261} 261}
262 262
263static __init void
264test_string_escape_overflow(const char *in, int p, unsigned int flags, const char *esc,
265 int q_test, const char *name)
266{
267 int q_real;
268
269 q_real = string_escape_mem(in, p, NULL, 0, flags, esc);
270 if (q_real != q_test)
271 pr_warn("Test '%s' failed: flags = %u, osz = 0, expected %d, got %d\n",
272 name, flags, q_test, q_real);
273}
274
263static __init void test_string_escape(const char *name, 275static __init void test_string_escape(const char *name,
264 const struct test_string_2 *s2, 276 const struct test_string_2 *s2,
265 unsigned int flags, const char *esc) 277 unsigned int flags, const char *esc)
266{ 278{
267 int q_real = 512; 279 size_t out_size = 512;
268 char *out_test = kmalloc(q_real, GFP_KERNEL); 280 char *out_test = kmalloc(out_size, GFP_KERNEL);
269 char *out_real = kmalloc(q_real, GFP_KERNEL); 281 char *out_real = kmalloc(out_size, GFP_KERNEL);
270 char *in = kmalloc(256, GFP_KERNEL); 282 char *in = kmalloc(256, GFP_KERNEL);
271 char *buf = out_real;
272 int p = 0, q_test = 0; 283 int p = 0, q_test = 0;
284 int q_real;
273 285
274 if (!out_test || !out_real || !in) 286 if (!out_test || !out_real || !in)
275 goto out; 287 goto out;
@@ -301,29 +313,19 @@ static __init void test_string_escape(const char *name,
301 q_test += len; 313 q_test += len;
302 } 314 }
303 315
304 q_real = string_escape_mem(in, p, &buf, q_real, flags, esc); 316 q_real = string_escape_mem(in, p, out_real, out_size, flags, esc);
305 317
306 test_string_check_buf(name, flags, in, p, out_real, q_real, out_test, 318 test_string_check_buf(name, flags, in, p, out_real, q_real, out_test,
307 q_test); 319 q_test);
320
321 test_string_escape_overflow(in, p, flags, esc, q_test, name);
322
308out: 323out:
309 kfree(in); 324 kfree(in);
310 kfree(out_real); 325 kfree(out_real);
311 kfree(out_test); 326 kfree(out_test);
312} 327}
313 328
314static __init void test_string_escape_nomem(void)
315{
316 char *in = "\eb \\C\007\"\x90\r]";
317 char out[64], *buf = out;
318 int rc = -ENOMEM, ret;
319
320 ret = string_escape_str_any_np(in, &buf, strlen(in), NULL);
321 if (ret == rc)
322 return;
323
324 pr_err("Test 'escape nomem' failed: got %d instead of %d\n", ret, rc);
325}
326
327static int __init test_string_helpers_init(void) 329static int __init test_string_helpers_init(void)
328{ 330{
329 unsigned int i; 331 unsigned int i;
@@ -342,8 +344,6 @@ static int __init test_string_helpers_init(void)
342 for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++) 344 for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++)
343 test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1); 345 test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1);
344 346
345 test_string_escape_nomem();
346
347 return -EINVAL; 347 return -EINVAL;
348} 348}
349module_init(test_string_helpers_init); 349module_init(test_string_helpers_init);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index b235c96167d3..3a1e0843f9a2 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -17,6 +17,7 @@
17 */ 17 */
18 18
19#include <stdarg.h> 19#include <stdarg.h>
20#include <linux/clk-provider.h>
20#include <linux/module.h> /* for KSYM_SYMBOL_LEN */ 21#include <linux/module.h> /* for KSYM_SYMBOL_LEN */
21#include <linux/types.h> 22#include <linux/types.h>
22#include <linux/string.h> 23#include <linux/string.h>
@@ -340,11 +341,11 @@ int num_to_str(char *buf, int size, unsigned long long num)
340 return len; 341 return len;
341} 342}
342 343
343#define ZEROPAD 1 /* pad with zero */ 344#define SIGN 1 /* unsigned/signed, must be 1 */
344#define SIGN 2 /* unsigned/signed long */ 345#define LEFT 2 /* left justified */
345#define PLUS 4 /* show plus */ 346#define PLUS 4 /* show plus */
346#define SPACE 8 /* space if plus */ 347#define SPACE 8 /* space if plus */
347#define LEFT 16 /* left justified */ 348#define ZEROPAD 16 /* pad with zero, must be 16 == '0' - ' ' */
348#define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */ 349#define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */
349#define SPECIAL 64 /* prefix hex with "0x", octal with "0" */ 350#define SPECIAL 64 /* prefix hex with "0x", octal with "0" */
350 351
@@ -383,10 +384,7 @@ static noinline_for_stack
383char *number(char *buf, char *end, unsigned long long num, 384char *number(char *buf, char *end, unsigned long long num,
384 struct printf_spec spec) 385 struct printf_spec spec)
385{ 386{
386 /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ 387 char tmp[3 * sizeof(num)];
387 static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
388
389 char tmp[66];
390 char sign; 388 char sign;
391 char locase; 389 char locase;
392 int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10); 390 int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
@@ -422,12 +420,7 @@ char *number(char *buf, char *end, unsigned long long num,
422 /* generate full string in tmp[], in reverse order */ 420 /* generate full string in tmp[], in reverse order */
423 i = 0; 421 i = 0;
424 if (num < spec.base) 422 if (num < spec.base)
425 tmp[i++] = digits[num] | locase; 423 tmp[i++] = hex_asc_upper[num] | locase;
426 /* Generic code, for any base:
427 else do {
428 tmp[i++] = (digits[do_div(num,base)] | locase);
429 } while (num != 0);
430 */
431 else if (spec.base != 10) { /* 8 or 16 */ 424 else if (spec.base != 10) { /* 8 or 16 */
432 int mask = spec.base - 1; 425 int mask = spec.base - 1;
433 int shift = 3; 426 int shift = 3;
@@ -435,7 +428,7 @@ char *number(char *buf, char *end, unsigned long long num,
435 if (spec.base == 16) 428 if (spec.base == 16)
436 shift = 4; 429 shift = 4;
437 do { 430 do {
438 tmp[i++] = (digits[((unsigned char)num) & mask] | locase); 431 tmp[i++] = (hex_asc_upper[((unsigned char)num) & mask] | locase);
439 num >>= shift; 432 num >>= shift;
440 } while (num); 433 } while (num);
441 } else { /* base 10 */ 434 } else { /* base 10 */
@@ -447,7 +440,7 @@ char *number(char *buf, char *end, unsigned long long num,
447 spec.precision = i; 440 spec.precision = i;
448 /* leading space padding */ 441 /* leading space padding */
449 spec.field_width -= spec.precision; 442 spec.field_width -= spec.precision;
450 if (!(spec.flags & (ZEROPAD+LEFT))) { 443 if (!(spec.flags & (ZEROPAD | LEFT))) {
451 while (--spec.field_width >= 0) { 444 while (--spec.field_width >= 0) {
452 if (buf < end) 445 if (buf < end)
453 *buf = ' '; 446 *buf = ' ';
@@ -475,7 +468,8 @@ char *number(char *buf, char *end, unsigned long long num,
475 } 468 }
476 /* zero or space padding */ 469 /* zero or space padding */
477 if (!(spec.flags & LEFT)) { 470 if (!(spec.flags & LEFT)) {
478 char c = (spec.flags & ZEROPAD) ? '0' : ' '; 471 char c = ' ' + (spec.flags & ZEROPAD);
472 BUILD_BUG_ON(' ' + ZEROPAD != '0');
479 while (--spec.field_width >= 0) { 473 while (--spec.field_width >= 0) {
480 if (buf < end) 474 if (buf < end)
481 *buf = c; 475 *buf = c;
@@ -783,11 +777,19 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
783 if (spec.field_width > 0) 777 if (spec.field_width > 0)
784 len = min_t(int, spec.field_width, 64); 778 len = min_t(int, spec.field_width, 64);
785 779
786 for (i = 0; i < len && buf < end - 1; i++) { 780 for (i = 0; i < len; ++i) {
787 buf = hex_byte_pack(buf, addr[i]); 781 if (buf < end)
782 *buf = hex_asc_hi(addr[i]);
783 ++buf;
784 if (buf < end)
785 *buf = hex_asc_lo(addr[i]);
786 ++buf;
788 787
789 if (buf < end && separator && i != len - 1) 788 if (separator && i != len - 1) {
790 *buf++ = separator; 789 if (buf < end)
790 *buf = separator;
791 ++buf;
792 }
791 } 793 }
792 794
793 return buf; 795 return buf;
@@ -1233,8 +1235,12 @@ char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
1233 1235
1234 len = spec.field_width < 0 ? 1 : spec.field_width; 1236 len = spec.field_width < 0 ? 1 : spec.field_width;
1235 1237
1236 /* Ignore the error. We print as many characters as we can */ 1238 /*
1237 string_escape_mem(addr, len, &buf, end - buf, flags, NULL); 1239 * string_escape_mem() writes as many characters as it can to
1240 * the given buffer, and returns the total size of the output
1241 * had the buffer been big enough.
1242 */
1243 buf += string_escape_mem(addr, len, buf, buf < end ? end - buf : 0, flags, NULL);
1238 1244
1239 return buf; 1245 return buf;
1240} 1246}
@@ -1322,6 +1328,30 @@ char *address_val(char *buf, char *end, const void *addr,
1322 return number(buf, end, num, spec); 1328 return number(buf, end, num, spec);
1323} 1329}
1324 1330
1331static noinline_for_stack
1332char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
1333 const char *fmt)
1334{
1335 if (!IS_ENABLED(CONFIG_HAVE_CLK) || !clk)
1336 return string(buf, end, NULL, spec);
1337
1338 switch (fmt[1]) {
1339 case 'r':
1340 return number(buf, end, clk_get_rate(clk), spec);
1341
1342 case 'n':
1343 default:
1344#ifdef CONFIG_COMMON_CLK
1345 return string(buf, end, __clk_get_name(clk), spec);
1346#else
1347 spec.base = 16;
1348 spec.field_width = sizeof(unsigned long) * 2 + 2;
1349 spec.flags |= SPECIAL | SMALL | ZEROPAD;
1350 return number(buf, end, (unsigned long)clk, spec);
1351#endif
1352 }
1353}
1354
1325int kptr_restrict __read_mostly; 1355int kptr_restrict __read_mostly;
1326 1356
1327/* 1357/*
@@ -1404,6 +1434,11 @@ int kptr_restrict __read_mostly;
1404 * (default assumed to be phys_addr_t, passed by reference) 1434 * (default assumed to be phys_addr_t, passed by reference)
1405 * - 'd[234]' For a dentry name (optionally 2-4 last components) 1435 * - 'd[234]' For a dentry name (optionally 2-4 last components)
1406 * - 'D[234]' Same as 'd' but for a struct file 1436 * - 'D[234]' Same as 'd' but for a struct file
1437 * - 'C' For a clock, it prints the name (Common Clock Framework) or address
1438 * (legacy clock framework) of the clock
1439 * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
1440 * (legacy clock framework) of the clock
1441 * - 'Cr' For a clock, it prints the current rate of the clock
1407 * 1442 *
1408 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 1443 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
1409 * function pointers are really function descriptors, which contain a 1444 * function pointers are really function descriptors, which contain a
@@ -1548,6 +1583,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1548 return address_val(buf, end, ptr, spec, fmt); 1583 return address_val(buf, end, ptr, spec, fmt);
1549 case 'd': 1584 case 'd':
1550 return dentry_name(buf, end, ptr, spec, fmt); 1585 return dentry_name(buf, end, ptr, spec, fmt);
1586 case 'C':
1587 return clock(buf, end, ptr, spec, fmt);
1551 case 'D': 1588 case 'D':
1552 return dentry_name(buf, end, 1589 return dentry_name(buf, end,
1553 ((const struct file *)ptr)->f_path.dentry, 1590 ((const struct file *)ptr)->f_path.dentry,
@@ -1738,29 +1775,21 @@ qualifier:
1738 if (spec->qualifier == 'L') 1775 if (spec->qualifier == 'L')
1739 spec->type = FORMAT_TYPE_LONG_LONG; 1776 spec->type = FORMAT_TYPE_LONG_LONG;
1740 else if (spec->qualifier == 'l') { 1777 else if (spec->qualifier == 'l') {
1741 if (spec->flags & SIGN) 1778 BUILD_BUG_ON(FORMAT_TYPE_ULONG + SIGN != FORMAT_TYPE_LONG);
1742 spec->type = FORMAT_TYPE_LONG; 1779 spec->type = FORMAT_TYPE_ULONG + (spec->flags & SIGN);
1743 else
1744 spec->type = FORMAT_TYPE_ULONG;
1745 } else if (_tolower(spec->qualifier) == 'z') { 1780 } else if (_tolower(spec->qualifier) == 'z') {
1746 spec->type = FORMAT_TYPE_SIZE_T; 1781 spec->type = FORMAT_TYPE_SIZE_T;
1747 } else if (spec->qualifier == 't') { 1782 } else if (spec->qualifier == 't') {
1748 spec->type = FORMAT_TYPE_PTRDIFF; 1783 spec->type = FORMAT_TYPE_PTRDIFF;
1749 } else if (spec->qualifier == 'H') { 1784 } else if (spec->qualifier == 'H') {
1750 if (spec->flags & SIGN) 1785 BUILD_BUG_ON(FORMAT_TYPE_UBYTE + SIGN != FORMAT_TYPE_BYTE);
1751 spec->type = FORMAT_TYPE_BYTE; 1786 spec->type = FORMAT_TYPE_UBYTE + (spec->flags & SIGN);
1752 else
1753 spec->type = FORMAT_TYPE_UBYTE;
1754 } else if (spec->qualifier == 'h') { 1787 } else if (spec->qualifier == 'h') {
1755 if (spec->flags & SIGN) 1788 BUILD_BUG_ON(FORMAT_TYPE_USHORT + SIGN != FORMAT_TYPE_SHORT);
1756 spec->type = FORMAT_TYPE_SHORT; 1789 spec->type = FORMAT_TYPE_USHORT + (spec->flags & SIGN);
1757 else
1758 spec->type = FORMAT_TYPE_USHORT;
1759 } else { 1790 } else {
1760 if (spec->flags & SIGN) 1791 BUILD_BUG_ON(FORMAT_TYPE_UINT + SIGN != FORMAT_TYPE_INT);
1761 spec->type = FORMAT_TYPE_INT; 1792 spec->type = FORMAT_TYPE_UINT + (spec->flags & SIGN);
1762 else
1763 spec->type = FORMAT_TYPE_UINT;
1764 } 1793 }
1765 1794
1766 return ++fmt - start; 1795 return ++fmt - start;
@@ -1800,6 +1829,11 @@ qualifier:
1800 * %*pE[achnops] print an escaped buffer 1829 * %*pE[achnops] print an escaped buffer
1801 * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 1830 * %*ph[CDN] a variable-length hex string with a separator (supports up to 64
1802 * bytes of the input) 1831 * bytes of the input)
1832 * %pC output the name (Common Clock Framework) or address (legacy clock
1833 * framework) of a clock
1834 * %pCn output the name (Common Clock Framework) or address (legacy clock
1835 * framework) of a clock
1836 * %pCr output the current rate of a clock
1803 * %n is ignored 1837 * %n is ignored
1804 * 1838 *
1805 * ** Please update Documentation/printk-formats.txt when making changes ** 1839 * ** Please update Documentation/printk-formats.txt when making changes **