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