Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2017, Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/remoteproc/qcom_rproc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/rpmsg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "qcom_common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) static BLOCKING_NOTIFIER_HEAD(sysmon_notifiers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) struct qcom_sysmon {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	struct rproc_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	struct rproc *rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct mutex state_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	int shutdown_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	int ssctl_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	int ssctl_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	struct notifier_block nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct rpmsg_endpoint *ept;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	struct completion comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	struct completion ind_comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct completion shutdown_comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	bool ssr_ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	struct qmi_handle qmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct sockaddr_qrtr ssctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	SSCTL_SSR_EVENT_BEFORE_POWERUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	SSCTL_SSR_EVENT_AFTER_POWERUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	SSCTL_SSR_EVENT_BEFORE_SHUTDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	SSCTL_SSR_EVENT_AFTER_SHUTDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static const char * const sysmon_state_string[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	[SSCTL_SSR_EVENT_BEFORE_POWERUP]	= "before_powerup",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	[SSCTL_SSR_EVENT_AFTER_POWERUP]		= "after_powerup",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	[SSCTL_SSR_EVENT_BEFORE_SHUTDOWN]	= "before_shutdown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	[SSCTL_SSR_EVENT_AFTER_SHUTDOWN]	= "after_shutdown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) struct sysmon_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	const char *subsys_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	u32 ssr_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static DEFINE_MUTEX(sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static LIST_HEAD(sysmon_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * sysmon_send_event() - send notification of other remote's SSR event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * @sysmon:	sysmon context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * @event:	sysmon event context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static void sysmon_send_event(struct qcom_sysmon *sysmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 			      const struct sysmon_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	char req[50];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	len = snprintf(req, sizeof(req), "ssr:%s:%s", event->subsys_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		       sysmon_state_string[event->ssr_event]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (len >= sizeof(req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	mutex_lock(&sysmon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	reinit_completion(&sysmon->comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	sysmon->ssr_ack = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	ret = rpmsg_send(sysmon->ept, req, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		dev_err(sysmon->dev, "failed to send sysmon event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	ret = wait_for_completion_timeout(&sysmon->comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 					  msecs_to_jiffies(5000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		dev_err(sysmon->dev, "timeout waiting for sysmon ack\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (!sysmon->ssr_ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		dev_err(sysmon->dev, "unexpected response to sysmon event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	mutex_unlock(&sysmon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * sysmon_request_shutdown() - request graceful shutdown of remote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * @sysmon:	sysmon context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static void sysmon_request_shutdown(struct qcom_sysmon *sysmon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	char *req = "ssr:shutdown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	mutex_lock(&sysmon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	reinit_completion(&sysmon->comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	sysmon->ssr_ack = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	ret = rpmsg_send(sysmon->ept, req, strlen(req) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		dev_err(sysmon->dev, "send sysmon shutdown request failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	ret = wait_for_completion_timeout(&sysmon->comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 					  msecs_to_jiffies(5000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		dev_err(sysmon->dev, "timeout waiting for sysmon ack\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (!sysmon->ssr_ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		dev_err(sysmon->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			"unexpected response to sysmon shutdown request\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	mutex_unlock(&sysmon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int sysmon_callback(struct rpmsg_device *rpdev, void *data, int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			   void *priv, u32 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	struct qcom_sysmon *sysmon = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	const char *ssr_ack = "ssr:ack";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	const int ssr_ack_len = strlen(ssr_ack) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (!sysmon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (count >= ssr_ack_len && !memcmp(data, ssr_ack, ssr_ack_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		sysmon->ssr_ack = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	complete(&sysmon->comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define SSCTL_SHUTDOWN_REQ		0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define SSCTL_SHUTDOWN_READY_IND	0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define SSCTL_SUBSYS_EVENT_REQ		0x23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define SSCTL_MAX_MSG_LEN		7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define SSCTL_SUBSYS_NAME_LENGTH	15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	SSCTL_SSR_EVENT_FORCED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	SSCTL_SSR_EVENT_GRACEFUL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct ssctl_shutdown_resp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	struct qmi_response_type_v01 resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static struct qmi_elem_info ssctl_shutdown_resp_ei[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		.data_type	= QMI_STRUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		.elem_len	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		.elem_size	= sizeof(struct qmi_response_type_v01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		.array_type	= NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		.tlv_type	= 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		.offset		= offsetof(struct ssctl_shutdown_resp, resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		.ei_array	= qmi_response_type_v01_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct ssctl_subsys_event_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	u8 subsys_name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	char subsys_name[SSCTL_SUBSYS_NAME_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	u32 event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	u8 evt_driven_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	u32 evt_driven;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static struct qmi_elem_info ssctl_subsys_event_req_ei[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		.data_type	= QMI_DATA_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		.elem_len	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		.elem_size	= sizeof(uint8_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		.array_type	= NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		.tlv_type	= 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		.offset		= offsetof(struct ssctl_subsys_event_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 					   subsys_name_len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		.ei_array	= NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		.data_type	= QMI_UNSIGNED_1_BYTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		.elem_len	= SSCTL_SUBSYS_NAME_LENGTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		.elem_size	= sizeof(char),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		.array_type	= VAR_LEN_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		.tlv_type	= 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		.offset		= offsetof(struct ssctl_subsys_event_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 					   subsys_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		.ei_array	= NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		.data_type	= QMI_SIGNED_4_BYTE_ENUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		.elem_len	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		.elem_size	= sizeof(uint32_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		.array_type	= NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		.tlv_type	= 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		.offset		= offsetof(struct ssctl_subsys_event_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 					   event),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		.ei_array	= NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		.data_type	= QMI_OPT_FLAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		.elem_len	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		.elem_size	= sizeof(uint8_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		.array_type	= NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		.tlv_type	= 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		.offset		= offsetof(struct ssctl_subsys_event_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 					   evt_driven_valid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		.ei_array	= NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		.data_type	= QMI_SIGNED_4_BYTE_ENUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		.elem_len	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		.elem_size	= sizeof(uint32_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		.array_type	= NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		.tlv_type	= 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		.offset		= offsetof(struct ssctl_subsys_event_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 					   evt_driven),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		.ei_array	= NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct ssctl_subsys_event_resp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	struct qmi_response_type_v01 resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static struct qmi_elem_info ssctl_subsys_event_resp_ei[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		.data_type	= QMI_STRUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		.elem_len	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		.elem_size	= sizeof(struct qmi_response_type_v01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		.array_type	= NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		.tlv_type	= 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		.offset		= offsetof(struct ssctl_subsys_event_resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 					   resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		.ei_array	= qmi_response_type_v01_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static struct qmi_elem_info ssctl_shutdown_ind_ei[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static void sysmon_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			  struct qmi_txn *txn, const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	struct qcom_sysmon *sysmon = container_of(qmi, struct qcom_sysmon, qmi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	complete(&sysmon->ind_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static struct qmi_msg_handler qmi_indication_handler[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		.type = QMI_INDICATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		.msg_id = SSCTL_SHUTDOWN_READY_IND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		.ei = ssctl_shutdown_ind_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		.decoded_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		.fn = sysmon_ind_cb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)  * ssctl_request_shutdown() - request shutdown via SSCTL QMI service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)  * @sysmon:	sysmon context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static void ssctl_request_shutdown(struct qcom_sysmon *sysmon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	struct ssctl_shutdown_resp resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	struct qmi_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	reinit_completion(&sysmon->ind_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	reinit_completion(&sysmon->shutdown_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_shutdown_resp_ei, &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		dev_err(sysmon->dev, "failed to allocate QMI txn\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	ret = qmi_send_request(&sysmon->qmi, &sysmon->ssctl, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			       SSCTL_SHUTDOWN_REQ, 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		dev_err(sysmon->dev, "failed to send shutdown request\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		qmi_txn_cancel(&txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	ret = qmi_txn_wait(&txn, 5 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		dev_err(sysmon->dev, "failed receiving QMI response\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	else if (resp.resp.result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		dev_err(sysmon->dev, "shutdown request failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		dev_dbg(sysmon->dev, "shutdown request completed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	if (sysmon->shutdown_irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		ret = wait_for_completion_timeout(&sysmon->shutdown_comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 						  10 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 			ret = try_wait_for_completion(&sysmon->ind_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 				dev_err(sysmon->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 					"timeout waiting for shutdown ack\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)  * ssctl_send_event() - send notification of other remote's SSR event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)  * @sysmon:	sysmon context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)  * @event:	sysmon event context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static void ssctl_send_event(struct qcom_sysmon *sysmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 			     const struct sysmon_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	struct ssctl_subsys_event_resp resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	struct ssctl_subsys_event_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	struct qmi_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	memset(&resp, 0, sizeof(resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_subsys_event_resp_ei, &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		dev_err(sysmon->dev, "failed to allocate QMI txn\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	memset(&req, 0, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	strlcpy(req.subsys_name, event->subsys_name, sizeof(req.subsys_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	req.subsys_name_len = strlen(req.subsys_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	req.event = event->ssr_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	req.evt_driven_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	req.evt_driven = SSCTL_SSR_EVENT_FORCED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	ret = qmi_send_request(&sysmon->qmi, &sysmon->ssctl, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			       SSCTL_SUBSYS_EVENT_REQ, 40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 			       ssctl_subsys_event_req_ei, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		dev_err(sysmon->dev, "failed to send shutdown request\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		qmi_txn_cancel(&txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	ret = qmi_txn_wait(&txn, 5 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		dev_err(sysmon->dev, "failed receiving QMI response\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	else if (resp.resp.result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		dev_err(sysmon->dev, "ssr event send failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		dev_dbg(sysmon->dev, "ssr event send completed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)  * ssctl_new_server() - QMI callback indicating a new service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)  * @qmi:	QMI handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)  * @svc:	service information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)  * Return: 0 if we're interested in this service, -EINVAL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int ssctl_new_server(struct qmi_handle *qmi, struct qmi_service *svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	struct qcom_sysmon *sysmon = container_of(qmi, struct qcom_sysmon, qmi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	switch (svc->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		if (svc->instance != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		if (strcmp(sysmon->name, "modem"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		if (svc->instance != sysmon->ssctl_instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	sysmon->ssctl_version = svc->version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	sysmon->ssctl.sq_family = AF_QIPCRTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	sysmon->ssctl.sq_node = svc->node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	sysmon->ssctl.sq_port = svc->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	svc->priv = sysmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)  * ssctl_del_server() - QMI callback indicating that @svc is removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)  * @qmi:	QMI handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)  * @svc:	service information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static void ssctl_del_server(struct qmi_handle *qmi, struct qmi_service *svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	struct qcom_sysmon *sysmon = svc->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	sysmon->ssctl_version = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static const struct qmi_ops ssctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	.new_server = ssctl_new_server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	.del_server = ssctl_del_server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static int sysmon_prepare(struct rproc_subdev *subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 						  subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	struct sysmon_event event = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		.subsys_name = sysmon->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		.ssr_event = SSCTL_SSR_EVENT_BEFORE_POWERUP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	mutex_lock(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	sysmon->state = SSCTL_SSR_EVENT_BEFORE_POWERUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	mutex_unlock(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)  * sysmon_start() - start callback for the sysmon remoteproc subdevice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)  * @subdev:	instance of the sysmon subdevice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)  * Inform all the listners of sysmon notifications that the rproc associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)  * to @subdev has booted up. The rproc that booted up also needs to know
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)  * which rprocs are already up and running, so send start notifications
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)  * on behalf of all the online rprocs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static int sysmon_start(struct rproc_subdev *subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 						  subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	struct qcom_sysmon *target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	struct sysmon_event event = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		.subsys_name = sysmon->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		.ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	mutex_lock(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	sysmon->state = SSCTL_SSR_EVENT_AFTER_POWERUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	mutex_unlock(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	mutex_lock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	list_for_each_entry(target, &sysmon_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		if (target == sysmon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		mutex_lock(&target->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		event.subsys_name = target->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		event.ssr_event = target->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		if (sysmon->ssctl_version == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 			ssctl_send_event(sysmon, &event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		else if (sysmon->ept)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 			sysmon_send_event(sysmon, &event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		mutex_unlock(&target->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	mutex_unlock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	struct sysmon_event event = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		.subsys_name = sysmon->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		.ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	mutex_lock(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	sysmon->state = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	mutex_unlock(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	/* Don't request graceful shutdown if we've crashed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	if (crashed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	if (sysmon->ssctl_version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		ssctl_request_shutdown(sysmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	else if (sysmon->ept)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 		sysmon_request_shutdown(sysmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static void sysmon_unprepare(struct rproc_subdev *subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 						  subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	struct sysmon_event event = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		.subsys_name = sysmon->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		.ssr_event = SSCTL_SSR_EVENT_AFTER_SHUTDOWN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	mutex_lock(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	sysmon->state = SSCTL_SSR_EVENT_AFTER_SHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	mutex_unlock(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)  * sysmon_notify() - notify sysmon target of another's SSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)  * @nb:		notifier_block associated with sysmon instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)  * @event:	unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)  * @data:	SSR identifier of the remote that is going down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static int sysmon_notify(struct notifier_block *nb, unsigned long event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 			 void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	struct sysmon_event *sysmon_event = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	/* Skip non-running rprocs and the originating instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	if (sysmon->state != SSCTL_SSR_EVENT_AFTER_POWERUP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	    !strcmp(sysmon_event->subsys_name, sysmon->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		dev_dbg(sysmon->dev, "not notifying %s\n", sysmon->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	/* Only SSCTL version 2 supports SSR events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	if (sysmon->ssctl_version == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		ssctl_send_event(sysmon, sysmon_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	else if (sysmon->ept)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		sysmon_send_event(sysmon, sysmon_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static irqreturn_t sysmon_shutdown_interrupt(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	struct qcom_sysmon *sysmon = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	complete(&sysmon->shutdown_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)  * qcom_add_sysmon_subdev() - create a sysmon subdev for the given remoteproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)  * @rproc:	rproc context to associate the subdev with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)  * @name:	name of this subdev, to use in SSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)  * @ssctl_instance: instance id of the ssctl QMI service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)  * Return: A new qcom_sysmon object, or NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 					   const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 					   int ssctl_instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	struct qcom_sysmon *sysmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	sysmon = kzalloc(sizeof(*sysmon), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	if (!sysmon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	sysmon->dev = rproc->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	sysmon->rproc = rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	sysmon->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	sysmon->ssctl_instance = ssctl_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	init_completion(&sysmon->comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	init_completion(&sysmon->ind_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	init_completion(&sysmon->shutdown_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	mutex_init(&sysmon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	mutex_init(&sysmon->state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	sysmon->shutdown_irq = of_irq_get_byname(sysmon->dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 						 "shutdown-ack");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	if (sysmon->shutdown_irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		if (sysmon->shutdown_irq != -ENODATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 			dev_err(sysmon->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 				"failed to retrieve shutdown-ack IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 			return ERR_PTR(sysmon->shutdown_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		ret = devm_request_threaded_irq(sysmon->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 						sysmon->shutdown_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 						NULL, sysmon_shutdown_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 						IRQF_TRIGGER_RISING | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 						"q6v5 shutdown-ack", sysmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			dev_err(sysmon->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 				"failed to acquire shutdown-ack IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 			return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 			      qmi_indication_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 		dev_err(sysmon->dev, "failed to initialize qmi handle\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		kfree(sysmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	qmi_add_lookup(&sysmon->qmi, 43, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	sysmon->subdev.prepare = sysmon_prepare;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	sysmon->subdev.start = sysmon_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	sysmon->subdev.stop = sysmon_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	sysmon->subdev.unprepare = sysmon_unprepare;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	rproc_add_subdev(rproc, &sysmon->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	sysmon->nb.notifier_call = sysmon_notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	blocking_notifier_chain_register(&sysmon_notifiers, &sysmon->nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	mutex_lock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	list_add(&sysmon->node, &sysmon_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	mutex_unlock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	return sysmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) EXPORT_SYMBOL_GPL(qcom_add_sysmon_subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)  * qcom_remove_sysmon_subdev() - release a qcom_sysmon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)  * @sysmon:	sysmon context, as retrieved by qcom_add_sysmon_subdev()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	if (!sysmon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	mutex_lock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	list_del(&sysmon->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	mutex_unlock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	blocking_notifier_chain_unregister(&sysmon_notifiers, &sysmon->nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	rproc_remove_subdev(sysmon->rproc, &sysmon->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	qmi_handle_release(&sysmon->qmi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	kfree(sysmon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) EXPORT_SYMBOL_GPL(qcom_remove_sysmon_subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)  * sysmon_probe() - probe sys_mon channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)  * @rpdev:	rpmsg device handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)  * Find the sysmon context associated with the ancestor remoteproc and assign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)  * this rpmsg device with said sysmon context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)  * Return: 0 on success, negative errno on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static int sysmon_probe(struct rpmsg_device *rpdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	struct qcom_sysmon *sysmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	struct rproc *rproc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	rproc = rproc_get_by_child(&rpdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	if (!rproc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 		dev_err(&rpdev->dev, "sysmon device not child of rproc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	mutex_lock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	list_for_each_entry(sysmon, &sysmon_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 		if (sysmon->rproc == rproc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 			goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	mutex_unlock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	dev_err(&rpdev->dev, "no sysmon associated with parent rproc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	mutex_unlock(&sysmon_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	rpdev->ept->priv = sysmon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	sysmon->ept = rpdev->ept;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)  * sysmon_remove() - sys_mon channel remove handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)  * @rpdev:	rpmsg device handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)  * Disassociate the rpmsg device with the sysmon instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) static void sysmon_remove(struct rpmsg_device *rpdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	struct qcom_sysmon *sysmon = rpdev->ept->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	sysmon->ept = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static const struct rpmsg_device_id sysmon_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	{ "sys_mon" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static struct rpmsg_driver sysmon_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	.probe = sysmon_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 	.remove = sysmon_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	.callback = sysmon_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	.id_table = sysmon_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	.drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 		.name = "qcom_sysmon",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) module_rpmsg_driver(sysmon_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) MODULE_DESCRIPTION("Qualcomm sysmon driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) MODULE_LICENSE("GPL v2");