From: Mark Yao Date: Mon, 1 Dec 2014 00:47:24 +0000 (+0800) Subject: rk_fb: fix iommu problem when hdmi plug or unplug. X-Git-Tag: firefly_0821_release~4427 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=6ba051470a10c3a6fa34b6fc758aaa5ebf115034;p=firefly-linux-kernel-4.4.55.git rk_fb: fix iommu problem when hdmi plug or unplug. There are two thread will update the win config, one is update_regs handler, another is hdmi hotplug thread, win config maybe modify by another thread unexpectly, then vop scan umap address, cause iommu crash, so we need use a mutex to protect win config. Signed-off-by: Mark Yao --- diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index dd39d61b6c3b..5944e9fc36ad 100755 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -1935,10 +1935,12 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv, (win_data->data_format == YUV420 || win_data->data_format == YUV420_A)) continue; + mutex_lock(&dev_drv->win_config); rk_fb_update_win(dev_drv, win, win_data); win->state = 1; dev_drv->ops->set_par(dev_drv, i); dev_drv->ops->pan_display(dev_drv, i); + mutex_unlock(&dev_drv->win_config); #if defined(CONFIG_ROCKCHIP_IOMMU) if (dev_drv->iommu_enabled) { g_last_addr[i] = win_data->reg_area_data[0].smem_start + @@ -3541,8 +3543,10 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) info->var.grayscale |= (dev_drv->cur_screen->mode.xres << 8) + (dev_drv->cur_screen->mode.yres << 20); + mutex_lock(&dev_drv->win_config); info->fbops->fb_set_par(info); info->fbops->fb_pan_display(&info->var, info); + mutex_unlock(&dev_drv->win_config); if (dev_drv->ops->dsp_black) dev_drv->ops->dsp_black(dev_drv, 0); @@ -3596,8 +3600,11 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id) (dev_drv->cur_screen->xsize << 8) + (dev_drv->cur_screen->ysize << 20); } + + mutex_lock(&dev_drv->win_config); info->fbops->fb_set_par(info); info->fbops->fb_pan_display(&info->var, info); + mutex_unlock(&dev_drv->win_config); } } } @@ -3684,9 +3691,11 @@ int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id) } } + mutex_lock(&dev_drv->win_config); info->fbops->fb_set_par(info); - /* info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0); */ dev_drv->ops->cfg_done(dev_drv); + mutex_unlock(&dev_drv->win_config); + return 0; } @@ -3911,6 +3920,7 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb, init_completion(&dev_drv->frame_done); spin_lock_init(&dev_drv->cpl_lock); mutex_init(&dev_drv->fb_win_id_mutex); + mutex_init(&dev_drv->win_config); dev_drv->ops->fb_win_remap(dev_drv, dev_drv->fb_win_map); dev_drv->first_frame = 1; dev_drv->overscan.left = 100; diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index 1c4ec6d791e6..2227a217f891 100755 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -562,6 +562,7 @@ struct rk_lcdc_driver { struct rk_fb_reg_area_data reg_area_data; struct mutex fb_win_id_mutex; + struct mutex win_config; struct completion frame_done; /*sync for pan_display,whe we set a new frame address to lcdc register,we must