History

vsprintf: Add %p extension "%pOF" for device tree

90% of the usage of device node's full_name is printing it out in a kernel message. However, storing the full path for every node is wasteful and redundant. With a custom format specifier, we can generate the full path at run-time and eventually remove the full path from every node. For instance typical use is: pr_info("Frobbing node %s\n", node->full_name); Which can be written now as: pr_info("Frobbing node %pOF\n", node); '%pO' is the base specifier to represent kobjects with '%pOF' representing struct device_node. Currently, struct device_node is the only supported type of kobject. More fine-grained control of formatting includes printing the name, flags, path-spec name and others, explained in the documentation entry. Originally written by Pantelis, but pretty much rewrote the core function using existing string/number functions. The 2 passes were unnecessary and have been removed. Also, updated the checkpatch.pl check. The unittest code was written by Grant Likely.

Pantelis Antoniou committed 11 years ago

Commit ce4fecf1 parent 27497e15 files · +234 −2Browse files

Unified · Split

5 files
  1. Documentation/printk-formats.txt +36 −0
  2. drivers/of/unittest-data/tests-platform.dtsi +3 −1
  3. drivers/of/unittest.c +58 −0
  4. lib/vsprintf.c +136 −0
  5. scripts/checkpatch.pl +1 −1
Documentation/printk-formats.txt+36−0
@@ -275,6 +275,42 @@ struct va_format: · 274 unmodified lines
275275
276276 Passed by reference.
277277
278+kobjects:
279+ %pO
280+
281+ Base specifier for kobject based structs. Must be followed with
282+ character for specific type of kobject as listed below:
283+
284+ Device tree nodes:
285+
286+ %pOF[fnpPcCF]
287+
288+ For printing device tree nodes. The optional arguments are:
289+ f device node full_name
290+ n device node name
291+ p device node phandle
292+ P device node path spec (name + @unit)
293+ F device node flags
294+ c major compatible string
295+ C full compatible string
296+ Without any arguments prints full_name (same as %pOFf)
297+ The separator when using multiple arguments is ':'
298+
299+ Examples:
300+
301+ %pOF /foo/bar@0 - Node full name
302+ %pOFf /foo/bar@0 - Same as above
303+ %pOFfp /foo/bar@0:10 - Node full name + phandle
304+ %pOFfcF /foo/bar@0:foo,device:--P- - Node full name +
305+ major compatible string +
306+ node flags
307+ D - dynamic
308+ d - detached
309+ P - Populated
310+ B - Populated bus
311+
312+ Passed by reference.
313+
278314 struct clk:
279315
280316 %pC pll1
drivers/of/unittest-data/tests-platform.dtsi+3−1
@@ -26,7 +26,9 @@ · 25 unmodified lines
2626 #size-cells = <0>;
2727
2828 dev@100 {
29− compatible = "test-sub-device";
29+ compatible = "test-sub-device",
30+ "test-compat2",
31+ "test-compat3";
3032 reg = <0x100>;
3133 };
3234 };
drivers/of/unittest.c+58−0
@@ -239,6 +239,63 @@ static void __init of_unittest_check_tree_linkage(void) · 238 unmodified lines
239239 pr_debug("allnodes list size (%i); sibling lists size (%i)\n", allnode_count, child_count);
240240 }
241241
242+static void __init of_unittest_printf_one(struct device_node *np, const char *fmt,
243+ const char *expected)
244+{
245+ unsigned char buf[strlen(expected)+10];
246+ int size, i;
247+
248+ /* Baseline; check conversion with a large size limit */
249+ memset(buf, 0xff, sizeof(buf));
250+ size = snprintf(buf, sizeof(buf) - 2, fmt, np);
251+
252+ /* use strcmp() instead of strncmp() here to be absolutely sure strings match */
253+ unittest((strcmp(buf, expected) == 0) && (buf[size+1] == 0xff),
254+ "sprintf failed; fmt='%s' expected='%s' rslt='%s'\n",
255+ fmt, expected, buf);
256+
257+ /* Make sure length limits work */
258+ size++;
259+ for (i = 0; i < 2; i++, size--) {
260+ /* Clear the buffer, and make sure it works correctly still */
261+ memset(buf, 0xff, sizeof(buf));
262+ snprintf(buf, size+1, fmt, np);
263+ unittest(strncmp(buf, expected, size) == 0 && (buf[size+1] == 0xff),
264+ "snprintf failed; size=%i fmt='%s' expected='%s' rslt='%s'\n",
265+ size, fmt, expected, buf);
266+ }
267+}
268+
269+static void __init of_unittest_printf(void)
270+{
271+ struct device_node *np;
272+ const char *full_name = "/testcase-data/platform-tests/test-device@1/dev@100";
273+ char phandle_str[16] = "";
274+
275+ np = of_find_node_by_path(full_name);
276+ if (!np) {
277+ unittest(np, "testcase data missing\n");
278+ return;
279+ }
280+
281+ num_to_str(phandle_str, sizeof(phandle_str), np->phandle);
282+
283+ of_unittest_printf_one(np, "%pOF", full_name);
284+ of_unittest_printf_one(np, "%pOFf", full_name);
285+ of_unittest_printf_one(np, "%pOFp", phandle_str);
286+ of_unittest_printf_one(np, "%pOFP", "dev@100");
287+ of_unittest_printf_one(np, "ABC %pOFP ABC", "ABC dev@100 ABC");
288+ of_unittest_printf_one(np, "%10pOFP", " dev@100");
289+ of_unittest_printf_one(np, "%-10pOFP", "dev@100 ");
290+ of_unittest_printf_one(of_root, "%pOFP", "/");
291+ of_unittest_printf_one(np, "%pOFF", "----");
292+ of_unittest_printf_one(np, "%pOFPF", "dev@100:----");
293+ of_unittest_printf_one(np, "%pOFPFPc", "dev@100:----:dev@100:test-sub-device");
294+ of_unittest_printf_one(np, "%pOFc", "test-sub-device");
295+ of_unittest_printf_one(np, "%pOFC",
296+ "\"test-sub-device\",\"test-compat2\",\"test-compat3\"");
297+}
298+
242299 struct node_hash {
243300 struct hlist_node node;
244301 struct device_node *np;
@@ -2269,6 +2326,7 @@ static int __init of_unittest(void) · 2024 unmodified lines
22692326 of_unittest_find_node_by_name();
22702327 of_unittest_dynamic();
22712328 of_unittest_parse_phandle_with_args();
2329+ of_unittest_printf();
22722330 of_unittest_property_string();
22732331 of_unittest_property_copy();
22742332 of_unittest_changeset();
lib/vsprintf.c+136−0
@@ -31,6 +31,7 @@ · 30 unmodified lines
3131 #include <linux/dcache.h>
3232 #include <linux/cred.h>
3333 #include <linux/uuid.h>
34+#include <linux/of.h>
3435 #include <net/addrconf.h>
3536 #ifdef CONFIG_BLOCK
3637 #include <linux/blkdev.h>
@@ -1470,6 +1471,126 @@ char *flags_string(char *buf, char *end, void *flags_ptr, const char *fmt) · 1433 unmodified lines
14701471 return format_flags(buf, end, flags, names);
14711472 }
14721473
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+
14731594 int kptr_restrict __read_mostly;
14741595
14751596 /*
@@ -1566,6 +1687,16 @@ int kptr_restrict __read_mostly; · 90 unmodified lines
15661687 * p page flags (see struct page) given as pointer to unsigned long
15671688 * g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t
15681689 * 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
15691700 *
15701701 * ** Please update also Documentation/printk-formats.txt when making changes **
15711702 *
@@ -1721,6 +1852,11 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, · 149 unmodified lines
17211852
17221853 case 'G':
17231854 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+ }
17241860 }
17251861 spec.flags |= SMALL;
17261862 if (spec.field_width == -1) {
scripts/checkpatch.pl+1−1
@@ -5709,7 +5709,7 @@ sub process { · 5708 unmodified lines
57095709 for (my $count = $linenr; $count <= $lc; $count++) {
57105710 my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
57115711 $fmt =~ s/%%//g;
5712− if ($fmt =~ /(\%[\*\d\.]*p(?![\WFfSsBKRraEhMmIiUDdgVCbGN]).)/) {
5712+ if ($fmt =~ /(\%[\*\d\.]*p(?![\WFfSsBKRraEhMmIiUDdgVCbGNO]).)/) {
57135713 $bad_extension = $1;
57145714 last;
57155715 }