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
event_seq_changed(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)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
event_release_buffer_ref(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)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
event_sys_error(struct venus_core * core,u32 event,struct hfi_msg_event_notify_pkt * pkt)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, VDBGH
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
event_session_error(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)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, VDBGH "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
hfi_event_notify(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_sys_init_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
sys_get_prop_image_version(struct device * dev,struct hfi_msg_sys_property_info_pkt * pkt)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, VDBGL "F/W version: %s\n", (u8 *)&pkt->data[1]);
251 }
252
hfi_sys_property_info(struct venus_core * core,struct venus_inst * inst,void * packet)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, VDBGL "no properties\n");
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, VDBGL "unknown property data\n");
270 break;
271 }
272 }
273
hfi_sys_rel_resource_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_sys_ping_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_sys_idle_done(struct venus_core * core,struct venus_inst * inst,void * packet)297 static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst,
298 void *packet)
299 {
300 dev_dbg(core->dev, VDBGL "sys idle\n");
301 }
302
hfi_sys_pc_prepare_done(struct venus_core * core,struct venus_inst * inst,void * packet)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, VDBGL "pc prepare done (error %x)\n",
309 pkt->error_type);
310 }
311
312 static unsigned int
session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt * pkt,struct hfi_profile_level * profile_level)313 session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt,
314 struct hfi_profile_level *profile_level)
315 {
316 struct hfi_profile_level *hfi;
317 u32 req_bytes;
318
319 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
320
321 if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level))
322 /* bad packet */
323 return HFI_ERR_SESSION_INVALID_PARAMETER;
324
325 hfi = (struct hfi_profile_level *)&pkt->data[1];
326 profile_level->profile = hfi->profile;
327 profile_level->level = hfi->level;
328
329 return HFI_ERR_NONE;
330 }
331
332 static unsigned int
session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt * pkt,struct hfi_buffer_requirements * bufreq)333 session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,
334 struct hfi_buffer_requirements *bufreq)
335 {
336 struct hfi_buffer_requirements *buf_req;
337 u32 req_bytes;
338 unsigned int idx = 0;
339
340 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
341
342 if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[1])
343 /* bad packet */
344 return HFI_ERR_SESSION_INVALID_PARAMETER;
345
346 buf_req = (struct hfi_buffer_requirements *)&pkt->data[1];
347 if (!buf_req)
348 return HFI_ERR_SESSION_INVALID_PARAMETER;
349
350 while (req_bytes) {
351 memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
352 idx++;
353
354 if (idx > HFI_BUFFER_TYPE_MAX)
355 return HFI_ERR_SESSION_INVALID_PARAMETER;
356
357 req_bytes -= sizeof(struct hfi_buffer_requirements);
358 buf_req++;
359 }
360
361 return HFI_ERR_NONE;
362 }
363
hfi_session_prop_info(struct venus_core * core,struct venus_inst * inst,void * packet)364 static void hfi_session_prop_info(struct venus_core *core,
365 struct venus_inst *inst, void *packet)
366 {
367 struct hfi_msg_session_property_info_pkt *pkt = packet;
368 struct device *dev = core->dev;
369 union hfi_get_property *hprop = &inst->hprop;
370 unsigned int error = HFI_ERR_NONE;
371
372 if (!pkt->num_properties) {
373 error = HFI_ERR_SESSION_INVALID_PARAMETER;
374 dev_err(dev, "%s: no properties\n", __func__);
375 goto done;
376 }
377
378 switch (pkt->data[0]) {
379 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
380 memset(hprop->bufreq, 0, sizeof(hprop->bufreq));
381 error = session_get_prop_buf_req(pkt, hprop->bufreq);
382 break;
383 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
384 memset(&hprop->profile_level, 0, sizeof(hprop->profile_level));
385 error = session_get_prop_profile_level(pkt,
386 &hprop->profile_level);
387 break;
388 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
389 break;
390 default:
391 dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->data[0]);
392 return;
393 }
394
395 done:
396 inst->error = error;
397 complete(&inst->done);
398 }
399
hfi_session_init_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_load_res_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_flush_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_etb_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_ftb_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_start_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_stop_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_rel_res_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_rel_buf_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_end_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_abort_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_session_get_seq_hdr_done(struct venus_core * core,struct venus_inst * inst,void * packet)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
hfi_process_watchdog_timeout(struct venus_core * core)698 void hfi_process_watchdog_timeout(struct venus_core *core)
699 {
700 event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
701 }
702
to_instance(struct venus_core * core,u32 session_id)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
hfi_process_msg_packet(struct venus_core * core,struct hfi_pkt_hdr * hdr)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