ivpu_ipc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2020-2024 Intel Corporation
  4. */
  5. #include <linux/genalloc.h>
  6. #include <linux/highmem.h>
  7. #include <linux/pm_runtime.h>
  8. #include <linux/wait.h>
  9. #include "ivpu_drv.h"
  10. #include "ivpu_gem.h"
  11. #include "ivpu_hw.h"
  12. #include "ivpu_hw_reg_io.h"
  13. #include "ivpu_ipc.h"
  14. #include "ivpu_jsm_msg.h"
  15. #include "ivpu_pm.h"
  16. #include "ivpu_trace.h"
  17. #define IPC_MAX_RX_MSG 128
  18. struct ivpu_ipc_tx_buf {
  19. struct ivpu_ipc_hdr ipc;
  20. struct vpu_jsm_msg jsm;
  21. };
  22. static void ivpu_ipc_msg_dump(struct ivpu_device *vdev, char *c,
  23. struct ivpu_ipc_hdr *ipc_hdr, u32 vpu_addr)
  24. {
  25. ivpu_dbg(vdev, IPC,
  26. "%s: vpu:0x%x (data_addr:0x%08x, data_size:0x%x, channel:0x%x, src_node:0x%x, dst_node:0x%x, status:0x%x)",
  27. c, vpu_addr, ipc_hdr->data_addr, ipc_hdr->data_size, ipc_hdr->channel,
  28. ipc_hdr->src_node, ipc_hdr->dst_node, ipc_hdr->status);
  29. }
  30. static void ivpu_jsm_msg_dump(struct ivpu_device *vdev, char *c,
  31. struct vpu_jsm_msg *jsm_msg, u32 vpu_addr)
  32. {
  33. u32 *payload = (u32 *)&jsm_msg->payload;
  34. ivpu_dbg(vdev, JSM,
  35. "%s: vpu:0x%08x (type:%s, status:0x%x, id: 0x%x, result: 0x%x, payload:0x%x 0x%x 0x%x 0x%x 0x%x)\n",
  36. c, vpu_addr, ivpu_jsm_msg_type_to_str(jsm_msg->type),
  37. jsm_msg->status, jsm_msg->request_id, jsm_msg->result,
  38. payload[0], payload[1], payload[2], payload[3], payload[4]);
  39. }
  40. static void
  41. ivpu_ipc_rx_mark_free(struct ivpu_device *vdev, struct ivpu_ipc_hdr *ipc_hdr,
  42. struct vpu_jsm_msg *jsm_msg)
  43. {
  44. ipc_hdr->status = IVPU_IPC_HDR_FREE;
  45. if (jsm_msg)
  46. jsm_msg->status = VPU_JSM_MSG_FREE;
  47. wmb(); /* Flush WC buffers for message statuses */
  48. }
  49. static void ivpu_ipc_mem_fini(struct ivpu_device *vdev)
  50. {
  51. struct ivpu_ipc_info *ipc = vdev->ipc;
  52. ivpu_bo_free(ipc->mem_rx);
  53. ivpu_bo_free(ipc->mem_tx);
  54. }
  55. static int
  56. ivpu_ipc_tx_prepare(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
  57. struct vpu_jsm_msg *req)
  58. {
  59. struct ivpu_ipc_info *ipc = vdev->ipc;
  60. struct ivpu_ipc_tx_buf *tx_buf;
  61. u32 tx_buf_vpu_addr;
  62. u32 jsm_vpu_addr;
  63. tx_buf_vpu_addr = gen_pool_alloc(ipc->mm_tx, sizeof(*tx_buf));
  64. if (!tx_buf_vpu_addr) {
  65. ivpu_err_ratelimited(vdev, "Failed to reserve IPC buffer, size %ld\n",
  66. sizeof(*tx_buf));
  67. return -ENOMEM;
  68. }
  69. tx_buf = ivpu_to_cpu_addr(ipc->mem_tx, tx_buf_vpu_addr);
  70. if (drm_WARN_ON(&vdev->drm, !tx_buf)) {
  71. gen_pool_free(ipc->mm_tx, tx_buf_vpu_addr, sizeof(*tx_buf));
  72. return -EIO;
  73. }
  74. jsm_vpu_addr = tx_buf_vpu_addr + offsetof(struct ivpu_ipc_tx_buf, jsm);
  75. if (tx_buf->ipc.status != IVPU_IPC_HDR_FREE)
  76. ivpu_warn_ratelimited(vdev, "IPC message vpu:0x%x not released by firmware\n",
  77. tx_buf_vpu_addr);
  78. if (tx_buf->jsm.status != VPU_JSM_MSG_FREE)
  79. ivpu_warn_ratelimited(vdev, "JSM message vpu:0x%x not released by firmware\n",
  80. jsm_vpu_addr);
  81. memset(tx_buf, 0, sizeof(*tx_buf));
  82. tx_buf->ipc.data_addr = jsm_vpu_addr;
  83. /* TODO: Set data_size to actual JSM message size, not union of all messages */
  84. tx_buf->ipc.data_size = sizeof(*req);
  85. tx_buf->ipc.channel = cons->channel;
  86. tx_buf->ipc.src_node = 0;
  87. tx_buf->ipc.dst_node = 1;
  88. tx_buf->ipc.status = IVPU_IPC_HDR_ALLOCATED;
  89. tx_buf->jsm.type = req->type;
  90. tx_buf->jsm.status = VPU_JSM_MSG_ALLOCATED;
  91. tx_buf->jsm.payload = req->payload;
  92. req->request_id = atomic_inc_return(&ipc->request_id);
  93. tx_buf->jsm.request_id = req->request_id;
  94. cons->request_id = req->request_id;
  95. wmb(); /* Flush WC buffers for IPC, JSM msgs */
  96. cons->tx_vpu_addr = tx_buf_vpu_addr;
  97. ivpu_jsm_msg_dump(vdev, "TX", &tx_buf->jsm, jsm_vpu_addr);
  98. ivpu_ipc_msg_dump(vdev, "TX", &tx_buf->ipc, tx_buf_vpu_addr);
  99. return 0;
  100. }
  101. static void ivpu_ipc_tx_release(struct ivpu_device *vdev, u32 vpu_addr)
  102. {
  103. struct ivpu_ipc_info *ipc = vdev->ipc;
  104. if (vpu_addr)
  105. gen_pool_free(ipc->mm_tx, vpu_addr, sizeof(struct ivpu_ipc_tx_buf));
  106. }
  107. static void ivpu_ipc_tx(struct ivpu_device *vdev, u32 vpu_addr)
  108. {
  109. ivpu_hw_ipc_tx_set(vdev, vpu_addr);
  110. }
  111. static void
  112. ivpu_ipc_rx_msg_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
  113. struct ivpu_ipc_hdr *ipc_hdr, struct vpu_jsm_msg *jsm_msg)
  114. {
  115. struct ivpu_ipc_info *ipc = vdev->ipc;
  116. struct ivpu_ipc_rx_msg *rx_msg;
  117. lockdep_assert_held(&ipc->cons_lock);
  118. rx_msg = kzalloc_obj(*rx_msg, GFP_ATOMIC);
  119. if (!rx_msg) {
  120. ivpu_ipc_rx_mark_free(vdev, ipc_hdr, jsm_msg);
  121. return;
  122. }
  123. atomic_inc(&ipc->rx_msg_count);
  124. rx_msg->ipc_hdr = ipc_hdr;
  125. rx_msg->jsm_msg = jsm_msg;
  126. rx_msg->callback = cons->rx_callback;
  127. if (rx_msg->callback) {
  128. list_add_tail(&rx_msg->link, &ipc->cb_msg_list);
  129. } else {
  130. spin_lock(&cons->rx_lock);
  131. list_add_tail(&rx_msg->link, &cons->rx_msg_list);
  132. spin_unlock(&cons->rx_lock);
  133. wake_up(&cons->rx_msg_wq);
  134. }
  135. }
  136. static void
  137. ivpu_ipc_rx_msg_del(struct ivpu_device *vdev, struct ivpu_ipc_rx_msg *rx_msg)
  138. {
  139. list_del(&rx_msg->link);
  140. ivpu_ipc_rx_mark_free(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg);
  141. atomic_dec(&vdev->ipc->rx_msg_count);
  142. kfree(rx_msg);
  143. }
  144. void ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
  145. u32 channel, ivpu_ipc_rx_callback_t rx_callback)
  146. {
  147. struct ivpu_ipc_info *ipc = vdev->ipc;
  148. INIT_LIST_HEAD(&cons->link);
  149. cons->channel = channel;
  150. cons->tx_vpu_addr = 0;
  151. cons->request_id = 0;
  152. cons->aborted = false;
  153. cons->rx_callback = rx_callback;
  154. spin_lock_init(&cons->rx_lock);
  155. INIT_LIST_HEAD(&cons->rx_msg_list);
  156. init_waitqueue_head(&cons->rx_msg_wq);
  157. spin_lock_irq(&ipc->cons_lock);
  158. list_add_tail(&cons->link, &ipc->cons_list);
  159. spin_unlock_irq(&ipc->cons_lock);
  160. }
  161. void ivpu_ipc_consumer_del(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons)
  162. {
  163. struct ivpu_ipc_info *ipc = vdev->ipc;
  164. struct ivpu_ipc_rx_msg *rx_msg, *r;
  165. spin_lock_irq(&ipc->cons_lock);
  166. list_del(&cons->link);
  167. spin_unlock_irq(&ipc->cons_lock);
  168. spin_lock_irq(&cons->rx_lock);
  169. list_for_each_entry_safe(rx_msg, r, &cons->rx_msg_list, link)
  170. ivpu_ipc_rx_msg_del(vdev, rx_msg);
  171. spin_unlock_irq(&cons->rx_lock);
  172. ivpu_ipc_tx_release(vdev, cons->tx_vpu_addr);
  173. }
  174. int ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, struct vpu_jsm_msg *req)
  175. {
  176. struct ivpu_ipc_info *ipc = vdev->ipc;
  177. int ret;
  178. mutex_lock(&ipc->lock);
  179. if (!ipc->on) {
  180. ret = -EAGAIN;
  181. goto unlock;
  182. }
  183. ret = ivpu_ipc_tx_prepare(vdev, cons, req);
  184. if (ret)
  185. goto unlock;
  186. ivpu_ipc_tx(vdev, cons->tx_vpu_addr);
  187. trace_jsm("[tx]", req);
  188. unlock:
  189. mutex_unlock(&ipc->lock);
  190. return ret;
  191. }
  192. static bool ivpu_ipc_rx_need_wakeup(struct ivpu_ipc_consumer *cons)
  193. {
  194. bool ret;
  195. spin_lock_irq(&cons->rx_lock);
  196. ret = !list_empty(&cons->rx_msg_list) || cons->aborted;
  197. spin_unlock_irq(&cons->rx_lock);
  198. return ret;
  199. }
  200. int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
  201. struct ivpu_ipc_hdr *ipc_buf,
  202. struct vpu_jsm_msg *jsm_msg, unsigned long timeout_ms)
  203. {
  204. struct ivpu_ipc_rx_msg *rx_msg;
  205. int wait_ret, ret = 0;
  206. if (drm_WARN_ONCE(&vdev->drm, cons->rx_callback, "Consumer works only in async mode\n"))
  207. return -EINVAL;
  208. wait_ret = wait_event_timeout(cons->rx_msg_wq,
  209. ivpu_ipc_rx_need_wakeup(cons),
  210. msecs_to_jiffies(timeout_ms));
  211. if (wait_ret == 0)
  212. return -ETIMEDOUT;
  213. spin_lock_irq(&cons->rx_lock);
  214. if (cons->aborted) {
  215. spin_unlock_irq(&cons->rx_lock);
  216. return -ECANCELED;
  217. }
  218. rx_msg = list_first_entry_or_null(&cons->rx_msg_list, struct ivpu_ipc_rx_msg, link);
  219. if (!rx_msg) {
  220. spin_unlock_irq(&cons->rx_lock);
  221. return -EAGAIN;
  222. }
  223. if (ipc_buf)
  224. memcpy(ipc_buf, rx_msg->ipc_hdr, sizeof(*ipc_buf));
  225. if (rx_msg->jsm_msg) {
  226. u32 size = min_t(int, rx_msg->ipc_hdr->data_size, sizeof(*jsm_msg));
  227. if (rx_msg->jsm_msg->result != VPU_JSM_STATUS_SUCCESS) {
  228. ivpu_err(vdev, "IPC resp result error: %d\n", rx_msg->jsm_msg->result);
  229. ret = -EBADMSG;
  230. }
  231. if (jsm_msg)
  232. memcpy(jsm_msg, rx_msg->jsm_msg, size);
  233. trace_jsm("[rx]", rx_msg->jsm_msg);
  234. }
  235. ivpu_ipc_rx_msg_del(vdev, rx_msg);
  236. spin_unlock_irq(&cons->rx_lock);
  237. return ret;
  238. }
  239. int
  240. ivpu_ipc_send_receive_internal(struct ivpu_device *vdev, struct vpu_jsm_msg *req,
  241. enum vpu_ipc_msg_type expected_resp_type,
  242. struct vpu_jsm_msg *resp, u32 channel, unsigned long timeout_ms)
  243. {
  244. struct ivpu_ipc_consumer cons;
  245. int ret;
  246. drm_WARN_ON(&vdev->drm, pm_runtime_status_suspended(vdev->drm.dev) &&
  247. pm_runtime_enabled(vdev->drm.dev));
  248. ivpu_ipc_consumer_add(vdev, &cons, channel, NULL);
  249. ret = ivpu_ipc_send(vdev, &cons, req);
  250. if (ret) {
  251. ivpu_warn_ratelimited(vdev, "IPC send failed: %d\n", ret);
  252. goto consumer_del;
  253. }
  254. ret = ivpu_ipc_receive(vdev, &cons, NULL, resp, timeout_ms);
  255. if (ret) {
  256. ivpu_warn_ratelimited(vdev, "IPC receive failed: type %s, ret %d\n",
  257. ivpu_jsm_msg_type_to_str(req->type), ret);
  258. goto consumer_del;
  259. }
  260. if (resp->type != expected_resp_type) {
  261. ivpu_warn_ratelimited(vdev, "Invalid JSM response type: 0x%x\n", resp->type);
  262. ret = -EBADE;
  263. }
  264. consumer_del:
  265. ivpu_ipc_consumer_del(vdev, &cons);
  266. return ret;
  267. }
  268. int ivpu_ipc_send_receive(struct ivpu_device *vdev, struct vpu_jsm_msg *req,
  269. enum vpu_ipc_msg_type expected_resp, struct vpu_jsm_msg *resp,
  270. u32 channel, unsigned long timeout_ms)
  271. {
  272. struct vpu_jsm_msg hb_req = { .type = VPU_JSM_MSG_QUERY_ENGINE_HB };
  273. struct vpu_jsm_msg hb_resp;
  274. int ret, hb_ret;
  275. ret = ivpu_rpm_get(vdev);
  276. if (ret < 0)
  277. return ret;
  278. ret = ivpu_ipc_send_receive_internal(vdev, req, expected_resp, resp, channel, timeout_ms);
  279. if (ret != -ETIMEDOUT)
  280. goto rpm_put;
  281. hb_ret = ivpu_ipc_send_receive_internal(vdev, &hb_req, VPU_JSM_MSG_QUERY_ENGINE_HB_DONE,
  282. &hb_resp, VPU_IPC_CHAN_ASYNC_CMD,
  283. vdev->timeout.jsm);
  284. if (hb_ret == -ETIMEDOUT)
  285. ivpu_pm_trigger_recovery(vdev, "IPC timeout");
  286. rpm_put:
  287. ivpu_rpm_put(vdev);
  288. return ret;
  289. }
  290. int ivpu_ipc_send_and_wait(struct ivpu_device *vdev, struct vpu_jsm_msg *req,
  291. u32 channel, unsigned long timeout_ms)
  292. {
  293. struct ivpu_ipc_consumer cons;
  294. int ret;
  295. ret = ivpu_rpm_get(vdev);
  296. if (ret < 0)
  297. return ret;
  298. ivpu_ipc_consumer_add(vdev, &cons, channel, NULL);
  299. ret = ivpu_ipc_send(vdev, &cons, req);
  300. if (ret) {
  301. ivpu_warn_ratelimited(vdev, "IPC send failed: %d\n", ret);
  302. goto consumer_del;
  303. }
  304. msleep(timeout_ms);
  305. consumer_del:
  306. ivpu_ipc_consumer_del(vdev, &cons);
  307. ivpu_rpm_put(vdev);
  308. return ret;
  309. }
  310. static bool
  311. ivpu_ipc_match_consumer(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
  312. struct ivpu_ipc_hdr *ipc_hdr, struct vpu_jsm_msg *jsm_msg)
  313. {
  314. if (cons->channel != ipc_hdr->channel)
  315. return false;
  316. if (!jsm_msg || jsm_msg->request_id == cons->request_id)
  317. return true;
  318. return false;
  319. }
  320. void ivpu_ipc_irq_handler(struct ivpu_device *vdev)
  321. {
  322. struct ivpu_ipc_info *ipc = vdev->ipc;
  323. struct ivpu_ipc_consumer *cons;
  324. struct ivpu_ipc_hdr *ipc_hdr;
  325. struct vpu_jsm_msg *jsm_msg;
  326. unsigned long flags;
  327. bool dispatched;
  328. u32 vpu_addr;
  329. /*
  330. * Driver needs to purge all messages from IPC FIFO to clear IPC interrupt.
  331. * Without purge IPC FIFO to 0 next IPC interrupts won't be generated.
  332. */
  333. while (ivpu_hw_ipc_rx_count_get(vdev)) {
  334. vpu_addr = ivpu_hw_ipc_rx_addr_get(vdev);
  335. if (vpu_addr == REG_IO_ERROR) {
  336. ivpu_err_ratelimited(vdev, "Failed to read IPC rx addr register\n");
  337. return;
  338. }
  339. ipc_hdr = ivpu_to_cpu_addr(ipc->mem_rx, vpu_addr);
  340. if (!ipc_hdr) {
  341. ivpu_warn_ratelimited(vdev, "IPC msg 0x%x out of range\n", vpu_addr);
  342. continue;
  343. }
  344. ivpu_ipc_msg_dump(vdev, "RX", ipc_hdr, vpu_addr);
  345. jsm_msg = NULL;
  346. if (ipc_hdr->channel != IVPU_IPC_CHAN_BOOT_MSG) {
  347. jsm_msg = ivpu_to_cpu_addr(ipc->mem_rx, ipc_hdr->data_addr);
  348. if (!jsm_msg) {
  349. ivpu_warn_ratelimited(vdev, "JSM msg 0x%x out of range\n",
  350. ipc_hdr->data_addr);
  351. ivpu_ipc_rx_mark_free(vdev, ipc_hdr, NULL);
  352. continue;
  353. }
  354. ivpu_jsm_msg_dump(vdev, "RX", jsm_msg, ipc_hdr->data_addr);
  355. }
  356. if (atomic_read(&ipc->rx_msg_count) > IPC_MAX_RX_MSG) {
  357. ivpu_warn_ratelimited(vdev, "IPC RX msg dropped, msg count %d\n",
  358. IPC_MAX_RX_MSG);
  359. ivpu_ipc_rx_mark_free(vdev, ipc_hdr, jsm_msg);
  360. continue;
  361. }
  362. dispatched = false;
  363. spin_lock_irqsave(&ipc->cons_lock, flags);
  364. list_for_each_entry(cons, &ipc->cons_list, link) {
  365. if (ivpu_ipc_match_consumer(vdev, cons, ipc_hdr, jsm_msg)) {
  366. ivpu_ipc_rx_msg_add(vdev, cons, ipc_hdr, jsm_msg);
  367. dispatched = true;
  368. break;
  369. }
  370. }
  371. spin_unlock_irqrestore(&ipc->cons_lock, flags);
  372. if (!dispatched) {
  373. ivpu_dbg(vdev, IPC, "IPC RX msg 0x%x dropped (no consumer)\n", vpu_addr);
  374. ivpu_ipc_rx_mark_free(vdev, ipc_hdr, jsm_msg);
  375. }
  376. }
  377. queue_work(system_percpu_wq, &vdev->irq_ipc_work);
  378. }
  379. void ivpu_ipc_irq_work_fn(struct work_struct *work)
  380. {
  381. struct ivpu_device *vdev = container_of(work, struct ivpu_device, irq_ipc_work);
  382. struct ivpu_ipc_info *ipc = vdev->ipc;
  383. struct ivpu_ipc_rx_msg *rx_msg, *r;
  384. struct list_head cb_msg_list;
  385. INIT_LIST_HEAD(&cb_msg_list);
  386. spin_lock_irq(&ipc->cons_lock);
  387. list_splice_tail_init(&ipc->cb_msg_list, &cb_msg_list);
  388. spin_unlock_irq(&ipc->cons_lock);
  389. list_for_each_entry_safe(rx_msg, r, &cb_msg_list, link) {
  390. rx_msg->callback(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg);
  391. ivpu_ipc_rx_msg_del(vdev, rx_msg);
  392. }
  393. }
  394. int ivpu_ipc_init(struct ivpu_device *vdev)
  395. {
  396. struct ivpu_ipc_info *ipc = vdev->ipc;
  397. int ret;
  398. ipc->mem_tx = ivpu_bo_create_global(vdev, SZ_16K, DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE);
  399. if (!ipc->mem_tx) {
  400. ivpu_err(vdev, "Failed to allocate mem_tx\n");
  401. return -ENOMEM;
  402. }
  403. ipc->mem_rx = ivpu_bo_create_global(vdev, SZ_16K, DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE);
  404. if (!ipc->mem_rx) {
  405. ivpu_err(vdev, "Failed to allocate mem_rx\n");
  406. ret = -ENOMEM;
  407. goto err_free_tx;
  408. }
  409. ipc->mm_tx = devm_gen_pool_create(vdev->drm.dev, __ffs(IVPU_IPC_ALIGNMENT),
  410. -1, "TX_IPC_JSM");
  411. if (IS_ERR(ipc->mm_tx)) {
  412. ret = PTR_ERR(ipc->mm_tx);
  413. ivpu_err(vdev, "Failed to create gen pool, %pe\n", ipc->mm_tx);
  414. goto err_free_rx;
  415. }
  416. ret = gen_pool_add(ipc->mm_tx, ipc->mem_tx->vpu_addr, ivpu_bo_size(ipc->mem_tx), -1);
  417. if (ret) {
  418. ivpu_err(vdev, "gen_pool_add failed, ret %d\n", ret);
  419. goto err_free_rx;
  420. }
  421. spin_lock_init(&ipc->cons_lock);
  422. INIT_LIST_HEAD(&ipc->cons_list);
  423. INIT_LIST_HEAD(&ipc->cb_msg_list);
  424. ret = drmm_mutex_init(&vdev->drm, &ipc->lock);
  425. if (ret) {
  426. ivpu_err(vdev, "Failed to initialize ipc->lock, ret %d\n", ret);
  427. goto err_free_rx;
  428. }
  429. ivpu_ipc_reset(vdev);
  430. return 0;
  431. err_free_rx:
  432. ivpu_bo_free(ipc->mem_rx);
  433. err_free_tx:
  434. ivpu_bo_free(ipc->mem_tx);
  435. return ret;
  436. }
  437. void ivpu_ipc_fini(struct ivpu_device *vdev)
  438. {
  439. struct ivpu_ipc_info *ipc = vdev->ipc;
  440. drm_WARN_ON(&vdev->drm, !list_empty(&ipc->cons_list));
  441. drm_WARN_ON(&vdev->drm, !list_empty(&ipc->cb_msg_list));
  442. drm_WARN_ON(&vdev->drm, atomic_read(&ipc->rx_msg_count) > 0);
  443. ivpu_ipc_mem_fini(vdev);
  444. }
  445. void ivpu_ipc_enable(struct ivpu_device *vdev)
  446. {
  447. struct ivpu_ipc_info *ipc = vdev->ipc;
  448. mutex_lock(&ipc->lock);
  449. ipc->on = true;
  450. mutex_unlock(&ipc->lock);
  451. }
  452. void ivpu_ipc_disable(struct ivpu_device *vdev)
  453. {
  454. struct ivpu_ipc_info *ipc = vdev->ipc;
  455. struct ivpu_ipc_consumer *cons, *c;
  456. struct ivpu_ipc_rx_msg *rx_msg, *r;
  457. drm_WARN_ON(&vdev->drm, !list_empty(&ipc->cb_msg_list));
  458. mutex_lock(&ipc->lock);
  459. ipc->on = false;
  460. mutex_unlock(&ipc->lock);
  461. spin_lock_irq(&ipc->cons_lock);
  462. list_for_each_entry_safe(cons, c, &ipc->cons_list, link) {
  463. spin_lock(&cons->rx_lock);
  464. if (!cons->rx_callback)
  465. cons->aborted = true;
  466. list_for_each_entry_safe(rx_msg, r, &cons->rx_msg_list, link)
  467. ivpu_ipc_rx_msg_del(vdev, rx_msg);
  468. spin_unlock(&cons->rx_lock);
  469. wake_up(&cons->rx_msg_wq);
  470. }
  471. spin_unlock_irq(&ipc->cons_lock);
  472. drm_WARN_ON(&vdev->drm, atomic_read(&ipc->rx_msg_count) > 0);
  473. }
  474. void ivpu_ipc_reset(struct ivpu_device *vdev)
  475. {
  476. struct ivpu_ipc_info *ipc = vdev->ipc;
  477. mutex_lock(&ipc->lock);
  478. drm_WARN_ON(&vdev->drm, ipc->on);
  479. memset(ivpu_bo_vaddr(ipc->mem_tx), 0, ivpu_bo_size(ipc->mem_tx));
  480. memset(ivpu_bo_vaddr(ipc->mem_rx), 0, ivpu_bo_size(ipc->mem_rx));
  481. wmb(); /* Flush WC buffers for TX and RX rings */
  482. mutex_unlock(&ipc->lock);
  483. }