kernel/0190-fix-The-wrong-dev-id-was-used-for-vcmd-release.patch
2024-12-19 16:34:44 -05:00

322 lines
14 KiB
Diff

From e6ab68dc8b3b40f5919b0c24086fd1be3eeab76d Mon Sep 17 00:00:00 2001
From: tangdaoyong <tangdaoyong@eswincomputing.com>
Date: Tue, 15 Oct 2024 14:00:44 +0800
Subject: [PATCH 190/219] fix:The wrong dev id was used for vcmd release
Changelogs:
1. The wrong dev id was used for vcmd release.
Signed-off-by: tangdaoyong <tangdaoyong@eswincomputing.com>
---
.../staging/media/eswin/vdec/hantro_vcmd.c | 98 ++++++++++++-------
1 file changed, 62 insertions(+), 36 deletions(-)
diff --git a/drivers/staging/media/eswin/vdec/hantro_vcmd.c b/drivers/staging/media/eswin/vdec/hantro_vcmd.c
index 7fd375c41006..ee87be45c346 100644
--- a/drivers/staging/media/eswin/vdec/hantro_vcmd.c
+++ b/drivers/staging/media/eswin/vdec/hantro_vcmd.c
@@ -788,7 +788,7 @@ static int vcmd_type_core_num[MAX_VCMD_TYPE];
static struct semaphore vcmd_reserve_cmdbuf_sem[MAX_VCMD_TYPE]; //for reserve
-#define CMDBUF_LOCK_NUM 8
+#define CMDBUF_LOCK_NUM 16
static spinlock_t cmdbuf_lock[CMDBUF_LOCK_NUM];
#define LOCK_CMDBUF_NODE(cmdbuf_id, flags) \
spin_lock_irqsave(&cmdbuf_lock[(cmdbuf_id) % CMDBUF_LOCK_NUM], flags)
@@ -1643,11 +1643,11 @@ static long release_cmdbuf(struct file *filp, u16 cmdbuf_id)
if (cmdbuf_obj->process_manager_obj) {
spin_lock_irqsave(&cmdbuf_obj->process_manager_obj->spinlock,
- flags);
+ flags);
cmdbuf_obj->process_manager_obj->total_exe_time -=
cmdbuf_obj->executing_time;
spin_unlock_irqrestore(&cmdbuf_obj->process_manager_obj->spinlock,
- flags);
+ flags);
wake_up_interruptible_all(&cmdbuf_obj->process_manager_obj->wait_queue);
}
free_cmdbuf_node(new_cmdbuf_node);
@@ -2413,6 +2413,7 @@ free_process_manager_obj(struct process_manager_obj *process_manager_obj)
LOG_DBG("%s\n", "free_process_manager_obj NULL");
return;
}
+ LOG_DBG("free process_manager_obj %px, filp=%px\n", process_manager_obj, process_manager_obj->filp);
//free current cmdbuf_obj
kfree(process_manager_obj);
return;
@@ -2482,6 +2483,7 @@ static void create_kernel_process_manager(void)
process_manager_obj =
(struct process_manager_obj *)process_manager_node->data;
process_manager_obj->filp = NULL;
+ LOG_DBG("create root process_manager_obj %px\n", process_manager_obj);
bi_list_insert_node_tail(&global_process_manager, process_manager_node);
}
@@ -2644,7 +2646,7 @@ int hantrovcmd_open(struct inode *inode, struct file *filp)
spin_unlock_irqrestore(&vcmd_process_manager_lock, flags);
LOG_DBG("dev opened\n");
- LOG_DBG("process node %p for filp opened %p\n", (void *)process_manager_node, (void *)filp);
+ LOG_DBG("opened::process obj %px for filp %px\n", (void *)process_manager_obj, (void *)filp);
return result;
}
@@ -2656,11 +2658,12 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
u32 release_cmdbuf_num = 0;
bi_list_node *new_cmdbuf_node = NULL;
struct cmdbuf_obj *cmdbuf_obj_temp = NULL;
- bi_list_node *process_manager_node;
+ bi_list_node *process_manager_node = NULL;
struct process_manager_obj *process_manager_obj = NULL;
int vcmd_aborted = 0; // vcmd is aborted in this function
struct cmdbuf_obj *restart_cmdbuf = NULL;
bi_list_node *next_cmdbuf = NULL;
+ bi_list_node *removed_node = NULL;
unsigned long flags;
long retVal = 0;
@@ -2673,13 +2676,14 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
fp_priv = (struct filp_priv *)filp->private_data;
dev = (struct hantrovcmd_dev *)fp_priv->dev;
- if (down_interruptible(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]))
- return -ERESTARTSYS;
-
if (dev->hw_version_id >= HW_ID_1_2_1) {
for (core_id = 0; core_id < total_vcmd_core_num; core_id++) {
if (!(&dev[core_id]))
continue;
+
+ if (down_interruptible(&vcmd_reserve_cmdbuf_sem[dev[core_id].vcmd_core_cfg.sub_module_type]))
+ return -ERESTARTSYS;
+
spin_lock_irqsave(dev[core_id].spinlock, flags);
new_cmdbuf_node = dev[core_id].list_manager.head;
while (1) {
@@ -2696,15 +2700,17 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
if (cmdbuf_obj_temp->cmdbuf_run_done) {
cmdbuf_obj_temp->cmdbuf_need_remove = 1;
retVal = release_cmdbuf_node(&dev[core_id].list_manager, new_cmdbuf_node);
- if (retVal == 1)
+ if (retVal == 1) {
cmdbuf_obj_temp->process_manager_obj = NULL;
+ }
} else if (cmdbuf_obj_temp->cmdbuf_data_linked == 0) {
cmdbuf_obj_temp->cmdbuf_data_linked = 1;
cmdbuf_obj_temp->cmdbuf_run_done = 1;
cmdbuf_obj_temp->cmdbuf_need_remove = 1;
retVal = release_cmdbuf_node(&dev[core_id].list_manager, new_cmdbuf_node);
- if (retVal == 1)
+ if (retVal == 1) {
cmdbuf_obj_temp->process_manager_obj = NULL;
+ }
} else if (cmdbuf_obj_temp->cmdbuf_data_linked == 1 &&
dev[core_id].working_state == WORKING_STATE_IDLE) {
vcmd_delink_rm_cmdbuf(&dev[core_id], new_cmdbuf_node);
@@ -2725,7 +2731,7 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
//abort the vcmd and wait
LOG_DBG("Abort due to linked cmdbuf %d of current process.\n", cmdbuf_obj_temp->cmdbuf_id);
- printk_vcmd_register_debug((const void *)dev->hwregs, "Before trigger to 0");
+ printk_vcmd_register_debug((const void *)dev[core_id].hwregs, "Before trigger to 0");
// disable abort interrupt
//vcmd_write_register_value((const void *)dev[core_id].hwregs,
//dev[core_id].reg_mirror,HWIF_VCMD_IRQ_ABORT_EN,0);
@@ -2735,7 +2741,7 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
0);
vcmd_aborted = 1;
- printk_vcmd_register_debug((const void *)dev->hwregs, "After trigger to 0");
+ printk_vcmd_register_debug((const void *)dev[core_id].hwregs, "After trigger to 0");
// Wait vcmd core aborted and vcmd enters IDLE mode.
//while (dev[core_id].working_state != WORKING_STATE_IDLE) {
while (vcmd_get_register_value((const void *)dev[core_id].hwregs,
@@ -2744,10 +2750,10 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
loop_count++;
if (!(loop_count % 10)) {
LOG_ERR("expected idle state, but irq status = 0x%0x\n",
- vcmd_read_reg((const void *)dev->hwregs,
+ vcmd_read_reg((const void *)dev[core_id].hwregs,
VCMD_REGISTER_INT_STATUS_OFFSET));
LOG_ERR("vcmd current status is %d\n",
- vcmd_get_register_value((const void *)dev->hwregs,
+ vcmd_get_register_value((const void *)dev[core_id].hwregs,
dev[core_id].reg_mirror,
HWIF_VCMD_WORK_STATE));
}
@@ -2756,7 +2762,7 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
if (loop_count > 100) {
LOG_ERR("too long before vcmd core to IDLE state\n");
spin_unlock_irqrestore(dev[core_id].spinlock, flags);
- up(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]);
+ up(&vcmd_reserve_cmdbuf_sem[dev[core_id].vcmd_core_cfg.sub_module_type]);
return -ERESTARTSYS;
}
}
@@ -2766,11 +2772,11 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
dev[core_id].reg_mirror,
HWIF_VCMD_IRQ_ABORT)) {
LOG_DBG("Abort interrupt triggered, now clear it to avoid abort int...\n");
- vcmd_write_reg((const void *)dev->hwregs,
+ vcmd_write_reg((const void *)dev[core_id].hwregs,
VCMD_REGISTER_INT_STATUS_OFFSET,
0x1 << 4);
LOG_DBG("Now irq status = 0x%0x.\n",
- vcmd_read_reg((const void *)dev->hwregs, VCMD_REGISTER_INT_STATUS_OFFSET));
+ vcmd_read_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET));
}
//printk_vcmd_register_debug((const void *)dev->hwregs, "vcmd status to IDLE");
@@ -2863,9 +2869,9 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
LOG_DBG("Restart from cmdbuf [%d] after aborting.\n", restart_cmdbuf->cmdbuf_id);
- irq_status1 = vcmd_read_reg((const void *)dev->hwregs, VCMD_REGISTER_INT_STATUS_OFFSET);
- vcmd_write_reg((const void *)dev->hwregs, VCMD_REGISTER_INT_STATUS_OFFSET, irq_status1);
- irq_status2 = vcmd_read_reg((const void *)dev->hwregs, VCMD_REGISTER_INT_STATUS_OFFSET);
+ irq_status1 = vcmd_read_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET);
+ vcmd_write_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET, irq_status1);
+ irq_status2 = vcmd_read_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET);
LOG_DBG("Clear irq status from 0x%0x -> 0x%0x\n", irq_status1, irq_status2);
if (mmu_enable) {
vcmd_write_register_value((const void *)dev[core_id].hwregs,
@@ -2922,7 +2928,7 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
dev[core_id].reg_mirror,
HWIF_VCMD_RDY_CMDBUF_COUNT,
dev[core_id].sw_cmdbuf_rdy_num);
- printk_vcmd_register_debug((const void *)dev->hwregs, "before restart");
+ printk_vcmd_register_debug((const void *)dev[core_id].hwregs, "before restart");
vcmd_write_register_value(
(const void *)dev[core_id].hwregs,
dev[core_id].reg_mirror,
@@ -2936,7 +2942,7 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
HWIF_VCMD_START_TRIGGER));
LOG_DBG("dev state from %d -> WORKING.\n", dev[core_id].working_state);
dev[core_id].working_state = WORKING_STATE_WORKING;
- printk_vcmd_register_debug((const void *)dev->hwregs, "after restart");
+ printk_vcmd_register_debug((const void *)dev[core_id].hwregs, "after restart");
} else {
LOG_DBG("No more command buffer to be restarted!\n");
}
@@ -2944,11 +2950,17 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
// VCMD aborted but not restarted, nedd to wake up
if (vcmd_aborted && !restart_cmdbuf)
wake_up_interruptible_all(dev[core_id].wait_queue);
+
+ up(&vcmd_reserve_cmdbuf_sem[dev[core_id].vcmd_core_cfg.sub_module_type]);
}
} else {
for (core_id = 0; core_id < total_vcmd_core_num; core_id++) {
if ((&dev[core_id]) == NULL)
continue;
+
+ if (down_interruptible(&vcmd_reserve_cmdbuf_sem[dev[core_id].vcmd_core_cfg.sub_module_type]))
+ return -ERESTARTSYS;
+
spin_lock_irqsave(dev[core_id].spinlock, flags);
new_cmdbuf_node = dev[core_id].list_manager.head;
while (1) {
@@ -2960,22 +2972,25 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
if (cmdbuf_obj_temp->cmdbuf_run_done) {
cmdbuf_obj_temp->cmdbuf_need_remove = 1;
retVal = release_cmdbuf_node(&dev[core_id].list_manager, new_cmdbuf_node);
- if (retVal == 1)
+ if (retVal == 1) {
cmdbuf_obj_temp->process_manager_obj = NULL;
+ }
} else if (cmdbuf_obj_temp->cmdbuf_data_linked == 0) {
cmdbuf_obj_temp->cmdbuf_data_linked = 1;
cmdbuf_obj_temp->cmdbuf_run_done = 1;
cmdbuf_obj_temp->cmdbuf_need_remove = 1;
retVal = release_cmdbuf_node(&dev[core_id].list_manager, new_cmdbuf_node);
- if (retVal == 1)
+ if (retVal == 1) {
cmdbuf_obj_temp->process_manager_obj = NULL;
+ }
} else if (cmdbuf_obj_temp->cmdbuf_data_linked == 1 &&
dev[core_id].working_state == WORKING_STATE_IDLE) {
cmdbuf_obj_temp->cmdbuf_run_done = 1;
cmdbuf_obj_temp->cmdbuf_need_remove = 1;
retVal = release_cmdbuf_node(&dev[core_id].list_manager, new_cmdbuf_node);
- if (retVal == 1)
+ if (retVal == 1) {
cmdbuf_obj_temp->process_manager_obj = NULL;
+ }
} else if (cmdbuf_obj_temp->cmdbuf_data_linked ==1 &&
dev[core_id].working_state == WORKING_STATE_WORKING) {
bi_list_node *last_cmdbuf_node;
@@ -2987,21 +3002,22 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
0);
if (wait_event_interruptible(*dev[core_id].wait_abort_queue, wait_abort_rdy(&dev[core_id]))) {
spin_unlock_irqrestore(dev[core_id].spinlock, flags);
- up(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]);
+ up(&vcmd_reserve_cmdbuf_sem[dev[core_id].vcmd_core_cfg.sub_module_type]);
return -ERESTARTSYS;
}
cmdbuf_obj_temp->cmdbuf_run_done = 1;
cmdbuf_obj_temp->cmdbuf_need_remove = 1;
retVal = release_cmdbuf_node(&dev[core_id].list_manager, new_cmdbuf_node);
- if (retVal == 1)
+ if (retVal == 1) {
cmdbuf_obj_temp->process_manager_obj = NULL;
+ }
//link
last_cmdbuf_node = find_last_linked_cmdbuf(dev[core_id].list_manager.tail);
- record_last_cmdbuf_rdy_num = dev->sw_cmdbuf_rdy_num;
- vcmd_link_cmdbuf(dev, last_cmdbuf_node);
+ record_last_cmdbuf_rdy_num = dev[core_id].sw_cmdbuf_rdy_num;
+ vcmd_link_cmdbuf(&dev[core_id], last_cmdbuf_node);
//re-run
if (dev[core_id].sw_cmdbuf_rdy_num)
- vcmd_start(dev, last_cmdbuf_node);
+ vcmd_start(&dev[core_id], last_cmdbuf_node);
}
release_cmdbuf_num++;
LOG_DBG("release reserved cmdbuf\n");
@@ -3009,6 +3025,8 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
new_cmdbuf_node = next_cmdbuf;
}
spin_unlock_irqrestore(dev[core_id].spinlock, flags);
+
+ up(&vcmd_reserve_cmdbuf_sem[dev[core_id].vcmd_core_cfg.sub_module_type]);
}
}
@@ -3021,17 +3039,25 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
if (!process_manager_node)
break;
process_manager_obj = (struct process_manager_obj *)process_manager_node->data;
- if (process_manager_obj->filp == filp)
+ if (process_manager_obj->filp == filp) {
+ removed_node = process_manager_node;
break;
+ }
process_manager_node = process_manager_node->next;
}
//remove node from list
- LOG_DBG("process node %p for filp to be removed: %p\n",
- (void *)process_manager_node, (void *)process_manager_obj->filp);
- bi_list_remove_node(&global_process_manager, process_manager_node);
+ if (removed_node) {
+ LOG_DBG("process node %p for filp to be removed: %px\n",
+ (void *)removed_node, (void *)process_manager_obj->filp);
+ bi_list_remove_node(&global_process_manager, removed_node);
+ }
spin_unlock_irqrestore(&vcmd_process_manager_lock, flags);
- free_process_manager_node(process_manager_node);
- up(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]);
+ if (removed_node) {
+ free_process_manager_node(removed_node);
+ } else {
+ LOG_WARN("no process node release for filp %px\n", filp);
+ }
+
return 0;
}
--
2.47.0