【微知】Mellanox OFED驱动中使用的8种日志打印函数以及涉及的6种内核日志打印函数盘点?(mlx5_core_info)

背景

日常使用最多的就是mlx的打印。不同日志打印有不同功能,比如使用dev_xxx的打印可以使用内核的动态debug开关相关文件打印(echo -n ‘file probe.c +p’ > /sys/kernel/debug/dynamic_debug/control),详细参考兄弟篇:如何给某个文件打开linux内核的动态打印开关
printk是内核中最基本的打印函数,用于将消息输出到内核日志中。它支持多种日志级别,但是printk本身不支持动态打印,但可以通过全局日志级别控制输出。
pr_err本身不支持动态打印
dev_xxx系列支持动态打印

关系

缩略图:
在这里插入图片描述

详细图:

kernel 内核接口
dev_printk_emit

dev_printk_emit -> vprintk_store -> log_output
pr_xxx

pr_dbg
pr_info
pr_warn
pr_err
printk

KERN_EMERG
KERN_ALERT
KERN_CRIT
KERN_ERR
KERN_WARNING
KERN_NOTICE
KERN_INFO
KERN_DEBUG
dev_xxx

dev_emerg
dev_crit
dev_alert
dev_err
dev_warn
dev_notice
dev_info
netdev_info
mlx5_ib_xxx

mlx5_ib_dbg
mlx5_ib_err
mlx5_ib_warn
mlx5_core_xxx

mlx5_core_dbg
mlx5_core_info
mlx5_core_warn
mlx5_core_err
mlx5_fpga_xxx

mlx5_fpga_dbg
mlx5_fpga_err
mlx5_fpga_warn
mlx5_fpga_notice
mlx5_fpga_info
iser_xxx

iser_info
iser_warn
iser_dbg
iser_err
esw_xxx

esw_info
esw_warn
esw_debug
mlx5dr_xxx

mlx5dr_err
mlx5dr_info
mlx5dr_dbg
mlx5_log
mlx5_printk
WARN_ONCE

函数细节

mlx5_ib_xxx系列

mlx5_ib_dbg
mlx5_ib_warn
mlx5_ib_err
是直接封装的dev_xxx系列的debug日志,添加了dev设备
举例:

#define mlx5_ib_err(_dev, format, arg...)                                      \
	dev_err(&(_dev)->ib_dev.dev, "%s:%d:(pid %d): " format, __func__,      \
		__LINE__, current->pid, ##arg)

mlx5_ib_err(dev, "could not change QP%d state to INIT: %d\n",
			    qp->qp_num, ret);

mlx5_core_xxx系列

mlx5_core_dbg
mlx5_core_info
mlx5_core_warn
mlx5_core_err

以一个为例:是直接封装的dev_xxx系列的debug日志,添加了dev设备

#define mlx5_core_dbg(__dev, format, ...)				\
	dev_dbg((__dev)->device, "%s:%d:(pid %d): " format,		\
		 __func__, __LINE__, current->pid,			\
		 ##__VA_ARGS__)

	mlx5_core_dbg(dev, "err %d, status %d\n", err, status);

mlx5_fpga_xxx系列

mlx5_fpga_dbg
mlx5_fpga_err
mlx5_fpga_warn
mlx5_fpga_notice
mlx5_fpga_info
是封装了 mlx5_core_xxx系列
以一个为例:

#define mlx5_fpga_err(__adev, format, ...) \
	mlx5_core_err((__adev)->mdev, "FPGA: %s:%d:(pid %d): " format, \
		      __func__, __LINE__, current->pid, ##__VA_ARGS__)

		mlx5_fpga_err(fdev, "Failed to activate FPGA RC QP: %d\n", err);

mlx5_log

#define mlx5_log(__dev, level, format, ...)			\
	mlx5_printk(__dev, level, "%s:%d:(pid %d): " format,	\
		    __func__, __LINE__, current->pid,		\
		    ##__VA_ARGS__)

mlx5_printk

static inline void mlx5_printk(struct mlx5_core_dev *dev, int level, const char *format, ...)
{
	struct device *device = dev->device;
	struct va_format vaf;
	va_list args;

	if (WARN_ONCE(level < LOGLEVEL_EMERG || level > LOGLEVEL_DEBUG,
		      "Level %d is out of range, set to default level\n", level))
		level = LOGLEVEL_DEFAULT;

	va_start(args, format);
	vaf.fmt = format;
	vaf.va = &args;

	dev_printk_emit(level, device, "%s %s: %pV", dev_driver_string(device), dev_name(device),
			&vaf);
	va_end(args);
}

netdev_info系列(内核接口)

比如:

netdev_info(priv->netdev, "%s: rx_jumbo_pending not supported\n",
	    __func__);

WARN_ONCE (内核接口)

比如:

	WARN_ONCE(1, "%s: unknown reg_state %d\n", dev->name, dev->reg_state);

iser_xxx系列 iser模块的

iser_info
iser_warn
iser_dbg
iser_err
是封装的内核pr_err系列接口

pr_xxx 内核接口

	pr_err(PFX "%s: " fmt, __func__ , ## arg)

esw_xxx 系列 esw的打印

esw_info
esw_warn
esw_debug
封装的dev系列的比如dev_info,加了个E-Switch: 的前缀
比如:

#define esw_info(__dev, format, ...)			\
	dev_info((__dev)->device, "E-Switch: " format, ##__VA_ARGS__)

这里也说明了,不同模块要定义自己的打印函数的根本动机在于定义自定义的字段
定义方式也很简单 前面几个参数,一般有format,以及…,然后套用其他的就用 ""format, 然后 …用 ##__VA_ARGS__来替代

mlx5dr_err 系列

mlx5dr_err
mlx5dr_info
mlx5dr_dbg
是封装的mlx5_core_info系列

其他

关于dev_xxx与printk的关系

从下面定义可得知,dev_info

define_dev_printk_level(_dev_emerg, KERN_EMERG);
define_dev_printk_level(_dev_alert, KERN_ALERT);
define_dev_printk_level(_dev_crit, KERN_CRIT);
define_dev_printk_level(_dev_err, KERN_ERR);
define_dev_printk_level(_dev_warn, KERN_WARNING);
define_dev_printk_level(_dev_notice, KERN_NOTICE);
define_dev_printk_level(_dev_info, KERN_INFO);

#define define_dev_printk_level(func, kern_level)		\
void func(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(kern_level, dev, &vaf);			\
								\
	va_end(args);						\
}								\
EXPORT_SYMBOL(func);

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);
}
# 可见,这里__dev_printk,增加了dev_driver_string以及dev_name的获取并且打印



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;
}

asmlinkage int vprintk_emit(int facility, int level,
...
boot_delay_msec(level);
	printk_delay();
wake_up_klogd();

实际举例

mlx5_core_info

比如插拔网线的时候会使用mlx5_core_info打印:
在这里插入图片描述
这里就会打上模块名字,以及PCIe的bdf号
在这里插入图片描述

综述

本文总结了Mellanox OFED驱动中使用的8种日志打印函数以及涉及的6种内核日志打印函数。 方便日常快速使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值