From 4aebc2893eada9e054a37df8bb342a53f8ca0d2a Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 22 Sep 2009 21:22:19 -0300 Subject: V4L/DVB (13060): radio-mr800: implement proper locking Implement proper locking Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 181 ++++++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 75 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index a1239083472d..75c69755a04c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -168,11 +168,7 @@ static int amradio_set_mute(struct amradio_device *radio, char argument) int retval; int size; - /* safety check */ - if (radio->removed) - return -EIO; - - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); radio->buffer[0] = 0x00; radio->buffer[1] = 0x55; @@ -186,15 +182,11 @@ static int amradio_set_mute(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) { - mutex_unlock(&radio->lock); + if (retval < 0 || size != BUFFER_LENGTH) return retval; - } radio->muted = argument; - mutex_unlock(&radio->lock); - return retval; } @@ -205,11 +197,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) int size; unsigned short freq_send = 0x10 + (freq >> 3) / 25; - /* safety check */ - if (radio->removed) - return -EIO; - - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); radio->buffer[0] = 0x00; radio->buffer[1] = 0x55; @@ -223,10 +211,8 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) { - mutex_unlock(&radio->lock); + if (retval < 0 || size != BUFFER_LENGTH) return retval; - } /* frequency is calculated from freq_send and placed in first 2 bytes */ radio->buffer[0] = (freq_send >> 8) & 0xff; @@ -240,13 +226,6 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) { - mutex_unlock(&radio->lock); - return retval; - } - - mutex_unlock(&radio->lock); - return retval; } @@ -255,11 +234,7 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) int retval; int size; - /* safety check */ - if (radio->removed) - return -EIO; - - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); radio->buffer[0] = 0x00; radio->buffer[1] = 0x55; @@ -275,14 +250,11 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) if (retval < 0 || size != BUFFER_LENGTH) { radio->stereo = -1; - mutex_unlock(&radio->lock); return retval; } radio->stereo = 1; - mutex_unlock(&radio->lock); - return retval; } @@ -325,12 +297,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct amradio_device *radio = video_get_drvdata(video_devdata(file)); int retval; + mutex_lock(&radio->lock); + /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } - if (v->index > 0) - return -EINVAL; + if (v->index > 0) { + retval = -EINVAL; + goto unlock; + } /* TODO: Add function which look is signal stereo or not * amradio_getstat(radio); @@ -357,7 +335,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->audmode = V4L2_TUNER_MODE_MONO; v->signal = 0xffff; /* Can't get the signal strength, sad.. */ v->afc = 0; /* Don't know what is this */ - return 0; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_s_tuner - set tuner attributes */ @@ -367,12 +348,18 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct amradio_device *radio = video_get_drvdata(video_devdata(file)); int retval; + mutex_lock(&radio->lock); + /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } - if (v->index > 0) - return -EINVAL; + if (v->index > 0) { + retval = -EINVAL; + goto unlock; + } /* mono/stereo selector */ switch (v->audmode) { @@ -389,10 +376,12 @@ static int vidioc_s_tuner(struct file *file, void *priv, "set stereo failed\n"); break; default: - return -EINVAL; + retval = -EINVAL; } - return 0; +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_s_frequency - set tuner radio frequency */ @@ -402,19 +391,24 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct amradio_device *radio = video_get_drvdata(video_devdata(file)); int retval; + mutex_lock(&radio->lock); + /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } - mutex_lock(&radio->lock); radio->curfreq = f->frequency; - mutex_unlock(&radio->lock); retval = amradio_setfreq(radio, radio->curfreq); if (retval < 0) amradio_dev_warn(&radio->videodev->dev, "set frequency failed\n"); - return 0; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_g_frequency - get tuner radio frequency */ @@ -422,14 +416,22 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval = 0; + + mutex_lock(&radio->lock); /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; - return 0; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_queryctrl - enumerate control items */ @@ -449,17 +451,26 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval = -EINVAL; + + mutex_lock(&radio->lock); /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = radio->muted; - return 0; + retval = 0; + break; } - return -EINVAL; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_s_ctrl - set the value of a control */ @@ -467,11 +478,15 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); - int retval; + int retval = -EINVAL; + + mutex_lock(&radio->lock); /* safety check */ - if (radio->removed) - return -EIO; + if (radio->removed) { + retval = -EIO; + goto unlock; + } switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -480,19 +495,20 @@ static int vidioc_s_ctrl(struct file *file, void *priv, if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "amradio_stop failed\n"); - return -1; } } else { retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "amradio_start failed\n"); - return -1; } } - return 0; + break; } - return -EINVAL; + +unlock: + mutex_unlock(&radio->lock); + return retval; } /* vidioc_g_audio - get audio attributes */ @@ -535,9 +551,14 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) static int usb_amradio_open(struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); - int retval; + int retval = 0; - lock_kernel(); + mutex_lock(&radio->lock); + + if (radio->removed) { + retval = -EIO; + goto unlock; + } radio->users = 1; radio->muted = 1; @@ -547,8 +568,7 @@ static int usb_amradio_open(struct file *file) amradio_dev_warn(&radio->videodev->dev, "radio did not start up properly\n"); radio->users = 0; - unlock_kernel(); - return -EIO; + goto unlock; } retval = amradio_set_stereo(radio, WANT_STEREO); @@ -561,22 +581,25 @@ static int usb_amradio_open(struct file *file) amradio_dev_warn(&radio->videodev->dev, "set frequency failed\n"); - unlock_kernel(); - return 0; +unlock: + mutex_unlock(&radio->lock); + return retval; } /*close device */ static int usb_amradio_close(struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); - int retval; - - if (!radio) - return -ENODEV; + int retval = 0; mutex_lock(&radio->lock); + + if (radio->removed) { + retval = -EIO; + goto unlock; + } + radio->users = 0; - mutex_unlock(&radio->lock); if (!radio->removed) { retval = amradio_set_mute(radio, AMRADIO_STOP); @@ -585,7 +608,9 @@ static int usb_amradio_close(struct file *file) "amradio_stop failed\n"); } - return 0; +unlock: + mutex_unlock(&radio->lock); + return retval; } /* Suspend device - stop device. Need to be checked and fixed */ @@ -594,12 +619,15 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) struct amradio_device *radio = usb_get_intfdata(intf); int retval; + mutex_lock(&radio->lock); + retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) dev_warn(&intf->dev, "amradio_stop failed\n"); dev_info(&intf->dev, "going into suspend..\n"); + mutex_unlock(&radio->lock); return 0; } @@ -609,12 +637,15 @@ static int usb_amradio_resume(struct usb_interface *intf) struct amradio_device *radio = usb_get_intfdata(intf); int retval; + mutex_lock(&radio->lock); + retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) dev_warn(&intf->dev, "amradio_start failed\n"); dev_info(&intf->dev, "coming out of suspend..\n"); + mutex_unlock(&radio->lock); return 0; } -- cgit v1.2.3 From 7a7d92e061ed13052d306cadad6972d52acea931 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 22 Sep 2009 21:37:30 -0300 Subject: V4L/DVB (13061): radio-mr800: simplify video_device allocation simplify video_device allocation Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 53 ++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 32 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 75c69755a04c..dd36ba0baab3 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -129,7 +129,7 @@ static int usb_amradio_resume(struct usb_interface *intf); struct amradio_device { /* reference to USB and video device */ struct usb_device *usbdev; - struct video_device *videodev; + struct video_device videodev; struct v4l2_device v4l2_dev; unsigned char *buffer; @@ -272,7 +272,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf) mutex_unlock(&radio->lock); usb_set_intfdata(intf, NULL); - video_unregister_device(radio->videodev); + video_unregister_device(&radio->videodev); v4l2_device_disconnect(&radio->v4l2_dev); } @@ -320,7 +320,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, */ retval = amradio_set_stereo(radio, WANT_STEREO); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); strcpy(v->name, "FM"); @@ -366,13 +366,13 @@ static int vidioc_s_tuner(struct file *file, void *priv, case V4L2_TUNER_MODE_MONO: retval = amradio_set_stereo(radio, WANT_MONO); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set mono failed\n"); break; case V4L2_TUNER_MODE_STEREO: retval = amradio_set_stereo(radio, WANT_STEREO); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); break; default: @@ -403,7 +403,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, retval = amradio_setfreq(radio, radio->curfreq); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n"); unlock: @@ -493,13 +493,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv, if (ctrl->value) { retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) { - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "amradio_stop failed\n"); } } else { retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) { - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "amradio_start failed\n"); } } @@ -565,7 +565,7 @@ static int usb_amradio_open(struct file *file) retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) { - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "radio did not start up properly\n"); radio->users = 0; goto unlock; @@ -573,12 +573,12 @@ static int usb_amradio_open(struct file *file) retval = amradio_set_stereo(radio, WANT_STEREO); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); retval = amradio_setfreq(radio, radio->curfreq); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n"); unlock: @@ -604,7 +604,7 @@ static int usb_amradio_close(struct file *file) if (!radio->removed) { retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) - amradio_dev_warn(&radio->videodev->dev, + amradio_dev_warn(&radio->videodev.dev, "amradio_stop failed\n"); } @@ -676,9 +676,6 @@ static void usb_amradio_video_device_release(struct video_device *videodev) { struct amradio_device *radio = video_get_drvdata(videodev); - /* we call v4l to free radio->videodev */ - video_device_release(videodev); - v4l2_device_unregister(&radio->v4l2_dev); /* free rest memory */ @@ -718,20 +715,12 @@ static int usb_amradio_probe(struct usb_interface *intf, return retval; } - radio->videodev = video_device_alloc(); - - if (!radio->videodev) { - dev_err(&intf->dev, "video_device_alloc failed\n"); - kfree(radio->buffer); - kfree(radio); - return -ENOMEM; - } - - strlcpy(radio->videodev->name, v4l2_dev->name, sizeof(radio->videodev->name)); - radio->videodev->v4l2_dev = v4l2_dev; - radio->videodev->fops = &usb_amradio_fops; - radio->videodev->ioctl_ops = &usb_amradio_ioctl_ops; - radio->videodev->release = usb_amradio_video_device_release; + strlcpy(radio->videodev.name, v4l2_dev->name, + sizeof(radio->videodev.name)); + radio->videodev.v4l2_dev = v4l2_dev; + radio->videodev.fops = &usb_amradio_fops; + radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; + radio->videodev.release = usb_amradio_video_device_release; radio->removed = 0; radio->users = 0; @@ -741,12 +730,12 @@ static int usb_amradio_probe(struct usb_interface *intf, mutex_init(&radio->lock); - video_set_drvdata(radio->videodev, radio); + video_set_drvdata(&radio->videodev, radio); - retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); + retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, + radio_nr); if (retval < 0) { dev_err(&intf->dev, "could not register video device\n"); - video_device_release(radio->videodev); v4l2_device_unregister(v4l2_dev); kfree(radio->buffer); kfree(radio); -- cgit v1.2.3 From 1b8bbb3c0a719f3baac22ea4a7eb1d636383ba3b Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 22 Sep 2009 21:43:19 -0300 Subject: V4L/DVB (13062): radio-mr800: simplify error paths in usb probe callback Simplify error paths in usb probe callback. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index dd36ba0baab3..0c5d734b00fa 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -689,30 +689,29 @@ static int usb_amradio_probe(struct usb_interface *intf, { struct amradio_device *radio; struct v4l2_device *v4l2_dev; - int retval; + int retval = 0; radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL); if (!radio) { dev_err(&intf->dev, "kmalloc for amradio_device failed\n"); - return -ENOMEM; + retval = -ENOMEM; + goto err; } radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); if (!radio->buffer) { dev_err(&intf->dev, "kmalloc for radio->buffer failed\n"); - kfree(radio); - return -ENOMEM; + retval = -ENOMEM; + goto err_nobuf; } v4l2_dev = &radio->v4l2_dev; retval = v4l2_device_register(&intf->dev, v4l2_dev); if (retval < 0) { dev_err(&intf->dev, "couldn't register v4l2_device\n"); - kfree(radio->buffer); - kfree(radio); - return retval; + goto err_v4l2; } strlcpy(radio->videodev.name, v4l2_dev->name, @@ -736,14 +735,20 @@ static int usb_amradio_probe(struct usb_interface *intf, radio_nr); if (retval < 0) { dev_err(&intf->dev, "could not register video device\n"); - v4l2_device_unregister(v4l2_dev); - kfree(radio->buffer); - kfree(radio); - return -EIO; + goto err_vdev; } usb_set_intfdata(intf, radio); return 0; + +err_vdev: + v4l2_device_unregister(v4l2_dev); +err_v4l2: + kfree(radio->buffer); +err_nobuf: + kfree(radio); +err: + return retval; } static int __init amradio_init(void) -- cgit v1.2.3 From d1939e4c5f053e34dd432b448e221f55586a68ec Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 22 Sep 2009 21:48:43 -0300 Subject: V4L/DVB (13063): radio-mr800: remove unnecessary local variable Remove unnecessary local variable. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0c5d734b00fa..24c55a5a6cac 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -688,7 +688,6 @@ static int usb_amradio_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct amradio_device *radio; - struct v4l2_device *v4l2_dev; int retval = 0; radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL); @@ -707,16 +706,15 @@ static int usb_amradio_probe(struct usb_interface *intf, goto err_nobuf; } - v4l2_dev = &radio->v4l2_dev; - retval = v4l2_device_register(&intf->dev, v4l2_dev); + retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); if (retval < 0) { dev_err(&intf->dev, "couldn't register v4l2_device\n"); goto err_v4l2; } - strlcpy(radio->videodev.name, v4l2_dev->name, + strlcpy(radio->videodev.name, radio->v4l2_dev.name, sizeof(radio->videodev.name)); - radio->videodev.v4l2_dev = v4l2_dev; + radio->videodev.v4l2_dev = &radio->v4l2_dev; radio->videodev.fops = &usb_amradio_fops; radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; radio->videodev.release = usb_amradio_video_device_release; @@ -742,7 +740,7 @@ static int usb_amradio_probe(struct usb_interface *intf, return 0; err_vdev: - v4l2_device_unregister(v4l2_dev); + v4l2_device_unregister(&radio->v4l2_dev); err_v4l2: kfree(radio->buffer); err_nobuf: -- cgit v1.2.3 From ceb99e1b5a093ae8f439fc55aac28d007145c8ec Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 17:45:31 -0300 Subject: V4L/DVB (13064): radio-mr800: simplify access to amradio_device Simplify access to amradio_device. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 24c55a5a6cac..5401952004bc 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -141,6 +141,8 @@ struct amradio_device { int muted; }; +#define vdev_to_amradio(r) container_of(r, struct amradio_device, videodev) + /* USB Device ID List */ static struct usb_device_id usb_amradio_device_table[] = { {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT, @@ -280,7 +282,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - struct amradio_device *radio = video_drvdata(file); + struct amradio_device *radio = file->private_data; strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); @@ -294,7 +296,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval; mutex_lock(&radio->lock); @@ -345,7 +347,7 @@ unlock: static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval; mutex_lock(&radio->lock); @@ -388,7 +390,7 @@ unlock: static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval; mutex_lock(&radio->lock); @@ -415,7 +417,7 @@ unlock: static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval = 0; mutex_lock(&radio->lock); @@ -450,7 +452,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval = -EINVAL; mutex_lock(&radio->lock); @@ -477,7 +479,7 @@ unlock: static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval = -EINVAL; mutex_lock(&radio->lock); @@ -550,7 +552,7 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) /* open device - amradio_start() and amradio_setfreq() */ static int usb_amradio_open(struct file *file) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = vdev_to_amradio(video_devdata(file)); int retval = 0; mutex_lock(&radio->lock); @@ -560,6 +562,7 @@ static int usb_amradio_open(struct file *file) goto unlock; } + file->private_data = radio; radio->users = 1; radio->muted = 1; @@ -589,7 +592,7 @@ unlock: /*close device */ static int usb_amradio_close(struct file *file) { - struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + struct amradio_device *radio = file->private_data; int retval = 0; mutex_lock(&radio->lock); @@ -674,7 +677,7 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { static void usb_amradio_video_device_release(struct video_device *videodev) { - struct amradio_device *radio = video_get_drvdata(videodev); + struct amradio_device *radio = vdev_to_amradio(videodev); v4l2_device_unregister(&radio->v4l2_dev); -- cgit v1.2.3 From eac000a90e70b990c7d847ac40ff1c33a5f00636 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 17:49:36 -0300 Subject: V4L/DVB (13065): radio-mr800: simplify locking in ioctl callbacks Simplify locking in ioctl callbacks. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 109 +++++++++++--------------------------- 1 file changed, 30 insertions(+), 79 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 5401952004bc..0498c4c60d8c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -299,18 +299,8 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct amradio_device *radio = file->private_data; int retval; - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } - - if (v->index > 0) { - retval = -EINVAL; - goto unlock; - } + if (v->index > 0) + return -EINVAL; /* TODO: Add function which look is signal stereo or not * amradio_getstat(radio); @@ -338,8 +328,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->signal = 0xffff; /* Can't get the signal strength, sad.. */ v->afc = 0; /* Don't know what is this */ -unlock: - mutex_unlock(&radio->lock); return retval; } @@ -348,20 +336,10 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct amradio_device *radio = file->private_data; - int retval; - - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } + int retval = -EINVAL; - if (v->index > 0) { - retval = -EINVAL; - goto unlock; - } + if (v->index > 0) + return -EINVAL; /* mono/stereo selector */ switch (v->audmode) { @@ -377,12 +355,8 @@ static int vidioc_s_tuner(struct file *file, void *priv, amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); break; - default: - retval = -EINVAL; } -unlock: - mutex_unlock(&radio->lock); return retval; } @@ -391,15 +365,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = file->private_data; - int retval; - - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } + int retval = 0; radio->curfreq = f->frequency; @@ -408,8 +374,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n"); -unlock: - mutex_unlock(&radio->lock); return retval; } @@ -418,22 +382,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = file->private_data; - int retval = 0; - - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; -unlock: - mutex_unlock(&radio->lock); - return retval; + return 0; } /* vidioc_queryctrl - enumerate control items */ @@ -453,26 +406,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct amradio_device *radio = file->private_data; - int retval = -EINVAL; - - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = radio->muted; - retval = 0; - break; + return 0; } -unlock: - mutex_unlock(&radio->lock); - return retval; + return -EINVAL; } /* vidioc_s_ctrl - set the value of a control */ @@ -482,14 +423,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct amradio_device *radio = file->private_data; int retval = -EINVAL; - mutex_lock(&radio->lock); - - /* safety check */ - if (radio->removed) { - retval = -EIO; - goto unlock; - } - switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { @@ -508,8 +441,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, break; } -unlock: - mutex_unlock(&radio->lock); return retval; } @@ -616,6 +547,26 @@ unlock: return retval; } +static long usb_amradio_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct amradio_device *radio = file->private_data; + long retval = 0; + + mutex_lock(&radio->lock); + + if (radio->removed) { + retval = -EIO; + goto unlock; + } + + retval = video_ioctl2(file, cmd, arg); + +unlock: + mutex_unlock(&radio->lock); + return retval; +} + /* Suspend device - stop device. Need to be checked and fixed */ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) { @@ -657,7 +608,7 @@ static const struct v4l2_file_operations usb_amradio_fops = { .owner = THIS_MODULE, .open = usb_amradio_open, .release = usb_amradio_close, - .ioctl = video_ioctl2, + .ioctl = usb_amradio_ioctl, }; static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { -- cgit v1.2.3 From 26452bfef4ae4798b96281ad8d3aed6e2d79846e Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 17:52:17 -0300 Subject: V4L/DVB (13066): radio-mr800: remove device removed indicator Remove device removed indicator Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0498c4c60d8c..c4f4cd8dbb6c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -137,7 +137,6 @@ struct amradio_device { int curfreq; int stereo; int users; - int removed; int muted; }; @@ -270,7 +269,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf) struct amradio_device *radio = usb_get_intfdata(intf); mutex_lock(&radio->lock); - radio->removed = 1; + radio->usbdev = NULL; mutex_unlock(&radio->lock); usb_set_intfdata(intf, NULL); @@ -488,7 +487,7 @@ static int usb_amradio_open(struct file *file) mutex_lock(&radio->lock); - if (radio->removed) { + if (!radio->usbdev) { retval = -EIO; goto unlock; } @@ -528,19 +527,17 @@ static int usb_amradio_close(struct file *file) mutex_lock(&radio->lock); - if (radio->removed) { + if (!radio->usbdev) { retval = -EIO; goto unlock; } radio->users = 0; - if (!radio->removed) { - retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "amradio_stop failed\n"); - } + retval = amradio_set_mute(radio, AMRADIO_STOP); + if (retval < 0) + amradio_dev_warn(&radio->videodev.dev, + "amradio_stop failed\n"); unlock: mutex_unlock(&radio->lock); @@ -555,7 +552,7 @@ static long usb_amradio_ioctl(struct file *file, unsigned int cmd, mutex_lock(&radio->lock); - if (radio->removed) { + if (!radio->usbdev) { retval = -EIO; goto unlock; } @@ -673,7 +670,6 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; radio->videodev.release = usb_amradio_video_device_release; - radio->removed = 0; radio->users = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = 95.16 * FREQ_MUL; -- cgit v1.2.3 From 4e3616576e9e65d53f9381b9f334257299c7262e Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:03:52 -0300 Subject: V4L/DVB (13067): radio-mr800: fix potential use after free Fix portential use after free. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index c4f4cd8dbb6c..dbae50ba250c 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -273,8 +273,8 @@ static void usb_amradio_disconnect(struct usb_interface *intf) mutex_unlock(&radio->lock); usb_set_intfdata(intf, NULL); - video_unregister_device(&radio->videodev); v4l2_device_disconnect(&radio->v4l2_dev); + video_unregister_device(&radio->videodev); } /* vidioc_querycap - query device capabilities */ -- cgit v1.2.3 From 8a7cd16f1fa31ef6db9cfc16b1eb0356566e974d Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:09:01 -0300 Subject: V4L/DVB (13068): radio-mr800: remove device initialization from open/close Remove device initialization from open/close. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index dbae50ba250c..399032e8cc18 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -136,7 +136,6 @@ struct amradio_device { struct mutex lock; /* buffer locking */ int curfreq; int stereo; - int users; int muted; }; @@ -493,26 +492,6 @@ static int usb_amradio_open(struct file *file) } file->private_data = radio; - radio->users = 1; - radio->muted = 1; - - retval = amradio_set_mute(radio, AMRADIO_START); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, - "radio did not start up properly\n"); - radio->users = 0; - goto unlock; - } - - retval = amradio_set_stereo(radio, WANT_STEREO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set stereo failed\n"); - - retval = amradio_setfreq(radio, radio->curfreq); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set frequency failed\n"); unlock: mutex_unlock(&radio->lock); @@ -527,19 +506,9 @@ static int usb_amradio_close(struct file *file) mutex_lock(&radio->lock); - if (!radio->usbdev) { + if (!radio->usbdev) retval = -EIO; - goto unlock; - } - - radio->users = 0; - retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "amradio_stop failed\n"); - -unlock: mutex_unlock(&radio->lock); return retval; } @@ -670,10 +639,10 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->videodev.ioctl_ops = &usb_amradio_ioctl_ops; radio->videodev.release = usb_amradio_video_device_release; - radio->users = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = 95.16 * FREQ_MUL; radio->stereo = -1; + radio->muted = 1; mutex_init(&radio->lock); -- cgit v1.2.3 From 502d50166cdef6cc8f63ab8c6ab35694ee39f608 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:13:50 -0300 Subject: V4L/DVB (13069): radio-mr800: ensure the radio is initialized to a consistent state Ensure the radio is initialized to a consistent state. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 399032e8cc18..7db992d3b0db 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -85,6 +85,9 @@ MODULE_LICENSE("GPL"); #define amradio_dev_warn(dev, fmt, arg...) \ dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg) +#define amradio_dev_err(dev, fmt, arg...) \ + dev_err(dev, MR800_DRIVER_NAME " - " fmt, ##arg) + /* Probably USB_TIMEOUT should be modified in module parameter */ #define BUFFER_LENGTH 8 #define USB_TIMEOUT 500 @@ -137,6 +140,7 @@ struct amradio_device { int curfreq; int stereo; int muted; + int initialized; }; #define vdev_to_amradio(r) container_of(r, struct amradio_device, videodev) @@ -478,6 +482,31 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) return 0; } +static int usb_amradio_init(struct amradio_device *radio) +{ + int retval; + + retval = amradio_set_mute(radio, AMRADIO_STOP); + if (retval < 0) { + amradio_dev_warn(&radio->videodev.dev, "amradio_stop failed\n"); + goto out_err; + } + + retval = amradio_set_stereo(radio, WANT_STEREO); + if (retval < 0) { + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); + goto out_err; + } + + radio->initialized = 1; + goto out; + +out_err: + amradio_dev_err(&radio->videodev.dev, "initialization failed\n"); +out: + return retval; +} + /* open device - amradio_start() and amradio_setfreq() */ static int usb_amradio_open(struct file *file) { @@ -493,6 +522,9 @@ static int usb_amradio_open(struct file *file) file->private_data = radio; + if (unlikely(!radio->initialized)) + retval = usb_amradio_init(radio); + unlock: mutex_unlock(&radio->lock); return retval; @@ -641,8 +673,6 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->usbdev = interface_to_usbdev(intf); radio->curfreq = 95.16 * FREQ_MUL; - radio->stereo = -1; - radio->muted = 1; mutex_init(&radio->lock); -- cgit v1.2.3 From 30dd4508b97155a3f826f877d5750d8888bc3183 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:16:38 -0300 Subject: V4L/DVB (13070): radio-mr800: fix behavior of set_stereo function Fix behavior of set_stereo function. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 7db992d3b0db..9764eca2c498 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -252,12 +252,13 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) { - radio->stereo = -1; + if (retval < 0 || size != BUFFER_LENGTH) return retval; - } - radio->stereo = 1; + if (argument == WANT_STEREO) + radio->stereo = 1; + else + radio->stereo = 0; return retval; } -- cgit v1.2.3 From d8970e5fd9eace437bc2f1aaff1c2a05fb3448ea Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:24:47 -0300 Subject: V4L/DVB (13071): radio-mr800: preserve radio state during suspend/resume Preserve radio state during suspend/resume. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 9764eca2c498..ac2107378942 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -574,9 +574,12 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) mutex_lock(&radio->lock); - retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) - dev_warn(&intf->dev, "amradio_stop failed\n"); + if (!radio->muted && radio->initialized) { + retval = amradio_set_mute(radio, AMRADIO_STOP); + if (retval < 0) + dev_warn(&intf->dev, "amradio_stop failed\n"); + radio->muted = 0; + } dev_info(&intf->dev, "going into suspend..\n"); @@ -592,10 +595,30 @@ static int usb_amradio_resume(struct usb_interface *intf) mutex_lock(&radio->lock); - retval = amradio_set_mute(radio, AMRADIO_START); + if (unlikely(!radio->initialized)) + goto unlock; + + if (radio->stereo) + retval = amradio_set_stereo(radio, WANT_STEREO); + else + retval = amradio_set_stereo(radio, WANT_MONO); + if (retval < 0) - dev_warn(&intf->dev, "amradio_start failed\n"); + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); + retval = amradio_setfreq(radio, radio->curfreq); + if (retval < 0) + amradio_dev_warn(&radio->videodev.dev, + "set frequency failed\n"); + + if (!radio->muted) { + retval = amradio_set_mute(radio, AMRADIO_START); + if (retval < 0) + dev_warn(&radio->videodev.dev, + "amradio_start failed\n"); + } + +unlock: dev_info(&intf->dev, "coming out of suspend..\n"); mutex_unlock(&radio->lock); -- cgit v1.2.3 From 16a72f41bb82573d7fe1dfea1cb8356dee307db4 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:28:02 -0300 Subject: V4L/DVB (13072): radio-mr800: simplify device warnings Simplify device warnings. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 78 +++++++++++++-------------------------- 1 file changed, 26 insertions(+), 52 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index ac2107378942..5506fac5fd49 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -186,8 +186,10 @@ static int amradio_set_mute(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) + if (retval < 0 || size != BUFFER_LENGTH) { + amradio_dev_warn(&radio->videodev.dev, "set mute failed\n"); return retval; + } radio->muted = argument; @@ -216,7 +218,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); if (retval < 0 || size != BUFFER_LENGTH) - return retval; + goto out_err; /* frequency is calculated from freq_send and placed in first 2 bytes */ radio->buffer[0] = (freq_send >> 8) & 0xff; @@ -230,6 +232,14 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); + if (retval < 0 || size != BUFFER_LENGTH) + goto out_err; + + goto out; + +out_err: + amradio_dev_warn(&radio->videodev.dev, "set frequency failed\n"); +out: return retval; } @@ -252,8 +262,10 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval < 0 || size != BUFFER_LENGTH) + if (retval < 0 || size != BUFFER_LENGTH) { + amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); return retval; + } if (argument == WANT_STEREO) radio->stereo = 1; @@ -314,9 +326,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, * amradio_set_stereo shouldn't be here */ retval = amradio_set_stereo(radio, WANT_STEREO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set stereo failed\n"); strcpy(v->name, "FM"); v->type = V4L2_TUNER_RADIO; @@ -348,15 +357,9 @@ static int vidioc_s_tuner(struct file *file, void *priv, switch (v->audmode) { case V4L2_TUNER_MODE_MONO: retval = amradio_set_stereo(radio, WANT_MONO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set mono failed\n"); break; case V4L2_TUNER_MODE_STEREO: retval = amradio_set_stereo(radio, WANT_STEREO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set stereo failed\n"); break; } @@ -373,9 +376,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, radio->curfreq = f->frequency; retval = amradio_setfreq(radio, radio->curfreq); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set frequency failed\n"); return retval; } @@ -428,19 +428,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { + if (ctrl->value) retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, - "amradio_stop failed\n"); - } - } else { + else retval = amradio_set_mute(radio, AMRADIO_START); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, - "amradio_start failed\n"); - } - } + break; } @@ -488,16 +480,12 @@ static int usb_amradio_init(struct amradio_device *radio) int retval; retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, "amradio_stop failed\n"); + if (retval) goto out_err; - } retval = amradio_set_stereo(radio, WANT_STEREO); - if (retval < 0) { - amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); + if (retval) goto out_err; - } radio->initialized = 1; goto out; @@ -570,14 +558,11 @@ unlock: static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) { struct amradio_device *radio = usb_get_intfdata(intf); - int retval; mutex_lock(&radio->lock); if (!radio->muted && radio->initialized) { - retval = amradio_set_mute(radio, AMRADIO_STOP); - if (retval < 0) - dev_warn(&intf->dev, "amradio_stop failed\n"); + amradio_set_mute(radio, AMRADIO_STOP); radio->muted = 0; } @@ -591,7 +576,6 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) static int usb_amradio_resume(struct usb_interface *intf) { struct amradio_device *radio = usb_get_intfdata(intf); - int retval; mutex_lock(&radio->lock); @@ -599,24 +583,14 @@ static int usb_amradio_resume(struct usb_interface *intf) goto unlock; if (radio->stereo) - retval = amradio_set_stereo(radio, WANT_STEREO); + amradio_set_stereo(radio, WANT_STEREO); else - retval = amradio_set_stereo(radio, WANT_MONO); + amradio_set_stereo(radio, WANT_MONO); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, "set stereo failed\n"); + amradio_setfreq(radio, radio->curfreq); - retval = amradio_setfreq(radio, radio->curfreq); - if (retval < 0) - amradio_dev_warn(&radio->videodev.dev, - "set frequency failed\n"); - - if (!radio->muted) { - retval = amradio_set_mute(radio, AMRADIO_START); - if (retval < 0) - dev_warn(&radio->videodev.dev, - "amradio_start failed\n"); - } + if (!radio->muted) + amradio_set_mute(radio, AMRADIO_START); unlock: dev_info(&intf->dev, "coming out of suspend..\n"); -- cgit v1.2.3 From 798166dbecafa98ec9b28d056774ec2fc80290df Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Wed, 23 Sep 2009 18:31:26 -0300 Subject: V4L/DVB (13073): radio-mr800: set radio frequency only upon success Set radio frequency only upon success. Signed-off-by: David Ellingsworth Acked-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 5506fac5fd49..4064109c4205 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -235,6 +235,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) if (retval < 0 || size != BUFFER_LENGTH) goto out_err; + radio->curfreq = freq; goto out; out_err: @@ -371,13 +372,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = file->private_data; - int retval = 0; - - radio->curfreq = f->frequency; - retval = amradio_setfreq(radio, radio->curfreq); - - return retval; + return amradio_setfreq(radio, f->frequency); } /* vidioc_g_frequency - get tuner radio frequency */ -- cgit v1.2.3 From d89ce0d9ec9f980d59eae8d5a0ead98988e3b545 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 9 Nov 2009 19:09:49 -0300 Subject: V4L/DVB (13402): radio-mr800 - autosuspend for radio-mr800 driver Patch adds autosuspend support for mr800 radio driver. Signed-off-by: Oliver Neukum Acked-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-mr800.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/media/radio/radio-mr800.c') diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 4064109c4205..44efa68d9f8e 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -132,6 +132,7 @@ static int usb_amradio_resume(struct usb_interface *intf); struct amradio_device { /* reference to USB and video device */ struct usb_device *usbdev; + struct usb_interface *intf; struct video_device videodev; struct v4l2_device v4l2_dev; @@ -163,7 +164,7 @@ static struct usb_driver usb_amradio_driver = { .resume = usb_amradio_resume, .reset_resume = usb_amradio_resume, .id_table = usb_amradio_device_table, - .supports_autosuspend = 0, + .supports_autosuspend = 1, }; /* switch on/off the radio. Send 8 bytes to device */ @@ -506,9 +507,15 @@ static int usb_amradio_open(struct file *file) } file->private_data = radio; + retval = usb_autopm_get_interface(radio->intf); + if (retval) + goto unlock; - if (unlikely(!radio->initialized)) + if (unlikely(!radio->initialized)) { retval = usb_amradio_init(radio); + if (retval) + usb_autopm_put_interface(radio->intf); + } unlock: mutex_unlock(&radio->lock); @@ -525,6 +532,8 @@ static int usb_amradio_close(struct file *file) if (!radio->usbdev) retval = -EIO; + else + usb_autopm_put_interface(radio->intf); mutex_unlock(&radio->lock); return retval; @@ -666,6 +675,7 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->videodev.release = usb_amradio_video_device_release; radio->usbdev = interface_to_usbdev(intf); + radio->intf = intf; radio->curfreq = 95.16 * FREQ_MUL; mutex_init(&radio->lock); -- cgit v1.2.3