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)