From c0aa55a912d6cf30926bedd56676411b1f286949 Mon Sep 17 00:00:00 2001 From: Hongzhang Yang Date: Thu, 17 Jan 2013 14:52:34 +0800 Subject: [PATCH] ENGR00240506 fix a bug in abnormal abort handling Bug: If app quits before FW is loaded to VPU, VPU driver will hang in vpu_release(). Root cause: In that case, if BIT_BUSY_FLAG=1, vpu_release may reset VPU and run FW init code, but FW has not been loaded. Solution: - Don't run FW init code after reset since VPU lib can load it next time. - If PC=0, which means VPU never runs, don't check BIT_BUSY_FLAG Signed-off-by: Hongzhang Yang --- drivers/mxc/vpu/mxc_vpu.c | 85 +++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c index bbb89f7339e3..708e8e97112a 100644 --- a/drivers/mxc/vpu/mxc_vpu.c +++ b/drivers/mxc/vpu/mxc_vpu.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2006-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -553,59 +553,58 @@ static int vpu_release(struct inode *inode, struct file *filp) /* Wait for vpu go to idle state */ clk_enable(vpu_clk); - timeout = jiffies + HZ; - while (READ_REG(BIT_BUSY_FLAG)) { - msleep(1); - if (time_after(jiffies, timeout)) { - printk(KERN_WARNING "VPU timeout during release\n"); - break; - } - } - clk_disable(vpu_clk); - - /* Clean up interrupt */ - cancel_work_sync(&vpu_data.work); - flush_workqueue(vpu_data.workqueue); - irq_status = 0; - - clk_enable(vpu_clk); - if (READ_REG(BIT_BUSY_FLAG)) { + if (READ_REG(BIT_CUR_PC)) { - if (cpu_is_mx51() || cpu_is_mx53()) { - printk(KERN_ERR - "fatal error: can't gate/power off when VPU is busy\n"); - clk_disable(vpu_clk); - mutex_unlock(&vpu_data.lock); - return -EFAULT; + timeout = jiffies + HZ; + while (READ_REG(BIT_BUSY_FLAG)) { + msleep(1); + if (time_after(jiffies, timeout)) { + printk(KERN_WARNING "VPU timeout during release\n"); + break; + } } + clk_disable(vpu_clk); -#ifdef CONFIG_SOC_IMX6Q - if (cpu_is_mx6dl() || cpu_is_mx6q()) { - WRITE_REG(0x11, 0x10F0); - timeout = jiffies + HZ; - while (READ_REG(0x10F4) != 0x77) { - msleep(1); - if (time_after(jiffies, timeout)) - break; - } + /* Clean up interrupt */ + cancel_work_sync(&vpu_data.work); + flush_workqueue(vpu_data.workqueue); + irq_status = 0; - if (READ_REG(0x10F4) != 0x77) { + clk_enable(vpu_clk); + if (READ_REG(BIT_BUSY_FLAG)) { + + if (cpu_is_mx51() || cpu_is_mx53()) { printk(KERN_ERR "fatal error: can't gate/power off when VPU is busy\n"); - WRITE_REG(0x0, 0x10F0); clk_disable(vpu_clk); mutex_unlock(&vpu_data.lock); return -EFAULT; - } else { - if (vpu_plat->reset) - vpu_plat->reset(); - WRITE_REG(0x1, BIT_BUSY_FLAG); - WRITE_REG(0x1, BIT_CODE_RUN); - while (READ_REG(BIT_BUSY_FLAG)) - ; } - } + +#ifdef CONFIG_SOC_IMX6Q + if (cpu_is_mx6dl() || cpu_is_mx6q()) { + WRITE_REG(0x11, 0x10F0); + timeout = jiffies + HZ; + while (READ_REG(0x10F4) != 0x77) { + msleep(1); + if (time_after(jiffies, timeout)) + break; + } + + if (READ_REG(0x10F4) != 0x77) { + printk(KERN_ERR + "fatal error: can't gate/power off when VPU is busy\n"); + WRITE_REG(0x0, 0x10F0); + clk_disable(vpu_clk); + mutex_unlock(&vpu_data.lock); + return -EFAULT; + } else { + if (vpu_plat->reset) + vpu_plat->reset(); + } + } #endif + } } clk_disable(vpu_clk); -- 2.39.5