aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2010-10-17 08:26:18 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-22 21:40:58 -0400
commita682d4cb768381039bdafdc3c04c53cf8d70dcf0 (patch)
tree5b4b92be483f34d08b85e25ae7938af416bc7316 /drivers/media
parente2302501c32a0e7e34b7077f10da03b72dd91570 (diff)
[media] [RFC] radio-mr800: locking fixes
- serialize the suspend and resume functions using the global lock. - do not call usb_autopm_put_interface after a disconnect. - fix a race when disconnecting the device. Reported-by: David Ellingsworth <david@identd.dyndns.org> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Acked-by: David Ellingsworth<david@identd.dyndns.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/radio/radio-mr800.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index 2f56b26cece9..b540e8072e92 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -284,9 +284,13 @@ static void usb_amradio_disconnect(struct usb_interface *intf)
284 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); 284 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
285 285
286 mutex_lock(&radio->lock); 286 mutex_lock(&radio->lock);
287 /* increase the device node's refcount */
288 get_device(&radio->videodev.dev);
287 v4l2_device_disconnect(&radio->v4l2_dev); 289 v4l2_device_disconnect(&radio->v4l2_dev);
288 mutex_unlock(&radio->lock);
289 video_unregister_device(&radio->videodev); 290 video_unregister_device(&radio->videodev);
291 mutex_unlock(&radio->lock);
292 /* decrease the device node's refcount, allowing it to be released */
293 put_device(&radio->videodev.dev);
290} 294}
291 295
292/* vidioc_querycap - query device capabilities */ 296/* vidioc_querycap - query device capabilities */
@@ -515,7 +519,8 @@ static int usb_amradio_close(struct file *file)
515{ 519{
516 struct amradio_device *radio = file->private_data; 520 struct amradio_device *radio = file->private_data;
517 521
518 usb_autopm_put_interface(radio->intf); 522 if (video_is_registered(&radio->videodev))
523 usb_autopm_put_interface(radio->intf);
519 return 0; 524 return 0;
520} 525}
521 526
@@ -524,10 +529,12 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
524{ 529{
525 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); 530 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
526 531
532 mutex_lock(&radio->lock);
527 if (!radio->muted && radio->initialized) { 533 if (!radio->muted && radio->initialized) {
528 amradio_set_mute(radio, AMRADIO_STOP); 534 amradio_set_mute(radio, AMRADIO_STOP);
529 radio->muted = 0; 535 radio->muted = 0;
530 } 536 }
537 mutex_unlock(&radio->lock);
531 538
532 dev_info(&intf->dev, "going into suspend..\n"); 539 dev_info(&intf->dev, "going into suspend..\n");
533 return 0; 540 return 0;
@@ -538,8 +545,9 @@ static int usb_amradio_resume(struct usb_interface *intf)
538{ 545{
539 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); 546 struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
540 547
548 mutex_lock(&radio->lock);
541 if (unlikely(!radio->initialized)) 549 if (unlikely(!radio->initialized))
542 return 0; 550 goto unlock;
543 551
544 if (radio->stereo) 552 if (radio->stereo)
545 amradio_set_stereo(radio, WANT_STEREO); 553 amradio_set_stereo(radio, WANT_STEREO);
@@ -551,6 +559,9 @@ static int usb_amradio_resume(struct usb_interface *intf)
551 if (!radio->muted) 559 if (!radio->muted)
552 amradio_set_mute(radio, AMRADIO_START); 560 amradio_set_mute(radio, AMRADIO_START);
553 561
562unlock:
563 mutex_unlock(&radio->lock);
564
554 dev_info(&intf->dev, "coming out of suspend..\n"); 565 dev_info(&intf->dev, "coming out of suspend..\n");
555 return 0; 566 return 0;
556} 567}