Google
  Web www.spinics.net

Re: handling failure in suspend() during autosuspend

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


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/
_______________________________________________
linux-usb-devel@xxxxxxxxxxxxxxxxxxxxx
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel


[Home]     [Video for Linux]     [Photo]     [Yosemite Forum]     [Yosemite Photos]    [Video Projectors]     [PDAs]     [Hacking TiVo]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Devices]     [Big List of Linux Books]     [Free Dating]

  Powered by Linux