MLK-11251 video: mxsfb: fix an auto reboot hang issue on imx7d-sdb board
authorFancy Fang <chen.fang@freescale.com>
Tue, 1 Sep 2015 05:03:01 +0000 (13:03 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:48:23 +0000 (14:48 -0500)
The hang issue is caused by the driver pan display function.
In the mxsfb, the pan display didn't wait the address flip
done before it exits. So this may cause the irq handler
running at the blank state which will cause system hang.
Two things are done in this patch:
1. Remove the 'flip_sem', since the pan_display is always
   called under the console lock hold.
2. Add a new completion 'flip_complete" to wait for the
   address flip done.

Signed-off-by: Fancy Fang <chen.fang@freescale.com>
(cherry picked from commit 7cb41403cb7cf1e977536af2a0422a214382c9f5)

Conflicts:
drivers/video/mxsfb.c

drivers/video/fbdev/mxsfb.c

index e7ac257..4a89f17 100644 (file)
@@ -217,7 +217,7 @@ struct mxsfb_info {
        bool wait4vsync;
        struct completion vsync_complete;
        ktime_t vsync_nf_timestamp;
-       struct semaphore flip_sem;
+       struct completion flip_complete;
        int cur_blank;
        int restore_blank;
        char disp_dev[32];
@@ -422,7 +422,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *dev_id)
                                host->base + LCDC_CTRL1 + REG_CLR);
                writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
                             host->base + LCDC_CTRL1 + REG_CLR);
-               up(&host->flip_sem);
+               complete(&host->flip_complete);
        }
 
        if (acked_status & CTRL1_UNDERFLOW_IRQ)
@@ -674,8 +674,6 @@ static int mxsfb_set_par(struct fb_info *fb_info)
                mxsfb_disable_controller(fb_info);
        }
 
-       sema_init(&host->flip_sem, 1);
-
        /* clear the FIFOs */
        writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
 
@@ -928,6 +926,7 @@ static int mxsfb_blank(int blank, struct fb_info *fb_info)
 static int mxsfb_pan_display(struct fb_var_screeninfo *var,
                struct fb_info *fb_info)
 {
+       int ret = 0;
        struct mxsfb_info *host = to_imxfb_host(fb_info);
        unsigned offset;
 
@@ -947,12 +946,9 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
 
-       offset = fb_info->fix.line_length * var->yoffset;
+       init_completion(&host->flip_complete);
 
-       if (down_timeout(&host->flip_sem, HZ / 2)) {
-               dev_err(fb_info->device, "timeout when waiting for flip irq\n");
-               return -ETIMEDOUT;
-       }
+       offset = fb_info->fix.line_length * var->yoffset;
 
        /* update on next VSYNC */
        writel(fb_info->fix.smem_start + offset,
@@ -961,7 +957,14 @@ static int mxsfb_pan_display(struct fb_var_screeninfo *var,
        writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
                host->base + LCDC_CTRL1 + REG_SET);
 
-       return 0;
+       ret = wait_for_completion_timeout(&host->flip_complete, HZ / 2);
+       if (ret < 0) {
+               dev_err(fb_info->device,
+                       "mxs wait for pan flip timeout\n");
+               ret = -ETIMEDOUT;
+       }
+
+       return ret;
 }
 
 static int mxsfb_mmap(struct fb_info *info, struct vm_area_struct *vma)