Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4dba5345 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

power: qpnp-fg-gen3: Fix possible integer overflow



Currently, DIV_ROUND_CLOSEST is used while finding the delta
between initial and final cc_soc_sw in terms of percentage. This
can go beyond 32 bits with the intermediate multiplication before
it is down-converted back to less than 32 bits. Fix this.

Also, when the cc_soc_sw delta is less than 50 %, discard the
data so that the last learned capacity won't be updated.

While at it, fix a similar use of DIV_ROUND_CLOSEST in another
place fg_encode_default() where an integer overflow can happen
if it is passed with large integer values.

Change-Id: Ia2b0f5456663a90bcd32a4fed52d1e579cff4e1f
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 5404e350
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -491,7 +491,7 @@ static void fg_encode_default(struct fg_sram_param *sp,
	int i, mask = 0xff;
	int64_t temp;

	temp = DIV_ROUND_CLOSEST(val * sp[id].numrtr, sp[id].denmtr);
	temp = (int64_t)div_s64((s64)val * sp[id].numrtr, sp[id].denmtr);
	pr_debug("temp: %llx id: %d, val: %d, buf: [ ", temp, id, val);
	for (i = 0; i < sp[id].len; i++) {
		buf[i] = temp & mask;
@@ -1315,9 +1315,16 @@ static int fg_cap_learning_process_full_data(struct fg_chip *chip)
		return rc;
	}

	cc_soc_delta_pct = DIV_ROUND_CLOSEST(
				abs(cc_soc_sw - chip->cl.init_cc_soc_sw) * 100,
	cc_soc_delta_pct =
		div64_s64((int64_t)(cc_soc_sw - chip->cl.init_cc_soc_sw) * 100,
			CC_SOC_30BIT);

	/* If the delta is < 50%, then skip processing full data */
	if (cc_soc_delta_pct < 50) {
		pr_err("cc_soc_delta_pct: %d\n", cc_soc_delta_pct);
		return -ERANGE;
	}

	delta_cc_uah = div64_s64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
				100);
	chip->cl.final_cc_uah = chip->cl.init_cc_uah + delta_cc_uah;
@@ -1387,7 +1394,6 @@ out:
	return rc;
}

#define FULL_SOC_RAW	255
static void fg_cap_learning_update(struct fg_chip *chip)
{
	int rc, batt_soc, batt_soc_msb;