Hi, this patch should cleanup suspend/resume support and add autosuspend support. Could you test this? Regards Oliver -- commit 57375ad73388fd944d7447ddb3e1e56eb48ba421 Author: Oliver Neukum <oneukum@linux-d698.(none)> Date: Thu Jul 2 20:03:02 2009 +0200 usb: autosuspend for radio-mr800 driver diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 837467f..496c9cf 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -123,11 +123,13 @@ static int usb_amradio_close(struct file *file); static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message); static int usb_amradio_resume(struct usb_interface *intf); +static int usb_amradio_reset_resume(struct usb_interface *intf); /* Data for one (physical) device */ 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; @@ -156,9 +158,9 @@ static struct usb_driver usb_amradio_driver = { .disconnect = usb_amradio_disconnect, .suspend = usb_amradio_suspend, .resume = usb_amradio_resume, - .reset_resume = usb_amradio_resume, + .reset_resume = usb_amradio_reset_resume, .id_table = usb_amradio_device_table, - .supports_autosuspend = 0, + .supports_autosuspend = 1, }; /* switch on/off the radio. Send 8 bytes to device */ @@ -541,13 +543,15 @@ static int usb_amradio_open(struct file *file) radio->users = 1; radio->muted = 1; + retval = usb_autopm_get_interface(radio->intf); + if (retval < 0) + goto err_out; + 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; - unlock_kernel(); - return -EIO; + "radio did not wake up\n"); + goto err_out_pm; } retval = amradio_set_stereo(radio, WANT_STEREO); @@ -562,6 +566,15 @@ static int usb_amradio_open(struct file *file) unlock_kernel(); return 0; + +err_out_pm: + amradio_dev_warn(&radio->videodev->dev, + "radio did not start up properly\n"); + usb_autopm_put_interface(radio->intf); +err_out: + radio->users = 0; + unlock_kernel(); + return -EIO; } /*close device */ @@ -582,6 +595,7 @@ static int usb_amradio_close(struct file *file) if (retval < 0) amradio_dev_warn(&radio->videodev->dev, "amradio_stop failed\n"); + usb_autopm_put_interface(radio->intf); } return 0; @@ -591,30 +605,45 @@ static int usb_amradio_close(struct file *file) static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) { struct amradio_device *radio = usb_get_intfdata(intf); - int retval; + int retval = 0; retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) dev_warn(&intf->dev, "amradio_stop failed\n"); + else + dev_info(&intf->dev, "going into suspend..\n"); - dev_info(&intf->dev, "going into suspend..\n"); - - return 0; + return retval; } -/* Resume device - start device. Need to be checked and fixed */ static int usb_amradio_resume(struct usb_interface *intf) { struct amradio_device *radio = usb_get_intfdata(intf); - int retval; + int retval = 0; - retval = amradio_set_mute(radio, AMRADIO_START); - if (retval < 0) - dev_warn(&intf->dev, "amradio_start failed\n"); + if (radio->users) { + 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"); - return 0; + return retval; +} + +static int usb_amradio_reset_resume(struct usb_interface *intf) +{ + struct amradio_device *radio = usb_get_intfdata(intf); + int retval = 0; + + if (radio->users) { + retval = amradio_set_stereo(radio, WANT_STEREO); + if (!retval) + retval = usb_amradio_resume(intf); + } + + return retval; } /* File system interface */ @@ -669,6 +698,7 @@ static int usb_amradio_probe(struct usb_interface *intf, return -ENOMEM; } + radio->intf = intf; radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); if (!radio->buffer) { -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html