max1720x_battery: use single mutex lock for protection
- add chip->history_ok to avoid multiple execution
- use single lock(chip->model_lock) for protection.
- fix history update condition when cycle count is fixed.
Bug: 322426625
Test: max1720x_check_history() only run once.
history can be updated after cycle count fix from 770 to 210
Merged-In: I84e3e1d5dce52b848efc37c496ba49a411380623
Change-Id: I9c8a0568722eccea42ac28037c8c9054682e886b
Signed-off-by: Spade Lee <[email protected]>
diff --git a/google_battery.c b/google_battery.c
index 8943870..57b134a 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -8911,8 +8911,14 @@
if (cycle_cnt <= 0)
return -EIO;
- if (cycle_cnt != batt_drv->cycle_count)
+ /*
+ * if cycle count mismatch is fixed, fg cycle count < cache cycle count
+ * update batt_drv->hist_data_saved_cnt to be able to update history
+ */
+ if (cycle_cnt < batt_drv->cycle_count) {
batt_drv->cycle_count = cycle_cnt;
+ batt_drv->hist_data_saved_cnt = cycle_cnt - 1;
+ }
if (batt_drv->blf_collect_now) {
pr_info("MSC_HIST cycle_cnt:%d->%d saved_cnt=%d\n",
diff --git a/max1720x_battery.c b/max1720x_battery.c
index 7ed22c7..80909b4 100644
--- a/max1720x_battery.c
+++ b/max1720x_battery.c
@@ -191,8 +191,9 @@
int model_reload;
bool model_ok; /* model is running */
bool cycle_reg_ok; /* restore cycle count from storage complete */
+ bool history_ok; /* history is validated */
- /* history */
+ /* max1720x history */
struct mutex history_lock;
int hcmajor;
struct cdev hcdev;
@@ -1151,10 +1152,12 @@
struct max1720x_chip *chip = power_supply_get_drvdata(psy);
int ret;
- if (buf[0] == '1') {
+ mutex_lock(&chip->model_lock);
+ if (buf[0] == '1' && !chip->por && !chip->history_ok) {
ret = max1720x_check_history(chip, true);
dev_info(chip->dev, "%s: fix cycle count (ret=%d)\n", __func__, ret);
}
+ mutex_unlock(&chip->model_lock);
return count;
}
@@ -1618,7 +1621,7 @@
return ret < 0 ? ret : 0;
}
-/* needs mutex_lock(&chip->model_lock) && mutex_lock(&chip->history_lock) */
+/* call holding chip->model_lock */
static int max1720x_check_history(struct max1720x_chip *chip, bool fix)
{
struct max17x0x_eeprom_history temp = { 0 };
@@ -1626,7 +1629,7 @@
const int last_cycle_count = chip->cycle_count;
if (chip->cycle_count_offset < MAXIM_CYCLE_COUNT_RESET)
- return 0;
+ goto done;
/* when the last entry before the overflow is non empty we are good */
ret = gbms_storage_read_data(GBMS_TAG_HIST, &temp, sizeof(temp),
@@ -1635,39 +1638,47 @@
return ret;
if (!max1720x_history_empty(&temp))
- return 0;
+ goto done;
/* # of entries that need to be moved from OVERFLOW_START_ENTRY */
misplaced_count = max1720x_find_empty(OVERFLOW_START_ENTRY);
if (misplaced_count <= 0)
- return 0;
+ goto done;
/* where entries will be moved to */
first_empty = max1720x_find_empty(0);
if (first_empty >= OVERFLOW_START_ENTRY)
- return 0;
+ goto done;
est_cycle = (first_empty + DIV_ROUND_UP(last_cycle_count, EEPROM_DELTA_CYCLE) -
OVERFLOW_START_ENTRY) * EEPROM_DELTA_CYCLE;
- if (fix) {
- ret = max1720x_recover_history(chip, first_empty, misplaced_count, est_cycle);
- /* log first empty after recovery and result */
- first_empty = max1720x_find_empty(0);
+ if (!fix) {
gbms_logbuffer_devlog(chip->monitor_log, chip->dev,
- LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
- "0x%04X 00:%04X 01:%04X 02:%04X 03:%04X", MONITOR_TAG_HV,
- first_empty, ret, last_cycle_count, chip->cycle_count);
- return ret;
+ LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
+ "0x%04X 00:%04X 01:%04X 02:%04X 03:%04X", MONITOR_TAG_HV,
+ first_empty, misplaced_count, last_cycle_count, est_cycle);
+
+ return 0;
}
+ ret = max1720x_recover_history(chip, first_empty, misplaced_count, est_cycle);
+ /* log first empty after recovery and result */
+ first_empty = max1720x_find_empty(0);
gbms_logbuffer_devlog(chip->monitor_log, chip->dev,
- LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
- "0x%04X 00:%04X 01:%04X 02:%04X 03:%04X", MONITOR_TAG_HV,
- first_empty, misplaced_count, last_cycle_count, est_cycle);
+ LOGLEVEL_INFO, 0, LOGLEVEL_INFO,
+ "0x%04X 00:%04X 01:%04X 02:%04X 03:%04X", MONITOR_TAG_HV,
+ first_empty, ret, last_cycle_count, chip->cycle_count);
+
+ if (ret < 0)
+ return ret;
+
+done:
+ chip->history_ok = true;
return 0;
}
+/* call holding chip->model_lock */
static int max1720x_restore_battery_cycle(struct max1720x_chip *chip)
{
int ret;
@@ -1720,9 +1731,7 @@
chip->cycle_count = reg_to_cycles((u32)reg_cycle, chip->gauge_type) +
chip->cycle_count_offset;
chip->cycle_reg_ok = true;
- mutex_lock(&chip->history_lock);
max1720x_check_history(chip, false);
- mutex_unlock(&chip->history_lock);
return 0;
}
@@ -1813,17 +1822,13 @@
return offset;
}
+/* call holding chip->model_lock */
static int max1720x_get_cycle_count(struct max1720x_chip *chip)
{
- int cc;
-
- mutex_lock(&chip->history_lock);
- cc = chip->cycle_count;
- mutex_unlock(&chip->history_lock);
-
- return cc;
+ return chip->cycle_count;
}
+/* call holding chip->model_lock */
static int max1720x_update_cycle_count(struct max1720x_chip *chip)
{
int err, cycle_count;
@@ -1839,9 +1844,7 @@
/* if cycle reg hasn't been restored from storage, restore it before update cycle count */
if (!chip->cycle_reg_ok && chip->gauge_type == MAX_M5_GAUGE_TYPE &&
max_m5_recal_state(chip->model_data) == RE_CAL_STATE_IDLE) {
- mutex_lock(&chip->model_lock);
err = max1720x_restore_battery_cycle(chip);
- mutex_unlock(&chip->model_lock);
if (err < 0)
dev_err(chip->dev, "%s cannot restore cycle count (%d)\n", __func__, err);
@@ -3338,21 +3341,24 @@
if (fg_status & MAX1720X_STATUS_DSOCI) {
const bool plugged = chip->cap_estimate.cable_in;
- if (max1720x_check_drift_on_soc(&chip->drift_data))
- max1720x_fixup_capacity(chip, plugged);
+ mutex_lock(&chip->model_lock);
+ if (!chip->por) {
+ if (max1720x_check_drift_on_soc(&chip->drift_data))
+ max1720x_fixup_capacity(chip, plugged);
- if (storm) {
- pr_debug("Force power_supply_change in storm\n");
- } else {
- max1720x_monitor_log_learning(chip, false);
- max1720x_monitor_log_data(chip, false);
- if (chip->gauge_type == MAX_M5_GAUGE_TYPE)
- max_m5_check_recal_state(chip->model_data,
- chip->bhi_recalibration_algo,
- chip->eeprom_cycle);
- max1720x_update_cycle_count(chip);
+ if (storm) {
+ pr_debug("Force power_supply_change in storm\n");
+ } else {
+ max1720x_monitor_log_learning(chip, false);
+ max1720x_monitor_log_data(chip, false);
+ if (chip->gauge_type == MAX_M5_GAUGE_TYPE)
+ max_m5_check_recal_state(chip->model_data,
+ chip->bhi_recalibration_algo,
+ chip->eeprom_cycle);
+ max1720x_update_cycle_count(chip);
+ }
}
-
+ mutex_unlock(&chip->model_lock);
storm = false;
}
@@ -5548,7 +5554,9 @@
/* max_m5 triggers loading of the model in the irq handler on POR */
if (!chip->por && chip->gauge_type == MAX_M5_GAUGE_TYPE) {
+ mutex_lock(&chip->model_lock);
ret = max1720x_restore_battery_cycle(chip);
+ mutex_unlock(&chip->model_lock);
if (ret < 0)
dev_err(chip->dev, "%s cannot restore cycle count (%d)\n", __func__, ret);
@@ -5771,6 +5779,8 @@
{
struct device *hcdev;
+ mutex_init(&chip->history_lock);
+
chip->hcmajor = -1;
/* cat /proc/devices */
@@ -6186,7 +6196,9 @@
switch (tag) {
case GBMS_TAG_CLHI:
+ mutex_lock(&chip->model_lock);
ret = max17x0x_collect_history_data(buff, size, chip);
+ mutex_unlock(&chip->model_lock);
break;
default:
@@ -6595,7 +6607,6 @@
/* fuel gauge model needs to know the batt_id */
mutex_init(&chip->model_lock);
- mutex_init(&chip->history_lock);
chip->get_prop_ws = wakeup_source_register(NULL, "GetProp");
if (!chip->get_prop_ws)