linux驱动优先级

9 篇文章 0 订阅

1、研究前提

在使用xilinx的dma驱动时,其时钟是使用的外部时钟,驱动加载的优先级都是6,导致时钟还未初始化,其xilinx的dma驱动就启用了。出现以下问题:
xilinx-vdma 43000000.dma: reset timeout, cr 10006, sr 1
xilinx-vdma 43000000.dma: Reset channel failed
xilinx-vdma 43000000.dma: Xilinx AXI VDMA Engine Driver Probed!!
在xilinx的论坛也有该问题链接: link https://support.xilinx.com/s/question/0D52E00006hpqcWSAQ/xilinxvdma-43000000dma-reset-timeout%E9%97%AE%E9%A2%98?language=en_US
于是考虑时钟问题,开始想着把驱动编译成模块,待内核加载完成后,手动加载驱动,确认是否为时钟问题,但是编译失败,于是驱动优先级的方法解决该问题。

2、驱动优先级

从kernel/include/linux/init.h下可以查到以下优先级

#define pure_initcall(fn)		__define_initcall(fn, 0)

#define core_initcall(fn)		__define_initcall(fn, 1)
#define core_initcall_sync(fn)		__define_initcall(fn, 1s)
#define postcore_initcall(fn)		__define_initcall(fn, 2)
#define postcore_initcall_sync(fn)	__define_initcall(fn, 2s)
#define arch_initcall(fn)		__define_initcall(fn, 3)
#define arch_initcall_sync(fn)		__define_initcall(fn, 3s)
#define subsys_initcall(fn)		__define_initcall(fn, 4)
#define subsys_initcall_sync(fn)	__define_initcall(fn, 4s)
#define fs_initcall(fn)			__define_initcall(fn, 5)
#define fs_initcall_sync(fn)		__define_initcall(fn, 5s)
#define rootfs_initcall(fn)		__define_initcall(fn, rootfs)
#define device_initcall(fn)		__define_initcall(fn, 6)
#define device_initcall_sync(fn)	__define_initcall(fn, 6s)
#define late_initcall(fn)		__define_initcall(fn, 7)
#define late_initcall_sync(fn)		__define_initcall(fn, 7s)

再上面的不同优先级中,数字越小,优先级越高。同一优先级的驱动,加载顺序是链接过程决定的,结果是不确定的,我们无法手动设置谁先谁后。只能通过设置驱动的优先级来决定其先后。

xilinx_dma.c采用的是平台总线,其驱动入口函数为

module_platform_driver(xilinx_vdma_driver);
#define module_platform_driver(__platform_driver) \
	module_driver(__platform_driver, platform_driver_register, \
			platform_driver_unregister)
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
	return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
	__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
#define module_init(x)	__initcall(x);
#define __initcall(fn) device_initcall(fn)

可以看出其最后是调用的__define_initcall(fn, 6) 函数,其优先级为6

时钟芯片对应的驱动入口函数采用的是

module_spi_driver(__spi_driver);
#define module_spi_driver(__spi_driver) \
	module_driver(__spi_driver, spi_register_driver, \
			spi_unregister_driver)

可以看出,其最后调用的也是__define_initcall(fn, 6) 函数,其优先级为6

3、xilinx_dma.c驱动优先级修改

在#include 。。。下添加以下内容

#define module_init_test(x)	device_initcall_sync(x);
#define module_exit_test(x)	__exitcall(x);

/**
 * module_driver_test() - Helper macro for drivers that don't do anything
 * special in module init/exit. This eliminates a lot of boilerplate.
 * Each module may only use this macro once, and calling it replaces
 * module_init_test() and module_exit_test().
 *
 * @__driver: driver name
 * @__register: register function for this driver type
 * @__unregister: unregister function for this driver type
 * @...: Additional arguments to be passed to __register and __unregister.
 *
 * Use this macro to construct bus specific macros for registering
 * drivers, and do not use it on its own.
 */
#define module_driver_test(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
	return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init_test(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
	__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit_test(__driver##_exit);

#define module_platform_driver_test(__platform_driver) \
	module_driver_test(__platform_driver, platform_driver_register, \
			platform_driver_unregister)

修改

module_platform_driver(xilinx_vdma_driver);

为以下内容

module_platform_driver_test(xilinx_vdma_driver);

即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值