iosm_ipc_protocol.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2020-21 Intel Corporation.
  4. */
  5. #include "iosm_ipc_imem.h"
  6. #include "iosm_ipc_protocol.h"
  7. #include "iosm_ipc_protocol_ops.h"
  8. #include "iosm_ipc_pm.h"
  9. #include "iosm_ipc_task_queue.h"
  10. int ipc_protocol_tq_msg_send(struct iosm_protocol *ipc_protocol,
  11. enum ipc_msg_prep_type msg_type,
  12. union ipc_msg_prep_args *prep_args,
  13. struct ipc_rsp *response)
  14. {
  15. int index = ipc_protocol_msg_prep(ipc_protocol->imem, msg_type,
  16. prep_args);
  17. /* Store reference towards caller specified response in response ring
  18. * and signal CP
  19. */
  20. if (index >= 0 && index < IPC_MEM_MSG_ENTRIES) {
  21. ipc_protocol->rsp_ring[index] = response;
  22. ipc_protocol_msg_hp_update(ipc_protocol->imem);
  23. }
  24. return index;
  25. }
  26. /* Callback for message send */
  27. static int ipc_protocol_tq_msg_send_cb(struct iosm_imem *ipc_imem, int arg,
  28. void *msg, size_t size)
  29. {
  30. struct ipc_call_msg_send_args *send_args = msg;
  31. struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
  32. return ipc_protocol_tq_msg_send(ipc_protocol, send_args->msg_type,
  33. send_args->prep_args,
  34. send_args->response);
  35. }
  36. /* Remove reference to a response. This is typically used when a requestor timed
  37. * out and is no longer interested in the response.
  38. */
  39. static int ipc_protocol_tq_msg_remove(struct iosm_imem *ipc_imem, int arg,
  40. void *msg, size_t size)
  41. {
  42. struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
  43. ipc_protocol->rsp_ring[arg] = NULL;
  44. return 0;
  45. }
  46. int ipc_protocol_msg_send(struct iosm_protocol *ipc_protocol,
  47. enum ipc_msg_prep_type prep,
  48. union ipc_msg_prep_args *prep_args)
  49. {
  50. struct ipc_call_msg_send_args send_args;
  51. unsigned int exec_timeout;
  52. struct ipc_rsp response;
  53. int index;
  54. exec_timeout = (ipc_protocol_get_ap_exec_stage(ipc_protocol) ==
  55. IPC_MEM_EXEC_STAGE_RUN ?
  56. IPC_MSG_COMPLETE_RUN_DEFAULT_TIMEOUT :
  57. IPC_MSG_COMPLETE_BOOT_DEFAULT_TIMEOUT);
  58. /* Trap if called from non-preemptible context */
  59. might_sleep();
  60. response.status = IPC_MEM_MSG_CS_INVALID;
  61. init_completion(&response.completion);
  62. send_args.msg_type = prep;
  63. send_args.prep_args = prep_args;
  64. send_args.response = &response;
  65. /* Allocate and prepare message to be sent in tasklet context.
  66. * A positive index returned form tasklet_call references the message
  67. * in case it needs to be cancelled when there is a timeout.
  68. */
  69. index = ipc_task_queue_send_task(ipc_protocol->imem,
  70. ipc_protocol_tq_msg_send_cb, 0,
  71. &send_args, 0, true);
  72. if (index < 0) {
  73. dev_err(ipc_protocol->dev, "msg %d failed", prep);
  74. return index;
  75. }
  76. /* Wait for the device to respond to the message */
  77. switch (wait_for_completion_timeout(&response.completion,
  78. msecs_to_jiffies(exec_timeout))) {
  79. case 0:
  80. /* Timeout, there was no response from the device.
  81. * Remove the reference to the local response completion
  82. * object as we are no longer interested in the response.
  83. */
  84. ipc_task_queue_send_task(ipc_protocol->imem,
  85. ipc_protocol_tq_msg_remove, index,
  86. NULL, 0, true);
  87. dev_err(ipc_protocol->dev, "msg timeout");
  88. ipc_uevent_send(ipc_protocol->pcie->dev, UEVENT_MDM_TIMEOUT);
  89. break;
  90. default:
  91. /* We got a response in time; check completion status: */
  92. if (response.status != IPC_MEM_MSG_CS_SUCCESS) {
  93. dev_err(ipc_protocol->dev,
  94. "msg completion status error %d",
  95. response.status);
  96. return -EIO;
  97. }
  98. }
  99. return 0;
  100. }
  101. static int ipc_protocol_msg_send_host_sleep(struct iosm_protocol *ipc_protocol,
  102. u32 state)
  103. {
  104. union ipc_msg_prep_args prep_args = {
  105. .sleep.target = 0,
  106. .sleep.state = state,
  107. };
  108. return ipc_protocol_msg_send(ipc_protocol, IPC_MSG_PREP_SLEEP,
  109. &prep_args);
  110. }
  111. void ipc_protocol_doorbell_trigger(struct iosm_protocol *ipc_protocol,
  112. u32 identifier)
  113. {
  114. ipc_pm_signal_hpda_doorbell(&ipc_protocol->pm, identifier, true);
  115. }
  116. bool ipc_protocol_pm_dev_sleep_handle(struct iosm_protocol *ipc_protocol)
  117. {
  118. u32 ipc_status = ipc_protocol_get_ipc_status(ipc_protocol);
  119. u32 requested;
  120. if (ipc_status != IPC_MEM_DEVICE_IPC_RUNNING) {
  121. dev_err(ipc_protocol->dev,
  122. "irq ignored, CP IPC state is %d, should be RUNNING",
  123. ipc_status);
  124. /* Stop further processing. */
  125. return false;
  126. }
  127. /* Get a copy of the requested PM state by the device and the local
  128. * device PM state.
  129. */
  130. requested = ipc_protocol_pm_dev_get_sleep_notification(ipc_protocol);
  131. return ipc_pm_dev_slp_notification(&ipc_protocol->pm, requested);
  132. }
  133. static int ipc_protocol_tq_wakeup_dev_slp(struct iosm_imem *ipc_imem, int arg,
  134. void *msg, size_t size)
  135. {
  136. struct iosm_pm *ipc_pm = &ipc_imem->ipc_protocol->pm;
  137. /* Wakeup from device sleep if it is not ACTIVE */
  138. ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_HS, true);
  139. ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_HS, false);
  140. return 0;
  141. }
  142. void ipc_protocol_s2idle_sleep(struct iosm_protocol *ipc_protocol, bool sleep)
  143. {
  144. ipc_pm_set_s2idle_sleep(&ipc_protocol->pm, sleep);
  145. }
  146. bool ipc_protocol_suspend(struct iosm_protocol *ipc_protocol)
  147. {
  148. if (!ipc_pm_prepare_host_sleep(&ipc_protocol->pm))
  149. goto err;
  150. ipc_task_queue_send_task(ipc_protocol->imem,
  151. ipc_protocol_tq_wakeup_dev_slp, 0, NULL, 0,
  152. true);
  153. if (!ipc_pm_wait_for_device_active(&ipc_protocol->pm)) {
  154. ipc_uevent_send(ipc_protocol->pcie->dev, UEVENT_MDM_TIMEOUT);
  155. goto err;
  156. }
  157. /* Send the sleep message for sync sys calls. */
  158. dev_dbg(ipc_protocol->dev, "send TARGET_HOST, ENTER_SLEEP");
  159. if (ipc_protocol_msg_send_host_sleep(ipc_protocol,
  160. IPC_HOST_SLEEP_ENTER_SLEEP)) {
  161. /* Sending ENTER_SLEEP message failed, we are still active */
  162. ipc_protocol->pm.host_pm_state = IPC_MEM_HOST_PM_ACTIVE;
  163. goto err;
  164. }
  165. ipc_protocol->pm.host_pm_state = IPC_MEM_HOST_PM_SLEEP;
  166. return true;
  167. err:
  168. return false;
  169. }
  170. bool ipc_protocol_resume(struct iosm_protocol *ipc_protocol)
  171. {
  172. if (!ipc_pm_prepare_host_active(&ipc_protocol->pm))
  173. return false;
  174. dev_dbg(ipc_protocol->dev, "send TARGET_HOST, EXIT_SLEEP");
  175. if (ipc_protocol_msg_send_host_sleep(ipc_protocol,
  176. IPC_HOST_SLEEP_EXIT_SLEEP)) {
  177. ipc_protocol->pm.host_pm_state = IPC_MEM_HOST_PM_SLEEP;
  178. return false;
  179. }
  180. ipc_protocol->pm.host_pm_state = IPC_MEM_HOST_PM_ACTIVE;
  181. return true;
  182. }
  183. struct iosm_protocol *ipc_protocol_init(struct iosm_imem *ipc_imem)
  184. {
  185. struct iosm_protocol *ipc_protocol = kzalloc_obj(*ipc_protocol);
  186. struct ipc_protocol_context_info *p_ci;
  187. u64 addr;
  188. if (!ipc_protocol)
  189. return NULL;
  190. ipc_protocol->dev = ipc_imem->dev;
  191. ipc_protocol->pcie = ipc_imem->pcie;
  192. ipc_protocol->imem = ipc_imem;
  193. ipc_protocol->p_ap_shm = NULL;
  194. ipc_protocol->phy_ap_shm = 0;
  195. ipc_protocol->old_msg_tail = 0;
  196. ipc_protocol->p_ap_shm =
  197. dma_alloc_coherent(&ipc_protocol->pcie->pci->dev,
  198. sizeof(*ipc_protocol->p_ap_shm),
  199. &ipc_protocol->phy_ap_shm, GFP_KERNEL);
  200. if (!ipc_protocol->p_ap_shm) {
  201. dev_err(ipc_protocol->dev, "pci shm alloc error");
  202. kfree(ipc_protocol);
  203. return NULL;
  204. }
  205. /* Prepare the context info for CP. */
  206. addr = ipc_protocol->phy_ap_shm;
  207. p_ci = &ipc_protocol->p_ap_shm->ci;
  208. p_ci->device_info_addr =
  209. addr + offsetof(struct ipc_protocol_ap_shm, device_info);
  210. p_ci->head_array =
  211. addr + offsetof(struct ipc_protocol_ap_shm, head_array);
  212. p_ci->tail_array =
  213. addr + offsetof(struct ipc_protocol_ap_shm, tail_array);
  214. p_ci->msg_head = addr + offsetof(struct ipc_protocol_ap_shm, msg_head);
  215. p_ci->msg_tail = addr + offsetof(struct ipc_protocol_ap_shm, msg_tail);
  216. p_ci->msg_ring_addr =
  217. addr + offsetof(struct ipc_protocol_ap_shm, msg_ring);
  218. p_ci->msg_ring_entries = cpu_to_le16(IPC_MEM_MSG_ENTRIES);
  219. p_ci->msg_irq_vector = IPC_MSG_IRQ_VECTOR;
  220. p_ci->device_info_irq_vector = IPC_DEVICE_IRQ_VECTOR;
  221. ipc_mmio_set_contex_info_addr(ipc_imem->mmio, addr);
  222. ipc_pm_init(ipc_protocol);
  223. return ipc_protocol;
  224. }
  225. void ipc_protocol_deinit(struct iosm_protocol *proto)
  226. {
  227. dma_free_coherent(&proto->pcie->pci->dev, sizeof(*proto->p_ap_shm),
  228. proto->p_ap_shm, proto->phy_ap_shm);
  229. ipc_pm_deinit(proto);
  230. kfree(proto);
  231. }