hfi_response_handler.c 21 KB

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