hfi_response_handler.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  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 struct msm_cvp_inst *cvp_get_inst_from_id(struct msm_cvp_core *core,
  329. unsigned int session_id)
  330. {
  331. struct msm_cvp_inst *inst = NULL;
  332. bool match = false;
  333. int count = 0;
  334. if (!core || !session_id)
  335. return NULL;
  336. retry:
  337. if (mutex_trylock(&core->lock)) {
  338. list_for_each_entry(inst, &core->instances, list) {
  339. if (hash32_ptr(inst->session) == session_id) {
  340. match = true;
  341. break;
  342. }
  343. }
  344. inst = match ? inst : NULL;
  345. mutex_unlock(&core->lock);
  346. } else {
  347. if (core->state == CVP_CORE_UNINIT)
  348. return NULL;
  349. usleep_range(100, 200);
  350. count++;
  351. if (count < 1000)
  352. goto retry;
  353. else
  354. dprintk(CVP_ERR, "timeout locking core mutex\n");
  355. }
  356. return inst;
  357. }
  358. static int hfi_process_session_cvp_msg(u32 device_id,
  359. void *hdr, struct msm_cvp_cb_info *info)
  360. {
  361. struct cvp_hfi_msg_session_hdr *pkt =
  362. (struct cvp_hfi_msg_session_hdr *)hdr;
  363. struct cvp_session_msg *sess_msg;
  364. struct msm_cvp_inst *inst = NULL;
  365. struct msm_cvp_core *core;
  366. unsigned int session_id;
  367. struct cvp_session_queue *sq;
  368. if (!pkt) {
  369. dprintk(CVP_ERR, "%s: invalid param\n", __func__);
  370. return -EINVAL;
  371. } else if (pkt->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int)) {
  372. dprintk(CVP_ERR, "%s: bad_pkt_size %d\n", __func__, pkt->size);
  373. return -E2BIG;
  374. }
  375. session_id = get_msg_session_id(pkt);
  376. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  377. inst = cvp_get_inst_from_id(core, session_id);
  378. if (!inst) {
  379. dprintk(CVP_ERR, "%s: invalid session\n", __func__);
  380. return -EINVAL;
  381. }
  382. if (pkt->client_data.kdata & FENCE_BIT)
  383. sq = &inst->session_queue_fence;
  384. else
  385. sq = &inst->session_queue;
  386. sess_msg = kmem_cache_alloc(cvp_driver->msg_cache, GFP_KERNEL);
  387. if (sess_msg == NULL) {
  388. dprintk(CVP_ERR, "%s runs out msg cache memory\n", __func__);
  389. return -ENOMEM;
  390. }
  391. memcpy(&sess_msg->pkt, pkt, get_msg_size(pkt));
  392. dprintk(CVP_HFI,
  393. "%s: Received msg %x cmd_done.status=%d sessionid=%x\n",
  394. __func__, pkt->packet_type,
  395. hfi_map_err_status(get_msg_errorcode(pkt)), session_id);
  396. spin_lock(&sq->lock);
  397. if (sq->msg_count >= MAX_NUM_MSGS_PER_SESSION) {
  398. dprintk(CVP_ERR, "Reached session queue size limit\n");
  399. goto error_handle_msg;
  400. }
  401. list_add_tail(&sess_msg->node, &sq->msgs);
  402. sq->msg_count++;
  403. spin_unlock(&sq->lock);
  404. wake_up_all(&sq->wq);
  405. info->response_type = HAL_NO_RESP;
  406. return 0;
  407. error_handle_msg:
  408. spin_unlock(&sq->lock);
  409. kmem_cache_free(cvp_driver->msg_cache, sess_msg);
  410. return -ENOMEM;
  411. }
  412. static void hfi_process_sys_get_prop_image_version(
  413. struct cvp_hfi_msg_sys_property_info_packet *pkt)
  414. {
  415. int i = 0;
  416. const u32 version_string_size = 128;
  417. u8 *str_image_version;
  418. int req_bytes;
  419. req_bytes = pkt->size - sizeof(*pkt);
  420. if (req_bytes < version_string_size ||
  421. !pkt->rg_property_data[1] ||
  422. pkt->num_properties > 1) {
  423. dprintk(CVP_ERR, "%s: bad_pkt: %d\n", __func__, req_bytes);
  424. return;
  425. }
  426. str_image_version = (u8 *)&pkt->rg_property_data[1];
  427. /*
  428. * The version string returned by firmware includes null
  429. * characters at the start and in between. Replace the null
  430. * characters with space, to print the version info.
  431. */
  432. for (i = 0; i < version_string_size; i++) {
  433. if (str_image_version[i] != '\0')
  434. cvp_driver->fw_version[i] = str_image_version[i];
  435. else
  436. cvp_driver->fw_version[i] = ' ';
  437. }
  438. cvp_driver->fw_version[i - 1] = '\0';
  439. dprintk(CVP_HFI, "F/W version: %s\n", cvp_driver->fw_version);
  440. }
  441. static int hfi_process_sys_property_info(u32 device_id,
  442. void *hdr, struct msm_cvp_cb_info *info)
  443. {
  444. struct cvp_hfi_msg_sys_property_info_packet *pkt =
  445. (struct cvp_hfi_msg_sys_property_info_packet *)hdr;
  446. if (!pkt) {
  447. dprintk(CVP_ERR, "%s: invalid param\n", __func__);
  448. return -EINVAL;
  449. } else if (pkt->size > sizeof(*pkt)) {
  450. dprintk(CVP_ERR,
  451. "%s: bad_pkt_size %d\n", __func__, pkt->size);
  452. return -E2BIG;
  453. } else if (!pkt->num_properties) {
  454. dprintk(CVP_WARN,
  455. "%s: no_properties\n", __func__);
  456. return -EINVAL;
  457. }
  458. switch (pkt->rg_property_data[0]) {
  459. case HFI_PROPERTY_SYS_IMAGE_VERSION:
  460. hfi_process_sys_get_prop_image_version(pkt);
  461. *info = (struct msm_cvp_cb_info) {
  462. .response_type = HAL_RESPONSE_UNUSED,
  463. };
  464. return 0;
  465. default:
  466. dprintk(CVP_WARN,
  467. "%s: unknown_prop_id: %x\n",
  468. __func__, pkt->rg_property_data[0]);
  469. return -ENOTSUPP;
  470. }
  471. }
  472. int cvp_hfi_process_msg_packet(u32 device_id, void *hdr,
  473. struct msm_cvp_cb_info *info)
  474. {
  475. typedef int (*pkt_func_def)(u32, void *, struct msm_cvp_cb_info *info);
  476. pkt_func_def pkt_func = NULL;
  477. struct cvp_hal_msg_pkt_hdr *msg_hdr = (struct cvp_hal_msg_pkt_hdr *)hdr;
  478. if (!info || !msg_hdr || msg_hdr->size < CVP_IFACEQ_MIN_PKT_SIZE) {
  479. dprintk(CVP_ERR, "%s: bad packet/packet size\n",
  480. __func__);
  481. return -EINVAL;
  482. }
  483. dprintk(CVP_HFI, "Received HFI MSG with type %#x\n", msg_hdr->packet);
  484. switch (msg_hdr->packet) {
  485. case HFI_MSG_EVENT_NOTIFY:
  486. pkt_func = (pkt_func_def)hfi_process_event_notify;
  487. break;
  488. case HFI_MSG_SYS_INIT_DONE:
  489. pkt_func = (pkt_func_def)hfi_process_sys_init_done;
  490. break;
  491. case HFI_MSG_SYS_SESSION_INIT_DONE:
  492. pkt_func = (pkt_func_def)hfi_process_session_init_done;
  493. break;
  494. case HFI_MSG_SYS_PROPERTY_INFO:
  495. pkt_func = (pkt_func_def)hfi_process_sys_property_info;
  496. break;
  497. case HFI_MSG_SYS_SESSION_END_DONE:
  498. pkt_func = (pkt_func_def)hfi_process_session_end_done;
  499. break;
  500. case HFI_MSG_SESSION_CVP_SET_BUFFERS:
  501. pkt_func = (pkt_func_def) hfi_process_session_set_buf_done;
  502. break;
  503. case HFI_MSG_SESSION_CVP_RELEASE_BUFFERS:
  504. pkt_func = (pkt_func_def)hfi_process_session_rel_buf_done;
  505. break;
  506. case HFI_MSG_SYS_SESSION_ABORT_DONE:
  507. pkt_func = (pkt_func_def)hfi_process_session_abort_done;
  508. break;
  509. case HFI_MSG_SESSION_CVP_FLUSH:
  510. pkt_func = (pkt_func_def)hfi_process_session_flush_done;
  511. break;
  512. default:
  513. dprintk(CVP_HFI, "Use default msg handler: %#x\n",
  514. msg_hdr->packet);
  515. pkt_func = (pkt_func_def)hfi_process_session_cvp_msg;
  516. break;
  517. }
  518. return pkt_func ?
  519. pkt_func(device_id, hdr, info) : -ENOTSUPP;
  520. }