printing_debugging

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
printing_debugging [2018/09/25 12:41] – [pr_* macros] rpjdayprinting_debugging [2018/09/25 13:27] (current) – [__netdev_printk()] rpjday
Line 71: Line 71:
 #define pr_info(fmt, ...) \ #define pr_info(fmt, ...) \
  printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)  printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
 +/*
 + * Like KERN_CONT, pr_cont() should only be used when continuing
 + * a line with no newline ('\n') enclosed. Otherwise it defaults
 + * back to KERN_DEFAULT.
 + */
 +#define pr_cont(fmt, ...) \
 +        printk(KERN_CONT fmt, ##__VA_ARGS__)
 </code> </code>
 +
 +===== Device debugging =====
 +
 +==== printk.h ====
 +
 +<code>
 +/* If you are writing a driver, please use dev_dbg instead */
 +</code>
 +
 +==== device.h: Device printing ====
 +
 +<code>
 +#ifndef dev_fmt
 +#define dev_fmt(fmt) fmt
 +#endif
 +
 +#ifdef CONFIG_PRINTK
 +
 +__printf(3, 0)
 +int dev_vprintk_emit(int level, const struct device *dev,
 +      const char *fmt, va_list args);
 +__printf(3, 4)
 +int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...);
 +
 +__printf(3, 4)
 +void dev_printk(const char *level, const struct device *dev,
 + const char *fmt, ...);
 +__printf(2, 3)
 +void _dev_emerg(const struct device *dev, const char *fmt, ...);
 +__printf(2, 3)
 +void _dev_alert(const struct device *dev, const char *fmt, ...);
 +__printf(2, 3)
 +void _dev_crit(const struct device *dev, const char *fmt, ...);
 +__printf(2, 3)
 +void _dev_err(const struct device *dev, const char *fmt, ...);
 +__printf(2, 3)
 +void _dev_warn(const struct device *dev, const char *fmt, ...);
 +__printf(2, 3)
 +void _dev_notice(const struct device *dev, const char *fmt, ...);
 +__printf(2, 3)
 +void _dev_info(const struct device *dev, const char *fmt, ...);
 +
 +#else
 +
 +... snip ...
 +
 +#endif
 +
 +#define dev_emerg(dev, fmt, ...) \
 + _dev_emerg(dev, dev_fmt(fmt), ##__VA_ARGS__)
 +#define dev_crit(dev, fmt, ...) \
 + _dev_crit(dev, dev_fmt(fmt), ##__VA_ARGS__)
 +#define dev_alert(dev, fmt, ...) \
 + _dev_alert(dev, dev_fmt(fmt), ##__VA_ARGS__)
 +#define dev_err(dev, fmt, ...) \
 + _dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__)
 +#define dev_warn(dev, fmt, ...) \
 + _dev_warn(dev, dev_fmt(fmt), ##__VA_ARGS__)
 +#define dev_notice(dev, fmt, ...) \
 + _dev_notice(dev, dev_fmt(fmt), ##__VA_ARGS__)
 +#define dev_info(dev, fmt, ...) \
 + _dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__)
 +</code>
 +
 +==== drivers/base/core.c ====
 +
 +=== dev_printk() ===
 +
 +<code>
 +void dev_printk(const char *level, const struct device *dev,
 + const char *fmt, ...)
 +{
 + struct va_format vaf;
 + va_list args;
 +
 + va_start(args, fmt);
 +
 + vaf.fmt = fmt;
 + vaf.va = &args;
 +
 + __dev_printk(level, dev, &vaf);
 +
 + va_end(args);
 +}
 +EXPORT_SYMBOL(dev_printk);
 +</code>
 +
 +=== __dev_printk() ===
 +
 +<code>
 +static void __dev_printk(const char *level, const struct device *dev,
 + struct va_format *vaf)
 +{
 + if (dev)
 + dev_printk_emit(level[1] - '0', dev, "%s %s: %pV",
 + dev_driver_string(dev), dev_name(dev), vaf);
 + else
 + printk("%s(NULL device *): %pV", level, vaf);
 +}
 +</code>
 +
 +=== dev_printk_emit() ===
 +
 +<code>
 +int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...)
 +{
 + va_list args;
 + int r;
 +
 + va_start(args, fmt);
 +
 + r = dev_vprintk_emit(level, dev, fmt, args);
 +
 + va_end(args);
 +
 + return r;
 +}
 +EXPORT_SYMBOL(dev_printk_emit);
 +</code>
 +
 +=== dev_vprintk_emit() ===
 +
 +<code>
 +int dev_vprintk_emit(int level, const struct device *dev,
 +      const char *fmt, va_list args)
 +{
 + char hdr[128];
 + size_t hdrlen;
 +
 + hdrlen = create_syslog_header(dev, hdr, sizeof(hdr));
 +
 + return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args);
 +}
 +</code>
 +
 +===== netdev debugging (net/core/dev.c) =====
 +
 +==== Defining macros ====
 +
 +<code>
 +#define define_netdev_printk_level(func, level)                 \
 +void func(const struct net_device *dev, const char *fmt, ...)   \
 +{                                                               \
 +        struct va_format vaf;                                   \
 +        va_list args;                                           \
 +                                                                \
 +        va_start(args, fmt);                                    \
 +                                                                \
 +        vaf.fmt = fmt;                                          \
 +        vaf.va = &args;                                         \
 +                                                                \
 +        __netdev_printk(level, dev, &vaf);                      \
 +                                                                \
 +        va_end(args);                                           \
 +}                                                               \
 +EXPORT_SYMBOL(func);
 +
 +define_netdev_printk_level(netdev_emerg, KERN_EMERG);
 +define_netdev_printk_level(netdev_alert, KERN_ALERT);
 +define_netdev_printk_level(netdev_crit, KERN_CRIT);
 +define_netdev_printk_level(netdev_err, KERN_ERR);
 +define_netdev_printk_level(netdev_warn, KERN_WARNING);
 +define_netdev_printk_level(netdev_notice, KERN_NOTICE);
 +define_netdev_printk_level(netdev_info, KERN_INFO);
 +</code>
 +
 +==== Alternate way of calling __netdev_printk() ====
 +
 +<code>
 +void netdev_printk(const char *level, const struct net_device *dev,
 +                   const char *format, ...)
 +{
 +        struct va_format vaf;
 +        va_list args;
 +
 +        va_start(args, format);
 +
 +        vaf.fmt = format;
 +        vaf.va = &args;
 +
 +        __netdev_printk(level, dev, &vaf);
 +
 +        va_end(args);
 +}
 +EXPORT_SYMBOL(netdev_printk);
 +</code>
 +
 +==== __netdev_printk() ====
 +
 +<code>
 +static void __netdev_printk(const char *level, const struct net_device *dev,
 +                            struct va_format *vaf)
 +{
 +        if (dev && dev->dev.parent) {
 +                dev_printk_emit(level[1] - '0',
 +                                dev->dev.parent,
 +                                "%s %s %s%s: %pV",
 +                                dev_driver_string(dev->dev.parent),
 +                                dev_name(dev->dev.parent),
 +                                netdev_name(dev), netdev_reg_state(dev),
 +                                vaf);
 +        } else if (dev) {
 +                printk("%s%s%s: %pV",
 +                       level, netdev_name(dev), netdev_reg_state(dev), vaf);
 +        } else {
 +                printk("%s(NULL net_device): %pV", level, vaf);
 +        }
 +}
 +</code>
 +
 +===== Dynamic debugging =====
 +
 +... coming ...
  • printing_debugging.1537879305.txt.gz
  • Last modified: 2018/09/25 12:41
  • by rpjday