Merge "msm: cvp: Optimize synX handling in cvp driver"

This commit is contained in:
qctecmdr 2020-04-13 10:50:18 -07:00 • committed by Gerrit - the friendly Code Review server
commit cba97f251a
10 changed files with 784 additions and 763 deletions

View file

@ -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

View file

@ -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 <linux/types.h>
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

View file

@ -278,19 +278,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;
@ -298,29 +295,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);
@ -357,40 +335,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;
@ -398,34 +357,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);
@ -458,19 +393,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;
}
@ -501,119 +424,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, &params);
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;
@ -656,10 +466,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",
@ -670,7 +480,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);
@ -693,6 +503,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;
@ -727,7 +539,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) {
@ -758,16 +569,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;
@ -897,77 +721,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.
@ -1006,10 +759,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,
@ -1069,64 +818,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;
@ -1430,7 +1121,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__);
@ -1440,16 +1131,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;
}
@ -1473,7 +1166,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++) {
@ -1549,107 +1242,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;
@ -1790,8 +1382,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);
}
@ -1802,7 +1394,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);
@ -1906,8 +1498,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);
}
@ -1921,7 +1513,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);
@ -1969,14 +1561,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);

View file

@ -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);

View file

@ -15,6 +15,7 @@
#include <media/msm_cvp_private.h>
#include <media/msm_cvp_vidc.h>
#include "msm_cvp_buf.h"
#include "msm_cvp_synx.h"
enum core_id {
MSM_CORE_CVP = 0,

View file

@ -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);

View file

@ -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:

View file

@ -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, &params);
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, &params);
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;
}
}

View file

@ -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 <linux/types.h>
#include <media/msm_cvp_private.h>
#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

View file

@ -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