video: driver: new workhandler for inst events

create a new work handler and post and handle
events like psc.
introduce reuse concept for internal buffers.

Change-Id: Ibeaabae1b5923681756e959389df00b287206fb6
Signed-off-by: Darshana Patil <darshana@codeaurora.org>
This commit is contained in:
Darshana Patil
2020-12-22 19:15:25 -08:00
parent 8f55c1030e
commit cff8298acc
8 changed files with 261 additions and 48 deletions

View File

@@ -725,56 +725,53 @@ static int msm_vdec_set_output_properties(struct msm_vidc_inst *inst)
static int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
{
int rc = 0;
struct msm_vidc_core *core;
if (!inst || !inst->core) {
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
/*
* TODO: Remove the hack of sending bigger buffer sizes
* once internal buffer calculations are finalised
*/
inst->buffers.bin.size = call_session_op(core, buffer_size,
inst, MSM_VIDC_BUF_BIN) + 100000000;
inst->buffers.comv.size = call_session_op(core, buffer_size,
inst, MSM_VIDC_BUF_COMV) + 100000000;
inst->buffers.non_comv.size = call_session_op(core, buffer_size,
inst, MSM_VIDC_BUF_NON_COMV) + 100000000;
inst->buffers.line.size = call_session_op(core, buffer_size,
inst, MSM_VIDC_BUF_LINE) + 100000000;
inst->buffers.persist.size = call_session_op(core, buffer_size,
inst, MSM_VIDC_BUF_PERSIST) + 100000000;
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_BIN);
if (rc)
return rc;
inst->buffers.bin.min_count = call_session_op(core, min_count,
inst, MSM_VIDC_BUF_BIN);
inst->buffers.comv.min_count = call_session_op(core, min_count,
inst, MSM_VIDC_BUF_COMV);
inst->buffers.non_comv.min_count = call_session_op(core, min_count,
inst, MSM_VIDC_BUF_NON_COMV);
inst->buffers.line.min_count = call_session_op(core, min_count,
inst, MSM_VIDC_BUF_LINE);
inst->buffers.persist.min_count = call_session_op(core, min_count,
inst, MSM_VIDC_BUF_PERSIST);
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_COMV);
if (rc)
return rc;
s_vpr_h(inst->sid, "internal buffer: min size\n");
s_vpr_h(inst->sid, "bin buffer: %d %d\n",
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_NON_COMV);
if (rc)
return rc;
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_LINE);
if (rc)
return rc;
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_PERSIST);
if (rc)
return rc;
s_vpr_h(inst->sid, "internal buffer: min size reuse\n");
s_vpr_h(inst->sid, "bin buffer: %d %d %d\n",
inst->buffers.bin.min_count,
inst->buffers.bin.size);
s_vpr_h(inst->sid, "comv buffer: %d %d\n",
inst->buffers.bin.size,
inst->buffers.bin.reuse);
s_vpr_h(inst->sid, "comv buffer: %d %d %d\n",
inst->buffers.comv.min_count,
inst->buffers.comv.size);
s_vpr_h(inst->sid, "non_comv buffer: %d %d\n",
inst->buffers.comv.size,
inst->buffers.comv.reuse);
s_vpr_h(inst->sid, "non_comv buffer: %d %d %d\n",
inst->buffers.non_comv.min_count,
inst->buffers.non_comv.size);
s_vpr_h(inst->sid, "line buffer: %d %d\n",
inst->buffers.non_comv.size,
inst->buffers.non_comv.reuse);
s_vpr_h(inst->sid, "line buffer: %d %d %d\n",
inst->buffers.line.min_count,
inst->buffers.line.size);
s_vpr_h(inst->sid, "persist buffer: %d %d\n",
inst->buffers.line.size,
inst->buffers.line.reuse);
s_vpr_h(inst->sid, "buffer: %d %d %d\n",
inst->buffers.persist.min_count,
inst->buffers.persist.size);
inst->buffers.persist.size,
inst->buffers.persist.reuse);
return rc;
}
@@ -1821,4 +1818,3 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
return rc;
}

View File

@@ -909,6 +909,45 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
return 0;
}
int msm_vidc_get_input_internal_buffers(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type)
{
u32 buf_size;
u32 buf_count;
struct msm_vidc_core *core;
struct msm_vidc_buffers *buffers;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
/*
* TODO: Remove the hack of sending bigger buffer sizes
* once internal buffer calculations are finalised
*/
buf_size = call_session_op(core, buffer_size,
inst, buffer_type) + 100000000;
buf_count = call_session_op(core, min_count,
inst, buffer_type);
buffers = msm_vidc_get_buffers(inst, buffer_type, __func__);
if (!buffers)
return -EINVAL;
if (buf_size <= buffers->size &&
buf_count <= buffers->min_count) {
buffers->reuse = true;
} else {
buffers->reuse = false;
buffers->size = buf_size;
buffers->min_count = buf_count;
}
return 0;
}
int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type, u32 index)
{
@@ -1015,6 +1054,12 @@ int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
if (!buffers)
return -EINVAL;
if (buffers->reuse) {
s_vpr_l(inst->sid, "%s: reuse enabled for buffer type %#x\n",
__func__, buffer_type);
return 0;
}
for (i = 0; i < buffers->min_count; i++)
rc = msm_vidc_create_internal_buffer(inst, buffer_type, i);
@@ -1043,6 +1088,12 @@ int msm_vidc_queue_internal_buffers(struct msm_vidc_inst *inst,
if (!buffers)
return -EINVAL;
if (buffers->reuse) {
s_vpr_l(inst->sid, "%s: reuse enabled for buffer type %#x\n",
__func__, buffer_type);
return 0;
}
list_for_each_entry_safe(buffer, dummy, &buffers->list, list) {
/* do not queue pending release buffers */
if (buffer->flags & MSM_VIDC_ATTR_PENDING_RELEASE)
@@ -1085,6 +1136,12 @@ int msm_vidc_release_internal_buffers(struct msm_vidc_inst *inst,
if (!buffers)
return -EINVAL;
if (buffers->reuse) {
s_vpr_l(inst->sid, "%s: reuse enabled for buffer type %#x\n",
__func__, buffer_type);
return 0;
}
list_for_each_entry_safe(buffer, dummy, &buffers->list, list) {
/* do not release already pending release buffers */
if (buffer->attr & MSM_VIDC_ATTR_PENDING_RELEASE)

View File

@@ -214,15 +214,25 @@ static int msm_vidc_initialize_core(struct msm_vidc_core *core)
goto exit;
}
core->inst_workq = create_singlethread_workqueue("inst_workq");
if (!core->inst_workq) {
d_vpr_e("%s: create workq failed\n", __func__);
destroy_workqueue(core->inst_workq);
rc = -EINVAL;
goto exit;
}
mutex_init(&core->lock);
INIT_LIST_HEAD(&core->instances);
INIT_LIST_HEAD(&core->dangling_instances);
INIT_LIST_HEAD(&core->inst_works);
INIT_WORK(&core->device_work, venus_hfi_work_handler);
INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
INIT_DELAYED_WORK(&core->batch_work, msm_vidc_batch_handler);
INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler);
INIT_DELAYED_WORK(&core->inst_work, venus_hfi_inst_work_handler);
exit:
return rc;

View File

@@ -124,8 +124,7 @@ int validate_packet(u8 *response_pkt, u8 *core_resp_pkt,
return -EINVAL;
}
response_limit = core_resp_pkt + core_resp_pkt_size -
max(sizeof(struct hfi_header), sizeof(struct hfi_packet));
response_limit = core_resp_pkt + core_resp_pkt_size;
if (response_pkt < core_resp_pkt || response_pkt > response_limit) {
d_vpr_e("%s: invalid packet address\n", func);
@@ -963,6 +962,121 @@ exit:
return rc;
}
static int venus_hfi_input_psc(struct msm_vidc_core *core,
struct work_header *work_hdr)
{
int rc = 0;
struct msm_vidc_inst *inst;
struct hfi_header *hdr = NULL;
struct hfi_packet *packet;
u8 *pkt, *temp_pkt;
u32 hfi_cmd_type = 0;
u32 hfi_port = 0;
int i;
if (!work_hdr) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
hdr = (struct hfi_header *)work_hdr->data;
if (!hdr) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
inst = get_inst(core, hdr->session_id);
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
mutex_lock(&inst->lock);
hfi_cmd_type = 0;
hfi_port = 0;
pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
temp_pkt = pkt;
for (i = 0; i < hdr->num_packets; i++) {
if (validate_packet(pkt, work_hdr->data,
work_hdr->data_size, __func__)) {
rc = -EINVAL;
goto exit;
}
packet = (struct hfi_packet *)pkt;
if (packet->type > HFI_CMD_BEGIN &&
packet->type < HFI_CMD_END) {
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
s_vpr_e(inst->sid,
"%s: invalid packet type %d in port settings change\n",
__func__, packet->type);
rc = -EINVAL;
goto exit;
}
hfi_cmd_type = packet->type;
hfi_port = packet->port;
rc = handle_session_command(inst, packet);
} else if (packet->type > HFI_PROP_BEGIN &&
packet->type < HFI_PROP_END) {
rc = handle_session_property(inst, packet);
} else if (packet->type > HFI_SESSION_ERROR_BEGIN &&
packet->type < HFI_SESSION_ERROR_END) {
rc = handle_session_error(inst, packet);
} else if (packet->type > HFI_INFORMATION_BEGIN &&
packet->type < HFI_INFORMATION_END) {
rc = handle_session_info(inst, packet);
} else {
s_vpr_e(inst->sid, "%s: Unknown packet type: %#x\n",
__func__, packet->type);
rc = -EINVAL;
goto exit;
}
pkt += packet->size;
}
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
if (hfi_port == HFI_PORT_BITSTREAM) {
print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
inst->subcr_params[INPUT_PORT]);
rc = msm_vdec_input_port_settings_change(inst);
if (rc)
goto exit;
}
}
exit:
mutex_unlock(&inst->lock);
put_inst(inst);
return rc;
}
void venus_hfi_inst_work_handler(struct work_struct *work)
{
struct msm_vidc_core *core;
struct work_header *work_hdr, *dummy = NULL;
core = container_of(work, struct msm_vidc_core, inst_work.work);
if (!core) {
d_vpr_e("%s: invalid params\n", __func__);
return;
}
list_for_each_entry_safe(work_hdr, dummy, &core->inst_works, list) {
switch (work_hdr->type) {
case MSM_VIDC_INST_WORK_PSC:
venus_hfi_input_psc(core, work_hdr);
break;
default:
d_vpr_e("%s(): invalid work type: %d\n", __func__,
work_hdr->type);
break;
}
list_del(&work_hdr->list);
kfree(work_hdr->data);
kfree(work_hdr);
}
}
static int handle_session_response(struct msm_vidc_core *core,
struct hfi_header *hdr)
{
@@ -994,6 +1108,26 @@ static int handle_session_response(struct msm_vidc_core *core,
packet = (struct hfi_packet *)pkt;
if (packet->type > HFI_CMD_BEGIN &&
packet->type < HFI_CMD_END) {
if (packet->type == HFI_CMD_SETTINGS_CHANGE &&
packet->port == HFI_PORT_BITSTREAM) {
struct work_header *work;
work = kzalloc(sizeof(struct work_header), GFP_KERNEL);
INIT_LIST_HEAD(&work->list);
work->type = MSM_VIDC_INST_WORK_PSC;
work->session_id = hdr->session_id;
work->data_size = hdr->size;
work->data = kzalloc(hdr->size, GFP_KERNEL);
if (!work->data) {
rc= -ENOMEM;
goto exit;
}
memcpy(work->data, (void *)hdr, hdr->size);
list_add_tail(&work->list, &core->inst_works);
queue_delayed_work(core->inst_workq,
&core->inst_work, msecs_to_jiffies(0));
goto exit;
}
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
s_vpr_e(inst->sid,
"%s: invalid packet type %d in port settings change\n",
@@ -1029,18 +1163,15 @@ static int handle_session_response(struct msm_vidc_core *core,
}
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
if (hfi_port == HFI_PORT_BITSTREAM) {
print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
inst->subcr_params[INPUT_PORT]);
rc = msm_vdec_input_port_settings_change(inst);
if (rc)
goto exit;
} else if (hfi_port == HFI_PORT_RAW) {
if (hfi_port == HFI_PORT_RAW) {
print_psc_properties(VIDC_HIGH, "OUTPUT_PSC", inst,
inst->subcr_params[OUTPUT_PORT]);
rc = msm_vdec_output_port_settings_change(inst);
if (rc)
goto exit;
} else {
s_vpr_e(inst->sid, "%s: invalid port type: %#x\n",
__func__, hfi_port);
}
}