aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2008-07-26 08:01:24 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-27 10:06:23 -0400
commit1052efe0fc69130d9d6a44bc9ceecd229221d9a1 (patch)
tree7e7f19cbbd3ff023e80eb7da5b68469085bdfe59 /drivers
parentfeb75f07102a85026d41e2c4e4113c34dd035c30 (diff)
V4L/DVB (8505): saa7134-empress.c: fix deadlock
ts_release() locked a mutex that videobuf_stop() also tried to obtain. But ts_release() shouldn't hold that mutex at all. Make empress_users atomic as well to prevent possible race condition. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c12
-rw-r--r--drivers/media/video/saa7134/saa7134.h2
2 files changed, 5 insertions, 9 deletions
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 8b3f95167781..2ecfbd1b41fc 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -89,14 +89,14 @@ static int ts_open(struct inode *inode, struct file *file)
89 err = -EBUSY; 89 err = -EBUSY;
90 if (!mutex_trylock(&dev->empress_tsq.vb_lock)) 90 if (!mutex_trylock(&dev->empress_tsq.vb_lock))
91 goto done; 91 goto done;
92 if (dev->empress_users) 92 if (atomic_read(&dev->empress_users))
93 goto done_up; 93 goto done_up;
94 94
95 /* Unmute audio */ 95 /* Unmute audio */
96 saa_writeb(SAA7134_AUDIO_MUTE_CTRL, 96 saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
97 saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6)); 97 saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
98 98
99 dev->empress_users++; 99 atomic_inc(&dev->empress_users);
100 file->private_data = dev; 100 file->private_data = dev;
101 err = 0; 101 err = 0;
102 102
@@ -110,8 +110,6 @@ static int ts_release(struct inode *inode, struct file *file)
110{ 110{
111 struct saa7134_dev *dev = file->private_data; 111 struct saa7134_dev *dev = file->private_data;
112 112
113 mutex_lock(&dev->empress_tsq.vb_lock);
114
115 videobuf_stop(&dev->empress_tsq); 113 videobuf_stop(&dev->empress_tsq);
116 videobuf_mmap_free(&dev->empress_tsq); 114 videobuf_mmap_free(&dev->empress_tsq);
117 115
@@ -122,9 +120,7 @@ static int ts_release(struct inode *inode, struct file *file)
122 saa_writeb(SAA7134_AUDIO_MUTE_CTRL, 120 saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
123 saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); 121 saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
124 122
125 dev->empress_users--; 123 atomic_dec(&dev->empress_users);
126
127 mutex_unlock(&dev->empress_tsq.vb_lock);
128 124
129 return 0; 125 return 0;
130} 126}
@@ -447,7 +443,7 @@ static void empress_signal_update(struct work_struct *work)
447 ts_reset_encoder(dev); 443 ts_reset_encoder(dev);
448 } else { 444 } else {
449 dprintk("video signal acquired\n"); 445 dprintk("video signal acquired\n");
450 if (dev->empress_users) 446 if (atomic_read(&dev->empress_users))
451 ts_init_encoder(dev); 447 ts_init_encoder(dev);
452 } 448 }
453} 449}
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index ade4e19799e9..ed20dd56379c 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -561,7 +561,7 @@ struct saa7134_dev {
561 /* SAA7134_MPEG_EMPRESS only */ 561 /* SAA7134_MPEG_EMPRESS only */
562 struct video_device *empress_dev; 562 struct video_device *empress_dev;
563 struct videobuf_queue empress_tsq; 563 struct videobuf_queue empress_tsq;
564 unsigned int empress_users; 564 atomic_t empress_users;
565 struct work_struct empress_workqueue; 565 struct work_struct empress_workqueue;
566 int empress_started; 566 int empress_started;
567 567