hfi_response_handler.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/bitops.h>
  6. #include <linux/slab.h>
  7. #include <linux/list.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/hash.h>
  10. #include <linux/soc/qcom/smem.h>
  11. #include "cvp_hfi_helper.h"
  12. #include "cvp_hfi_io.h"
  13. #include "msm_cvp_debug.h"
  14. #include "cvp_hfi.h"
  15. #include "msm_cvp_common.h"
  16. extern struct msm_cvp_drv *cvp_driver;
  17. static enum cvp_status hfi_map_err_status(u32 hfi_err)
  18. {
  19. enum cvp_status cvp_err;
  20. switch (hfi_err) {
  21. case HFI_ERR_NONE:
  22. cvp_err = CVP_ERR_NONE;
  23. break;
  24. case HFI_ERR_SYS_FATAL:
  25. cvp_err = CVP_ERR_HW_FATAL;
  26. break;
  27. case HFI_ERR_SYS_NOC_ERROR:
  28. cvp_err = CVP_ERR_NOC_ERROR;
  29. break;
  30. case HFI_ERR_SYS_VERSION_MISMATCH:
  31. case HFI_ERR_SYS_INVALID_PARAMETER:
  32. case HFI_ERR_SYS_SESSION_ID_OUT_OF_RANGE:
  33. case HFI_ERR_SESSION_INVALID_PARAMETER:
  34. case HFI_ERR_SESSION_INVALID_SESSION_ID:
  35. case HFI_ERR_SESSION_INVALID_STREAM_ID:
  36. cvp_err = CVP_ERR_BAD_PARAM;
  37. break;
  38. case HFI_ERR_SYS_INSUFFICIENT_RESOURCES:
  39. case HFI_ERR_SYS_UNSUPPORTED_DOMAIN:
  40. case HFI_ERR_SYS_UNSUPPORTED_CODEC:
  41. case HFI_ERR_SESSION_UNSUPPORTED_PROPERTY:
  42. case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
  43. case HFI_ERR_SESSION_INSUFFICIENT_RESOURCES:
  44. case HFI_ERR_SESSION_UNSUPPORTED_STREAM:
  45. cvp_err = CVP_ERR_NOT_SUPPORTED;
  46. break;
  47. case HFI_ERR_SYS_MAX_SESSIONS_REACHED:
  48. cvp_err = CVP_ERR_MAX_CLIENTS;
  49. break;
  50. case HFI_ERR_SYS_SESSION_IN_USE:
  51. cvp_err = CVP_ERR_CLIENT_PRESENT;
  52. break;
  53. case HFI_ERR_SESSION_FATAL:
  54. cvp_err = CVP_ERR_CLIENT_FATAL;
  55. break;
  56. case HFI_ERR_SESSION_BAD_POINTER:
  57. cvp_err = CVP_ERR_BAD_PARAM;
  58. break;
  59. case HFI_ERR_SESSION_INCORRECT_STATE_OPERATION:
  60. cvp_err = CVP_ERR_BAD_STATE;
  61. break;
  62. default:
  63. cvp_err = CVP_ERR_FAIL;
  64. break;
  65. }
  66. return cvp_err;
  67. }
  68. static int hfi_process_sys_error(u32 device_id,
  69. struct cvp_hfi_msg_event_notify_packet *pkt,
  70. struct msm_cvp_cb_info *info)
  71. {
  72. struct msm_cvp_cb_cmd_done cmd_done = {0};
  73. cmd_done.device_id = device_id;
  74. cmd_done.status = hfi_map_err_status(pkt->event_data1);
  75. info->response_type = HAL_SYS_ERROR;
  76. info->response.cmd = cmd_done;
  77. return 0;
  78. }
  79. static int hfi_process_session_error(u32 device_id,
  80. struct cvp_hfi_msg_event_notify_packet *pkt,
  81. struct msm_cvp_cb_info *info)
  82. {
  83. struct msm_cvp_cb_cmd_done cmd_done = {0};
  84. cmd_done.device_id = device_id;
  85. cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
  86. cmd_done.status = hfi_map_err_status(pkt->event_data1);
  87. info->response.cmd = cmd_done;
  88. dprintk(CVP_INFO, "Received: SESSION_ERROR with event id : %#x %#x\n",
  89. pkt->event_data1, pkt->event_data2);
  90. switch (pkt->event_data1) {
  91. /* Ignore below errors */
  92. case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
  93. case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
  94. dprintk(CVP_INFO, "Non Fatal: HFI_EVENT_SESSION_ERROR\n");
  95. info->response_type = HAL_RESPONSE_UNUSED;
  96. break;
  97. default:
  98. dprintk(CVP_ERR,
  99. "%s: session %x data1 %#x, data2 %#x\n", __func__,
  100. pkt->session_id, pkt->event_data1, pkt->event_data2);
  101. info->response_type = HAL_RESPONSE_UNUSED;
  102. break;
  103. }
  104. return 0;
  105. }
  106. static int hfi_process_event_notify(u32 device_id,
  107. void *hdr, struct msm_cvp_cb_info *info)
  108. {
  109. struct cvp_hfi_msg_event_notify_packet *pkt =
  110. (struct cvp_hfi_msg_event_notify_packet *)hdr;
  111. dprintk(CVP_HFI, "Received: EVENT_NOTIFY\n");
  112. if (pkt->size < sizeof(struct cvp_hfi_msg_event_notify_packet)) {
  113. dprintk(CVP_ERR, "Invalid Params\n");
  114. return -E2BIG;
  115. }
  116. switch (pkt->event_id) {
  117. case HFI_EVENT_SYS_ERROR:
  118. dprintk(CVP_ERR, "HFI_EVENT_SYS_ERROR: %d, %#x\n",
  119. pkt->event_data1, pkt->event_data2);
  120. return hfi_process_sys_error(device_id, pkt, info);
  121. case HFI_EVENT_SESSION_ERROR:
  122. dprintk(CVP_INFO, "HFI_EVENT_SESSION_ERROR[%#x]\n",
  123. pkt->session_id);
  124. return hfi_process_session_error(device_id, pkt, info);
  125. default:
  126. *info = (struct msm_cvp_cb_info) {
  127. .response_type = HAL_RESPONSE_UNUSED,
  128. };
  129. return 0;
  130. }
  131. }
  132. static int hfi_process_sys_init_done(u32 device_id,
  133. void *hdr, struct msm_cvp_cb_info *info)
  134. {
  135. struct cvp_hfi_msg_sys_init_done_packet *pkt =
  136. (struct cvp_hfi_msg_sys_init_done_packet *)hdr;
  137. struct msm_cvp_cb_cmd_done cmd_done = {0};
  138. enum cvp_status status = CVP_ERR_NONE;
  139. dprintk(CVP_CORE, "RECEIVED: SYS_INIT_DONE\n");
  140. if (sizeof(struct cvp_hfi_msg_sys_init_done_packet) > pkt->size) {
  141. dprintk(CVP_ERR, "%s: bad_pkt_size: %d\n", __func__,
  142. pkt->size);
  143. return -E2BIG;
  144. }
  145. if (!pkt->num_properties) {
  146. dprintk(CVP_CORE,
  147. "hal_process_sys_init_done: no_properties\n");
  148. goto err_no_prop;
  149. }
  150. status = hfi_map_err_status(pkt->error_type);
  151. if (status) {
  152. dprintk(CVP_ERR, "%s: status %#x\n",
  153. __func__, status);
  154. goto err_no_prop;
  155. }
  156. err_no_prop:
  157. cmd_done.device_id = device_id;
  158. cmd_done.session_id = NULL;
  159. cmd_done.status = (u32)status;
  160. cmd_done.size = sizeof(struct cvp_hal_sys_init_done);
  161. info->response_type = HAL_SYS_INIT_DONE;
  162. info->response.cmd = cmd_done;
  163. return 0;
  164. }
  165. enum cvp_status cvp_hfi_process_sys_init_done_prop_read(
  166. struct cvp_hfi_msg_sys_init_done_packet *pkt,
  167. struct cvp_hal_sys_init_done *sys_init_done)
  168. {
  169. enum cvp_status status = CVP_ERR_NONE;
  170. u32 rem_bytes, num_properties;
  171. u8 *data_ptr;
  172. if (!pkt || !sys_init_done) {
  173. dprintk(CVP_ERR,
  174. "hfi_msg_sys_init_done: Invalid input\n");
  175. return CVP_ERR_FAIL;
  176. }
  177. rem_bytes = pkt->size - sizeof(struct
  178. cvp_hfi_msg_sys_init_done_packet) + sizeof(u32);
  179. if (!rem_bytes) {
  180. dprintk(CVP_ERR,
  181. "hfi_msg_sys_init_done: missing_prop_info\n");
  182. return CVP_ERR_FAIL;
  183. }
  184. status = hfi_map_err_status(pkt->error_type);
  185. if (status) {
  186. dprintk(CVP_ERR, "%s: status %#x\n", __func__, status);
  187. return status;
  188. }
  189. data_ptr = (u8 *) &pkt->rg_property_data[0];
  190. num_properties = pkt->num_properties;
  191. dprintk(CVP_HFI,
  192. "%s: data_start %pK, num_properties %#x\n",
  193. __func__, data_ptr, num_properties);
  194. sys_init_done->capabilities = NULL;
  195. return status;
  196. }
  197. static int hfi_process_session_init_done(u32 device_id,
  198. void *hdr, struct msm_cvp_cb_info *info)
  199. {
  200. struct cvp_hfi_msg_sys_session_init_done_packet *pkt =
  201. (struct cvp_hfi_msg_sys_session_init_done_packet *)hdr;
  202. struct msm_cvp_cb_cmd_done cmd_done = {0};
  203. struct cvp_hal_session_init_done session_init_done = { {0} };
  204. dprintk(CVP_SESS, "RECEIVED: SESSION_INIT_DONE[%x]\n", pkt->session_id);
  205. if (sizeof(struct cvp_hfi_msg_sys_session_init_done_packet)
  206. > pkt->size) {
  207. dprintk(CVP_ERR,
  208. "hal_process_session_init_done: bad_pkt_size\n");
  209. return -E2BIG;
  210. }
  211. cmd_done.device_id = device_id;
  212. cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
  213. cmd_done.status = hfi_map_err_status(pkt->error_type);
  214. cmd_done.data.session_init_done = session_init_done;
  215. cmd_done.size = sizeof(struct cvp_hal_session_init_done);
  216. info->response_type = HAL_SESSION_INIT_DONE;
  217. info->response.cmd = cmd_done;
  218. return 0;
  219. }
  220. static int hfi_process_session_end_done(u32 device_id,
  221. void *hdr, struct msm_cvp_cb_info *info)
  222. {
  223. struct cvp_hfi_msg_sys_session_end_done_packet *pkt =
  224. (struct cvp_hfi_msg_sys_session_end_done_packet *)hdr;
  225. struct msm_cvp_cb_cmd_done cmd_done = {0};
  226. dprintk(CVP_SESS, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
  227. if (!pkt || pkt->size !=
  228. sizeof(struct cvp_hfi_msg_sys_session_end_done_packet)) {
  229. dprintk(CVP_ERR, "%s: bad packet/packet size\n", __func__);
  230. return -E2BIG;
  231. }
  232. cmd_done.device_id = device_id;
  233. cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
  234. cmd_done.status = hfi_map_err_status(pkt->error_type);
  235. cmd_done.size = 0;
  236. info->response_type = HAL_SESSION_END_DONE;
  237. info->response.cmd = cmd_done;
  238. return 0;
  239. }
  240. static int hfi_process_session_abort_done(u32 device_id,
  241. void *hdr, struct msm_cvp_cb_info *info)
  242. {
  243. struct cvp_hfi_msg_sys_session_abort_done_packet *pkt =
  244. (struct cvp_hfi_msg_sys_session_abort_done_packet *)hdr;
  245. struct msm_cvp_cb_cmd_done cmd_done = {0};
  246. dprintk(CVP_SESS, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
  247. pkt->session_id);
  248. if (!pkt || pkt->size !=
  249. sizeof(struct cvp_hfi_msg_sys_session_abort_done_packet)) {
  250. dprintk(CVP_ERR, "%s: bad packet/packet size: %d\n",
  251. __func__, pkt ? pkt->size : 0);
  252. return -E2BIG;
  253. }
  254. cmd_done.device_id = device_id;
  255. cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
  256. cmd_done.status = hfi_map_err_status(pkt->error_type);
  257. cmd_done.size = 0;
  258. info->response_type = HAL_SESSION_ABORT_DONE;
  259. info->response.cmd = cmd_done;
  260. return 0;
  261. }
  262. static int hfi_process_session_set_buf_done(u32 device_id,
  263. void *hdr, struct msm_cvp_cb_info *info)
  264. {
  265. struct cvp_hfi_msg_session_hdr *pkt =
  266. (struct cvp_hfi_msg_session_hdr *)hdr;
  267. struct msm_cvp_cb_cmd_done cmd_done = {0};
  268. unsigned int pkt_size = get_msg_size(pkt);
  269. if (!pkt || pkt->size < pkt_size) {
  270. dprintk(CVP_ERR, "bad packet/packet size %d\n",
  271. pkt ? pkt->size : 0);
  272. return -E2BIG;
  273. }
  274. dprintk(CVP_SESS, "RECEIVED:CVP_SET_BUFFER_DONE[%#x]\n",
  275. pkt->session_id);
  276. cmd_done.device_id = device_id;
  277. cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
  278. cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
  279. cmd_done.size = 0;
  280. info->response_type = HAL_SESSION_SET_BUFFER_DONE;
  281. info->response.cmd = cmd_done;
  282. return 0;
  283. }
  284. static int hfi_process_session_flush_done(u32 device_id,
  285. void *hdr, struct msm_cvp_cb_info *info)
  286. {
  287. struct cvp_hfi_msg_sys_session_flush_done_packet *pkt =
  288. (struct cvp_hfi_msg_sys_session_flush_done_packet *)hdr;
  289. struct msm_cvp_cb_cmd_done cmd_done = {0};
  290. dprintk(CVP_SESS, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n",
  291. pkt->session_id);
  292. if (!pkt || pkt->size <
  293. sizeof(struct cvp_hfi_msg_sys_session_flush_done_packet)) {
  294. dprintk(CVP_ERR, "%s: bad packet/packet size: %d\n",
  295. __func__, pkt ? pkt->size : 0);
  296. return -E2BIG;
  297. }
  298. cmd_done.device_id = device_id;
  299. cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
  300. cmd_done.status = hfi_map_err_status(pkt->error_type);
  301. cmd_done.size = 0;
  302. info->response_type = HAL_SESSION_FLUSH_DONE;
  303. info->response.cmd = cmd_done;
  304. return 0;
  305. }
  306. static int hfi_process_session_rel_buf_done(u32 device_id,
  307. void *hdr, struct msm_cvp_cb_info *info)
  308. {
  309. struct cvp_hfi_msg_session_hdr *pkt =
  310. (struct cvp_hfi_msg_session_hdr *)hdr;
  311. struct msm_cvp_cb_cmd_done cmd_done = {0};
  312. unsigned int pkt_size = get_msg_size(pkt);
  313. if (!pkt || pkt->size < pkt_size) {
  314. dprintk(CVP_ERR, "bad packet/packet size %d\n",
  315. pkt ? pkt->size : 0);
  316. return -E2BIG;
  317. }
  318. dprintk(CVP_SESS, "RECEIVED:CVP_RELEASE_BUFFER_DONE[%#x]\n",
  319. pkt->session_id);
  320. cmd_done.device_id = device_id;
  321. cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
  322. cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
  323. cmd_done.size = 0;
  324. info->response_type = HAL_SESSION_RELEASE_BUFFER_DONE;
  325. info->response.cmd = cmd_done;
  326. return 0;
  327. }
  328. static int hfi_process_session_cvp_operation_config(u32 device_id,
  329. void *hdr, struct msm_cvp_cb_info *info)
  330. {
  331. struct cvp_hfi_msg_session_op_cfg_packet *pkt =
  332. (struct cvp_hfi_msg_session_op_cfg_packet *)hdr;
  333. struct cvp_hfi_msg_session_hdr *lhdr =
  334. (struct cvp_hfi_msg_session_hdr *)hdr;
  335. struct msm_cvp_cb_cmd_done cmd_done = {0};
  336. int signal;
  337. unsigned int conf_id, session_id, error_type;
  338. if (!pkt) {
  339. dprintk(CVP_ERR, "%s: invalid param\n", __func__);
  340. return -EINVAL;
  341. } else if (pkt->size < get_msg_size(lhdr)) {
  342. dprintk(CVP_ERR,
  343. "%s: bad_pkt_size\n", __func__);
  344. return -E2BIG;
  345. }
  346. get_msg_opconfigs(pkt, &session_id, &error_type, &conf_id);
  347. cmd_done.device_id = device_id;
  348. cmd_done.session_id = (void *)(uintptr_t)session_id;
  349. cmd_done.status = hfi_map_err_status(error_type);
  350. cmd_done.size = 0;
  351. dprintk(CVP_HFI,
  352. "%s: device_id=%d status=%d, sessionid=%pK config=%x\n",
  353. __func__, device_id, cmd_done.status,
  354. cmd_done.session_id, pkt->op_conf_id);
  355. if (pkt->packet_type == HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS)
  356. signal = get_signal_from_pkt_type(
  357. HFI_CMD_SESSION_CVP_SET_PERSIST_BUFFERS);
  358. else if (pkt->packet_type ==
  359. HFI_MSG_SESSION_CVP_RELEASE_PERSIST_BUFFERS)
  360. signal = get_signal_from_pkt_type(
  361. HFI_CMD_SESSION_CVP_RELEASE_PERSIST_BUFFERS);
  362. else if (pkt->packet_type == HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS)
  363. signal = get_signal_from_pkt_type(
  364. HFI_CMD_SESSION_CVP_SET_MODEL_BUFFERS);
  365. else if (pkt->packet_type == HFI_MSG_SESSION_CVP_DMM_PARAMS)
  366. signal = get_signal_from_pkt_type(
  367. HFI_CMD_SESSION_CVP_DMM_PARAMS);
  368. else if (pkt->packet_type == HFI_MSG_SESSION_CVP_WARP_DS_PARAMS)
  369. signal = get_signal_from_pkt_type(
  370. HFI_CMD_SESSION_CVP_WARP_DS_PARAMS);
  371. else
  372. signal = get_signal_from_pkt_type(conf_id);
  373. if (signal < 0) {
  374. dprintk(CVP_ERR, "%s Invalid op config id\n", __func__);
  375. return -EINVAL;
  376. }
  377. info->response_type = signal;
  378. info->response.cmd = cmd_done;
  379. return 0;
  380. }
  381. static struct msm_cvp_inst *cvp_get_inst_from_id(struct msm_cvp_core *core,
  382. unsigned int session_id)
  383. {
  384. struct msm_cvp_inst *inst = NULL;
  385. bool match = false;
  386. int count = 0;
  387. if (!core || !session_id)
  388. return NULL;
  389. retry:
  390. if (mutex_trylock(&core->lock)) {
  391. list_for_each_entry(inst, &core->instances, list) {
  392. if (hash32_ptr(inst->session) == session_id) {
  393. match = true;
  394. break;
  395. }
  396. }
  397. inst = match ? inst : NULL;
  398. mutex_unlock(&core->lock);
  399. } else {
  400. if (core->state == CVP_CORE_UNINIT)
  401. return NULL;
  402. usleep_range(100, 200);
  403. count++;
  404. if (count < 1000)
  405. goto retry;
  406. else
  407. dprintk(CVP_ERR, "timeout locking core mutex\n");
  408. }
  409. return inst;
  410. }
  411. static int hfi_process_session_cvp_msg(u32 device_id,
  412. void *hdr, struct msm_cvp_cb_info *info)
  413. {
  414. struct cvp_hfi_msg_session_hdr *pkt =
  415. (struct cvp_hfi_msg_session_hdr *)hdr;
  416. struct cvp_session_msg *sess_msg;
  417. struct msm_cvp_inst *inst = NULL;
  418. struct msm_cvp_core *core;
  419. unsigned int session_id;
  420. struct cvp_session_queue *sq;
  421. if (!pkt) {
  422. dprintk(CVP_ERR, "%s: invalid param\n", __func__);
  423. return -EINVAL;
  424. } else if (pkt->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int)) {
  425. dprintk(CVP_ERR, "%s: bad_pkt_size %d\n", __func__, pkt->size);
  426. return -E2BIG;
  427. }
  428. session_id = get_msg_session_id(pkt);
  429. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  430. inst = cvp_get_inst_from_id(core, session_id);
  431. if (!inst) {
  432. dprintk(CVP_ERR, "%s: invalid session\n", __func__);
  433. return -EINVAL;
  434. }
  435. if (pkt->client_data.kdata & FENCE_BIT)
  436. sq = &inst->session_queue_fence;
  437. else
  438. sq = &inst->session_queue;
  439. sess_msg = kmem_cache_alloc(cvp_driver->msg_cache, GFP_KERNEL);
  440. if (sess_msg == NULL) {
  441. dprintk(CVP_ERR, "%s runs out msg cache memory\n", __func__);
  442. return -ENOMEM;
  443. }
  444. memcpy(&sess_msg->pkt, pkt, get_msg_size(pkt));
  445. dprintk(CVP_HFI,
  446. "%s: Received msg %x cmd_done.status=%d sessionid=%x\n",
  447. __func__, pkt->packet_type,
  448. hfi_map_err_status(get_msg_errorcode(pkt)), session_id);
  449. spin_lock(&sq->lock);
  450. if (sq->msg_count >= MAX_NUM_MSGS_PER_SESSION) {
  451. dprintk(CVP_ERR, "Reached session queue size limit\n");
  452. goto error_handle_msg;
  453. }
  454. list_add_tail(&sess_msg->node, &sq->msgs);
  455. sq->msg_count++;
  456. spin_unlock(&sq->lock);
  457. wake_up_all(&sq->wq);
  458. info->response_type = HAL_NO_RESP;
  459. return 0;
  460. error_handle_msg:
  461. spin_unlock(&sq->lock);
  462. kmem_cache_free(cvp_driver->msg_cache, sess_msg);
  463. return -ENOMEM;
  464. }
  465. static void hfi_process_sys_get_prop_image_version(
  466. struct cvp_hfi_msg_sys_property_info_packet *pkt)
  467. {
  468. int i = 0;
  469. const u32 version_string_size = 128;
  470. u8 *str_image_version;
  471. int req_bytes;
  472. req_bytes = pkt->size - sizeof(*pkt);
  473. if (req_bytes < version_string_size ||
  474. !pkt->rg_property_data[1] ||
  475. pkt->num_properties > 1) {
  476. dprintk(CVP_ERR, "%s: bad_pkt: %d\n", __func__, req_bytes);
  477. return;
  478. }
  479. str_image_version = (u8 *)&pkt->rg_property_data[1];
  480. /*
  481. * The version string returned by firmware includes null
  482. * characters at the start and in between. Replace the null
  483. * characters with space, to print the version info.
  484. */
  485. for (i = 0; i < version_string_size; i++) {
  486. if (str_image_version[i] != '\0')
  487. cvp_driver->fw_version[i] = str_image_version[i];
  488. else
  489. cvp_driver->fw_version[i] = ' ';
  490. }
  491. cvp_driver->fw_version[i - 1] = '\0';
  492. dprintk(CVP_HFI, "F/W version: %s\n", cvp_driver->fw_version);
  493. }
  494. static int hfi_process_sys_property_info(u32 device_id,
  495. void *hdr, struct msm_cvp_cb_info *info)
  496. {
  497. struct cvp_hfi_msg_sys_property_info_packet *pkt =
  498. (struct cvp_hfi_msg_sys_property_info_packet *)hdr;
  499. if (!pkt) {
  500. dprintk(CVP_ERR, "%s: invalid param\n", __func__);
  501. return -EINVAL;
  502. } else if (pkt->size > sizeof(*pkt)) {
  503. dprintk(CVP_ERR,
  504. "%s: bad_pkt_size %d\n", __func__, pkt->size);
  505. return -E2BIG;
  506. } else if (!pkt->num_properties) {
  507. dprintk(CVP_WARN,
  508. "%s: no_properties\n", __func__);
  509. return -EINVAL;
  510. }
  511. switch (pkt->rg_property_data[0]) {
  512. case HFI_PROPERTY_SYS_IMAGE_VERSION:
  513. hfi_process_sys_get_prop_image_version(pkt);
  514. *info = (struct msm_cvp_cb_info) {
  515. .response_type = HAL_RESPONSE_UNUSED,
  516. };
  517. return 0;
  518. default:
  519. dprintk(CVP_WARN,
  520. "%s: unknown_prop_id: %x\n",
  521. __func__, pkt->rg_property_data[0]);
  522. return -ENOTSUPP;
  523. }
  524. }
  525. int cvp_hfi_process_msg_packet(u32 device_id, void *hdr,
  526. struct msm_cvp_cb_info *info)
  527. {
  528. typedef int (*pkt_func_def)(u32, void *, struct msm_cvp_cb_info *info);
  529. pkt_func_def pkt_func = NULL;
  530. struct cvp_hal_msg_pkt_hdr *msg_hdr = (struct cvp_hal_msg_pkt_hdr *)hdr;
  531. if (!info || !msg_hdr || msg_hdr->size < CVP_IFACEQ_MIN_PKT_SIZE) {
  532. dprintk(CVP_ERR, "%s: bad packet/packet size\n",
  533. __func__);
  534. return -EINVAL;
  535. }
  536. dprintk(CVP_HFI, "Received HFI MSG with type %#x\n", msg_hdr->packet);
  537. switch (msg_hdr->packet) {
  538. case HFI_MSG_EVENT_NOTIFY:
  539. pkt_func = (pkt_func_def)hfi_process_event_notify;
  540. break;
  541. case HFI_MSG_SYS_INIT_DONE:
  542. pkt_func = (pkt_func_def)hfi_process_sys_init_done;
  543. break;
  544. case HFI_MSG_SYS_SESSION_INIT_DONE:
  545. pkt_func = (pkt_func_def)hfi_process_session_init_done;
  546. break;
  547. case HFI_MSG_SYS_PROPERTY_INFO:
  548. pkt_func = (pkt_func_def)hfi_process_sys_property_info;
  549. break;
  550. case HFI_MSG_SYS_SESSION_END_DONE:
  551. pkt_func = (pkt_func_def)hfi_process_session_end_done;
  552. break;
  553. case HFI_MSG_SESSION_CVP_SET_BUFFERS:
  554. pkt_func = (pkt_func_def) hfi_process_session_set_buf_done;
  555. break;
  556. case HFI_MSG_SESSION_CVP_RELEASE_BUFFERS:
  557. pkt_func = (pkt_func_def)hfi_process_session_rel_buf_done;
  558. break;
  559. case HFI_MSG_SYS_SESSION_ABORT_DONE:
  560. pkt_func = (pkt_func_def)hfi_process_session_abort_done;
  561. break;
  562. case HFI_MSG_SESSION_CVP_FLUSH:
  563. pkt_func = (pkt_func_def)hfi_process_session_flush_done;
  564. break;
  565. case HFI_MSG_SESSION_CVP_OPERATION_CONFIG:
  566. case HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS:
  567. case HFI_MSG_SESSION_CVP_RELEASE_PERSIST_BUFFERS:
  568. case HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS:
  569. case HFI_MSG_SESSION_CVP_DMM_PARAMS:
  570. case HFI_MSG_SESSION_CVP_WARP_DS_PARAMS:
  571. pkt_func =
  572. (pkt_func_def)hfi_process_session_cvp_operation_config;
  573. break;
  574. case HFI_MSG_SESSION_CVP_DS:
  575. case HFI_MSG_SESSION_CVP_DFS:
  576. case HFI_MSG_SESSION_CVP_DMM:
  577. case HFI_MSG_SESSION_CVP_WARP:
  578. case HFI_MSG_SESSION_CVP_WARP_NCC:
  579. case HFI_MSG_SESSION_CVP_FD:
  580. case HFI_MSG_SESSION_CVP_SGM_OF:
  581. pkt_func = (pkt_func_def)hfi_process_session_cvp_msg;
  582. break;
  583. default:
  584. dprintk(CVP_HFI, "Use default msg handler: %#x\n",
  585. msg_hdr->packet);
  586. pkt_func = (pkt_func_def)hfi_process_session_cvp_msg;
  587. break;
  588. }
  589. return pkt_func ?
  590. pkt_func(device_id, hdr, info) : -ENOTSUPP;
  591. }