ghs_comm.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include "hab.h"
  7. #include "hab_ghs.h"
  8. int physical_channel_read(struct physical_channel *pchan,
  9. void *payload,
  10. size_t read_size)
  11. {
  12. struct ghs_vdev *dev = (struct ghs_vdev *)pchan->hyp_data;
  13. /* size in header is only for payload excluding the header itself */
  14. if (dev->read_size < read_size + sizeof(struct hab_header)) {
  15. pr_warn("read %zd is less than requested %zd plus header %zd\n",
  16. dev->read_size, read_size, sizeof(struct hab_header));
  17. read_size = 0;
  18. } else {
  19. /* always skip the header */
  20. memcpy(payload, (unsigned char *)dev->read_data +
  21. sizeof(struct hab_header) + dev->read_offset, read_size);
  22. dev->read_offset += read_size;
  23. }
  24. return read_size;
  25. }
  26. int physical_channel_send(struct physical_channel *pchan,
  27. struct hab_header *header,
  28. void *payload,
  29. unsigned int flags)
  30. {
  31. size_t sizebytes = HAB_HEADER_GET_SIZE(*header);
  32. struct ghs_vdev *dev = (struct ghs_vdev *)pchan->hyp_data;
  33. GIPC_Result result;
  34. uint8_t *msg;
  35. int irqs_disabled;
  36. /* Only used in virtio arch */
  37. (void)flags;
  38. if (!dev) {
  39. pr_err("no send pchan %s has been de-alloced msg for %zd bytes\n",
  40. pchan->name);
  41. return -ENODEV;
  42. }
  43. irqs_disabled = irqs_disabled();
  44. hab_spin_lock(&dev->io_lock, irqs_disabled);
  45. result = hab_gipc_wait_to_send(dev->endpoint);
  46. if (result != GIPC_Success) {
  47. hab_spin_unlock(&dev->io_lock, irqs_disabled);
  48. pr_err("failed to wait to send %d\n", result);
  49. return -EBUSY;
  50. }
  51. result = GIPC_PrepareMessage(dev->endpoint, sizebytes+sizeof(*header),
  52. (void **)&msg);
  53. if (result == GIPC_Full) {
  54. hab_spin_unlock(&dev->io_lock, irqs_disabled);
  55. /* need to wait for space! */
  56. pr_err("failed to reserve send msg for %zd bytes\n",
  57. sizebytes+sizeof(*header));
  58. return -EBUSY;
  59. } else if (result != GIPC_Success) {
  60. hab_spin_unlock(&dev->io_lock, irqs_disabled);
  61. pr_err("failed to send due to error %d\n", result);
  62. return -ENOMEM;
  63. }
  64. if (HAB_HEADER_GET_TYPE(*header) == HAB_PAYLOAD_TYPE_PROFILE) {
  65. struct timespec64 ts = {0};
  66. struct habmm_xing_vm_stat *pstat =
  67. (struct habmm_xing_vm_stat *)payload;
  68. ktime_get_ts64(&ts);
  69. pstat->tx_sec = ts.tv_sec;
  70. pstat->tx_usec = ts.tv_nsec/NSEC_PER_USEC;
  71. }
  72. memcpy(msg, header, sizeof(*header));
  73. if (sizebytes)
  74. memcpy(msg+sizeof(*header), payload, sizebytes);
  75. result = GIPC_IssueMessage(dev->endpoint, sizebytes+sizeof(*header),
  76. header->id_type);
  77. hab_spin_unlock(&dev->io_lock, irqs_disabled);
  78. if (result != GIPC_Success) {
  79. pr_err("send error %d, sz %zd, id type %x, size %x\n",
  80. result, sizebytes+sizeof(*header),
  81. header->id_type, header->payload_size);
  82. return -EAGAIN;
  83. }
  84. return 0;
  85. }
  86. void physical_channel_rx_dispatch_common(unsigned long physical_channel)
  87. {
  88. struct hab_header header;
  89. struct physical_channel *pchan =
  90. (struct physical_channel *)physical_channel;
  91. struct ghs_vdev *dev = (struct ghs_vdev *)pchan->hyp_data;
  92. GIPC_Result result;
  93. int irqs_disabled;
  94. if (!dev) {
  95. pr_err("no recv pchan %s has been de-alloced msg for %zd bytes\n",
  96. pchan->name);
  97. return;
  98. }
  99. irqs_disabled = irqs_disabled();
  100. hab_spin_lock(&pchan->rxbuf_lock, irqs_disabled);
  101. while (1) {
  102. dev->read_size = 0;
  103. dev->read_offset = 0;
  104. result = GIPC_ReceiveMessage(dev->endpoint,
  105. dev->read_data,
  106. GIPC_RECV_BUFF_SIZE_BYTES,
  107. &dev->read_size,
  108. &header.id_type);
  109. if (result == GIPC_Success || dev->read_size > 0) {
  110. /* handle corrupted msg? */
  111. hab_msg_recv(pchan, dev->read_data);
  112. continue;
  113. } else if (result == GIPC_Empty) {
  114. /* no more pending msg */
  115. break;
  116. }
  117. pr_err("recv unhandled result %d, size %zd\n",
  118. result, dev->read_size);
  119. break;
  120. }
  121. hab_spin_unlock(&pchan->rxbuf_lock, irqs_disabled);
  122. }