Linux设备驱动有标准的结构,注册的时候对比device和driver的名字,如果相等就调用probe函数将资源注册进去,但是如果注册失败,在probe中途退出的时候要注意,如果直接退出,但是原来注册了部分资源,如果不设置错误原因的参数返回,默认是成功返回这样,错误的驱动就会被其他资源使用,但是由于没有完成注册好,缺少资源。或者由于注册失败在中途退出虽然将原来的资源释放掉了,但是probe没有设置错误原因,结果被认为注册成功。这样别的地方调用驱动就会出问题。会空指针引起死机。
另一方面,如果某个设备坏了,或者没有装上某个设备,执行probe探测函数的时候,如果代码结构不好,开始先执行部分申请了资源代码,然后做设备探测,如果探测不到设备就退出注册驱动过程,但是退出的过程没有释放前面申请的资源,结果就会引起副作用,比如待机电流大,待机死机。
比如,编写camera驱动,如果流程不对,在probe的时候先申请camera控制器的时钟,把控制器的时钟打开了,但是由于camera有问题,导致后面的初始化出错,就退出注册,但是没有按照注册的反方向将资源释放,没有将控制器时钟资源释放,没有关闭camera的控制器时钟。由于注册不成功,没有将suspend和resume注册进去驱动链表,睡眠的时候不会执行suspend函数,不会关闭camera控制器的时钟,导致时钟的投票关闭不通过,19M的时钟不会关闭,系统能够睡眠,但是睡眠电流就有接近17ma的电流(正常睡眠电流是2ma)。另外正常工作的电流也比原来大。这种情况可以no_console_suspend添加到命令行,用示波器看看19M时钟在系统睡眠状态是否存在。在睡眠模块将时钟树打印出来,看那个时钟打开。
如果注册某个设备,已经将设备节点注册到了链表,但是中途出错,退出的时候又没有将节点释放,结果suspend函数指针是空的,睡眠的时候调用到这个设备的suspend函数就会由于空指针引起死机。
正常的流程是注册过程失败的时候,要按照申请资源的反方向将原来申请的资源释放掉,否则会出现孤儿资源,包括内存泄漏,打开了设备的电源没有关闭导致电流过大,打开了控制器时钟没有关闭导致电流过大,孤儿资源导致空指针引起panic等等的问题。虽然这里就几行文字,但这是多年的经验。也是比较难查的问题