diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-07 13:37:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-07 13:37:54 -0400 |
commit | dd6ec12f3bf83ca3c4e712a9f35960aec779f6f9 (patch) | |
tree | 8b6f9f187eb0ae621a64798270c420143c698484 /lib/vsprintf.c | |
parent | 21c19bc7ee256094aba74af8d91a824da4bc36af (diff) | |
parent | a4485b545e2fad4d65732cb7c60089bf4246de5c (diff) |
Merge tag 'devicetree-for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull DeviceTree updates from Rob Herring:
- vsprintf format specifier %pOF for device_node's. This will enable us
to stop storing the full node names. Conversion of users will happen
next cycle.
- Update documentation to point to DT specification instead of ePAPR.
- Split out graph and property functions to a separate file.
- New of-graph functions for ALSA
- Add vendor prefixes for RISC-V, Linksys, iWave Systems, Roofull,
Itead, and BananaPi.
- Improve dtx_diff utility filename printing.
* tag 'devicetree-for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (32 commits)
of: document /sys/firmware/fdt
dt-bindings: Add RISC-V vendor prefix
vsprintf: Add %p extension "%pOF" for device tree
of: find_node_by_full_name rewrite to compare each level
of: use kbasename instead of open coding
dt-bindings: thermal: add file extension to brcm,ns-thermal
of: update ePAPR references to point to Devicetree Specification
scripts/dtc: dtx_diff - Show real file names in diff header
of: detect invalid phandle in overlay
of: be consistent in form of file mode
of: make __of_attach_node() static
of: address.c header comment typo
of: fdt.c header comment typo
of: make of_fdt_is_compatible() static
dt-bindings: display-timing.txt convert non-ascii characters to ascii
Documentation: remove overlay-notes reference to non-existent file
dt-bindings: usb: exynos-usb: Add missing required VDD properties
dt-bindings: Add vendor prefix for Linksys
MAINTAINERS: add device tree ABI documentation file
of: Add vendor prefix for iWave Systems Technologies Pvt. Ltd
...
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 9f37d6208e99..86c3385b9eb3 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/dcache.h> | 31 | #include <linux/dcache.h> |
32 | #include <linux/cred.h> | 32 | #include <linux/cred.h> |
33 | #include <linux/uuid.h> | 33 | #include <linux/uuid.h> |
34 | #include <linux/of.h> | ||
34 | #include <net/addrconf.h> | 35 | #include <net/addrconf.h> |
35 | #ifdef CONFIG_BLOCK | 36 | #ifdef CONFIG_BLOCK |
36 | #include <linux/blkdev.h> | 37 | #include <linux/blkdev.h> |
@@ -1470,6 +1471,126 @@ char *flags_string(char *buf, char *end, void *flags_ptr, const char *fmt) | |||
1470 | return format_flags(buf, end, flags, names); | 1471 | return format_flags(buf, end, flags, names); |
1471 | } | 1472 | } |
1472 | 1473 | ||
1474 | static const char *device_node_name_for_depth(const struct device_node *np, int depth) | ||
1475 | { | ||
1476 | for ( ; np && depth; depth--) | ||
1477 | np = np->parent; | ||
1478 | |||
1479 | return kbasename(np->full_name); | ||
1480 | } | ||
1481 | |||
1482 | static noinline_for_stack | ||
1483 | char *device_node_gen_full_name(const struct device_node *np, char *buf, char *end) | ||
1484 | { | ||
1485 | int depth; | ||
1486 | const struct device_node *parent = np->parent; | ||
1487 | static const struct printf_spec strspec = { | ||
1488 | .field_width = -1, | ||
1489 | .precision = -1, | ||
1490 | }; | ||
1491 | |||
1492 | /* special case for root node */ | ||
1493 | if (!parent) | ||
1494 | return string(buf, end, "/", strspec); | ||
1495 | |||
1496 | for (depth = 0; parent->parent; depth++) | ||
1497 | parent = parent->parent; | ||
1498 | |||
1499 | for ( ; depth >= 0; depth--) { | ||
1500 | buf = string(buf, end, "/", strspec); | ||
1501 | buf = string(buf, end, device_node_name_for_depth(np, depth), | ||
1502 | strspec); | ||
1503 | } | ||
1504 | return buf; | ||
1505 | } | ||
1506 | |||
1507 | static noinline_for_stack | ||
1508 | char *device_node_string(char *buf, char *end, struct device_node *dn, | ||
1509 | struct printf_spec spec, const char *fmt) | ||
1510 | { | ||
1511 | char tbuf[sizeof("xxxx") + 1]; | ||
1512 | const char *p; | ||
1513 | int ret; | ||
1514 | char *buf_start = buf; | ||
1515 | struct property *prop; | ||
1516 | bool has_mult, pass; | ||
1517 | static const struct printf_spec num_spec = { | ||
1518 | .flags = SMALL, | ||
1519 | .field_width = -1, | ||
1520 | .precision = -1, | ||
1521 | .base = 10, | ||
1522 | }; | ||
1523 | |||
1524 | struct printf_spec str_spec = spec; | ||
1525 | str_spec.field_width = -1; | ||
1526 | |||
1527 | if (!IS_ENABLED(CONFIG_OF)) | ||
1528 | return string(buf, end, "(!OF)", spec); | ||
1529 | |||
1530 | if ((unsigned long)dn < PAGE_SIZE) | ||
1531 | return string(buf, end, "(null)", spec); | ||
1532 | |||
1533 | /* simple case without anything any more format specifiers */ | ||
1534 | fmt++; | ||
1535 | if (fmt[0] == '\0' || strcspn(fmt,"fnpPFcC") > 0) | ||
1536 | fmt = "f"; | ||
1537 | |||
1538 | for (pass = false; strspn(fmt,"fnpPFcC"); fmt++, pass = true) { | ||
1539 | if (pass) { | ||
1540 | if (buf < end) | ||
1541 | *buf = ':'; | ||
1542 | buf++; | ||
1543 | } | ||
1544 | |||
1545 | switch (*fmt) { | ||
1546 | case 'f': /* full_name */ | ||
1547 | buf = device_node_gen_full_name(dn, buf, end); | ||
1548 | break; | ||
1549 | case 'n': /* name */ | ||
1550 | buf = string(buf, end, dn->name, str_spec); | ||
1551 | break; | ||
1552 | case 'p': /* phandle */ | ||
1553 | buf = number(buf, end, (unsigned int)dn->phandle, num_spec); | ||
1554 | break; | ||
1555 | case 'P': /* path-spec */ | ||
1556 | p = kbasename(of_node_full_name(dn)); | ||
1557 | if (!p[1]) | ||
1558 | p = "/"; | ||
1559 | buf = string(buf, end, p, str_spec); | ||
1560 | break; | ||
1561 | case 'F': /* flags */ | ||
1562 | tbuf[0] = of_node_check_flag(dn, OF_DYNAMIC) ? 'D' : '-'; | ||
1563 | tbuf[1] = of_node_check_flag(dn, OF_DETACHED) ? 'd' : '-'; | ||
1564 | tbuf[2] = of_node_check_flag(dn, OF_POPULATED) ? 'P' : '-'; | ||
1565 | tbuf[3] = of_node_check_flag(dn, OF_POPULATED_BUS) ? 'B' : '-'; | ||
1566 | tbuf[4] = 0; | ||
1567 | buf = string(buf, end, tbuf, str_spec); | ||
1568 | break; | ||
1569 | case 'c': /* major compatible string */ | ||
1570 | ret = of_property_read_string(dn, "compatible", &p); | ||
1571 | if (!ret) | ||
1572 | buf = string(buf, end, p, str_spec); | ||
1573 | break; | ||
1574 | case 'C': /* full compatible string */ | ||
1575 | has_mult = false; | ||
1576 | of_property_for_each_string(dn, "compatible", prop, p) { | ||
1577 | if (has_mult) | ||
1578 | buf = string(buf, end, ",", str_spec); | ||
1579 | buf = string(buf, end, "\"", str_spec); | ||
1580 | buf = string(buf, end, p, str_spec); | ||
1581 | buf = string(buf, end, "\"", str_spec); | ||
1582 | |||
1583 | has_mult = true; | ||
1584 | } | ||
1585 | break; | ||
1586 | default: | ||
1587 | break; | ||
1588 | } | ||
1589 | } | ||
1590 | |||
1591 | return widen_string(buf, buf - buf_start, end, spec); | ||
1592 | } | ||
1593 | |||
1473 | int kptr_restrict __read_mostly; | 1594 | int kptr_restrict __read_mostly; |
1474 | 1595 | ||
1475 | /* | 1596 | /* |
@@ -1566,6 +1687,16 @@ int kptr_restrict __read_mostly; | |||
1566 | * p page flags (see struct page) given as pointer to unsigned long | 1687 | * p page flags (see struct page) given as pointer to unsigned long |
1567 | * g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t | 1688 | * g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t |
1568 | * v vma flags (VM_*) given as pointer to unsigned long | 1689 | * v vma flags (VM_*) given as pointer to unsigned long |
1690 | * - 'O' For a kobject based struct. Must be one of the following: | ||
1691 | * - 'OF[fnpPcCF]' For a device tree object | ||
1692 | * Without any optional arguments prints the full_name | ||
1693 | * f device node full_name | ||
1694 | * n device node name | ||
1695 | * p device node phandle | ||
1696 | * P device node path spec (name + @unit) | ||
1697 | * F device node flags | ||
1698 | * c major compatible string | ||
1699 | * C full compatible string | ||
1569 | * | 1700 | * |
1570 | * ** Please update also Documentation/printk-formats.txt when making changes ** | 1701 | * ** Please update also Documentation/printk-formats.txt when making changes ** |
1571 | * | 1702 | * |
@@ -1721,6 +1852,11 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1721 | 1852 | ||
1722 | case 'G': | 1853 | case 'G': |
1723 | return flags_string(buf, end, ptr, fmt); | 1854 | return flags_string(buf, end, ptr, fmt); |
1855 | case 'O': | ||
1856 | switch (fmt[1]) { | ||
1857 | case 'F': | ||
1858 | return device_node_string(buf, end, ptr, spec, fmt + 1); | ||
1859 | } | ||
1724 | } | 1860 | } |
1725 | spec.flags |= SMALL; | 1861 | spec.flags |= SMALL; |
1726 | if (spec.field_width == -1) { | 1862 | if (spec.field_width == -1) { |