197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 209c2845eSStanimir Varbanov /* 309c2845eSStanimir Varbanov * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 409c2845eSStanimir Varbanov * Copyright (C) 2017 Linaro Ltd. 509c2845eSStanimir Varbanov */ 609c2845eSStanimir Varbanov #include <linux/hash.h> 709c2845eSStanimir Varbanov #include <linux/list.h> 809c2845eSStanimir Varbanov #include <linux/slab.h> 909c2845eSStanimir Varbanov #include <media/videobuf2-v4l2.h> 1009c2845eSStanimir Varbanov 1109c2845eSStanimir Varbanov #include "core.h" 1209c2845eSStanimir Varbanov #include "hfi.h" 1309c2845eSStanimir Varbanov #include "hfi_helper.h" 1409c2845eSStanimir Varbanov #include "hfi_msgs.h" 151a73374aSStanimir Varbanov #include "hfi_parser.h" 1609c2845eSStanimir Varbanov 1709c2845eSStanimir Varbanov static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, 1809c2845eSStanimir Varbanov struct hfi_msg_event_notify_pkt *pkt) 1909c2845eSStanimir Varbanov { 209eb2146eSStanimir Varbanov enum hfi_version ver = core->res->hfi_version; 2109c2845eSStanimir Varbanov struct hfi_event_data event = {0}; 2209c2845eSStanimir Varbanov int num_properties_changed; 2309c2845eSStanimir Varbanov struct hfi_framesize *frame_sz; 2409c2845eSStanimir Varbanov struct hfi_profile_level *profile_level; 259eb2146eSStanimir Varbanov struct hfi_bit_depth *pixel_depth; 269eb2146eSStanimir Varbanov struct hfi_pic_struct *pic_struct; 279eb2146eSStanimir Varbanov struct hfi_colour_space *colour_info; 289eb2146eSStanimir Varbanov struct hfi_buffer_requirements *bufreq; 299eb2146eSStanimir Varbanov struct hfi_extradata_input_crop *crop; 3009c2845eSStanimir Varbanov u8 *data_ptr; 3109c2845eSStanimir Varbanov u32 ptype; 3209c2845eSStanimir Varbanov 3309c2845eSStanimir Varbanov inst->error = HFI_ERR_NONE; 3409c2845eSStanimir Varbanov 3509c2845eSStanimir Varbanov switch (pkt->event_data1) { 3609c2845eSStanimir Varbanov case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES: 3709c2845eSStanimir Varbanov case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES: 3809c2845eSStanimir Varbanov break; 3909c2845eSStanimir Varbanov default: 4009c2845eSStanimir Varbanov inst->error = HFI_ERR_SESSION_INVALID_PARAMETER; 4109c2845eSStanimir Varbanov goto done; 4209c2845eSStanimir Varbanov } 4309c2845eSStanimir Varbanov 4409c2845eSStanimir Varbanov event.event_type = pkt->event_data1; 4509c2845eSStanimir Varbanov 4609c2845eSStanimir Varbanov num_properties_changed = pkt->event_data2; 4709c2845eSStanimir Varbanov if (!num_properties_changed) { 4809c2845eSStanimir Varbanov inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; 4909c2845eSStanimir Varbanov goto done; 5009c2845eSStanimir Varbanov } 5109c2845eSStanimir Varbanov 5209c2845eSStanimir Varbanov data_ptr = (u8 *)&pkt->ext_event_data[0]; 5309c2845eSStanimir Varbanov do { 5409c2845eSStanimir Varbanov ptype = *((u32 *)data_ptr); 5509c2845eSStanimir Varbanov switch (ptype) { 5609c2845eSStanimir Varbanov case HFI_PROPERTY_PARAM_FRAME_SIZE: 5709c2845eSStanimir Varbanov data_ptr += sizeof(u32); 5809c2845eSStanimir Varbanov frame_sz = (struct hfi_framesize *)data_ptr; 5909c2845eSStanimir Varbanov event.width = frame_sz->width; 6009c2845eSStanimir Varbanov event.height = frame_sz->height; 61ea8afbabSStanimir Varbanov data_ptr += sizeof(*frame_sz); 6209c2845eSStanimir Varbanov break; 6309c2845eSStanimir Varbanov case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: 6409c2845eSStanimir Varbanov data_ptr += sizeof(u32); 6509c2845eSStanimir Varbanov profile_level = (struct hfi_profile_level *)data_ptr; 6609c2845eSStanimir Varbanov event.profile = profile_level->profile; 6709c2845eSStanimir Varbanov event.level = profile_level->level; 68ea8afbabSStanimir Varbanov data_ptr += sizeof(*profile_level); 6909c2845eSStanimir Varbanov break; 709eb2146eSStanimir Varbanov case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: 719eb2146eSStanimir Varbanov data_ptr += sizeof(u32); 729eb2146eSStanimir Varbanov pixel_depth = (struct hfi_bit_depth *)data_ptr; 739eb2146eSStanimir Varbanov event.bit_depth = pixel_depth->bit_depth; 749eb2146eSStanimir Varbanov data_ptr += sizeof(*pixel_depth); 759eb2146eSStanimir Varbanov break; 769eb2146eSStanimir Varbanov case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: 779eb2146eSStanimir Varbanov data_ptr += sizeof(u32); 789eb2146eSStanimir Varbanov pic_struct = (struct hfi_pic_struct *)data_ptr; 799eb2146eSStanimir Varbanov event.pic_struct = pic_struct->progressive_only; 809eb2146eSStanimir Varbanov data_ptr += sizeof(*pic_struct); 819eb2146eSStanimir Varbanov break; 829eb2146eSStanimir Varbanov case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: 839eb2146eSStanimir Varbanov data_ptr += sizeof(u32); 849eb2146eSStanimir Varbanov colour_info = (struct hfi_colour_space *)data_ptr; 859eb2146eSStanimir Varbanov event.colour_space = colour_info->colour_space; 869eb2146eSStanimir Varbanov data_ptr += sizeof(*colour_info); 879eb2146eSStanimir Varbanov break; 889eb2146eSStanimir Varbanov case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: 899eb2146eSStanimir Varbanov data_ptr += sizeof(u32); 909eb2146eSStanimir Varbanov event.entropy_mode = *(u32 *)data_ptr; 919eb2146eSStanimir Varbanov data_ptr += sizeof(u32); 929eb2146eSStanimir Varbanov break; 939eb2146eSStanimir Varbanov case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: 949eb2146eSStanimir Varbanov data_ptr += sizeof(u32); 959eb2146eSStanimir Varbanov bufreq = (struct hfi_buffer_requirements *)data_ptr; 969eb2146eSStanimir Varbanov event.buf_count = HFI_BUFREQ_COUNT_MIN(bufreq, ver); 979eb2146eSStanimir Varbanov data_ptr += sizeof(*bufreq); 989eb2146eSStanimir Varbanov break; 999eb2146eSStanimir Varbanov case HFI_INDEX_EXTRADATA_INPUT_CROP: 1009eb2146eSStanimir Varbanov data_ptr += sizeof(u32); 1019eb2146eSStanimir Varbanov crop = (struct hfi_extradata_input_crop *)data_ptr; 1029eb2146eSStanimir Varbanov event.input_crop.left = crop->left; 1039eb2146eSStanimir Varbanov event.input_crop.top = crop->top; 1049eb2146eSStanimir Varbanov event.input_crop.width = crop->width; 1059eb2146eSStanimir Varbanov event.input_crop.height = crop->height; 1069eb2146eSStanimir Varbanov data_ptr += sizeof(*crop); 1079eb2146eSStanimir Varbanov break; 10809c2845eSStanimir Varbanov default: 10909c2845eSStanimir Varbanov break; 11009c2845eSStanimir Varbanov } 11109c2845eSStanimir Varbanov num_properties_changed--; 11209c2845eSStanimir Varbanov } while (num_properties_changed > 0); 11309c2845eSStanimir Varbanov 11409c2845eSStanimir Varbanov done: 11509c2845eSStanimir Varbanov inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); 11609c2845eSStanimir Varbanov } 11709c2845eSStanimir Varbanov 11809c2845eSStanimir Varbanov static void event_release_buffer_ref(struct venus_core *core, 11909c2845eSStanimir Varbanov struct venus_inst *inst, 12009c2845eSStanimir Varbanov struct hfi_msg_event_notify_pkt *pkt) 12109c2845eSStanimir Varbanov { 12209c2845eSStanimir Varbanov struct hfi_event_data event = {0}; 12309c2845eSStanimir Varbanov struct hfi_msg_event_release_buffer_ref_pkt *data; 12409c2845eSStanimir Varbanov 12509c2845eSStanimir Varbanov data = (struct hfi_msg_event_release_buffer_ref_pkt *) 12609c2845eSStanimir Varbanov pkt->ext_event_data; 12709c2845eSStanimir Varbanov 12809c2845eSStanimir Varbanov event.event_type = HFI_EVENT_RELEASE_BUFFER_REFERENCE; 12909c2845eSStanimir Varbanov event.packet_buffer = data->packet_buffer; 13009c2845eSStanimir Varbanov event.extradata_buffer = data->extradata_buffer; 13109c2845eSStanimir Varbanov event.tag = data->output_tag; 13209c2845eSStanimir Varbanov 13309c2845eSStanimir Varbanov inst->error = HFI_ERR_NONE; 13409c2845eSStanimir Varbanov inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); 13509c2845eSStanimir Varbanov } 13609c2845eSStanimir Varbanov 13709c2845eSStanimir Varbanov static void event_sys_error(struct venus_core *core, u32 event, 13809c2845eSStanimir Varbanov struct hfi_msg_event_notify_pkt *pkt) 13909c2845eSStanimir Varbanov { 14009c2845eSStanimir Varbanov if (pkt) 1418c91dc08SStanimir Varbanov dev_dbg(core->dev, VDBGH 14209c2845eSStanimir Varbanov "sys error (session id:%x, data1:%x, data2:%x)\n", 14309c2845eSStanimir Varbanov pkt->shdr.session_id, pkt->event_data1, 14409c2845eSStanimir Varbanov pkt->event_data2); 14509c2845eSStanimir Varbanov 14609c2845eSStanimir Varbanov core->core_ops->event_notify(core, event); 14709c2845eSStanimir Varbanov } 14809c2845eSStanimir Varbanov 14909c2845eSStanimir Varbanov static void 15009c2845eSStanimir Varbanov event_session_error(struct venus_core *core, struct venus_inst *inst, 15109c2845eSStanimir Varbanov struct hfi_msg_event_notify_pkt *pkt) 15209c2845eSStanimir Varbanov { 15309c2845eSStanimir Varbanov struct device *dev = core->dev; 15409c2845eSStanimir Varbanov 1558c91dc08SStanimir Varbanov dev_dbg(dev, VDBGH "session error: event id:%x, session id:%x\n", 15609c2845eSStanimir Varbanov pkt->event_data1, pkt->shdr.session_id); 15709c2845eSStanimir Varbanov 15809c2845eSStanimir Varbanov if (!inst) 15909c2845eSStanimir Varbanov return; 16009c2845eSStanimir Varbanov 16109c2845eSStanimir Varbanov switch (pkt->event_data1) { 16209c2845eSStanimir Varbanov /* non fatal session errors */ 16309c2845eSStanimir Varbanov case HFI_ERR_SESSION_INVALID_SCALE_FACTOR: 16409c2845eSStanimir Varbanov case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE: 16509c2845eSStanimir Varbanov case HFI_ERR_SESSION_UNSUPPORTED_SETTING: 16609c2845eSStanimir Varbanov case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED: 16709c2845eSStanimir Varbanov inst->error = HFI_ERR_NONE; 16809c2845eSStanimir Varbanov break; 16909c2845eSStanimir Varbanov default: 17009c2845eSStanimir Varbanov dev_err(dev, "session error: event id:%x (%x), session id:%x\n", 17109c2845eSStanimir Varbanov pkt->event_data1, pkt->event_data2, 17209c2845eSStanimir Varbanov pkt->shdr.session_id); 17309c2845eSStanimir Varbanov 17409c2845eSStanimir Varbanov inst->error = pkt->event_data1; 17509c2845eSStanimir Varbanov inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL); 17609c2845eSStanimir Varbanov break; 17709c2845eSStanimir Varbanov } 17809c2845eSStanimir Varbanov } 17909c2845eSStanimir Varbanov 18009c2845eSStanimir Varbanov static void hfi_event_notify(struct venus_core *core, struct venus_inst *inst, 18109c2845eSStanimir Varbanov void *packet) 18209c2845eSStanimir Varbanov { 18309c2845eSStanimir Varbanov struct hfi_msg_event_notify_pkt *pkt = packet; 18409c2845eSStanimir Varbanov 18509c2845eSStanimir Varbanov if (!packet) 18609c2845eSStanimir Varbanov return; 18709c2845eSStanimir Varbanov 18809c2845eSStanimir Varbanov switch (pkt->event_id) { 18909c2845eSStanimir Varbanov case HFI_EVENT_SYS_ERROR: 19009c2845eSStanimir Varbanov event_sys_error(core, EVT_SYS_ERROR, pkt); 19109c2845eSStanimir Varbanov break; 19209c2845eSStanimir Varbanov case HFI_EVENT_SESSION_ERROR: 19309c2845eSStanimir Varbanov event_session_error(core, inst, pkt); 19409c2845eSStanimir Varbanov break; 19509c2845eSStanimir Varbanov case HFI_EVENT_SESSION_SEQUENCE_CHANGED: 19609c2845eSStanimir Varbanov event_seq_changed(core, inst, pkt); 19709c2845eSStanimir Varbanov break; 19809c2845eSStanimir Varbanov case HFI_EVENT_RELEASE_BUFFER_REFERENCE: 19909c2845eSStanimir Varbanov event_release_buffer_ref(core, inst, pkt); 20009c2845eSStanimir Varbanov break; 20109c2845eSStanimir Varbanov case HFI_EVENT_SESSION_PROPERTY_CHANGED: 20209c2845eSStanimir Varbanov break; 20309c2845eSStanimir Varbanov default: 20409c2845eSStanimir Varbanov break; 20509c2845eSStanimir Varbanov } 20609c2845eSStanimir Varbanov } 20709c2845eSStanimir Varbanov 20809c2845eSStanimir Varbanov static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst, 20909c2845eSStanimir Varbanov void *packet) 21009c2845eSStanimir Varbanov { 21109c2845eSStanimir Varbanov struct hfi_msg_sys_init_done_pkt *pkt = packet; 2121a73374aSStanimir Varbanov int rem_bytes; 2131a73374aSStanimir Varbanov u32 error; 21409c2845eSStanimir Varbanov 21509c2845eSStanimir Varbanov error = pkt->error_type; 21609c2845eSStanimir Varbanov if (error != HFI_ERR_NONE) 2171a73374aSStanimir Varbanov goto done; 21809c2845eSStanimir Varbanov 2191a73374aSStanimir Varbanov if (!pkt->num_properties) { 22009c2845eSStanimir Varbanov error = HFI_ERR_SYS_INVALID_PARAMETER; 2211a73374aSStanimir Varbanov goto done; 22209c2845eSStanimir Varbanov } 22309c2845eSStanimir Varbanov 22409c2845eSStanimir Varbanov rem_bytes = pkt->hdr.size - sizeof(*pkt) + sizeof(u32); 2251a73374aSStanimir Varbanov if (rem_bytes <= 0) { 22609c2845eSStanimir Varbanov /* missing property data */ 22709c2845eSStanimir Varbanov error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES; 2281a73374aSStanimir Varbanov goto done; 22909c2845eSStanimir Varbanov } 23009c2845eSStanimir Varbanov 2311a73374aSStanimir Varbanov error = hfi_parser(core, inst, pkt->data, rem_bytes); 23209c2845eSStanimir Varbanov 2331a73374aSStanimir Varbanov done: 23409c2845eSStanimir Varbanov core->error = error; 23509c2845eSStanimir Varbanov complete(&core->done); 23609c2845eSStanimir Varbanov } 23709c2845eSStanimir Varbanov 23809c2845eSStanimir Varbanov static void 23909c2845eSStanimir Varbanov sys_get_prop_image_version(struct device *dev, 24009c2845eSStanimir Varbanov struct hfi_msg_sys_property_info_pkt *pkt) 24109c2845eSStanimir Varbanov { 24209c2845eSStanimir Varbanov int req_bytes; 24309c2845eSStanimir Varbanov 24409c2845eSStanimir Varbanov req_bytes = pkt->hdr.size - sizeof(*pkt); 24509c2845eSStanimir Varbanov 24609c2845eSStanimir Varbanov if (req_bytes < 128 || !pkt->data[1] || pkt->num_properties > 1) 24709c2845eSStanimir Varbanov /* bad packet */ 24809c2845eSStanimir Varbanov return; 24909c2845eSStanimir Varbanov 2508c91dc08SStanimir Varbanov dev_dbg(dev, VDBGL "F/W version: %s\n", (u8 *)&pkt->data[1]); 25109c2845eSStanimir Varbanov } 25209c2845eSStanimir Varbanov 25309c2845eSStanimir Varbanov static void hfi_sys_property_info(struct venus_core *core, 25409c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 25509c2845eSStanimir Varbanov { 25609c2845eSStanimir Varbanov struct hfi_msg_sys_property_info_pkt *pkt = packet; 25709c2845eSStanimir Varbanov struct device *dev = core->dev; 25809c2845eSStanimir Varbanov 25909c2845eSStanimir Varbanov if (!pkt->num_properties) { 2608c91dc08SStanimir Varbanov dev_dbg(dev, VDBGL "no properties\n"); 26109c2845eSStanimir Varbanov return; 26209c2845eSStanimir Varbanov } 26309c2845eSStanimir Varbanov 26409c2845eSStanimir Varbanov switch (pkt->data[0]) { 26509c2845eSStanimir Varbanov case HFI_PROPERTY_SYS_IMAGE_VERSION: 26609c2845eSStanimir Varbanov sys_get_prop_image_version(dev, pkt); 26709c2845eSStanimir Varbanov break; 26809c2845eSStanimir Varbanov default: 2698c91dc08SStanimir Varbanov dev_dbg(dev, VDBGL "unknown property data\n"); 27009c2845eSStanimir Varbanov break; 27109c2845eSStanimir Varbanov } 27209c2845eSStanimir Varbanov } 27309c2845eSStanimir Varbanov 27409c2845eSStanimir Varbanov static void hfi_sys_rel_resource_done(struct venus_core *core, 27509c2845eSStanimir Varbanov struct venus_inst *inst, 27609c2845eSStanimir Varbanov void *packet) 27709c2845eSStanimir Varbanov { 27809c2845eSStanimir Varbanov struct hfi_msg_sys_release_resource_done_pkt *pkt = packet; 27909c2845eSStanimir Varbanov 28009c2845eSStanimir Varbanov core->error = pkt->error_type; 28109c2845eSStanimir Varbanov complete(&core->done); 28209c2845eSStanimir Varbanov } 28309c2845eSStanimir Varbanov 28409c2845eSStanimir Varbanov static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst, 28509c2845eSStanimir Varbanov void *packet) 28609c2845eSStanimir Varbanov { 28709c2845eSStanimir Varbanov struct hfi_msg_sys_ping_ack_pkt *pkt = packet; 28809c2845eSStanimir Varbanov 28909c2845eSStanimir Varbanov core->error = HFI_ERR_NONE; 29009c2845eSStanimir Varbanov 29109c2845eSStanimir Varbanov if (pkt->client_data != 0xbeef) 29209c2845eSStanimir Varbanov core->error = HFI_ERR_SYS_FATAL; 29309c2845eSStanimir Varbanov 29409c2845eSStanimir Varbanov complete(&core->done); 29509c2845eSStanimir Varbanov } 29609c2845eSStanimir Varbanov 29709c2845eSStanimir Varbanov static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst, 29809c2845eSStanimir Varbanov void *packet) 29909c2845eSStanimir Varbanov { 3008c91dc08SStanimir Varbanov dev_dbg(core->dev, VDBGL "sys idle\n"); 30109c2845eSStanimir Varbanov } 30209c2845eSStanimir Varbanov 30309c2845eSStanimir Varbanov static void hfi_sys_pc_prepare_done(struct venus_core *core, 30409c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 30509c2845eSStanimir Varbanov { 30609c2845eSStanimir Varbanov struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet; 30709c2845eSStanimir Varbanov 3088c91dc08SStanimir Varbanov dev_dbg(core->dev, VDBGL "pc prepare done (error %x)\n", 3098c91dc08SStanimir Varbanov pkt->error_type); 31009c2845eSStanimir Varbanov } 31109c2845eSStanimir Varbanov 31209c2845eSStanimir Varbanov static unsigned int 31309c2845eSStanimir Varbanov session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt, 31409c2845eSStanimir Varbanov struct hfi_profile_level *profile_level) 31509c2845eSStanimir Varbanov { 31609c2845eSStanimir Varbanov struct hfi_profile_level *hfi; 31709c2845eSStanimir Varbanov u32 req_bytes; 31809c2845eSStanimir Varbanov 31909c2845eSStanimir Varbanov req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 32009c2845eSStanimir Varbanov 32109c2845eSStanimir Varbanov if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level)) 32209c2845eSStanimir Varbanov /* bad packet */ 32309c2845eSStanimir Varbanov return HFI_ERR_SESSION_INVALID_PARAMETER; 32409c2845eSStanimir Varbanov 32509c2845eSStanimir Varbanov hfi = (struct hfi_profile_level *)&pkt->data[1]; 32609c2845eSStanimir Varbanov profile_level->profile = hfi->profile; 32709c2845eSStanimir Varbanov profile_level->level = hfi->level; 32809c2845eSStanimir Varbanov 32909c2845eSStanimir Varbanov return HFI_ERR_NONE; 33009c2845eSStanimir Varbanov } 33109c2845eSStanimir Varbanov 33209c2845eSStanimir Varbanov static unsigned int 33309c2845eSStanimir Varbanov session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt, 33409c2845eSStanimir Varbanov struct hfi_buffer_requirements *bufreq) 33509c2845eSStanimir Varbanov { 33609c2845eSStanimir Varbanov struct hfi_buffer_requirements *buf_req; 33709c2845eSStanimir Varbanov u32 req_bytes; 33809c2845eSStanimir Varbanov unsigned int idx = 0; 33909c2845eSStanimir Varbanov 34009c2845eSStanimir Varbanov req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 34109c2845eSStanimir Varbanov 34209c2845eSStanimir Varbanov if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[1]) 34309c2845eSStanimir Varbanov /* bad packet */ 34409c2845eSStanimir Varbanov return HFI_ERR_SESSION_INVALID_PARAMETER; 34509c2845eSStanimir Varbanov 34609c2845eSStanimir Varbanov buf_req = (struct hfi_buffer_requirements *)&pkt->data[1]; 34709c2845eSStanimir Varbanov if (!buf_req) 34809c2845eSStanimir Varbanov return HFI_ERR_SESSION_INVALID_PARAMETER; 34909c2845eSStanimir Varbanov 35009c2845eSStanimir Varbanov while (req_bytes) { 35109c2845eSStanimir Varbanov memcpy(&bufreq[idx], buf_req, sizeof(*bufreq)); 35209c2845eSStanimir Varbanov idx++; 35309c2845eSStanimir Varbanov 35409c2845eSStanimir Varbanov if (idx > HFI_BUFFER_TYPE_MAX) 35509c2845eSStanimir Varbanov return HFI_ERR_SESSION_INVALID_PARAMETER; 35609c2845eSStanimir Varbanov 35709c2845eSStanimir Varbanov req_bytes -= sizeof(struct hfi_buffer_requirements); 35809c2845eSStanimir Varbanov buf_req++; 35909c2845eSStanimir Varbanov } 36009c2845eSStanimir Varbanov 36109c2845eSStanimir Varbanov return HFI_ERR_NONE; 36209c2845eSStanimir Varbanov } 36309c2845eSStanimir Varbanov 36409c2845eSStanimir Varbanov static void hfi_session_prop_info(struct venus_core *core, 36509c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 36609c2845eSStanimir Varbanov { 36709c2845eSStanimir Varbanov struct hfi_msg_session_property_info_pkt *pkt = packet; 36809c2845eSStanimir Varbanov struct device *dev = core->dev; 36909c2845eSStanimir Varbanov union hfi_get_property *hprop = &inst->hprop; 37009c2845eSStanimir Varbanov unsigned int error = HFI_ERR_NONE; 37109c2845eSStanimir Varbanov 37209c2845eSStanimir Varbanov if (!pkt->num_properties) { 37309c2845eSStanimir Varbanov error = HFI_ERR_SESSION_INVALID_PARAMETER; 37409c2845eSStanimir Varbanov dev_err(dev, "%s: no properties\n", __func__); 37509c2845eSStanimir Varbanov goto done; 37609c2845eSStanimir Varbanov } 37709c2845eSStanimir Varbanov 37809c2845eSStanimir Varbanov switch (pkt->data[0]) { 37909c2845eSStanimir Varbanov case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: 38009c2845eSStanimir Varbanov memset(hprop->bufreq, 0, sizeof(hprop->bufreq)); 38109c2845eSStanimir Varbanov error = session_get_prop_buf_req(pkt, hprop->bufreq); 38209c2845eSStanimir Varbanov break; 38309c2845eSStanimir Varbanov case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: 38409c2845eSStanimir Varbanov memset(&hprop->profile_level, 0, sizeof(hprop->profile_level)); 38509c2845eSStanimir Varbanov error = session_get_prop_profile_level(pkt, 38609c2845eSStanimir Varbanov &hprop->profile_level); 38709c2845eSStanimir Varbanov break; 38809c2845eSStanimir Varbanov case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: 38909c2845eSStanimir Varbanov break; 39009c2845eSStanimir Varbanov default: 3918c91dc08SStanimir Varbanov dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->data[0]); 39209c2845eSStanimir Varbanov return; 39309c2845eSStanimir Varbanov } 39409c2845eSStanimir Varbanov 39509c2845eSStanimir Varbanov done: 39609c2845eSStanimir Varbanov inst->error = error; 39709c2845eSStanimir Varbanov complete(&inst->done); 39809c2845eSStanimir Varbanov } 39909c2845eSStanimir Varbanov 40009c2845eSStanimir Varbanov static void hfi_session_init_done(struct venus_core *core, 40109c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 40209c2845eSStanimir Varbanov { 40309c2845eSStanimir Varbanov struct hfi_msg_session_init_done_pkt *pkt = packet; 4041a73374aSStanimir Varbanov int rem_bytes; 4051a73374aSStanimir Varbanov u32 error; 40609c2845eSStanimir Varbanov 40709c2845eSStanimir Varbanov error = pkt->error_type; 40809c2845eSStanimir Varbanov if (error != HFI_ERR_NONE) 40909c2845eSStanimir Varbanov goto done; 41009c2845eSStanimir Varbanov 4111a73374aSStanimir Varbanov if (!IS_V1(core)) 41209c2845eSStanimir Varbanov goto done; 41309c2845eSStanimir Varbanov 4141a73374aSStanimir Varbanov rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32); 4151a73374aSStanimir Varbanov if (rem_bytes <= 0) { 4161a73374aSStanimir Varbanov error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; 4171a73374aSStanimir Varbanov goto done; 4181a73374aSStanimir Varbanov } 41909c2845eSStanimir Varbanov 4201a73374aSStanimir Varbanov error = hfi_parser(core, inst, pkt->data, rem_bytes); 42109c2845eSStanimir Varbanov done: 42209c2845eSStanimir Varbanov inst->error = error; 42309c2845eSStanimir Varbanov complete(&inst->done); 42409c2845eSStanimir Varbanov } 42509c2845eSStanimir Varbanov 42609c2845eSStanimir Varbanov static void hfi_session_load_res_done(struct venus_core *core, 42709c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 42809c2845eSStanimir Varbanov { 42909c2845eSStanimir Varbanov struct hfi_msg_session_load_resources_done_pkt *pkt = packet; 43009c2845eSStanimir Varbanov 43109c2845eSStanimir Varbanov inst->error = pkt->error_type; 43209c2845eSStanimir Varbanov complete(&inst->done); 43309c2845eSStanimir Varbanov } 43409c2845eSStanimir Varbanov 43509c2845eSStanimir Varbanov static void hfi_session_flush_done(struct venus_core *core, 43609c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 43709c2845eSStanimir Varbanov { 43809c2845eSStanimir Varbanov struct hfi_msg_session_flush_done_pkt *pkt = packet; 43909c2845eSStanimir Varbanov 44009c2845eSStanimir Varbanov inst->error = pkt->error_type; 44109c2845eSStanimir Varbanov complete(&inst->done); 44285872f86SStanimir Varbanov if (inst->ops->flush_done) 44385872f86SStanimir Varbanov inst->ops->flush_done(inst); 44409c2845eSStanimir Varbanov } 44509c2845eSStanimir Varbanov 44609c2845eSStanimir Varbanov static void hfi_session_etb_done(struct venus_core *core, 44709c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 44809c2845eSStanimir Varbanov { 44909c2845eSStanimir Varbanov struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet; 45009c2845eSStanimir Varbanov 45109c2845eSStanimir Varbanov inst->error = pkt->error_type; 45209c2845eSStanimir Varbanov inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag, 45309c2845eSStanimir Varbanov pkt->filled_len, pkt->offset, 0, 0, 0); 45409c2845eSStanimir Varbanov } 45509c2845eSStanimir Varbanov 45609c2845eSStanimir Varbanov static void hfi_session_ftb_done(struct venus_core *core, 45709c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 45809c2845eSStanimir Varbanov { 45909c2845eSStanimir Varbanov u32 session_type = inst->session_type; 46009c2845eSStanimir Varbanov u64 timestamp_us = 0; 46109c2845eSStanimir Varbanov u32 timestamp_hi = 0, timestamp_lo = 0; 46209c2845eSStanimir Varbanov unsigned int error; 46309c2845eSStanimir Varbanov u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0; 46409c2845eSStanimir Varbanov u32 pic_type = 0, buffer_type = 0, output_tag = -1; 46509c2845eSStanimir Varbanov 46609c2845eSStanimir Varbanov if (session_type == VIDC_SESSION_TYPE_ENC) { 46709c2845eSStanimir Varbanov struct hfi_msg_session_fbd_compressed_pkt *pkt = packet; 46809c2845eSStanimir Varbanov 46909c2845eSStanimir Varbanov timestamp_hi = pkt->time_stamp_hi; 47009c2845eSStanimir Varbanov timestamp_lo = pkt->time_stamp_lo; 47109c2845eSStanimir Varbanov hfi_flags = pkt->flags; 47209c2845eSStanimir Varbanov offset = pkt->offset; 47309c2845eSStanimir Varbanov filled_len = pkt->filled_len; 47409c2845eSStanimir Varbanov pic_type = pkt->picture_type; 47509c2845eSStanimir Varbanov output_tag = pkt->output_tag; 47609c2845eSStanimir Varbanov buffer_type = HFI_BUFFER_OUTPUT; 47709c2845eSStanimir Varbanov 47809c2845eSStanimir Varbanov error = pkt->error_type; 47909c2845eSStanimir Varbanov } else if (session_type == VIDC_SESSION_TYPE_DEC) { 48009c2845eSStanimir Varbanov struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = 48109c2845eSStanimir Varbanov packet; 48209c2845eSStanimir Varbanov 48309c2845eSStanimir Varbanov timestamp_hi = pkt->time_stamp_hi; 48409c2845eSStanimir Varbanov timestamp_lo = pkt->time_stamp_lo; 48509c2845eSStanimir Varbanov hfi_flags = pkt->flags; 48609c2845eSStanimir Varbanov offset = pkt->offset; 48709c2845eSStanimir Varbanov filled_len = pkt->filled_len; 48809c2845eSStanimir Varbanov pic_type = pkt->picture_type; 48909c2845eSStanimir Varbanov output_tag = pkt->output_tag; 49009c2845eSStanimir Varbanov 49109c2845eSStanimir Varbanov if (pkt->stream_id == 0) 49209c2845eSStanimir Varbanov buffer_type = HFI_BUFFER_OUTPUT; 49309c2845eSStanimir Varbanov else if (pkt->stream_id == 1) 49409c2845eSStanimir Varbanov buffer_type = HFI_BUFFER_OUTPUT2; 49509c2845eSStanimir Varbanov 49609c2845eSStanimir Varbanov error = pkt->error_type; 49709c2845eSStanimir Varbanov } else { 49809c2845eSStanimir Varbanov error = HFI_ERR_SESSION_INVALID_PARAMETER; 49909c2845eSStanimir Varbanov } 50009c2845eSStanimir Varbanov 5015f43f90aSStanimir Varbanov if (buffer_type != HFI_BUFFER_OUTPUT && 5025f43f90aSStanimir Varbanov buffer_type != HFI_BUFFER_OUTPUT2) 50309c2845eSStanimir Varbanov goto done; 50409c2845eSStanimir Varbanov 50509c2845eSStanimir Varbanov if (hfi_flags & HFI_BUFFERFLAG_EOS) 50609c2845eSStanimir Varbanov flags |= V4L2_BUF_FLAG_LAST; 50709c2845eSStanimir Varbanov 50809c2845eSStanimir Varbanov switch (pic_type) { 50909c2845eSStanimir Varbanov case HFI_PICTURE_IDR: 51009c2845eSStanimir Varbanov case HFI_PICTURE_I: 51109c2845eSStanimir Varbanov flags |= V4L2_BUF_FLAG_KEYFRAME; 51209c2845eSStanimir Varbanov break; 51309c2845eSStanimir Varbanov case HFI_PICTURE_P: 51409c2845eSStanimir Varbanov flags |= V4L2_BUF_FLAG_PFRAME; 51509c2845eSStanimir Varbanov break; 51609c2845eSStanimir Varbanov case HFI_PICTURE_B: 51709c2845eSStanimir Varbanov flags |= V4L2_BUF_FLAG_BFRAME; 51809c2845eSStanimir Varbanov break; 51909c2845eSStanimir Varbanov case HFI_FRAME_NOTCODED: 52009c2845eSStanimir Varbanov case HFI_UNUSED_PICT: 52109c2845eSStanimir Varbanov case HFI_FRAME_YUV: 52209c2845eSStanimir Varbanov default: 52309c2845eSStanimir Varbanov break; 52409c2845eSStanimir Varbanov } 52509c2845eSStanimir Varbanov 52609c2845eSStanimir Varbanov if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) { 52709c2845eSStanimir Varbanov timestamp_us = timestamp_hi; 52809c2845eSStanimir Varbanov timestamp_us = (timestamp_us << 32) | timestamp_lo; 52909c2845eSStanimir Varbanov } 53009c2845eSStanimir Varbanov 53109c2845eSStanimir Varbanov done: 53209c2845eSStanimir Varbanov inst->error = error; 53309c2845eSStanimir Varbanov inst->ops->buf_done(inst, buffer_type, output_tag, filled_len, 53409c2845eSStanimir Varbanov offset, flags, hfi_flags, timestamp_us); 53509c2845eSStanimir Varbanov } 53609c2845eSStanimir Varbanov 53709c2845eSStanimir Varbanov static void hfi_session_start_done(struct venus_core *core, 53809c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 53909c2845eSStanimir Varbanov { 54009c2845eSStanimir Varbanov struct hfi_msg_session_start_done_pkt *pkt = packet; 54109c2845eSStanimir Varbanov 54209c2845eSStanimir Varbanov inst->error = pkt->error_type; 54309c2845eSStanimir Varbanov complete(&inst->done); 54409c2845eSStanimir Varbanov } 54509c2845eSStanimir Varbanov 54609c2845eSStanimir Varbanov static void hfi_session_stop_done(struct venus_core *core, 54709c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 54809c2845eSStanimir Varbanov { 54909c2845eSStanimir Varbanov struct hfi_msg_session_stop_done_pkt *pkt = packet; 55009c2845eSStanimir Varbanov 55109c2845eSStanimir Varbanov inst->error = pkt->error_type; 55209c2845eSStanimir Varbanov complete(&inst->done); 55309c2845eSStanimir Varbanov } 55409c2845eSStanimir Varbanov 55509c2845eSStanimir Varbanov static void hfi_session_rel_res_done(struct venus_core *core, 55609c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 55709c2845eSStanimir Varbanov { 55809c2845eSStanimir Varbanov struct hfi_msg_session_release_resources_done_pkt *pkt = packet; 55909c2845eSStanimir Varbanov 56009c2845eSStanimir Varbanov inst->error = pkt->error_type; 56109c2845eSStanimir Varbanov complete(&inst->done); 56209c2845eSStanimir Varbanov } 56309c2845eSStanimir Varbanov 56409c2845eSStanimir Varbanov static void hfi_session_rel_buf_done(struct venus_core *core, 56509c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 56609c2845eSStanimir Varbanov { 56709c2845eSStanimir Varbanov struct hfi_msg_session_release_buffers_done_pkt *pkt = packet; 56809c2845eSStanimir Varbanov 56909c2845eSStanimir Varbanov inst->error = pkt->error_type; 57009c2845eSStanimir Varbanov complete(&inst->done); 57109c2845eSStanimir Varbanov } 57209c2845eSStanimir Varbanov 57309c2845eSStanimir Varbanov static void hfi_session_end_done(struct venus_core *core, 57409c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 57509c2845eSStanimir Varbanov { 57609c2845eSStanimir Varbanov struct hfi_msg_session_end_done_pkt *pkt = packet; 57709c2845eSStanimir Varbanov 57809c2845eSStanimir Varbanov inst->error = pkt->error_type; 57909c2845eSStanimir Varbanov complete(&inst->done); 58009c2845eSStanimir Varbanov } 58109c2845eSStanimir Varbanov 58209c2845eSStanimir Varbanov static void hfi_session_abort_done(struct venus_core *core, 58309c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 58409c2845eSStanimir Varbanov { 58509c2845eSStanimir Varbanov struct hfi_msg_sys_session_abort_done_pkt *pkt = packet; 58609c2845eSStanimir Varbanov 58709c2845eSStanimir Varbanov inst->error = pkt->error_type; 58809c2845eSStanimir Varbanov complete(&inst->done); 58909c2845eSStanimir Varbanov } 59009c2845eSStanimir Varbanov 59109c2845eSStanimir Varbanov static void hfi_session_get_seq_hdr_done(struct venus_core *core, 59209c2845eSStanimir Varbanov struct venus_inst *inst, void *packet) 59309c2845eSStanimir Varbanov { 59409c2845eSStanimir Varbanov struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet; 59509c2845eSStanimir Varbanov 59609c2845eSStanimir Varbanov inst->error = pkt->error_type; 59709c2845eSStanimir Varbanov complete(&inst->done); 59809c2845eSStanimir Varbanov } 59909c2845eSStanimir Varbanov 60009c2845eSStanimir Varbanov struct hfi_done_handler { 60109c2845eSStanimir Varbanov u32 pkt; 60209c2845eSStanimir Varbanov u32 pkt_sz; 60309c2845eSStanimir Varbanov u32 pkt_sz2; 60409c2845eSStanimir Varbanov void (*done)(struct venus_core *, struct venus_inst *, void *); 60509c2845eSStanimir Varbanov bool is_sys_pkt; 60609c2845eSStanimir Varbanov }; 60709c2845eSStanimir Varbanov 60809c2845eSStanimir Varbanov static const struct hfi_done_handler handlers[] = { 60909c2845eSStanimir Varbanov {.pkt = HFI_MSG_EVENT_NOTIFY, 61009c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt), 61109c2845eSStanimir Varbanov .done = hfi_event_notify, 61209c2845eSStanimir Varbanov }, 61309c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_INIT, 61409c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt), 61509c2845eSStanimir Varbanov .done = hfi_sys_init_done, 61609c2845eSStanimir Varbanov .is_sys_pkt = true, 61709c2845eSStanimir Varbanov }, 61809c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_PROPERTY_INFO, 61909c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt), 62009c2845eSStanimir Varbanov .done = hfi_sys_property_info, 62109c2845eSStanimir Varbanov .is_sys_pkt = true, 62209c2845eSStanimir Varbanov }, 62309c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_RELEASE_RESOURCE, 62409c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt), 62509c2845eSStanimir Varbanov .done = hfi_sys_rel_resource_done, 62609c2845eSStanimir Varbanov .is_sys_pkt = true, 62709c2845eSStanimir Varbanov }, 62809c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_PING_ACK, 62909c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt), 63009c2845eSStanimir Varbanov .done = hfi_sys_ping_done, 63109c2845eSStanimir Varbanov .is_sys_pkt = true, 63209c2845eSStanimir Varbanov }, 63309c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_IDLE, 63409c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt), 63509c2845eSStanimir Varbanov .done = hfi_sys_idle_done, 63609c2845eSStanimir Varbanov .is_sys_pkt = true, 63709c2845eSStanimir Varbanov }, 63809c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_PC_PREP, 63909c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt), 64009c2845eSStanimir Varbanov .done = hfi_sys_pc_prepare_done, 64109c2845eSStanimir Varbanov .is_sys_pkt = true, 64209c2845eSStanimir Varbanov }, 64309c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_SESSION_INIT, 64409c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt), 64509c2845eSStanimir Varbanov .done = hfi_session_init_done, 64609c2845eSStanimir Varbanov }, 64709c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_SESSION_END, 64809c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt), 64909c2845eSStanimir Varbanov .done = hfi_session_end_done, 65009c2845eSStanimir Varbanov }, 65109c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_LOAD_RESOURCES, 65209c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt), 65309c2845eSStanimir Varbanov .done = hfi_session_load_res_done, 65409c2845eSStanimir Varbanov }, 65509c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_START, 65609c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt), 65709c2845eSStanimir Varbanov .done = hfi_session_start_done, 65809c2845eSStanimir Varbanov }, 65909c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_STOP, 66009c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt), 66109c2845eSStanimir Varbanov .done = hfi_session_stop_done, 66209c2845eSStanimir Varbanov }, 66309c2845eSStanimir Varbanov {.pkt = HFI_MSG_SYS_SESSION_ABORT, 66409c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt), 66509c2845eSStanimir Varbanov .done = hfi_session_abort_done, 66609c2845eSStanimir Varbanov }, 66709c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_EMPTY_BUFFER, 66809c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt), 66909c2845eSStanimir Varbanov .done = hfi_session_etb_done, 67009c2845eSStanimir Varbanov }, 67109c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_FILL_BUFFER, 67209c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt), 67309c2845eSStanimir Varbanov .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt), 67409c2845eSStanimir Varbanov .done = hfi_session_ftb_done, 67509c2845eSStanimir Varbanov }, 67609c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_FLUSH, 67709c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt), 67809c2845eSStanimir Varbanov .done = hfi_session_flush_done, 67909c2845eSStanimir Varbanov }, 68009c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_PROPERTY_INFO, 68109c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt), 68209c2845eSStanimir Varbanov .done = hfi_session_prop_info, 68309c2845eSStanimir Varbanov }, 68409c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES, 68509c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt), 68609c2845eSStanimir Varbanov .done = hfi_session_rel_res_done, 68709c2845eSStanimir Varbanov }, 68809c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER, 68909c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt), 69009c2845eSStanimir Varbanov .done = hfi_session_get_seq_hdr_done, 69109c2845eSStanimir Varbanov }, 69209c2845eSStanimir Varbanov {.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS, 69309c2845eSStanimir Varbanov .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt), 69409c2845eSStanimir Varbanov .done = hfi_session_rel_buf_done, 69509c2845eSStanimir Varbanov }, 69609c2845eSStanimir Varbanov }; 69709c2845eSStanimir Varbanov 69809c2845eSStanimir Varbanov void hfi_process_watchdog_timeout(struct venus_core *core) 69909c2845eSStanimir Varbanov { 70009c2845eSStanimir Varbanov event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL); 70109c2845eSStanimir Varbanov } 70209c2845eSStanimir Varbanov 70309c2845eSStanimir Varbanov static struct venus_inst *to_instance(struct venus_core *core, u32 session_id) 70409c2845eSStanimir Varbanov { 70509c2845eSStanimir Varbanov struct venus_inst *inst; 70609c2845eSStanimir Varbanov 70709c2845eSStanimir Varbanov mutex_lock(&core->lock); 70809c2845eSStanimir Varbanov list_for_each_entry(inst, &core->instances, list) 70909c2845eSStanimir Varbanov if (hash32_ptr(inst) == session_id) { 71009c2845eSStanimir Varbanov mutex_unlock(&core->lock); 71109c2845eSStanimir Varbanov return inst; 71209c2845eSStanimir Varbanov } 71309c2845eSStanimir Varbanov mutex_unlock(&core->lock); 71409c2845eSStanimir Varbanov 71509c2845eSStanimir Varbanov return NULL; 71609c2845eSStanimir Varbanov } 71709c2845eSStanimir Varbanov 71809c2845eSStanimir Varbanov u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr) 71909c2845eSStanimir Varbanov { 72009c2845eSStanimir Varbanov const struct hfi_done_handler *handler; 72109c2845eSStanimir Varbanov struct device *dev = core->dev; 72209c2845eSStanimir Varbanov struct venus_inst *inst; 72309c2845eSStanimir Varbanov bool found = false; 72409c2845eSStanimir Varbanov unsigned int i; 72509c2845eSStanimir Varbanov 72609c2845eSStanimir Varbanov for (i = 0; i < ARRAY_SIZE(handlers); i++) { 72709c2845eSStanimir Varbanov handler = &handlers[i]; 72809c2845eSStanimir Varbanov if (handler->pkt != hdr->pkt_type) 72909c2845eSStanimir Varbanov continue; 73009c2845eSStanimir Varbanov found = true; 73109c2845eSStanimir Varbanov break; 73209c2845eSStanimir Varbanov } 73309c2845eSStanimir Varbanov 73409c2845eSStanimir Varbanov if (!found) 73509c2845eSStanimir Varbanov return hdr->pkt_type; 73609c2845eSStanimir Varbanov 73709c2845eSStanimir Varbanov if (hdr->size && hdr->size < handler->pkt_sz && 73809c2845eSStanimir Varbanov hdr->size < handler->pkt_sz2) { 73909c2845eSStanimir Varbanov dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n", 74009c2845eSStanimir Varbanov hdr->size, handler->pkt_sz, hdr->pkt_type); 74109c2845eSStanimir Varbanov 74209c2845eSStanimir Varbanov return hdr->pkt_type; 74309c2845eSStanimir Varbanov } 74409c2845eSStanimir Varbanov 74509c2845eSStanimir Varbanov if (handler->is_sys_pkt) { 74609c2845eSStanimir Varbanov inst = NULL; 74709c2845eSStanimir Varbanov } else { 74809c2845eSStanimir Varbanov struct hfi_session_pkt *pkt; 74909c2845eSStanimir Varbanov 75009c2845eSStanimir Varbanov pkt = (struct hfi_session_pkt *)hdr; 75109c2845eSStanimir Varbanov inst = to_instance(core, pkt->shdr.session_id); 75209c2845eSStanimir Varbanov 75309c2845eSStanimir Varbanov if (!inst) 75409c2845eSStanimir Varbanov dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n", 75509c2845eSStanimir Varbanov pkt->shdr.session_id, 75609c2845eSStanimir Varbanov handler ? handler->pkt : 0); 75709c2845eSStanimir Varbanov 75809c2845eSStanimir Varbanov /* 75909c2845eSStanimir Varbanov * Event of type HFI_EVENT_SYS_ERROR will not have any session 76009c2845eSStanimir Varbanov * associated with it 76109c2845eSStanimir Varbanov */ 76209c2845eSStanimir Varbanov if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) { 76309c2845eSStanimir Varbanov dev_err(dev, "got invalid session id:%x\n", 76409c2845eSStanimir Varbanov pkt->shdr.session_id); 76509c2845eSStanimir Varbanov goto invalid_session; 76609c2845eSStanimir Varbanov } 76709c2845eSStanimir Varbanov } 76809c2845eSStanimir Varbanov 76909c2845eSStanimir Varbanov handler->done(core, inst, hdr); 77009c2845eSStanimir Varbanov 77109c2845eSStanimir Varbanov invalid_session: 77209c2845eSStanimir Varbanov return hdr->pkt_type; 77309c2845eSStanimir Varbanov } 774