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

Commit 496458cb authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "esoc: Add support for client hooks based on priority"

parents 3b9f55d4 f41dec67
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/workqueue.h>
#include <linux/reboot.h>
#include <linux/of.h>
#include <linux/esoc_client.h>
#include "esoc.h"
#include "mdm-dbg.h"

@@ -105,6 +106,39 @@ static void mdm_ssr_fn(struct work_struct *work)
	esoc_clink_request_ssr(mdm_drv->esoc_clink);
}

static void esoc_client_link_power_on(struct esoc_clink *esoc_clink,
							bool mdm_crashed)
{
	int i;
	struct esoc_client_hook *client_hook;

	dev_dbg(&esoc_clink->dev, "Calling power_on hooks\n");

	for (i = 0; i < ESOC_MAX_HOOKS; i++) {
		client_hook = esoc_clink->client_hook[i];
		if (client_hook && client_hook->esoc_link_power_on)
			client_hook->esoc_link_power_on(client_hook->priv,
							mdm_crashed);
	}
}

static void esoc_client_link_power_off(struct esoc_clink *esoc_clink,
							bool mdm_crashed)
{
	int i;
	struct esoc_client_hook *client_hook;

	dev_dbg(&esoc_clink->dev, "Calling power_off hooks\n");

	for (i = 0; i < ESOC_MAX_HOOKS; i++) {
		client_hook = esoc_clink->client_hook[i];
		if (client_hook && client_hook->esoc_link_power_off) {
			client_hook->esoc_link_power_off(client_hook->priv,
							mdm_crashed);
		}
	}
}

static void mdm_crash_shutdown(const struct subsys_desc *mdm_subsys)
{
	struct esoc_clink *esoc_clink =
@@ -134,6 +168,9 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys,
			 * to move to next stage
			 */
			return 0;

		esoc_client_link_power_off(esoc_clink, true);

		ret = clink_ops->cmd_exe(ESOC_PREPARE_DEBUG,
							esoc_clink);
		if (ret) {
@@ -159,6 +196,7 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys,
			return ret;
		}
		mdm_drv->mode = PWR_OFF;
		esoc_client_link_power_off(esoc_clink, false);
	}
	return 0;
}
@@ -185,6 +223,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys)
			dev_err(&esoc_clink->dev, "pwr on fail\n");
			return ret;
		}
		esoc_client_link_power_on(esoc_clink, false);
	} else if (mdm_drv->mode == IN_DEBUG) {
		ret = clink_ops->cmd_exe(ESOC_EXIT_DEBUG, esoc_clink);
		if (ret) {
@@ -197,6 +236,7 @@ static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys)
			dev_err(&esoc_clink->dev, "pwr on fail\n");
			return ret;
		}
		esoc_client_link_power_on(esoc_clink, true);
	}

	/*
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/cdev.h>
#include <linux/completion.h>
#include <linux/esoc_ctrl.h>
#include <linux/esoc_client.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -89,6 +90,7 @@ struct esoc_clink {
	bool primary;
	bool statusline_not_a_powersource;
	bool userspace_handle_shutdown;
	struct esoc_client_hook *client_hook[ESOC_MAX_HOOKS];
};

/**
+64 −0
Original line number Diff line number Diff line
@@ -142,3 +142,67 @@ void notify_esoc_clients(struct esoc_clink *esoc_clink, unsigned long evt)
	spin_unlock_irqrestore(&notify_lock, flags);
}
EXPORT_SYMBOL(notify_esoc_clients);

int esoc_register_client_hook(struct esoc_desc *desc,
				struct esoc_client_hook *client_hook)
{
	int i;
	struct esoc_clink *esoc_clink;

	if (IS_ERR_OR_NULL(desc) || IS_ERR_OR_NULL(client_hook)) {
		pr_debug("%s: Invalid parameters\n", __func__);
		return -EINVAL;
	}

	esoc_clink = desc->priv;
	if (IS_ERR_OR_NULL(esoc_clink)) {
		pr_debug("%s: Invalid esoc link\n", __func__);
		return -EINVAL;
	}

	for (i = 0; i < ESOC_MAX_HOOKS; i++) {
		if (i == client_hook->prio &&
			esoc_clink->client_hook[i] == NULL) {
			esoc_clink->client_hook[i] = client_hook;
			dev_dbg(&esoc_clink->dev,
				"Client hook registration successful\n");
			return 0;
		}
	}

	dev_dbg(&esoc_clink->dev, "Client hook registration failed!\n");
	return -EINVAL;
}
EXPORT_SYMBOL(esoc_register_client_hook);

int esoc_unregister_client_hook(struct esoc_desc *desc,
				struct esoc_client_hook *client_hook)
{
	int i;
	struct esoc_clink *esoc_clink;

	if (IS_ERR_OR_NULL(desc) || IS_ERR_OR_NULL(client_hook)) {
		pr_debug("%s: Invalid parameters\n", __func__);
		return -EINVAL;
	}

	esoc_clink = desc->priv;
	if (IS_ERR_OR_NULL(esoc_clink)) {
		pr_debug("%s: Invalid esoc link\n", __func__);
		return -EINVAL;
	}

	for (i = 0; i < ESOC_MAX_HOOKS; i++) {
		if (i == client_hook->prio &&
			esoc_clink->client_hook[i] != NULL) {
			esoc_clink->client_hook[i] = NULL;
			dev_dbg(&esoc_clink->dev,
				"Client hook unregistration successful\n");
			return 0;
		}
	}

	dev_dbg(&esoc_clink->dev, "Client hook unregistration failed!\n");
	return -EINVAL;
}
EXPORT_SYMBOL(esoc_unregister_client_hook);
+47 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/esoc_client.h>
#include "esoc.h"

/**
@@ -172,6 +173,50 @@ void esoc_udev_handle_clink_evt(enum esoc_evt evt, struct esoc_eng *eng)
	wake_up_interruptible(&esoc_udev->evt_wait);
}

static int esoc_get_link_id(struct esoc_clink *esoc_clink,
						unsigned long arg)
{
	struct esoc_link_data link_data;
	struct esoc_client_hook *client_hook;
	struct esoc_link_data __user *user_arg;

	user_arg = (struct esoc_link_data __user *) arg;
	if (!user_arg) {
		dev_err(&esoc_clink->dev, "Missing argument for link id\n");
		return -EINVAL;
	}

	if (copy_from_user((void *) &link_data, user_arg, sizeof(*user_arg))) {
		dev_err(&esoc_clink->dev,
			"Unable to copy the data from the user\n");
		return -EFAULT;
	}

	if (link_data.prio < 0 || link_data.prio >= ESOC_MAX_HOOKS) {
		dev_err(&esoc_clink->dev, "Invalid client identifier passed\n");
		return -EINVAL;
	}

	client_hook = esoc_clink->client_hook[link_data.prio];
	if (client_hook && client_hook->esoc_link_get_id) {
		link_data.link_id =
		client_hook->esoc_link_get_id(client_hook->priv);

		if (copy_to_user((void *) user_arg, &link_data,
						sizeof(*user_arg))) {
			dev_err(&esoc_clink->dev,
				"Failed to send the data to the user\n");
			return -EFAULT;
		}

		return 0;
	}

	dev_err(&esoc_clink->dev,
			"Client hooks not registered for the device\n");
	return -EINVAL;
}

static long esoc_dev_ioctl(struct file *file, unsigned int cmd,
						unsigned long arg)
{
@@ -246,6 +291,8 @@ static long esoc_dev_ioctl(struct file *file, unsigned int cmd,
			put_user(evt, (unsigned int __user *)uarg);
		}
		return err;
	case ESOC_GET_LINK_ID:
		return esoc_get_link_id(esoc_clink, arg);
	default:
		return -EINVAL;
	};
+23 −0
Original line number Diff line number Diff line
@@ -16,6 +16,15 @@
#include <linux/esoc_ctrl.h>
#include <linux/notifier.h>

struct esoc_client_hook {
	char *name;
	void *priv;
	enum esoc_client_hook_prio prio;
	int (*esoc_link_power_on)(void *priv, bool mdm_crashed);
	void (*esoc_link_power_off)(void *priv, bool mdm_crashed);
	u64 (*esoc_link_get_id)(void *priv);
};

/*
 * struct esoc_desc: Describes an external soc
 * @name: external soc name
@@ -35,6 +44,10 @@ struct esoc_desc *devm_register_esoc_client(struct device *dev,
void devm_unregister_esoc_client(struct device *dev,
						struct esoc_desc *esoc_desc);
int esoc_register_client_notifier(struct notifier_block *nb);
int esoc_register_client_hook(struct esoc_desc *desc,
				struct esoc_client_hook *client_hook);
int esoc_unregister_client_hook(struct esoc_desc *desc,
				struct esoc_client_hook *client_hook);
#else
static inline struct esoc_desc *devm_register_esoc_client(struct device *dev,
							const char *name)
@@ -49,5 +62,15 @@ static inline int esoc_register_client_notifier(struct notifier_block *nb)
{
	return -EIO;
}
int esoc_register_client_hook(struct esoc_desc *desc,
				struct esoc_client_hook *client_hook)
{
	return -EIO;
}
int esoc_unregister_client_hook(struct esoc_desc *desc,
				struct esoc_client_hook *client_hook);
{
	return -EIO;
}
#endif
#endif
Loading