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