Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2017, Linaro Ltd.
0004  */
0005 #include <linux/firmware.h>
0006 #include <linux/module.h>
0007 #include <linux/notifier.h>
0008 #include <linux/slab.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/io.h>
0011 #include <linux/of_irq.h>
0012 #include <linux/of_platform.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/remoteproc/qcom_rproc.h>
0015 #include <linux/rpmsg.h>
0016 
0017 #include "qcom_common.h"
0018 
0019 static BLOCKING_NOTIFIER_HEAD(sysmon_notifiers);
0020 
0021 struct qcom_sysmon {
0022     struct rproc_subdev subdev;
0023     struct rproc *rproc;
0024 
0025     int state;
0026     struct mutex state_lock;
0027 
0028     struct list_head node;
0029 
0030     const char *name;
0031 
0032     int shutdown_irq;
0033     int ssctl_version;
0034     int ssctl_instance;
0035 
0036     struct notifier_block nb;
0037 
0038     struct device *dev;
0039 
0040     struct rpmsg_endpoint *ept;
0041     struct completion comp;
0042     struct completion ind_comp;
0043     struct completion shutdown_comp;
0044     struct completion ssctl_comp;
0045     struct mutex lock;
0046 
0047     bool ssr_ack;
0048     bool shutdown_acked;
0049 
0050     struct qmi_handle qmi;
0051     struct sockaddr_qrtr ssctl;
0052 };
0053 
0054 enum {
0055     SSCTL_SSR_EVENT_BEFORE_POWERUP,
0056     SSCTL_SSR_EVENT_AFTER_POWERUP,
0057     SSCTL_SSR_EVENT_BEFORE_SHUTDOWN,
0058     SSCTL_SSR_EVENT_AFTER_SHUTDOWN,
0059 };
0060 
0061 static const char * const sysmon_state_string[] = {
0062     [SSCTL_SSR_EVENT_BEFORE_POWERUP]    = "before_powerup",
0063     [SSCTL_SSR_EVENT_AFTER_POWERUP]     = "after_powerup",
0064     [SSCTL_SSR_EVENT_BEFORE_SHUTDOWN]   = "before_shutdown",
0065     [SSCTL_SSR_EVENT_AFTER_SHUTDOWN]    = "after_shutdown",
0066 };
0067 
0068 struct sysmon_event {
0069     const char *subsys_name;
0070     u32 ssr_event;
0071 };
0072 
0073 static DEFINE_MUTEX(sysmon_lock);
0074 static LIST_HEAD(sysmon_list);
0075 
0076 /**
0077  * sysmon_send_event() - send notification of other remote's SSR event
0078  * @sysmon: sysmon context
0079  * @event:  sysmon event context
0080  */
0081 static void sysmon_send_event(struct qcom_sysmon *sysmon,
0082                   const struct sysmon_event *event)
0083 {
0084     char req[50];
0085     int len;
0086     int ret;
0087 
0088     len = snprintf(req, sizeof(req), "ssr:%s:%s", event->subsys_name,
0089                sysmon_state_string[event->ssr_event]);
0090     if (len >= sizeof(req))
0091         return;
0092 
0093     mutex_lock(&sysmon->lock);
0094     reinit_completion(&sysmon->comp);
0095     sysmon->ssr_ack = false;
0096 
0097     ret = rpmsg_send(sysmon->ept, req, len);
0098     if (ret < 0) {
0099         dev_err(sysmon->dev, "failed to send sysmon event\n");
0100         goto out_unlock;
0101     }
0102 
0103     ret = wait_for_completion_timeout(&sysmon->comp,
0104                       msecs_to_jiffies(5000));
0105     if (!ret) {
0106         dev_err(sysmon->dev, "timeout waiting for sysmon ack\n");
0107         goto out_unlock;
0108     }
0109 
0110     if (!sysmon->ssr_ack)
0111         dev_err(sysmon->dev, "unexpected response to sysmon event\n");
0112 
0113 out_unlock:
0114     mutex_unlock(&sysmon->lock);
0115 }
0116 
0117 /**
0118  * sysmon_request_shutdown() - request graceful shutdown of remote
0119  * @sysmon: sysmon context
0120  *
0121  * Return: boolean indicator of the remote processor acking the request
0122  */
0123 static bool sysmon_request_shutdown(struct qcom_sysmon *sysmon)
0124 {
0125     char *req = "ssr:shutdown";
0126     bool acked = false;
0127     int ret;
0128 
0129     mutex_lock(&sysmon->lock);
0130     reinit_completion(&sysmon->comp);
0131     sysmon->ssr_ack = false;
0132 
0133     ret = rpmsg_send(sysmon->ept, req, strlen(req) + 1);
0134     if (ret < 0) {
0135         dev_err(sysmon->dev, "send sysmon shutdown request failed\n");
0136         goto out_unlock;
0137     }
0138 
0139     ret = wait_for_completion_timeout(&sysmon->comp,
0140                       msecs_to_jiffies(5000));
0141     if (!ret) {
0142         dev_err(sysmon->dev, "timeout waiting for sysmon ack\n");
0143         goto out_unlock;
0144     }
0145 
0146     if (!sysmon->ssr_ack)
0147         dev_err(sysmon->dev,
0148             "unexpected response to sysmon shutdown request\n");
0149     else
0150         acked = true;
0151 
0152 out_unlock:
0153     mutex_unlock(&sysmon->lock);
0154 
0155     return acked;
0156 }
0157 
0158 static int sysmon_callback(struct rpmsg_device *rpdev, void *data, int count,
0159                void *priv, u32 addr)
0160 {
0161     struct qcom_sysmon *sysmon = priv;
0162     const char *ssr_ack = "ssr:ack";
0163     const int ssr_ack_len = strlen(ssr_ack) + 1;
0164 
0165     if (!sysmon)
0166         return -EINVAL;
0167 
0168     if (count >= ssr_ack_len && !memcmp(data, ssr_ack, ssr_ack_len))
0169         sysmon->ssr_ack = true;
0170 
0171     complete(&sysmon->comp);
0172 
0173     return 0;
0174 }
0175 
0176 #define SSCTL_SHUTDOWN_REQ      0x21
0177 #define SSCTL_SHUTDOWN_READY_IND    0x21
0178 #define SSCTL_SUBSYS_EVENT_REQ      0x23
0179 
0180 #define SSCTL_MAX_MSG_LEN       7
0181 
0182 #define SSCTL_SUBSYS_NAME_LENGTH    15
0183 
0184 enum {
0185     SSCTL_SSR_EVENT_FORCED,
0186     SSCTL_SSR_EVENT_GRACEFUL,
0187 };
0188 
0189 struct ssctl_shutdown_resp {
0190     struct qmi_response_type_v01 resp;
0191 };
0192 
0193 static struct qmi_elem_info ssctl_shutdown_resp_ei[] = {
0194     {
0195         .data_type  = QMI_STRUCT,
0196         .elem_len   = 1,
0197         .elem_size  = sizeof(struct qmi_response_type_v01),
0198         .array_type = NO_ARRAY,
0199         .tlv_type   = 0x02,
0200         .offset     = offsetof(struct ssctl_shutdown_resp, resp),
0201         .ei_array   = qmi_response_type_v01_ei,
0202     },
0203     {}
0204 };
0205 
0206 struct ssctl_subsys_event_req {
0207     u8 subsys_name_len;
0208     char subsys_name[SSCTL_SUBSYS_NAME_LENGTH];
0209     u32 event;
0210     u8 evt_driven_valid;
0211     u32 evt_driven;
0212 };
0213 
0214 static struct qmi_elem_info ssctl_subsys_event_req_ei[] = {
0215     {
0216         .data_type  = QMI_DATA_LEN,
0217         .elem_len   = 1,
0218         .elem_size  = sizeof(uint8_t),
0219         .array_type = NO_ARRAY,
0220         .tlv_type   = 0x01,
0221         .offset     = offsetof(struct ssctl_subsys_event_req,
0222                        subsys_name_len),
0223         .ei_array   = NULL,
0224     },
0225     {
0226         .data_type  = QMI_UNSIGNED_1_BYTE,
0227         .elem_len   = SSCTL_SUBSYS_NAME_LENGTH,
0228         .elem_size  = sizeof(char),
0229         .array_type = VAR_LEN_ARRAY,
0230         .tlv_type   = 0x01,
0231         .offset     = offsetof(struct ssctl_subsys_event_req,
0232                        subsys_name),
0233         .ei_array   = NULL,
0234     },
0235     {
0236         .data_type  = QMI_SIGNED_4_BYTE_ENUM,
0237         .elem_len   = 1,
0238         .elem_size  = sizeof(uint32_t),
0239         .array_type = NO_ARRAY,
0240         .tlv_type   = 0x02,
0241         .offset     = offsetof(struct ssctl_subsys_event_req,
0242                        event),
0243         .ei_array   = NULL,
0244     },
0245     {
0246         .data_type  = QMI_OPT_FLAG,
0247         .elem_len   = 1,
0248         .elem_size  = sizeof(uint8_t),
0249         .array_type = NO_ARRAY,
0250         .tlv_type   = 0x10,
0251         .offset     = offsetof(struct ssctl_subsys_event_req,
0252                        evt_driven_valid),
0253         .ei_array   = NULL,
0254     },
0255     {
0256         .data_type  = QMI_SIGNED_4_BYTE_ENUM,
0257         .elem_len   = 1,
0258         .elem_size  = sizeof(uint32_t),
0259         .array_type = NO_ARRAY,
0260         .tlv_type   = 0x10,
0261         .offset     = offsetof(struct ssctl_subsys_event_req,
0262                        evt_driven),
0263         .ei_array   = NULL,
0264     },
0265     {}
0266 };
0267 
0268 struct ssctl_subsys_event_resp {
0269     struct qmi_response_type_v01 resp;
0270 };
0271 
0272 static struct qmi_elem_info ssctl_subsys_event_resp_ei[] = {
0273     {
0274         .data_type  = QMI_STRUCT,
0275         .elem_len   = 1,
0276         .elem_size  = sizeof(struct qmi_response_type_v01),
0277         .array_type = NO_ARRAY,
0278         .tlv_type   = 0x02,
0279         .offset     = offsetof(struct ssctl_subsys_event_resp,
0280                        resp),
0281         .ei_array   = qmi_response_type_v01_ei,
0282     },
0283     {}
0284 };
0285 
0286 static struct qmi_elem_info ssctl_shutdown_ind_ei[] = {
0287     {}
0288 };
0289 
0290 static void sysmon_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
0291               struct qmi_txn *txn, const void *data)
0292 {
0293     struct qcom_sysmon *sysmon = container_of(qmi, struct qcom_sysmon, qmi);
0294 
0295     complete(&sysmon->ind_comp);
0296 }
0297 
0298 static const struct qmi_msg_handler qmi_indication_handler[] = {
0299     {
0300         .type = QMI_INDICATION,
0301         .msg_id = SSCTL_SHUTDOWN_READY_IND,
0302         .ei = ssctl_shutdown_ind_ei,
0303         .decoded_size = 0,
0304         .fn = sysmon_ind_cb
0305     },
0306     {}
0307 };
0308 
0309 static bool ssctl_request_shutdown_wait(struct qcom_sysmon *sysmon)
0310 {
0311     int ret;
0312 
0313     ret = wait_for_completion_timeout(&sysmon->shutdown_comp, 10 * HZ);
0314     if (ret)
0315         return true;
0316 
0317     ret = try_wait_for_completion(&sysmon->ind_comp);
0318     if (ret)
0319         return true;
0320 
0321     dev_err(sysmon->dev, "timeout waiting for shutdown ack\n");
0322     return false;
0323 }
0324 
0325 /**
0326  * ssctl_request_shutdown() - request shutdown via SSCTL QMI service
0327  * @sysmon: sysmon context
0328  *
0329  * Return: boolean indicator of the remote processor acking the request
0330  */
0331 static bool ssctl_request_shutdown(struct qcom_sysmon *sysmon)
0332 {
0333     struct ssctl_shutdown_resp resp;
0334     struct qmi_txn txn;
0335     bool acked = false;
0336     int ret;
0337 
0338     reinit_completion(&sysmon->ind_comp);
0339     reinit_completion(&sysmon->shutdown_comp);
0340     ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_shutdown_resp_ei, &resp);
0341     if (ret < 0) {
0342         dev_err(sysmon->dev, "failed to allocate QMI txn\n");
0343         return false;
0344     }
0345 
0346     ret = qmi_send_request(&sysmon->qmi, &sysmon->ssctl, &txn,
0347                    SSCTL_SHUTDOWN_REQ, 0, NULL, NULL);
0348     if (ret < 0) {
0349         dev_err(sysmon->dev, "failed to send shutdown request\n");
0350         qmi_txn_cancel(&txn);
0351         return false;
0352     }
0353 
0354     ret = qmi_txn_wait(&txn, 5 * HZ);
0355     if (ret < 0) {
0356         dev_err(sysmon->dev, "timeout waiting for shutdown response\n");
0357     } else if (resp.resp.result) {
0358         dev_err(sysmon->dev, "shutdown request rejected\n");
0359     } else {
0360         dev_dbg(sysmon->dev, "shutdown request completed\n");
0361         acked = true;
0362     }
0363 
0364     if (sysmon->shutdown_irq > 0)
0365         return ssctl_request_shutdown_wait(sysmon);
0366 
0367     return acked;
0368 }
0369 
0370 /**
0371  * ssctl_send_event() - send notification of other remote's SSR event
0372  * @sysmon: sysmon context
0373  * @event:  sysmon event context
0374  */
0375 static void ssctl_send_event(struct qcom_sysmon *sysmon,
0376                  const struct sysmon_event *event)
0377 {
0378     struct ssctl_subsys_event_resp resp;
0379     struct ssctl_subsys_event_req req;
0380     struct qmi_txn txn;
0381     int ret;
0382 
0383     memset(&resp, 0, sizeof(resp));
0384     ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_subsys_event_resp_ei, &resp);
0385     if (ret < 0) {
0386         dev_err(sysmon->dev, "failed to allocate QMI txn\n");
0387         return;
0388     }
0389 
0390     memset(&req, 0, sizeof(req));
0391     strlcpy(req.subsys_name, event->subsys_name, sizeof(req.subsys_name));
0392     req.subsys_name_len = strlen(req.subsys_name);
0393     req.event = event->ssr_event;
0394     req.evt_driven_valid = true;
0395     req.evt_driven = SSCTL_SSR_EVENT_FORCED;
0396 
0397     ret = qmi_send_request(&sysmon->qmi, &sysmon->ssctl, &txn,
0398                    SSCTL_SUBSYS_EVENT_REQ, 40,
0399                    ssctl_subsys_event_req_ei, &req);
0400     if (ret < 0) {
0401         dev_err(sysmon->dev, "failed to send subsystem event\n");
0402         qmi_txn_cancel(&txn);
0403         return;
0404     }
0405 
0406     ret = qmi_txn_wait(&txn, 5 * HZ);
0407     if (ret < 0)
0408         dev_err(sysmon->dev, "timeout waiting for subsystem event response\n");
0409     else if (resp.resp.result)
0410         dev_err(sysmon->dev, "subsystem event rejected\n");
0411     else
0412         dev_dbg(sysmon->dev, "subsystem event accepted\n");
0413 }
0414 
0415 /**
0416  * ssctl_new_server() - QMI callback indicating a new service
0417  * @qmi:    QMI handle
0418  * @svc:    service information
0419  *
0420  * Return: 0 if we're interested in this service, -EINVAL otherwise.
0421  */
0422 static int ssctl_new_server(struct qmi_handle *qmi, struct qmi_service *svc)
0423 {
0424     struct qcom_sysmon *sysmon = container_of(qmi, struct qcom_sysmon, qmi);
0425 
0426     switch (svc->version) {
0427     case 1:
0428         if (svc->instance != 0)
0429             return -EINVAL;
0430         if (strcmp(sysmon->name, "modem"))
0431             return -EINVAL;
0432         break;
0433     case 2:
0434         if (svc->instance != sysmon->ssctl_instance)
0435             return -EINVAL;
0436         break;
0437     default:
0438         return -EINVAL;
0439     }
0440 
0441     sysmon->ssctl_version = svc->version;
0442 
0443     sysmon->ssctl.sq_family = AF_QIPCRTR;
0444     sysmon->ssctl.sq_node = svc->node;
0445     sysmon->ssctl.sq_port = svc->port;
0446 
0447     svc->priv = sysmon;
0448 
0449     complete(&sysmon->ssctl_comp);
0450 
0451     return 0;
0452 }
0453 
0454 /**
0455  * ssctl_del_server() - QMI callback indicating that @svc is removed
0456  * @qmi:    QMI handle
0457  * @svc:    service information
0458  */
0459 static void ssctl_del_server(struct qmi_handle *qmi, struct qmi_service *svc)
0460 {
0461     struct qcom_sysmon *sysmon = svc->priv;
0462 
0463     sysmon->ssctl_version = 0;
0464 }
0465 
0466 static const struct qmi_ops ssctl_ops = {
0467     .new_server = ssctl_new_server,
0468     .del_server = ssctl_del_server,
0469 };
0470 
0471 static int sysmon_prepare(struct rproc_subdev *subdev)
0472 {
0473     struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
0474                           subdev);
0475     struct sysmon_event event = {
0476         .subsys_name = sysmon->name,
0477         .ssr_event = SSCTL_SSR_EVENT_BEFORE_POWERUP
0478     };
0479 
0480     mutex_lock(&sysmon->state_lock);
0481     sysmon->state = SSCTL_SSR_EVENT_BEFORE_POWERUP;
0482     blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
0483     mutex_unlock(&sysmon->state_lock);
0484 
0485     return 0;
0486 }
0487 
0488 /**
0489  * sysmon_start() - start callback for the sysmon remoteproc subdevice
0490  * @subdev: instance of the sysmon subdevice
0491  *
0492  * Inform all the listners of sysmon notifications that the rproc associated
0493  * to @subdev has booted up. The rproc that booted up also needs to know
0494  * which rprocs are already up and running, so send start notifications
0495  * on behalf of all the online rprocs.
0496  */
0497 static int sysmon_start(struct rproc_subdev *subdev)
0498 {
0499     struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
0500                           subdev);
0501     struct qcom_sysmon *target;
0502     struct sysmon_event event = {
0503         .subsys_name = sysmon->name,
0504         .ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP
0505     };
0506 
0507     reinit_completion(&sysmon->ssctl_comp);
0508     mutex_lock(&sysmon->state_lock);
0509     sysmon->state = SSCTL_SSR_EVENT_AFTER_POWERUP;
0510     blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
0511     mutex_unlock(&sysmon->state_lock);
0512 
0513     mutex_lock(&sysmon_lock);
0514     list_for_each_entry(target, &sysmon_list, node) {
0515         mutex_lock(&target->state_lock);
0516         if (target == sysmon || target->state != SSCTL_SSR_EVENT_AFTER_POWERUP) {
0517             mutex_unlock(&target->state_lock);
0518             continue;
0519         }
0520 
0521         event.subsys_name = target->name;
0522         event.ssr_event = target->state;
0523 
0524         if (sysmon->ssctl_version == 2)
0525             ssctl_send_event(sysmon, &event);
0526         else if (sysmon->ept)
0527             sysmon_send_event(sysmon, &event);
0528         mutex_unlock(&target->state_lock);
0529     }
0530     mutex_unlock(&sysmon_lock);
0531 
0532     return 0;
0533 }
0534 
0535 static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
0536 {
0537     struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon, subdev);
0538     struct sysmon_event event = {
0539         .subsys_name = sysmon->name,
0540         .ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN
0541     };
0542 
0543     sysmon->shutdown_acked = false;
0544 
0545     mutex_lock(&sysmon->state_lock);
0546     sysmon->state = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN;
0547     blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
0548     mutex_unlock(&sysmon->state_lock);
0549 
0550     /* Don't request graceful shutdown if we've crashed */
0551     if (crashed)
0552         return;
0553 
0554     if (sysmon->ssctl_instance) {
0555         if (!wait_for_completion_timeout(&sysmon->ssctl_comp, HZ / 2))
0556             dev_err(sysmon->dev, "timeout waiting for ssctl service\n");
0557     }
0558 
0559     if (sysmon->ssctl_version)
0560         sysmon->shutdown_acked = ssctl_request_shutdown(sysmon);
0561     else if (sysmon->ept)
0562         sysmon->shutdown_acked = sysmon_request_shutdown(sysmon);
0563 }
0564 
0565 static void sysmon_unprepare(struct rproc_subdev *subdev)
0566 {
0567     struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,
0568                           subdev);
0569     struct sysmon_event event = {
0570         .subsys_name = sysmon->name,
0571         .ssr_event = SSCTL_SSR_EVENT_AFTER_SHUTDOWN
0572     };
0573 
0574     mutex_lock(&sysmon->state_lock);
0575     sysmon->state = SSCTL_SSR_EVENT_AFTER_SHUTDOWN;
0576     blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)&event);
0577     mutex_unlock(&sysmon->state_lock);
0578 }
0579 
0580 /**
0581  * sysmon_notify() - notify sysmon target of another's SSR
0582  * @nb:     notifier_block associated with sysmon instance
0583  * @event:  unused
0584  * @data:   SSR identifier of the remote that is going down
0585  */
0586 static int sysmon_notify(struct notifier_block *nb, unsigned long event,
0587              void *data)
0588 {
0589     struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb);
0590     struct sysmon_event *sysmon_event = data;
0591 
0592     /* Skip non-running rprocs and the originating instance */
0593     if (sysmon->state != SSCTL_SSR_EVENT_AFTER_POWERUP ||
0594         !strcmp(sysmon_event->subsys_name, sysmon->name)) {
0595         dev_dbg(sysmon->dev, "not notifying %s\n", sysmon->name);
0596         return NOTIFY_DONE;
0597     }
0598 
0599     /* Only SSCTL version 2 supports SSR events */
0600     if (sysmon->ssctl_version == 2)
0601         ssctl_send_event(sysmon, sysmon_event);
0602     else if (sysmon->ept)
0603         sysmon_send_event(sysmon, sysmon_event);
0604 
0605     return NOTIFY_DONE;
0606 }
0607 
0608 static irqreturn_t sysmon_shutdown_interrupt(int irq, void *data)
0609 {
0610     struct qcom_sysmon *sysmon = data;
0611 
0612     complete(&sysmon->shutdown_comp);
0613 
0614     return IRQ_HANDLED;
0615 }
0616 
0617 /**
0618  * qcom_add_sysmon_subdev() - create a sysmon subdev for the given remoteproc
0619  * @rproc:  rproc context to associate the subdev with
0620  * @name:   name of this subdev, to use in SSR
0621  * @ssctl_instance: instance id of the ssctl QMI service
0622  *
0623  * Return: A new qcom_sysmon object, or NULL on failure
0624  */
0625 struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
0626                        const char *name,
0627                        int ssctl_instance)
0628 {
0629     struct qcom_sysmon *sysmon;
0630     int ret;
0631 
0632     sysmon = kzalloc(sizeof(*sysmon), GFP_KERNEL);
0633     if (!sysmon)
0634         return ERR_PTR(-ENOMEM);
0635 
0636     sysmon->dev = rproc->dev.parent;
0637     sysmon->rproc = rproc;
0638 
0639     sysmon->name = name;
0640     sysmon->ssctl_instance = ssctl_instance;
0641 
0642     init_completion(&sysmon->comp);
0643     init_completion(&sysmon->ind_comp);
0644     init_completion(&sysmon->shutdown_comp);
0645     init_completion(&sysmon->ssctl_comp);
0646     mutex_init(&sysmon->lock);
0647     mutex_init(&sysmon->state_lock);
0648 
0649     sysmon->shutdown_irq = of_irq_get_byname(sysmon->dev->of_node,
0650                          "shutdown-ack");
0651     if (sysmon->shutdown_irq < 0) {
0652         if (sysmon->shutdown_irq != -ENODATA) {
0653             dev_err(sysmon->dev,
0654                 "failed to retrieve shutdown-ack IRQ\n");
0655             return ERR_PTR(sysmon->shutdown_irq);
0656         }
0657     } else {
0658         ret = devm_request_threaded_irq(sysmon->dev,
0659                         sysmon->shutdown_irq,
0660                         NULL, sysmon_shutdown_interrupt,
0661                         IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0662                         "q6v5 shutdown-ack", sysmon);
0663         if (ret) {
0664             dev_err(sysmon->dev,
0665                 "failed to acquire shutdown-ack IRQ\n");
0666             return ERR_PTR(ret);
0667         }
0668     }
0669 
0670     ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops,
0671                   qmi_indication_handler);
0672     if (ret < 0) {
0673         dev_err(sysmon->dev, "failed to initialize qmi handle\n");
0674         kfree(sysmon);
0675         return ERR_PTR(ret);
0676     }
0677 
0678     qmi_add_lookup(&sysmon->qmi, 43, 0, 0);
0679 
0680     sysmon->subdev.prepare = sysmon_prepare;
0681     sysmon->subdev.start = sysmon_start;
0682     sysmon->subdev.stop = sysmon_stop;
0683     sysmon->subdev.unprepare = sysmon_unprepare;
0684 
0685     rproc_add_subdev(rproc, &sysmon->subdev);
0686 
0687     sysmon->nb.notifier_call = sysmon_notify;
0688     blocking_notifier_chain_register(&sysmon_notifiers, &sysmon->nb);
0689 
0690     mutex_lock(&sysmon_lock);
0691     list_add(&sysmon->node, &sysmon_list);
0692     mutex_unlock(&sysmon_lock);
0693 
0694     return sysmon;
0695 }
0696 EXPORT_SYMBOL_GPL(qcom_add_sysmon_subdev);
0697 
0698 /**
0699  * qcom_remove_sysmon_subdev() - release a qcom_sysmon
0700  * @sysmon: sysmon context, as retrieved by qcom_add_sysmon_subdev()
0701  */
0702 void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon)
0703 {
0704     if (!sysmon)
0705         return;
0706 
0707     mutex_lock(&sysmon_lock);
0708     list_del(&sysmon->node);
0709     mutex_unlock(&sysmon_lock);
0710 
0711     blocking_notifier_chain_unregister(&sysmon_notifiers, &sysmon->nb);
0712 
0713     rproc_remove_subdev(sysmon->rproc, &sysmon->subdev);
0714 
0715     qmi_handle_release(&sysmon->qmi);
0716 
0717     kfree(sysmon);
0718 }
0719 EXPORT_SYMBOL_GPL(qcom_remove_sysmon_subdev);
0720 
0721 /**
0722  * qcom_sysmon_shutdown_acked() - query the success of the last shutdown
0723  * @sysmon: sysmon context
0724  *
0725  * When sysmon is used to request a graceful shutdown of the remote processor
0726  * this can be used by the remoteproc driver to query the success, in order to
0727  * know if it should fall back to other means of requesting a shutdown.
0728  *
0729  * Return: boolean indicator of the success of the last shutdown request
0730  */
0731 bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon)
0732 {
0733     return sysmon && sysmon->shutdown_acked;
0734 }
0735 EXPORT_SYMBOL_GPL(qcom_sysmon_shutdown_acked);
0736 
0737 /**
0738  * sysmon_probe() - probe sys_mon channel
0739  * @rpdev:  rpmsg device handle
0740  *
0741  * Find the sysmon context associated with the ancestor remoteproc and assign
0742  * this rpmsg device with said sysmon context.
0743  *
0744  * Return: 0 on success, negative errno on failure.
0745  */
0746 static int sysmon_probe(struct rpmsg_device *rpdev)
0747 {
0748     struct qcom_sysmon *sysmon;
0749     struct rproc *rproc;
0750 
0751     rproc = rproc_get_by_child(&rpdev->dev);
0752     if (!rproc) {
0753         dev_err(&rpdev->dev, "sysmon device not child of rproc\n");
0754         return -EINVAL;
0755     }
0756 
0757     mutex_lock(&sysmon_lock);
0758     list_for_each_entry(sysmon, &sysmon_list, node) {
0759         if (sysmon->rproc == rproc)
0760             goto found;
0761     }
0762     mutex_unlock(&sysmon_lock);
0763 
0764     dev_err(&rpdev->dev, "no sysmon associated with parent rproc\n");
0765 
0766     return -EINVAL;
0767 
0768 found:
0769     mutex_unlock(&sysmon_lock);
0770 
0771     rpdev->ept->priv = sysmon;
0772     sysmon->ept = rpdev->ept;
0773 
0774     return 0;
0775 }
0776 
0777 /**
0778  * sysmon_remove() - sys_mon channel remove handler
0779  * @rpdev:  rpmsg device handle
0780  *
0781  * Disassociate the rpmsg device with the sysmon instance.
0782  */
0783 static void sysmon_remove(struct rpmsg_device *rpdev)
0784 {
0785     struct qcom_sysmon *sysmon = rpdev->ept->priv;
0786 
0787     sysmon->ept = NULL;
0788 }
0789 
0790 static const struct rpmsg_device_id sysmon_match[] = {
0791     { "sys_mon" },
0792     {}
0793 };
0794 
0795 static struct rpmsg_driver sysmon_driver = {
0796     .probe = sysmon_probe,
0797     .remove = sysmon_remove,
0798     .callback = sysmon_callback,
0799     .id_table = sysmon_match,
0800     .drv = {
0801         .name = "qcom_sysmon",
0802     },
0803 };
0804 
0805 module_rpmsg_driver(sysmon_driver);
0806 
0807 MODULE_DESCRIPTION("Qualcomm sysmon driver");
0808 MODULE_LICENSE("GPL v2");