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

Commit 45122c52 authored by Kavya Nunna's avatar Kavya Nunna Committed by Gerrit - the friendly Code Review server
Browse files

power: smb5-lib: Fix race conditions for typec power role



Currently power_role is accessed by set_prop and get_prop
functions of typec_power_role without any locking mechanism,
there can be a scenario where both function calls were invoked
simultaneously and power_role variable is not correctly
updated, and it leads to enumeration issues when connected to PC.

Fix it by adding locking mechanism to power_role.

Change-Id: I4f5dc38a9536b535510dc2b112712a5cbd2b3f84
Signed-off-by: default avatarKavya Nunna <knunna@codeaurora.org>
parent f22e39f7
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -3785,18 +3785,19 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
		return 0;
	}

	spin_lock(&chg->typec_pr_lock);
	rc = smblib_read(chg, TYPE_C_MODE_CFG_REG, &ctrl);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_MODE_CFG_REG rc=%d\n",
			rc);
		return rc;
		goto unlock;
	}
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_MODE_CFG_REG = 0x%02x\n",
		   ctrl);

	if (ctrl & TYPEC_DISABLE_CMD_BIT) {
		val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
		return rc;
		goto unlock;
	}

	switch (ctrl & (EN_SRC_ONLY_BIT | EN_SNK_ONLY_BIT)) {
@@ -3813,10 +3814,14 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
		val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
		smblib_err(chg, "unsupported power role 0x%02lx\n",
			ctrl & (EN_SRC_ONLY_BIT | EN_SNK_ONLY_BIT));
		return -EINVAL;
		rc = -EINVAL;
		goto unlock;
	}

	chg->power_role = val->intval;
unlock:
	spin_unlock(&chg->typec_pr_lock);

	return rc;
}

@@ -4444,6 +4449,7 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
	if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
		return 0;

	spin_lock(&chg->typec_pr_lock);
	smblib_dbg(chg, PR_MISC, "power role change: %d --> %d!",
			chg->power_role, val->intval);

@@ -4455,7 +4461,7 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
			chg->power_role != POWER_SUPPLY_TYPEC_PR_NONE) {
		smblib_dbg(chg, PR_MISC, "power role already in %d, ignore!",
				chg->power_role);
		return 0;
		goto unlock;
	}

	typec_mode = smblib_get_prop_typec_mode(chg);
@@ -4481,7 +4487,6 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
	smblib_dbg(chg, PR_MISC, "snk_attached = %d, src_attached = %d, is_pr_lock = %d\n",
			snk_attached, src_attached, is_pr_lock);
	cancel_delayed_work(&chg->pr_lock_clear_work);
	spin_lock(&chg->typec_pr_lock);
	if (!chg->pr_lock_in_progress && is_pr_lock) {
		smblib_dbg(chg, PR_MISC, "disable type-c interrupts for power role locking\n");
		smblib_typec_irq_config(chg, false);
@@ -4493,7 +4498,6 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
	}

	chg->pr_lock_in_progress = is_pr_lock;
	spin_unlock(&chg->typec_pr_lock);

	switch (val->intval) {
	case POWER_SUPPLY_TYPEC_PR_NONE:
@@ -4510,7 +4514,8 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
		break;
	default:
		smblib_err(chg, "power role %d not supported\n", val->intval);
		return -EINVAL;
		rc = -EINVAL;
		goto unlock;
	}

	rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
@@ -4519,10 +4524,13 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
	if (rc < 0) {
		smblib_err(chg, "Couldn't write 0x%02x to TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
			power_role, rc);
		return rc;
		goto unlock;
	}

	chg->power_role = val->intval;
unlock:
	spin_unlock(&chg->typec_pr_lock);

	return rc;
}