[ 5.567108][ T1] CALLER: bq25790_probe+0x594/0x764, func:regmap_write [ 5.567112][ T1] bqHGQ---------------------------------------------reg: 0x02, val: 0xa4, func:regmap_write, line:1949, file:drivers/base/regmap/regmap.c [ 5.567752][ T1] bqHGQ---------------------------func:bq25790_set_input_volt_lim, line:413, file:drivers/power/supply/bq25790_charger.c为什么bq25790_set_input_volt_lim调用regmap_write,log打印的是bq25790_probe
时间: 2025-04-25 17:38:39 浏览: 23
<think>好的,我现在需要分析用户的问题:当调用bq25790_set_input_volt_lim函数时使用regmap_write,但日志中却显示bq25790_probe的原因。用户提到涉及的文件是drivers/power/supply/bq25790_charger.c和drivers/base/regmap/regmap.c。
首先,我应该回忆一下Linux内核驱动的基本结构。通常,probe函数是在设备被检测到时调用的,用于初始化和注册设备。而像设置输入电压限制这样的操作通常是在驱动已经成功probe之后才会进行的。所以,正常情况下,调用regmap_write应该在probe完成之后发生。
接下来,用户提到在调用regmap_write时日志打印了bq25790_probe,这可能意味着在写寄存器的时候probe函数被再次调用了,或者probe函数中的某些代码被执行了。这显然不符合预期,需要找出可能的原因。
可能的原因一:竞态条件或并发问题。比如,在probe函数还未完成初始化时,另一个线程(如用户空间的某个操作)调用了bq25790_set_input_volt_lim,导致regmap_write被调用,而此时regmap结构可能尚未完全初始化,或者设备还未准备好,触发了某些错误处理路径,进而重新探测设备。
可能的原因二:regmap配置错误。在bq25790_probe中,如果regmap的配置有误,比如寄存器范围、读写权限等设置不正确,当regmap_write被调用时,可能会触发regmap的错误处理机制,例如尝试重新初始化设备,从而导致probe被再次调用。
可能的原因三:电源管理或热插拔事件。如果在运行时发生了某些事件,比如电源断开再连接,可能导致设备被重新探测,从而触发probe函数。这时候,如果正好有regmap_write在操作,可能会在日志中看到probe相关的信息。
接下来需要查看相关代码,特别是bq25790_probe函数和bq25790_set_input_volt_lim函数中的regmap_write调用。在probe函数中,是否在初始化regmap时注册了某些操作,或者是否有错误处理代码可能导致probe被重新调用。例如,如果在regmap_write失败时,驱动程序尝试重新初始化设备,可能会再次调用probe。
另外,检查regmap的配置是否正确。比如,regmap_config结构中的max_register是否设置正确,是否有正确的读写回调函数。如果regmap_write访问了一个超出范围的寄存器,可能会导致regmap报错,并可能触发设备的重新探测。
还有一种可能是,在probe函数中,某些资源(如中断)的注册失败,导致设备被卸载后再次尝试探测,这时候如果有并发的regmap_write操作,可能会看到probe被调用的情况。
此外,内核中的调试日志可能会显示调用栈,这有助于确定probe函数是在什么情况下被调用的。例如,是否在regmap_write的过程中发生了某种错误,导致设备被重新注册,从而触发probe。
总结可能的原因:
1. 并发或竞态条件导致probe未完成时调用了regmap_write。
2. regmap配置错误导致写入失败,触发重新探测。
3. 设备在运行时被重新插入或电源变化导致probe再次调用。
4. 驱动中的错误处理逻辑在regmap_write失败时重新初始化设备。
需要进一步分析代码中的具体实现,尤其是错误处理路径和regmap的配置是否正确。例如,在bq25790_probe函数中,是否有可能在错误处理时重新注册设备,或者regmap的初始化是否有问题。同时,检查regmap_write的调用上下文,是否在probe完成之后才被调用。</think>### 分析`bq25790_set_input_volt_lim`调用`regmap_write`时触发`bq25790_probe`日志的原因
#### 1. **驱动生命周期与函数调用时序**
- **`bq25790_probe`**是驱动初始化函数,负责设备注册、资源分配(如`regmap`初始化)等操作[^1]。
- **`bq25790_set_input_volt_lim`**属于运行时配置接口,需在`probe`完成后才能安全调用。
- **可能原因**:`regmap_write`调用时,设备未完成初始化(例如`probe`未正确返回),导致内核错误地触发重新探测(re-probe),从而打印`bq25790_probe`日志。
#### 2. **`regmap`配置或访问错误**
- **`regmap`初始化问题**:若`bq25790_probe`中`regmap`配置(如寄存器范围、读写权限)错误,`regmap_write`会因非法操作触发内核错误[^2]。
- **错误处理路径**:内核可能在`regmap`访问失败时尝试重新初始化设备(如释放后重新`probe`),导致日志中重复出现`bq25790_probe`。
#### 3. **并发或竞态条件**
- **多线程访问**:若用户空间或内核其他模块在`probe`未完成时调用`bq25790_set_input_volt_lim`,可能导致`regmap`未就绪(例如指针为`NULL`),触发异常。
- **资源竞争**:未正确同步`probe`和运行时接口的访问,可能引发UAF(Use-After-Free)或空指针解引用。
#### 4. **电源管理或热插拔事件**
- **硬件状态变化**:设备在运行时断开并重新连接(如USB热插拔),会触发内核重新调用`probe`函数。若此时`regmap_write`正在执行,日志将同时显示两者信息。
---
### 关键代码段分析(假设场景)
在`drivers/power/supply/bq25790_charger.c`中:
```c
static int bq25790_probe(struct i2c_client *client) {
// 初始化regmap
bq->regmap = devm_regmap_init_i2c(client, &bq25790_regmap_config);
if (IS_ERR(bq->regmap)) {
dev_err(dev, "regmap init failed");
return PTR_ERR(bq->regmap);
}
// 其他初始化...
}
static int bq25790_set_input_volt_lim(struct bq25790_device *bq, u32 volt) {
// 调用regmap_write前未检查regmap状态
return regmap_write(bq->regmap, BQ25790_INPUT_VOLT_LIMIT_REG, volt);
}
```
在`drivers/base/regmap/regmap.c`中,若`regmap_write`检测到寄存器越界或权限错误:
```c
int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) {
if (reg > map->max_register) { // 检查寄存器范围
dev_err(map->dev, "Invalid register %x\n", reg);
return -EINVAL;
}
// 实际写入操作...
}
```
---
### 修复建议
1. **确保`probe`完成前禁用外部调用**:在`probe`函数中设置设备状态标志,运行时接口调用前检查该标志。
2. **添加`regmap`有效性检查**:在`bq25790_set_input_volt_lim`中验证`bq->regmap`是否为`NULL`。
3. **内核日志分析**:通过`dmesg`查看完整调用栈,确认`bq25790_probe`触发时的上下文(如是否因`regmap`错误导致设备重新注册)。
---
阅读全文
相关推荐


















