diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-10-17 08:26:18 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-22 21:40:58 -0400 |
commit | a682d4cb768381039bdafdc3c04c53cf8d70dcf0 (patch) | |
tree | 5b4b92be483f34d08b85e25ae7938af416bc7316 /drivers/media/radio | |
parent | e2302501c32a0e7e34b7077f10da03b72dd91570 (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/radio')
-rw-r--r-- | drivers/media/radio/radio-mr800.c | 17 |
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 | ||
562 | unlock: | ||
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 | } |