vc8000d-kernel: fixup vcmdbuf release leak issue

This issue is reported in TLV-299.
This commit fixed allocate_cmdbuf may infinite loop
and leak of release the cmdbuf only reserved but not
link_and_run.
If cmdbuf not run done when release,do not firstly abort,
instead wait done event reduce abort failed.

Add cmdbuf id and line info for error log.
Fixed busy count record idle twice in read module all
regs issue.

Signed-off-by: xianbing Zhu <xianbing.zhu@linux.alibaba.com>
Change-Id: Ieb0b751d18a1ed65fe198e3d75a6953dabf15ef8
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
This commit is contained in:
Han Gao
2024-07-20 15:32:15 +08:00
committed by Han Gao
parent 719387f851
commit 9ee78c8b51
3 changed files with 231 additions and 126 deletions

View File

@@ -2348,7 +2348,7 @@ void decoder_devfreq_record_busy(struct decoder_devfreq *devfreq)
decoder_dev_clk_lock(); decoder_dev_clk_lock();
spin_lock_irqsave(&devfreq->lock, irqflags); spin_lock_irqsave(&devfreq->lock, irqflags);
busy_count = devfreq->busy_count; 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) if(devfreq->busy_count > 0)
{ {
devfreq->busy_count++; devfreq->busy_count++;
@@ -2376,7 +2376,7 @@ void decoder_devfreq_record_idle(struct decoder_devfreq *devfreq)
if (!devfreq) if (!devfreq)
return; return;
spin_lock_irqsave(&devfreq->lock, irqflags); 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) if(devfreq->busy_count > 1)
{ {
devfreq->busy_count--; devfreq->busy_count--;
@@ -2581,7 +2581,7 @@ int decoder_devfreq_init(struct device *dev)
int ret = 0; int ret = 0;
struct decoder_devfreq *devfreq = decoder_get_devfreq_priv_data(); struct decoder_devfreq *devfreq = decoder_get_devfreq_priv_data();
memset(devfreq,sizeof(struct decoder_devfreq),0); memset(devfreq,0,sizeof(struct decoder_devfreq));
spin_lock_init(&devfreq->lock); spin_lock_init(&devfreq->lock);
init_waitqueue_head(&devfreq->target_freq_wait_queue); init_waitqueue_head(&devfreq->target_freq_wait_queue);
mutex_init(&devfreq->clk_mutex); mutex_init(&devfreq->clk_mutex);

View File

@@ -1425,7 +1425,7 @@ static enum MMUStatus MMUMemNodeMap(struct addr_desc *addr, struct file *filp) {
page_count = (addr->size - 1)/PAGE_SIZE + 1; page_count = (addr->size - 1)/PAGE_SIZE + 1;
GetPhysicalAddress(addr->virtual_address, &address); GetPhysicalAddress(addr->virtual_address, &address);
MMUDEBUG(" *****MMU map address*****%x\n", address); MMUDEBUG(" *****MMU map address*****%llx phys_to_virt %lx\n", address,(unsigned long)phys_to_virt(address));
if(address >= REGION_IN_START && if(address >= REGION_IN_START &&
address + addr->size < REGION_IN_END) address + addr->size < REGION_IN_END)
e = MMU_REGION_IN; e = MMU_REGION_IN;
@@ -1505,7 +1505,7 @@ static enum MMUStatus MMUMemNodeMap(struct addr_desc *addr, struct file *filp) {
MMUDEBUG(" MMU_MTLB_SHIFT %d MMU_STLB_4K_SHIFT %d\n", MMU_MTLB_SHIFT, MMU_STLB_4K_SHIFT); MMUDEBUG(" MMU_MTLB_SHIFT %d MMU_STLB_4K_SHIFT %d\n", MMU_MTLB_SHIFT, MMU_STLB_4K_SHIFT);
MMUDEBUG(" MMUMemNodeMap map total %d pages in region %d\nMTLB/STLB starts %d/%d, MTLB/STLB ends %d/%d\n", MMUDEBUG(" MMUMemNodeMap map total %d pages in region %d\nMTLB/STLB starts %d/%d, MTLB/STLB ends %d/%d\n",
page_count, (u32)e, p->mtlb_start, p->stlb_start, p->mtlb_end, p->stlb_end); page_count, (u32)e, p->mtlb_start, p->stlb_start, p->mtlb_end, p->stlb_end);
MMUDEBUG(" MMUMemNodeMap map %p -> 0x%08x\n", addr->virtual_address, addr->bus_address); MMUDEBUG(" MMUMemNodeMap map %px -> 0x%08x\n", addr->virtual_address, addr->bus_address);
ReleaseMutex(g_mmu->page_table_mutex); ReleaseMutex(g_mmu->page_table_mutex);

View File

@@ -580,6 +580,7 @@ struct process_manager_obj
u64 total_exe_time; u64 total_exe_time;
spinlock_t spinlock; spinlock_t spinlock;
u32 pm_count; u32 pm_count;
wait_queue_head_t wait_queue; wait_queue_head_t wait_queue;
} ; } ;
@@ -602,7 +603,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. 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_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. u8 cmdbuf_data_linked; //0 :not linked, 1:linked.
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 cmdbuf_need_remove; // if 0, not need to remove CMDBUF; 1 CMDBUF can be removed if it is not the last CMDBUF;
u32 waited; // if 0, the cmd buf hasn't been waited, otherwise, has been waited. u32 waited; // if 0, the cmd buf hasn't been waited, otherwise, has been waited.
u8 has_end_cmdbuf; //if 1, the last opcode is end opCode. u8 has_end_cmdbuf; //if 1, the last opcode is end opCode.
@@ -896,8 +897,47 @@ static void free_cmdbuf_mem(u16 cmdbuf_id )
spin_lock_irqsave(&vcmd_cmdbuf_alloc_lock, flags); spin_lock_irqsave(&vcmd_cmdbuf_alloc_lock, flags);
cmdbuf_used[cmdbuf_id]=0; cmdbuf_used[cmdbuf_id]=0;
cmdbuf_used_residual +=1; cmdbuf_used_residual +=1;
PDEBUG(" ## real free cmdbuf[%d]\n",cmdbuf_id);
spin_unlock_irqrestore(&vcmd_cmdbuf_alloc_lock, flags); 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) static bi_list_node* create_cmdbuf_node(void)
@@ -907,8 +947,13 @@ static bi_list_node* create_cmdbuf_node(void)
struct noncache_mem new_cmdbuf_addr; struct noncache_mem new_cmdbuf_addr;
struct noncache_mem new_status_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("wait allocate_cmdbuf timeout\n");
return NULL; return NULL;
}
#ifdef DYNAMIC_MALLOC_VCMDNODE #ifdef DYNAMIC_MALLOC_VCMDNODE
cmdbuf_obj=create_cmdbuf_obj(); cmdbuf_obj=create_cmdbuf_obj();
#else #else
@@ -1028,18 +1073,21 @@ static u64 calculate_executing_time_after_node_high_priority(bi_list_node* exe_c
} }
return time_run_all; return time_run_all;
} }
#ifdef DEBUG_CMDBUF_ALLOC
int cmdbuf_node_unexpected[TOTAL_DISCRETE_CMDBUF_NUM];
#endif
/**********************************************************************************************************\ /**********************************************************************************************************\
*cmdbuf pool management *cmdbuf pool management
\***********************************************************************************************************/ \***********************************************************************************************************/
static int allocate_cmdbuf(struct noncache_mem* new_cmdbuf_addr,struct noncache_mem* new_status_cmdbuf_addr) static int allocate_cmdbuf(struct noncache_mem* new_cmdbuf_addr,struct noncache_mem* new_status_cmdbuf_addr)
{ {
unsigned long flags; unsigned long flags;
u16 cmdbuf_used_pos_start = cmdbuf_used_pos;
spin_lock_irqsave(&vcmd_cmdbuf_alloc_lock, flags); spin_lock_irqsave(&vcmd_cmdbuf_alloc_lock, flags);
if(cmdbuf_used_residual==0) if(cmdbuf_used_residual==0)
{ {
spin_unlock_irqrestore(&vcmd_cmdbuf_alloc_lock, flags); spin_unlock_irqrestore(&vcmd_cmdbuf_alloc_lock, flags);
pr_err("%s:no empty cmdbuf\n",__func__);
//no empty cmdbuf //no empty cmdbuf
return 0; return 0;
} }
@@ -1060,6 +1108,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->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->size=CMDBUF_MAX_SIZE;
new_status_cmdbuf_addr->cmdbuf_id = cmdbuf_used_pos; 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++; cmdbuf_used_pos++;
if(cmdbuf_used_pos>=TOTAL_DISCRETE_CMDBUF_NUM) if(cmdbuf_used_pos>=TOTAL_DISCRETE_CMDBUF_NUM)
cmdbuf_used_pos=0; cmdbuf_used_pos=0;
@@ -1068,11 +1117,30 @@ static int allocate_cmdbuf(struct noncache_mem* new_cmdbuf_addr,struct noncache
} }
else 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("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("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++; cmdbuf_used_pos++;
if(cmdbuf_used_pos>=TOTAL_DISCRETE_CMDBUF_NUM) if(cmdbuf_used_pos>=TOTAL_DISCRETE_CMDBUF_NUM)
cmdbuf_used_pos=0; 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: no cmdbuf found,cmdbuf_used_residual %d\n",__func__,cmdbuf_used_residual);
return 0; return 0;
} }
@@ -1113,7 +1181,9 @@ static int select_vcmd(bi_list_node* new_cmdbuf_node)
size_t exe_cmdbuf_addr=0; size_t exe_cmdbuf_addr=0;
struct cmdbuf_obj* cmdbuf_obj_temp=NULL; struct cmdbuf_obj* cmdbuf_obj_temp=NULL;
u32 cmdbuf_id=0; u32 cmdbuf_id=0;
struct process_manager_obj* process_manager_temp;
cmdbuf_obj=(struct cmdbuf_obj*)new_cmdbuf_node->data; cmdbuf_obj=(struct cmdbuf_obj*)new_cmdbuf_node->data;
//there is an empty vcmd to be used //there is an empty vcmd to be used
while(1) while(1)
{ {
@@ -1446,7 +1516,7 @@ static long reserve_cmdbuf(struct file *filp,struct exchange_parameter* input_pa
{ {
return -1; return -1;
} }
PDEBUG("reserve cmdbuf filp %p\n", (void *)filp); PDEBUG("reserve cmdbuf filp %px\n", (void *)filp);
spin_lock_irqsave(&vcmd_process_manager_lock, flags); spin_lock_irqsave(&vcmd_process_manager_lock, flags);
process_manager_node = global_process_manager.head; process_manager_node = global_process_manager.head;
while(1) while(1)
@@ -1459,7 +1529,7 @@ static long reserve_cmdbuf(struct file *filp,struct exchange_parameter* input_pa
return -1; return -1;
} }
process_manager_obj = (struct process_manager_obj*)process_manager_node->data; process_manager_obj = (struct process_manager_obj*)process_manager_node->data;
PDEBUG("reserve loop: node %p, filp %p\n", (void *)process_manager_node, PDEBUG("reserve loop: node %px, filp %px\n", (void *)process_manager_node,
(void *)process_manager_obj->filp); (void *)process_manager_obj->filp);
if (filp == process_manager_obj->filp) if (filp == process_manager_obj->filp)
break; break;
@@ -1470,13 +1540,19 @@ static long reserve_cmdbuf(struct file *filp,struct exchange_parameter* input_pa
spin_lock_irqsave(&process_manager_obj->spinlock, flags); spin_lock_irqsave(&process_manager_obj->spinlock, flags);
process_manager_obj->total_exe_time += input_para->executing_time; process_manager_obj->total_exe_time += input_para->executing_time;
spin_unlock_irqrestore(&process_manager_obj->spinlock, flags); spin_unlock_irqrestore(&process_manager_obj->spinlock, flags);
if(wait_event_interruptible(process_manager_obj->wait_queue, wait_process_resource_rdy(process_manager_obj))) if(!wait_event_interruptible_timeout(process_manager_obj->wait_queue, wait_process_resource_rdy(process_manager_obj),
return -1; msecs_to_jiffies(500) ))
{
pr_err("wait_process_resource_rdy timeout! total_exe_time %lld\n",process_manager_obj->total_exe_time);
return -1;
}
new_cmdbuf_node=create_cmdbuf_node(); new_cmdbuf_node=create_cmdbuf_node();
if(new_cmdbuf_node==NULL) if(new_cmdbuf_node==NULL)
return -1; return -1;
cmdbuf_obj = (struct cmdbuf_obj* )new_cmdbuf_node->data; cmdbuf_obj = (struct cmdbuf_obj* )new_cmdbuf_node->data;
cmdbuf_obj->module_type = input_para->module_type; cmdbuf_obj->module_type = input_para->module_type;
cmdbuf_obj->priority = input_para->priority; cmdbuf_obj->priority = input_para->priority;
@@ -1559,6 +1635,7 @@ static long release_cmdbuf(struct file *filp,u16 cmdbuf_id)
up(&vcmd_reserve_cmdbuf_sem[module_type]); up(&vcmd_reserve_cmdbuf_sem[module_type]);
return 0; return 0;
} }
static long release_cmdbuf_node(bi_list* list,bi_list_node*cmdbuf_node) static long release_cmdbuf_node(bi_list* list,bi_list_node*cmdbuf_node)
{ {
bi_list_node* new_cmdbuf_node=NULL; bi_list_node* new_cmdbuf_node=NULL;
@@ -1710,7 +1787,7 @@ static long link_and_run_cmdbuf(struct file *filp,struct exchange_parameter* inp
dev = &hantrovcmd_data[cmdbuf_obj->core_id]; dev = &hantrovcmd_data[cmdbuf_obj->core_id];
input_para->core_id = cmdbuf_obj->core_id; input_para->core_id = cmdbuf_obj->core_id;
PDEBUG("filp=%p, VCMD Link CMDBUF [%d] to core [%d]\n", (void *)filp, 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. //set ddr address for vcmd registers copy.
if(dev->hw_version_id > HW_ID_1_0_C ) if(dev->hw_version_id > HW_ID_1_0_C )
{ {
@@ -1953,11 +2030,11 @@ 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)) check_cmdbuf_irq(dev,cmdbuf_obj,irq_status_ret),msecs_to_jiffies(500))
) )
{ {
pr_err("vcmd_wait_queue_0 timeout"); pr_err("vcmd_wait_queue_0 timeout cmdbuf[%d]\n",cmdbuf_id);
return -ETIME; return -ETIME;
} }
PDEBUG("filp=%p, VCMD Wait CMDBUF [%d]\n", (void *)filp, cmdbuf_id); PDEBUG("filp=%px, VCMD Wait CMDBUF [%d]\n", (void *)filp, cmdbuf_id);
return 0; return 0;
} else { } else {
if (check_mc_cmdbuf_irq(filp, cmdbuf_obj, irq_status_ret)) if (check_mc_cmdbuf_irq(filp, cmdbuf_obj, irq_status_ret))
@@ -2096,7 +2173,7 @@ long hantrovcmd_ioctl(struct file *filp,
ret = reserve_cmdbuf(filp,&input_para); ret = reserve_cmdbuf(filp,&input_para);
if (ret == 0) if (ret == 0)
copy_to_user((struct exchange_parameter*)arg,&input_para,sizeof(struct exchange_parameter)); copy_to_user((struct exchange_parameter*)arg,&input_para,sizeof(struct exchange_parameter));
PDEBUG("filp=%p, VCMD Reserve CMDBUF [%d]\n", (void *)filp, 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; return ret;
} }
@@ -2106,7 +2183,7 @@ long hantrovcmd_ioctl(struct file *filp,
long retVal; long retVal;
copy_from_user(&input_para,(struct exchange_parameter*)arg,sizeof(struct exchange_parameter)); copy_from_user(&input_para,(struct exchange_parameter*)arg,sizeof(struct exchange_parameter));
PDEBUG("filp=%p,VCMD link and run cmdbuf,[%d] \n",(void *)filp, input_para.cmdbuf_id); PDEBUG("filp=%px,VCMD link and run cmdbuf,[%d] \n",(void *)filp, input_para.cmdbuf_id);
if (process_manager_obj) if (process_manager_obj)
process_manager_obj->pm_count++; process_manager_obj->pm_count++;
@@ -2126,11 +2203,11 @@ long hantrovcmd_ioctl(struct file *filp,
__get_user(cmdbuf_id, (u16*)arg); __get_user(cmdbuf_id, (u16*)arg);
/*high 16 bits are core id, low 16 bits are cmdbuf_id*/ /*high 16 bits are core id, low 16 bits are cmdbuf_id*/
PDEBUG("filp=%p,VCMD wait for CMDBUF finishing. %d,\n",filp,cmdbuf_id); PDEBUG("filp=%px,VCMD wait for CMDBUF finishing. %d,\n",filp,cmdbuf_id);
//TODO //TODO
tmp = wait_cmdbuf_ready(filp,cmdbuf_id,&irq_status_ret); tmp = wait_cmdbuf_ready(filp,cmdbuf_id,&irq_status_ret);
PDEBUG("filp=%p,VCMD wait for CMDBUF finished. %d,\n",filp,cmdbuf_id); PDEBUG("filp=%px,VCMD wait for CMDBUF finished. %d,\n",filp,cmdbuf_id);
cmdbuf_id=(u16)irq_status_ret; cmdbuf_id=(u16)irq_status_ret;
if (tmp==0) if (tmp==0)
{ {
@@ -2151,11 +2228,11 @@ long hantrovcmd_ioctl(struct file *filp,
__get_user(cmdbuf_id, (u16*)arg); __get_user(cmdbuf_id, (u16*)arg);
/*16 bits are cmdbuf_id*/ /*16 bits are cmdbuf_id*/
PDEBUG("filp=%p,VCMD release CMDBUF ,%d\n",filp,cmdbuf_id);
if (process_manager_obj) if (process_manager_obj)
process_manager_obj->pm_count--; process_manager_obj->pm_count--;
release_cmdbuf(filp,cmdbuf_id); release_cmdbuf(filp,cmdbuf_id);
PDEBUG("filp=%px,VCMD release CMDBUF ,%d,remain %d \n",filp,cmdbuf_id,cmdbuf_used_residual);
return 0; return 0;
break; break;
} }
@@ -2403,7 +2480,7 @@ int hantrovcmd_open(struct inode *inode, struct file *filp)
filp->private_data = process_manager_node->data; filp->private_data = process_manager_node->data;
PDEBUG("dev opened\n"); PDEBUG("dev opened\n");
PDEBUG("process node %p for filp opened %p\n", (void *)process_manager_node, (void *)filp); PDEBUG("process node %px for filp opened %px\n", (void *)process_manager_node, (void *)filp);
return result; return result;
} }
@@ -2422,7 +2499,7 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
unsigned long flags; unsigned long flags;
long retVal=0; long retVal=0;
PDEBUG("dev closed for process %p via hantrovcmd_release\n", (void *)filp); PDEBUG("dev closed for process %px via hantrovcmd_release\n", (void *)filp);
down(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]); down(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]);
for (core_id = 0;core_id < total_vcmd_core_num; core_id++) for (core_id = 0;core_id < total_vcmd_core_num; core_id++)
@@ -2436,8 +2513,13 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
if(new_cmdbuf_node==NULL) if(new_cmdbuf_node==NULL)
break; break;
cmdbuf_obj_temp=(struct cmdbuf_obj*)new_cmdbuf_node->data; cmdbuf_obj_temp=(struct cmdbuf_obj*)new_cmdbuf_node->data;
PDEBUG("Process %p is releasing: checking cmdbuf %d of process %p.\n", if(cmdbuf_obj_temp->cmdbuf_id > 1)
filp, cmdbuf_obj_temp->cmdbuf_id, cmdbuf_obj_temp->filp); {
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 (dev[core_id].hwregs && (cmdbuf_obj_temp->filp == filp))
{ {
if(cmdbuf_obj_temp->cmdbuf_run_done) if(cmdbuf_obj_temp->cmdbuf_run_done)
@@ -2473,105 +2555,122 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
bi_list_node* done_cmdbuf_node = NULL; bi_list_node* done_cmdbuf_node = NULL;
int abort_cmdbuf_id; int abort_cmdbuf_id;
int loop_count = 0; int loop_count = 0;
u32 irq_status_ret;
//abort the vcmd and wait spin_unlock_irqrestore(dev[core_id].spinlock, flags);
pr_info("Abort due to linked cmdbuf %d of current process.\n", cmdbuf_obj_temp->cmdbuf_id); if(wait_event_timeout(*dev[core_id].wait_queue,
printk_vcmd_register_debug((const void *)dev->hwregs, "Before trigger to 0"); check_cmdbuf_irq(dev,cmdbuf_obj_temp,&irq_status_ret),msecs_to_jiffies(1000))
// disable abort interrupt )
//vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_IRQ_ABORT_EN,0); {
vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_START_TRIGGER,0); spin_lock_irqsave(dev[core_id].spinlock, flags);
vcmd_aborted = 1; 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;
printk_vcmd_register_debug((const void *)dev->hwregs,"After trigger to 0"); retVal=release_cmdbuf_node(&dev[core_id].list_manager,new_cmdbuf_node);
// Wait vcmd core aborted and vcmd enters IDLE mode. if(retVal==1)
//while (dev[core_id].working_state != WORKING_STATE_IDLE) { cmdbuf_obj_temp->process_manager_obj = NULL;
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->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->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");
spin_unlock_irqrestore(dev[core_id].spinlock, flags);
pm_runtime_mark_last_busy(&dev[0].pdev->dev);
pm_runtime_put_sync_suspend(&dev[0].pdev->dev);
up(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]);
return -ERESTARTSYS;
}
} }
dev[core_id].working_state = WORKING_STATE_IDLE; else
// 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)) { spin_lock_irqsave(dev[core_id].spinlock, flags);
PDEBUG("Abort interrupt triggered, now clear it to avoid abort int...\n"); //abort the vcmd and wait
vcmd_write_reg((const void *)dev->hwregs, VCMD_REGISTER_INT_STATUS_OFFSET, 0x1<<4); pr_info("Abort due to linked cmdbuf %d of current process.\n", cmdbuf_obj_temp->cmdbuf_id);
PDEBUG("Now irq status = 0x%0x.\n", vcmd_read_reg((const void *)dev->hwregs, VCMD_REGISTER_INT_STATUS_OFFSET)); printk_vcmd_register_debug((const void *)dev->hwregs, "Before trigger to 0");
} // disable abort interrupt
//printk_vcmd_register_debug((const void *)dev->hwregs, "vcmd status to IDLE"); //vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_IRQ_ABORT_EN,0);
vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_START_TRIGGER,0);
vcmd_aborted = 1;
abort_cmdbuf_id = vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_CMDBUF_EXECUTING_ID); printk_vcmd_register_debug((const void *)dev->hwregs,"After trigger to 0");
PDEBUG("Abort when executing cmd buf %d.\n", abort_cmdbuf_id); // Wait vcmd core aborted and vcmd enters IDLE mode.
dev[core_id].sw_cmdbuf_rdy_num = 0; //while (dev[core_id].working_state != WORKING_STATE_IDLE) {
dev[core_id].duration_without_int = 0; while (vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_WORK_STATE)) {
vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_EXE_CMDBUF_COUNT,0); loop_count++;
vcmd_write_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_RDY_CMDBUF_COUNT,0); if (!(loop_count % 10)) {
u32 irq_status = vcmd_read_reg((const void *)dev->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->hwregs, dev[core_id].reg_mirror, HWIF_VCMD_WORK_STATE));
}
mdelay(50); // wait 10ms
if (loop_count > 100) { // too long
pr_err("hantrovcmd: too long before vcmd core to IDLE state\n");
/* 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);
}
if (done_cmdbuf_node) {
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 && spin_unlock_irqrestore(dev[core_id].spinlock, flags);
((struct cmdbuf_obj*)last_cmdbuf_node->data)->cmdbuf_id != abort_cmdbuf_id) { pm_runtime_mark_last_busy(&dev[0].pdev->dev);
restart_cmdbuf = (struct cmdbuf_obj*)last_cmdbuf_node->data; pm_runtime_put_sync_suspend(&dev[0].pdev->dev);
last_cmdbuf_node = last_cmdbuf_node->previous; up(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]);
dev[core_id].sw_cmdbuf_rdy_num++; return -ERESTARTSYS;
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;
if (restart_cmdbuf) { // clear interrupt & restore abort_e
PDEBUG("Set restart cmdbuf [%d] via else.\n", restart_cmdbuf->cmdbuf_id); 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->hwregs, VCMD_REGISTER_INT_STATUS_OFFSET, 0x1<<4);
PDEBUG("Now irq status = 0x%0x.\n", vcmd_read_reg((const void *)dev->hwregs, VCMD_REGISTER_INT_STATUS_OFFSET));
}
//printk_vcmd_register_debug((const void *)dev->hwregs, "vcmd status to IDLE");
// remove first linked cmdbuf from list abort_cmdbuf_id = vcmd_get_register_value((const void *)dev[core_id].hwregs,dev[core_id].reg_mirror,HWIF_VCMD_CMDBUF_EXECUTING_ID);
vcmd_delink_rm_cmdbuf(&dev[core_id], new_cmdbuf_node); 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);
}
if (done_cmdbuf_node) {
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);
}
} }
release_cmdbuf_num++; release_cmdbuf_num++;
PDEBUG("release reserved cmdbuf\n"); PDEBUG("release reserved cmdbuf,remain %d\n",cmdbuf_used_residual);
} else if (vcmd_aborted && !cmdbuf_obj_temp->cmdbuf_run_done) { } else if (vcmd_aborted && !cmdbuf_obj_temp->cmdbuf_run_done) {
/* VCMD is aborted, need to re-calculate the duration_without_int */ /* VCMD is aborted, need to re-calculate the duration_without_int */
if (!restart_cmdbuf) if (!restart_cmdbuf)
@@ -2630,7 +2729,12 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
} }
if(release_cmdbuf_num) 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); spin_lock_irqsave(&vcmd_process_manager_lock, flags);
process_manager_node = global_process_manager.head; process_manager_node = global_process_manager.head;
while(1) while(1)
@@ -2645,7 +2749,7 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
//remove node from list //remove node from list
PDEBUG("process node %p for filp to be removed: %p\n", (void *)process_manager_node, (void *)process_manager_obj->filp); 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); bi_list_remove_node(&global_process_manager,process_manager_node);
spin_unlock_irqrestore(&vcmd_process_manager_lock, flags); spin_unlock_irqrestore(&vcmd_process_manager_lock, flags);
free_process_manager_node(process_manager_node); free_process_manager_node(process_manager_node);
@@ -3140,7 +3244,7 @@ static void read_main_module_all_registers(u32 main_module_type)
//msleep(1000); //msleep(1000);
hantrovcmd_isr(input_para.core_id, &hantrovcmd_data[input_para.core_id]); hantrovcmd_isr(input_para.core_id, &hantrovcmd_data[input_para.core_id]);
wait_cmdbuf_ready(NULL,input_para.cmdbuf_id,&irq_status_ret); wait_cmdbuf_ready(NULL,input_para.cmdbuf_id,&irq_status_ret);
decoder_devfreq_record_idle( decoder_get_devfreq_priv_data() ); pr_info("%s:record_idle:busy_count = %d\n",__func__,decoder_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); 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 0:0x%x\n",*status_base_virt_addr);
pr_info("vc8000_vcmd_driver: main module register 50:0x%08x\n",*(status_base_virt_addr+50)); pr_info("vc8000_vcmd_driver: main module register 50:0x%08x\n",*(status_base_virt_addr+50));
@@ -3293,6 +3397,7 @@ int hantrovcmd_init(struct platform_device *pdev)
cmdbuf_used_pos=1; cmdbuf_used_pos=1;
cmdbuf_used[0]=1; cmdbuf_used[0]=1;
cmdbuf_used_residual -=1; cmdbuf_used_residual -=1;
pr_info(" CMDBUF[0] reserved,remain %d\n",cmdbuf_used_residual);
create_kernel_process_manager(); create_kernel_process_manager();
for(i=0;i<MAX_VCMD_TYPE;i++) for(i=0;i<MAX_VCMD_TYPE;i++)
@@ -3618,7 +3723,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id)
new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id];
if(new_cmdbuf_node==NULL) 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); spin_unlock_irqrestore(dev->spinlock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -3681,7 +3786,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id)
new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id];
if(new_cmdbuf_node==NULL) 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); spin_unlock_irqrestore(dev->spinlock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -3754,7 +3859,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id)
new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id];
if(new_cmdbuf_node==NULL) 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); spin_unlock_irqrestore(dev->spinlock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -3823,7 +3928,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id)
new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id];
if(new_cmdbuf_node==NULL) 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); spin_unlock_irqrestore(dev->spinlock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -3896,7 +4001,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id)
new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id];
if(new_cmdbuf_node==NULL) 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); spin_unlock_irqrestore(dev->spinlock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -3967,7 +4072,7 @@ static irqreturn_t hantrovcmd_isr(int irq, void *dev_id)
new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id]; new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id];
if(new_cmdbuf_node==NULL) 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); spin_unlock_irqrestore(dev->spinlock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }