diff --git a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_vcmd_driver.c b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_vcmd_driver.c index 582a05a65..aacc0c20e 100644 --- a/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_vcmd_driver.c +++ b/drivers/staging/media/vpu-vc8000e-kernel/linux/kernel_module/vc8000_vcmd_driver.c @@ -634,7 +634,7 @@ struct cmdbuf_obj u16 cmdbuf_id; //used to manage CMDBUF in driver.It is a handle to identify cmdbuf.also is an interrupt vector.position in pool,same as status position. u8 cmdbuf_data_loaded; //0 means sw has not copied data into this CMDBUF; 1 means sw has copied data into this CMDBUF u8 cmdbuf_data_linked; //0 :not linked, 1:linked.into a vcmd core list. - u8 cmdbuf_run_done; //if 0,waiting for CMDBUF finish; if 1, op code in CMDBUF has finished one by one. HANTRO_VCMD_IOCH_WAIT_CMDBUF will check this variable. + volatile u8 cmdbuf_run_done; //if 0,waiting for CMDBUF finish; if 1, op code in CMDBUF has finished one by one. HANTRO_VCMD_IOCH_WAIT_CMDBUF will check this variable. u8 cmdbuf_need_remove; // if 0, not need to remove CMDBUF; 1 CMDBUF can be removed if it is not the last CMDBUF; u8 has_end_cmdbuf; //if 1, the last opcode is end opCode. u8 no_normal_int_cmdbuf; //if 1, JMP will not send normal interrupt. @@ -930,8 +930,47 @@ static void free_cmdbuf_mem(u16 cmdbuf_id ) spin_lock_irqsave(&vcmd_cmdbuf_alloc_lock, flags); cmdbuf_used[cmdbuf_id]=0; cmdbuf_used_residual +=1; + PDEBUG(" ## real free cmdbuf[%d]\n",cmdbuf_id); spin_unlock_irqrestore(&vcmd_cmdbuf_alloc_lock, flags); - wake_up_interruptible_all(&vcmd_cmdbuf_memory_wait); + wake_up_all(&vcmd_cmdbuf_memory_wait); +} + +static void free_cmdbuf_not_linked_by_flip(struct file *filp) +{ + unsigned long flags; + int i; + struct cmdbuf_obj* cmdbuf_obj; + bi_list_node* new_cmdbuf_node; + bool freed_flag = false; + spin_lock_irqsave(&vcmd_cmdbuf_alloc_lock, flags); + + for(i = 0; i < TOTAL_DISCRETE_CMDBUF_NUM; i++) + { + if(cmdbuf_used[i] && global_cmdbuf_node[i] != NULL) + { + new_cmdbuf_node = global_cmdbuf_node[i]; + if(new_cmdbuf_node == 0x55555555) + { + continue; + } + cmdbuf_obj = (struct cmdbuf_obj* )new_cmdbuf_node->data; + if(cmdbuf_obj->filp == filp && !cmdbuf_obj->cmdbuf_data_linked && !cmdbuf_obj->cmdbuf_run_done) + { + cmdbuf_used[i]=0; + cmdbuf_used_residual +=1; + global_cmdbuf_node[i] = NULL; + freed_flag = true; + PDEBUG(" ## Find left node not freed,real free cmdbuf[%d],remain %d\n",i,cmdbuf_used_residual); + } + } + + if(cmdbuf_used_residual >= (TOTAL_DISCRETE_CMDBUF_NUM-2)) + break; + + } + spin_unlock_irqrestore(&vcmd_cmdbuf_alloc_lock, flags); + if(freed_flag) + wake_up_all(&vcmd_cmdbuf_memory_wait); } static bi_list_node* create_cmdbuf_node(void) @@ -941,8 +980,13 @@ static bi_list_node* create_cmdbuf_node(void) struct noncache_mem new_cmdbuf_addr; struct noncache_mem new_status_cmdbuf_addr; - if(wait_event_interruptible(vcmd_cmdbuf_memory_wait, allocate_cmdbuf(&new_cmdbuf_addr,&new_status_cmdbuf_addr)) ) + if(!wait_event_interruptible_timeout(vcmd_cmdbuf_memory_wait, allocate_cmdbuf(&new_cmdbuf_addr,&new_status_cmdbuf_addr), + msecs_to_jiffies(500)) ) + { + pr_err("vc8000e: wait allocate_cmdbuf timeout\n"); return NULL; + } + cmdbuf_obj = create_vcmd_cmdbuf_obj(new_cmdbuf_addr.cmdbuf_id); if(cmdbuf_obj==NULL) { @@ -1048,18 +1092,21 @@ static u32 calculate_executing_time_after_node_high_priority(bi_list_node* exe_c } return time_run_all; } - - +#ifdef DEBUG_CMDBUF_ALLOC +int cmdbuf_node_unexpected[TOTAL_DISCRETE_CMDBUF_NUM]; +#endif /**********************************************************************************************************\ *cmdbuf pool management \***********************************************************************************************************/ static int allocate_cmdbuf(struct noncache_mem* new_cmdbuf_addr,struct noncache_mem* new_status_cmdbuf_addr) { unsigned long flags; + u16 cmdbuf_used_pos_start = cmdbuf_used_pos; spin_lock_irqsave(&vcmd_cmdbuf_alloc_lock, flags); if(cmdbuf_used_residual==0) { spin_unlock_irqrestore(&vcmd_cmdbuf_alloc_lock, flags); + pr_err("%s:vc8000e:no empty cmdbuf\n",__func__); //no empty cmdbuf return 0; } @@ -1080,6 +1127,7 @@ static int allocate_cmdbuf(struct noncache_mem* new_cmdbuf_addr,struct noncache new_status_cmdbuf_addr->mmu_bus_address=vcmd_status_buf_mem_pool.mmu_bus_address + cmdbuf_used_pos*CMDBUF_MAX_SIZE; new_status_cmdbuf_addr->size=CMDBUF_MAX_SIZE; new_status_cmdbuf_addr->cmdbuf_id = cmdbuf_used_pos; + global_cmdbuf_node[cmdbuf_used_pos]=0x55555555; //temp set it,for another thread not hit cmdbuf_used[x] set but global_cmdbuf_node[x] is null cmdbuf_used_pos++; if(cmdbuf_used_pos>=TOTAL_DISCRETE_CMDBUF_NUM) cmdbuf_used_pos=0; @@ -1088,11 +1136,30 @@ static int allocate_cmdbuf(struct noncache_mem* new_cmdbuf_addr,struct noncache } else { + #ifdef DEBUG_CMDBUF_ALLOC + if(cmdbuf_used[cmdbuf_used_pos]==0 && (global_cmdbuf_node[cmdbuf_used_pos]!=NULL ) && (cmdbuf_node_unexpected[cmdbuf_used_pos] == 0x55)) + { + pr_warn("vc8000e:unexpected cmdbuf_used[%d] is 0,but global_cmdbuf_node[%d] != NULL\n", + cmdbuf_used_pos,cmdbuf_used_pos); + cmdbuf_node_unexpected[cmdbuf_used_pos] = 0x55; + } + else if(cmdbuf_used[cmdbuf_used_pos]!=0 && (global_cmdbuf_node[cmdbuf_used_pos] == NULL ) && (cmdbuf_node_unexpected[cmdbuf_used_pos] == 0x55)) + { + pr_warn("vc8000e:unexpected cmdbuf_used[%d] != 0,but global_cmdbuf_node[%d] is NULL\n", + cmdbuf_used_pos,cmdbuf_used_pos); + cmdbuf_node_unexpected[cmdbuf_used_pos] = 0x55; + } + #endif cmdbuf_used_pos++; if(cmdbuf_used_pos>=TOTAL_DISCRETE_CMDBUF_NUM) cmdbuf_used_pos=0; + + if(cmdbuf_used_pos_start == cmdbuf_used_pos) //searched all,not find one,should return; + break; } } + spin_unlock_irqrestore(&vcmd_cmdbuf_alloc_lock, flags); + pr_err("%s:vc8000e: no cmdbuf found,cmdbuf_used_residual %d\n",__func__,cmdbuf_used_residual); return 0; } @@ -1493,8 +1560,13 @@ static long reserve_cmdbuf(struct file *filp,struct exchange_parameter* input_pa spin_lock_irqsave(&process_manager_obj->spinlock, flags); process_manager_obj->total_exe_time += input_para->executing_time; spin_unlock_irqrestore(&process_manager_obj->spinlock, flags); - if(wait_event_interruptible(process_manager_obj->wait_queue, wait_process_resource_rdy(process_manager_obj))) - return -1; + if(!wait_event_interruptible_timeout(process_manager_obj->wait_queue, wait_process_resource_rdy(process_manager_obj), + msecs_to_jiffies(500) )) + { + pr_err("vc8000e: wait_process_resource_rdy timeout! total_exe_time %lld\n",process_manager_obj->total_exe_time); + return -1; + } + new_cmdbuf_node=create_cmdbuf_node(); if(new_cmdbuf_node==NULL) @@ -1728,7 +1800,7 @@ static long link_and_run_cmdbuf(struct file *filp,struct exchange_parameter* inp dev = &hantrovcmd_data[cmdbuf_obj->core_id]; input_para->core_id = cmdbuf_obj->core_id; - PDEBUG("Allocate cmd buffer [%d] to core [%d]\n", cmdbuf_id, input_para->core_id); + PDEBUG("filp=%px, VCMD Link CMDBUF [%d] to core [%d]\n", (void *)filp, cmdbuf_id, input_para->core_id); //set ddr address for vcmd registers copy. if(dev->hw_version_id > HW_ID_1_0_C ) { @@ -1937,7 +2009,7 @@ static unsigned int wait_cmdbuf_ready(struct file *filp,u16 cmdbuf_id,u32 *irq_s check_cmdbuf_irq(dev,cmdbuf_obj,irq_status_ret), msecs_to_jiffies(500) ) ) { - pr_err("vcmd_wait_queue_0 timeout\n"); + pr_err("vc8000e:vcmd_wait_queue_0 timeout cmdbuf[%d]\n",cmdbuf_id); //abort the vcmd vcmd_write_register_value((const void *)dev->hwregs,dev->reg_mirror,HWIF_VCMD_START_TRIGGER,0); return -ETIME; @@ -1952,7 +2024,7 @@ bool hantrovcmd_devfreq_check_state(void) u32 state = 0; for (core_id = 0;core_id < total_vcmd_core_num; core_id++) { state = vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_WORK_STATE); - if((state != 3) && (state != 0)) //HW state pend or idle + if((state != 0) && (state != 3) ) //HW state pend or idle return false; } return true; @@ -2078,7 +2150,7 @@ static long hantrovcmd_ioctl(struct file *filp, ret = reserve_cmdbuf(filp,&input_para); if (ret == 0) copy_to_user((struct exchange_parameter*)arg,&input_para,sizeof(struct exchange_parameter)); - PDEBUG(" VCMD Reserve CMDBUF %d\n", input_para.cmdbuf_id); + PDEBUG("filp=%px, VCMD Reserve CMDBUF [%d] remain %d \n", (void *)filp, input_para.cmdbuf_id,cmdbuf_used_residual); return ret; } @@ -2088,7 +2160,7 @@ static long hantrovcmd_ioctl(struct file *filp, long retVal; copy_from_user(&input_para,(struct exchange_parameter*)arg,sizeof(struct exchange_parameter)); - PDEBUG("VCMD link and run cmdbuf\n"); + PDEBUG("filp=%px,VCMD link and run cmdbuf,[%d] \n",(void *)filp, input_para.cmdbuf_id); pm_runtime_resume_and_get(dev); if (process_manager_obj) process_manager_obj->pm_count++; @@ -2107,10 +2179,11 @@ static long hantrovcmd_ioctl(struct file *filp, __get_user(cmdbuf_id, (u16*)arg); /*high 16 bits are core id, low 16 bits are cmdbuf_id*/ - PDEBUG("VCMD wait for CMDBUF finishing. \n"); + PDEBUG("filp=%px,VCMD wait for CMDBUF finishing. %d,\n",filp,cmdbuf_id); //TODO tmp = wait_cmdbuf_ready(filp,cmdbuf_id,&irq_status_ret); + PDEBUG("filp=%px,VCMD wait for CMDBUF finished. %d,\n",filp,cmdbuf_id); cmdbuf_id=(u16)irq_status_ret; if (tmp==0) { @@ -2130,13 +2203,12 @@ static long hantrovcmd_ioctl(struct file *filp, __get_user(cmdbuf_id, (u16*)arg); /*16 bits are cmdbuf_id*/ - PDEBUG("VCMD release CMDBUF\n"); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); if (process_manager_obj) process_manager_obj->pm_count--; release_cmdbuf(filp,cmdbuf_id); + PDEBUG("filp=%px,VCMD release CMDBUF ,%d,remain %d \n",filp,cmdbuf_id,cmdbuf_used_residual); return 0; break; } @@ -2388,7 +2460,7 @@ static int hantrovcmd_open(struct inode *inode, struct file *filp) spin_unlock_irqrestore(&vcmd_process_manager_lock, flags); filp->private_data = process_manager_node->data; - PDEBUG("dev opened\n"); + PDEBUG("process node %px for filp opened %px\n", (void *)process_manager_node, (void *)filp); return result; } static int __hantrovcmd_release(struct inode *inode, struct file *filp) @@ -2406,9 +2478,8 @@ static int __hantrovcmd_release(struct inode *inode, struct file *filp) unsigned long flags; long retVal=0; - PDEBUG("dev closed for process %p\n", (void *)filp); - if (down_interruptible(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type])) - return -ERESTARTSYS; + PDEBUG("dev closed for process %px\n", (void *)filp); + down(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]); //should be wait,do not use interruptible interface for (core_id = 0;core_id < total_vcmd_core_num; core_id++) { @@ -2421,6 +2492,13 @@ static int __hantrovcmd_release(struct inode *inode, struct file *filp) if(new_cmdbuf_node==NULL) break; cmdbuf_obj_temp=(struct cmdbuf_obj*)new_cmdbuf_node->data; + if(cmdbuf_obj_temp->cmdbuf_id > 1) + { + PDEBUG("Process %px is releasing: checking cmdbuf %d (done %d,linked %d wstat %d) process %px. remain %d\n", + filp, cmdbuf_obj_temp->cmdbuf_id, cmdbuf_obj_temp->cmdbuf_run_done,cmdbuf_obj_temp->cmdbuf_data_linked, + dev[core_id].working_state, + cmdbuf_obj_temp->filp,cmdbuf_used_residual); + } if (dev[core_id].hwregs && (cmdbuf_obj_temp->filp == filp)) { if(cmdbuf_obj_temp->cmdbuf_run_done) @@ -2451,111 +2529,127 @@ static int __hantrovcmd_release(struct inode *inode, struct file *filp) bi_list_node* done_cmdbuf_node = NULL; int abort_cmdbuf_id; int loop_count = 0; + u32 irq_status_ret; - //abort the vcmd and wait - PDEBUG("Abort due to linked cmdbuf %d of current process.\n", cmdbuf_obj_temp->cmdbuf_id); -#ifdef VCMD_DEBUG_INTERNAL - printk_vcmd_register_debug((const void *)dev[core_id].hwregs, "Before trigger to 0"); -#endif - // disable abort interrupt - vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_START_TRIGGER,0); - vcmd_aborted = 1; - software_triger_abort = 1; -#ifdef VCMD_DEBUG_INTERNAL - printk_vcmd_register_debug((const void *)dev[core_id].hwregs,"After trigger to 0"); -#endif - // wait vcmd core aborted and vcmd enters IDLE mode. - while (vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_WORK_STATE)) { - loop_count++; - if (!(loop_count % 10)) { - u32 irq_status = vcmd_read_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET); - pr_err("hantrovcmd: expected idle state, but irq status = 0x%0x\n", irq_status); - pr_err("hantrovcmd: vcmd current status is %d\n", vcmd_get_register_value((const void *)dev[core_id].hwregs, dev[core_id].reg_mirror, HWIF_VCMD_WORK_STATE)); - } - mdelay(10); // wait 10ms - if (loop_count > 100) { // too long - pr_err("hantrovcmd: too long before vcmd core to IDLE state\n"); - process_manager_obj = (struct process_manager_obj*)filp->private_data; - if (process_manager_obj) - { - while(process_manager_obj->pm_count > 0) - { - pm_runtime_mark_last_busy(&dev[0].pdev->dev); - pm_runtime_put_autosuspend(&dev[0].pdev->dev); - process_manager_obj->pm_count--; + spin_unlock_irqrestore(dev[core_id].spinlock, flags); + if(wait_event_timeout(*dev[core_id].wait_queue, + check_cmdbuf_irq(dev,cmdbuf_obj_temp,&irq_status_ret),msecs_to_jiffies(1000)) + ) + { + spin_lock_irqsave(dev[core_id].spinlock, flags); + PDEBUG(" ## wait got cmdbuf[%d] done %d \n",cmdbuf_obj_temp->cmdbuf_id,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) + cmdbuf_obj_temp->process_manager_obj = NULL; + } + else + { + //abort the vcmd and wait + PDEBUG("Abort due to linked cmdbuf %d of current process.\n", cmdbuf_obj_temp->cmdbuf_id); + #ifdef VCMD_DEBUG_INTERNAL + printk_vcmd_register_debug((const void *)dev[core_id].hwregs, "Before trigger to 0"); + #endif + // disable abort interrupt + vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_START_TRIGGER,0); + vcmd_aborted = 1; + software_triger_abort = 1; + #ifdef VCMD_DEBUG_INTERNAL + printk_vcmd_register_debug((const void *)dev[core_id].hwregs,"After trigger to 0"); + #endif + // wait vcmd core aborted and vcmd enters IDLE mode. + while (vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_WORK_STATE)) { + loop_count++; + if (!(loop_count % 10)) { + u32 irq_status = vcmd_read_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET); + pr_err("hantrovcmd: expected idle state, but irq status = 0x%0x\n", irq_status); + pr_err("hantrovcmd: vcmd current status is %d\n", vcmd_get_register_value((const void *)dev[core_id].hwregs, dev[core_id].reg_mirror, HWIF_VCMD_WORK_STATE)); + } + mdelay(10); // wait 10ms + if (loop_count > 100) { // too long + pr_err("hantrovcmd: too long before vcmd core to IDLE state\n"); + process_manager_obj = (struct process_manager_obj*)filp->private_data; + if (process_manager_obj) + { + while(process_manager_obj->pm_count > 0) + { + pm_runtime_mark_last_busy(&dev[0].pdev->dev); + pm_runtime_put_autosuspend(&dev[0].pdev->dev); + process_manager_obj->pm_count--; + } + } + spin_unlock_irqrestore(dev[core_id].spinlock, flags); + up(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]); + return -ERESTARTSYS; } } - spin_unlock_irqrestore(dev[core_id].spinlock, flags); - up(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]); - return -ERESTARTSYS; - } - } - dev[core_id].working_state = WORKING_STATE_IDLE; - // clear interrupt & restore abort_e - if (vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_IRQ_ABORT)) { - PDEBUG("Abort interrupt triggered, now clear it to avoid abort int...\n"); - vcmd_write_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET, 0x1<<4); - PDEBUG("Now irq status = 0x%0x.\n", vcmd_read_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET)); - } - - abort_cmdbuf_id = vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_CMDBUF_EXECUTING_ID); - PDEBUG("Abort when executing cmd buf %d.\n", abort_cmdbuf_id); - dev[core_id].sw_cmdbuf_rdy_num = 0; - dev[core_id].duration_without_int = 0; - vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_EXE_CMDBUF_COUNT,0); - vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_RDY_CMDBUF_COUNT,0); - - /* Mark cmdbuf_run_done to 1 for all the cmd buf executed. */ - done_cmdbuf_node = dev[core_id].list_manager.head; - while (done_cmdbuf_node) { - if (!((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_run_done) { - ((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_run_done = 1; - ((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_data_linked = 0; - PDEBUG("Set cmdbuf [%d] cmdbuf_run_done to 1.\n", ((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_id); - } - if (((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_id == abort_cmdbuf_id) - break; - done_cmdbuf_node = done_cmdbuf_node->next; - } - if (cmdbuf_obj_temp->cmdbuf_run_done) { - /* current cmdbuf is in fact has been executed, but due to interrupt is not triggered, the status is not updated. - Just delink and remove it from the list. */ - if (done_cmdbuf_node && done_cmdbuf_node->data) { - PDEBUG("done_cmdbuf_node is cmdbuf [%d].\n", ((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_id); - } - done_cmdbuf_node = done_cmdbuf_node->next; - if (done_cmdbuf_node) - restart_cmdbuf = (struct cmdbuf_obj*)done_cmdbuf_node->data; - if (restart_cmdbuf) { - PDEBUG("Set restart cmdbuf [%d] via if.\n", restart_cmdbuf->cmdbuf_id); - } - } else { - last_cmdbuf_node = new_cmdbuf_node; - /* cmd buf num from aborted cmd buf to current cmdbuf_obj_temp */ - if (cmdbuf_obj_temp->cmdbuf_id != abort_cmdbuf_id) { - last_cmdbuf_node = new_cmdbuf_node->previous; - - while (last_cmdbuf_node && - ((struct cmdbuf_obj*)last_cmdbuf_node->data)->cmdbuf_id != abort_cmdbuf_id) { - restart_cmdbuf = (struct cmdbuf_obj*)last_cmdbuf_node->data; - last_cmdbuf_node = last_cmdbuf_node->previous; - dev[core_id].sw_cmdbuf_rdy_num++; - dev[core_id].duration_without_int += restart_cmdbuf->executing_time; - PDEBUG("Keep valid cmdbuf [%d] in the list.\n", restart_cmdbuf->cmdbuf_id); + dev[core_id].working_state = WORKING_STATE_IDLE; + // clear interrupt & restore abort_e + if (vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_IRQ_ABORT)) { + PDEBUG("Abort interrupt triggered, now clear it to avoid abort int...\n"); + vcmd_write_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET, 0x1<<4); + PDEBUG("Now irq status = 0x%0x.\n", vcmd_read_reg((const void *)dev[core_id].hwregs, VCMD_REGISTER_INT_STATUS_OFFSET)); } - } - if (restart_cmdbuf) { - PDEBUG("Set restart cmdbuf [%d] via else.\n", restart_cmdbuf->cmdbuf_id); - } - } - // remove first linked cmdbuf from list - vcmd_delink_rm_cmdbuf(&dev[core_id], new_cmdbuf_node); + abort_cmdbuf_id = vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_CMDBUF_EXECUTING_ID); + PDEBUG("Abort when executing cmd buf %d.\n", abort_cmdbuf_id); + dev[core_id].sw_cmdbuf_rdy_num = 0; + dev[core_id].duration_without_int = 0; + vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_EXE_CMDBUF_COUNT,0); + vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_RDY_CMDBUF_COUNT,0); + + /* Mark cmdbuf_run_done to 1 for all the cmd buf executed. */ + done_cmdbuf_node = dev[core_id].list_manager.head; + while (done_cmdbuf_node) { + if (!((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_run_done) { + ((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_run_done = 1; + ((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_data_linked = 0; + PDEBUG("Set cmdbuf [%d] cmdbuf_run_done to 1.\n", ((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_id); + } + if (((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_id == abort_cmdbuf_id) + break; + done_cmdbuf_node = done_cmdbuf_node->next; + } + if (cmdbuf_obj_temp->cmdbuf_run_done) { + /* current cmdbuf is in fact has been executed, but due to interrupt is not triggered, the status is not updated. + Just delink and remove it from the list. */ + if (done_cmdbuf_node && done_cmdbuf_node->data) { + PDEBUG("done_cmdbuf_node is cmdbuf [%d].\n", ((struct cmdbuf_obj*)done_cmdbuf_node->data)->cmdbuf_id); + } + done_cmdbuf_node = done_cmdbuf_node->next; + if (done_cmdbuf_node) + restart_cmdbuf = (struct cmdbuf_obj*)done_cmdbuf_node->data; + if (restart_cmdbuf) { + PDEBUG("Set restart cmdbuf [%d] via if.\n", restart_cmdbuf->cmdbuf_id); + } + } else { + last_cmdbuf_node = new_cmdbuf_node; + /* cmd buf num from aborted cmd buf to current cmdbuf_obj_temp */ + if (cmdbuf_obj_temp->cmdbuf_id != abort_cmdbuf_id) { + last_cmdbuf_node = new_cmdbuf_node->previous; + + while (last_cmdbuf_node && + ((struct cmdbuf_obj*)last_cmdbuf_node->data)->cmdbuf_id != abort_cmdbuf_id) { + restart_cmdbuf = (struct cmdbuf_obj*)last_cmdbuf_node->data; + last_cmdbuf_node = last_cmdbuf_node->previous; + dev[core_id].sw_cmdbuf_rdy_num++; + dev[core_id].duration_without_int += restart_cmdbuf->executing_time; + PDEBUG("Keep valid cmdbuf [%d] in the list.\n", restart_cmdbuf->cmdbuf_id); + } + } + if (restart_cmdbuf) { + PDEBUG("Set restart cmdbuf [%d] via else.\n", restart_cmdbuf->cmdbuf_id); + } + } + + // remove first linked cmdbuf from list + vcmd_delink_rm_cmdbuf(&dev[core_id], new_cmdbuf_node); + } } software_triger_abort = 0; release_cmdbuf_num++; - PDEBUG("release reserved cmdbuf\n"); + PDEBUG("vc8000e : release reserved cmdbuf,remain %d\n",cmdbuf_used_residual); } else if (vcmd_aborted && !cmdbuf_obj_temp->cmdbuf_run_done) { /* VCMD is aborted, need to re-calculate the duration_without_int */ @@ -2618,7 +2712,12 @@ static int __hantrovcmd_release(struct inode *inode, struct file *filp) wake_up_all(dev[core_id].wait_queue); } if(release_cmdbuf_num) - wake_up_interruptible_all(&vcmd_cmdbuf_memory_wait); + wake_up_all(&vcmd_cmdbuf_memory_wait); + + // free reserved but unlinkd node + // Here is powerfull free all this process reserved/linked cmdbuf + free_cmdbuf_not_linked_by_flip(filp); + spin_lock_irqsave(&vcmd_process_manager_lock, flags); process_manager_node = global_process_manager.head; while(1) @@ -2640,6 +2739,7 @@ static int __hantrovcmd_release(struct inode *inode, struct file *filp) } } //remove node from list + PDEBUG("process node %px for filp to be removed: %px remain %d\n", (void *)process_manager_node, (void *)process_manager_obj->filp,cmdbuf_used_residual); bi_list_remove_node(&global_process_manager,process_manager_node); spin_unlock_irqrestore(&vcmd_process_manager_lock, flags); free_process_manager_node(process_manager_node); @@ -2790,7 +2890,7 @@ static u32 ConfigAXIFE(u32 mode) #endif if (axife_hwregs[i][0] != NULL) { - PDEBUG("ConfigAXIFE: axife_hwregs[%d][0]=%p\n", i, axife_hwregs[i][0]); + PDEBUG("ConfigAXIFE: axife_hwregs[%d][0]=%px\n", i, axife_hwregs[i][0]); AXIFEEnable(axife_hwregs[i][0], mode); } } @@ -2810,7 +2910,7 @@ static u32 ConfigAXIFE(u32 mode) #endif if (axife_hwregs[i][1] != NULL) { - PDEBUG("ConfigAXIFE: axife_hwregs[%d][1]=%p\n", i, axife_hwregs[i][1]); + PDEBUG("ConfigAXIFE: axife_hwregs[%d][1]=%px\n", i, axife_hwregs[i][1]); AXIFEEnable(axife_hwregs[i][1] , mode); } } @@ -2858,7 +2958,7 @@ static u32 ConfigMMU(void) } else pr_info("MMU detected!\n"); - PDEBUG("mmu_hwregs[%d][0]=%p\n", i, mmu_hwregs[i][0]); + PDEBUG("mmu_hwregs[%d][0]=%px\n", i, mmu_hwregs[i][0]); } } @@ -2876,7 +2976,7 @@ static u32 ConfigMMU(void) mmu_hwregs[i][1] = (volatile u8*)ioremap(vcmd_core_array[i].vcmd_base_addr +vcmd_core_array[i].submodule_MMU_addr[1], MMU_SIZE); #endif - PDEBUG("mmu_hwregs[%d][1]=%p\n", i, mmu_hwregs[i][1]); + PDEBUG("mmu_hwregs[%d][1]=%px\n", i, mmu_hwregs[i][1]); } } mmu_status = MMUEnable(mmu_hwregs); @@ -3492,7 +3592,8 @@ static void read_main_module_all_registers(u32 main_module_type) //msleep(1000); hantrovcmd_isr(input_para.core_id, &hantrovcmd_data[input_para.core_id]); wait_cmdbuf_ready(NULL,input_para.cmdbuf_id,&irq_status_ret); - encoder_devfreq_record_idle( encoder_get_devfreq_priv_data() ); + + pr_info("%s:record_idle:busy_count = %d\n",__func__,encoder_get_devfreq_priv_data()->busy_count); status_base_virt_addr=vcmd_status_buf_mem_pool.virtualAddress + input_para.cmdbuf_id*CMDBUF_MAX_SIZE/4+(vcmd_manager[input_para.module_type][0]->vcmd_core_cfg.submodule_main_addr/2/4+0); pr_info("vc8000_vcmd_driver: main module register 0:0x%x\n",*status_base_virt_addr); pr_info("vc8000_vcmd_driver: main module register 80:0x%x\n",*(status_base_virt_addr+80)); @@ -3869,7 +3970,7 @@ void encoder_devfreq_record_busy(struct encoder_devfreq *devfreq) encoder_dev_clk_lock(); spin_lock_irqsave(&devfreq->lock, irqflags); busy_count = devfreq->busy_count; - //pr_info("record_busy:busy_count = %d\n",busy_count); + PDEBUG("record_busy:busy_count = %d\n",busy_count); if(devfreq->busy_count > 0) { devfreq->busy_count++; @@ -3898,7 +3999,7 @@ void encoder_devfreq_record_idle(struct encoder_devfreq *devfreq) return; spin_lock_irqsave(&devfreq->lock, irqflags); - //pr_info("record_idle:busy_count = %d\n",devfreq->busy_count); + PDEBUG("record_idle:busy_count = %d\n",devfreq->busy_count); if(devfreq->busy_count > 1) { devfreq->busy_count--; @@ -4102,7 +4203,7 @@ int encoder_devfreq_init(struct device *dev) int ret = 0; struct encoder_devfreq *devfreq = encoder_get_devfreq_priv_data(); - memset(devfreq,sizeof(struct encoder_devfreq),0); + memset(devfreq,0,sizeof(struct encoder_devfreq)); spin_lock_init(&devfreq->lock); init_waitqueue_head(&devfreq->target_freq_wait_queue); mutex_init(&devfreq->clk_mutex); @@ -4486,6 +4587,7 @@ int __init hantroenc_vcmd_probe(struct platform_device *pdev) cmdbuf_used_pos=1; cmdbuf_used[0]=1; cmdbuf_used_residual -=1; + pr_info(" CMDBUF[0] reserved,remain %d\n",cmdbuf_used_residual); pr_info("vc8000_vcmd_driver: module inserted. Major <%d>\n", hantrovcmd_major); @@ -4699,7 +4801,7 @@ static int vcmd_reserve_IO(void) /*read hwid and check validness and store it*/ hwid = (u32)ioread32(( void *)hantrovcmd_data[i].hwregs); - pr_info("vcmd_reserve_IO: hantrovcmd_data[%d].hwregs=0x%p\n",i, hantrovcmd_data[i].hwregs); + pr_info("vcmd_reserve_IO: hantrovcmd_data[%d].hwregs=0x%px\n",i, hantrovcmd_data[i].hwregs); pr_info("hwid=0x%08x\n", hwid); hantrovcmd_data[i].hw_version_id = hwid; @@ -4879,7 +4981,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; if(new_cmdbuf_node==NULL) { - pr_err("hantrovcmd_isr error cmdbuf_id !!\n"); + pr_err("hantrovcmd_isr error cmdbuf_id %d line %d!!\n",cmdbuf_id,__LINE__); spin_unlock_irqrestore(dev->spinlock, flags); return IRQ_HANDLED; } @@ -4951,7 +5053,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; if(new_cmdbuf_node==NULL) { - pr_err("hantrovcmd_isr error cmdbuf_id !!\n"); + pr_err("hantrovcmd_isr error cmdbuf_id %d line %d!!\n",cmdbuf_id,__LINE__); spin_unlock_irqrestore(dev->spinlock, flags); return IRQ_HANDLED; } @@ -5023,7 +5125,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; if(new_cmdbuf_node==NULL) { - pr_err("hantrovcmd_isr error cmdbuf_id !!\n"); + pr_err("hantrovcmd_isr error cmdbuf_id %d line %d!!\n",cmdbuf_id,__LINE__); spin_unlock_irqrestore(dev->spinlock, flags); return IRQ_HANDLED; } @@ -5163,7 +5265,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; if(new_cmdbuf_node==NULL) { - pr_err("hantrovcmd_isr error cmdbuf_id !!\n"); + pr_err("hantrovcmd_isr error cmdbuf_id %d line %d!!\n",cmdbuf_id,__LINE__); spin_unlock_irqrestore(dev->spinlock, flags); return IRQ_HANDLED; } @@ -5233,7 +5335,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id) new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; if(new_cmdbuf_node==NULL) { - pr_err("hantrovcmd_isr error cmdbuf_id !!\n"); + pr_err("hantrovcmd_isr error cmdbuf_id %d line %d!!\n",cmdbuf_id,__LINE__); spin_unlock_irqrestore(dev->spinlock, flags); return IRQ_HANDLED; }