modifications to new generic autosuspend code

Oliver Neukum <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
Hi Alan,

here are the changes I made to adapt the HID suspend code to the new
model. Basically I just changed the simple flag to a callback that allows
to know whether the flag has been checked and allow several independently
removable sources of business.

	Regards
		Oliver

--------

--- linux-2.6.20/drivers/usb/core/driver.c	2007-02-06 14:14:48.000000000 +0100
+++ linux-stern/drivers/usb/core/driver.c	2007-02-15 16:04:57.000000000 +0100
@@ -942,21 +942,48 @@
 
 #ifdef	CONFIG_USB_SUSPEND
 
+static int is_interface_busy(struct usb_interface *intf)
+{
+	struct usb_driver *drv = to_usb_driver(intf->dev.driver);
+
+	if (!drv)
+		return 0;
+	if (!drv->check_busy)
+		return 0;
+
+	return (drv->check_busy)(intf);
+}
+
 /* 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 starting)
 {
 	int			i;
+	unsigned		delay;
 	struct usb_interface	*intf;
 
-	/* For autosuspend, fail fast if anything is in use.
-	 * Also fail if any interfaces require remote wakeup but it
-	 * isn't available. */
+	/* For autosuspend, fail fast if anything is in use or autosuspend
+	 * is disabled.  Also fail if any interfaces require remote wakeup
+	 * but it isn't available.
+	 */
 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 	if (udev->pm_usage_cnt > 0)
 		return -EBUSY;
+	if (!udev->autosuspend_delay)
+		return -EPERM;
+
+	/* starting is non-zero when the autosuspend timer is first started,
+	 * in which case we should return the maximum delay needed.
+	 * It is zero when the timer expires, in which case we should return
+	 * 0 if it is okay to autosuspend now, otherwise the next timer
+	 * delay value.
+	 */
+	delay = (starting ? udev->autosuspend_delay : 0);
+
 	if (udev->actconfig) {
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
+			if (!intf->autosuspend_delay)
+				return -EPERM;
 			if (!is_active(intf))
 				continue;
 			if (intf->pm_usage_cnt > 0)
@@ -967,6 +994,29 @@
 						"for autosuspend\n");
 				return -EOPNOTSUPP;
 			}
+			if (starting || is_interface_busy(intf))
+				delay = max(delay, intf->autosuspend_delay);
+		}
+	}
+	return delay;
+}
+
+/* Internal routine to check whether we need to autoresume a device. */
+static int autosuspend_recheck(struct usb_device *udev)
+{
+	int			i;
+	struct usb_interface	*intf;
+
+	/* There's a race between the test of the USB_IF_DEVICE_BUSY flag
+	 * above and the completion of an URB (when a driver would set the
+	 * flag).  If the flag gets set after the decision to start an
+	 * autosuspend has been made, we need to go back and autoresume
+	 * the device. */
+	if (udev->actconfig) {
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			intf = udev->actconfig->interface[i];
+			if (is_interface_busy(intf))
+				return 1;
 		}
 	}
 	return 0;
--- linux-2.6.20/include/linux/usb.h	2007-02-06 14:14:57.000000000 +0100
+++ linux-stern/include/linux/usb.h	2007-02-15 13:41:21.000000000 +0100
@@ -804,6 +812,8 @@
 	void (*pre_reset) (struct usb_interface *intf);
 	void (*post_reset) (struct usb_interface *intf);
 
+	int (*check_busy) (struct usb_interface *intf);
+
 	const struct usb_device_id *id_table;
 
 	struct usb_dynids dynids;

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[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.