From: 陈恒明 <chm@rock-chips.com> Date: Thu, 15 Sep 2011 07:30:29 +0000 (+0800) Subject: rk29: vpu_service: fix task counting bug X-Git-Tag: firefly_0821_release~9767^2~25^2~9 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5f0d040a13dcfd6e3b3709853999e70cdb444874;p=firefly-linux-kernel-4.4.55.git rk29: vpu_service: fix task counting bug --- diff --git a/arch/arm/mach-rk29/vpu_service.c b/arch/arm/mach-rk29/vpu_service.c index b29bb4fbadda..6c26538a6231 100644 --- a/arch/arm/mach-rk29/vpu_service.c +++ b/arch/arm/mach-rk29/vpu_service.c @@ -190,9 +190,7 @@ static void vpu_reset(void) static void reg_deinit(vpu_reg *reg); static void vpu_service_session_clear(vpu_session *session) { - unsigned long flag; vpu_reg *reg, *n; - spin_lock_irqsave(&service.lock, flag); list_for_each_entry_safe(reg, n, &session->waiting, session_link) { reg_deinit(reg); } @@ -202,17 +200,14 @@ static void vpu_service_session_clear(vpu_session *session) list_for_each_entry_safe(reg, n, &session->done, session_link) { reg_deinit(reg); } - spin_unlock_irqrestore(&service.lock, flag); } static void vpu_service_dump(void) { int running; - unsigned long flag; vpu_reg *reg, *reg_tmp; vpu_session *session, *session_tmp; - spin_lock_irqsave(&service.lock, flag); running = atomic_read(&service.total_running); printk("total_running %d\n", running); @@ -234,7 +229,6 @@ static void vpu_service_dump(void) printk("done register set 0x%.8x\n", (unsigned int)reg); } } - spin_unlock_irqrestore(&service.lock, flag); } static void vpu_service_power_off(void) @@ -394,6 +388,7 @@ static void reg_from_run_to_done(vpu_reg *reg) } } atomic_sub(1, ®->session->task_running); + atomic_sub(1, &service.total_running); wake_up_interruptible_sync(®->session->wait); spin_unlock(&service.lock); } @@ -591,18 +586,22 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long pr_err("pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running)); ret = -ETIMEDOUT; } + spin_lock_irqsave(&service.lock, flag); if (ret < 0) { int task_running = atomic_read(&session->task_running); vpu_service_dump(); if (task_running) { atomic_set(&session->task_running, 0); + atomic_sub(task_running, &service.total_running); printk("%d task is running but not return, reset hardware...", task_running); vpu_reset(); printk("done\n"); } vpu_service_session_clear(session); + spin_unlock_irqrestore(&service.lock, flag); return ret; } + spin_unlock_irqrestore(&service.lock, flag); } spin_lock_irqsave(&service.lock, flag); reg = list_entry(session->done.next, vpu_reg, session_link); @@ -726,6 +725,7 @@ static int vpu_service_open(struct inode *inode, struct file *filp) static int vpu_service_release(struct inode *inode, struct file *filp) { int task_running; + unsigned long flag; vpu_session *session = (vpu_session *)filp->private_data; if (NULL == session) return -EINVAL; @@ -737,6 +737,7 @@ static int vpu_service_release(struct inode *inode, struct file *filp) } wake_up_interruptible_sync(&session->wait); + spin_lock_irqsave(&service.lock, flag); /* remove this filp from the asynchronusly notified filp's */ //vpu_service_fasync(-1, filp, 0); list_del(&session->list_session); @@ -744,6 +745,7 @@ static int vpu_service_release(struct inode *inode, struct file *filp) vpu_service_session_clear(session); kfree(session); + spin_unlock_irqrestore(&service.lock, flag); pr_debug("dev closed\n"); return 0; @@ -1001,7 +1003,6 @@ static irqreturn_t vdpu_isr(int irq, void *dev_id) /* clear dec IRQ */ writel(irq_status_dec & (~DEC_INTERRUPT_BIT), dev->hwregs + DEC_INTERRUPT_REGISTER); pr_debug("DEC IRQ received!\n"); - atomic_sub(1, &service.total_running); if (NULL == service.reg_codec) { pr_err("dec isr with no task waiting\n"); } else { @@ -1013,7 +1014,6 @@ static irqreturn_t vdpu_isr(int irq, void *dev_id) /* clear pp IRQ */ writel(irq_status_pp & (~DEC_INTERRUPT_BIT), dev->hwregs + PP_INTERRUPT_REGISTER); pr_debug("PP IRQ received!\n"); - atomic_sub(1, &service.total_running); if (NULL == service.reg_pproc) { pr_err("pp isr with no task waiting\n"); } else { @@ -1035,7 +1035,6 @@ static irqreturn_t vepu_isr(int irq, void *dev_id) /* clear enc IRQ */ writel(irq_status & (~ENC_INTERRUPT_BIT), dev->hwregs + ENC_INTERRUPT_REGISTER); pr_debug("ENC IRQ received!\n"); - atomic_sub(1, &service.total_running); if (NULL == service.reg_codec) { pr_err("enc isr with no task waiting\n"); } else {