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