]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00240506 fix a bug in abnormal abort handling
authorHongzhang Yang <Hongzhang.Yang@freescale.com>
Thu, 17 Jan 2013 06:52:34 +0000 (14:52 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:51 +0000 (08:35 +0200)
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 <Hongzhang.Yang@freescale.com>
drivers/mxc/vpu/mxc_vpu.c

index bbb89f7339e3defec6ce920bd324df78021d9e60..708e8e97112a95918f187b8dd91b029ac59b6d5d 100644 (file)
@@ -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);