msm_cvp_dsp.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/module.h>
  6. #include <linux/rpmsg.h>
  7. #include <linux/of_platform.h>
  8. #include <linux/of_fdt.h>
  9. #include <soc/qcom/secure_buffer.h>
  10. #include "msm_cvp_dsp.h"
  11. #include "msm_cvp_internal.h"
  12. struct cvp_dsp_apps gfa_cv;
  13. static int hlosVM[HLOS_VM_NUM] = {VMID_HLOS};
  14. static int dspVM[DSP_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6};
  15. static int dspVMperm[DSP_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC,
  16. PERM_READ | PERM_WRITE | PERM_EXEC };
  17. static int hlosVMperm[HLOS_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC };
  18. static int cvp_dsp_send_cmd(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
  19. {
  20. int rc = 0;
  21. struct cvp_dsp_apps *me = &gfa_cv;
  22. dprintk(CVP_DSP, "%s: cmd = %d\n", __func__, cmd->type);
  23. if (IS_ERR_OR_NULL(me->chan)) {
  24. dprintk(CVP_ERR, "%s: DSP GLink is not ready\n", __func__);
  25. rc = -EINVAL;
  26. goto exit;
  27. }
  28. rc = rpmsg_send(me->chan->ept, cmd, len);
  29. if (rc) {
  30. dprintk(CVP_ERR, "%s: DSP rpmsg_send failed rc=%d\n",
  31. __func__, rc);
  32. goto exit;
  33. }
  34. exit:
  35. return rc;
  36. }
  37. static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
  38. {
  39. int rc = 0;
  40. struct cvp_dsp_apps *me = &gfa_cv;
  41. dprintk(CVP_DSP, "%s: cmd = %d\n", __func__, cmd->type);
  42. me->pending_dsp2cpu_rsp.type = cmd->type;
  43. rc = cvp_dsp_send_cmd(cmd, len);
  44. if (rc) {
  45. dprintk(CVP_ERR, "%s: cvp_dsp_send_cmd failed rc=%d\n",
  46. __func__, rc);
  47. goto exit;
  48. }
  49. if (!wait_for_completion_timeout(&me->completions[cmd->type],
  50. msecs_to_jiffies(CVP_DSP_RESPONSE_TIMEOUT))) {
  51. dprintk(CVP_ERR, "%s cmd %d timeout\n", __func__, cmd->type);
  52. rc = -ETIMEDOUT;
  53. goto exit;
  54. }
  55. exit:
  56. me->pending_dsp2cpu_rsp.type = CVP_INVALID_RPMSG_TYPE;
  57. return rc;
  58. }
  59. static int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
  60. uint32_t size_in_bytes)
  61. {
  62. int rc = 0;
  63. struct cvp_dsp_cmd_msg cmd;
  64. cmd.type = CPU2DSP_SEND_HFI_QUEUE;
  65. cmd.msg_ptr = (uint64_t)phys_addr;
  66. cmd.msg_ptr_len = size_in_bytes;
  67. cmd.ddr_type = of_fdt_get_ddrtype();
  68. if (cmd.ddr_type < 0) {
  69. dprintk(CVP_ERR,
  70. "%s: Incorrect DDR type value %d\n",
  71. __func__, cmd.ddr_type);
  72. return -EINVAL;
  73. }
  74. dprintk(CVP_DSP,
  75. "%s: address of buffer, PA=0x%pK size_buff=%d ddr_type=%d\n",
  76. __func__, phys_addr, size_in_bytes, cmd.ddr_type);
  77. rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
  78. if (rc) {
  79. dprintk(CVP_ERR,
  80. "%s: cvp_dsp_send_cmd failed rc = %d\n",
  81. __func__, rc);
  82. goto exit;
  83. }
  84. exit:
  85. return rc;
  86. }
  87. static int cvp_hyp_assign_to_dsp(uint64_t addr, uint32_t size)
  88. {
  89. int rc = 0;
  90. struct cvp_dsp_apps *me = &gfa_cv;
  91. if (!me->hyp_assigned) {
  92. rc = hyp_assign_phys(addr, size, hlosVM, HLOS_VM_NUM, dspVM,
  93. dspVMperm, DSP_VM_NUM);
  94. if (rc) {
  95. dprintk(CVP_ERR, "%s failed. rc=%d\n", __func__, rc);
  96. return rc;
  97. }
  98. me->addr = addr;
  99. me->size = size;
  100. me->hyp_assigned = true;
  101. }
  102. return rc;
  103. }
  104. static int cvp_hyp_assign_from_dsp(void)
  105. {
  106. int rc = 0;
  107. struct cvp_dsp_apps *me = &gfa_cv;
  108. if (me->hyp_assigned) {
  109. rc = hyp_assign_phys(me->addr, me->size, dspVM, DSP_VM_NUM,
  110. hlosVM, hlosVMperm, HLOS_VM_NUM);
  111. if (rc) {
  112. dprintk(CVP_ERR, "%s failed. rc=%d\n", __func__, rc);
  113. return rc;
  114. }
  115. me->addr = 0;
  116. me->size = 0;
  117. me->hyp_assigned = false;
  118. }
  119. return rc;
  120. }
  121. static int cvp_dsp_rpmsg_probe(struct rpmsg_device *rpdev)
  122. {
  123. struct cvp_dsp_apps *me = &gfa_cv;
  124. if (strcmp(rpdev->dev.parent->of_node->name, "cdsp")) {
  125. dprintk(CVP_ERR,
  126. "%s: Failed to probe rpmsg device.Node name:%s\n",
  127. __func__, rpdev->dev.parent->of_node->name);
  128. return -EINVAL;
  129. }
  130. mutex_lock(&me->lock);
  131. me->chan = rpdev;
  132. me->state = DSP_PROBED;
  133. complete(&me->completions[CPU2DSP_MAX_CMD]);
  134. mutex_unlock(&me->lock);
  135. return 0;
  136. }
  137. static void cvp_dsp_rpmsg_remove(struct rpmsg_device *rpdev)
  138. {
  139. struct cvp_dsp_apps *me = &gfa_cv;
  140. dprintk(CVP_WARN, "%s: CDSP SSR triggered\n", __func__);
  141. mutex_lock(&me->lock);
  142. cvp_hyp_assign_from_dsp();
  143. me->chan = NULL;
  144. me->state = DSP_UNINIT;
  145. mutex_unlock(&me->lock);
  146. /* kernel driver needs clean all dsp sessions */
  147. }
  148. static int cvp_dsp_rpmsg_callback(struct rpmsg_device *rpdev,
  149. void *data, int len, void *priv, u32 addr)
  150. {
  151. struct cvp_dsp_rsp_msg *rsp = (struct cvp_dsp_rsp_msg *)data;
  152. struct cvp_dsp_apps *me = &gfa_cv;
  153. dprintk(CVP_DSP, "%s: type = 0x%x ret = 0x%x len = 0x%x\n",
  154. __func__, rsp->type, rsp->ret, len);
  155. if (rsp->type < CPU2DSP_MAX_CMD && len == sizeof(*rsp)) {
  156. if (me->pending_dsp2cpu_rsp.type == rsp->type) {
  157. memcpy(&me->pending_dsp2cpu_rsp, rsp,
  158. sizeof(struct cvp_dsp_rsp_msg));
  159. complete(&me->completions[rsp->type]);
  160. } else {
  161. dprintk(CVP_ERR, "%s: CPU2DSP resp %d, pending %d\n",
  162. __func__, rsp->type,
  163. me->pending_dsp2cpu_rsp.type);
  164. goto exit;
  165. }
  166. } else if (rsp->type < CVP_DSP_MAX_CMD &&
  167. len == sizeof(struct cvp_dsp2cpu_cmd_msg)) {
  168. if (me->pending_dsp2cpu_cmd.type != CVP_INVALID_RPMSG_TYPE) {
  169. dprintk(CVP_ERR, "%s: DSP2CPU cmd:%d pending %d\n",
  170. __func__, rsp->type,
  171. me->pending_dsp2cpu_cmd.type);
  172. goto exit;
  173. }
  174. memcpy(&me->pending_dsp2cpu_cmd, rsp,
  175. sizeof(struct cvp_dsp2cpu_cmd_msg));
  176. complete(&me->completions[CPU2DSP_MAX_CMD]);
  177. } else {
  178. dprintk(CVP_ERR, "%s: Invalid type: %d\n", __func__, rsp->type);
  179. return 0;
  180. }
  181. return 0;
  182. exit:
  183. dprintk(CVP_ERR, "concurrent dsp cmd type = %d, rsp type = %d\n",
  184. me->pending_dsp2cpu_cmd.type,
  185. me->pending_dsp2cpu_rsp.type);
  186. return 0;
  187. }
  188. int cvp_dsp_suspend(uint32_t session_flag)
  189. {
  190. int rc = 0;
  191. struct cvp_dsp_cmd_msg cmd;
  192. struct cvp_dsp_apps *me = &gfa_cv;
  193. cmd.type = CPU2DSP_SUSPEND;
  194. mutex_lock(&me->lock);
  195. if (me->state != DSP_READY)
  196. goto exit;
  197. /* Use cvp_dsp_send_cmd_sync after dsp driver is ready */
  198. rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
  199. if (rc) {
  200. dprintk(CVP_ERR,
  201. "%s: cvp_dsp_send_cmd failed rc = %d\n",
  202. __func__, rc);
  203. goto exit;
  204. }
  205. me->state = DSP_SUSPEND;
  206. exit:
  207. mutex_unlock(&me->lock);
  208. return rc;
  209. }
  210. int cvp_dsp_resume(uint32_t session_flag)
  211. {
  212. int rc = 0;
  213. struct cvp_dsp_cmd_msg cmd;
  214. struct cvp_dsp_apps *me = &gfa_cv;
  215. cmd.type = CPU2DSP_RESUME;
  216. mutex_lock(&me->lock);
  217. if (me->state != DSP_SUSPEND)
  218. goto exit;
  219. /* Use cvp_dsp_send_cmd_sync after dsp driver is ready */
  220. rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
  221. if (rc) {
  222. dprintk(CVP_ERR,
  223. "%s: cvp_dsp_send_cmd failed rc = %d\n",
  224. __func__, rc);
  225. goto exit;
  226. }
  227. me->state = DSP_READY;
  228. exit:
  229. mutex_unlock(&me->lock);
  230. return rc;
  231. }
  232. int cvp_dsp_shutdown(uint32_t session_flag)
  233. {
  234. struct cvp_dsp_apps *me = &gfa_cv;
  235. int rc = 0;
  236. struct cvp_dsp_cmd_msg cmd;
  237. cmd.type = CPU2DSP_SHUTDOWN;
  238. mutex_lock(&me->lock);
  239. if (me->state == DSP_INVALID)
  240. goto exit;
  241. me->state = DSP_INACTIVE;
  242. rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
  243. if (rc) {
  244. dprintk(CVP_ERR,
  245. "%s: cvp_dsp_send_cmd failed with rc = %d\n",
  246. __func__, rc);
  247. cvp_hyp_assign_from_dsp();
  248. goto exit;
  249. }
  250. rc = cvp_hyp_assign_from_dsp();
  251. exit:
  252. mutex_unlock(&me->lock);
  253. return rc;
  254. }
  255. int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd,
  256. uint32_t buff_fd_size, uint32_t buff_size,
  257. uint32_t buff_offset, uint32_t buff_index,
  258. uint32_t buff_fd_iova)
  259. {
  260. struct cvp_dsp_cmd_msg cmd;
  261. int rc;
  262. struct cvp_dsp_apps *me = &gfa_cv;
  263. cmd.type = CPU2DSP_REGISTER_BUFFER;
  264. cmd.session_id = session_id;
  265. cmd.buff_fd = buff_fd;
  266. cmd.buff_fd_size = buff_fd_size;
  267. cmd.buff_size = buff_size;
  268. cmd.buff_offset = buff_offset;
  269. cmd.buff_index = buff_index;
  270. cmd.buff_fd_iova = buff_fd_iova;
  271. dprintk(CVP_DSP,
  272. "%s: type=0x%x, buff_fd_iova=0x%x buff_index=0x%x\n",
  273. __func__, cmd.type, buff_fd_iova,
  274. cmd.buff_index);
  275. dprintk(CVP_DSP, "%s: buff_size=0x%x session_id=0x%x\n",
  276. __func__, cmd.buff_size, cmd.session_id);
  277. mutex_lock(&me->lock);
  278. rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
  279. if (rc) {
  280. dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc);
  281. goto exit;
  282. }
  283. exit:
  284. mutex_unlock(&me->lock);
  285. return rc;
  286. }
  287. int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd,
  288. uint32_t buff_fd_size, uint32_t buff_size,
  289. uint32_t buff_offset, uint32_t buff_index,
  290. uint32_t buff_fd_iova)
  291. {
  292. struct cvp_dsp_cmd_msg cmd;
  293. int rc;
  294. struct cvp_dsp_apps *me = &gfa_cv;
  295. cmd.type = CPU2DSP_DEREGISTER_BUFFER;
  296. cmd.session_id = session_id;
  297. cmd.buff_fd = buff_fd;
  298. cmd.buff_fd_size = buff_fd_size;
  299. cmd.buff_size = buff_size;
  300. cmd.buff_offset = buff_offset;
  301. cmd.buff_index = buff_index;
  302. cmd.buff_fd_iova = buff_fd_iova;
  303. dprintk(CVP_DSP,
  304. "%s: type=0x%x, buff_fd_iova=0x%x buff_index=0x%x\n",
  305. __func__, cmd.type, buff_fd_iova,
  306. cmd.buff_index);
  307. dprintk(CVP_DSP, "%s: buff_size=0x%x session_id=0x%x\n",
  308. __func__, cmd.buff_size, cmd.session_id);
  309. mutex_lock(&me->lock);
  310. rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
  311. if (rc) {
  312. dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc);
  313. goto exit;
  314. }
  315. exit:
  316. mutex_unlock(&me->lock);
  317. return rc;
  318. }
  319. static const struct rpmsg_device_id cvp_dsp_rpmsg_match[] = {
  320. { CVP_APPS_DSP_GLINK_GUID },
  321. { },
  322. };
  323. static struct rpmsg_driver cvp_dsp_rpmsg_client = {
  324. .id_table = cvp_dsp_rpmsg_match,
  325. .probe = cvp_dsp_rpmsg_probe,
  326. .remove = cvp_dsp_rpmsg_remove,
  327. .callback = cvp_dsp_rpmsg_callback,
  328. .drv = {
  329. .name = "qcom,msm_cvp_dsp_rpmsg",
  330. },
  331. };
  332. void cvp_dsp_send_hfi_queue(void)
  333. {
  334. struct msm_cvp_core *core;
  335. struct iris_hfi_device *device;
  336. struct cvp_dsp_apps *me = &gfa_cv;
  337. uint64_t addr;
  338. uint32_t size;
  339. int rc;
  340. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  341. if (core && core->device)
  342. device = core->device->hfi_device_data;
  343. else
  344. return;
  345. if (!device) {
  346. dprintk(CVP_ERR, "%s: NULL device\n", __func__);
  347. return;
  348. }
  349. dprintk(CVP_DSP, "Entering %s\n", __func__);
  350. mutex_lock(&device->lock);
  351. mutex_lock(&me->lock);
  352. addr = (uint64_t)device->dsp_iface_q_table.mem_data.dma_handle;
  353. size = device->dsp_iface_q_table.mem_data.size;
  354. if (!addr || !size) {
  355. dprintk(CVP_DSP, "%s: HFI queue is not ready\n", __func__);
  356. goto exit;
  357. }
  358. if (me->state != DSP_PROBED && me->state != DSP_INACTIVE)
  359. goto exit;
  360. rc = cvp_hyp_assign_to_dsp(addr, size);
  361. if (rc) {
  362. dprintk(CVP_ERR, "%s: cvp_hyp_assign_to_dsp. rc=%d\n",
  363. __func__, rc);
  364. goto exit;
  365. }
  366. rc = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)addr, size);
  367. if (rc) {
  368. dprintk(CVP_WARN, "%s: Send HFI Queue failed rc = %d\n",
  369. __func__, rc);
  370. goto exit;
  371. }
  372. dprintk(CVP_DSP, "%s: dsp initialized\n", __func__);
  373. me->state = DSP_READY;
  374. exit:
  375. mutex_unlock(&me->lock);
  376. mutex_unlock(&device->lock);
  377. }
  378. static int cvp_dsp_thread(void *data)
  379. {
  380. int rc = 0, old_state;
  381. struct cvp_dsp_apps *me = &gfa_cv;
  382. struct cvp_dsp_cmd_msg cmd;
  383. struct cvp_hfi_device *hdev;
  384. struct msm_cvp_core *core;
  385. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  386. if (!core) {
  387. dprintk(CVP_ERR, "%s: Failed to find core\n", __func__);
  388. rc = -EINVAL;
  389. goto exit;
  390. }
  391. hdev = (struct cvp_hfi_device *)core->device;
  392. if (!hdev) {
  393. dprintk(CVP_ERR, "%s Invalid device handle\n", __func__);
  394. rc = -EINVAL;
  395. goto exit;
  396. }
  397. wait_dsp:
  398. rc = wait_for_completion_interruptible(
  399. &me->completions[CPU2DSP_MAX_CMD]);
  400. if (me->state == DSP_INVALID)
  401. goto exit;
  402. if (me->state == DSP_UNINIT)
  403. goto wait_dsp;
  404. if (me->state == DSP_PROBED) {
  405. cvp_dsp_send_hfi_queue();
  406. goto wait_dsp;
  407. }
  408. cmd.type = me->pending_dsp2cpu_cmd.type;
  409. if (rc == -ERESTARTSYS) {
  410. dprintk(CVP_WARN, "%s received interrupt signal\n", __func__);
  411. } else {
  412. mutex_lock(&me->lock);
  413. switch (me->pending_dsp2cpu_cmd.type) {
  414. case DSP2CPU_POWERON:
  415. {
  416. if (me->state == DSP_READY)
  417. break;
  418. mutex_unlock(&me->lock);
  419. old_state = me->state;
  420. me->state = DSP_READY;
  421. rc = call_hfi_op(hdev, resume, hdev->hfi_device_data);
  422. if (rc) {
  423. dprintk(CVP_WARN, "%s Failed to resume cvp\n",
  424. __func__);
  425. mutex_lock(&me->lock);
  426. me->state = old_state;
  427. cmd.ret = 1;
  428. break;
  429. }
  430. mutex_lock(&me->lock);
  431. cmd.ret = 0;
  432. break;
  433. }
  434. case DSP2CPU_POWEROFF:
  435. {
  436. me->state = DSP_SUSPEND;
  437. cmd.ret = 0;
  438. break;
  439. }
  440. default:
  441. dprintk(CVP_ERR, "unrecognaized dsp cmds: %d\n",
  442. me->pending_dsp2cpu_cmd.type);
  443. break;
  444. }
  445. me->pending_dsp2cpu_cmd.type = CVP_INVALID_RPMSG_TYPE;
  446. mutex_unlock(&me->lock);
  447. }
  448. /* Responds to DSP */
  449. rc = cvp_dsp_send_cmd(&cmd, sizeof(struct cvp_dsp_cmd_msg));
  450. if (rc)
  451. dprintk(CVP_ERR,
  452. "%s: cvp_dsp_send_cmd failed rc = %d cmd type=%d\n",
  453. __func__, rc, cmd.type);
  454. goto wait_dsp;
  455. exit:
  456. dprintk(CVP_DBG, "dsp thread exit\n");
  457. do_exit(rc);
  458. }
  459. int cvp_dsp_device_init(void)
  460. {
  461. struct cvp_dsp_apps *me = &gfa_cv;
  462. char tname[16];
  463. int rc;
  464. int i;
  465. mutex_init(&me->lock);
  466. me->state = DSP_INVALID;
  467. me->hyp_assigned = false;
  468. for (i = 0; i <= CPU2DSP_MAX_CMD; i++)
  469. init_completion(&me->completions[i]);
  470. me->pending_dsp2cpu_cmd.type = CVP_INVALID_RPMSG_TYPE;
  471. me->pending_dsp2cpu_rsp.type = CVP_INVALID_RPMSG_TYPE;
  472. rc = register_rpmsg_driver(&cvp_dsp_rpmsg_client);
  473. if (rc) {
  474. dprintk(CVP_ERR,
  475. "%s : register_rpmsg_driver failed rc = %d\n",
  476. __func__, rc);
  477. goto register_bail;
  478. }
  479. snprintf(tname, sizeof(tname), "cvp-dsp-thread");
  480. me->state = DSP_UNINIT;
  481. me->dsp_thread = kthread_run(cvp_dsp_thread, me, tname);
  482. if (!me->dsp_thread) {
  483. dprintk(CVP_ERR, "%s create %s fail", __func__, tname);
  484. rc = -ECHILD;
  485. me->state = DSP_INVALID;
  486. goto register_bail;
  487. }
  488. return 0;
  489. register_bail:
  490. return rc;
  491. }
  492. void cvp_dsp_device_exit(void)
  493. {
  494. struct cvp_dsp_apps *me = &gfa_cv;
  495. int i;
  496. mutex_lock(&me->lock);
  497. me->state = DSP_INVALID;
  498. mutex_unlock(&me->lock);
  499. for (i = 0; i <= CPU2DSP_MAX_CMD; i++)
  500. complete_all(&me->completions[i]);
  501. mutex_destroy(&me->lock);
  502. unregister_rpmsg_driver(&cvp_dsp_rpmsg_client);
  503. }