diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2011-10-11 05:06:58 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-16 06:59:43 -0500 |
commit | cdc037817cc15caf931cd3476970860d62f1985c (patch) | |
tree | f6694311b9bcc8d0f58d4f20ca46d6ce49eb54c0 /drivers/media | |
parent | 4d68e700d6a192a5a8b394b26ac056a1c0fa6ebc (diff) |
[media] ivtv: switch to the v4l core lock
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Andy Walls <awalls@md.metrocast.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 48 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 22 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 1 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.c | 22 |
4 files changed, 39 insertions, 54 deletions
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 69a3de9bae62..116ece4d6f27 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, | |||
268 | } | 268 | } |
269 | 269 | ||
270 | /* wait for more data to arrive */ | 270 | /* wait for more data to arrive */ |
271 | mutex_unlock(&itv->serialize_lock); | ||
271 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 272 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
272 | /* New buffers might have become available before we were added to the waitqueue */ | 273 | /* New buffers might have become available before we were added to the waitqueue */ |
273 | if (!s->q_full.buffers) | 274 | if (!s->q_full.buffers) |
274 | schedule(); | 275 | schedule(); |
275 | finish_wait(&s->waitq, &wait); | 276 | finish_wait(&s->waitq, &wait); |
277 | mutex_lock(&itv->serialize_lock); | ||
276 | if (signal_pending(current)) { | 278 | if (signal_pending(current)) { |
277 | /* return if a signal was received */ | 279 | /* return if a signal was received */ |
278 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); | 280 | 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 | 509 | ||
508 | IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); | 510 | IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); |
509 | 511 | ||
510 | mutex_lock(&itv->serialize_lock); | ||
511 | rc = ivtv_start_capture(id); | 512 | rc = ivtv_start_capture(id); |
512 | mutex_unlock(&itv->serialize_lock); | ||
513 | if (rc) | 513 | if (rc) |
514 | return rc; | 514 | return rc; |
515 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); | 515 | 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 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 584 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
585 | 585 | ||
586 | /* Start decoder (returns 0 if already started) */ | 586 | /* Start decoder (returns 0 if already started) */ |
587 | mutex_lock(&itv->serialize_lock); | ||
588 | rc = ivtv_start_decoding(id, itv->speed); | 587 | rc = ivtv_start_decoding(id, itv->speed); |
589 | mutex_unlock(&itv->serialize_lock); | ||
590 | if (rc) { | 588 | if (rc) { |
591 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); | 589 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); |
592 | 590 | ||
@@ -627,11 +625,13 @@ retry: | |||
627 | break; | 625 | break; |
628 | if (filp->f_flags & O_NONBLOCK) | 626 | if (filp->f_flags & O_NONBLOCK) |
629 | return -EAGAIN; | 627 | return -EAGAIN; |
628 | mutex_unlock(&itv->serialize_lock); | ||
630 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 629 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
631 | /* New buffers might have become free before we were added to the waitqueue */ | 630 | /* New buffers might have become free before we were added to the waitqueue */ |
632 | if (!s->q_free.buffers) | 631 | if (!s->q_free.buffers) |
633 | schedule(); | 632 | schedule(); |
634 | finish_wait(&s->waitq, &wait); | 633 | finish_wait(&s->waitq, &wait); |
634 | mutex_lock(&itv->serialize_lock); | ||
635 | if (signal_pending(current)) { | 635 | if (signal_pending(current)) { |
636 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); | 636 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); |
637 | return -EINTR; | 637 | return -EINTR; |
@@ -686,12 +686,14 @@ retry: | |||
686 | if (mode == OUT_YUV) | 686 | if (mode == OUT_YUV) |
687 | ivtv_yuv_setup_stream_frame(itv); | 687 | ivtv_yuv_setup_stream_frame(itv); |
688 | 688 | ||
689 | mutex_unlock(&itv->serialize_lock); | ||
689 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | 690 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); |
690 | while (!(got_sig = signal_pending(current)) && | 691 | while (!(got_sig = signal_pending(current)) && |
691 | test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { | 692 | test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { |
692 | schedule(); | 693 | schedule(); |
693 | } | 694 | } |
694 | finish_wait(&itv->dma_waitq, &wait); | 695 | finish_wait(&itv->dma_waitq, &wait); |
696 | mutex_lock(&itv->serialize_lock); | ||
695 | if (got_sig) { | 697 | if (got_sig) { |
696 | IVTV_DEBUG_INFO("User interrupted %s\n", s->name); | 698 | IVTV_DEBUG_INFO("User interrupted %s\n", s->name); |
697 | return -EINTR; | 699 | return -EINTR; |
@@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) | |||
756 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | 758 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { |
757 | int rc; | 759 | int rc; |
758 | 760 | ||
759 | mutex_lock(&itv->serialize_lock); | ||
760 | rc = ivtv_start_capture(id); | 761 | rc = ivtv_start_capture(id); |
761 | mutex_unlock(&itv->serialize_lock); | ||
762 | if (rc) { | 762 | if (rc) { |
763 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", | 763 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", |
764 | s->name, rc); | 764 | s->name, rc); |
@@ -861,7 +861,6 @@ int ivtv_v4l2_close(struct file *filp) | |||
861 | 861 | ||
862 | IVTV_DEBUG_FILE("close %s\n", s->name); | 862 | IVTV_DEBUG_FILE("close %s\n", s->name); |
863 | 863 | ||
864 | mutex_lock(&itv->serialize_lock); | ||
865 | /* Stop radio */ | 864 | /* Stop radio */ |
866 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD && | 865 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD && |
867 | v4l2_fh_is_singular_file(filp)) { | 866 | v4l2_fh_is_singular_file(filp)) { |
@@ -893,7 +892,6 @@ int ivtv_v4l2_close(struct file *filp) | |||
893 | /* Easy case first: this stream was never claimed by us */ | 892 | /* Easy case first: this stream was never claimed by us */ |
894 | if (s->id != id->open_id) { | 893 | if (s->id != id->open_id) { |
895 | kfree(id); | 894 | kfree(id); |
896 | mutex_unlock(&itv->serialize_lock); | ||
897 | return 0; | 895 | return 0; |
898 | } | 896 | } |
899 | 897 | ||
@@ -914,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp) | |||
914 | ivtv_stop_capture(id, 0); | 912 | ivtv_stop_capture(id, 0); |
915 | } | 913 | } |
916 | kfree(id); | 914 | kfree(id); |
917 | mutex_unlock(&itv->serialize_lock); | ||
918 | return 0; | 915 | return 0; |
919 | } | 916 | } |
920 | 917 | ||
921 | static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | 918 | int ivtv_v4l2_open(struct file *filp) |
922 | { | 919 | { |
923 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
924 | struct video_device *vdev = video_devdata(filp); | 920 | struct video_device *vdev = video_devdata(filp); |
925 | #endif | 921 | struct ivtv_stream *s = video_get_drvdata(vdev); |
926 | struct ivtv *itv = s->itv; | 922 | struct ivtv *itv = s->itv; |
927 | struct ivtv_open_id *item; | 923 | struct ivtv_open_id *item; |
928 | int res = 0; | 924 | int res = 0; |
929 | 925 | ||
930 | IVTV_DEBUG_FILE("open %s\n", s->name); | 926 | IVTV_DEBUG_FILE("open %s\n", s->name); |
931 | 927 | ||
928 | if (ivtv_init_on_first_open(itv)) { | ||
929 | IVTV_ERR("Failed to initialize on device %s\n", | ||
930 | video_device_node_name(vdev)); | ||
931 | return -ENXIO; | ||
932 | } | ||
933 | |||
932 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 934 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
933 | /* Unless ivtv_fw_debug is set, error out if firmware dead. */ | 935 | /* Unless ivtv_fw_debug is set, error out if firmware dead. */ |
934 | if (ivtv_fw_debug) { | 936 | if (ivtv_fw_debug) { |
@@ -1017,28 +1019,6 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |||
1017 | return 0; | 1019 | return 0; |
1018 | } | 1020 | } |
1019 | 1021 | ||
1020 | int ivtv_v4l2_open(struct file *filp) | ||
1021 | { | ||
1022 | int res; | ||
1023 | struct ivtv *itv = NULL; | ||
1024 | struct ivtv_stream *s = NULL; | ||
1025 | struct video_device *vdev = video_devdata(filp); | ||
1026 | |||
1027 | s = video_get_drvdata(vdev); | ||
1028 | itv = s->itv; | ||
1029 | |||
1030 | mutex_lock(&itv->serialize_lock); | ||
1031 | if (ivtv_init_on_first_open(itv)) { | ||
1032 | IVTV_ERR("Failed to initialize on device %s\n", | ||
1033 | video_device_node_name(vdev)); | ||
1034 | mutex_unlock(&itv->serialize_lock); | ||
1035 | return -ENXIO; | ||
1036 | } | ||
1037 | res = ivtv_serialized_open(s, filp); | ||
1038 | mutex_unlock(&itv->serialize_lock); | ||
1039 | return res; | ||
1040 | } | ||
1041 | |||
1042 | void ivtv_mute(struct ivtv *itv) | 1022 | void ivtv_mute(struct ivtv *itv) |
1043 | { | 1023 | { |
1044 | if (atomic_read(&itv->capturing)) | 1024 | if (atomic_read(&itv->capturing)) |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index ecafa697326e..c4bc48143098 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) | |||
179 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0); | 179 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0); |
180 | 180 | ||
181 | /* Wait for any DMA to finish */ | 181 | /* Wait for any DMA to finish */ |
182 | mutex_unlock(&itv->serialize_lock); | ||
182 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | 183 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); |
183 | while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { | 184 | while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { |
184 | got_sig = signal_pending(current); | 185 | got_sig = signal_pending(current); |
@@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) | |||
188 | schedule(); | 189 | schedule(); |
189 | } | 190 | } |
190 | finish_wait(&itv->dma_waitq, &wait); | 191 | finish_wait(&itv->dma_waitq, &wait); |
192 | mutex_lock(&itv->serialize_lock); | ||
191 | if (got_sig) | 193 | if (got_sig) |
192 | return -EINTR; | 194 | return -EINTR; |
193 | 195 | ||
@@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) | |||
1107 | * happens within the first 100 lines of the top field. | 1109 | * happens within the first 100 lines of the top field. |
1108 | * Make 4 attempts to sync to the decoder before giving up. | 1110 | * Make 4 attempts to sync to the decoder before giving up. |
1109 | */ | 1111 | */ |
1112 | mutex_unlock(&itv->serialize_lock); | ||
1110 | for (f = 0; f < 4; f++) { | 1113 | for (f = 0; f < 4; f++) { |
1111 | prepare_to_wait(&itv->vsync_waitq, &wait, | 1114 | prepare_to_wait(&itv->vsync_waitq, &wait, |
1112 | TASK_UNINTERRUPTIBLE); | 1115 | TASK_UNINTERRUPTIBLE); |
@@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) | |||
1115 | schedule_timeout(msecs_to_jiffies(25)); | 1118 | schedule_timeout(msecs_to_jiffies(25)); |
1116 | } | 1119 | } |
1117 | finish_wait(&itv->vsync_waitq, &wait); | 1120 | finish_wait(&itv->vsync_waitq, &wait); |
1121 | mutex_lock(&itv->serialize_lock); | ||
1118 | 1122 | ||
1119 | if (f == 4) | 1123 | if (f == 4) |
1120 | IVTV_WARN("Mode change failed to sync to decoder\n"); | 1124 | 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 | return 0; | 1846 | return 0; |
1843 | } | 1847 | } |
1844 | 1848 | ||
1845 | static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | 1849 | long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1846 | unsigned int cmd, unsigned long arg) | ||
1847 | { | 1850 | { |
1848 | struct video_device *vfd = video_devdata(filp); | 1851 | struct video_device *vfd = video_devdata(filp); |
1849 | long ret; | 1852 | long ret; |
@@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | |||
1855 | return ret; | 1858 | return ret; |
1856 | } | 1859 | } |
1857 | 1860 | ||
1858 | long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
1859 | { | ||
1860 | struct ivtv_open_id *id = fh2id(filp->private_data); | ||
1861 | struct ivtv *itv = id->itv; | ||
1862 | long res; | ||
1863 | |||
1864 | /* DQEVENT can block, so this should not run with the serialize lock */ | ||
1865 | if (cmd == VIDIOC_DQEVENT) | ||
1866 | return ivtv_serialized_ioctl(itv, filp, cmd, arg); | ||
1867 | mutex_lock(&itv->serialize_lock); | ||
1868 | res = ivtv_serialized_ioctl(itv, filp, cmd, arg); | ||
1869 | mutex_unlock(&itv->serialize_lock); | ||
1870 | return res; | ||
1871 | } | ||
1872 | |||
1873 | static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { | 1861 | static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { |
1874 | .vidioc_querycap = ivtv_querycap, | 1862 | .vidioc_querycap = ivtv_querycap, |
1875 | .vidioc_s_audio = ivtv_s_audio, | 1863 | .vidioc_s_audio = ivtv_s_audio, |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index e7794dc1330e..d598df046605 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -214,6 +214,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) | |||
214 | s->vdev->fops = ivtv_stream_info[type].fops; | 214 | s->vdev->fops = ivtv_stream_info[type].fops; |
215 | s->vdev->release = video_device_release; | 215 | s->vdev->release = video_device_release; |
216 | s->vdev->tvnorms = V4L2_STD_ALL; | 216 | s->vdev->tvnorms = V4L2_STD_ALL; |
217 | s->vdev->lock = &itv->serialize_lock; | ||
217 | set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); | 218 | set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); |
218 | ivtv_set_funcs(s->vdev); | 219 | ivtv_set_funcs(s->vdev); |
219 | return 0; | 220 | return 0; |
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index dcbab6ad4c26..2ad65eb29832 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src) | |||
1149 | { | 1149 | { |
1150 | struct yuv_playback_info *yi = &itv->yuv_info; | 1150 | struct yuv_playback_info *yi = &itv->yuv_info; |
1151 | struct ivtv_dma_frame dma_args; | 1151 | struct ivtv_dma_frame dma_args; |
1152 | int res; | ||
1152 | 1153 | ||
1153 | ivtv_yuv_setup_stream_frame(itv); | 1154 | ivtv_yuv_setup_stream_frame(itv); |
1154 | 1155 | ||
1155 | /* We only need to supply source addresses for this */ | 1156 | /* We only need to supply source addresses for this */ |
1156 | dma_args.y_source = src; | 1157 | dma_args.y_source = src; |
1157 | dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); | 1158 | dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); |
1158 | return ivtv_yuv_udma_frame(itv, &dma_args); | 1159 | /* Wait for frame DMA. Note that serialize_lock is locked, |
1160 | so to allow other processes to access the driver while | ||
1161 | we are waiting unlock first and later lock again. */ | ||
1162 | mutex_unlock(&itv->serialize_lock); | ||
1163 | res = ivtv_yuv_udma_frame(itv, &dma_args); | ||
1164 | mutex_lock(&itv->serialize_lock); | ||
1165 | return res; | ||
1159 | } | 1166 | } |
1160 | 1167 | ||
1161 | /* IVTV_IOC_DMA_FRAME ioctl handler */ | 1168 | /* IVTV_IOC_DMA_FRAME ioctl handler */ |
1162 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | 1169 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) |
1163 | { | 1170 | { |
1164 | /* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ | 1171 | int res; |
1165 | 1172 | ||
1173 | /* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ | ||
1166 | ivtv_yuv_next_free(itv); | 1174 | ivtv_yuv_next_free(itv); |
1167 | ivtv_yuv_setup_frame(itv, args); | 1175 | ivtv_yuv_setup_frame(itv, args); |
1168 | return ivtv_yuv_udma_frame(itv, args); | 1176 | /* Wait for frame DMA. Note that serialize_lock is locked, |
1177 | so to allow other processes to access the driver while | ||
1178 | we are waiting unlock first and later lock again. */ | ||
1179 | mutex_unlock(&itv->serialize_lock); | ||
1180 | res = ivtv_yuv_udma_frame(itv, args); | ||
1181 | mutex_lock(&itv->serialize_lock); | ||
1182 | return res; | ||
1169 | } | 1183 | } |
1170 | 1184 | ||
1171 | void ivtv_yuv_close(struct ivtv *itv) | 1185 | void ivtv_yuv_close(struct ivtv *itv) |
@@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv) | |||
1174 | int h_filter, v_filter_1, v_filter_2; | 1188 | int h_filter, v_filter_1, v_filter_2; |
1175 | 1189 | ||
1176 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); | 1190 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); |
1191 | mutex_unlock(&itv->serialize_lock); | ||
1177 | ivtv_waitq(&itv->vsync_waitq); | 1192 | ivtv_waitq(&itv->vsync_waitq); |
1193 | mutex_lock(&itv->serialize_lock); | ||
1178 | 1194 | ||
1179 | yi->running = 0; | 1195 | yi->running = 0; |
1180 | atomic_set(&yi->next_dma_frame, -1); | 1196 | atomic_set(&yi->next_dma_frame, -1); |