summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFancy Fang <chen.fang@freescale.com>2015-09-01 13:03:01 +0800
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:23:04 +0800
commitfbcbb58910d247c92fd5d840b0b4688bafae4f94 (patch)
treecebb7d84eef12af221de4f4f5e61d75e6eb4e2b3
parentee1056ad16a1c571c7a452cc4f93b567a40b1273 (diff)
MLK-11251 video: mxsfb: fix an auto reboot hang issue on imx7d-sdb board
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
-rw-r--r--drivers/video/fbdev/mxsfb.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
index e7ac2574d907..4a89f1736390 100644
--- a/drivers/video/fbdev/mxsfb.c
+++ b/drivers/video/fbdev/mxsfb.c
@@ -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)