video: rk322x: fix crash on suspend/resume
authorMark Yao <mark.yao@rock-chips.com>
Wed, 20 Jan 2016 08:06:33 +0000 (16:06 +0800)
committerHuang Jiachai <hjc@rock-chips.com>
Mon, 25 Jan 2016 12:40:46 +0000 (20:40 +0800)
Skip the update_reg_update when vop is suspend, because
register access would hang up the system when vop is suspend.

Change-Id: I01e712736df9a6de88440ee67c624a26ea752d85
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/video/rockchip/lcdc/rk322x_lcdc.c
drivers/video/rockchip/rk_fb.c

index 50e1ceb80de866965977bd73961b0f69e95aecf3..0ec00873161163c274a5e707ad7b1aeb065fe339 100644 (file)
@@ -2525,6 +2525,7 @@ static int vop_early_suspend(struct rk_lcdc_driver *dev_drv)
                return 0;
 
        dev_drv->suspend_flag = 1;
+       smp_wmb();
        flush_kthread_worker(&dev_drv->update_regs_worker);
 
        if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
@@ -2538,8 +2539,10 @@ static int vop_early_suspend(struct rk_lcdc_driver *dev_drv)
                vop_msk_reg(vop_dev, SYS_CTRL, V_VOP_STANDBY_EN(1));
                vop_cfg_done(vop_dev);
 
-               if (dev_drv->iommu_enabled && dev_drv->mmu_dev)
-                               rockchip_iovmm_deactivate(dev_drv->dev);
+               if (dev_drv->iommu_enabled && dev_drv->mmu_dev) {
+                       mdelay(50);
+                       rockchip_iovmm_deactivate(dev_drv->dev);
+               }
 
                spin_unlock(&vop_dev->reg_lock);
        }
@@ -3640,7 +3643,7 @@ static void vop_shutdown(struct platform_device *pdev)
        struct rk_lcdc_driver *dev_drv = &vop_dev->driver;
 
        dev_drv->suspend_flag = 1;
-       mdelay(100);
+       smp_wmb();
        flush_kthread_worker(&dev_drv->update_regs_worker);
        kthread_stop(dev_drv->update_regs_thread);
        vop_deint(vop_dev);
index 66aecd006d6f2d303a5ed1357cc623be2a5101f3..35aa8be4486de63ec72be6ef72466fa94856e4d4 100644 (file)
@@ -1816,6 +1816,17 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
        int count = 100;
        long timeout;
        int pagefault = 0;
+
+       if (dev_drv->suspend_flag == 1) {
+#ifdef H_USE_FENCE
+               sw_sync_timeline_inc(dev_drv->timeline, 1);
+#endif
+               for (i = 0; i < regs->win_num; i++) {
+                       win_data = &regs->reg_win_data[i];
+                       rk_fb_free_dma_buf(dev_drv, win_data);
+               }
+               return;
+       }
        /* acq_fence wait */
        for (i = 0; i < regs->win_num; i++) {
                win_data = &regs->reg_win_data[i];