cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hfi_msgs.c (21055B)


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