cvp_vm_msgq.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* SPDX-License-Identifier: GPL-2.0-only
  2. *
  3. * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #include <linux/kthread.h>
  6. #include "cvp_vm_msgq.h"
  7. #include "msm_cvp_debug.h"
  8. /**
  9. * cvp_msgq_receiver - thread function that receive msg from gunyah msgq
  10. * data: cvp_msgq_drv pointer
  11. *
  12. * Note: single thread. If the sub-function or global data used in this
  13. * function is also used somehwere else, please add rx_lock.
  14. */
  15. static int cvp_msgq_receiver(void *data)
  16. {
  17. struct cvp_msgq_drv *msgq_drv = data;
  18. if (IS_ERR_OR_NULL(msgq_drv))
  19. return -EINVAL;
  20. return 0;
  21. }
  22. static int cvp_complete_msgq_init(struct cvp_msgq_drv *msgq_drv)
  23. {
  24. int i;
  25. msgq_drv->receiver_thread = kthread_run(
  26. cvp_msgq_receiver,
  27. (void *)msgq_drv,
  28. "CVP msgq receiver");
  29. if (IS_ERR_OR_NULL(msgq_drv->receiver_thread)) {
  30. dprintk(CVP_ERR, "Failed to start msgq receiver thread\n");
  31. return -EINVAL;
  32. }
  33. mutex_init(&msgq_drv->ipc_lock);
  34. for (i = 0; i <= CVP_MAX_IPC_CMD; i++)
  35. init_completion(&msgq_drv->completions[i]);
  36. return 0;
  37. }
  38. static int cvp_msgq_cb(struct notifier_block *nb,
  39. unsigned long cmd, void *data)
  40. {
  41. struct gh_rm_notif_vm_status_payload *vm_status_payload;
  42. struct cvp_gh_msgq_config *msgq_config;
  43. struct cvp_msgq_drv *msgq_drv;
  44. gh_vmid_t peer_vmid;
  45. gh_vmid_t self_vmid;
  46. int rc;
  47. if (IS_ERR_OR_NULL(nb))
  48. return -EINVAL;
  49. msgq_config = container_of(nb, struct cvp_gh_msgq_config, rm_nb);
  50. msgq_drv = container_of(msgq_config, struct cvp_msgq_drv, config);
  51. if (cmd != GH_RM_NOTIF_VM_STATUS)
  52. return NOTIFY_DONE;
  53. /**
  54. * Check VM status, only GH_TRUSTED_VM notification activate
  55. * Gunyah msgq registration
  56. */
  57. vm_status_payload = (struct gh_rm_notif_vm_status_payload *)data;
  58. if (vm_status_payload->vm_status != GH_RM_VM_STATUS_READY)
  59. return -12;
  60. if (gh_rm_get_vmid(msgq_config->peer_id, &peer_vmid))
  61. return -13;
  62. if (gh_rm_get_vmid(GH_PRIMARY_VM, &self_vmid))
  63. return -14;
  64. if (peer_vmid != vm_status_payload->vmid)
  65. return NOTIFY_DONE;
  66. dprintk(CVP_VM, "%s vmid=%d, peer_vmid=%d\n", vm_status_payload->vmid,
  67. peer_vmid);
  68. if (msgq_config->handle)
  69. return -15;
  70. msgq_config->handle = gh_msgq_register(GH_MSGQ_LABEL_EVA);
  71. if (IS_ERR(msgq_config->handle)) {
  72. rc = PTR_ERR(msgq_drv->config.handle);
  73. dprintk(CVP_ERR, "PVM failed to register msgq %d\n", rc);
  74. return rc;
  75. }
  76. rc = cvp_complete_msgq_init(msgq_drv);
  77. return rc;
  78. }
  79. static int cvp_msgq_init(struct cvp_msgq_drv *msgq_drv)
  80. {
  81. int rc = 0;
  82. msgq_drv->config.label = GH_MSGQ_LABEL_EVA;
  83. msgq_drv->config.handle = NULL;
  84. #ifndef CONFIG_EVA_TVM
  85. /* PVM init */
  86. msgq_drv->config.peer_id = GH_TRUSTED_VM;
  87. msgq_drv->config.rm_nb.notifier_call = cvp_msgq_cb;
  88. rc = gh_rm_register_notifier(&msgq_drv->config.rm_nb);
  89. if (rc) {
  90. dprintk(CVP_ERR, "PVM Fail register msgq notifier %d\n", rc);
  91. return rc;
  92. }
  93. #else
  94. /* TVM init */
  95. msgq_drv->config.handle = gh_msgq_register(GH_MSGQ_LABEL_EVA);
  96. if (IS_ERR(msgq_drv->config.handle)) {
  97. rc = PTR_ERR(msgq_drv->config.handle);
  98. dprintk(CVP_ERR, "TVM failed to register msgq %d\n", rc);
  99. return rc;
  100. }
  101. rc = cvp_msgq_complete_init(msgq_drv);
  102. #endif
  103. return rc;
  104. }
  105. static int cvp_msgq_deinit(struct cvp_msgq_drv *msgq_drv)
  106. {
  107. if (msgq_drv->receiver_thread)
  108. kthread_stop(msgq_drv->receiver_thread);
  109. return 0;
  110. }
  111. static int cvp_msgq_send(struct cvp_msgq_drv *msgq_drv,
  112. void *msg, size_t msg_size)
  113. {
  114. return 0;
  115. }
  116. static int cvp_msgq_receive(struct cvp_msgq_drv *msgq_drv)
  117. {
  118. return 0;
  119. }
  120. static struct cvp_msgq_ops msgq_ops = {
  121. .msgq_init = cvp_msgq_init,
  122. .msgq_deinit = cvp_msgq_deinit,
  123. .msgq_send = cvp_msgq_send,
  124. .msgq_receive = cvp_msgq_receive,
  125. };
  126. struct cvp_msgq_drv cvp_ipc_msgq = {
  127. .ops = &msgq_ops,
  128. };