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