GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / media / platform / qcom / venus / hfi_msgs.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
721 void hfi_process_watchdog_timeout(struct venus_core *core)
722 {
723         event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
724 }
725
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
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 }