123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780 |
- /*
- * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
- * Copyright (C) 2017 Linaro Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <linux/hash.h>
- #include <linux/list.h>
- #include <linux/slab.h>
- #include <media/videobuf2-v4l2.h>
- #include "core.h"
- #include "hfi.h"
- #include "hfi_helper.h"
- #include "hfi_msgs.h"
- #include "hfi_parser.h"
- static void event_seq_changed(struct venus_core *core, struct venus_inst *inst,
- struct hfi_msg_event_notify_pkt *pkt)
- {
- enum hfi_version ver = core->res->hfi_version;
- struct hfi_event_data event = {0};
- int num_properties_changed;
- struct hfi_framesize *frame_sz;
- struct hfi_profile_level *profile_level;
- struct hfi_bit_depth *pixel_depth;
- struct hfi_pic_struct *pic_struct;
- struct hfi_colour_space *colour_info;
- struct hfi_buffer_requirements *bufreq;
- struct hfi_extradata_input_crop *crop;
- u8 *data_ptr;
- u32 ptype;
- inst->error = HFI_ERR_NONE;
- switch (pkt->event_data1) {
- case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
- case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
- break;
- default:
- inst->error = HFI_ERR_SESSION_INVALID_PARAMETER;
- goto done;
- }
- event.event_type = pkt->event_data1;
- num_properties_changed = pkt->event_data2;
- if (!num_properties_changed) {
- inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
- goto done;
- }
- data_ptr = (u8 *)&pkt->ext_event_data[0];
- do {
- ptype = *((u32 *)data_ptr);
- switch (ptype) {
- case HFI_PROPERTY_PARAM_FRAME_SIZE:
- data_ptr += sizeof(u32);
- frame_sz = (struct hfi_framesize *)data_ptr;
- event.width = frame_sz->width;
- event.height = frame_sz->height;
- data_ptr += sizeof(*frame_sz);
- break;
- case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
- data_ptr += sizeof(u32);
- profile_level = (struct hfi_profile_level *)data_ptr;
- event.profile = profile_level->profile;
- event.level = profile_level->level;
- data_ptr += sizeof(*profile_level);
- break;
- case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
- data_ptr += sizeof(u32);
- pixel_depth = (struct hfi_bit_depth *)data_ptr;
- event.bit_depth = pixel_depth->bit_depth;
- data_ptr += sizeof(*pixel_depth);
- break;
- case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
- data_ptr += sizeof(u32);
- pic_struct = (struct hfi_pic_struct *)data_ptr;
- event.pic_struct = pic_struct->progressive_only;
- data_ptr += sizeof(*pic_struct);
- break;
- case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
- data_ptr += sizeof(u32);
- colour_info = (struct hfi_colour_space *)data_ptr;
- event.colour_space = colour_info->colour_space;
- data_ptr += sizeof(*colour_info);
- break;
- case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
- data_ptr += sizeof(u32);
- event.entropy_mode = *(u32 *)data_ptr;
- data_ptr += sizeof(u32);
- break;
- case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
- data_ptr += sizeof(u32);
- bufreq = (struct hfi_buffer_requirements *)data_ptr;
- event.buf_count = HFI_BUFREQ_COUNT_MIN(bufreq, ver);
- data_ptr += sizeof(*bufreq);
- break;
- case HFI_INDEX_EXTRADATA_INPUT_CROP:
- data_ptr += sizeof(u32);
- crop = (struct hfi_extradata_input_crop *)data_ptr;
- event.input_crop.left = crop->left;
- event.input_crop.top = crop->top;
- event.input_crop.width = crop->width;
- event.input_crop.height = crop->height;
- data_ptr += sizeof(*crop);
- break;
- default:
- break;
- }
- num_properties_changed--;
- } while (num_properties_changed > 0);
- done:
- inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
- }
- static void event_release_buffer_ref(struct venus_core *core,
- struct venus_inst *inst,
- struct hfi_msg_event_notify_pkt *pkt)
- {
- struct hfi_event_data event = {0};
- struct hfi_msg_event_release_buffer_ref_pkt *data;
- data = (struct hfi_msg_event_release_buffer_ref_pkt *)
- pkt->ext_event_data;
- event.event_type = HFI_EVENT_RELEASE_BUFFER_REFERENCE;
- event.packet_buffer = data->packet_buffer;
- event.extradata_buffer = data->extradata_buffer;
- event.tag = data->output_tag;
- inst->error = HFI_ERR_NONE;
- inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
- }
- static void event_sys_error(struct venus_core *core, u32 event,
- struct hfi_msg_event_notify_pkt *pkt)
- {
- if (pkt)
- dev_dbg(core->dev,
- "sys error (session id:%x, data1:%x, data2:%x)\n",
- pkt->shdr.session_id, pkt->event_data1,
- pkt->event_data2);
- core->core_ops->event_notify(core, event);
- }
- static void
- event_session_error(struct venus_core *core, struct venus_inst *inst,
- struct hfi_msg_event_notify_pkt *pkt)
- {
- struct device *dev = core->dev;
- dev_dbg(dev, "session error: event id:%x, session id:%x\n",
- pkt->event_data1, pkt->shdr.session_id);
- if (!inst)
- return;
- switch (pkt->event_data1) {
- /* non fatal session errors */
- case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
- case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
- case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
- case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
- inst->error = HFI_ERR_NONE;
- break;
- default:
- dev_err(dev, "session error: event id:%x (%x), session id:%x\n",
- pkt->event_data1, pkt->event_data2,
- pkt->shdr.session_id);
- inst->error = pkt->event_data1;
- inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL);
- break;
- }
- }
- static void hfi_event_notify(struct venus_core *core, struct venus_inst *inst,
- void *packet)
- {
- struct hfi_msg_event_notify_pkt *pkt = packet;
- if (!packet)
- return;
- switch (pkt->event_id) {
- case HFI_EVENT_SYS_ERROR:
- event_sys_error(core, EVT_SYS_ERROR, pkt);
- break;
- case HFI_EVENT_SESSION_ERROR:
- event_session_error(core, inst, pkt);
- break;
- case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
- event_seq_changed(core, inst, pkt);
- break;
- case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
- event_release_buffer_ref(core, inst, pkt);
- break;
- case HFI_EVENT_SESSION_PROPERTY_CHANGED:
- break;
- default:
- break;
- }
- }
- static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst,
- void *packet)
- {
- struct hfi_msg_sys_init_done_pkt *pkt = packet;
- int rem_bytes;
- u32 error;
- error = pkt->error_type;
- if (error != HFI_ERR_NONE)
- goto done;
- if (!pkt->num_properties) {
- error = HFI_ERR_SYS_INVALID_PARAMETER;
- goto done;
- }
- rem_bytes = pkt->hdr.size - sizeof(*pkt) + sizeof(u32);
- if (rem_bytes <= 0) {
- /* missing property data */
- error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
- goto done;
- }
- error = hfi_parser(core, inst, pkt->data, rem_bytes);
- done:
- core->error = error;
- complete(&core->done);
- }
- static void
- sys_get_prop_image_version(struct device *dev,
- struct hfi_msg_sys_property_info_pkt *pkt)
- {
- int req_bytes;
- req_bytes = pkt->hdr.size - sizeof(*pkt);
- if (req_bytes < 128 || !pkt->data[1] || pkt->num_properties > 1)
- /* bad packet */
- return;
- dev_dbg(dev, "F/W version: %s\n", (u8 *)&pkt->data[1]);
- }
- static void hfi_sys_property_info(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_sys_property_info_pkt *pkt = packet;
- struct device *dev = core->dev;
- if (!pkt->num_properties) {
- dev_dbg(dev, "%s: no properties\n", __func__);
- return;
- }
- switch (pkt->data[0]) {
- case HFI_PROPERTY_SYS_IMAGE_VERSION:
- sys_get_prop_image_version(dev, pkt);
- break;
- default:
- dev_dbg(dev, "%s: unknown property data\n", __func__);
- break;
- }
- }
- static void hfi_sys_rel_resource_done(struct venus_core *core,
- struct venus_inst *inst,
- void *packet)
- {
- struct hfi_msg_sys_release_resource_done_pkt *pkt = packet;
- core->error = pkt->error_type;
- complete(&core->done);
- }
- static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst,
- void *packet)
- {
- struct hfi_msg_sys_ping_ack_pkt *pkt = packet;
- core->error = HFI_ERR_NONE;
- if (pkt->client_data != 0xbeef)
- core->error = HFI_ERR_SYS_FATAL;
- complete(&core->done);
- }
- static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst,
- void *packet)
- {
- dev_dbg(core->dev, "sys idle\n");
- }
- static void hfi_sys_pc_prepare_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet;
- dev_dbg(core->dev, "pc prepare done (error %x)\n", pkt->error_type);
- }
- static unsigned int
- session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt,
- struct hfi_profile_level *profile_level)
- {
- struct hfi_profile_level *hfi;
- u32 req_bytes;
- req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
- if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level))
- /* bad packet */
- return HFI_ERR_SESSION_INVALID_PARAMETER;
- hfi = (struct hfi_profile_level *)&pkt->data[1];
- profile_level->profile = hfi->profile;
- profile_level->level = hfi->level;
- return HFI_ERR_NONE;
- }
- static unsigned int
- session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,
- struct hfi_buffer_requirements *bufreq)
- {
- struct hfi_buffer_requirements *buf_req;
- u32 req_bytes;
- unsigned int idx = 0;
- req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
- if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[1])
- /* bad packet */
- return HFI_ERR_SESSION_INVALID_PARAMETER;
- buf_req = (struct hfi_buffer_requirements *)&pkt->data[1];
- if (!buf_req)
- return HFI_ERR_SESSION_INVALID_PARAMETER;
- while (req_bytes) {
- memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
- idx++;
- if (idx > HFI_BUFFER_TYPE_MAX)
- return HFI_ERR_SESSION_INVALID_PARAMETER;
- req_bytes -= sizeof(struct hfi_buffer_requirements);
- buf_req++;
- }
- return HFI_ERR_NONE;
- }
- static void hfi_session_prop_info(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_property_info_pkt *pkt = packet;
- struct device *dev = core->dev;
- union hfi_get_property *hprop = &inst->hprop;
- unsigned int error = HFI_ERR_NONE;
- if (!pkt->num_properties) {
- error = HFI_ERR_SESSION_INVALID_PARAMETER;
- dev_err(dev, "%s: no properties\n", __func__);
- goto done;
- }
- switch (pkt->data[0]) {
- case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
- memset(hprop->bufreq, 0, sizeof(hprop->bufreq));
- error = session_get_prop_buf_req(pkt, hprop->bufreq);
- break;
- case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
- memset(&hprop->profile_level, 0, sizeof(hprop->profile_level));
- error = session_get_prop_profile_level(pkt,
- &hprop->profile_level);
- break;
- case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
- break;
- default:
- dev_dbg(dev, "%s: unknown property id:%x\n", __func__,
- pkt->data[0]);
- return;
- }
- done:
- inst->error = error;
- complete(&inst->done);
- }
- static void hfi_session_init_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_init_done_pkt *pkt = packet;
- int rem_bytes;
- u32 error;
- error = pkt->error_type;
- if (error != HFI_ERR_NONE)
- goto done;
- if (!IS_V1(core))
- goto done;
- rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32);
- if (rem_bytes <= 0) {
- error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
- goto done;
- }
- error = hfi_parser(core, inst, pkt->data, rem_bytes);
- done:
- inst->error = error;
- complete(&inst->done);
- }
- static void hfi_session_load_res_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_load_resources_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- static void hfi_session_flush_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_flush_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- static void hfi_session_etb_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag,
- pkt->filled_len, pkt->offset, 0, 0, 0);
- }
- static void hfi_session_ftb_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- u32 session_type = inst->session_type;
- u64 timestamp_us = 0;
- u32 timestamp_hi = 0, timestamp_lo = 0;
- unsigned int error;
- u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0;
- u32 pic_type = 0, buffer_type = 0, output_tag = -1;
- if (session_type == VIDC_SESSION_TYPE_ENC) {
- struct hfi_msg_session_fbd_compressed_pkt *pkt = packet;
- timestamp_hi = pkt->time_stamp_hi;
- timestamp_lo = pkt->time_stamp_lo;
- hfi_flags = pkt->flags;
- offset = pkt->offset;
- filled_len = pkt->filled_len;
- pic_type = pkt->picture_type;
- output_tag = pkt->output_tag;
- buffer_type = HFI_BUFFER_OUTPUT;
- error = pkt->error_type;
- } else if (session_type == VIDC_SESSION_TYPE_DEC) {
- struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt =
- packet;
- timestamp_hi = pkt->time_stamp_hi;
- timestamp_lo = pkt->time_stamp_lo;
- hfi_flags = pkt->flags;
- offset = pkt->offset;
- filled_len = pkt->filled_len;
- pic_type = pkt->picture_type;
- output_tag = pkt->output_tag;
- if (pkt->stream_id == 0)
- buffer_type = HFI_BUFFER_OUTPUT;
- else if (pkt->stream_id == 1)
- buffer_type = HFI_BUFFER_OUTPUT2;
- error = pkt->error_type;
- } else {
- error = HFI_ERR_SESSION_INVALID_PARAMETER;
- }
- if (buffer_type != HFI_BUFFER_OUTPUT &&
- buffer_type != HFI_BUFFER_OUTPUT2)
- goto done;
- if (hfi_flags & HFI_BUFFERFLAG_EOS)
- flags |= V4L2_BUF_FLAG_LAST;
- switch (pic_type) {
- case HFI_PICTURE_IDR:
- case HFI_PICTURE_I:
- flags |= V4L2_BUF_FLAG_KEYFRAME;
- break;
- case HFI_PICTURE_P:
- flags |= V4L2_BUF_FLAG_PFRAME;
- break;
- case HFI_PICTURE_B:
- flags |= V4L2_BUF_FLAG_BFRAME;
- break;
- case HFI_FRAME_NOTCODED:
- case HFI_UNUSED_PICT:
- case HFI_FRAME_YUV:
- default:
- break;
- }
- if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) {
- timestamp_us = timestamp_hi;
- timestamp_us = (timestamp_us << 32) | timestamp_lo;
- }
- done:
- inst->error = error;
- inst->ops->buf_done(inst, buffer_type, output_tag, filled_len,
- offset, flags, hfi_flags, timestamp_us);
- }
- static void hfi_session_start_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_start_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- static void hfi_session_stop_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_stop_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- static void hfi_session_rel_res_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_release_resources_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- static void hfi_session_rel_buf_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_release_buffers_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- static void hfi_session_end_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_end_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- static void hfi_session_abort_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_sys_session_abort_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- static void hfi_session_get_seq_hdr_done(struct venus_core *core,
- struct venus_inst *inst, void *packet)
- {
- struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet;
- inst->error = pkt->error_type;
- complete(&inst->done);
- }
- struct hfi_done_handler {
- u32 pkt;
- u32 pkt_sz;
- u32 pkt_sz2;
- void (*done)(struct venus_core *, struct venus_inst *, void *);
- bool is_sys_pkt;
- };
- static const struct hfi_done_handler handlers[] = {
- {.pkt = HFI_MSG_EVENT_NOTIFY,
- .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
- .done = hfi_event_notify,
- },
- {.pkt = HFI_MSG_SYS_INIT,
- .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
- .done = hfi_sys_init_done,
- .is_sys_pkt = true,
- },
- {.pkt = HFI_MSG_SYS_PROPERTY_INFO,
- .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
- .done = hfi_sys_property_info,
- .is_sys_pkt = true,
- },
- {.pkt = HFI_MSG_SYS_RELEASE_RESOURCE,
- .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt),
- .done = hfi_sys_rel_resource_done,
- .is_sys_pkt = true,
- },
- {.pkt = HFI_MSG_SYS_PING_ACK,
- .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt),
- .done = hfi_sys_ping_done,
- .is_sys_pkt = true,
- },
- {.pkt = HFI_MSG_SYS_IDLE,
- .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt),
- .done = hfi_sys_idle_done,
- .is_sys_pkt = true,
- },
- {.pkt = HFI_MSG_SYS_PC_PREP,
- .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt),
- .done = hfi_sys_pc_prepare_done,
- .is_sys_pkt = true,
- },
- {.pkt = HFI_MSG_SYS_SESSION_INIT,
- .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt),
- .done = hfi_session_init_done,
- },
- {.pkt = HFI_MSG_SYS_SESSION_END,
- .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt),
- .done = hfi_session_end_done,
- },
- {.pkt = HFI_MSG_SESSION_LOAD_RESOURCES,
- .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt),
- .done = hfi_session_load_res_done,
- },
- {.pkt = HFI_MSG_SESSION_START,
- .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt),
- .done = hfi_session_start_done,
- },
- {.pkt = HFI_MSG_SESSION_STOP,
- .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt),
- .done = hfi_session_stop_done,
- },
- {.pkt = HFI_MSG_SYS_SESSION_ABORT,
- .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt),
- .done = hfi_session_abort_done,
- },
- {.pkt = HFI_MSG_SESSION_EMPTY_BUFFER,
- .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt),
- .done = hfi_session_etb_done,
- },
- {.pkt = HFI_MSG_SESSION_FILL_BUFFER,
- .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt),
- .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt),
- .done = hfi_session_ftb_done,
- },
- {.pkt = HFI_MSG_SESSION_FLUSH,
- .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt),
- .done = hfi_session_flush_done,
- },
- {.pkt = HFI_MSG_SESSION_PROPERTY_INFO,
- .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt),
- .done = hfi_session_prop_info,
- },
- {.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES,
- .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt),
- .done = hfi_session_rel_res_done,
- },
- {.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER,
- .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt),
- .done = hfi_session_get_seq_hdr_done,
- },
- {.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS,
- .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt),
- .done = hfi_session_rel_buf_done,
- },
- };
- void hfi_process_watchdog_timeout(struct venus_core *core)
- {
- event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
- }
- static struct venus_inst *to_instance(struct venus_core *core, u32 session_id)
- {
- struct venus_inst *inst;
- mutex_lock(&core->lock);
- list_for_each_entry(inst, &core->instances, list)
- if (hash32_ptr(inst) == session_id) {
- mutex_unlock(&core->lock);
- return inst;
- }
- mutex_unlock(&core->lock);
- return NULL;
- }
- u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr)
- {
- const struct hfi_done_handler *handler;
- struct device *dev = core->dev;
- struct venus_inst *inst;
- bool found = false;
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(handlers); i++) {
- handler = &handlers[i];
- if (handler->pkt != hdr->pkt_type)
- continue;
- found = true;
- break;
- }
- if (!found)
- return hdr->pkt_type;
- if (hdr->size && hdr->size < handler->pkt_sz &&
- hdr->size < handler->pkt_sz2) {
- dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n",
- hdr->size, handler->pkt_sz, hdr->pkt_type);
- return hdr->pkt_type;
- }
- if (handler->is_sys_pkt) {
- inst = NULL;
- } else {
- struct hfi_session_pkt *pkt;
- pkt = (struct hfi_session_pkt *)hdr;
- inst = to_instance(core, pkt->shdr.session_id);
- if (!inst)
- dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n",
- pkt->shdr.session_id,
- handler ? handler->pkt : 0);
- /*
- * Event of type HFI_EVENT_SYS_ERROR will not have any session
- * associated with it
- */
- if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) {
- dev_err(dev, "got invalid session id:%x\n",
- pkt->shdr.session_id);
- goto invalid_session;
- }
- }
- handler->done(core, inst, hdr);
- invalid_session:
- return hdr->pkt_type;
- }
|