diff options
author | Kay Sievers <kay@vrfy.org> | 2012-05-02 20:29:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-07 20:12:03 -0400 |
commit | c4e00daaa96d3a0786f1f4fe6456281c60ef9a16 (patch) | |
tree | 802b018c8ee8280db04b03224e4d2d61e232d94b /drivers/base | |
parent | e11fea92e13fb91c50bacca799a6131c81929986 (diff) |
driver-core: extend dev_printk() to pass structured data
Extends dev_printk() to attach a dictionary with a device identifier
and the driver core subsystem name to logged messages, which makes
dev_prink() reliable machine-readable. In addition to the printed
plain text message, it creates these properties:
SUBSYSTEM= - the driver-core subsytem name
DEVICE=
b12:8 - block dev_t
c127:3 - char dev_t
n8 - netdev ifindex
+sound:card0 - subsystem:devname
Tested-by: William Douglas <william.douglas@intel.com>
Signed-off-by: Kay Sievers <kay@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 33461ec35d8f..346be8b78b24 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/async.h> | 26 | #include <linux/async.h> |
27 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
28 | #include <linux/netdevice.h> | ||
28 | 29 | ||
29 | #include "base.h" | 30 | #include "base.h" |
30 | #include "power/power.h" | 31 | #include "power/power.h" |
@@ -1843,15 +1844,60 @@ void device_shutdown(void) | |||
1843 | */ | 1844 | */ |
1844 | 1845 | ||
1845 | #ifdef CONFIG_PRINTK | 1846 | #ifdef CONFIG_PRINTK |
1846 | |||
1847 | int __dev_printk(const char *level, const struct device *dev, | 1847 | int __dev_printk(const char *level, const struct device *dev, |
1848 | struct va_format *vaf) | 1848 | struct va_format *vaf) |
1849 | { | 1849 | { |
1850 | char dict[128]; | ||
1851 | size_t dictlen = 0; | ||
1852 | const char *subsys; | ||
1853 | |||
1850 | if (!dev) | 1854 | if (!dev) |
1851 | return printk("%s(NULL device *): %pV", level, vaf); | 1855 | return printk("%s(NULL device *): %pV", level, vaf); |
1852 | 1856 | ||
1853 | return printk("%s%s %s: %pV", | 1857 | if (dev->class) |
1854 | level, dev_driver_string(dev), dev_name(dev), vaf); | 1858 | subsys = dev->class->name; |
1859 | else if (dev->bus) | ||
1860 | subsys = dev->bus->name; | ||
1861 | else | ||
1862 | goto skip; | ||
1863 | |||
1864 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
1865 | "SUBSYSTEM=%s", subsys); | ||
1866 | |||
1867 | /* | ||
1868 | * Add device identifier DEVICE=: | ||
1869 | * b12:8 block dev_t | ||
1870 | * c127:3 char dev_t | ||
1871 | * n8 netdev ifindex | ||
1872 | * +sound:card0 subsystem:devname | ||
1873 | */ | ||
1874 | if (MAJOR(dev->devt)) { | ||
1875 | char c; | ||
1876 | |||
1877 | if (strcmp(subsys, "block") == 0) | ||
1878 | c = 'b'; | ||
1879 | else | ||
1880 | c = 'c'; | ||
1881 | dictlen++; | ||
1882 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
1883 | "DEVICE=%c%u:%u", | ||
1884 | c, MAJOR(dev->devt), MINOR(dev->devt)); | ||
1885 | } else if (strcmp(subsys, "net") == 0) { | ||
1886 | struct net_device *net = to_net_dev(dev); | ||
1887 | |||
1888 | dictlen++; | ||
1889 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
1890 | "DEVICE=n%u", net->ifindex); | ||
1891 | } else { | ||
1892 | dictlen++; | ||
1893 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
1894 | "DEVICE=+%s:%s", subsys, dev_name(dev)); | ||
1895 | } | ||
1896 | skip: | ||
1897 | return printk_emit(0, level[1] - '0', | ||
1898 | dictlen ? dict : NULL, dictlen, | ||
1899 | "%s %s: %pV", | ||
1900 | dev_driver_string(dev), dev_name(dev), vaf); | ||
1855 | } | 1901 | } |
1856 | EXPORT_SYMBOL(__dev_printk); | 1902 | EXPORT_SYMBOL(__dev_printk); |
1857 | 1903 | ||