如何调整Linux内核启动中的驱动初始化顺序

如何调整Linux内核启动中的驱动初始化顺序(zz)
2010-07-14 21:34:11
标签: Linux  内核  顺序  驱动  调整
http://linux.chinaunix.net/bbs/viewthread.php?tid=1143601

如何调整Linux内核启动中的驱动初始化顺序

【问题】
此处我要实现的是将芯片的ID用于网卡MAC地址,网卡驱动是enc28j60_init。
但是,读取芯片ID的函数,在as352x_afe_init模块中,所以要先初始化as352x_afe_init。
此处,内核编译完之后,在生成的system.map中可以看到,
enc28j60_init在as352x_afe_init之前,所以,无法去读芯片ID。
所以我们的目标是,将as352x_afe_init驱动初始化放到enc28j60_init之前,
然后才能读取芯片ID,才能用于网卡初始化的时候的,将芯片ID设置成网卡MAC地址。

解决过程】
【1】
最简单想到的,是内核里面的
arch\arm\mach-as352x\core.c
中,去改devices设备列表中的顺序。
enc28j60_init对应的是ssp_device,因为网卡初始化用到的是SPI驱动去进行和通讯的。
as352x_afe_init对应的是afe_device。
原先是:
  1. &uart_device,
  2. &audio_device,
  3. &ssp_device,
  4. {
  5. &nand_device,
  6. &as352xkbd_device,
  7. #define pure_initcall(fn)   __define_initcall("0",fn,1)
  8. #define core_initcall_sync(fn)   __define_initcall("1s",fn,1s)
  9. #define arch_initcall(fn)   __define_initcall("3",fn,3)
  10. #define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
  11. #define rootfs_initcall(fn)   __define_initcall("rootfs",fn,rootfs)
  12. #define late_initcall(fn)   __define_initcall("7",fn,7)
  13. #define __initcall(fn) device_initcall(fn)
复制代码

把自己的驱动的函数名用这些宏去定义之后,
就会对应不同的加载时候的优先级。

其中,我们写驱动中所用到的 module_init对应的是
#define module_init(x) __initcall(x);

#define __initcall(fn) device_initcall(fn)
所以,驱动对应的加载的优先级为6

在上面的不同的优先级中,
数字越小,优先级越高。
同一等级的优先级的驱动,加载顺序是链接过程决定的,结果是不确定的,我们无法去手动设置谁先谁后。
不同等级的驱动加载的顺序是先优先级高,后优先级低,这是可以确定的。

所以,像我们之前在驱动中用:
  1. module_init(as352x_afe_i2c_init);
  2. 。。。
  3. c00197f4 t __initcall_default_rootfsrootfs
  4. 。。。
  5. c00198e0 t __initcall_loopback_init6
  6. c0019900 t __initcall_as352x_spi_init6
  7. c0019920 t __initcall_i2c_dev_init6
  8. 。。。
  9. c0019978 t __initcall_rtc_hctosys7
  10. c001997c T __initcall_end

  11. #define postcore_initcall(fn)   __define_initcall("2",fn,2)
  12. #define arch_initcall_sync(fn)   __define_initcall("3s",fn,3s)
  13. #define fs_initcall(fn)    __define_initcall("5",fn,5)
  14. #if 1
  15. #define device_initcall(fn)   __define_initcall("7",fn,7)
  16. #define late_initcall_sync(fn)   __define_initcall("8s",fn,8s)
  17. #define device_initcall(fn)   __define_initcall("6",fn,6)
  18. #define late_initcall_sync(fn)   __define_initcall("7s",fn,7s)
  19. prev_device_initcall(as352x_afe_i2c_init);
  20. c001997c t __initcall_con_init
  21. #define INITCALLS        \
  22. *(.initcall1.init)       \
  23. *(.initcall2s.init)       \
  24. *(.initcall4.init)       \
  25. *(.initcall5s.init)       \
  26. *(.initcall6s.init)       \
  27. *(.initcall8.init)       \
  28. #else
  29. *(.initcall0.init)       \
  30. *(.initcall1s.init)       \
  31. *(.initcall3.init)       \
  32. *(.initcall4s.init)       \
  33. *(.initcallrootfs.init)       \
  34. *(.initcall7.init)       \
  35. #endif
复制代码

最后,再重新编译,就可以实现我们要的,
和afe相关的驱动初始化,都在网卡enc28j60_init之前了。
也就可以在网卡里面读芯片ID了。
当然,对应编译生成的system.map文件中,
对应的通过module_init定义的驱动,优先级也都变成7了。
而late_initcall对应优先级8了。

注:当前 开发板arm的板子,所以,对应的load 脚本在:

linux-2.6.28.4\arch\arm\ kernel\vmlinux.lds

看起来,应该是这个文件:

linux-2.6.28.4\arch\arm\kernel\vmlinux.lds.S

生成上面那个脚本的。

vmlinux.lds中的这一行:

  1. <li "lucida="" console"',="" '"courier="" new"',="" serif;="" font-size:="" 12px;="" "="" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 2em; list-style-type: decimal-leading-zero; list-style-position: initial; list-style-image: initial; word-wrap: break-word; line-height: 1.8em; ">__initcall_start = .;
    <li "lucida="" console"',="" '"courier="" new"',="" serif;="" font-size:="" 12px;="" "="" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 2em; list-style-type: decimal-leading-zero; list-style-position: initial; list-style-image: initial; word-wrap: break-word; line-height: 1.8em; ">   *(.initcallearly.init) __early_initcall_end = .; *(.initcall0.init) *(.initcall0s.init) *(.initcall1.init) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initcall4.init) *(.initcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.init) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init)
复制代码

就是将之前那些对应的init类型的函数,展开,放到这对应的位置。

【3】
不过,最后的最后,竟然发现网卡还是工作不正常,结果第二天,无意间发现是网卡地址设置导致网卡工作不正常的。
也就是说,实际是直接将afe设置到原先的优先级5就可以的,而不用这么麻烦去改 系统的东西的。。。

不过,至少这也是一种办法,虽然不是那么的好。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值