Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a682d4cb authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

[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: default avatarDavid Ellingsworth <david@identd.dyndns.org>
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Acked-by: default avatarDavid <Ellingsworth&lt;david@identd.dyndns.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent e2302501
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -284,9 +284,13 @@ static void usb_amradio_disconnect(struct usb_interface *intf)
	struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));

	mutex_lock(&radio->lock);
	/* increase the device node's refcount */
	get_device(&radio->videodev.dev);
	v4l2_device_disconnect(&radio->v4l2_dev);
	mutex_unlock(&radio->lock);
	video_unregister_device(&radio->videodev);
	mutex_unlock(&radio->lock);
	/* decrease the device node's refcount, allowing it to be released */
	put_device(&radio->videodev.dev);
}

/* vidioc_querycap - query device capabilities */
@@ -515,6 +519,7 @@ static int usb_amradio_close(struct file *file)
{
	struct amradio_device *radio = file->private_data;

	if (video_is_registered(&radio->videodev))
		usb_autopm_put_interface(radio->intf);
	return 0;
}
@@ -524,10 +529,12 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));

	mutex_lock(&radio->lock);
	if (!radio->muted && radio->initialized) {
		amradio_set_mute(radio, AMRADIO_STOP);
		radio->muted = 0;
	}
	mutex_unlock(&radio->lock);

	dev_info(&intf->dev, "going into suspend..\n");
	return 0;
@@ -538,8 +545,9 @@ static int usb_amradio_resume(struct usb_interface *intf)
{
	struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));

	mutex_lock(&radio->lock);
	if (unlikely(!radio->initialized))
		return 0;
		goto unlock;

	if (radio->stereo)
		amradio_set_stereo(radio, WANT_STEREO);
@@ -551,6 +559,9 @@ static int usb_amradio_resume(struct usb_interface *intf)
	if (!radio->muted)
		amradio_set_mute(radio, AMRADIO_START);

unlock:
	mutex_unlock(&radio->lock);

	dev_info(&intf->dev, "coming out of suspend..\n");
	return 0;
}