Hi Oliver, Am Freitag, 1. Februar 2008 15:52:37 schrieben Sie: > this should implement autosuspend. Could you please test it? > It's against 1.0.6.
I still don't know yet, what usb autosuspend really does and how I have to control /sys/bus/usb/devices/*/power/autosuspend. But anyway... the new functionallity should work out of the box. The radio still works. But the rds daemon now hangs on start and can't be terminated any more. ps shows D+. I inserted some debug printk to see if the new functions, suspend and resume, do anything, which is not the case here. So I then removed the mutex radio->lock codes and from then on everything works fine again. But the debug code still shows, that suspend and resume are never called. cat /sys/bus/usb/devices/*/power/autosuspend shows all devices having 2, expect from the radio, which has 0. Do I have to configure here anything, so that suspend and resume get's ever called? I was wondering about another thing: The radio is per se switched off (radio_stop), when no users are using this device. In that case suspend and resume are useless, as the device is already powered off. If a radio application or the rdsd is running, then the usb device should never go to suspend or resume. So then suspend and resume are useless here too. Or am I missing here something? The current patch, which is working here without the locking stuff, is shown below. Bye, Toby --- versions/1.0.6/radio-si470x.c 2008-01-31 22:40:28.000000000 +0100 +++ radio-si470x.c 2008-02-02 15:05:42.000000000 +0100 @@ -81,6 +81,9 @@ * - racy interruptible_sleep_on(), * replaced with wait_event_interruptible() * - handle signals in read() + * 2008-02-01 Tobias Lorenz <[EMAIL PROTECTED]> + * Oliver Neukum <[EMAIL PROTECTED]> + * - autosuspend * * ToDo: * - add seeking support @@ -108,7 +111,7 @@ #include <linux/usb.h> #include <linux/hid.h> #include <linux/version.h> -#include "compat.h" +//#include "compat.h" #include <linux/videodev2.h> #include <linux/mutex.h> #include <media/v4l2-common.h> @@ -416,6 +419,7 @@ MODULE_PARM_DESC(rds_poll_time, "RDS pol struct si470x_device { /* reference to USB and video device */ struct usb_device *usbdev; + struct usb_interface *intf; struct video_device *videodev; /* driver management */ @@ -962,10 +966,22 @@ static unsigned int si470x_fops_poll(str static int si470x_fops_open(struct inode *inode, struct file *file) { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + int retval; radio->users++; - if (radio->users == 1) - return si470x_start(radio); + + retval = usb_autopm_get_interface(radio->intf); + if (retval < 0) { + radio->users--; + return -EIO; + } + + if (radio->users == 1) { + retval = si470x_start(radio); + if (retval < 0) + usb_autopm_put_interface(radio->intf); + return retval; + } return 0; } @@ -977,6 +993,7 @@ static int si470x_fops_open(struct inode static int si470x_fops_release(struct inode *inode, struct file *file) { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + int retval; if (!radio) return -ENODEV; @@ -989,7 +1006,9 @@ static int si470x_fops_release(struct in /* cancel read processes */ wake_up_interruptible(&radio->read_queue); - return si470x_stop(radio); + retval = si470x_stop(radio); + usb_autopm_put_interface(radio->intf); + return retval; } return 0; @@ -1378,6 +1397,7 @@ static int si470x_usb_driver_probe(struc sizeof(si470x_viddev_template)); radio->users = 0; radio->usbdev = interface_to_usbdev(intf); + radio->intf = intf; mutex_init(&radio->lock); video_set_drvdata(radio->videodev, radio); @@ -1441,6 +1461,39 @@ err_initial: /* + * si470x_usb_driver_suspend - suspend the device + */ +static int si470x_usb_driver_suspend(struct usb_interface *intf, + pm_message_t message) +{ + struct si470x_device *radio = usb_get_intfdata(intf); + + printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); + + cancel_delayed_work_sync(&radio->work); + + return 0; +} + + +/* + * si470x_usb_driver_resume - resume the device + */ +static int si470x_usb_driver_resume(struct usb_interface *intf) +{ + struct si470x_device *radio = usb_get_intfdata(intf); + + printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); + + if (radio->users && radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) + schedule_delayed_work(&radio->work, + msecs_to_jiffies(rds_poll_time)); + + return 0; +} + + +/* * si470x_usb_driver_disconnect - disconnect the device */ static void si470x_usb_driver_disconnect(struct usb_interface *intf) @@ -1459,10 +1512,13 @@ static void si470x_usb_driver_disconnect * si470x_usb_driver - usb driver interface */ static struct usb_driver si470x_usb_driver = { - .name = DRIVER_NAME, - .probe = si470x_usb_driver_probe, - .disconnect = si470x_usb_driver_disconnect, - .id_table = si470x_usb_driver_id_table, + .name = DRIVER_NAME, + .probe = si470x_usb_driver_probe, + .disconnect = si470x_usb_driver_disconnect, + .suspend = si470x_usb_driver_suspend, + .resume = si470x_usb_driver_resume, + .id_table = si470x_usb_driver_id_table, + .supports_autosuspend = 1, }; - To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html