summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/au0828/au0828-video.c
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2012-08-07 03:46:58 +0200
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-10 01:34:16 +0200
commit549ee4df1951c8a1a123e81a073d73c2e1c26588 (patch)
treea200ea038a0389b6214bea7ff3b1d7d503921e1a /drivers/media/video/au0828/au0828-video.c
parent[media] xc5000: properly report i2c write failures (diff)
downloadlinux-549ee4df1951c8a1a123e81a073d73c2e1c26588.tar.xz
linux-549ee4df1951c8a1a123e81a073d73c2e1c26588.zip
[media] au0828: fix race condition that causes xc5000 to not bind for digital
In some cases users would see the xc5000_attach() call failing for the digital side of the tuner on initialization. This is because of udev running v4l-id while the digital side of the board is still coming up. This is the exact same race condition which was present in em28xx (not surprising since I copied all the locking logic from that driver when I added analog support). Reproduce Mauro's fix from the em28xx driver in au0828. Reported-by: Rick Harding <rharding@mitechie.com> Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/au0828/au0828-video.c')
-rw-r--r--drivers/media/video/au0828/au0828-video.c21
1 files changed, 8 insertions, 13 deletions
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index 6e30c094c56f..b1f8d1856eec 100644
--- a/drivers/media/video/au0828/au0828-video.c
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -864,17 +864,15 @@ static int res_get(struct au0828_fh *fh, unsigned int bit)
return 1;
/* is it free? */
- mutex_lock(&dev->lock);
if (dev->resources & bit) {
/* no, someone else uses it */
- mutex_unlock(&dev->lock);
return 0;
}
/* it's free, grab it */
fh->resources |= bit;
dev->resources |= bit;
dprintk(1, "res: get %d\n", bit);
- mutex_unlock(&dev->lock);
+
return 1;
}
@@ -894,11 +892,9 @@ static void res_free(struct au0828_fh *fh, unsigned int bits)
BUG_ON((fh->resources & bits) != bits);
- mutex_lock(&dev->lock);
fh->resources &= ~bits;
dev->resources &= ~bits;
dprintk(1, "res: put %d\n", bits);
- mutex_unlock(&dev->lock);
}
static int get_ressource(struct au0828_fh *fh)
@@ -1023,7 +1019,8 @@ static int au0828_v4l2_open(struct file *filp)
NULL, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
- sizeof(struct au0828_buffer), fh, NULL);
+ sizeof(struct au0828_buffer), fh,
+ &dev->lock);
/* VBI Setup */
dev->vbi_width = 720;
@@ -1032,8 +1029,8 @@ static int au0828_v4l2_open(struct file *filp)
NULL, &dev->slock,
V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_SEQ_TB,
- sizeof(struct au0828_buffer), fh, NULL);
-
+ sizeof(struct au0828_buffer), fh,
+ &dev->lock);
return ret;
}
@@ -1312,8 +1309,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
if (rc < 0)
return rc;
- mutex_lock(&dev->lock);
-
if (videobuf_queue_is_busy(&fh->vb_vidq)) {
printk(KERN_INFO "%s queue busy\n", __func__);
rc = -EBUSY;
@@ -1322,7 +1317,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
out:
- mutex_unlock(&dev->lock);
return rc;
}
@@ -1832,7 +1826,7 @@ static struct v4l2_file_operations au0828_v4l_fops = {
.read = au0828_v4l2_read,
.poll = au0828_v4l2_poll,
.mmap = au0828_v4l2_mmap,
- .ioctl = video_ioctl2,
+ .unlocked_ioctl = video_ioctl2,
};
static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1922,7 +1916,6 @@ int au0828_analog_register(struct au0828_dev *dev,
init_waitqueue_head(&dev->open);
spin_lock_init(&dev->slock);
- mutex_init(&dev->lock);
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
@@ -1963,11 +1956,13 @@ int au0828_analog_register(struct au0828_dev *dev,
/* Fill the video capture device struct */
*dev->vdev = au0828_video_template;
dev->vdev->parent = &dev->usbdev->dev;
+ dev->vdev->lock = &dev->lock;
strcpy(dev->vdev->name, "au0828a video");
/* Setup the VBI device */
*dev->vbi_dev = au0828_video_template;
dev->vbi_dev->parent = &dev->usbdev->dev;
+ dev->vbi_dev->lock = &dev->lock;
strcpy(dev->vbi_dev->name, "au0828a vbi");
/* Register the v4l2 device */