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