summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Liu <r64343@freescale.com>2015-03-13 16:50:19 +0800
committerJason Liu <r64343@freescale.com>2015-05-13 10:19:50 +0800
commit04cb927116e1e6d29e42bccd52472d6925972d4e (patch)
tree478cf01ce6ff0d826c263a54211318b9d731e8b3
parent949dba5dd9d2d63c5a3e2c986042d819ec410774 (diff)
MLK-10803 media: mxc: vout: fix the race condition for multiple disaplay
There will some race condition such as the followings: - multiple open concurrence will cause the vout refer to the stall vout-> v4l_wq or the vout-> v4l_wq is not initialized correctly. - multiple open concurrence will cause the global fb setting race-condition, thus, it will have the “set_crop error exceeds width/height” or “mxc_v4l2_output v4l2_out.30: can not find output” This patch fix the above issue by adding the protection for the critical section. Reviewed-by: Liu Ying <b17645@freescale.com> Signed-off-by: Jason Liu <r64343@freescale.com> (cherry picked from commit 226bc39341bc2526f4d36b88c65ad27c5fac157c)
-rw-r--r--drivers/media/platform/mxc/output/mxc_vout.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/media/platform/mxc/output/mxc_vout.c b/drivers/media/platform/mxc/output/mxc_vout.c
index 1b55f10f0d53..fd94d3395608 100644
--- a/drivers/media/platform/mxc/output/mxc_vout.c
+++ b/drivers/media/platform/mxc/output/mxc_vout.c
@@ -233,6 +233,9 @@ static struct mxc_vout_fb g_fb_setting[MAX_FB_NUM];
static int config_disp_output(struct mxc_vout_output *vout);
static void release_disp_output(struct mxc_vout_output *vout);
+static DEFINE_MUTEX(gfb_mutex);
+static DEFINE_MUTEX(gfbi_mutex);
+
static unsigned int get_frame_size(struct mxc_vout_output *vout)
{
unsigned int size;
@@ -313,6 +316,7 @@ static void update_display_setting(void)
struct fb_info *fbi;
struct v4l2_rect bg_crop_bounds[2];
+ mutex_lock(&gfb_mutex);
for (i = 0; i < num_registered_fb; i++) {
fbi = registered_fb[i];
@@ -347,6 +351,7 @@ static void update_display_setting(void)
g_fb_setting[i].crop_bounds =
bg_crop_bounds[g_fb_setting[i].ipu_id];
}
+ mutex_unlock(&gfb_mutex);
}
/* called after g_fb_setting filled by update_display_setting */
@@ -356,6 +361,10 @@ static int update_setting_from_fbi(struct mxc_vout_output *vout,
int i;
bool found = false;
+ mutex_lock(&gfbi_mutex);
+
+ update_display_setting();
+
for (i = 0; i < MAX_FB_NUM; i++) {
if (g_fb_setting[i].name) {
if (!strcmp(fbi->fix.id, g_fb_setting[i].name)) {
@@ -373,6 +382,7 @@ static int update_setting_from_fbi(struct mxc_vout_output *vout,
if (!found) {
v4l2_err(vout->vfd->v4l2_dev, "can not find output\n");
+ mutex_unlock(&gfbi_mutex);
return -EINVAL;
}
strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name));
@@ -397,6 +407,7 @@ static int update_setting_from_fbi(struct mxc_vout_output *vout,
else
vout->task.output.format = IPU_PIX_FMT_RGB565;
+ mutex_unlock(&gfbi_mutex);
return 0;
}
@@ -940,6 +951,7 @@ static int mxc_vout_release(struct file *file)
if (!vout)
return 0;
+ mutex_lock(&vout->task_lock);
if (--vout->open_cnt == 0) {
q = &vout->vbq;
if (q->streaming)
@@ -952,6 +964,7 @@ static int mxc_vout_release(struct file *file)
ret = videobuf_mmap_free(q);
}
+ mutex_unlock(&vout->task_lock);
return ret;
}
@@ -965,11 +978,11 @@ static int mxc_vout_open(struct file *file)
if (vout == NULL)
return -ENODEV;
+ mutex_lock(&vout->task_lock);
if (vout->open_cnt++ == 0) {
vout->ctrl_rotate = 0;
vout->ctrl_vflip = 0;
vout->ctrl_hflip = 0;
- update_display_setting();
ret = update_setting_from_fbi(vout, vout->fbi);
if (ret < 0)
goto err;
@@ -999,6 +1012,7 @@ static int mxc_vout_open(struct file *file)
file->private_data = vout;
err:
+ mutex_unlock(&vout->task_lock);
return ret;
}