- 问题背景:
新平台 lcd hdf化第一版已经完成的情况,内核合入了一个drm的大patch,合入后,第一版的hdf出现亮屏后突然黑屏问题,且按power无法亮屏。问题必现
- 定位过程:
通过几次复现,发现出现问题的时候会有这样的打印,几乎同时间,好的版本中没有红色部分打印
[ 33.765684] vcc3v3_lcd0_n: disabling
[ 33.765723] vcc3v3_lcd1_n: disabling
[ 33.765772] pcie30_3v3: disabling
此时示波器测量lcd电源,电源电压为0。
查询dts,vcc3v3_lcd0_n为mipi的power-supply
此时根据上述现象基本可以判断,lcd的电被下了
那么问题来了,谁下了我的电?
问题发生时候,查看vcc3v3_lcd0_n的debug节点如下:
此时查看enable节点
发现问题发生时候enable为0,正常应该是1.
于是在刚开机的时候就去cat该节点,发现刚开始画面出来的时候一直是1,当失去画面的时候突然为0,这也证实了确实是有其他动作下了这个电,那么是谁呢?
插曲:此时手动向该值写1,能写进去值,电压也有,但是屏不亮,这是正常的,因为下电再上电,只是电源通了,但是还是需要重新走上电写初始化参数的动作的,此时没写所以不亮正常。
根据经验,怀疑以下动作关电:
- 系统休眠,确实该版本有超时5s休眠的动作
- 哪个模块显式的关闭了这个电。
- 上层直接通过/sys/kernel/debug/regulator/vcc3v3_lcd0_n/enable节点关电
针对怀疑1:关闭休眠动作,问题仍然复现,排除
针对怀疑2:做了如下实验,在代码中显式的调用regulator_disable接口,但是此时并没有打印出类似vcc3v3_lcd0_n: disabling的打印,这条怀疑也排除
针对怀疑3:根据打印看,并不只是单独关闭该regulator,而且上层也不会定点的open这种特殊节点去操作,除非有特殊特性需求,也基本可以排除。
此时陷入僵局,没有思路,询问rk的显示负责人,也没有思路。
没办法,只能做最苦力的方法,搜打印。
根据经验,如果直接搜索disabling,那么结果太多,根本没法看,所以就搜索:
“: disabling”这个格式,但是整个内核搜完也没有搜到,没办法整个工程搜,也没有搜到。此时再次陷入僵局
喝口茶,冷静的想了下,看了下打印:
[ 33.765574] vcc5v0_otg: disabling
[ 33.765684] vcc3v3_lcd0_n: disabling
[ 33.765723] vcc3v3_lcd1_n: disabling
[ 33.765772] pcie30_3v3: disabling
非常整齐的操作,且disable的都是regulator的节点,更像是一种统一的操作手法,于是尝试在linux-5.10/drivers/regulator下直接搜索disabling关键字
找到一个最像的,跟进去
果然是这里,这里是个拼接打印。。。。
能找到这里问题就不大了,可以正向看这个问题。大概梳理了下代码逻辑,这是regulator的核心层逻辑
regulator_init_complete这里核心层的入口,这里会开启一个内核工作队列,起一个task
schedule_delayed_work(®ulator_init_complete_work,
msecs_to_jiffies(30000));
static DECLARE_DELAYED_WORK(regulator_init_complete_work,
regulator_init_complete_work_function);
regulator_init_complete_work_function每30000个滴答时间启动一次
task中干这个事:
即遍历regulator_class上的所有设备,然后执行regulator_late_cleanup。
这里就是出现打印的状态,跟了下,有如下几种情况会走到这个分支
1.电源没有被使用
2. 电源没有被使能
这2点很好排查,直接看regulator节点,查看
这2个节点就可以
此时问题复现后,查看enable刚开是为1,条件满足,查看use_count为0,这个条件不满足,所以会进入清理分支,就看到我们的打印
到这里整个问题就被扒的很干净,原理也很清晰了,瞬间感觉腰也不疼了,眼睛也花了,这感觉来了。
问题就聚焦在了为何use_count为0上,当使用regulator_enable使能该power-supply时,这个值就会累加。那就意味着,出问题的时候,这个power资源就没使用。
后排查代码,找到了问题点:
在drm 大patch合入后,将一个regulator_enable的接口给置为空了,所以这个power为闲置状态,被regulator的这个守护线程给清理掉了
至此该问题结束
遗留点:此次最终通过非常显著的log信息找到regulator子系统的关键逻辑代码,进而反推出驱动代码本身的使用问题。那若是关键逻辑代码本身没有打印,这个问题又该如何定位?