diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-11-26 04:43:51 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-12-01 17:10:18 -0500 |
commit | 2877842de8cbf6272b0a851cb12587b7dd8c2afb (patch) | |
tree | 1f04f8d9a4873a5904e5a2f0278f3423cef0d2ca /drivers | |
parent | 78b055be2710b63cb196fc37669f3b662fecc9e4 (diff) |
[media] v4l2-dev: use mutex_lock_interruptible instead of plain mutex_lock
Where reasonable use mutex_lock_interruptible instead of mutex_lock.
Also fix the poll, read and write error codes when called with an unregistered
device (e.g. after a USB device was disconnected). Poll must return
POLLERR|POLLHUP and read/write must return -ENODEV.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/v4l2-dev.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 03f7f4670e9b..bfd392e2436d 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -186,12 +186,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, | |||
186 | size_t sz, loff_t *off) | 186 | size_t sz, loff_t *off) |
187 | { | 187 | { |
188 | struct video_device *vdev = video_devdata(filp); | 188 | struct video_device *vdev = video_devdata(filp); |
189 | int ret = -EIO; | 189 | int ret = -ENODEV; |
190 | 190 | ||
191 | if (!vdev->fops->read) | 191 | if (!vdev->fops->read) |
192 | return -EINVAL; | 192 | return -EINVAL; |
193 | if (vdev->lock) | 193 | if (vdev->lock && mutex_lock_interruptible(vdev->lock)) |
194 | mutex_lock(vdev->lock); | 194 | return -ERESTARTSYS; |
195 | if (video_is_registered(vdev)) | 195 | if (video_is_registered(vdev)) |
196 | ret = vdev->fops->read(filp, buf, sz, off); | 196 | ret = vdev->fops->read(filp, buf, sz, off); |
197 | if (vdev->lock) | 197 | if (vdev->lock) |
@@ -203,12 +203,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, | |||
203 | size_t sz, loff_t *off) | 203 | size_t sz, loff_t *off) |
204 | { | 204 | { |
205 | struct video_device *vdev = video_devdata(filp); | 205 | struct video_device *vdev = video_devdata(filp); |
206 | int ret = -EIO; | 206 | int ret = -ENODEV; |
207 | 207 | ||
208 | if (!vdev->fops->write) | 208 | if (!vdev->fops->write) |
209 | return -EINVAL; | 209 | return -EINVAL; |
210 | if (vdev->lock) | 210 | if (vdev->lock && mutex_lock_interruptible(vdev->lock)) |
211 | mutex_lock(vdev->lock); | 211 | return -ERESTARTSYS; |
212 | if (video_is_registered(vdev)) | 212 | if (video_is_registered(vdev)) |
213 | ret = vdev->fops->write(filp, buf, sz, off); | 213 | ret = vdev->fops->write(filp, buf, sz, off); |
214 | if (vdev->lock) | 214 | if (vdev->lock) |
@@ -219,10 +219,10 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, | |||
219 | static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) | 219 | static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) |
220 | { | 220 | { |
221 | struct video_device *vdev = video_devdata(filp); | 221 | struct video_device *vdev = video_devdata(filp); |
222 | int ret = DEFAULT_POLLMASK; | 222 | int ret = POLLERR | POLLHUP; |
223 | 223 | ||
224 | if (!vdev->fops->poll) | 224 | if (!vdev->fops->poll) |
225 | return ret; | 225 | return DEFAULT_POLLMASK; |
226 | if (vdev->lock) | 226 | if (vdev->lock) |
227 | mutex_lock(vdev->lock); | 227 | mutex_lock(vdev->lock); |
228 | if (video_is_registered(vdev)) | 228 | if (video_is_registered(vdev)) |
@@ -238,8 +238,8 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
238 | int ret = -ENODEV; | 238 | int ret = -ENODEV; |
239 | 239 | ||
240 | if (vdev->fops->unlocked_ioctl) { | 240 | if (vdev->fops->unlocked_ioctl) { |
241 | if (vdev->lock) | 241 | if (vdev->lock && mutex_lock_interruptible(vdev->lock)) |
242 | mutex_lock(vdev->lock); | 242 | return -ERESTARTSYS; |
243 | if (video_is_registered(vdev)) | 243 | if (video_is_registered(vdev)) |
244 | ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); | 244 | ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); |
245 | if (vdev->lock) | 245 | if (vdev->lock) |
@@ -265,8 +265,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) | |||
265 | 265 | ||
266 | if (!vdev->fops->mmap) | 266 | if (!vdev->fops->mmap) |
267 | return ret; | 267 | return ret; |
268 | if (vdev->lock) | 268 | if (vdev->lock && mutex_lock_interruptible(vdev->lock)) |
269 | mutex_lock(vdev->lock); | 269 | return -ERESTARTSYS; |
270 | if (video_is_registered(vdev)) | 270 | if (video_is_registered(vdev)) |
271 | ret = vdev->fops->mmap(filp, vm); | 271 | ret = vdev->fops->mmap(filp, vm); |
272 | if (vdev->lock) | 272 | if (vdev->lock) |
@@ -292,8 +292,10 @@ static int v4l2_open(struct inode *inode, struct file *filp) | |||
292 | video_get(vdev); | 292 | video_get(vdev); |
293 | mutex_unlock(&videodev_lock); | 293 | mutex_unlock(&videodev_lock); |
294 | if (vdev->fops->open) { | 294 | if (vdev->fops->open) { |
295 | if (vdev->lock) | 295 | if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { |
296 | mutex_lock(vdev->lock); | 296 | ret = -ERESTARTSYS; |
297 | goto err; | ||
298 | } | ||
297 | if (video_is_registered(vdev)) | 299 | if (video_is_registered(vdev)) |
298 | ret = vdev->fops->open(filp); | 300 | ret = vdev->fops->open(filp); |
299 | else | 301 | else |
@@ -302,6 +304,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) | |||
302 | mutex_unlock(vdev->lock); | 304 | mutex_unlock(vdev->lock); |
303 | } | 305 | } |
304 | 306 | ||
307 | err: | ||
305 | /* decrease the refcount in case of an error */ | 308 | /* decrease the refcount in case of an error */ |
306 | if (ret) | 309 | if (ret) |
307 | video_put(vdev); | 310 | video_put(vdev); |