^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");