Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| printing_debugging [2018/09/25 12:09] – [Overview] rpjday | printing_debugging [2018/09/25 13:27] (current) – [__netdev_printk()] rpjday | ||
|---|---|---|---|
| Line 32: | Line 32: | ||
| </ | </ | ||
| - | ==== printk_get_level() ==== | + | ==== printk.h: |
| Remember to skip leading '' | Remember to skip leading '' | ||
| Line 51: | Line 51: | ||
| </ | </ | ||
| - | ==== pr_* macros ==== | + | ==== printk.h: |
| Unconditional printing at all log levels. | Unconditional printing at all log levels. | ||
| Line 71: | Line 71: | ||
| #define pr_info(fmt, | #define pr_info(fmt, | ||
| printk(KERN_INFO pr_fmt(fmt), | printk(KERN_INFO pr_fmt(fmt), | ||
| + | /* | ||
| + | * Like KERN_CONT, pr_cont() should only be used when continuing | ||
| + | * a line with no newline (' | ||
| + | * back to KERN_DEFAULT. | ||
| + | */ | ||
| + | #define pr_cont(fmt, | ||
| + | printk(KERN_CONT fmt, ## | ||
| </ | </ | ||
| + | |||
| + | ===== Device debugging ===== | ||
| + | |||
| + | ==== printk.h ==== | ||
| + | |||
| + | < | ||
| + | /* If you are writing a driver, please use dev_dbg instead */ | ||
| + | </ | ||
| + | |||
| + | ==== device.h: Device printing ==== | ||
| + | |||
| + | < | ||
| + | #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, | ||
| + | _dev_emerg(dev, | ||
| + | #define dev_crit(dev, | ||
| + | _dev_crit(dev, | ||
| + | #define dev_alert(dev, | ||
| + | _dev_alert(dev, | ||
| + | #define dev_err(dev, | ||
| + | _dev_err(dev, | ||
| + | #define dev_warn(dev, | ||
| + | _dev_warn(dev, | ||
| + | #define dev_notice(dev, | ||
| + | _dev_notice(dev, | ||
| + | #define dev_info(dev, | ||
| + | _dev_info(dev, | ||
| + | </ | ||
| + | |||
| + | ==== drivers/ | ||
| + | |||
| + | === dev_printk() === | ||
| + | |||
| + | < | ||
| + | void dev_printk(const char *level, const struct device *dev, | ||
| + | const char *fmt, ...) | ||
| + | { | ||
| + | struct va_format vaf; | ||
| + | va_list args; | ||
| + | |||
| + | va_start(args, | ||
| + | |||
| + | vaf.fmt = fmt; | ||
| + | vaf.va = &args; | ||
| + | |||
| + | __dev_printk(level, | ||
| + | |||
| + | va_end(args); | ||
| + | } | ||
| + | EXPORT_SYMBOL(dev_printk); | ||
| + | </ | ||
| + | |||
| + | === __dev_printk() === | ||
| + | |||
| + | < | ||
| + | static void __dev_printk(const char *level, const struct device *dev, | ||
| + | struct va_format *vaf) | ||
| + | { | ||
| + | if (dev) | ||
| + | dev_printk_emit(level[1] - ' | ||
| + | dev_driver_string(dev), | ||
| + | else | ||
| + | printk(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | === dev_printk_emit() === | ||
| + | |||
| + | < | ||
| + | int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...) | ||
| + | { | ||
| + | va_list args; | ||
| + | int r; | ||
| + | |||
| + | va_start(args, | ||
| + | |||
| + | r = dev_vprintk_emit(level, | ||
| + | |||
| + | va_end(args); | ||
| + | |||
| + | return r; | ||
| + | } | ||
| + | EXPORT_SYMBOL(dev_printk_emit); | ||
| + | </ | ||
| + | |||
| + | === dev_vprintk_emit() === | ||
| + | |||
| + | < | ||
| + | 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, | ||
| + | |||
| + | return vprintk_emit(0, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== netdev debugging (net/ | ||
| + | |||
| + | ==== Defining macros ==== | ||
| + | |||
| + | < | ||
| + | #define define_netdev_printk_level(func, | ||
| + | void func(const struct net_device *dev, const char *fmt, ...) \ | ||
| + | { \ | ||
| + | struct va_format vaf; \ | ||
| + | va_list args; \ | ||
| + | \ | ||
| + | va_start(args, | ||
| + | \ | ||
| + | vaf.fmt = fmt; \ | ||
| + | vaf.va = & | ||
| + | \ | ||
| + | __netdev_printk(level, | ||
| + | \ | ||
| + | va_end(args); | ||
| + | } \ | ||
| + | EXPORT_SYMBOL(func); | ||
| + | |||
| + | define_netdev_printk_level(netdev_emerg, | ||
| + | define_netdev_printk_level(netdev_alert, | ||
| + | define_netdev_printk_level(netdev_crit, | ||
| + | define_netdev_printk_level(netdev_err, | ||
| + | define_netdev_printk_level(netdev_warn, | ||
| + | define_netdev_printk_level(netdev_notice, | ||
| + | define_netdev_printk_level(netdev_info, | ||
| + | </ | ||
| + | |||
| + | ==== Alternate way of calling __netdev_printk() ==== | ||
| + | |||
| + | < | ||
| + | void netdev_printk(const char *level, const struct net_device *dev, | ||
| + | const char *format, ...) | ||
| + | { | ||
| + | struct va_format vaf; | ||
| + | va_list args; | ||
| + | |||
| + | va_start(args, | ||
| + | |||
| + | vaf.fmt = format; | ||
| + | vaf.va = &args; | ||
| + | |||
| + | __netdev_printk(level, | ||
| + | |||
| + | va_end(args); | ||
| + | } | ||
| + | EXPORT_SYMBOL(netdev_printk); | ||
| + | </ | ||
| + | |||
| + | ==== __netdev_printk() ==== | ||
| + | |||
| + | < | ||
| + | static void __netdev_printk(const char *level, const struct net_device *dev, | ||
| + | struct va_format *vaf) | ||
| + | { | ||
| + | if (dev && dev-> | ||
| + | dev_printk_emit(level[1] - ' | ||
| + | dev-> | ||
| + | "%s %s %s%s: %pV", | ||
| + | dev_driver_string(dev-> | ||
| + | dev_name(dev-> | ||
| + | netdev_name(dev), | ||
| + | vaf); | ||
| + | } else if (dev) { | ||
| + | printk(" | ||
| + | | ||
| + | } else { | ||
| + | printk(" | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== Dynamic debugging ===== | ||
| + | |||
| + | ... coming ... | ||