821 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 46919#define VER_STR_SZ 12820#define SMEM_IMG_OFFSET_VENUS (14 * 128)21 22static 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_get_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 126done:127 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);128}129 130static 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 149static 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, VDBGH154 "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 161static void162event_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 192static 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 220static 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);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 245done:246 core->error = error;247 complete(&core->done);248}249 250static void251sys_get_prop_image_version(struct venus_core *core,252 struct hfi_msg_sys_property_info_pkt *pkt)253{254 struct device *dev = core->dev;255 u8 *smem_tbl_ptr;256 u8 *img_ver;257 int req_bytes;258 size_t smem_blk_sz;259 int ret;260 261 req_bytes = pkt->hdr.size - sizeof(*pkt);262 263 if (req_bytes < VER_STR_SZ || !pkt->data[0] || pkt->num_properties > 1)264 /* bad packet */265 return;266 267 img_ver = pkt->data;268 if (!img_ver)269 return;270 271 ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u",272 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);273 if (ret)274 goto done;275 276 ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u",277 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);278 if (ret)279 goto done;280 281 ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u",282 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);283 if (ret)284 goto done;285 286 dev_err(dev, VDBGL "error reading F/W version\n");287 return;288 289done:290 dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n",291 img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev);292 293 smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,294 SMEM_IMG_VER_TBL, &smem_blk_sz);295 if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)296 memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS,297 img_ver, VER_STR_SZ);298}299 300static void hfi_sys_property_info(struct venus_core *core,301 struct venus_inst *inst, void *packet)302{303 struct hfi_msg_sys_property_info_pkt *pkt = packet;304 struct device *dev = core->dev;305 306 if (!pkt->num_properties) {307 dev_dbg(dev, VDBGL "no properties\n");308 return;309 }310 311 switch (pkt->property) {312 case HFI_PROPERTY_SYS_IMAGE_VERSION:313 sys_get_prop_image_version(core, pkt);314 break;315 default:316 dev_dbg(dev, VDBGL "unknown property data\n");317 break;318 }319}320 321static void hfi_sys_rel_resource_done(struct venus_core *core,322 struct venus_inst *inst,323 void *packet)324{325 struct hfi_msg_sys_release_resource_done_pkt *pkt = packet;326 327 core->error = pkt->error_type;328 complete(&core->done);329}330 331static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst,332 void *packet)333{334 struct hfi_msg_sys_ping_ack_pkt *pkt = packet;335 336 core->error = HFI_ERR_NONE;337 338 if (pkt->client_data != 0xbeef)339 core->error = HFI_ERR_SYS_FATAL;340 341 complete(&core->done);342}343 344static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst,345 void *packet)346{347 dev_dbg(core->dev, VDBGL "sys idle\n");348}349 350static void hfi_sys_pc_prepare_done(struct venus_core *core,351 struct venus_inst *inst, void *packet)352{353 struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet;354 355 dev_dbg(core->dev, VDBGL "pc prepare done (error %x)\n",356 pkt->error_type);357}358 359static unsigned int360session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt,361 struct hfi_profile_level *profile_level)362{363 struct hfi_profile_level *hfi;364 u32 req_bytes;365 366 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);367 368 if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level))369 /* bad packet */370 return HFI_ERR_SESSION_INVALID_PARAMETER;371 372 hfi = (struct hfi_profile_level *)&pkt->data[0];373 profile_level->profile = hfi->profile;374 profile_level->level = hfi->level;375 376 return HFI_ERR_NONE;377}378 379static unsigned int380session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,381 struct hfi_buffer_requirements *bufreq)382{383 struct hfi_buffer_requirements *buf_req;384 u32 req_bytes;385 unsigned int idx = 0;386 387 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);388 389 if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[0])390 /* bad packet */391 return HFI_ERR_SESSION_INVALID_PARAMETER;392 393 buf_req = (struct hfi_buffer_requirements *)&pkt->data[0];394 if (!buf_req)395 return HFI_ERR_SESSION_INVALID_PARAMETER;396 397 while (req_bytes) {398 memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));399 idx++;400 401 if (idx >= HFI_BUFFER_TYPE_MAX)402 return HFI_ERR_SESSION_INVALID_PARAMETER;403 404 req_bytes -= sizeof(struct hfi_buffer_requirements);405 buf_req++;406 }407 408 return HFI_ERR_NONE;409}410 411static void hfi_session_prop_info(struct venus_core *core,412 struct venus_inst *inst, void *packet)413{414 struct hfi_msg_session_property_info_pkt *pkt = packet;415 struct device *dev = core->dev;416 union hfi_get_property *hprop = &inst->hprop;417 unsigned int error = HFI_ERR_NONE;418 419 if (!pkt->num_properties) {420 error = HFI_ERR_SESSION_INVALID_PARAMETER;421 dev_err(dev, "%s: no properties\n", __func__);422 goto done;423 }424 425 switch (pkt->property) {426 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:427 memset(hprop->bufreq, 0, sizeof(hprop->bufreq));428 error = session_get_prop_buf_req(pkt, hprop->bufreq);429 break;430 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:431 memset(&hprop->profile_level, 0, sizeof(hprop->profile_level));432 error = session_get_prop_profile_level(pkt,433 &hprop->profile_level);434 break;435 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:436 break;437 default:438 dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->property);439 return;440 }441 442done:443 inst->error = error;444 complete(&inst->done);445}446 447static void hfi_session_init_done(struct venus_core *core,448 struct venus_inst *inst, void *packet)449{450 struct hfi_msg_session_init_done_pkt *pkt = packet;451 int rem_bytes;452 u32 error;453 454 error = pkt->error_type;455 if (error != HFI_ERR_NONE)456 goto done;457 458 if (!IS_V1(core))459 goto done;460 461 rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt);462 if (rem_bytes <= 0) {463 error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;464 goto done;465 }466 467 error = hfi_parser(core, inst, pkt->data, rem_bytes);468done:469 inst->error = error;470 complete(&inst->done);471}472 473static void hfi_session_load_res_done(struct venus_core *core,474 struct venus_inst *inst, void *packet)475{476 struct hfi_msg_session_load_resources_done_pkt *pkt = packet;477 478 inst->error = pkt->error_type;479 complete(&inst->done);480}481 482static void hfi_session_flush_done(struct venus_core *core,483 struct venus_inst *inst, void *packet)484{485 struct hfi_msg_session_flush_done_pkt *pkt = packet;486 487 inst->error = pkt->error_type;488 complete(&inst->done);489 if (inst->ops->flush_done)490 inst->ops->flush_done(inst);491}492 493static void hfi_session_etb_done(struct venus_core *core,494 struct venus_inst *inst, void *packet)495{496 struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet;497 498 inst->error = pkt->error_type;499 inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag,500 pkt->filled_len, pkt->offset, 0, 0, 0);501}502 503static void hfi_session_ftb_done(struct venus_core *core,504 struct venus_inst *inst, void *packet)505{506 u32 session_type = inst->session_type;507 u64 timestamp_us = 0;508 u32 timestamp_hi = 0, timestamp_lo = 0;509 unsigned int error;510 u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0;511 u32 pic_type = 0, buffer_type = 0, output_tag = -1;512 513 if (session_type == VIDC_SESSION_TYPE_ENC) {514 struct hfi_msg_session_fbd_compressed_pkt *pkt = packet;515 516 timestamp_hi = pkt->time_stamp_hi;517 timestamp_lo = pkt->time_stamp_lo;518 hfi_flags = pkt->flags;519 offset = pkt->offset;520 filled_len = pkt->filled_len;521 pic_type = pkt->picture_type;522 output_tag = pkt->output_tag;523 buffer_type = HFI_BUFFER_OUTPUT;524 525 error = pkt->error_type;526 } else if (session_type == VIDC_SESSION_TYPE_DEC) {527 struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt =528 packet;529 530 timestamp_hi = pkt->time_stamp_hi;531 timestamp_lo = pkt->time_stamp_lo;532 hfi_flags = pkt->flags;533 offset = pkt->offset;534 filled_len = pkt->filled_len;535 pic_type = pkt->picture_type;536 output_tag = pkt->output_tag;537 538 if (pkt->stream_id == 0)539 buffer_type = HFI_BUFFER_OUTPUT;540 else if (pkt->stream_id == 1)541 buffer_type = HFI_BUFFER_OUTPUT2;542 543 error = pkt->error_type;544 } else {545 error = HFI_ERR_SESSION_INVALID_PARAMETER;546 }547 548 if (buffer_type != HFI_BUFFER_OUTPUT &&549 buffer_type != HFI_BUFFER_OUTPUT2)550 goto done;551 552 if (hfi_flags & HFI_BUFFERFLAG_EOS)553 flags |= V4L2_BUF_FLAG_LAST;554 555 switch (pic_type) {556 case HFI_PICTURE_IDR:557 case HFI_PICTURE_I:558 flags |= V4L2_BUF_FLAG_KEYFRAME;559 break;560 case HFI_PICTURE_P:561 flags |= V4L2_BUF_FLAG_PFRAME;562 break;563 case HFI_PICTURE_B:564 flags |= V4L2_BUF_FLAG_BFRAME;565 break;566 case HFI_FRAME_NOTCODED:567 case HFI_UNUSED_PICT:568 case HFI_FRAME_YUV:569 default:570 break;571 }572 573 if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) {574 timestamp_us = timestamp_hi;575 timestamp_us = (timestamp_us << 32) | timestamp_lo;576 }577 578done:579 inst->error = error;580 inst->ops->buf_done(inst, buffer_type, output_tag, filled_len,581 offset, flags, hfi_flags, timestamp_us);582}583 584static void hfi_session_start_done(struct venus_core *core,585 struct venus_inst *inst, void *packet)586{587 struct hfi_msg_session_start_done_pkt *pkt = packet;588 589 inst->error = pkt->error_type;590 complete(&inst->done);591}592 593static void hfi_session_stop_done(struct venus_core *core,594 struct venus_inst *inst, void *packet)595{596 struct hfi_msg_session_stop_done_pkt *pkt = packet;597 598 inst->error = pkt->error_type;599 complete(&inst->done);600}601 602static void hfi_session_rel_res_done(struct venus_core *core,603 struct venus_inst *inst, void *packet)604{605 struct hfi_msg_session_release_resources_done_pkt *pkt = packet;606 607 inst->error = pkt->error_type;608 complete(&inst->done);609}610 611static void hfi_session_rel_buf_done(struct venus_core *core,612 struct venus_inst *inst, void *packet)613{614 struct hfi_msg_session_release_buffers_done_pkt *pkt = packet;615 616 inst->error = pkt->error_type;617 complete(&inst->done);618}619 620static void hfi_session_end_done(struct venus_core *core,621 struct venus_inst *inst, void *packet)622{623 struct hfi_msg_session_end_done_pkt *pkt = packet;624 625 inst->error = pkt->error_type;626 complete(&inst->done);627}628 629static void hfi_session_abort_done(struct venus_core *core,630 struct venus_inst *inst, void *packet)631{632 struct hfi_msg_sys_session_abort_done_pkt *pkt = packet;633 634 inst->error = pkt->error_type;635 complete(&inst->done);636}637 638static void hfi_session_get_seq_hdr_done(struct venus_core *core,639 struct venus_inst *inst, void *packet)640{641 struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet;642 643 inst->error = pkt->error_type;644 complete(&inst->done);645}646 647struct hfi_done_handler {648 u32 pkt;649 u32 pkt_sz;650 u32 pkt_sz2;651 void (*done)(struct venus_core *, struct venus_inst *, void *);652 bool is_sys_pkt;653};654 655static const struct hfi_done_handler handlers[] = {656 {.pkt = HFI_MSG_EVENT_NOTIFY,657 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),658 .done = hfi_event_notify,659 },660 {.pkt = HFI_MSG_SYS_INIT,661 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),662 .done = hfi_sys_init_done,663 .is_sys_pkt = true,664 },665 {.pkt = HFI_MSG_SYS_PROPERTY_INFO,666 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),667 .done = hfi_sys_property_info,668 .is_sys_pkt = true,669 },670 {.pkt = HFI_MSG_SYS_RELEASE_RESOURCE,671 .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt),672 .done = hfi_sys_rel_resource_done,673 .is_sys_pkt = true,674 },675 {.pkt = HFI_MSG_SYS_PING_ACK,676 .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt),677 .done = hfi_sys_ping_done,678 .is_sys_pkt = true,679 },680 {.pkt = HFI_MSG_SYS_IDLE,681 .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt),682 .done = hfi_sys_idle_done,683 .is_sys_pkt = true,684 },685 {.pkt = HFI_MSG_SYS_PC_PREP,686 .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt),687 .done = hfi_sys_pc_prepare_done,688 .is_sys_pkt = true,689 },690 {.pkt = HFI_MSG_SYS_SESSION_INIT,691 .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt),692 .done = hfi_session_init_done,693 },694 {.pkt = HFI_MSG_SYS_SESSION_END,695 .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt),696 .done = hfi_session_end_done,697 },698 {.pkt = HFI_MSG_SESSION_LOAD_RESOURCES,699 .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt),700 .done = hfi_session_load_res_done,701 },702 {.pkt = HFI_MSG_SESSION_START,703 .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt),704 .done = hfi_session_start_done,705 },706 {.pkt = HFI_MSG_SESSION_STOP,707 .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt),708 .done = hfi_session_stop_done,709 },710 {.pkt = HFI_MSG_SYS_SESSION_ABORT,711 .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt),712 .done = hfi_session_abort_done,713 },714 {.pkt = HFI_MSG_SESSION_EMPTY_BUFFER,715 .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt),716 .done = hfi_session_etb_done,717 },718 {.pkt = HFI_MSG_SESSION_FILL_BUFFER,719 .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt),720 .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt),721 .done = hfi_session_ftb_done,722 },723 {.pkt = HFI_MSG_SESSION_FLUSH,724 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt),725 .done = hfi_session_flush_done,726 },727 {.pkt = HFI_MSG_SESSION_PROPERTY_INFO,728 .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt),729 .done = hfi_session_prop_info,730 },731 {.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES,732 .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt),733 .done = hfi_session_rel_res_done,734 },735 {.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER,736 .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt),737 .done = hfi_session_get_seq_hdr_done,738 },739 {.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS,740 .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt),741 .done = hfi_session_rel_buf_done,742 },743};744 745void hfi_process_watchdog_timeout(struct venus_core *core)746{747 event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);748}749 750static struct venus_inst *to_instance(struct venus_core *core, u32 session_id)751{752 struct venus_inst *inst;753 754 mutex_lock(&core->lock);755 list_for_each_entry(inst, &core->instances, list)756 if (hash32_ptr(inst) == session_id) {757 mutex_unlock(&core->lock);758 return inst;759 }760 mutex_unlock(&core->lock);761 762 return NULL;763}764 765u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr)766{767 const struct hfi_done_handler *handler;768 struct device *dev = core->dev;769 struct venus_inst *inst;770 bool found = false;771 unsigned int i;772 773 for (i = 0; i < ARRAY_SIZE(handlers); i++) {774 handler = &handlers[i];775 if (handler->pkt != hdr->pkt_type)776 continue;777 found = true;778 break;779 }780 781 if (!found)782 return hdr->pkt_type;783 784 if (hdr->size && hdr->size < handler->pkt_sz &&785 hdr->size < handler->pkt_sz2) {786 dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n",787 hdr->size, handler->pkt_sz, hdr->pkt_type);788 789 return hdr->pkt_type;790 }791 792 if (handler->is_sys_pkt) {793 inst = NULL;794 } else {795 struct hfi_session_pkt *pkt;796 797 pkt = (struct hfi_session_pkt *)hdr;798 inst = to_instance(core, pkt->shdr.session_id);799 800 if (!inst)801 dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n",802 pkt->shdr.session_id,803 handler ? handler->pkt : 0);804 805 /*806 * Event of type HFI_EVENT_SYS_ERROR will not have any session807 * associated with it808 */809 if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) {810 dev_err(dev, "got invalid session id:%x\n",811 pkt->shdr.session_id);812 goto invalid_session;813 }814 }815 816 handler->done(core, inst, hdr);817 818invalid_session:819 return hdr->pkt_type;820}821