Skip to content

Commit f16d9fb

Browse files
Jerry Lvsre
authored andcommitted
power: supply: bq27xxx: Retrieve again when busy
Multiple applications may access the battery gauge at the same time, so the gauge may be busy and EBUSY will be returned. The driver will set a flag to record the EBUSY state, and this flag will be kept until the next periodic update. When this flag is set, bq27xxx_battery_get_property() will just return ENODEV until the flag is updated. Even if the gauge was busy during the last accessing attempt, returning ENODEV is not ideal, and can cause confusion in the applications layer. Instead, retry accessing the I2C to update the flag is as expected, for the gauge typically recovers from busy state within a few milliseconds. If still failed to access the gauge, the real error code would be returned instead of ENODEV (as suggested by Pali Rohár). Reviewed-by: Pali Rohár <pali@kernel.org> Signed-off-by: Jerry Lv <Jerry.Lv@axis.com> Link: https://lore.kernel.org/r/20250415-foo-fix-v2-1-5b45a395e4cc@axis.com Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
1 parent 1e3e2cf commit f16d9fb

File tree

2 files changed

+13
-2
lines changed

2 files changed

+13
-2
lines changed

drivers/power/supply/bq27xxx_battery.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2131,7 +2131,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
21312131
mutex_unlock(&di->lock);
21322132

21332133
if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
2134-
return -ENODEV;
2134+
return di->cache.flags;
21352135

21362136
switch (psp) {
21372137
case POWER_SUPPLY_PROP_STATUS:

drivers/power/supply/bq27xxx_battery_i2c.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Andrew F. Davis <afd@ti.com>
77
*/
88

9+
#include <linux/delay.h>
910
#include <linux/i2c.h>
1011
#include <linux/interrupt.h>
1112
#include <linux/module.h>
@@ -31,6 +32,7 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
3132
struct i2c_msg msg[2];
3233
u8 data[2];
3334
int ret;
35+
int retry = 0;
3436

3537
if (!client->adapter)
3638
return -ENODEV;
@@ -47,7 +49,16 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
4749
else
4850
msg[1].len = 2;
4951

50-
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
52+
do {
53+
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
54+
if (ret == -EBUSY && ++retry < 3) {
55+
/* sleep 10 milliseconds when busy */
56+
usleep_range(10000, 11000);
57+
continue;
58+
}
59+
break;
60+
} while (1);
61+
5162
if (ret < 0)
5263
return ret;
5364

0 commit comments

Comments
 (0)