linux 内核 通知链的使用例子


前言

两个驱动模组之间的通信:A驱动模组发生了一些事件,需要通知B驱动模组,这时就可以使用通知链。
通知链 内核中的具体实现就不描述了,感兴趣可以去查看一下。


一、接口函数

头文件:

#include <linux/notifier.h>

这里使用阻塞式的通知链

//初始化一个通知链
#define BLOCKING_NOTIFIER_HEAD(name)

//通知链的注册,模块需要被通知,根据前言,注册就使用在模块B
int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
		struct notifier_block *nb);
		
//通知链的通知,模块需要发出通知到其他模块,根据前言,通知就使用在模块A
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
		unsigned long val, void *v);

//哪里注册,就哪里使用解除注册,解除注册后,相应的就收不到通知链
int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
		struct notifier_block *nb);

二、使用例子

2.1.创建通知链函数接口

2.1.1 kk_test_notifty.h

/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2024 KKC Inc.
*/

#ifndef __KK_TEST_NOTIFY_H__
#define __KK_TEST_NOTIFY_H__

#include <linux/err.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/notifier.h>

/* The mipi dphy enable occurred */
#define KK_TEST_ENABLE	0x78

int kk_test_notifier_register(const char *source, struct notifier_block *nb);
int kk_test_notifier_unregister(struct notifier_block *nb);
int kk_test_notifier_call_chain(unsigned long val, void *v);

#endif

2.1.2 kk_test_notifty.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2024 KKC Inc.
*/

#include <linux/module.h>
#include "kk_test_notify.h"

static BLOCKING_NOTIFIER_HEAD(kk_test_notifier_list);

int kk_test_notifier_register(const char *source, struct notifier_block *nb)
{
	if (!source)
		return -EINVAL;

	printk(":%s", source);

	return blocking_notifier_chain_register(&kk_test_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(kk_test_notifier_register);

int kk_test_notifier_unregister(struct notifier_block *nb)
{
	return blocking_notifier_chain_unregister(&kk_test_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(kk_test_notifier_unregister);

int kk_test_notifier_call_chain(unsigned long val, void *v)
{
	return blocking_notifier_call_chain(&kk_test_notifier_list, val, v);
}
EXPORT_SYMBOL_GPL(kk_test_notifier_call_chain);

MODULE_AUTHOR("AIC <kk.z@kkc.com>");
MODULE_DESCRIPTION("kk test notify");
MODULE_LICENSE("GPL v2");

2.2 使用RK3568的代码进行测试

这里想在mipi的dphy上电前,让屏端那边做点事。
根据上述需求,mipi的dphy上电前可以做一个通知发送(dw-mipi-dsi.c代码里),屏端驱动(panel-simple.c代码里)那里可以做一个通知的接收处理

注意1:关于2.1的通知链的编译,我们直接放在drm/rockchip的Makefile里了

rockchipdrm-y := kk_test_notify.o

注意2:关于通知链的头文件包含问题

/*
*	rockchip_drm_drv.h这个头文件,dw-mipi-dsi.c和panel-simple.c都引用了
*	因此,把#include "em_mipi_dphy_notify.h"放到rockchip_drm_drv.h中
*/

2.2.1 通知的发送(dw-mipi-dsi.c代码里)

mipi的dphy上电是在dw-mipi-dsi.c里,直接贴代码

//我们会在dw_mipi_dsi_encoder_enable这里func里进行操作
static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
{
	...
	//这里仅关注我们想要的内容
	//仅encoder->crtc->state->active == 1时才通知
	if (encoder->crtc->state->active) {
		kk_test_notifier_call_chain(KK_TEST_ENABLE, "active:1");
	}
	//下面这个func就是mipi dphy上电了,下面会贴一部分代码
	dw_mipi_dsi_pre_enable(dsi);
	...
}
static void dw_mipi_dsi_pre_enable(struct dw_mipi_dsi *dsi)
{
	...
	//省略的大部分都是对寄存器做了一些操作,这里就不看了
	//下面这个就是上电了
	mipi_dphy_power_on(dsi);
	...
}

2.2.2 通知的接收(panel-simple.c代码里)

static int __init panel_simple_init(void)
{
	int err;

	err = platform_driver_register(&panel_simple_platform_driver);
	if (err < 0)
		return err;

	if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
		err = mipi_dsi_driver_register(&panel_simple_dsi_driver);
		if (err < 0)
			return err;
	}

	//上述代码注册成功后,才会注册这个通知链
	kk_test_notifier_register("kk_test", &kk_test_active_notifier);

	return 0;
}
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
rootfs_initcall(panel_simple_init);
#else
module_init(panel_simple_init);
#endif

//这里方便思路往下走,就不把kk_test_active_notifier按编译顺序贴上面了,直接往下贴

static int kk_test_active_notifier_callback(struct notifier_block *nb, unsigned long value, void *v)
{
    printk("%s \n", __func__);
	
    if (value == KK_TEST_ENABLE){
		printk("%s KK_TEST_ENABLE\n", __func__);
	}
	
    return NOTIFY_DONE;
}

static struct notifier_block kk_test_active_notifier= {
        .notifier_call =  kk_test_active_notifier_callback,
};

2.3 Log

在这里插入图片描述
红线右侧是使用adb使系统进入休眠,然后休眠唤醒
红线左侧是我们的log,执行第二次input keyevent 26 休眠唤醒后,就会出现左侧log。


如有错误,请指正,谢谢。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值