From da53e790e2f71ee7dae472408264ead18e5ffa5a Mon Sep 17 00:00:00 2001 From: George Shen Date: Sat, 21 Mar 2020 16:47:36 -0700 Subject: [PATCH] msm: cvp: Optimize synX handling in cvp driver Make synX handling in kernel independent of CVP features. It also simplified handling logic. Change-Id: I598d2c78f0fea4463c5801b5db945b74c071ebab Signed-off-by: George Shen --- drivers/media/platform/msm/cvp/Makefile | 3 +- drivers/media/platform/msm/cvp/cvp_comm_def.h | 24 + drivers/media/platform/msm/cvp/msm_cvp.c | 516 ++-------------- drivers/media/platform/msm/cvp/msm_cvp_core.c | 139 +---- drivers/media/platform/msm/cvp/msm_cvp_core.h | 1 + .../media/platform/msm/cvp/msm_cvp_internal.h | 38 -- .../media/platform/msm/cvp/msm_cvp_ioctl.c | 154 ++--- drivers/media/platform/msm/cvp/msm_cvp_synx.c | 565 ++++++++++++++++++ drivers/media/platform/msm/cvp/msm_cvp_synx.h | 54 ++ include/uapi/media/msm_cvp_private.h | 53 +- 10 files changed, 784 insertions(+), 763 deletions(-) create mode 100644 drivers/media/platform/msm/cvp/cvp_comm_def.h create mode 100644 drivers/media/platform/msm/cvp/msm_cvp_synx.c create mode 100644 drivers/media/platform/msm/cvp/msm_cvp_synx.h diff --git a/drivers/media/platform/msm/cvp/Makefile b/drivers/media/platform/msm/cvp/Makefile index c135359250cf..f3ee23607a7b 100644 --- a/drivers/media/platform/msm/cvp/Makefile +++ b/drivers/media/platform/msm/cvp/Makefile @@ -17,6 +17,7 @@ msm-cvp-objs := cvp.o \ cvp_core_hfi.o \ msm_cvp_clocks.o \ msm_cvp_dsp.o \ - msm_cvp_buf.o + msm_cvp_buf.o \ + msm_cvp_synx.o obj-$(CONFIG_MSM_CVP) := msm-cvp.o diff --git a/drivers/media/platform/msm/cvp/cvp_comm_def.h b/drivers/media/platform/msm/cvp/cvp_comm_def.h new file mode 100644 index 000000000000..1e590fdc6e64 --- /dev/null +++ b/drivers/media/platform/msm/cvp/cvp_comm_def.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _MSM_COMM_DEF_H_ +#define _MSM_COMM_DEF_H_ + +#include + +enum op_mode { + OP_NORMAL, + OP_DRAINING, + OP_FLUSH, + OP_INVALID, +}; + +enum queue_state { + QUEUE_INIT, + QUEUE_ACTIVE = 1, + QUEUE_STOP = 2, + QUEUE_INVALID, +}; +#endif diff --git a/drivers/media/platform/msm/cvp/msm_cvp.c b/drivers/media/platform/msm/cvp/msm_cvp.c index 459356675b15..b9d4f826dc07 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp.c +++ b/drivers/media/platform/msm/cvp/msm_cvp.c @@ -275,19 +275,16 @@ static bool cvp_fence_wait(struct cvp_fence_queue *q, return true; } -static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, +static int cvp_fence_dme(struct msm_cvp_inst *inst, + struct cvp_fence_command *fc, struct cvp_hfi_cmd_session_hdr *pkt) { - int i; int rc = 0; unsigned long timeout; - int h_synx; u64 ktid; - unsigned long timeout_ms = 1000; int synx_state = SYNX_STATE_SIGNALED_SUCCESS; struct cvp_hfi_device *hdev; struct cvp_session_queue *sq; - struct synx_session ssid; u32 hfi_err = HFI_ERR_NONE; struct cvp_hfi_msg_session_hdr *hdr; @@ -295,29 +292,10 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, hdev = inst->core->device; sq = &inst->session_queue_fence; - ssid = inst->synx_session_id; ktid = pkt->client_data.kdata; - i = 0; - while (i < HFI_DME_BUF_NUM - 1) { - h_synx = synx[i]; - if (h_synx) { - rc = synx_wait(ssid, h_synx, timeout_ms); - if (rc) { - dprintk(CVP_ERR, "%s %s: synx_wait %d failed\n", - current->comm, __func__, i); - synx_state = SYNX_STATE_SIGNALED_ERROR; - goto exit; - } - /* - * Increase loop count to skip fence - * waiting on downscale image where i == 1. - */ - if (i == FENCE_DME_ICA_ENABLED_IDX) - ++i; - } - ++i; - } + if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) + goto exit; rc = call_hfi_op(hdev, session_send, (void *)inst->session, (struct cvp_kmd_hfi_packet *)pkt); @@ -354,40 +332,21 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, } exit: - if (synx[FENCE_DME_ICA_ENABLED_IDX]) { - h_synx = synx[FENCE_DME_DS_IDX]; - - rc = synx_signal(ssid, h_synx, synx_state); - if (rc) { - dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n", - current->comm, __func__, FENCE_DME_DS_IDX); - synx_state = SYNX_STATE_SIGNALED_ERROR; - } - } - - h_synx = synx[FENCE_DME_OUTPUT_IDX]; - rc = synx_signal(ssid, h_synx, synx_state); - if (rc) - dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n", - current->comm, __func__, FENCE_DME_OUTPUT_IDX); + rc = cvp_synx_ops(inst, CVP_OUTPUT_SYNX, fc, &synx_state); return rc; } -static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, +static int cvp_fence_proc(struct msm_cvp_inst *inst, + struct cvp_fence_command *fc, struct cvp_hfi_cmd_session_hdr *pkt) { - int i; int rc = 0; unsigned long timeout; - int h_synx; u64 ktid; - unsigned long timeout_ms = 1000; int synx_state = SYNX_STATE_SIGNALED_SUCCESS; struct cvp_hfi_device *hdev; struct cvp_session_queue *sq; - struct synx_session ssid; - u32 in, out; u32 hfi_err = HFI_ERR_NONE; struct cvp_hfi_msg_session_hdr *hdr; @@ -395,34 +354,10 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, hdev = inst->core->device; sq = &inst->session_queue_fence; - ssid = inst->synx_session_id; ktid = pkt->client_data.kdata; - in = synx[0] >> 16; - out = synx[0] & 0xFFFF; - - i = 1; - while (i <= in) { - h_synx = synx[i]; - if (h_synx) { - rc = synx_wait(ssid, h_synx, timeout_ms); - if (rc) { - synx_state = synx_get_status(ssid, h_synx); - if (synx_state == SYNX_STATE_SIGNALED_CANCEL) { - dprintk(CVP_DBG, - "%s: synx_wait %d cancel %d state %d\n", - current->comm, i, rc, synx_state); - } else { - dprintk(CVP_ERR, - "%s: synx_wait %d failed %d state %d\n", - current->comm, i, rc, synx_state); - synx_state = SYNX_STATE_SIGNALED_ERROR; - } - goto exit; - } - } - ++i; - } + if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) + goto exit; rc = call_hfi_op(hdev, session_send, (void *)inst->session, (struct cvp_kmd_hfi_packet *)pkt); @@ -455,19 +390,7 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, } exit: - i = in + 1; - while (i <= in + out) { - h_synx = synx[i]; - if (h_synx) { - rc = synx_signal(ssid, h_synx, synx_state); - if (rc) { - dprintk(CVP_ERR, "%s: synx_signal %d failed\n", - current->comm, i); - synx_state = SYNX_STATE_SIGNALED_ERROR; - } - } - ++i; - } + rc = cvp_synx_ops(inst, CVP_OUTPUT_SYNX, fc, &synx_state); return rc; } @@ -498,119 +421,6 @@ static void cvp_free_fence_data(struct cvp_fence_command *f) f = NULL; } -static int cvp_import_synx(struct msm_cvp_inst *inst, u32 type, u32 *fence, - u32 *synx) -{ - int rc = 0; - int i; - int start = 0, end = 0; - struct cvp_fence_type *f; - struct synx_import_params params; - s32 h_synx; - struct synx_session ssid; - - f = (struct cvp_fence_type *)fence; - ssid = inst->synx_session_id; - - switch (type) { - case HFI_CMD_SESSION_CVP_DME_FRAME: - { - start = 0; - end = HFI_DME_BUF_NUM; - break; - } - case HFI_CMD_SESSION_CVP_FD_FRAME: - { - u32 in = fence[0]; - u32 out = fence[1]; - - if (in > MAX_HFI_FENCE_SIZE || out > MAX_HFI_FENCE_SIZE - || in > MAX_HFI_FENCE_SIZE - out) { - dprintk(CVP_ERR, "%s: failed!\n", __func__); - rc = -EINVAL; - return rc; - } - - synx[0] = (in << 16) | out; - start = 1; - end = in + out + 1; - break; - } - default: - dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); - rc = -EINVAL; - return rc; - } - - for (i = start; i < end; ++i) { - h_synx = f[i].h_synx; - - if (h_synx) { - params.h_synx = h_synx; - params.secure_key = f[i].secure_key; - params.new_h_synx = &synx[i]; - - rc = synx_import(ssid, ¶ms); - if (rc) { - dprintk(CVP_ERR, - "%s: synx_import failed\n", - __func__); - return rc; - } - } - } - - return rc; -} - -static int cvp_release_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx) -{ - int rc = 0; - int i; - s32 h_synx; - struct synx_session ssid; - int start = 0, end = 0; - - ssid = inst->synx_session_id; - - switch (type) { - case HFI_CMD_SESSION_CVP_DME_FRAME: - { - start = 0; - end = HFI_DME_BUF_NUM; - - break; - } - case HFI_CMD_SESSION_CVP_FD_FRAME: - { - u32 in = synx[0] >> 16; - u32 out = synx[0] & 0xFFFF; - - start = 1; - end = in + out + 1; - - break; - } - default: - dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); - rc = -EINVAL; - return rc; - } - - for (i = start; i < end; ++i) { - h_synx = synx[i]; - if (h_synx) { - rc = synx_release(ssid, h_synx); - if (rc) - dprintk(CVP_ERR, - "%s: synx_release %d failed\n", - __func__, i); - } - } - - return rc; -} - static int cvp_fence_thread(void *data) { int rc = 0; @@ -653,10 +463,10 @@ wait: switch (f->type) { case HFI_CMD_SESSION_CVP_DME_FRAME: - rc = cvp_fence_dme(inst, synx, pkt); + rc = cvp_fence_dme(inst, f, pkt); break; case HFI_CMD_SESSION_CVP_FD_FRAME: - rc = cvp_fence_proc(inst, synx, pkt); + rc = cvp_fence_proc(inst, f, pkt); break; default: dprintk(CVP_ERR, "%s: unknown hfi cmd type 0x%x\n", @@ -667,7 +477,7 @@ wait: } mutex_lock(&q->lock); - cvp_release_synx(inst, f->type, synx); + cvp_release_synx(inst, f); list_del_init(&f->list); mutex_unlock(&q->lock); @@ -690,6 +500,8 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, int rc = 0; int idx; struct cvp_kmd_hfi_fence_packet *fence_pkt; + struct cvp_kmd_hfi_synx_packet *synx_pkt; + struct cvp_kmd_fence_ctrl *kfc; struct cvp_hfi_cmd_session_hdr *pkt; unsigned int offset, buf_num, in_offset, in_buf_num; struct msm_cvp_inst *s; @@ -724,7 +536,6 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, fence_pkt = &arg->data.hfi_fence_pkt; pkt = (struct cvp_hfi_cmd_session_hdr *)&fence_pkt->pkt_data; - fence = (u32 *)&fence_pkt->fence_data; idx = get_pkt_index((struct cvp_hal_session_cmd_pkt *)pkt); if (idx < 0 || pkt->size > MAX_HFI_FENCE_OFFSET) { @@ -751,16 +562,29 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, goto exit; f->type = cvp_hfi_defs[idx].type; - f->frame_id = arg->data.hfi_fence_pkt.frame_id; f->mode = OP_NORMAL; + synx_pkt = &arg->data.hfi_synx_pkt; + if (synx_pkt->fence_data[0] != 0xFEEDFACE) { + fence = (u32 *)&fence_pkt->fence_data; + f->frame_id = arg->data.hfi_fence_pkt.frame_id; + } else { + kfc = &synx_pkt->fc; + fence = (u32 *)&kfc->fences; + f->frame_id = kfc->frame_id; + f->signature = 0xFEEDFACE; + f->num_fences = kfc->num_fences; + f->output_index = kfc->output_index; + } + + dprintk(CVP_DBG, "%s: frameID %llu\n", __func__, f->frame_id); memcpy(f->pkt, pkt, pkt->size); f->pkt->client_data.kdata |= FENCE_BIT; - rc = cvp_import_synx(inst, f->type, fence, f->synx); + rc = cvp_import_synx(inst, f, fence); if (rc) { kfree(f); goto exit; @@ -890,77 +714,6 @@ static void aggregate_power_update(struct msm_cvp_core *core, rt_pwr->bw_sum += bw_sum[1]; } - -static void aggregate_power_request(struct msm_cvp_core *core, - struct cvp_power_level *nrt_pwr, - struct cvp_power_level *rt_pwr, - unsigned int max_clk_rate) -{ - struct msm_cvp_inst *inst; - int i; - unsigned long core_sum[2] = {0}, ctlr_sum[2] = {0}, fw_sum[2] = {0}; - unsigned long op_core_max[2] = {0}, op_ctlr_max[2] = {0}; - unsigned long op_fw_max[2] = {0}, bw_sum[2] = {0}, op_bw_max[2] = {0}; - - list_for_each_entry(inst, &core->instances, list) { - if (inst->state == MSM_CVP_CORE_INVALID || - inst->state == MSM_CVP_CORE_UNINIT || - is_subblock_profile_existed(inst)) - continue; - if (inst->prop.priority <= CVP_RT_PRIO_THRESHOLD) { - /* Non-realtime session use index 0 */ - i = 0; - } else { - i = 1; - } - dprintk(CVP_PROF, "pwrReq sess %pK core %u ctl %u fw %u\n", - inst, inst->power.clock_cycles_a, - inst->power.clock_cycles_b, - inst->power.reserved[0]); - dprintk(CVP_PROF, "pwrReq op_core %u op_ctl %u op_fw %u\n", - inst->power.reserved[1], - inst->power.reserved[2], - inst->power.reserved[3]); - - core_sum[i] += inst->power.clock_cycles_a; - ctlr_sum[i] += inst->power.clock_cycles_b; - fw_sum[i] += inst->power.reserved[0]; - op_core_max[i] = - (op_core_max[i] >= inst->power.reserved[1]) ? - op_core_max[i] : inst->power.reserved[1]; - op_ctlr_max[i] = - (op_ctlr_max[i] >= inst->power.reserved[2]) ? - op_ctlr_max[i] : inst->power.reserved[2]; - op_fw_max[i] = - (op_fw_max[i] >= inst->power.reserved[3]) ? - op_fw_max[i] : inst->power.reserved[3]; - bw_sum[i] += inst->power.ddr_bw; - op_bw_max[i] = - (op_bw_max[i] >= inst->power.reserved[4]) ? - op_bw_max[i] : inst->power.reserved[4]; - } - - for (i = 0; i < 2; i++) { - core_sum[i] = max_3(core_sum[i], ctlr_sum[i], fw_sum[i]); - op_core_max[i] = max_3(op_core_max[i], - op_ctlr_max[i], op_fw_max[i]); - op_core_max[i] = - (op_core_max[i] > max_clk_rate) ? - max_clk_rate : op_core_max[i]; - bw_sum[i] = (bw_sum[i] >= op_bw_max[i]) ? - bw_sum[i] : op_bw_max[i]; - } - - nrt_pwr->core_sum += core_sum[0]; - nrt_pwr->op_core_sum = (nrt_pwr->op_core_sum >= op_core_max[0]) ? - nrt_pwr->op_core_sum : op_core_max[0]; - nrt_pwr->bw_sum += bw_sum[0]; - rt_pwr->core_sum += core_sum[1]; - rt_pwr->op_core_sum = (rt_pwr->op_core_sum >= op_core_max[1]) ? - rt_pwr->op_core_sum : op_core_max[1]; - rt_pwr->bw_sum += bw_sum[1]; -} - /** * adjust_bw_freqs(): calculate CVP clock freq and bw required to sustain * required use case. @@ -999,10 +752,6 @@ static int adjust_bw_freqs(void) max_bw = bus->range[1]; min_bw = max_bw/10; - aggregate_power_request(core, &nrt_pwr, &rt_pwr, cvp_max_rate); - dprintk(CVP_DBG, "PwrReq nrt %u %u rt %u %u\n", - nrt_pwr.core_sum, nrt_pwr.op_core_sum, - rt_pwr.core_sum, rt_pwr.op_core_sum); aggregate_power_update(core, &nrt_pwr, &rt_pwr, cvp_max_rate); dprintk(CVP_DBG, "PwrUpdate nrt %u %u rt %u %u\n", nrt_pwr.core_sum, nrt_pwr.op_core_sum, @@ -1062,64 +811,6 @@ static int adjust_bw_freqs(void) return rc; } -/** - * Use of cvp_kmd_request_power structure - * clock_cycles_a: CVP core clock freq - * clock_cycles_b: CVP controller clock freq - * ddr_bw: b/w vote in Bps - * reserved[0]: CVP firmware required clock freq - * reserved[1]: CVP core operational clock freq - * reserved[2]: CVP controller operational clock freq - * reserved[3]: CVP firmware operational clock freq - * reserved[4]: CVP operational b/w vote - * - * session's power record only saves normalized freq or b/w vote - */ -static int msm_cvp_request_power(struct msm_cvp_inst *inst, - struct cvp_kmd_request_power *power) -{ - int rc = 0; - struct msm_cvp_core *core; - struct msm_cvp_inst *s; - - if (!inst || !power) { - dprintk(CVP_ERR, "%s: invalid params\n", __func__); - return -EINVAL; - } - - s = cvp_get_inst_validate(inst->core, inst); - if (!s) - return -ECONNRESET; - - inst->cur_cmd_type = CVP_KMD_REQUEST_POWER; - core = inst->core; - - mutex_lock(&core->lock); - - memcpy(&inst->power, power, sizeof(*power)); - - /* Normalize CVP controller clock freqs */ - inst->power.clock_cycles_b = div_by_1dot5(inst->power.clock_cycles_b); - inst->power.reserved[0] = div_by_1dot5(inst->power.reserved[0]); - inst->power.reserved[2] = div_by_1dot5(inst->power.reserved[2]); - inst->power.reserved[3] = div_by_1dot5(inst->power.reserved[3]); - - /* Convert bps to KBps */ - inst->power.ddr_bw = inst->power.ddr_bw >> 10; - - rc = adjust_bw_freqs(); - if (rc) { - memset(&inst->power, 0x0, sizeof(inst->power)); - dprintk(CVP_ERR, "Instance %pK power request out of range\n"); - } - - mutex_unlock(&core->lock); - inst->cur_cmd_type = 0; - cvp_put_inst(s); - - return rc; -} - static int msm_cvp_update_power(struct msm_cvp_inst *inst) { int rc = 0; @@ -1423,7 +1114,7 @@ static int msm_cvp_get_sysprop(struct msm_cvp_inst *inst, struct cvp_kmd_sys_properties *props = &arg->data.sys_properties; struct cvp_hfi_device *hdev; struct iris_hfi_device *hfi; - int rc = 0; + int i, rc = 0; if (!inst || !inst->core || !inst->core->device) { dprintk(CVP_ERR, "%s: invalid params\n", __func__); @@ -1433,16 +1124,18 @@ static int msm_cvp_get_sysprop(struct msm_cvp_inst *inst, hdev = inst->core->device; hfi = hdev->hfi_device_data; - switch (props->prop_data.prop_type) { - case CVP_KMD_PROP_HFI_VERSION: - { - props->prop_data.data = hfi->version; - break; - } - default: - dprintk(CVP_ERR, "unrecognized sys property %d\n", - props->prop_data.prop_type); - rc = -EFAULT; + for (i = 0; i < props->prop_num; i++) { + switch (props->prop_data[i].prop_type) { + case CVP_KMD_PROP_HFI_VERSION: + { + props->prop_data[i].data = hfi->version; + break; + } + default: + dprintk(CVP_ERR, "unrecognized sys property %d\n", + props->prop_data[i].prop_type); + rc = -EFAULT; + } } return rc; } @@ -1466,7 +1159,7 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst, return -E2BIG; } - prop_array = &arg->data.sys_properties.prop_data; + prop_array = &arg->data.sys_properties.prop_data[0]; session_prop = &inst->prop; for (i = 0; i < props->prop_num; i++) { @@ -1542,107 +1235,6 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst, return rc; } -static int cvp_cancel_input_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx) -{ - int rc = 0; - int i; - int h_synx; - struct synx_session ssid; - int start = 0, end = 0; - int synx_state = SYNX_STATE_SIGNALED_CANCEL; - - ssid = inst->synx_session_id; - - switch (type) { - case HFI_CMD_SESSION_CVP_DME_FRAME: - { - start = 1; - end = HFI_DME_BUF_NUM - 1; - break; - } - case HFI_CMD_SESSION_CVP_FD_FRAME: - { - u32 in, out; - - in = synx[0] >> 16; - out = synx[0] & 0xFFFF; - - start = 1; - end = in + 1; - break; - } - default: - dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); - rc = -EINVAL; - return rc; - } - - for (i = start; i < end; ++i) { - h_synx = synx[i]; - if (h_synx) { - rc = synx_signal(ssid, h_synx, synx_state); - if (rc && rc != -EALREADY) { - dprintk(CVP_ERR, "%s: synx_signal %d failed\n", - __func__, i); - synx_state = SYNX_STATE_SIGNALED_ERROR; - } - } - } - - return rc; -} - -static int cvp_cancel_output_synx(struct msm_cvp_inst *inst, u32 type, - u32 *synx) -{ - int rc = 0; - int i; - int h_synx; - struct synx_session ssid; - int start = 0, end = 0; - int synx_state = SYNX_STATE_SIGNALED_CANCEL; - - ssid = inst->synx_session_id; - - switch (type) { - case HFI_CMD_SESSION_CVP_DME_FRAME: - { - start = FENCE_DME_OUTPUT_IDX; - end = FENCE_DME_OUTPUT_IDX + 1; - break; - } - case HFI_CMD_SESSION_CVP_FD_FRAME: - { - u32 in, out; - - in = synx[0] >> 16; - out = synx[0] & 0xFFFF; - - start = in + 1; - end = in + out + 1; - break; - } - default: - dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); - rc = -EINVAL; - return rc; - } - - for (i = start; i < end; ++i) { - h_synx = synx[i]; - if (h_synx) { - rc = synx_signal(ssid, h_synx, synx_state); - if (rc) { - dprintk(CVP_ERR, "%s: synx_signal %d failed\n", - __func__, i); - synx_state = SYNX_STATE_SIGNALED_ERROR; - } - } - } - - return rc; -} - static int cvp_drain_fence_cmd_queue_partial(struct msm_cvp_inst *inst) { unsigned long wait_time; @@ -1783,8 +1375,8 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) list_del_init(&f->list); msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); - cvp_cancel_output_synx(inst, f->type, f->synx); - cvp_release_synx(inst, f->type, f->synx); + cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f); + cvp_release_synx(inst, f); cvp_free_fence_data(f); } @@ -1795,7 +1387,7 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) __func__, ktid); dprintk(CVP_DBG, "%s: flush frameID %llu from sched_list\n", __func__, f->frame_id); - cvp_cancel_input_synx(inst, f->type, f->synx); + cvp_cancel_synx(inst, CVP_INPUT_SYNX, f); } mutex_unlock(&q->lock); @@ -1899,8 +1491,8 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) list_del_init(&f->list); msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); - cvp_cancel_output_synx(inst, f->type, f->synx); - cvp_release_synx(inst, f->type, f->synx); + cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f); + cvp_release_synx(inst, f); cvp_free_fence_data(f); } @@ -1914,7 +1506,7 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) __func__, ktid); dprintk(CVP_DBG, "%s: flush frameID %llu from sched_list\n", __func__, f->frame_id); - cvp_cancel_input_synx(inst, f->type, f->synx); + cvp_cancel_synx(inst, CVP_INPUT_SYNX, f); } mutex_unlock(&q->lock); @@ -1962,14 +1554,6 @@ int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg) rc = msm_cvp_get_session_info(inst, session); break; } - case CVP_KMD_REQUEST_POWER: - { - struct cvp_kmd_request_power *power = - (struct cvp_kmd_request_power *)&arg->data.req_power; - - rc = msm_cvp_request_power(inst, power); - break; - } case CVP_KMD_UPDATE_POWER: { rc = msm_cvp_update_power(inst); diff --git a/drivers/media/platform/msm/cvp/msm_cvp_core.c b/drivers/media/platform/msm/cvp/msm_cvp_core.c index 1fce69b97e0c..4722ca802d31 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_core.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_core.c @@ -29,144 +29,7 @@ int msm_cvp_est_cycles(struct cvp_kmd_usecase_desc *cvp_desc, struct cvp_kmd_request_power *cvp_voting) { - unsigned int cvp_cycles = 0; - unsigned int hcd_cycles = 0; - unsigned int dme_cycles = 0; - unsigned int ds_cycles = 0; - unsigned int ncc_cycles = 0; - unsigned int num_16x16_blocks = 0; - - unsigned int cvp_bw = 0; - unsigned int ds_pixel_read = 0; - unsigned int ds_pixel_write = 0; - unsigned int hcd_pixel_read = 0; - unsigned int hcd_stats_write = 0; - unsigned int dme_pixel_read = 0; - unsigned int ncc_pixel_read = 0; - unsigned int process_width = 0; - unsigned int process_height = 0; - - if (!cvp_desc || !cvp_voting) { - dprintk(CVP_ERR, "%s: invalid args\n", __func__); - return -EINVAL; - } - - if (cvp_desc->is_downscale) { - num_16x16_blocks = (cvp_desc->fullres_width>>4) - * (cvp_desc->fullres_height>>4); - ds_cycles = NUM_CYCLES16X16_DS_FRAME * num_16x16_blocks; - process_width = cvp_desc->downscale_width; - process_height = cvp_desc->downscale_height; - num_16x16_blocks = (process_width>>4)*(process_height>>4); - hcd_cycles = NUM_CYCLES16X16_HCD_FRAME * num_16x16_blocks; - /*Estimate downscale output (always UBWC) BW stats*/ - if (cvp_desc->fullres_width <= 1920) { - /*w*h/1.58=w*h*(81/128)*/ - ds_pixel_write = ((process_width*process_height*81)>>7); - } else { - /*w*h/2.38=w*h*(54/128)*/ - ds_pixel_write = ((process_width*process_height*54)>>7); - } - /*Estimate downscale input BW stats based on colorfmt*/ - switch (cvp_desc->colorfmt) { - case COLOR_FMT_NV12: - { - /*w*h*1.5*/ - ds_pixel_read = ((cvp_desc->fullres_width - * cvp_desc->fullres_height * 3)>>1); - break; - } - case COLOR_FMT_P010: - { - /*w*h*2*1.5*/ - ds_pixel_read = cvp_desc->fullres_width - * cvp_desc->fullres_height * 3; - break; - } - case COLOR_FMT_NV12_UBWC: - { - /*w*h*1.5/factor(factor=width>1920?2.38:1.58)*/ - if (cvp_desc->fullres_width <= 1920) { - /*w*h*1.5/1.58 = w*h*121/128*/ - ds_pixel_read = ((cvp_desc->fullres_width - * cvp_desc->fullres_height * 121)>>7); - } else { - /*w*h*1.5/1.61 = w*h*119/128*/ - ds_pixel_read = ((cvp_desc->fullres_width - * cvp_desc->fullres_height * 119)>>7); - } - break; - } - case COLOR_FMT_NV12_BPP10_UBWC: - { - /*w*h*1.33*1.5/factor(factor=width>1920?2.38:1.58)*/ - if (cvp_desc->fullres_width <= 1920) { - /*w*h*1.33*1.5/1.58 = w*h*5/4*/ - ds_pixel_read = ((cvp_desc->fullres_width - * cvp_desc->fullres_height * 5)>>2); - } else { - /*w*h*1.33*1.5/1.61 = w*h*79/64*/ - ds_pixel_read = ((cvp_desc->fullres_width - * cvp_desc->fullres_height * 79)>>6); - } - break; - } - default: - dprintk(CVP_ERR, "Defaulting to linear P010\n"); - /*w*h*1.5*2 COLOR_FMT_P010*/ - ds_pixel_read = (cvp_desc->fullres_width - * cvp_desc->fullres_height * 3); - } - } else { - process_width = cvp_desc->fullres_width; - process_height = cvp_desc->fullres_height; - num_16x16_blocks = (process_width>>4)*(process_height>>4); - hcd_cycles = NUM_CYCLES16X16_HCD_FRAME * num_16x16_blocks; - } - - dme_cycles = NUM_CYCLES16X16_DME_FRAME * NUM_DME_MAX_FEATURE_POINTS; - ncc_cycles = NUM_CYCLES16X16_NCC_FRAME * NUM_DME_MAX_FEATURE_POINTS; - - cvp_cycles = dme_cycles + ds_cycles + hcd_cycles + ncc_cycles; - cvp_cycles = cvp_cycles + (cvp_cycles>>CYCLES_MARGIN_IN_POWEROF2); - - cvp_voting->clock_cycles_a = cvp_cycles * cvp_desc->fps; - cvp_voting->clock_cycles_b = 0; - cvp_voting->reserved[0] = NUM_CYCLESFW_FRAME * cvp_desc->fps; - cvp_voting->reserved[1] = cvp_cycles * cvp_desc->op_rate; - cvp_voting->reserved[2] = 0; - cvp_voting->reserved[3] = NUM_CYCLESFW_FRAME*cvp_desc->op_rate; - - if (process_width <= 1920) { - /*w*h*1.5(for filter fetch overhead)/1.58=w*h*(3/2)*(5/8)*/ - hcd_pixel_read = ((process_width * process_height * 15)>>4); - /*num_16x16_blocks*8*4*/ - hcd_stats_write = (num_16x16_blocks<<5); - /*NUM_DME_MAX_FEATURE_POINTS*96*48/1.58*/ - dme_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 2880; - /*NUM_DME_MAX_FEATURE_POINTS*(18/8+1)*32*8*2/1.58*/ - ncc_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 1040; - } else { - /*w*h*1.5(for filter fetch overhead)/2.38=w*h*(3/2)*(54/128)*/ - hcd_pixel_read = ((process_width * process_height * 81)>>7); - /*num_16x16_blocks*8*4*/ - hcd_stats_write = (num_16x16_blocks<<5); - /*NUM_DME_MAX_FEATURE_POINTS*96*48/2.38*/ - dme_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 1944; - /*NUM_DME_MAX_FEATURE_POINTS*(18/8+1)*32*8*2/2.38*/ - ncc_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 702; - } - - cvp_bw = ds_pixel_read + ds_pixel_write + hcd_pixel_read - + hcd_stats_write + dme_pixel_read + ncc_pixel_read; - - cvp_voting->ddr_bw = cvp_bw * cvp_desc->fps; - cvp_voting->reserved[4] = cvp_bw * cvp_desc->op_rate; - - dprintk(CVP_DBG, "%s Voting cycles_a, b, bw: %d %d %d\n", __func__, - cvp_voting->clock_cycles_a, cvp_voting->clock_cycles_b, - cvp_voting->ddr_bw); - + dprintk(CVP_ERR, "Deprecated cvp func %s\n", __func__); return 0; } EXPORT_SYMBOL(msm_cvp_est_cycles); diff --git a/drivers/media/platform/msm/cvp/msm_cvp_core.h b/drivers/media/platform/msm/cvp/msm_cvp_core.h index be1730963b92..3c09cc9fe38d 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_core.h +++ b/drivers/media/platform/msm/cvp/msm_cvp_core.h @@ -15,6 +15,7 @@ #include #include #include "msm_cvp_buf.h" +#include "msm_cvp_synx.h" enum core_id { MSM_CORE_CVP = 0, diff --git a/drivers/media/platform/msm/cvp/msm_cvp_internal.h b/drivers/media/platform/msm/cvp/msm_cvp_internal.h index a82315383e86..daeadb3f9cbf 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_internal.h +++ b/drivers/media/platform/msm/cvp/msm_cvp_internal.h @@ -194,13 +194,6 @@ struct cvp_session_msg { struct cvp_hfi_msg_session_hdr pkt; }; -enum queue_state { - QUEUE_INIT, - QUEUE_ACTIVE = 1, - QUEUE_STOP = 2, - QUEUE_INVALID, -}; - struct cvp_session_queue { spinlock_t lock; enum queue_state state; @@ -232,22 +225,6 @@ struct cvp_session_prop { u32 ddr_op_cache; }; -enum op_mode { - OP_NORMAL, - OP_DRAINING, - OP_FLUSH, - OP_INVALID, -}; - -struct cvp_fence_queue { - struct mutex lock; - enum queue_state state; - enum op_mode mode; - struct list_head wait_list; - wait_queue_head_t wq; - struct list_head sched_list; -}; - enum cvp_event_t { CVP_NO_EVENT, CVP_SSR_EVENT = 1, @@ -312,27 +289,12 @@ struct msm_cvp_inst { enum msm_cvp_modes flags; struct msm_cvp_capability capability; struct kref kref; - struct cvp_kmd_request_power power; struct cvp_session_prop prop; u32 cur_cmd_type; struct synx_session synx_session_id; struct cvp_fence_queue fence_cmd_queue; }; -struct cvp_fence_type { - s32 h_synx; - u32 secure_key; -}; - -struct cvp_fence_command { - struct list_head list; - u64 frame_id; - enum op_mode mode; - u32 type; - u32 synx[MAX_HFI_FENCE_SIZE/2]; - struct cvp_hfi_cmd_session_hdr *pkt; -}; - extern struct msm_cvp_drv *cvp_driver; void cvp_handle_cmd_response(enum hal_command_response cmd, void *data); diff --git a/drivers/media/platform/msm/cvp/msm_cvp_ioctl.c b/drivers/media/platform/msm/cvp/msm_cvp_ioctl.c index f014b36ba298..8721b3ac3fe0 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_ioctl.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_ioctl.c @@ -40,9 +40,9 @@ set_default_pkt_hdr: static int _get_fence_pkt_hdr_from_user(struct cvp_kmd_arg __user *up, struct cvp_hal_session_cmd_pkt *pkt_hdr) { - struct cvp_kmd_hfi_fence_packet *u; + struct cvp_kmd_hfi_synx_packet __user *u; - u = &up->data.hfi_fence_pkt; + u = &up->data.hfi_synx_pkt; if (get_user(pkt_hdr->size, &u->pkt_data[0])) return -EFAULT; @@ -73,21 +73,27 @@ static int _copy_pkt_from_user(struct cvp_kmd_arg *kp, return 0; } -/* Size is in unit of u32 */ -static int _copy_fence_pkt_from_user(struct cvp_kmd_arg *kp, - struct cvp_kmd_arg __user *up, - unsigned int size) +static int _copy_synx_data_from_user( + struct cvp_kmd_hfi_synx_packet *k, + struct cvp_kmd_hfi_synx_packet __user *u) { - struct cvp_kmd_hfi_fence_packet *k; - struct cvp_kmd_hfi_fence_packet __user *u; int i; - k = &kp->data.hfi_fence_pkt; - u = &up->data.hfi_fence_pkt; - for (i = 0; i < MAX_HFI_FENCE_OFFSET; i++) { - if (get_user(k->pkt_data[i], &u->pkt_data[i])) + for (i = 0; i < MAX_FENCE_DATA_SIZE; i++) { + if (get_user(k->fence_data[i], &u->fence_data[i])) return -EFAULT; } + + return 0; +} + +/* Size is in unit of u32 */ +static int _copy_fence_data_from_user_deprecate( + struct cvp_kmd_hfi_fence_packet *k, + struct cvp_kmd_hfi_fence_packet __user *u) +{ + int i; + for (i = 0; i < MAX_HFI_FENCE_SIZE; i++) { if (get_user(k->fence_data[i], &u->fence_data[i])) return -EFAULT; @@ -98,10 +104,34 @@ static int _copy_fence_pkt_from_user(struct cvp_kmd_arg *kp, return -EFAULT; } - return 0; } +static int _copy_fence_pkt_from_user(struct cvp_kmd_arg *kp, + struct cvp_kmd_arg __user *up) +{ struct cvp_kmd_hfi_synx_packet *k; + struct cvp_kmd_hfi_synx_packet __user *u; + struct cvp_kmd_hfi_fence_packet __user *u1; + int i; + + k = &kp->data.hfi_synx_pkt; + u = &up->data.hfi_synx_pkt; + u1 = &up->data.hfi_fence_pkt; + + for (i = 0; i < MAX_HFI_PKT_SIZE; i++) + if (get_user(k->pkt_data[i], &u->pkt_data[i])) + return -EFAULT; + + if (get_user(k->fence_data[0], &u->fence_data[0])) + return -EFAULT; + + if (k->fence_data[0] == 0xFEEDFACE) + return _copy_synx_data_from_user(k, u); + else + return _copy_fence_data_from_user_deprecate( + (struct cvp_kmd_hfi_fence_packet *)k, u1); +} + static int _copy_frameid_from_user(struct cvp_kmd_arg *kp, struct cvp_kmd_arg __user *up) { @@ -150,35 +180,35 @@ static int _copy_pkt_to_user(struct cvp_kmd_arg *kp, } static int _copy_fence_pkt_to_user(struct cvp_kmd_arg *kp, - struct cvp_kmd_arg __user *up, - unsigned int size) + struct cvp_kmd_arg __user *up) { - struct cvp_kmd_hfi_fence_packet *k, *u; + struct cvp_kmd_hfi_synx_packet *k; + struct cvp_kmd_hfi_synx_packet __user *u; int i; - k = &kp->data.hfi_fence_pkt; - u = &up->data.hfi_fence_pkt; - for (i = 0; i < MAX_HFI_FENCE_OFFSET; i++) { + k = &kp->data.hfi_synx_pkt; + u = &up->data.hfi_synx_pkt; + for (i = 0; i < MAX_HFI_PKT_SIZE; i++) { if (put_user(k->pkt_data[i], &u->pkt_data[i])) return -EFAULT; } - for (i = 0; i < MAX_HFI_FENCE_SIZE; i++) { - if (put_user(k->fence_data[i], &u->fence_data[i])) - return -EFAULT; - } + return 0; } static int _copy_sysprop_to_user(struct cvp_kmd_arg *kp, struct cvp_kmd_arg __user *up) { - struct cvp_kmd_sys_properties *k, *u; + struct cvp_kmd_sys_properties *k; + struct cvp_kmd_sys_properties __user *u; + int i; k = &kp->data.sys_properties; u = &up->data.sys_properties; - if (put_user(k->prop_data.data, &u->prop_data.data)) - return -EFAULT; + for (i = 0; i < 8; i++) + if (put_user(k->prop_data[i].data, &u->prop_data[i].data)) + return -EFAULT; return 0; @@ -245,26 +275,6 @@ static int _get_session_info_from_user( return 0; } -static int _get_power_request( - struct cvp_kmd_request_power *k, - struct cvp_kmd_request_power __user *u) -{ - int i; - - if (get_user(k->clock_cycles_a, &u->clock_cycles_a) || - get_user(k->clock_cycles_b, &u->clock_cycles_b) || - get_user(k->ddr_bw, &u->ddr_bw) || - get_user(k->sys_cache_bw, &u->sys_cache_bw)) - return -EFAULT; - - for (i = 0; i < 8; i++) - if (get_user(k->reserved[i], &u->reserved[i])) - return -EFAULT; - - return 0; - -} - static int convert_from_user(struct cvp_kmd_arg *kp, unsigned long arg, struct msm_cvp_inst *inst) @@ -304,20 +314,6 @@ static int convert_from_user(struct cvp_kmd_arg *kp, break; } - case CVP_KMD_REQUEST_POWER: - { - struct cvp_kmd_request_power *k; - struct cvp_kmd_request_power __user *u; - - k = &kp->data.req_power; - u = &up->data.req_power; - if (_get_power_request(k, u)) { - dprintk(CVP_ERR, "fail to get power request\n"); - return -EFAULT; - } - - break; - } case CVP_KMD_REGISTER_BUFFER: { struct cvp_kmd_buffer *k, *u; @@ -386,7 +382,7 @@ static int convert_from_user(struct cvp_kmd_arg *kp, return -EFAULT; } - rc = _copy_fence_pkt_from_user(kp, up, (pkt_hdr.size >> 2)); + rc = _copy_fence_pkt_from_user(kp, up); break; } case CVP_KMD_RECEIVE_MSG_PKT: @@ -452,26 +448,6 @@ static int _put_user_session_info( return 0; } - -static int _put_power_request( - struct cvp_kmd_request_power *k, - struct cvp_kmd_request_power __user *u) -{ - int i; - - if (put_user(k->clock_cycles_a, &u->clock_cycles_a) || - put_user(k->clock_cycles_b, &u->clock_cycles_b) || - put_user(k->ddr_bw, &u->ddr_bw) || - put_user(k->sys_cache_bw, &u->sys_cache_bw)) - return -EFAULT; - - for (i = 0; i < 8; i++) - if (put_user(k->reserved[i], &u->reserved[i])) - return -EFAULT; - - return 0; -} - static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg) { int rc = 0; @@ -513,20 +489,6 @@ static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg) break; } - case CVP_KMD_REQUEST_POWER: - { - struct cvp_kmd_request_power *k; - struct cvp_kmd_request_power __user *u; - - k = &kp->data.req_power; - u = &up->data.req_power; - if (_put_power_request(k, u)) { - dprintk(CVP_ERR, "fail to copy power to user\n"); - return -EFAULT; - } - - break; - } case CVP_KMD_REGISTER_BUFFER: { struct cvp_kmd_buffer *k, *u; @@ -583,7 +545,7 @@ static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg) dprintk(CVP_DBG, "Send user cmd pkt: %d %d\n", pkt_hdr.size, pkt_hdr.packet_type); - rc = _copy_fence_pkt_to_user(kp, up, (pkt_hdr.size >> 2)); + rc = _copy_fence_pkt_to_user(kp, up); break; } case CVP_KMD_SESSION_CONTROL: diff --git a/drivers/media/platform/msm/cvp/msm_cvp_synx.c b/drivers/media/platform/msm/cvp/msm_cvp_synx.c new file mode 100644 index 000000000000..b1b2a44c19f9 --- /dev/null +++ b/drivers/media/platform/msm/cvp/msm_cvp_synx.c @@ -0,0 +1,565 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "msm_cvp_common.h" +#include "cvp_hfi_api.h" +#include "msm_cvp_debug.h" +#include "msm_cvp_core.h" +#include "msm_cvp_dsp.h" + +static int cvp_import_synx_deprecate(struct msm_cvp_inst *inst, u32 type, + u32 *fence, u32 *synx) +{ + int rc = 0; + int i; + int start = 0, end = 0; + struct cvp_fence_type *f; + struct synx_import_params params; + s32 h_synx; + struct synx_session ssid; + + f = (struct cvp_fence_type *)fence; + ssid = inst->synx_session_id; + + switch (type) { + case HFI_CMD_SESSION_CVP_DME_FRAME: + { + start = 0; + end = HFI_DME_BUF_NUM; + break; + } + case HFI_CMD_SESSION_CVP_FD_FRAME: + { + u32 in = fence[0]; + u32 out = fence[1]; + + if (in > MAX_HFI_FENCE_SIZE || out > MAX_HFI_FENCE_SIZE + || in > MAX_HFI_FENCE_SIZE - out) { + dprintk(CVP_ERR, "%s: failed!\n", __func__); + rc = -EINVAL; + return rc; + } + + synx[0] = (in << 16) | out; + start = 1; + end = in + out + 1; + break; + } + default: + dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); + rc = -EINVAL; + return rc; + } + + for (i = start; i < end; ++i) { + h_synx = f[i].h_synx; + + if (h_synx) { + params.h_synx = h_synx; + params.secure_key = f[i].secure_key; + params.new_h_synx = &synx[i]; + + rc = synx_import(ssid, ¶ms); + if (rc) { + dprintk(CVP_ERR, + "%s: synx_import failed\n", + __func__); + return rc; + } + } + } + + return rc; +} + +int cvp_import_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc, + u32 *fence) +{ + int rc = 0; + int i; + struct cvp_fence_type *fs; + struct synx_import_params params; + s32 h_synx; + struct synx_session ssid; + + if (fc->signature != 0xFEEDFACE) + return cvp_import_synx_deprecate(inst, fc->type, fence, + fc->synx); + + fs = (struct cvp_fence_type *)fence; + ssid = inst->synx_session_id; + + for (i = 0; i < fc->num_fences; ++i) { + h_synx = fs[i].h_synx; + + if (h_synx) { + params.h_synx = h_synx; + params.secure_key = fs[i].secure_key; + params.new_h_synx = &fc->synx[i]; + + rc = synx_import(ssid, ¶ms); + if (rc) { + dprintk(CVP_ERR, + "%s: synx_import failed\n", + __func__); + return rc; + } + } + } + + return 0; +} + +static int cvp_release_synx_deprecate(struct msm_cvp_inst *inst, u32 type, + u32 *synx) +{ + int rc = 0; + int i; + s32 h_synx; + struct synx_session ssid; + int start = 0, end = 0; + + ssid = inst->synx_session_id; + + switch (type) { + case HFI_CMD_SESSION_CVP_DME_FRAME: + { + start = 0; + end = HFI_DME_BUF_NUM; + + break; + } + case HFI_CMD_SESSION_CVP_FD_FRAME: + { + u32 in = synx[0] >> 16; + u32 out = synx[0] & 0xFFFF; + + start = 1; + end = in + out + 1; + + break; + } + default: + dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); + rc = -EINVAL; + return rc; + } + + for (i = start; i < end; ++i) { + h_synx = synx[i]; + if (h_synx) { + rc = synx_release(ssid, h_synx); + if (rc) + dprintk(CVP_ERR, + "%s: synx_release %d failed\n", + __func__, i); + } + } + + return rc; +} + +int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc) +{ + int rc = 0; + int i; + s32 h_synx; + struct synx_session ssid; + + if (fc->signature != 0xFEEDFACE) + return cvp_release_synx_deprecate(inst, fc->type, fc->synx); + + ssid = inst->synx_session_id; + for (i = 0; i < fc->num_fences; ++i) { + h_synx = fc->synx[i]; + if (h_synx) { + rc = synx_release(ssid, h_synx); + if (rc) + dprintk(CVP_ERR, + "%s: synx_release %d failed\n", + __func__, i); + } + } + return rc; +} + +static int cvp_cancel_input_synx_deprecate(struct msm_cvp_inst *inst, u32 type, + u32 *synx) +{ + int rc = 0; + int i; + int h_synx; + struct synx_session ssid; + int start = 0, end = 0; + int synx_state = SYNX_STATE_SIGNALED_CANCEL; + + ssid = inst->synx_session_id; + + switch (type) { + case HFI_CMD_SESSION_CVP_DME_FRAME: + { + start = 1; + end = HFI_DME_BUF_NUM - 1; + break; + } + case HFI_CMD_SESSION_CVP_FD_FRAME: + { + u32 in, out; + + in = synx[0] >> 16; + out = synx[0] & 0xFFFF; + + start = 1; + end = in + 1; + break; + } + default: + dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); + rc = -EINVAL; + return rc; + } + + for (i = start; i < end; ++i) { + h_synx = synx[i]; + if (h_synx) { + rc = synx_signal(ssid, h_synx, synx_state); + if (rc && rc != -EALREADY) { + dprintk(CVP_ERR, "%s: synx_signal %d failed\n", + __func__, i); + synx_state = SYNX_STATE_SIGNALED_ERROR; + } + } + } + + return rc; +} + +static int cvp_cancel_output_synx_deprecate(struct msm_cvp_inst *inst, u32 type, + u32 *synx) +{ + int rc = 0; + int i; + int h_synx; + struct synx_session ssid; + int start = 0, end = 0; + int synx_state = SYNX_STATE_SIGNALED_CANCEL; + + ssid = inst->synx_session_id; + + switch (type) { + case HFI_CMD_SESSION_CVP_DME_FRAME: + { + start = FENCE_DME_OUTPUT_IDX; + end = FENCE_DME_OUTPUT_IDX + 1; + break; + } + case HFI_CMD_SESSION_CVP_FD_FRAME: + { + u32 in, out; + + in = synx[0] >> 16; + out = synx[0] & 0xFFFF; + + start = in + 1; + end = in + out + 1; + break; + } + default: + dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); + rc = -EINVAL; + return rc; + } + + for (i = start; i < end; ++i) { + h_synx = synx[i]; + if (h_synx) { + rc = synx_signal(ssid, h_synx, synx_state); + if (rc) { + dprintk(CVP_ERR, "%s: synx_signal %d failed\n", + __func__, i); + synx_state = SYNX_STATE_SIGNALED_ERROR; + } + } + } + + return rc; +} + +static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst, + enum cvp_synx_type type, + struct cvp_fence_command *fc) +{ + int rc = 0; + int i; + int h_synx; + struct synx_session ssid; + int start = 0, end = 0; + int synx_state = SYNX_STATE_SIGNALED_CANCEL; + + ssid = inst->synx_session_id; + + if (type == CVP_INPUT_SYNX) { + start = 0; + end = fc->output_index; + } else if (type == CVP_OUTPUT_SYNX) { + start = fc->output_index; + end = fc->num_fences; + } else { + dprintk(CVP_ERR, "%s Incorrect synx type\n", __func__); + return -EINVAL; + } + + for (i = start; i < end; ++i) { + h_synx = fc->synx[i]; + if (h_synx) { + rc = synx_signal(ssid, h_synx, synx_state); + if (rc) { + dprintk(CVP_ERR, "%s: synx_signal %d failed\n", + __func__, i); + synx_state = SYNX_STATE_SIGNALED_ERROR; + } + } + } + + return rc; + + +} + +int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type, + struct cvp_fence_command *fc) +{ + if (fc->signature != 0xFEEDFACE) { + if (type == CVP_INPUT_SYNX) + return cvp_cancel_input_synx_deprecate(inst, fc->type, + fc->synx); + else if (type == CVP_OUTPUT_SYNX) + return cvp_cancel_output_synx_deprecate(inst, fc->type, + fc->synx); + else { + dprintk(CVP_ERR, "Incorrect synx type %d\n", type); + return -EINVAL; + } + } + + return cvp_cancel_synx_impl(inst, type, fc); +} + +static int cvp_wait_dme_synx_deprecate(struct synx_session ssid, u32 *synx, + u32 *synx_state) +{ + int i, rc = 0; + int h_synx; + unsigned long timeout_ms = 1000; + + i = 0; + while (i < HFI_DME_BUF_NUM - 1) { + h_synx = synx[i]; + if (h_synx) { + rc = synx_wait(ssid, h_synx, timeout_ms); + if (rc) { + dprintk(CVP_ERR, "%s %s: synx_wait %d failed\n", + current->comm, __func__, i); + *synx_state = SYNX_STATE_SIGNALED_ERROR; + return -EINVAL; + } + /* + * Increase loop count to skip fence + * waiting on downscale image where i == 1. + */ + if (i == FENCE_DME_ICA_ENABLED_IDX) + ++i; + } + ++i; + } + return rc; +} + +static int cvp_signal_dme_synx_deprecate(struct synx_session ssid, u32 *synx, + u32 synx_state) +{ + int rc = 0; + int h_synx; + + if (synx[FENCE_DME_ICA_ENABLED_IDX]) { + h_synx = synx[FENCE_DME_DS_IDX]; + + rc = synx_signal(ssid, h_synx, synx_state); + if (rc) { + dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n", + current->comm, __func__, FENCE_DME_DS_IDX); + synx_state = SYNX_STATE_SIGNALED_ERROR; + } + } + + h_synx = synx[FENCE_DME_OUTPUT_IDX]; + rc = synx_signal(ssid, h_synx, synx_state); + if (rc) + dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n", + current->comm, __func__, FENCE_DME_OUTPUT_IDX); + + return rc; +} + +static int cvp_wait_fd_synx_deprecate(struct synx_session ssid, u32 *synx, + u32 *synx_state) +{ + int i, rc = 0; + unsigned long timeout_ms = 1000; + int h_synx; + u32 in; + + in = synx[0] >> 16; + + i = 1; + while (i <= in) { + h_synx = synx[i]; + if (h_synx) { + rc = synx_wait(ssid, h_synx, timeout_ms); + if (rc) { + *synx_state = synx_get_status(ssid, h_synx); + if (*synx_state == SYNX_STATE_SIGNALED_CANCEL) { + dprintk(CVP_DBG, + "%s: synx_wait %d cancel %d state %d\n", + current->comm, i, rc, *synx_state); + } else { + dprintk(CVP_ERR, + "%s: synx_wait %d failed %d state %d\n", + current->comm, i, rc, *synx_state); + *synx_state = SYNX_STATE_SIGNALED_ERROR; + } + return rc; + } + } + ++i; + } + return rc; +} + +static int cvp_signal_fd_synx_deprecate(struct synx_session ssid, u32 *synx, + u32 synx_state) +{ + int i, rc = 0; + u32 in, out; + int h_synx; + + in = synx[0] >> 16; + out = synx[0] & 0xFFFF; + + i = in + 1; + while (i <= in + out) { + h_synx = synx[i]; + if (h_synx) { + rc = synx_signal(ssid, h_synx, synx_state); + if (rc) { + dprintk(CVP_ERR, "%s: synx_signal %d failed\n", + current->comm, i); + synx_state = SYNX_STATE_SIGNALED_ERROR; + } + } + ++i; + } + + return rc; +} + +static int cvp_wait_synx(struct synx_session ssid, u32 *synx, u32 num_synx, + u32 *synx_state) +{ + int i = 0, rc = 0; + unsigned long timeout_ms = 1000; + int h_synx; + + while (i < num_synx) { + h_synx = synx[i]; + if (h_synx) { + rc = synx_wait(ssid, h_synx, timeout_ms); + if (rc) { + *synx_state = synx_get_status(ssid, h_synx); + if (*synx_state == SYNX_STATE_SIGNALED_CANCEL) { + dprintk(CVP_DBG, + "%s: synx_wait %d cancel %d state %d\n", + current->comm, i, rc, *synx_state); + } else { + dprintk(CVP_ERR, + "%s: synx_wait %d failed %d state %d\n", + current->comm, i, rc, *synx_state); + *synx_state = SYNX_STATE_SIGNALED_ERROR; + } + return rc; + } + } + ++i; + } + return rc; +} + +static int cvp_signal_synx(struct synx_session ssid, u32 *synx, u32 num_synx, + u32 synx_state) +{ + int i = 0, rc = 0; + int h_synx; + + while (i < num_synx) { + h_synx = synx[i]; + if (h_synx) { + rc = synx_signal(ssid, h_synx, synx_state); + if (rc) { + dprintk(CVP_ERR, "%s: synx_signal %d failed\n", + current->comm, i); + synx_state = SYNX_STATE_SIGNALED_ERROR; + } + } + ++i; + } + return rc; +} + +int cvp_synx_ops(struct msm_cvp_inst *inst, enum cvp_synx_type type, + struct cvp_fence_command *fc, u32 *synx_state) +{ + struct synx_session ssid; + + ssid = inst->synx_session_id; + + if (fc->signature != 0xFEEDFACE) { + if (fc->type == HFI_CMD_SESSION_CVP_DME_FRAME) { + if (type == CVP_INPUT_SYNX) + return cvp_wait_dme_synx_deprecate(ssid, + fc->synx, synx_state); + else if (type == CVP_OUTPUT_SYNX) + return cvp_signal_dme_synx_deprecate(ssid, + fc->synx, *synx_state); + else + return -EINVAL; + } else if (fc->type == HFI_CMD_SESSION_CVP_FD_FRAME) { + if (type == CVP_INPUT_SYNX) + return cvp_wait_fd_synx_deprecate(ssid, + fc->synx, synx_state); + else if (type == CVP_OUTPUT_SYNX) + return cvp_signal_fd_synx_deprecate(ssid, + fc->synx, *synx_state); + else + return -EINVAL; + } else { + dprintk(CVP_ERR, "%s Incorrect pkt type\n", + __func__); + return -EINVAL; + } + } + + if (type == CVP_INPUT_SYNX) { + return cvp_wait_synx(ssid, fc->synx, fc->output_index, + synx_state); + } else if (type == CVP_OUTPUT_SYNX) { + return cvp_signal_synx(ssid, &fc->synx[fc->output_index], + (fc->num_fences - fc->output_index), + *synx_state); + } else { + dprintk(CVP_ERR, "%s Incorrect SYNX type\n", __func__); + return -EINVAL; + } +} + diff --git a/drivers/media/platform/msm/cvp/msm_cvp_synx.h b/drivers/media/platform/msm/cvp/msm_cvp_synx.h new file mode 100644 index 000000000000..4ecae2c580c4 --- /dev/null +++ b/drivers/media/platform/msm/cvp/msm_cvp_synx.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _MSM_CVP_SYNX_H_ +#define _MSM_CVP_SYNX_H_ + +#include +#include +#include "cvp_comm_def.h" + + +struct cvp_fence_queue { + struct mutex lock; + enum queue_state state; + enum op_mode mode; + struct list_head wait_list; + wait_queue_head_t wq; + struct list_head sched_list; +}; + +struct cvp_fence_type { + s32 h_synx; + u32 secure_key; +}; + +struct cvp_fence_command { + struct list_head list; + u64 frame_id; + enum op_mode mode; + u32 signature; + u32 num_fences; + u32 output_index; + u32 type; + u32 synx[MAX_HFI_FENCE_SIZE/2]; + struct cvp_hfi_cmd_session_hdr *pkt; +}; + +enum cvp_synx_type { + CVP_UINIT_SYNX, + CVP_INPUT_SYNX, + CVP_OUTPUT_SYNX, + CVP_INVALID_SYNX, +}; + +int cvp_import_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc, + u32 *fence); +int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc); +int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type, + struct cvp_fence_command *fc); +int cvp_synx_ops(struct msm_cvp_inst *inst, enum cvp_synx_type type, + struct cvp_fence_command *fc, u32 *synx_state); +#endif diff --git a/include/uapi/media/msm_cvp_private.h b/include/uapi/media/msm_cvp_private.h index 0fc8baaa9f9e..68c657ad283a 100644 --- a/include/uapi/media/msm_cvp_private.h +++ b/include/uapi/media/msm_cvp_private.h @@ -23,13 +23,6 @@ */ #define CVP_KMD_GET_SESSION_INFO (CVP_KMD_CMD_START + 1) -/* - * CVP_KMD_REQUEST_POWER - this argument type is used to - * set the power required to driver. it passes - * struct cvp_kmd_request_power {} - */ -#define CVP_KMD_REQUEST_POWER (CVP_KMD_CMD_START + 2) - /* * CVP_KMD_REGISTER_BUFFER - this argument type is used to * register the buffer to driver. it passes @@ -82,21 +75,6 @@ struct cvp_kmd_session_info { __u32 reserved[10]; }; -/** - * struct cvp_kmd_request_power - power / clock data information - * @clock_cycles_a: clock cycles per second required for hardware_a - * @clock_cycles_b: clock cycles per second required for hardware_b - * @ddr_bw: bandwidth required for ddr in bps - * @sys_cache_bw: bandwidth required for system cache in bps - */ -struct cvp_kmd_request_power { - __u32 clock_cycles_a; - __u32 clock_cycles_b; - __u32 ddr_bw; - __u32 sys_cache_bw; - __u32 reserved[8]; -}; - /** * struct cvp_kmd_buffer - buffer information to be registered * @index: index of buffer @@ -180,7 +158,7 @@ struct cvp_kmd_sys_property { struct cvp_kmd_sys_properties { __u32 prop_num; - struct cvp_kmd_sys_property prop_data; + struct cvp_kmd_sys_property prop_data[8]; }; #define SESSION_CREATE 1 @@ -202,6 +180,29 @@ struct cvp_kmd_hfi_fence_packet { __u64 frame_id; }; +struct cvp_kmd_fence { + __s32 h_synx; + __u32 secure_key; +}; + +struct cvp_kmd_fence_ctrl { + __u32 magic; + __u32 reserved; + __u64 frame_id; + __u32 num_fences; + __u32 output_index; + struct cvp_kmd_fence fences[MAX_HFI_FENCE_SIZE/2]; +}; + +#define MAX_FENCE_DATA_SIZE (MAX_HFI_FENCE_SIZE + 6) + +struct cvp_kmd_hfi_synx_packet { + __u32 pkt_data[MAX_HFI_PKT_SIZE]; + union { + __u32 fence_data[MAX_FENCE_DATA_SIZE]; + struct cvp_kmd_fence_ctrl fc; + }; +}; /** * struct cvp_kmd_arg @@ -225,15 +226,19 @@ struct cvp_kmd_arg { __u32 buf_num; union cvp_data_t { struct cvp_kmd_session_info session; - struct cvp_kmd_request_power req_power; struct cvp_kmd_buffer regbuf; struct cvp_kmd_buffer unregbuf; struct cvp_kmd_send_cmd send_cmd; struct cvp_kmd_hfi_packet hfi_pkt; struct cvp_kmd_sys_properties sys_properties; struct cvp_kmd_hfi_fence_packet hfi_fence_pkt; + struct cvp_kmd_hfi_synx_packet hfi_synx_pkt; struct cvp_kmd_session_control session_ctrl; __u64 frame_id; } data; }; + +struct cvp_kmd_request_power { + __u32 deprecated; +}; #endif