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