video: rockchip: mpp: rkvenc2: Fix dchs conflict

When both cores are used on encoding and the first task on core 0 is
finished the next task on core 0 may use the same txid as the finished
task. It will delay the running task on core 1.

So we have to find a unused txid to remap the txid in logic. And the
both logical id and remap id should be record for each dchs status.

Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
Change-Id: I35e6a05bb879d9f389f308ad87bf62b0f20f3c6c
This commit is contained in:
Herman Chen
2022-04-11 18:23:20 +08:00
committed by Tao Huang
parent 3f9fb57349
commit 21225a4a1e

View File

@@ -41,6 +41,7 @@
#define RKVENC_SESSION_MAX_BUFFERS 40
#define RKVENC_MAX_CORE_NUM 4
#define RKVENC_MAX_DCHS_ID 4
#define to_rkvenc_info(info) \
container_of(info, struct rkvenc_hw_info, hw)
@@ -128,9 +129,17 @@ union rkvenc2_dual_core_handshake_id {
u32 txe : 1;
u32 rxe : 1;
u32 working : 1;
u32 reserve0 : 9;
u32 reserve0 : 1;
u32 txid_orig : 2;
u32 rxid_orig : 2;
u32 txid_map : 2;
u32 rxid_map : 2;
u32 offset : 11;
u32 reserve1 : 5;
u32 reserve1 : 1;
u32 txe_orig : 1;
u32 rxe_orig : 1;
u32 txe_map : 1;
u32 rxe_map : 1;
u32 session_id;
};
};
@@ -664,6 +673,16 @@ static void rkvenc2_setup_task_id(u32 session_id, struct rkvenc_task *task)
task->reg[RKVENC_CLASS_PIC].data[DCHS_CLASS_OFFSET] = val;
task->dchs_id.val = (((u64)session_id << 32) | val);
task->dchs_id.txid_orig = task->dchs_id.txid;
task->dchs_id.rxid_orig = task->dchs_id.rxid;
task->dchs_id.txid_map = task->dchs_id.txid;
task->dchs_id.rxid_map = task->dchs_id.rxid;
task->dchs_id.txe_orig = task->dchs_id.txe;
task->dchs_id.rxe_orig = task->dchs_id.rxe;
task->dchs_id.txe_map = task->dchs_id.txe;
task->dchs_id.rxe_map = task->dchs_id.rxe;
}
static int rkvenc2_is_split_task(struct rkvenc_task *task)
@@ -820,7 +839,7 @@ static void rkvenc2_patch_dchs(struct rkvenc_dev *enc, struct rkvenc_task *task)
{
struct rkvenc_ccu *ccu;
union rkvenc2_dual_core_handshake_id *dchs;
union rkvenc2_dual_core_handshake_id *task_id = &task->dchs_id;
union rkvenc2_dual_core_handshake_id *task_dchs = &task->dchs_id;
int core_num;
int core_id = enc->mpp.core_id;
unsigned long flags;
@@ -842,8 +861,9 @@ static void rkvenc2_patch_dchs(struct rkvenc_dev *enc, struct rkvenc_task *task)
spin_lock_irqsave(&ccu->lock_dchs, flags);
if (dchs[core_id].working) {
pr_err("can not config when core %d is still working\n", core_id);
spin_unlock_irqrestore(&ccu->lock_dchs, flags);
mpp_err("can not config when core %d is still working\n", core_id);
return;
}
@@ -853,32 +873,81 @@ static void rkvenc2_patch_dchs(struct rkvenc_dev *enc, struct rkvenc_task *task)
dchs[0].txid, dchs[0].txe, dchs[0].rxid, dchs[0].rxe,
dchs[1].working ? "work" : "idle",
dchs[1].txid, dchs[1].txe, dchs[1].rxid, dchs[1].rxe,
core_id, task_id->txid, task_id->txe, task_id->rxid, task_id->rxe);
core_id, task_dchs->txid, task_dchs->txe,
task_dchs->rxid, task_dchs->rxe);
dchs[core_id].val = task_id->val;
if (task_id->rxe) {
u32 task_rxid = task_id->rxid;
u32 session_id = task_id->session_id;
int dependency_core = -1;
/* always use new id as */
{
struct mpp_task *mpp_task = &task->mpp_task;
unsigned long id_valid = (unsigned long)-1;
int txid_map = -1;
int rxid_map = -1;
/* scan all used id */
for (i = 0; i < core_num; i++) {
if (i == core_id || !dchs[i].working)
if (!dchs[i].working)
continue;
if (task_rxid == dchs[i].txid && session_id == dchs[i].session_id) {
dependency_core = i;
clear_bit(dchs[i].txid_map, &id_valid);
clear_bit(dchs[i].rxid_map, &id_valid);
}
if (task_dchs->rxe) {
for (i = 0; i < core_num; i++) {
if (i == core_id)
continue;
if (!dchs[i].working)
continue;
if (task_dchs->session_id != dchs[i].session_id)
continue;
if (task_dchs->rxid_orig != dchs[i].txid_orig)
continue;
rxid_map = dchs[i].txid_map;
break;
}
}
if (dependency_core < 0) {
u32 dchs_val = (u32)task_id->val & (~(DCHS_RXE));
txid_map = find_first_bit(&id_valid, RKVENC_MAX_DCHS_ID);
if (txid_map == RKVENC_MAX_DCHS_ID) {
spin_unlock_irqrestore(&ccu->lock_dchs, flags);
task->reg[RKVENC_CLASS_PIC].data[DCHS_CLASS_OFFSET] = dchs_val;
dchs[core_id].rxe = 0;
mpp_err("task %d:%d on core %d failed to find a txid\n",
mpp_task->session->pid, mpp_task->task_id,
mpp_task->core_id);
return;
}
clear_bit(txid_map, &id_valid);
task_dchs->txid_map = txid_map;
if (rxid_map < 0) {
rxid_map = find_first_bit(&id_valid, RKVENC_MAX_DCHS_ID);
if (rxid_map == RKVENC_MAX_DCHS_ID) {
spin_unlock_irqrestore(&ccu->lock_dchs, flags);
mpp_err("task %d:%d on core %d failed to find a rxid\n",
mpp_task->session->pid, mpp_task->task_id,
mpp_task->core_id);
return;
}
task_dchs->rxe_map = 0;
}
task_dchs->rxid_map = rxid_map;
}
task_dchs->txid = task_dchs->txid_map;
task_dchs->rxid = task_dchs->rxid_map;
task_dchs->rxe = task_dchs->rxe_map;
dchs[core_id].val = task_dchs->val;
task->reg[RKVENC_CLASS_PIC].data[DCHS_CLASS_OFFSET] = task_dchs->val;
dchs[core_id].working = 1;
spin_unlock_irqrestore(&ccu->lock_dchs, flags);
@@ -899,22 +968,23 @@ static void rkvenc2_update_dchs(struct rkvenc_dev *enc, struct rkvenc_task *task
return;
}
if (mpp_debug_unlikely(DEBUG_CORE))
pr_info("core %d task done\n", core_id);
spin_lock_irqsave(&ccu->lock_dchs, flags);
ccu->dchs[core_id].val = 0;
if (mpp_debug_unlikely(DEBUG_CORE)) {
union rkvenc2_dual_core_handshake_id *dchs = ccu->dchs;
union rkvenc2_dual_core_handshake_id *task_id = &task->dchs_id;
union rkvenc2_dual_core_handshake_id *task_dchs = &task->dchs_id;
pr_info("core %d task done\n", core_id);
pr_info("core tx:rx 0 %s %d:%d %d:%d -- 1 %s %d:%d %d:%d -- task %d %d:%d %d:%d\n",
dchs[0].working ? "work" : "idle",
dchs[0].txid, dchs[0].txe, dchs[0].rxid, dchs[0].rxe,
dchs[1].working ? "work" : "idle",
dchs[1].txid, dchs[1].txe, dchs[1].rxid, dchs[1].rxe,
core_id, task_id->txid, task_id->txe, task_id->rxid, task_id->rxe);
core_id, task_dchs->txid, task_dchs->txe,
task_dchs->rxid, task_dchs->rxe);
}
spin_unlock_irqrestore(&ccu->lock_dchs, flags);
}