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 14:58:57 -0400 |
commit | 645daaab0b6adc35c1838df2a82f9d729fdb1767 (patch) | |
tree | 908d58f6c0ad01e9c1622a4c12c9c8080c629baa /include/linux/usb.h | |
parent | b6956ffa595db97656d5901ca8fec77ef272d41a (diff) |
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 @@ | |||
19 | #include <linux/fs.h> /* for struct file_operations */ | 19 | #include <linux/fs.h> /* for struct file_operations */ |
20 | #include <linux/completion.h> /* for struct completion */ | 20 | #include <linux/completion.h> /* for struct completion */ |
21 | #include <linux/sched.h> /* for current && schedule_timeout */ | 21 | #include <linux/sched.h> /* for current && schedule_timeout */ |
22 | #include <linux/mutex.h> /* for struct mutex */ | ||
22 | 23 | ||
23 | struct usb_device; | 24 | struct usb_device; |
24 | struct usb_driver; | 25 | struct usb_driver; |
@@ -103,8 +104,12 @@ enum usb_interface_condition { | |||
103 | * @condition: binding state of the interface: not bound, binding | 104 | * @condition: binding state of the interface: not bound, binding |
104 | * (in probe()), bound to a driver, or unbinding (in disconnect()) | 105 | * (in probe()), bound to a driver, or unbinding (in disconnect()) |
105 | * @is_active: flag set when the interface is bound and not suspended. | 106 | * @is_active: flag set when the interface is bound and not suspended. |
107 | * @needs_remote_wakeup: flag set when the driver requires remote-wakeup | ||
108 | * capability during autosuspend. | ||
106 | * @dev: driver model's view of this device | 109 | * @dev: driver model's view of this device |
107 | * @class_dev: driver model's class view of this device. | 110 | * @class_dev: driver model's class view of this device. |
111 | * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not | ||
112 | * allowed unless the counter is 0. | ||
108 | * | 113 | * |
109 | * USB device drivers attach to interfaces on a physical device. Each | 114 | * USB device drivers attach to interfaces on a physical device. Each |
110 | * interface encapsulates a single high level function, such as feeding | 115 | * interface encapsulates a single high level function, such as feeding |
@@ -144,9 +149,11 @@ struct usb_interface { | |||
144 | * bound to */ | 149 | * bound to */ |
145 | enum usb_interface_condition condition; /* state of binding */ | 150 | enum usb_interface_condition condition; /* state of binding */ |
146 | unsigned is_active:1; /* the interface is not suspended */ | 151 | unsigned is_active:1; /* the interface is not suspended */ |
152 | unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ | ||
147 | 153 | ||
148 | struct device dev; /* interface specific device info */ | 154 | struct device dev; /* interface specific device info */ |
149 | struct class_device *class_dev; | 155 | struct class_device *class_dev; |
156 | int pm_usage_cnt; /* usage counter for autosuspend */ | ||
150 | }; | 157 | }; |
151 | #define to_usb_interface(d) container_of(d, struct usb_interface, dev) | 158 | #define to_usb_interface(d) container_of(d, struct usb_interface, dev) |
152 | #define interface_to_usbdev(intf) \ | 159 | #define interface_to_usbdev(intf) \ |
@@ -372,6 +379,15 @@ struct usb_device { | |||
372 | 379 | ||
373 | int maxchild; /* Number of ports if hub */ | 380 | int maxchild; /* Number of ports if hub */ |
374 | struct usb_device *children[USB_MAXCHILDREN]; | 381 | struct usb_device *children[USB_MAXCHILDREN]; |
382 | |||
383 | #ifdef CONFIG_PM | ||
384 | struct work_struct autosuspend; /* for delayed autosuspends */ | ||
385 | struct mutex pm_mutex; /* protects PM operations */ | ||
386 | int pm_usage_cnt; /* usage counter for autosuspend */ | ||
387 | |||
388 | unsigned auto_pm:1; /* autosuspend/resume in progress */ | ||
389 | unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ | ||
390 | #endif | ||
375 | }; | 391 | }; |
376 | #define to_usb_device(d) container_of(d, struct usb_device, dev) | 392 | #define to_usb_device(d) container_of(d, struct usb_device, dev) |
377 | 393 | ||
@@ -392,6 +408,17 @@ extern int usb_reset_composite_device(struct usb_device *dev, | |||
392 | 408 | ||
393 | extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); | 409 | extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); |
394 | 410 | ||
411 | /* USB autosuspend and autoresume */ | ||
412 | #ifdef CONFIG_USB_SUSPEND | ||
413 | extern int usb_autopm_get_interface(struct usb_interface *intf); | ||
414 | extern void usb_autopm_put_interface(struct usb_interface *intf); | ||
415 | |||
416 | #else | ||
417 | #define usb_autopm_get_interface(intf) 0 | ||
418 | #define usb_autopm_put_interface(intf) do {} while (0) | ||
419 | #endif | ||
420 | |||
421 | |||
395 | /*-------------------------------------------------------------------------*/ | 422 | /*-------------------------------------------------------------------------*/ |
396 | 423 | ||
397 | /* for drivers using iso endpoints */ | 424 | /* for drivers using iso endpoints */ |
@@ -593,6 +620,8 @@ struct usbdrv_wrap { | |||
593 | * @drvwrap: Driver-model core structure wrapper. | 620 | * @drvwrap: Driver-model core structure wrapper. |
594 | * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be | 621 | * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be |
595 | * added to this driver by preventing the sysfs file from being created. | 622 | * added to this driver by preventing the sysfs file from being created. |
623 | * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend | ||
624 | * for interfaces bound to this driver. | ||
596 | * | 625 | * |
597 | * USB interface drivers must provide a name, probe() and disconnect() | 626 | * USB interface drivers must provide a name, probe() and disconnect() |
598 | * methods, and an id_table. Other driver fields are optional. | 627 | * methods, and an id_table. Other driver fields are optional. |
@@ -631,6 +660,7 @@ struct usb_driver { | |||
631 | struct usb_dynids dynids; | 660 | struct usb_dynids dynids; |
632 | struct usbdrv_wrap drvwrap; | 661 | struct usbdrv_wrap drvwrap; |
633 | unsigned int no_dynamic_id:1; | 662 | unsigned int no_dynamic_id:1; |
663 | unsigned int supports_autosuspend:1; | ||
634 | }; | 664 | }; |
635 | #define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver) | 665 | #define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver) |
636 | 666 | ||
@@ -648,6 +678,8 @@ struct usb_driver { | |||
648 | * @suspend: Called when the device is going to be suspended by the system. | 678 | * @suspend: Called when the device is going to be suspended by the system. |
649 | * @resume: Called when the device is being resumed by the system. | 679 | * @resume: Called when the device is being resumed by the system. |
650 | * @drvwrap: Driver-model core structure wrapper. | 680 | * @drvwrap: Driver-model core structure wrapper. |
681 | * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend | ||
682 | * for devices bound to this driver. | ||
651 | * | 683 | * |
652 | * USB drivers must provide all the fields listed above except drvwrap. | 684 | * USB drivers must provide all the fields listed above except drvwrap. |
653 | */ | 685 | */ |
@@ -660,6 +692,7 @@ struct usb_device_driver { | |||
660 | int (*suspend) (struct usb_device *udev, pm_message_t message); | 692 | int (*suspend) (struct usb_device *udev, pm_message_t message); |
661 | int (*resume) (struct usb_device *udev); | 693 | int (*resume) (struct usb_device *udev); |
662 | struct usbdrv_wrap drvwrap; | 694 | struct usbdrv_wrap drvwrap; |
695 | unsigned int supports_autosuspend:1; | ||
663 | }; | 696 | }; |
664 | #define to_usb_device_driver(d) container_of(d, struct usb_device_driver, \ | 697 | #define to_usb_device_driver(d) container_of(d, struct usb_device_driver, \ |
665 | drvwrap.driver) | 698 | drvwrap.driver) |