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

Commit 50888a8a authored by Ashay Jaiswal's avatar Ashay Jaiswal
Browse files

power: pmic-voter: Add API to override votes



Add an API to override votes on a votable. This is useful
in case where one wants to force a value on a MIN/MAX votable
irrespective of its current value.

If two clients vote to override same votable, the latest vote
is set.

Change-Id: Ida14d686905df2c0c3340cc1832ece1bba31b454
Signed-off-by: default avatarAshay Jaiswal <ashayj@codeaurora.org>
Signed-off-by: default avatarSahil Chandna <chandna@codeaurora.org>
parent cf8928d0
Loading
Loading
Loading
Loading
+74 −4
Original line number Diff line number Diff line
@@ -28,12 +28,14 @@ struct client_vote {

struct votable {
	const char		*name;
	const char		*override_client;
	struct list_head	list;
	struct client_vote	votes[NUM_MAX_CLIENTS];
	int			num_clients;
	int			type;
	int			effective_client_id;
	int			effective_result;
	int			override_result;
	struct mutex		vote_lock;
	void			*data;
	int			(*callback)(struct votable *votable,
@@ -270,6 +272,9 @@ int get_effective_result_locked(struct votable *votable)
	if (votable->force_active)
		return votable->force_val;

	if (votable->override_result != -EINVAL)
		return votable->override_result;

	return votable->effective_result;
}

@@ -306,6 +311,9 @@ const char *get_effective_client_locked(struct votable *votable)
	if (votable->force_active)
		return DEBUG_FORCE_CLIENT;

	if (votable->override_result != -EINVAL)
		return votable->override_client;

	return get_client_str(votable, votable->effective_client_id);
}

@@ -416,7 +424,8 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val)
			votable->name, effective_result,
			get_client_str(votable, effective_id),
			effective_id);
		if (votable->callback && !votable->force_active)
		if (votable->callback && !votable->force_active
				&& (votable->override_result == -EINVAL))
			rc = votable->callback(votable, votable->data,
					effective_result,
					get_client_str(votable, effective_id));
@@ -428,6 +437,57 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val)
	return rc;
}

/**
 * vote_override() -
 *
 * @votable:		The votable object
 * @override_client:	The voting client that will override other client's
 *			votes, that are already present. When force_active
 *			and override votes are set on a votable, force_active's
 *			client will have the higher priority and it's vote will
 *			be the effective one.
 * @enabled:		This provides a means for the override client to exclude
 *			itself from election. This client's vote
 *			(the next argument) will be considered only when
 *			it has enabled its participation. When this is
 *			set true, this will force a value on a MIN/MAX votable
 *			irrespective of its current value.
 * @val:		The vote value. This will be effective only if enabled
 *			is set true.
 * Returns:
 *	The result of vote. 0 is returned if the vote
 *	is successfully set by the overriding client, when enabled is set.
 */
int vote_override(struct votable *votable, const char *override_client,
		  bool enabled, int val)
{
	int rc = 0;

	lock_votable(votable);
	if (votable->force_active) {
		votable->override_result = enabled ? val : -EINVAL;
		goto out;
	}

	if (enabled) {
		rc = votable->callback(votable, votable->data,
					val, override_client);
		if (!rc) {
			votable->override_client = override_client;
			votable->override_result = val;
		}
	} else {
		rc = votable->callback(votable, votable->data,
			votable->effective_result,
			get_client_str(votable, votable->effective_client_id));
		votable->override_result = -EINVAL;
	}

out:
	unlock_votable(votable);
	return rc;
}

int rerun_election(struct votable *votable)
{
	int rc = 0;
@@ -482,6 +542,8 @@ static int force_active_set(void *data, u64 val)
{
	struct votable *votable = data;
	int rc = 0;
	int effective_result;
	const char *client;

	lock_votable(votable);
	votable->force_active = !!val;
@@ -494,9 +556,16 @@ static int force_active_set(void *data, u64 val)
			votable->force_val,
			DEBUG_FORCE_CLIENT);
	} else {
		rc = votable->callback(votable, votable->data,
			votable->effective_result,
			get_client_str(votable, votable->effective_client_id));
		if (votable->override_result != -EINVAL) {
			effective_result = votable->override_result;
			client = votable->override_client;
		} else {
			effective_result = votable->effective_result;
			client = get_client_str(votable,
					votable->effective_client_id);
		}
		rc = votable->callback(votable, votable->data, effective_result,
					client);
	}
out:
	unlock_votable(votable);
@@ -604,6 +673,7 @@ struct votable *create_votable(const char *name,
	votable->callback = callback;
	votable->type = votable_type;
	votable->data = data;
	votable->override_result = -EINVAL;
	mutex_init(&votable->vote_lock);

	/*
+4 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */

/*
 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
 */

#ifndef __PMIC_VOTER_H
@@ -27,6 +28,8 @@ int get_effective_result_locked(struct votable *votable);
const char *get_effective_client(struct votable *votable);
const char *get_effective_client_locked(struct votable *votable);
int vote(struct votable *votable, const char *client_str, bool state, int val);
int vote_override(struct votable *votable, const char *override_client,
		  bool state, int val);
int rerun_election(struct votable *votable);
struct votable *find_votable(const char *name);
struct votable *create_votable(const char *name,