Re: handling failure in suspend() during autosuspend

Alan Stern <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
On Fri, 5 Oct 2007, Oliver Neukum wrote:

> Am Freitag 05 Oktober 2007 schrieb Alan Stern:
> > As far as the race is concerned...  In practice it shouldn't matter
> > unless autosuspend_delay is set to 0.  I suppose autosuspend_check()  
> > could take an extra "reschedule" flag.  If the flag was set, the
> > routine would schedule another autosuspend attempt (with a 1-second
> > delay) if the idle-time period had already expired.
> 
> OK. Like this?

I had in mind something a little more cautious, like this:

Alan Stern


Index: usb-2.6/drivers/usb/core/driver.c
===================================================================
--- usb-2.6.orig/drivers/usb/core/driver.c
+++ usb-2.6/drivers/usb/core/driver.c
@@ -935,7 +935,7 @@ done:
 #ifdef	CONFIG_USB_SUSPEND
 
 /* Internal routine to check whether we may autosuspend a device. */
-static int autosuspend_check(struct usb_device *udev)
+static int autosuspend_check(struct usb_device *udev, int reschedule)
 {
 	int			i;
 	struct usb_interface	*intf;
@@ -981,9 +981,15 @@ static int autosuspend_check(struct usb_
 	}
 
 	/* If everything is okay but the device hasn't been idle for long
-	 * enough, queue a delayed autosuspend request.
+	 * enough, queue a delayed autosuspend request.  If the device
+	 * _has_ been idle for long enough and the reschedule flag is set,
+	 * likewise queue a delayed (1 second) autosuspend request.
 	 */
-	if (time_after(suspend_time, jiffies)) {
+	if (time_after(suspend_time, jiffies))
+		reschedule = 1;
+	else
+		suspend_time = jiffies + HZ;
+	if (reschedule) {
 		if (!timer_pending(&udev->autosuspend.timer)) {
 
 			/* The value of jiffies may change between the
@@ -993,7 +999,7 @@ static int autosuspend_check(struct usb_
 			 * or for the past.
 			 */
 			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-				round_jiffies_relative(suspend_time - jiffies));
+				round_jiffies(suspend_time));
 			}
 		return -EAGAIN;
 	}
@@ -1002,7 +1008,7 @@ static int autosuspend_check(struct usb_
 
 #else
 
-static inline int autosuspend_check(struct usb_device *udev)
+static inline int autosuspend_check(struct usb_device *udev, int reschedule)
 {
 	return 0;
 }
@@ -1059,7 +1065,7 @@ static int usb_suspend_both(struct usb_d
 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 
 	if (udev->auto_pm) {
-		status = autosuspend_check(udev);
+		status = autosuspend_check(udev, 0);
 		if (status < 0)
 			goto done;
 	}
@@ -1085,7 +1091,7 @@ static int usb_suspend_both(struct usb_d
 
 		/* Try another autosuspend when the interfaces aren't busy */
 		if (udev->auto_pm)
-			autosuspend_check(udev);
+			autosuspend_check(udev, status == -EBUSY);
 
 	/* If the suspend succeeded then prevent any more URB submissions,
 	 * flush any outstanding URBs, and propagate the suspend up the tree.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.