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.c (11084B)


      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/slab.h>
      7#include <linux/mutex.h>
      8#include <linux/list.h>
      9#include <linux/completion.h>
     10#include <linux/platform_device.h>
     11#include <linux/videodev2.h>
     12
     13#include "core.h"
     14#include "hfi.h"
     15#include "hfi_cmds.h"
     16#include "hfi_venus.h"
     17
     18#define TIMEOUT		msecs_to_jiffies(1000)
     19
     20static u32 to_codec_type(u32 pixfmt)
     21{
     22	switch (pixfmt) {
     23	case V4L2_PIX_FMT_H264:
     24	case V4L2_PIX_FMT_H264_NO_SC:
     25		return HFI_VIDEO_CODEC_H264;
     26	case V4L2_PIX_FMT_H263:
     27		return HFI_VIDEO_CODEC_H263;
     28	case V4L2_PIX_FMT_MPEG1:
     29		return HFI_VIDEO_CODEC_MPEG1;
     30	case V4L2_PIX_FMT_MPEG2:
     31		return HFI_VIDEO_CODEC_MPEG2;
     32	case V4L2_PIX_FMT_MPEG4:
     33		return HFI_VIDEO_CODEC_MPEG4;
     34	case V4L2_PIX_FMT_VC1_ANNEX_G:
     35	case V4L2_PIX_FMT_VC1_ANNEX_L:
     36		return HFI_VIDEO_CODEC_VC1;
     37	case V4L2_PIX_FMT_VP8:
     38		return HFI_VIDEO_CODEC_VP8;
     39	case V4L2_PIX_FMT_VP9:
     40		return HFI_VIDEO_CODEC_VP9;
     41	case V4L2_PIX_FMT_XVID:
     42		return HFI_VIDEO_CODEC_DIVX;
     43	case V4L2_PIX_FMT_HEVC:
     44		return HFI_VIDEO_CODEC_HEVC;
     45	default:
     46		return 0;
     47	}
     48}
     49
     50int hfi_core_init(struct venus_core *core)
     51{
     52	int ret = 0;
     53
     54	mutex_lock(&core->lock);
     55
     56	if (core->state >= CORE_INIT)
     57		goto unlock;
     58
     59	reinit_completion(&core->done);
     60
     61	ret = core->ops->core_init(core);
     62	if (ret)
     63		goto unlock;
     64
     65	ret = wait_for_completion_timeout(&core->done, TIMEOUT);
     66	if (!ret) {
     67		ret = -ETIMEDOUT;
     68		goto unlock;
     69	}
     70
     71	ret = 0;
     72
     73	if (core->error != HFI_ERR_NONE) {
     74		ret = -EIO;
     75		goto unlock;
     76	}
     77
     78	core->state = CORE_INIT;
     79unlock:
     80	mutex_unlock(&core->lock);
     81	return ret;
     82}
     83
     84int hfi_core_deinit(struct venus_core *core, bool blocking)
     85{
     86	int ret = 0, empty;
     87
     88	mutex_lock(&core->lock);
     89
     90	if (core->state == CORE_UNINIT)
     91		goto unlock;
     92
     93	empty = list_empty(&core->instances);
     94
     95	if (!empty && !blocking) {
     96		ret = -EBUSY;
     97		goto unlock;
     98	}
     99
    100	if (!empty) {
    101		mutex_unlock(&core->lock);
    102		wait_var_event(&core->insts_count,
    103			       !atomic_read(&core->insts_count));
    104		mutex_lock(&core->lock);
    105	}
    106
    107	if (!core->ops)
    108		goto unlock;
    109
    110	ret = core->ops->core_deinit(core);
    111
    112	if (!ret)
    113		core->state = CORE_UNINIT;
    114
    115unlock:
    116	mutex_unlock(&core->lock);
    117	return ret;
    118}
    119
    120int hfi_core_suspend(struct venus_core *core)
    121{
    122	if (core->state != CORE_INIT)
    123		return 0;
    124
    125	return core->ops->suspend(core);
    126}
    127
    128int hfi_core_resume(struct venus_core *core, bool force)
    129{
    130	if (!force && core->state != CORE_INIT)
    131		return 0;
    132
    133	return core->ops->resume(core);
    134}
    135
    136int hfi_core_trigger_ssr(struct venus_core *core, u32 type)
    137{
    138	return core->ops->core_trigger_ssr(core, type);
    139}
    140
    141int hfi_core_ping(struct venus_core *core)
    142{
    143	int ret;
    144
    145	mutex_lock(&core->lock);
    146
    147	ret = core->ops->core_ping(core, 0xbeef);
    148	if (ret)
    149		goto unlock;
    150
    151	ret = wait_for_completion_timeout(&core->done, TIMEOUT);
    152	if (!ret) {
    153		ret = -ETIMEDOUT;
    154		goto unlock;
    155	}
    156	ret = 0;
    157	if (core->error != HFI_ERR_NONE)
    158		ret = -ENODEV;
    159unlock:
    160	mutex_unlock(&core->lock);
    161	return ret;
    162}
    163
    164static int wait_session_msg(struct venus_inst *inst)
    165{
    166	int ret;
    167
    168	ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
    169	if (!ret)
    170		return -ETIMEDOUT;
    171
    172	if (inst->error != HFI_ERR_NONE)
    173		return -EIO;
    174
    175	return 0;
    176}
    177
    178int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops)
    179{
    180	struct venus_core *core = inst->core;
    181	bool max;
    182	int ret;
    183
    184	if (!ops)
    185		return -EINVAL;
    186
    187	inst->state = INST_UNINIT;
    188	init_completion(&inst->done);
    189	inst->ops = ops;
    190
    191	mutex_lock(&core->lock);
    192
    193	if (test_bit(0, &inst->core->sys_error)) {
    194		ret = -EIO;
    195		goto unlock;
    196	}
    197
    198	max = atomic_add_unless(&core->insts_count, 1,
    199				core->max_sessions_supported);
    200	if (!max) {
    201		ret = -EAGAIN;
    202	} else {
    203		list_add_tail(&inst->list, &core->instances);
    204		ret = 0;
    205	}
    206
    207unlock:
    208	mutex_unlock(&core->lock);
    209
    210	return ret;
    211}
    212EXPORT_SYMBOL_GPL(hfi_session_create);
    213
    214int hfi_session_init(struct venus_inst *inst, u32 pixfmt)
    215{
    216	struct venus_core *core = inst->core;
    217	const struct hfi_ops *ops = core->ops;
    218	int ret;
    219
    220	/*
    221	 * If core shutdown is in progress or if we are in system
    222	 * recovery, return an error as during system error recovery
    223	 * session_init() can't pass successfully
    224	 */
    225	mutex_lock(&core->lock);
    226	if (!core->ops || test_bit(0, &inst->core->sys_error)) {
    227		mutex_unlock(&core->lock);
    228		return -EIO;
    229	}
    230	mutex_unlock(&core->lock);
    231
    232	if (inst->state != INST_UNINIT)
    233		return -EALREADY;
    234
    235	inst->hfi_codec = to_codec_type(pixfmt);
    236	reinit_completion(&inst->done);
    237
    238	ret = ops->session_init(inst, inst->session_type, inst->hfi_codec);
    239	if (ret)
    240		return ret;
    241
    242	ret = wait_session_msg(inst);
    243	if (ret)
    244		return ret;
    245
    246	inst->state = INST_INIT;
    247
    248	return 0;
    249}
    250EXPORT_SYMBOL_GPL(hfi_session_init);
    251
    252void hfi_session_destroy(struct venus_inst *inst)
    253{
    254	struct venus_core *core = inst->core;
    255
    256	mutex_lock(&core->lock);
    257	list_del_init(&inst->list);
    258	if (atomic_dec_and_test(&core->insts_count))
    259		wake_up_var(&core->insts_count);
    260	mutex_unlock(&core->lock);
    261}
    262EXPORT_SYMBOL_GPL(hfi_session_destroy);
    263
    264int hfi_session_deinit(struct venus_inst *inst)
    265{
    266	const struct hfi_ops *ops = inst->core->ops;
    267	int ret;
    268
    269	if (inst->state == INST_UNINIT)
    270		return 0;
    271
    272	if (inst->state < INST_INIT)
    273		return -EINVAL;
    274
    275	if (test_bit(0, &inst->core->sys_error))
    276		goto done;
    277
    278	reinit_completion(&inst->done);
    279
    280	ret = ops->session_end(inst);
    281	if (ret)
    282		return ret;
    283
    284	ret = wait_session_msg(inst);
    285	if (ret)
    286		return ret;
    287
    288done:
    289	inst->state = INST_UNINIT;
    290
    291	return 0;
    292}
    293EXPORT_SYMBOL_GPL(hfi_session_deinit);
    294
    295int hfi_session_start(struct venus_inst *inst)
    296{
    297	const struct hfi_ops *ops = inst->core->ops;
    298	int ret;
    299
    300	if (test_bit(0, &inst->core->sys_error))
    301		return -EIO;
    302
    303	if (inst->state != INST_LOAD_RESOURCES)
    304		return -EINVAL;
    305
    306	reinit_completion(&inst->done);
    307
    308	ret = ops->session_start(inst);
    309	if (ret)
    310		return ret;
    311
    312	ret = wait_session_msg(inst);
    313	if (ret)
    314		return ret;
    315
    316	inst->state = INST_START;
    317
    318	return 0;
    319}
    320EXPORT_SYMBOL_GPL(hfi_session_start);
    321
    322int hfi_session_stop(struct venus_inst *inst)
    323{
    324	const struct hfi_ops *ops = inst->core->ops;
    325	int ret;
    326
    327	if (test_bit(0, &inst->core->sys_error))
    328		return -EIO;
    329
    330	if (inst->state != INST_START)
    331		return -EINVAL;
    332
    333	reinit_completion(&inst->done);
    334
    335	ret = ops->session_stop(inst);
    336	if (ret)
    337		return ret;
    338
    339	ret = wait_session_msg(inst);
    340	if (ret)
    341		return ret;
    342
    343	inst->state = INST_STOP;
    344
    345	return 0;
    346}
    347EXPORT_SYMBOL_GPL(hfi_session_stop);
    348
    349int hfi_session_continue(struct venus_inst *inst)
    350{
    351	struct venus_core *core = inst->core;
    352
    353	if (test_bit(0, &inst->core->sys_error))
    354		return -EIO;
    355
    356	if (core->res->hfi_version == HFI_VERSION_1XX)
    357		return 0;
    358
    359	return core->ops->session_continue(inst);
    360}
    361EXPORT_SYMBOL_GPL(hfi_session_continue);
    362
    363int hfi_session_abort(struct venus_inst *inst)
    364{
    365	const struct hfi_ops *ops = inst->core->ops;
    366	int ret;
    367
    368	if (test_bit(0, &inst->core->sys_error))
    369		return -EIO;
    370
    371	reinit_completion(&inst->done);
    372
    373	ret = ops->session_abort(inst);
    374	if (ret)
    375		return ret;
    376
    377	ret = wait_session_msg(inst);
    378	if (ret)
    379		return ret;
    380
    381	return 0;
    382}
    383EXPORT_SYMBOL_GPL(hfi_session_abort);
    384
    385int hfi_session_load_res(struct venus_inst *inst)
    386{
    387	const struct hfi_ops *ops = inst->core->ops;
    388	int ret;
    389
    390	if (test_bit(0, &inst->core->sys_error))
    391		return -EIO;
    392
    393	if (inst->state != INST_INIT)
    394		return -EINVAL;
    395
    396	reinit_completion(&inst->done);
    397
    398	ret = ops->session_load_res(inst);
    399	if (ret)
    400		return ret;
    401
    402	ret = wait_session_msg(inst);
    403	if (ret)
    404		return ret;
    405
    406	inst->state = INST_LOAD_RESOURCES;
    407
    408	return 0;
    409}
    410
    411int hfi_session_unload_res(struct venus_inst *inst)
    412{
    413	const struct hfi_ops *ops = inst->core->ops;
    414	int ret;
    415
    416	if (test_bit(0, &inst->core->sys_error))
    417		return -EIO;
    418
    419	if (inst->state != INST_STOP)
    420		return -EINVAL;
    421
    422	reinit_completion(&inst->done);
    423
    424	ret = ops->session_release_res(inst);
    425	if (ret)
    426		return ret;
    427
    428	ret = wait_session_msg(inst);
    429	if (ret)
    430		return ret;
    431
    432	inst->state = INST_RELEASE_RESOURCES;
    433
    434	return 0;
    435}
    436EXPORT_SYMBOL_GPL(hfi_session_unload_res);
    437
    438int hfi_session_flush(struct venus_inst *inst, u32 type, bool block)
    439{
    440	const struct hfi_ops *ops = inst->core->ops;
    441	int ret;
    442
    443	if (test_bit(0, &inst->core->sys_error))
    444		return -EIO;
    445
    446	reinit_completion(&inst->done);
    447
    448	ret = ops->session_flush(inst, type);
    449	if (ret)
    450		return ret;
    451
    452	if (block) {
    453		ret = wait_session_msg(inst);
    454		if (ret)
    455			return ret;
    456	}
    457
    458	return 0;
    459}
    460EXPORT_SYMBOL_GPL(hfi_session_flush);
    461
    462int hfi_session_set_buffers(struct venus_inst *inst, struct hfi_buffer_desc *bd)
    463{
    464	const struct hfi_ops *ops = inst->core->ops;
    465
    466	if (test_bit(0, &inst->core->sys_error))
    467		return -EIO;
    468
    469	return ops->session_set_buffers(inst, bd);
    470}
    471
    472int hfi_session_unset_buffers(struct venus_inst *inst,
    473			      struct hfi_buffer_desc *bd)
    474{
    475	const struct hfi_ops *ops = inst->core->ops;
    476	int ret;
    477
    478	if (test_bit(0, &inst->core->sys_error))
    479		return -EIO;
    480
    481	reinit_completion(&inst->done);
    482
    483	ret = ops->session_unset_buffers(inst, bd);
    484	if (ret)
    485		return ret;
    486
    487	if (!bd->response_required)
    488		return 0;
    489
    490	ret = wait_session_msg(inst);
    491	if (ret)
    492		return ret;
    493
    494	return 0;
    495}
    496
    497int hfi_session_get_property(struct venus_inst *inst, u32 ptype,
    498			     union hfi_get_property *hprop)
    499{
    500	const struct hfi_ops *ops = inst->core->ops;
    501	int ret;
    502
    503	if (test_bit(0, &inst->core->sys_error))
    504		return -EIO;
    505
    506	if (inst->state < INST_INIT || inst->state >= INST_STOP)
    507		return -EINVAL;
    508
    509	reinit_completion(&inst->done);
    510
    511	ret = ops->session_get_property(inst, ptype);
    512	if (ret)
    513		return ret;
    514
    515	ret = wait_session_msg(inst);
    516	if (ret)
    517		return ret;
    518
    519	*hprop = inst->hprop;
    520
    521	return 0;
    522}
    523EXPORT_SYMBOL_GPL(hfi_session_get_property);
    524
    525int hfi_session_set_property(struct venus_inst *inst, u32 ptype, void *pdata)
    526{
    527	const struct hfi_ops *ops = inst->core->ops;
    528
    529	if (test_bit(0, &inst->core->sys_error))
    530		return -EIO;
    531
    532	if (inst->state < INST_INIT || inst->state >= INST_STOP)
    533		return -EINVAL;
    534
    535	return ops->session_set_property(inst, ptype, pdata);
    536}
    537EXPORT_SYMBOL_GPL(hfi_session_set_property);
    538
    539int hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd)
    540{
    541	const struct hfi_ops *ops = inst->core->ops;
    542
    543	if (test_bit(0, &inst->core->sys_error))
    544		return -EIO;
    545
    546	if (fd->buffer_type == HFI_BUFFER_INPUT)
    547		return ops->session_etb(inst, fd);
    548	else if (fd->buffer_type == HFI_BUFFER_OUTPUT ||
    549		 fd->buffer_type == HFI_BUFFER_OUTPUT2)
    550		return ops->session_ftb(inst, fd);
    551
    552	return -EINVAL;
    553}
    554EXPORT_SYMBOL_GPL(hfi_session_process_buf);
    555
    556irqreturn_t hfi_isr_thread(int irq, void *dev_id)
    557{
    558	struct venus_core *core = dev_id;
    559
    560	return core->ops->isr_thread(core);
    561}
    562
    563irqreturn_t hfi_isr(int irq, void *dev)
    564{
    565	struct venus_core *core = dev;
    566
    567	return core->ops->isr(core);
    568}
    569
    570int hfi_create(struct venus_core *core, const struct hfi_core_ops *ops)
    571{
    572	int ret;
    573
    574	if (!ops)
    575		return -EINVAL;
    576
    577	atomic_set(&core->insts_count, 0);
    578	core->core_ops = ops;
    579	core->state = CORE_UNINIT;
    580	init_completion(&core->done);
    581	pkt_set_version(core->res->hfi_version);
    582	ret = venus_hfi_create(core);
    583
    584	return ret;
    585}
    586
    587void hfi_destroy(struct venus_core *core)
    588{
    589	venus_hfi_destroy(core);
    590}
    591
    592void hfi_reinit(struct venus_core *core)
    593{
    594	venus_hfi_queues_reinit(core);
    595}