Commit 643800d5 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] cx231xx: use core-assisted lock

Instead of doing its own lock, use core-assisted one. As a bonus, it
will do the proper unlock during queue wait events. This fixes a
long-standing bug where softwares like tvtime would hang if you try to
use cx231xx-alsa.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0f861583
...@@ -1019,8 +1019,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, ...@@ -1019,8 +1019,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct cx231xx_fh *fh = priv; struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev; struct cx231xx *dev = fh->dev;
mutex_lock(&dev->lock);
f->fmt.pix.width = dev->width; f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height; f->fmt.pix.height = dev->height;
f->fmt.pix.pixelformat = dev->format->fourcc; f->fmt.pix.pixelformat = dev->format->fourcc;
...@@ -1030,8 +1028,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, ...@@ -1030,8 +1028,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.field = V4L2_FIELD_INTERLACED; f->fmt.pix.field = V4L2_FIELD_INTERLACED;
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -1092,26 +1088,20 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -1092,26 +1088,20 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
if (rc < 0) if (rc < 0)
return rc; return rc;
mutex_lock(&dev->lock);
vidioc_try_fmt_vid_cap(file, priv, f); vidioc_try_fmt_vid_cap(file, priv, f);
fmt = format_by_fourcc(f->fmt.pix.pixelformat); fmt = format_by_fourcc(f->fmt.pix.pixelformat);
if (!fmt) { if (!fmt)
rc = -EINVAL; return -EINVAL;
goto out;
}
if (videobuf_queue_is_busy(&fh->vb_vidq)) { if (videobuf_queue_is_busy(&fh->vb_vidq)) {
cx231xx_errdev("%s queue busy\n", __func__); cx231xx_errdev("%s queue busy\n", __func__);
rc = -EBUSY; return -EBUSY;
goto out;
} }
if (dev->stream_on && !fh->stream_on) { if (dev->stream_on && !fh->stream_on) {
cx231xx_errdev("%s device in use by another fh\n", __func__); cx231xx_errdev("%s device in use by another fh\n", __func__);
rc = -EBUSY; return -EBUSY;
goto out;
} }
/* set new image size */ /* set new image size */
...@@ -1123,8 +1113,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -1123,8 +1113,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
call_all(dev, video, s_mbus_fmt, &mbus_fmt); call_all(dev, video, s_mbus_fmt, &mbus_fmt);
v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
out:
mutex_unlock(&dev->lock);
return rc; return rc;
} }
...@@ -1151,7 +1139,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) ...@@ -1151,7 +1139,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm); cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm);
mutex_lock(&dev->lock);
dev->norm = *norm; dev->norm = *norm;
/* Adjusts width/height, if needed */ /* Adjusts width/height, if needed */
...@@ -1172,8 +1159,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) ...@@ -1172,8 +1159,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
dev->width = f.fmt.pix.width; dev->width = f.fmt.pix.width;
dev->height = f.fmt.pix.height; dev->height = f.fmt.pix.height;
mutex_unlock(&dev->lock);
/* do mode control overrides */ /* do mode control overrides */
cx231xx_do_mode_ctrl_overrides(dev); cx231xx_do_mode_ctrl_overrides(dev);
...@@ -1242,8 +1227,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) ...@@ -1242,8 +1227,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
if (0 == INPUT(i)->type) if (0 == INPUT(i)->type)
return -EINVAL; return -EINVAL;
mutex_lock(&dev->lock);
video_mux(dev, i); video_mux(dev, i);
if (INPUT(i)->type == CX231XX_VMUX_TELEVISION || if (INPUT(i)->type == CX231XX_VMUX_TELEVISION ||
...@@ -1254,7 +1237,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) ...@@ -1254,7 +1237,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
call_all(dev, core, s_std, dev->norm); call_all(dev, core, s_std, dev->norm);
} }
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -1330,9 +1312,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, ...@@ -1330,9 +1312,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
} }
*qc = cx231xx_ctls[i].v; *qc = cx231xx_ctls[i].v;
mutex_lock(&dev->lock);
call_all(dev, core, queryctrl, qc); call_all(dev, core, queryctrl, qc);
mutex_unlock(&dev->lock);
if (qc->type) if (qc->type)
return 0; return 0;
...@@ -1351,9 +1331,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, ...@@ -1351,9 +1331,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
if (rc < 0) if (rc < 0)
return rc; return rc;
mutex_lock(&dev->lock);
call_all(dev, core, g_ctrl, ctrl); call_all(dev, core, g_ctrl, ctrl);
mutex_unlock(&dev->lock);
return rc; return rc;
} }
...@@ -1368,9 +1346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, ...@@ -1368,9 +1346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
if (rc < 0) if (rc < 0)
return rc; return rc;
mutex_lock(&dev->lock);
call_all(dev, core, s_ctrl, ctrl); call_all(dev, core, s_ctrl, ctrl);
mutex_unlock(&dev->lock);
return rc; return rc;
} }
...@@ -1410,9 +1386,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) ...@@ -1410,9 +1386,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
if (0 != t->index) if (0 != t->index)
return -EINVAL; return -EINVAL;
#if 0 #if 0
mutex_lock(&dev->lock);
call_all(dev, tuner, s_tuner, t); call_all(dev, tuner, s_tuner, t);
mutex_unlock(&dev->lock);
#endif #endif
return 0; return 0;
} }
...@@ -1423,14 +1397,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, ...@@ -1423,14 +1397,11 @@ static int vidioc_g_frequency(struct file *file, void *priv,
struct cx231xx_fh *fh = priv; struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev; struct cx231xx *dev = fh->dev;
mutex_lock(&dev->lock);
f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
f->frequency = dev->ctl_freq; f->frequency = dev->ctl_freq;
call_all(dev, tuner, g_frequency, f); call_all(dev, tuner, g_frequency, f);
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -1461,13 +1432,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, ...@@ -1461,13 +1432,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
/* set pre channel change settings in DIF first */ /* set pre channel change settings in DIF first */
rc = cx231xx_tuner_pre_channel_change(dev); rc = cx231xx_tuner_pre_channel_change(dev);
mutex_lock(&dev->lock);
dev->ctl_freq = f->frequency; dev->ctl_freq = f->frequency;
call_all(dev, tuner, s_frequency, f); call_all(dev, tuner, s_frequency, f);
mutex_unlock(&dev->lock);
/* set post channel change settings in DIF first */ /* set post channel change settings in DIF first */
rc = cx231xx_tuner_post_channel_change(dev); rc = cx231xx_tuner_post_channel_change(dev);
...@@ -1655,9 +1622,7 @@ static int vidioc_g_register(struct file *file, void *priv, ...@@ -1655,9 +1622,7 @@ static int vidioc_g_register(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
} }
mutex_lock(&dev->lock);
call_all(dev, core, g_register, reg); call_all(dev, core, g_register, reg);
mutex_unlock(&dev->lock);
return ret; return ret;
} }
...@@ -1822,9 +1787,7 @@ static int vidioc_s_register(struct file *file, void *priv, ...@@ -1822,9 +1787,7 @@ static int vidioc_s_register(struct file *file, void *priv,
break; break;
} }
mutex_lock(&dev->lock);
call_all(dev, core, s_register, reg); call_all(dev, core, s_register, reg);
mutex_unlock(&dev->lock);
return ret; return ret;
} }
...@@ -1861,7 +1824,6 @@ static int vidioc_streamon(struct file *file, void *priv, ...@@ -1861,7 +1824,6 @@ static int vidioc_streamon(struct file *file, void *priv,
if (rc < 0) if (rc < 0)
return rc; return rc;
mutex_lock(&dev->lock);
rc = res_get(fh); rc = res_get(fh);
if (likely(rc >= 0)) if (likely(rc >= 0))
...@@ -1869,8 +1831,6 @@ static int vidioc_streamon(struct file *file, void *priv, ...@@ -1869,8 +1831,6 @@ static int vidioc_streamon(struct file *file, void *priv,
call_all(dev, video, s_stream, 1); call_all(dev, video, s_stream, 1);
mutex_unlock(&dev->lock);
return rc; return rc;
} }
...@@ -1891,15 +1851,11 @@ static int vidioc_streamoff(struct file *file, void *priv, ...@@ -1891,15 +1851,11 @@ static int vidioc_streamoff(struct file *file, void *priv,
if (type != fh->type) if (type != fh->type)
return -EINVAL; return -EINVAL;
mutex_lock(&dev->lock);
cx25840_call(dev, video, s_stream, 0); cx25840_call(dev, video, s_stream, 0);
videobuf_streamoff(&fh->vb_vidq); videobuf_streamoff(&fh->vb_vidq);
res_free(fh); res_free(fh);
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -1954,8 +1910,6 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, ...@@ -1954,8 +1910,6 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
if (rc < 0) if (rc < 0)
return rc; return rc;
mutex_lock(&dev->lock);
f->fmt.sliced.service_set = 0; f->fmt.sliced.service_set = 0;
call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced); call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
...@@ -1963,7 +1917,6 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, ...@@ -1963,7 +1917,6 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
if (f->fmt.sliced.service_set == 0) if (f->fmt.sliced.service_set == 0)
rc = -EINVAL; rc = -EINVAL;
mutex_unlock(&dev->lock);
return rc; return rc;
} }
...@@ -1978,9 +1931,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, ...@@ -1978,9 +1931,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
if (rc < 0) if (rc < 0)
return rc; return rc;
mutex_lock(&dev->lock);
call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced); call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
mutex_unlock(&dev->lock);
if (f->fmt.sliced.service_set == 0) if (f->fmt.sliced.service_set == 0)
return -EINVAL; return -EINVAL;
...@@ -2130,9 +2081,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) ...@@ -2130,9 +2081,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
strcpy(t->name, "Radio"); strcpy(t->name, "Radio");
t->type = V4L2_TUNER_RADIO; t->type = V4L2_TUNER_RADIO;
mutex_lock(&dev->lock);
call_all(dev, tuner, s_tuner, t); call_all(dev, tuner, s_tuner, t);
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -2163,9 +2112,7 @@ static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) ...@@ -2163,9 +2112,7 @@ static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
if (0 != t->index) if (0 != t->index)
return -EINVAL; return -EINVAL;
mutex_lock(&dev->lock);
call_all(dev, tuner, s_tuner, t); call_all(dev, tuner, s_tuner, t);
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -2224,8 +2171,6 @@ static int cx231xx_v4l2_open(struct file *filp) ...@@ -2224,8 +2171,6 @@ static int cx231xx_v4l2_open(struct file *filp)
break; break;
} }
mutex_lock(&dev->lock);
cx231xx_videodbg("open dev=%s type=%s users=%d\n", cx231xx_videodbg("open dev=%s type=%s users=%d\n",
video_device_node_name(vdev), v4l2_type_names[fh_type], video_device_node_name(vdev), v4l2_type_names[fh_type],
dev->users); dev->users);
...@@ -2235,7 +2180,6 @@ static int cx231xx_v4l2_open(struct file *filp) ...@@ -2235,7 +2180,6 @@ static int cx231xx_v4l2_open(struct file *filp)
if (errCode < 0) { if (errCode < 0) {
cx231xx_errdev cx231xx_errdev
("Device locked on digital mode. Can't open analog\n"); ("Device locked on digital mode. Can't open analog\n");
mutex_unlock(&dev->lock);
return -EBUSY; return -EBUSY;
} }
#endif #endif
...@@ -2243,7 +2187,6 @@ static int cx231xx_v4l2_open(struct file *filp) ...@@ -2243,7 +2187,6 @@ static int cx231xx_v4l2_open(struct file *filp)
fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL); fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
if (!fh) { if (!fh) {
cx231xx_errdev("cx231xx-video.c: Out of memory?!\n"); cx231xx_errdev("cx231xx-video.c: Out of memory?!\n");
mutex_unlock(&dev->lock);
return -ENOMEM; return -ENOMEM;
} }
fh->dev = dev; fh->dev = dev;
...@@ -2293,7 +2236,7 @@ static int cx231xx_v4l2_open(struct file *filp) ...@@ -2293,7 +2236,7 @@ static int cx231xx_v4l2_open(struct file *filp)
NULL, &dev->video_mode.slock, NULL, &dev->video_mode.slock,
fh->type, V4L2_FIELD_INTERLACED, fh->type, V4L2_FIELD_INTERLACED,
sizeof(struct cx231xx_buffer), sizeof(struct cx231xx_buffer),
fh, NULL); fh, &dev->lock);
if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
/* Set the required alternate setting VBI interface works in /* Set the required alternate setting VBI interface works in
Bulk mode only */ Bulk mode only */
...@@ -2305,11 +2248,9 @@ static int cx231xx_v4l2_open(struct file *filp) ...@@ -2305,11 +2248,9 @@ static int cx231xx_v4l2_open(struct file *filp)
NULL, &dev->vbi_mode.slock, NULL, &dev->vbi_mode.slock,
fh->type, V4L2_FIELD_SEQ_TB, fh->type, V4L2_FIELD_SEQ_TB,
sizeof(struct cx231xx_buffer), sizeof(struct cx231xx_buffer),
fh, NULL); fh, &dev->lock);
} }
mutex_unlock(&dev->lock);
return errCode; return errCode;
} }
...@@ -2366,7 +2307,6 @@ static int cx231xx_v4l2_close(struct file *filp) ...@@ -2366,7 +2307,6 @@ static int cx231xx_v4l2_close(struct file *filp)
cx231xx_videodbg("users=%d\n", dev->users); cx231xx_videodbg("users=%d\n", dev->users);
mutex_lock(&dev->lock);
cx231xx_videodbg("users=%d\n", dev->users); cx231xx_videodbg("users=%d\n", dev->users);
if (res_check(fh)) if (res_check(fh))
res_free(fh); res_free(fh);
...@@ -2384,12 +2324,10 @@ static int cx231xx_v4l2_close(struct file *filp) ...@@ -2384,12 +2324,10 @@ static int cx231xx_v4l2_close(struct file *filp)
if (dev->state & DEV_DISCONNECTED) { if (dev->state & DEV_DISCONNECTED) {
if (atomic_read(&dev->devlist_count) > 0) { if (atomic_read(&dev->devlist_count) > 0) {
cx231xx_release_resources(dev); cx231xx_release_resources(dev);
mutex_unlock(&dev->lock);
kfree(dev); kfree(dev);
dev = NULL; dev = NULL;
return 0; return 0;
} }
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -2405,7 +2343,6 @@ static int cx231xx_v4l2_close(struct file *filp) ...@@ -2405,7 +2343,6 @@ static int cx231xx_v4l2_close(struct file *filp)
kfree(fh); kfree(fh);
dev->users--; dev->users--;
wake_up_interruptible_nr(&dev->open, 1); wake_up_interruptible_nr(&dev->open, 1);
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -2417,7 +2354,6 @@ static int cx231xx_v4l2_close(struct file *filp) ...@@ -2417,7 +2354,6 @@ static int cx231xx_v4l2_close(struct file *filp)
free the remaining resources */ free the remaining resources */
if (dev->state & DEV_DISCONNECTED) { if (dev->state & DEV_DISCONNECTED) {
cx231xx_release_resources(dev); cx231xx_release_resources(dev);
mutex_unlock(&dev->lock);
kfree(dev); kfree(dev);
dev = NULL; dev = NULL;
return 0; return 0;
...@@ -2439,7 +2375,6 @@ static int cx231xx_v4l2_close(struct file *filp) ...@@ -2439,7 +2375,6 @@ static int cx231xx_v4l2_close(struct file *filp)
kfree(fh); kfree(fh);
dev->users--; dev->users--;
wake_up_interruptible_nr(&dev->open, 1); wake_up_interruptible_nr(&dev->open, 1);
mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -2461,9 +2396,7 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, ...@@ -2461,9 +2396,7 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
(fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) { (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) {
mutex_lock(&dev->lock);
rc = res_get(fh); rc = res_get(fh);
mutex_unlock(&dev->lock);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
return rc; return rc;
...@@ -2488,9 +2421,7 @@ static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait) ...@@ -2488,9 +2421,7 @@ static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
if (rc < 0) if (rc < 0)
return rc; return rc;
mutex_lock(&dev->lock);
rc = res_get(fh); rc = res_get(fh);
mutex_unlock(&dev->lock);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
return POLLERR; return POLLERR;
...@@ -2515,9 +2446,7 @@ static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -2515,9 +2446,7 @@ static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
if (rc < 0) if (rc < 0)
return rc; return rc;
mutex_lock(&dev->lock);
rc = res_get(fh); rc = res_get(fh);
mutex_unlock(&dev->lock);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
return rc; return rc;
...@@ -2539,7 +2468,7 @@ static const struct v4l2_file_operations cx231xx_v4l_fops = { ...@@ -2539,7 +2468,7 @@ static const struct v4l2_file_operations cx231xx_v4l_fops = {
.read = cx231xx_v4l2_read, .read = cx231xx_v4l2_read,
.poll = cx231xx_v4l2_poll, .poll = cx231xx_v4l2_poll,
.mmap = cx231xx_v4l2_mmap, .mmap = cx231xx_v4l2_mmap,
.ioctl = video_ioctl2, .unlocked_ioctl = video_ioctl2,
}; };
static const struct v4l2_ioctl_ops video_ioctl_ops = { static const struct v4l2_ioctl_ops video_ioctl_ops = {
...@@ -2641,6 +2570,7 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, ...@@ -2641,6 +2570,7 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
vfd->v4l2_dev = &dev->v4l2_dev; vfd->v4l2_dev = &dev->v4l2_dev;
vfd->release = video_device_release; vfd->release = video_device_release;
vfd->debug = video_debug; vfd->debug = video_debug;
vfd->lock = &dev->lock;
snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment