xref: /linux/drivers/media/platform/qcom/venus/hfi_msgs.c (revision e7e86d7697c6ed1dbbde18d7185c35b6967945ed)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
4  * Copyright (C) 2017 Linaro Ltd.
5  */
6 #include <linux/hash.h>
7 #include <linux/list.h>
8 #include <linux/slab.h>
9 #include <linux/soc/qcom/smem.h>
10 #include <media/videobuf2-v4l2.h>
11 
12 #include "core.h"
13 #include "hfi.h"
14 #include "hfi_helper.h"
15 #include "hfi_msgs.h"
16 #include "hfi_parser.h"
17 
18 #define SMEM_IMG_VER_TBL	469
19 #define VER_STR_SZ		128
20 #define SMEM_IMG_OFFSET_VENUS	(14 * 128)
21 
22 static void event_seq_changed(struct venus_core *core, struct venus_inst *inst,
23 			      struct hfi_msg_event_notify_pkt *pkt)
24 {
25 	enum hfi_version ver = core->res->hfi_version;
26 	struct hfi_event_data event = {0};
27 	int num_properties_changed;
28 	struct hfi_framesize *frame_sz;
29 	struct hfi_profile_level *profile_level;
30 	struct hfi_bit_depth *pixel_depth;
31 	struct hfi_pic_struct *pic_struct;
32 	struct hfi_colour_space *colour_info;
33 	struct hfi_buffer_requirements *bufreq;
34 	struct hfi_extradata_input_crop *crop;
35 	struct hfi_dpb_counts *dpb_count;
36 	u32 ptype, rem_bytes;
37 	u32 size_read = 0;
38 	u8 *data_ptr;
39 
40 	inst->error = HFI_ERR_NONE;
41 
42 	switch (pkt->event_data1) {
43 	case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
44 	case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
45 		break;
46 	default:
47 		inst->error = HFI_ERR_SESSION_INVALID_PARAMETER;
48 		inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
49 		return;
50 	}
51 
52 	event.event_type = pkt->event_data1;
53 
54 	num_properties_changed = pkt->event_data2;
55 	if (!num_properties_changed)
56 		goto error;
57 
58 	data_ptr = (u8 *)&pkt->ext_event_data[0];
59 	rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
60 
61 	do {
62 		if (rem_bytes < sizeof(u32))
63 			goto error;
64 		ptype = *((u32 *)data_ptr);
65 
66 		data_ptr += sizeof(u32);
67 		rem_bytes -= sizeof(u32);
68 
69 		switch (ptype) {
70 		case HFI_PROPERTY_PARAM_FRAME_SIZE:
71 			if (rem_bytes < sizeof(struct hfi_framesize))
72 				goto error;
73 
74 			frame_sz = (struct hfi_framesize *)data_ptr;
75 			event.width = frame_sz->width;
76 			event.height = frame_sz->height;
77 			size_read = sizeof(struct hfi_framesize);
78 			break;
79 		case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
80 			if (rem_bytes < sizeof(struct hfi_profile_level))
81 				goto error;
82 
83 			profile_level = (struct hfi_profile_level *)data_ptr;
84 			event.profile = profile_level->profile;
85 			event.level = profile_level->level;
86 			size_read = sizeof(struct hfi_profile_level);
87 			break;
88 		case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
89 			if (rem_bytes < sizeof(struct hfi_bit_depth))
90 				goto error;
91 
92 			pixel_depth = (struct hfi_bit_depth *)data_ptr;
93 			event.bit_depth = pixel_depth->bit_depth;
94 			size_read = sizeof(struct hfi_bit_depth);
95 			break;
96 		case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
97 			if (rem_bytes < sizeof(struct hfi_pic_struct))
98 				goto error;
99 
100 			pic_struct = (struct hfi_pic_struct *)data_ptr;
101 			event.pic_struct = pic_struct->progressive_only;
102 			size_read = sizeof(struct hfi_pic_struct);
103 			break;
104 		case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
105 			if (rem_bytes < sizeof(struct hfi_colour_space))
106 				goto error;
107 
108 			colour_info = (struct hfi_colour_space *)data_ptr;
109 			event.colour_space = colour_info->colour_space;
110 			size_read = sizeof(struct hfi_colour_space);
111 			break;
112 		case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
113 			if (rem_bytes < sizeof(u32))
114 				goto error;
115 
116 			event.entropy_mode = *(u32 *)data_ptr;
117 			size_read = sizeof(u32);
118 			break;
119 		case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
120 			if (rem_bytes < sizeof(struct hfi_buffer_requirements))
121 				goto error;
122 
123 			bufreq = (struct hfi_buffer_requirements *)data_ptr;
124 			event.buf_count = hfi_bufreq_get_count_min(bufreq, ver);
125 			size_read = sizeof(struct hfi_buffer_requirements);
126 			break;
127 		case HFI_INDEX_EXTRADATA_INPUT_CROP:
128 			if (rem_bytes < sizeof(struct hfi_extradata_input_crop))
129 				goto error;
130 
131 			crop = (struct hfi_extradata_input_crop *)data_ptr;
132 			event.input_crop.left = crop->left;
133 			event.input_crop.top = crop->top;
134 			event.input_crop.width = crop->width;
135 			event.input_crop.height = crop->height;
136 			size_read = sizeof(struct hfi_extradata_input_crop);
137 			break;
138 		case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS:
139 			if (rem_bytes < sizeof(struct hfi_dpb_counts))
140 				goto error;
141 
142 			dpb_count = (struct hfi_dpb_counts *)data_ptr;
143 			event.buf_count = dpb_count->fw_min_cnt;
144 			size_read = sizeof(struct hfi_dpb_counts);
145 			break;
146 		default:
147 			size_read = 0;
148 			break;
149 		}
150 		data_ptr += size_read;
151 		rem_bytes -= size_read;
152 		num_properties_changed--;
153 	} while (num_properties_changed > 0);
154 
155 	inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
156 	return;
157 
158 error:
159 	inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
160 	inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
161 }
162 
163 static void event_release_buffer_ref(struct venus_core *core,
164 				     struct venus_inst *inst,
165 				     struct hfi_msg_event_notify_pkt *pkt)
166 {
167 	struct hfi_event_data event = {0};
168 	struct hfi_msg_event_release_buffer_ref_pkt *data;
169 
170 	data = (struct hfi_msg_event_release_buffer_ref_pkt *)
171 		pkt->ext_event_data;
172 
173 	event.event_type = HFI_EVENT_RELEASE_BUFFER_REFERENCE;
174 	event.packet_buffer = data->packet_buffer;
175 	event.extradata_buffer = data->extradata_buffer;
176 	event.tag = data->output_tag;
177 
178 	inst->error = HFI_ERR_NONE;
179 	inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
180 }
181 
182 static void event_sys_error(struct venus_core *core, u32 event,
183 			    struct hfi_msg_event_notify_pkt *pkt)
184 {
185 	if (pkt)
186 		dev_dbg(core->dev, VDBGH
187 			"sys error (session id:%x, data1:%x, data2:%x)\n",
188 			pkt->shdr.session_id, pkt->event_data1,
189 			pkt->event_data2);
190 
191 	core->core_ops->event_notify(core, event);
192 }
193 
194 static void
195 event_session_error(struct venus_core *core, struct venus_inst *inst,
196 		    struct hfi_msg_event_notify_pkt *pkt)
197 {
198 	struct device *dev = core->dev;
199 
200 	dev_dbg(dev, VDBGH "session error: event id:%x, session id:%x\n",
201 		pkt->event_data1, pkt->shdr.session_id);
202 
203 	if (!inst)
204 		return;
205 
206 	switch (pkt->event_data1) {
207 	/* non fatal session errors */
208 	case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
209 	case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
210 	case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
211 	case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
212 		inst->error = HFI_ERR_NONE;
213 		break;
214 	default:
215 		dev_err(dev, "session error: event id:%x (%x), session id:%x\n",
216 			pkt->event_data1, pkt->event_data2,
217 			pkt->shdr.session_id);
218 
219 		inst->error = pkt->event_data1;
220 		inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL);
221 		break;
222 	}
223 }
224 
225 static void hfi_event_notify(struct venus_core *core, struct venus_inst *inst,
226 			     void *packet)
227 {
228 	struct hfi_msg_event_notify_pkt *pkt = packet;
229 
230 	if (!packet)
231 		return;
232 
233 	switch (pkt->event_id) {
234 	case HFI_EVENT_SYS_ERROR:
235 		event_sys_error(core, EVT_SYS_ERROR, pkt);
236 		break;
237 	case HFI_EVENT_SESSION_ERROR:
238 		event_session_error(core, inst, pkt);
239 		break;
240 	case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
241 		event_seq_changed(core, inst, pkt);
242 		break;
243 	case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
244 		event_release_buffer_ref(core, inst, pkt);
245 		break;
246 	case HFI_EVENT_SESSION_PROPERTY_CHANGED:
247 		break;
248 	default:
249 		break;
250 	}
251 }
252 
253 static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst,
254 			      void *packet)
255 {
256 	struct hfi_msg_sys_init_done_pkt *pkt = packet;
257 	int rem_bytes;
258 	u32 error;
259 
260 	error = pkt->error_type;
261 	if (error != HFI_ERR_NONE)
262 		goto done;
263 
264 	if (!pkt->num_properties) {
265 		error = HFI_ERR_SYS_INVALID_PARAMETER;
266 		goto done;
267 	}
268 
269 	rem_bytes = pkt->hdr.size - sizeof(*pkt);
270 	if (rem_bytes <= 0) {
271 		/* missing property data */
272 		error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
273 		goto done;
274 	}
275 
276 	error = hfi_parser(core, inst, pkt->data, rem_bytes);
277 
278 done:
279 	core->error = error;
280 	complete(&core->done);
281 }
282 
283 static void
284 sys_get_prop_image_version(struct venus_core *core,
285 			   struct hfi_msg_sys_property_info_pkt *pkt)
286 {
287 	struct device *dev = core->dev;
288 	u8 *smem_tbl_ptr;
289 	u8 *img_ver;
290 	int req_bytes;
291 	size_t smem_blk_sz;
292 	int ret;
293 
294 	req_bytes = pkt->hdr.size - sizeof(*pkt);
295 
296 	if (req_bytes < VER_STR_SZ || !pkt->data[0] || pkt->num_properties > 1)
297 		/* bad packet */
298 		return;
299 
300 	img_ver = pkt->data;
301 	if (!img_ver)
302 		return;
303 
304 	ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u",
305 		     &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
306 	if (ret)
307 		goto done;
308 
309 	ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u",
310 		     &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
311 	if (ret)
312 		goto done;
313 
314 	ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u",
315 		     &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
316 	if (ret)
317 		goto done;
318 
319 	dev_err(dev, VDBGL "error reading F/W version\n");
320 	return;
321 
322 done:
323 	dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n",
324 		img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev);
325 
326 	smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
327 		SMEM_IMG_VER_TBL, &smem_blk_sz);
328 	if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
329 		memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS,
330 		       img_ver, VER_STR_SZ);
331 }
332 
333 static void hfi_sys_property_info(struct venus_core *core,
334 				  struct venus_inst *inst, void *packet)
335 {
336 	struct hfi_msg_sys_property_info_pkt *pkt = packet;
337 	struct device *dev = core->dev;
338 
339 	if (!pkt->num_properties) {
340 		dev_dbg(dev, VDBGL "no properties\n");
341 		return;
342 	}
343 
344 	switch (pkt->property) {
345 	case HFI_PROPERTY_SYS_IMAGE_VERSION:
346 		sys_get_prop_image_version(core, pkt);
347 		break;
348 	default:
349 		dev_dbg(dev, VDBGL "unknown property data\n");
350 		break;
351 	}
352 }
353 
354 static void hfi_sys_rel_resource_done(struct venus_core *core,
355 				      struct venus_inst *inst,
356 				      void *packet)
357 {
358 	struct hfi_msg_sys_release_resource_done_pkt *pkt = packet;
359 
360 	core->error = pkt->error_type;
361 	complete(&core->done);
362 }
363 
364 static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst,
365 			      void *packet)
366 {
367 	struct hfi_msg_sys_ping_ack_pkt *pkt = packet;
368 
369 	core->error = HFI_ERR_NONE;
370 
371 	if (pkt->client_data != 0xbeef)
372 		core->error = HFI_ERR_SYS_FATAL;
373 
374 	complete(&core->done);
375 }
376 
377 static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst,
378 			      void *packet)
379 {
380 	dev_dbg(core->dev, VDBGL "sys idle\n");
381 }
382 
383 static void hfi_sys_pc_prepare_done(struct venus_core *core,
384 				    struct venus_inst *inst, void *packet)
385 {
386 	struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet;
387 
388 	dev_dbg(core->dev, VDBGL "pc prepare done (error %x)\n",
389 		pkt->error_type);
390 }
391 
392 static unsigned int
393 session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt,
394 			       struct hfi_profile_level *profile_level)
395 {
396 	struct hfi_profile_level *hfi;
397 	u32 req_bytes;
398 
399 	req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
400 
401 	if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level))
402 		/* bad packet */
403 		return HFI_ERR_SESSION_INVALID_PARAMETER;
404 
405 	hfi = (struct hfi_profile_level *)&pkt->data[0];
406 	profile_level->profile = hfi->profile;
407 	profile_level->level = hfi->level;
408 
409 	return HFI_ERR_NONE;
410 }
411 
412 static unsigned int
413 session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,
414 			 struct hfi_buffer_requirements *bufreq)
415 {
416 	struct hfi_buffer_requirements *buf_req;
417 	u32 req_bytes;
418 	unsigned int idx = 0;
419 
420 	req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
421 
422 	if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[0])
423 		/* bad packet */
424 		return HFI_ERR_SESSION_INVALID_PARAMETER;
425 
426 	buf_req = (struct hfi_buffer_requirements *)&pkt->data[0];
427 	if (!buf_req)
428 		return HFI_ERR_SESSION_INVALID_PARAMETER;
429 
430 	while (req_bytes) {
431 		memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
432 		idx++;
433 
434 		if (idx >= HFI_BUFFER_TYPE_MAX)
435 			return HFI_ERR_SESSION_INVALID_PARAMETER;
436 
437 		req_bytes -= sizeof(struct hfi_buffer_requirements);
438 		buf_req++;
439 	}
440 
441 	return HFI_ERR_NONE;
442 }
443 
444 static void hfi_session_prop_info(struct venus_core *core,
445 				  struct venus_inst *inst, void *packet)
446 {
447 	struct hfi_msg_session_property_info_pkt *pkt = packet;
448 	struct device *dev = core->dev;
449 	union hfi_get_property *hprop = &inst->hprop;
450 	unsigned int error = HFI_ERR_NONE;
451 
452 	if (!pkt->num_properties) {
453 		error = HFI_ERR_SESSION_INVALID_PARAMETER;
454 		dev_err(dev, "%s: no properties\n", __func__);
455 		goto done;
456 	}
457 
458 	switch (pkt->property) {
459 	case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
460 		memset(hprop->bufreq, 0, sizeof(hprop->bufreq));
461 		error = session_get_prop_buf_req(pkt, hprop->bufreq);
462 		break;
463 	case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
464 		memset(&hprop->profile_level, 0, sizeof(hprop->profile_level));
465 		error = session_get_prop_profile_level(pkt,
466 						       &hprop->profile_level);
467 		break;
468 	case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
469 		break;
470 	default:
471 		dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->property);
472 		return;
473 	}
474 
475 done:
476 	inst->error = error;
477 	complete(&inst->done);
478 }
479 
480 static void hfi_session_init_done(struct venus_core *core,
481 				  struct venus_inst *inst, void *packet)
482 {
483 	struct hfi_msg_session_init_done_pkt *pkt = packet;
484 	int rem_bytes;
485 	u32 error;
486 
487 	error = pkt->error_type;
488 	if (error != HFI_ERR_NONE)
489 		goto done;
490 
491 	if (!IS_V1(core))
492 		goto done;
493 
494 	rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
495 	if (rem_bytes <= 0) {
496 		error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
497 		goto done;
498 	}
499 
500 	error = hfi_parser(core, inst, pkt->data, rem_bytes);
501 done:
502 	inst->error = error;
503 	complete(&inst->done);
504 }
505 
506 static void hfi_session_load_res_done(struct venus_core *core,
507 				      struct venus_inst *inst, void *packet)
508 {
509 	struct hfi_msg_session_load_resources_done_pkt *pkt = packet;
510 
511 	inst->error = pkt->error_type;
512 	complete(&inst->done);
513 }
514 
515 static void hfi_session_flush_done(struct venus_core *core,
516 				   struct venus_inst *inst, void *packet)
517 {
518 	struct hfi_msg_session_flush_done_pkt *pkt = packet;
519 
520 	inst->error = pkt->error_type;
521 	complete(&inst->done);
522 	if (inst->ops->flush_done)
523 		inst->ops->flush_done(inst);
524 }
525 
526 static void hfi_session_etb_done(struct venus_core *core,
527 				 struct venus_inst *inst, void *packet)
528 {
529 	struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet;
530 
531 	inst->error = pkt->error_type;
532 	inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag,
533 			    pkt->filled_len, pkt->offset, 0, 0, 0);
534 }
535 
536 static void hfi_session_ftb_done(struct venus_core *core,
537 				 struct venus_inst *inst, void *packet)
538 {
539 	u32 session_type = inst->session_type;
540 	u64 timestamp_us = 0;
541 	u32 timestamp_hi = 0, timestamp_lo = 0;
542 	unsigned int error;
543 	u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0;
544 	u32 pic_type = 0, buffer_type = 0, output_tag = -1;
545 
546 	if (session_type == VIDC_SESSION_TYPE_ENC) {
547 		struct hfi_msg_session_fbd_compressed_pkt *pkt = packet;
548 
549 		timestamp_hi = pkt->time_stamp_hi;
550 		timestamp_lo = pkt->time_stamp_lo;
551 		hfi_flags = pkt->flags;
552 		offset = pkt->offset;
553 		filled_len = pkt->filled_len;
554 		pic_type = pkt->picture_type;
555 		output_tag = pkt->output_tag;
556 		buffer_type = HFI_BUFFER_OUTPUT;
557 
558 		error = pkt->error_type;
559 	} else if (session_type == VIDC_SESSION_TYPE_DEC) {
560 		struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt =
561 			packet;
562 
563 		timestamp_hi = pkt->time_stamp_hi;
564 		timestamp_lo = pkt->time_stamp_lo;
565 		hfi_flags = pkt->flags;
566 		offset = pkt->offset;
567 		filled_len = pkt->filled_len;
568 		pic_type = pkt->picture_type;
569 		output_tag = pkt->output_tag;
570 
571 		if (pkt->stream_id == 0)
572 			buffer_type = HFI_BUFFER_OUTPUT;
573 		else if (pkt->stream_id == 1)
574 			buffer_type = HFI_BUFFER_OUTPUT2;
575 
576 		error = pkt->error_type;
577 	} else {
578 		error = HFI_ERR_SESSION_INVALID_PARAMETER;
579 	}
580 
581 	if (buffer_type != HFI_BUFFER_OUTPUT &&
582 	    buffer_type != HFI_BUFFER_OUTPUT2)
583 		goto done;
584 
585 	if (hfi_flags & HFI_BUFFERFLAG_EOS)
586 		flags |= V4L2_BUF_FLAG_LAST;
587 
588 	switch (pic_type) {
589 	case HFI_PICTURE_IDR:
590 	case HFI_PICTURE_I:
591 		flags |= V4L2_BUF_FLAG_KEYFRAME;
592 		break;
593 	case HFI_PICTURE_P:
594 		flags |= V4L2_BUF_FLAG_PFRAME;
595 		break;
596 	case HFI_PICTURE_B:
597 		flags |= V4L2_BUF_FLAG_BFRAME;
598 		break;
599 	case HFI_FRAME_NOTCODED:
600 	case HFI_UNUSED_PICT:
601 	case HFI_FRAME_YUV:
602 	default:
603 		break;
604 	}
605 
606 	if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) {
607 		timestamp_us = timestamp_hi;
608 		timestamp_us = (timestamp_us << 32) | timestamp_lo;
609 	}
610 
611 done:
612 	inst->error = error;
613 	inst->ops->buf_done(inst, buffer_type, output_tag, filled_len,
614 			    offset, flags, hfi_flags, timestamp_us);
615 }
616 
617 static void hfi_session_start_done(struct venus_core *core,
618 				   struct venus_inst *inst, void *packet)
619 {
620 	struct hfi_msg_session_start_done_pkt *pkt = packet;
621 
622 	inst->error = pkt->error_type;
623 	complete(&inst->done);
624 }
625 
626 static void hfi_session_stop_done(struct venus_core *core,
627 				  struct venus_inst *inst, void *packet)
628 {
629 	struct hfi_msg_session_stop_done_pkt *pkt = packet;
630 
631 	inst->error = pkt->error_type;
632 	complete(&inst->done);
633 }
634 
635 static void hfi_session_rel_res_done(struct venus_core *core,
636 				     struct venus_inst *inst, void *packet)
637 {
638 	struct hfi_msg_session_release_resources_done_pkt *pkt = packet;
639 
640 	inst->error = pkt->error_type;
641 	complete(&inst->done);
642 }
643 
644 static void hfi_session_rel_buf_done(struct venus_core *core,
645 				     struct venus_inst *inst, void *packet)
646 {
647 	struct hfi_msg_session_release_buffers_done_pkt *pkt = packet;
648 
649 	inst->error = pkt->error_type;
650 	complete(&inst->done);
651 }
652 
653 static void hfi_session_end_done(struct venus_core *core,
654 				 struct venus_inst *inst, void *packet)
655 {
656 	struct hfi_msg_session_end_done_pkt *pkt = packet;
657 
658 	inst->error = pkt->error_type;
659 	complete(&inst->done);
660 }
661 
662 static void hfi_session_abort_done(struct venus_core *core,
663 				   struct venus_inst *inst, void *packet)
664 {
665 	struct hfi_msg_sys_session_abort_done_pkt *pkt = packet;
666 
667 	inst->error = pkt->error_type;
668 	complete(&inst->done);
669 }
670 
671 static void hfi_session_get_seq_hdr_done(struct venus_core *core,
672 					 struct venus_inst *inst, void *packet)
673 {
674 	struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet;
675 
676 	inst->error = pkt->error_type;
677 	complete(&inst->done);
678 }
679 
680 struct hfi_done_handler {
681 	u32 pkt;
682 	u32 pkt_sz;
683 	u32 pkt_sz2;
684 	void (*done)(struct venus_core *, struct venus_inst *, void *);
685 	bool is_sys_pkt;
686 };
687 
688 static const struct hfi_done_handler handlers[] = {
689 	{.pkt = HFI_MSG_EVENT_NOTIFY,
690 	 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
691 	 .done = hfi_event_notify,
692 	},
693 	{.pkt = HFI_MSG_SYS_INIT,
694 	 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
695 	 .done = hfi_sys_init_done,
696 	 .is_sys_pkt = true,
697 	},
698 	{.pkt = HFI_MSG_SYS_PROPERTY_INFO,
699 	 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
700 	 .done = hfi_sys_property_info,
701 	 .is_sys_pkt = true,
702 	},
703 	{.pkt = HFI_MSG_SYS_RELEASE_RESOURCE,
704 	 .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt),
705 	 .done = hfi_sys_rel_resource_done,
706 	 .is_sys_pkt = true,
707 	},
708 	{.pkt = HFI_MSG_SYS_PING_ACK,
709 	 .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt),
710 	 .done = hfi_sys_ping_done,
711 	 .is_sys_pkt = true,
712 	},
713 	{.pkt = HFI_MSG_SYS_IDLE,
714 	 .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt),
715 	 .done = hfi_sys_idle_done,
716 	 .is_sys_pkt = true,
717 	},
718 	{.pkt = HFI_MSG_SYS_PC_PREP,
719 	 .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt),
720 	 .done = hfi_sys_pc_prepare_done,
721 	 .is_sys_pkt = true,
722 	},
723 	{.pkt = HFI_MSG_SYS_SESSION_INIT,
724 	 .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt),
725 	 .done = hfi_session_init_done,
726 	},
727 	{.pkt = HFI_MSG_SYS_SESSION_END,
728 	 .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt),
729 	 .done = hfi_session_end_done,
730 	},
731 	{.pkt = HFI_MSG_SESSION_LOAD_RESOURCES,
732 	 .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt),
733 	 .done = hfi_session_load_res_done,
734 	},
735 	{.pkt = HFI_MSG_SESSION_START,
736 	 .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt),
737 	 .done = hfi_session_start_done,
738 	},
739 	{.pkt = HFI_MSG_SESSION_STOP,
740 	 .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt),
741 	 .done = hfi_session_stop_done,
742 	},
743 	{.pkt = HFI_MSG_SYS_SESSION_ABORT,
744 	 .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt),
745 	 .done = hfi_session_abort_done,
746 	},
747 	{.pkt = HFI_MSG_SESSION_EMPTY_BUFFER,
748 	 .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt),
749 	 .done = hfi_session_etb_done,
750 	},
751 	{.pkt = HFI_MSG_SESSION_FILL_BUFFER,
752 	 .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt),
753 	 .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt),
754 	 .done = hfi_session_ftb_done,
755 	},
756 	{.pkt = HFI_MSG_SESSION_FLUSH,
757 	 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt),
758 	 .done = hfi_session_flush_done,
759 	},
760 	{.pkt = HFI_MSG_SESSION_PROPERTY_INFO,
761 	 .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt),
762 	 .done = hfi_session_prop_info,
763 	},
764 	{.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES,
765 	 .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt),
766 	 .done = hfi_session_rel_res_done,
767 	},
768 	{.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER,
769 	 .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt),
770 	 .done = hfi_session_get_seq_hdr_done,
771 	},
772 	{.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS,
773 	 .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt),
774 	 .done = hfi_session_rel_buf_done,
775 	},
776 };
777 
778 void hfi_process_watchdog_timeout(struct venus_core *core)
779 {
780 	event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
781 }
782 
783 static struct venus_inst *to_instance(struct venus_core *core, u32 session_id)
784 {
785 	struct venus_inst *inst;
786 
787 	mutex_lock(&core->lock);
788 	list_for_each_entry(inst, &core->instances, list)
789 		if (hash32_ptr(inst) == session_id) {
790 			mutex_unlock(&core->lock);
791 			return inst;
792 		}
793 	mutex_unlock(&core->lock);
794 
795 	return NULL;
796 }
797 
798 u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr)
799 {
800 	const struct hfi_done_handler *handler;
801 	struct device *dev = core->dev;
802 	struct venus_inst *inst;
803 	bool found = false;
804 	unsigned int i;
805 
806 	for (i = 0; i < ARRAY_SIZE(handlers); i++) {
807 		handler = &handlers[i];
808 		if (handler->pkt != hdr->pkt_type)
809 			continue;
810 		found = true;
811 		break;
812 	}
813 
814 	if (!found)
815 		return hdr->pkt_type;
816 
817 	if (hdr->size && hdr->size < handler->pkt_sz &&
818 	    hdr->size < handler->pkt_sz2) {
819 		dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n",
820 			hdr->size, handler->pkt_sz, hdr->pkt_type);
821 
822 		return hdr->pkt_type;
823 	}
824 
825 	if (handler->is_sys_pkt) {
826 		inst = NULL;
827 	} else {
828 		struct hfi_session_pkt *pkt;
829 
830 		pkt = (struct hfi_session_pkt *)hdr;
831 		inst = to_instance(core, pkt->shdr.session_id);
832 
833 		if (!inst)
834 			dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n",
835 				 pkt->shdr.session_id,
836 				 handler ? handler->pkt : 0);
837 
838 		/*
839 		 * Event of type HFI_EVENT_SYS_ERROR will not have any session
840 		 * associated with it
841 		 */
842 		if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) {
843 			dev_err(dev, "got invalid session id:%x\n",
844 				pkt->shdr.session_id);
845 			goto invalid_session;
846 		}
847 	}
848 
849 	handler->done(core, inst, hdr);
850 
851 invalid_session:
852 	return hdr->pkt_type;
853 }
854