diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-08-30 15:47:02 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 11:58:57 -0700 |
commit | 645daaab0b6adc35c1838df2a82f9d729fdb1767 (patch) | |
tree | 908d58f6c0ad01e9c1622a4c12c9c8080c629baa /include/linux/usb.h | |
parent | b6956ffa595db97656d5901ca8fec77ef272d41a (diff) | |
download | lwn-645daaab0b6adc35c1838df2a82f9d729fdb1767.tar.gz lwn-645daaab0b6adc35c1838df2a82f9d729fdb1767.zip |
usbcore: add autosuspend/autoresume infrastructure
This patch (as739) adds the basic infrastructure for USB autosuspend
and autoresume. The main features are:
PM usage counters added to struct usb_device and struct
usb_interface, indicating whether it's okay to autosuspend
them or they are currently in use.
Flag added to usb_device indicating whether the current
suspend/resume operation originated from outside or as an
autosuspend/autoresume.
Flag added to usb_driver indicating whether the driver
supports autosuspend. If not, no device bound to the driver
will be autosuspended.
Mutex added to usb_device for protecting PM operations.
Unlike the device semaphore, the locking rule for the pm_mutex
is that you must acquire the locks going _up_ the device tree.
New routines handling autosuspend/autoresume requests for
interfaces and devices.
Suspend and resume requests are propagated up the device tree
(but not outside the USB subsystem).
work_struct added to usb_device, for carrying out delayed
autosuspend requests.
Autoresume added (and autosuspend prevented) during probe and
disconnect.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'include/linux/usb.h')
-rw-r--r-- | include/linux/usb.h | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/include/linux/usb.h b/include/linux/usb.h index df5c93eb3ce9..0da15b0b02be 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -19,6 +19,7 @@ #include <linux/fs.h> /* for struct file_operations */ #include <linux/completion.h> /* for struct completion */ #include <linux/sched.h> /* for current && schedule_timeout */ +#include <linux/mutex.h> /* for struct mutex */ struct usb_device; struct usb_driver; @@ -103,8 +104,12 @@ enum usb_interface_condition { * @condition: binding state of the interface: not bound, binding * (in probe()), bound to a driver, or unbinding (in disconnect()) * @is_active: flag set when the interface is bound and not suspended. + * @needs_remote_wakeup: flag set when the driver requires remote-wakeup + * capability during autosuspend. * @dev: driver model's view of this device * @class_dev: driver model's class view of this device. + * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not + * allowed unless the counter is 0. * * USB device drivers attach to interfaces on a physical device. Each * interface encapsulates a single high level function, such as feeding @@ -144,9 +149,11 @@ struct usb_interface { * bound to */ enum usb_interface_condition condition; /* state of binding */ unsigned is_active:1; /* the interface is not suspended */ + unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ struct device dev; /* interface specific device info */ struct class_device *class_dev; + int pm_usage_cnt; /* usage counter for autosuspend */ }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) #define interface_to_usbdev(intf) \ @@ -372,6 +379,15 @@ struct usb_device { int maxchild; /* Number of ports if hub */ struct usb_device *children[USB_MAXCHILDREN]; + +#ifdef CONFIG_PM + struct work_struct autosuspend; /* for delayed autosuspends */ + struct mutex pm_mutex; /* protects PM operations */ + int pm_usage_cnt; /* usage counter for autosuspend */ + + unsigned auto_pm:1; /* autosuspend/resume in progress */ + unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ +#endif }; #define to_usb_device(d) container_of(d, struct usb_device, dev) @@ -392,6 +408,17 @@ extern int usb_reset_composite_device(struct usb_device *dev, extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); +/* USB autosuspend and autoresume */ +#ifdef CONFIG_USB_SUSPEND +extern int usb_autopm_get_interface(struct usb_interface *intf); +extern void usb_autopm_put_interface(struct usb_interface *intf); + +#else +#define usb_autopm_get_interface(intf) 0 +#define usb_autopm_put_interface(intf) do {} while (0) +#endif + + /*-------------------------------------------------------------------------*/ /* for drivers using iso endpoints */ @@ -593,6 +620,8 @@ struct usbdrv_wrap { * @drvwrap: Driver-model core structure wrapper. * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be * added to this driver by preventing the sysfs file from being created. + * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend + * for interfaces bound to this driver. * * USB interface drivers must provide a name, probe() and disconnect() * methods, and an id_table. Other driver fields are optional. @@ -631,6 +660,7 @@ struct usb_driver { struct usb_dynids dynids; struct usbdrv_wrap drvwrap; unsigned int no_dynamic_id:1; + unsigned int supports_autosuspend:1; }; #define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver) @@ -648,6 +678,8 @@ struct usb_driver { * @suspend: Called when the device is going to be suspended by the system. * @resume: Called when the device is being resumed by the system. * @drvwrap: Driver-model core structure wrapper. + * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend + * for devices bound to this driver. * * USB drivers must provide all the fields listed above except drvwrap. */ @@ -660,6 +692,7 @@ struct usb_device_driver { int (*suspend) (struct usb_device *udev, pm_message_t message); int (*resume) (struct usb_device *udev); struct usbdrv_wrap drvwrap; + unsigned int supports_autosuspend:1; }; #define to_usb_device_driver(d) container_of(d, struct usb_device_driver, \ drvwrap.driver) |