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