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