From e6ab68dc8b3b40f5919b0c24086fd1be3eeab76d Mon Sep 17 00:00:00 2001 From: tangdaoyong 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 --- .../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