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

Commit 65382619 authored by Kiran Gunda's avatar Kiran Gunda Committed by Gerrit - the friendly Code Review server
Browse files

power: supply: qti_battery_charger: Handle probe failure gracefully



Due to a race condition between the probe and glink message
callback, it is observed that the glink messages/notifications
can be handled even after the probe failure which leads to
an invalid memory access. Fix it by introducing "initialized"
flag. While at it, add few error logs to identify the exact
message failures.

Change-Id: I18e61dea734efde6a11ee072793da8eead269b12
Signed-off-by: default avatarKiran Gunda <kgunda@codeaurora.org>
parent 35d006a9
Loading
Loading
Loading
Loading
+25 −5
Original line number Diff line number Diff line
@@ -237,6 +237,8 @@ struct battery_chg_dev {
	u32				last_fcc_ua;
	u32				usb_icl_ua;
	bool				restrict_chg_en;
	/* To track the driver initialization status */
	bool				initialized;
};

static const int battery_prop_map[BATT_PROP_MAX] = {
@@ -719,6 +721,12 @@ static int battery_chg_callback(void *priv, void *data, size_t len)
	pr_debug("owner: %u type: %u opcode: %#x len: %zu\n", hdr->owner,
		hdr->type, hdr->opcode, len);

	if (!bcdev->initialized) {
		pr_debug("Driver initialization failed: Dropping glink callback message: state %d\n",
			 bcdev->state);
		return 0;
	}

	if (hdr->opcode == BC_NOTIFY_IND)
		handle_notification(bcdev, data, len);
	else
@@ -810,8 +818,10 @@ static int usb_psy_set_icl(struct battery_chg_dev *bcdev, u32 prop_id, int val)
	int rc;

	rc = read_property_id(bcdev, pst, USB_ADAP_TYPE);
	if (rc < 0)
	if (rc < 0) {
		pr_err("Failed to read prop USB_ADAP_TYPE, rc=%d\n", rc);
		return rc;
	}

	/* Allow this only for SDP or USB_PD and not for other charger types */
	if (pst->prop[USB_ADAP_TYPE] != POWER_SUPPLY_USB_TYPE_SDP &&
@@ -830,7 +840,9 @@ static int usb_psy_set_icl(struct battery_chg_dev *bcdev, u32 prop_id, int val)
		temp = UINT_MAX;

	rc = write_property_id(bcdev, pst, prop_id, temp);
	if (!rc) {
	if (rc < 0) {
		pr_err("Failed to set ICL (%u uA) rc=%d\n", temp, rc);
	} else {
		pr_debug("Set ICL to %u\n", temp);
		bcdev->usb_icl_ua = temp;
	}
@@ -1730,8 +1742,11 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev)
	len = rc;

	rc = read_property_id(bcdev, pst, BATT_CHG_CTRL_LIM_MAX);
	if (rc < 0)
	if (rc < 0) {
		pr_err("Failed to read prop BATT_CHG_CTRL_LIM_MAX, rc=%d\n",
			rc);
		return rc;
	}

	prev = pst->prop[BATT_CHG_CTRL_LIM_MAX];

@@ -1862,13 +1877,16 @@ static int battery_chg_probe(struct platform_device *pdev)
		return rc;
	}

	bcdev->initialized = true;
	bcdev->reboot_notifier.notifier_call = battery_chg_ship_mode;
	bcdev->reboot_notifier.priority = 255;
	register_reboot_notifier(&bcdev->reboot_notifier);

	rc = battery_chg_parse_dt(bcdev);
	if (rc < 0)
	if (rc < 0) {
		dev_err(dev, "Failed to parse dt rc=%d\n", rc);
		goto error;
	}

	bcdev->restrict_fcc_ua = DEFAULT_RESTRICT_FCC_UA;
	platform_set_drvdata(pdev, bcdev);
@@ -1881,7 +1899,7 @@ static int battery_chg_probe(struct platform_device *pdev)
	bcdev->battery_class.class_groups = battery_class_groups;
	rc = class_register(&bcdev->battery_class);
	if (rc < 0) {
		pr_err("Failed to create battery_class rc=%d\n", rc);
		dev_err(dev, "Failed to create battery_class rc=%d\n", rc);
		goto error;
	}

@@ -1891,6 +1909,8 @@ static int battery_chg_probe(struct platform_device *pdev)

	return 0;
error:
	bcdev->initialized = false;
	complete(&bcdev->ack);
	pmic_glink_unregister_client(bcdev->client);
	unregister_reboot_notifier(&bcdev->reboot_notifier);
	return rc;