sde_vm_msgq.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  5. */
  6. #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
  7. #include <linux/gunyah/gh_msgq.h>
  8. #include <linux/kthread.h>
  9. #include "sde_kms.h"
  10. #include "sde_vm.h"
  11. static void _sde_vm_msgq_process_msg(struct kthread_work *work)
  12. {
  13. struct sde_vm_msg_work *vm_work =
  14. container_of(work, struct sde_vm_msg_work, work);
  15. struct sde_vm_ops *vm_ops = &vm_work->sde_vm->vm_ops;
  16. if (vm_ops->vm_msg_recv_cb)
  17. vm_ops->vm_msg_recv_cb(vm_work->sde_vm, vm_work->msg_buf,
  18. vm_work->msg_size);
  19. kfree(vm_work->msg_buf);
  20. }
  21. static int _sde_vm_msgq_listener(void *data)
  22. {
  23. struct sde_vm *sde_vm = (struct sde_vm *)data;
  24. struct sde_kms *sde_kms = sde_vm->sde_kms;
  25. struct sde_vm_msg_work *vm_work;
  26. struct msm_drm_private *priv;
  27. struct msm_drm_thread *event_thread;
  28. void *buf;
  29. size_t size;
  30. int ret = 0;
  31. priv = sde_kms->dev->dev_private;
  32. event_thread = &priv->event_thread[0];
  33. vm_work = &sde_vm->vm_work;
  34. while (true) {
  35. buf = kzalloc(GH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
  36. if (!buf)
  37. return -ENOMEM;
  38. ret = gh_msgq_recv(sde_vm->msgq_handle, buf,
  39. GH_MSGQ_MAX_MSG_SIZE_BYTES, &size, 0);
  40. if (ret < 0) {
  41. kfree(buf);
  42. SDE_ERROR("gh_msgq_recv failed, rc=%d\n", ret);
  43. return -EINVAL;
  44. }
  45. vm_work->msg_buf = buf;
  46. vm_work->msg_size = size;
  47. vm_work->sde_vm = sde_vm;
  48. kthread_queue_work(&event_thread->worker, &vm_work->work);
  49. }
  50. return 0;
  51. }
  52. int sde_vm_msgq_send(struct sde_vm *sde_vm, void *msg, size_t msg_size)
  53. {
  54. if (!sde_vm->msgq_handle) {
  55. SDE_ERROR("Failed to send msg, invalid msgq handle\n");
  56. return -EINVAL;
  57. }
  58. if (msg_size > GH_MSGQ_MAX_MSG_SIZE_BYTES) {
  59. SDE_ERROR("msg size unsupported for msgq: %ld > %d\n", msg_size,
  60. GH_MSGQ_MAX_MSG_SIZE_BYTES);
  61. return -E2BIG;
  62. }
  63. return gh_msgq_send(sde_vm->msgq_handle, msg, msg_size, GH_MSGQ_TX_PUSH);
  64. }
  65. int sde_vm_msgq_init(struct sde_vm *sde_vm)
  66. {
  67. struct sde_vm_ops *vm_ops = &sde_vm->vm_ops;
  68. void *msgq_handle = NULL;
  69. struct task_struct *msgq_listener_thread = NULL;
  70. int rc = 0;
  71. msgq_handle = gh_msgq_register(GH_MSGQ_LABEL_DISPLAY);
  72. if (IS_ERR(msgq_handle)) {
  73. SDE_ERROR("gh_msgq_register failed, hdl=%p\n", msgq_handle);
  74. return -EINVAL;
  75. }
  76. sde_vm->msgq_handle = msgq_handle;
  77. if (!vm_ops->vm_msg_recv_cb)
  78. goto done;
  79. msgq_listener_thread = kthread_run(_sde_vm_msgq_listener,
  80. (void *)sde_vm, "disp_msgq_listener");
  81. if (IS_ERR(msgq_listener_thread)) {
  82. SDE_ERROR("kthread creation failed for msgq, hdl: %p\n",
  83. msgq_listener_thread);
  84. rc = -EINVAL;
  85. goto kthread_create_fail;
  86. }
  87. kthread_init_work(&sde_vm->vm_work.work, _sde_vm_msgq_process_msg);
  88. sde_vm->msgq_listener_thread = msgq_listener_thread;
  89. return 0;
  90. kthread_create_fail:
  91. gh_msgq_unregister(msgq_handle);
  92. sde_vm->msgq_handle = NULL;
  93. done:
  94. return rc;
  95. }
  96. void sde_vm_msgq_deinit(struct sde_vm *sde_vm)
  97. {
  98. if (sde_vm->msgq_listener_thread)
  99. kthread_stop(sde_vm->msgq_listener_thread);
  100. if (sde_vm->msgq_handle)
  101. gh_msgq_unregister(sde_vm->msgq_handle);
  102. }