提交 cdc03781 编写于 作者: H Hans Verkuil 提交者: Mauro Carvalho Chehab

[media] ivtv: switch to the v4l core lock

Signed-off-by: NHans Verkuil <hans.verkuil@cisco.com>
Acked-by: NAndy Walls <awalls@md.metrocast.net>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 4d68e700
...@@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, ...@@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
} }
/* wait for more data to arrive */ /* wait for more data to arrive */
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become available before we were added to the waitqueue */ /* New buffers might have become available before we were added to the waitqueue */
if (!s->q_full.buffers) if (!s->q_full.buffers)
schedule(); schedule();
finish_wait(&s->waitq, &wait); finish_wait(&s->waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (signal_pending(current)) { if (signal_pending(current)) {
/* return if a signal was received */ /* return if a signal was received */
IVTV_DEBUG_INFO("User stopped %s\n", s->name); IVTV_DEBUG_INFO("User stopped %s\n", s->name);
...@@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_ ...@@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_
IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
mutex_lock(&itv->serialize_lock);
rc = ivtv_start_capture(id); rc = ivtv_start_capture(id);
mutex_unlock(&itv->serialize_lock);
if (rc) if (rc)
return rc; return rc;
return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
...@@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c ...@@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
set_bit(IVTV_F_S_APPL_IO, &s->s_flags); set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
/* Start decoder (returns 0 if already started) */ /* Start decoder (returns 0 if already started) */
mutex_lock(&itv->serialize_lock);
rc = ivtv_start_decoding(id, itv->speed); rc = ivtv_start_decoding(id, itv->speed);
mutex_unlock(&itv->serialize_lock);
if (rc) { if (rc) {
IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
...@@ -627,11 +625,13 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c ...@@ -627,11 +625,13 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
break; break;
if (filp->f_flags & O_NONBLOCK) if (filp->f_flags & O_NONBLOCK)
return -EAGAIN; return -EAGAIN;
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become free before we were added to the waitqueue */ /* New buffers might have become free before we were added to the waitqueue */
if (!s->q_free.buffers) if (!s->q_free.buffers)
schedule(); schedule();
finish_wait(&s->waitq, &wait); finish_wait(&s->waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (signal_pending(current)) { if (signal_pending(current)) {
IVTV_DEBUG_INFO("User stopped %s\n", s->name); IVTV_DEBUG_INFO("User stopped %s\n", s->name);
return -EINTR; return -EINTR;
...@@ -686,12 +686,14 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c ...@@ -686,12 +686,14 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
if (mode == OUT_YUV) if (mode == OUT_YUV)
ivtv_yuv_setup_stream_frame(itv); ivtv_yuv_setup_stream_frame(itv);
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (!(got_sig = signal_pending(current)) && while (!(got_sig = signal_pending(current)) &&
test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
schedule(); schedule();
} }
finish_wait(&itv->dma_waitq, &wait); finish_wait(&itv->dma_waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (got_sig) { if (got_sig) {
IVTV_DEBUG_INFO("User interrupted %s\n", s->name); IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
return -EINTR; return -EINTR;
...@@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) ...@@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
int rc; int rc;
mutex_lock(&itv->serialize_lock);
rc = ivtv_start_capture(id); rc = ivtv_start_capture(id);
mutex_unlock(&itv->serialize_lock);
if (rc) { if (rc) {
IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
s->name, rc); s->name, rc);
...@@ -861,7 +861,6 @@ int ivtv_v4l2_close(struct file *filp) ...@@ -861,7 +861,6 @@ int ivtv_v4l2_close(struct file *filp)
IVTV_DEBUG_FILE("close %s\n", s->name); IVTV_DEBUG_FILE("close %s\n", s->name);
mutex_lock(&itv->serialize_lock);
/* Stop radio */ /* Stop radio */
if (id->type == IVTV_ENC_STREAM_TYPE_RAD && if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
v4l2_fh_is_singular_file(filp)) { v4l2_fh_is_singular_file(filp)) {
...@@ -893,7 +892,6 @@ int ivtv_v4l2_close(struct file *filp) ...@@ -893,7 +892,6 @@ int ivtv_v4l2_close(struct file *filp)
/* Easy case first: this stream was never claimed by us */ /* Easy case first: this stream was never claimed by us */
if (s->id != id->open_id) { if (s->id != id->open_id) {
kfree(id); kfree(id);
mutex_unlock(&itv->serialize_lock);
return 0; return 0;
} }
...@@ -914,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp) ...@@ -914,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp)
ivtv_stop_capture(id, 0); ivtv_stop_capture(id, 0);
} }
kfree(id); kfree(id);
mutex_unlock(&itv->serialize_lock);
return 0; return 0;
} }
static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) int ivtv_v4l2_open(struct file *filp)
{ {
#ifdef CONFIG_VIDEO_ADV_DEBUG
struct video_device *vdev = video_devdata(filp); struct video_device *vdev = video_devdata(filp);
#endif struct ivtv_stream *s = video_get_drvdata(vdev);
struct ivtv *itv = s->itv; struct ivtv *itv = s->itv;
struct ivtv_open_id *item; struct ivtv_open_id *item;
int res = 0; int res = 0;
IVTV_DEBUG_FILE("open %s\n", s->name); IVTV_DEBUG_FILE("open %s\n", s->name);
if (ivtv_init_on_first_open(itv)) {
IVTV_ERR("Failed to initialize on device %s\n",
video_device_node_name(vdev));
return -ENXIO;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
/* Unless ivtv_fw_debug is set, error out if firmware dead. */ /* Unless ivtv_fw_debug is set, error out if firmware dead. */
if (ivtv_fw_debug) { if (ivtv_fw_debug) {
...@@ -1017,28 +1019,6 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) ...@@ -1017,28 +1019,6 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
return 0; return 0;
} }
int ivtv_v4l2_open(struct file *filp)
{
int res;
struct ivtv *itv = NULL;
struct ivtv_stream *s = NULL;
struct video_device *vdev = video_devdata(filp);
s = video_get_drvdata(vdev);
itv = s->itv;
mutex_lock(&itv->serialize_lock);
if (ivtv_init_on_first_open(itv)) {
IVTV_ERR("Failed to initialize on device %s\n",
video_device_node_name(vdev));
mutex_unlock(&itv->serialize_lock);
return -ENXIO;
}
res = ivtv_serialized_open(s, filp);
mutex_unlock(&itv->serialize_lock);
return res;
}
void ivtv_mute(struct ivtv *itv) void ivtv_mute(struct ivtv *itv)
{ {
if (atomic_read(&itv->capturing)) if (atomic_read(&itv->capturing))
......
...@@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) ...@@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0); ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
/* Wait for any DMA to finish */ /* Wait for any DMA to finish */
mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
got_sig = signal_pending(current); got_sig = signal_pending(current);
...@@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) ...@@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
schedule(); schedule();
} }
finish_wait(&itv->dma_waitq, &wait); finish_wait(&itv->dma_waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (got_sig) if (got_sig)
return -EINTR; return -EINTR;
...@@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) ...@@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
* happens within the first 100 lines of the top field. * happens within the first 100 lines of the top field.
* Make 4 attempts to sync to the decoder before giving up. * Make 4 attempts to sync to the decoder before giving up.
*/ */
mutex_unlock(&itv->serialize_lock);
for (f = 0; f < 4; f++) { for (f = 0; f < 4; f++) {
prepare_to_wait(&itv->vsync_waitq, &wait, prepare_to_wait(&itv->vsync_waitq, &wait,
TASK_UNINTERRUPTIBLE); TASK_UNINTERRUPTIBLE);
...@@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) ...@@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
schedule_timeout(msecs_to_jiffies(25)); schedule_timeout(msecs_to_jiffies(25));
} }
finish_wait(&itv->vsync_waitq, &wait); finish_wait(&itv->vsync_waitq, &wait);
mutex_lock(&itv->serialize_lock);
if (f == 4) if (f == 4)
IVTV_WARN("Mode change failed to sync to decoder\n"); IVTV_WARN("Mode change failed to sync to decoder\n");
...@@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio, ...@@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio,
return 0; return 0;
} }
static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
struct video_device *vfd = video_devdata(filp); struct video_device *vfd = video_devdata(filp);
long ret; long ret;
...@@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, ...@@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
return ret; return ret;
} }
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct ivtv_open_id *id = fh2id(filp->private_data);
struct ivtv *itv = id->itv;
long res;
/* DQEVENT can block, so this should not run with the serialize lock */
if (cmd == VIDIOC_DQEVENT)
return ivtv_serialized_ioctl(itv, filp, cmd, arg);
mutex_lock(&itv->serialize_lock);
res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
mutex_unlock(&itv->serialize_lock);
return res;
}
static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
.vidioc_querycap = ivtv_querycap, .vidioc_querycap = ivtv_querycap,
.vidioc_s_audio = ivtv_s_audio, .vidioc_s_audio = ivtv_s_audio,
......
...@@ -214,6 +214,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) ...@@ -214,6 +214,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
s->vdev->fops = ivtv_stream_info[type].fops; s->vdev->fops = ivtv_stream_info[type].fops;
s->vdev->release = video_device_release; s->vdev->release = video_device_release;
s->vdev->tvnorms = V4L2_STD_ALL; s->vdev->tvnorms = V4L2_STD_ALL;
s->vdev->lock = &itv->serialize_lock;
set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
ivtv_set_funcs(s->vdev); ivtv_set_funcs(s->vdev);
return 0; return 0;
......
...@@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src) ...@@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
{ {
struct yuv_playback_info *yi = &itv->yuv_info; struct yuv_playback_info *yi = &itv->yuv_info;
struct ivtv_dma_frame dma_args; struct ivtv_dma_frame dma_args;
int res;
ivtv_yuv_setup_stream_frame(itv); ivtv_yuv_setup_stream_frame(itv);
/* We only need to supply source addresses for this */ /* We only need to supply source addresses for this */
dma_args.y_source = src; dma_args.y_source = src;
dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
return ivtv_yuv_udma_frame(itv, &dma_args); /* Wait for frame DMA. Note that serialize_lock is locked,
so to allow other processes to access the driver while
we are waiting unlock first and later lock again. */
mutex_unlock(&itv->serialize_lock);
res = ivtv_yuv_udma_frame(itv, &dma_args);
mutex_lock(&itv->serialize_lock);
return res;
} }
/* IVTV_IOC_DMA_FRAME ioctl handler */ /* IVTV_IOC_DMA_FRAME ioctl handler */
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
{ {
/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ int res;
/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
ivtv_yuv_next_free(itv); ivtv_yuv_next_free(itv);
ivtv_yuv_setup_frame(itv, args); ivtv_yuv_setup_frame(itv, args);
return ivtv_yuv_udma_frame(itv, args); /* Wait for frame DMA. Note that serialize_lock is locked,
so to allow other processes to access the driver while
we are waiting unlock first and later lock again. */
mutex_unlock(&itv->serialize_lock);
res = ivtv_yuv_udma_frame(itv, args);
mutex_lock(&itv->serialize_lock);
return res;
} }
void ivtv_yuv_close(struct ivtv *itv) void ivtv_yuv_close(struct ivtv *itv)
...@@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv) ...@@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv)
int h_filter, v_filter_1, v_filter_2; int h_filter, v_filter_1, v_filter_2;
IVTV_DEBUG_YUV("ivtv_yuv_close\n"); IVTV_DEBUG_YUV("ivtv_yuv_close\n");
mutex_unlock(&itv->serialize_lock);
ivtv_waitq(&itv->vsync_waitq); ivtv_waitq(&itv->vsync_waitq);
mutex_lock(&itv->serialize_lock);
yi->running = 0; yi->running = 0;
atomic_set(&yi->next_dma_frame, -1); atomic_set(&yi->next_dma_frame, -1);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册