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