diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-02-20 15:03:32 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-23 18:03:47 -0500 |
commit | 19c262391c4741b012a5031fc438fb694e77c385 (patch) | |
tree | 1ce81bf30086104f8102b83617d31d998338fbd6 /drivers/usb | |
parent | dfa87c824a9a5430008acd1ed2e8111ed164fcbe (diff) |
USB: export autosuspend delay in sysfs
This patch (as861) adds sysfs attributes to expose the autosuspend
delay value for each USB device. If the user changes the delay from 0
(no autosuspend) to a positive value, an autosuspend is attempted.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/driver.c | 20 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 64 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 4 |
3 files changed, 87 insertions, 1 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index a420d72a0254..9e3e943f313c 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1225,6 +1225,26 @@ void usb_autosuspend_device(struct usb_device *udev) | |||
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | /** | 1227 | /** |
1228 | * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces | ||
1229 | * @udev: the usb_device to autosuspend | ||
1230 | * | ||
1231 | * This routine should be called when a core subsystem thinks @udev may | ||
1232 | * be ready to autosuspend. | ||
1233 | * | ||
1234 | * @udev's usage counter left unchanged. If it or any of the usage counters | ||
1235 | * for an active interface is greater than 0, or autosuspend is not allowed | ||
1236 | * for any other reason, no autosuspend request will be queued. | ||
1237 | * | ||
1238 | * This routine can run only in process context. | ||
1239 | */ | ||
1240 | void usb_try_autosuspend_device(struct usb_device *udev) | ||
1241 | { | ||
1242 | usb_autopm_do_device(udev, 0); | ||
1243 | // dev_dbg(&udev->dev, "%s: cnt %d\n", | ||
1244 | // __FUNCTION__, udev->pm_usage_cnt); | ||
1245 | } | ||
1246 | |||
1247 | /** | ||
1228 | * usb_autoresume_device - immediately autoresume a USB device and its interfaces | 1248 | * usb_autoresume_device - immediately autoresume a USB device and its interfaces |
1229 | * @udev: the usb_device to autoresume | 1249 | * @udev: the usb_device to autoresume |
1230 | * | 1250 | * |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index cad4fb323f6c..311d5df80386 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -158,6 +158,65 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf) | |||
158 | } | 158 | } |
159 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); | 159 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); |
160 | 160 | ||
161 | #ifdef CONFIG_USB_SUSPEND | ||
162 | |||
163 | static ssize_t | ||
164 | show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf) | ||
165 | { | ||
166 | struct usb_device *udev = to_usb_device(dev); | ||
167 | |||
168 | return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ); | ||
169 | } | ||
170 | |||
171 | static ssize_t | ||
172 | set_autosuspend(struct device *dev, struct device_attribute *attr, | ||
173 | const char *buf, size_t count) | ||
174 | { | ||
175 | struct usb_device *udev = to_usb_device(dev); | ||
176 | unsigned value, old; | ||
177 | |||
178 | if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ) | ||
179 | return -EINVAL; | ||
180 | value *= HZ; | ||
181 | |||
182 | old = udev->autosuspend_delay; | ||
183 | udev->autosuspend_delay = value; | ||
184 | if (value > 0 && old == 0) | ||
185 | usb_try_autosuspend_device(udev); | ||
186 | |||
187 | return count; | ||
188 | } | ||
189 | |||
190 | static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR, | ||
191 | show_autosuspend, set_autosuspend); | ||
192 | |||
193 | static char power_group[] = "power"; | ||
194 | |||
195 | static int add_power_attributes(struct device *dev) | ||
196 | { | ||
197 | int rc = 0; | ||
198 | |||
199 | if (is_usb_device(dev)) | ||
200 | rc = sysfs_add_file_to_group(&dev->kobj, | ||
201 | &dev_attr_autosuspend.attr, | ||
202 | power_group); | ||
203 | return rc; | ||
204 | } | ||
205 | |||
206 | static void remove_power_attributes(struct device *dev) | ||
207 | { | ||
208 | sysfs_remove_file_from_group(&dev->kobj, | ||
209 | &dev_attr_autosuspend.attr, | ||
210 | power_group); | ||
211 | } | ||
212 | |||
213 | #else | ||
214 | |||
215 | #define add_power_attributes(dev) 0 | ||
216 | #define remove_power_attributes(dev) do {} while (0) | ||
217 | |||
218 | #endif /* CONFIG_USB_SUSPEND */ | ||
219 | |||
161 | /* Descriptor fields */ | 220 | /* Descriptor fields */ |
162 | #define usb_descriptor_attr_le16(field, format_string) \ | 221 | #define usb_descriptor_attr_le16(field, format_string) \ |
163 | static ssize_t \ | 222 | static ssize_t \ |
@@ -230,6 +289,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) | |||
230 | if (retval) | 289 | if (retval) |
231 | return retval; | 290 | return retval; |
232 | 291 | ||
292 | retval = add_power_attributes(dev); | ||
293 | if (retval) | ||
294 | goto error; | ||
295 | |||
233 | if (udev->manufacturer) { | 296 | if (udev->manufacturer) { |
234 | retval = device_create_file(dev, &dev_attr_manufacturer); | 297 | retval = device_create_file(dev, &dev_attr_manufacturer); |
235 | if (retval) | 298 | if (retval) |
@@ -262,6 +325,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) | |||
262 | device_remove_file(dev, &dev_attr_manufacturer); | 325 | device_remove_file(dev, &dev_attr_manufacturer); |
263 | device_remove_file(dev, &dev_attr_product); | 326 | device_remove_file(dev, &dev_attr_product); |
264 | device_remove_file(dev, &dev_attr_serial); | 327 | device_remove_file(dev, &dev_attr_serial); |
328 | remove_power_attributes(dev); | ||
265 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); | 329 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); |
266 | } | 330 | } |
267 | 331 | ||
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index b0a35f45b099..08b5a04e3755 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -66,11 +66,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {} | |||
66 | #ifdef CONFIG_USB_SUSPEND | 66 | #ifdef CONFIG_USB_SUSPEND |
67 | 67 | ||
68 | extern void usb_autosuspend_device(struct usb_device *udev); | 68 | extern void usb_autosuspend_device(struct usb_device *udev); |
69 | extern void usb_try_autosuspend_device(struct usb_device *udev); | ||
69 | extern int usb_autoresume_device(struct usb_device *udev); | 70 | extern int usb_autoresume_device(struct usb_device *udev); |
70 | 71 | ||
71 | #else | 72 | #else |
72 | 73 | ||
73 | #define usb_autosuspend_device(udev) do {} while (0) | 74 | #define usb_autosuspend_device(udev) do {} while (0) |
75 | #define usb_try_autosuspend_device(udev) do {} while (0) | ||
74 | static inline int usb_autoresume_device(struct usb_device *udev) | 76 | static inline int usb_autoresume_device(struct usb_device *udev) |
75 | { | 77 | { |
76 | return 0; | 78 | return 0; |