aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/sysfs.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-05-30 15:39:33 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-12 19:34:30 -0400
commitb41a60eca833d76593d4dac8a59f5c38714194ee (patch)
treea7c5cf721d9978503c3c8c88183747cf954b8733 /drivers/usb/core/sysfs.c
parent54515fe528d8c6f9bfaf7d0b9fffb908deecad78 (diff)
USB: add power/persist device attribute
This patch (as920) adds an extra level of protection to the USB-Persist facility. Now it will apply by default only to hubs; for all other devices the user must enable it explicitly by setting the power/persist device attribute. The disconnect_all_children() routine in hub.c has been removed and its code placed inline. This is the way it was originally as part of hub_pre_reset(); the revised usage in hub_reset_resume() is sufficiently different that the code can no longer be shared. Likewise, mark_children_for_reset() is now inline as part of hub_reset_resume(). The end result looks much cleaner than before. The sysfs interface is updated to add the new attribute file, and there are corresponding documentation updates. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/sysfs.c')
-rw-r--r--drivers/usb/core/sysfs.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index be37c863fdfb..5dfe31bc32ba 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -169,6 +169,73 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
169} 169}
170static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); 170static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
171 171
172
173#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
174static const char power_group[] = "power";
175#endif
176
177#ifdef CONFIG_USB_PERSIST
178
179static ssize_t
180show_persist(struct device *dev, struct device_attribute *attr, char *buf)
181{
182 struct usb_device *udev = to_usb_device(dev);
183
184 return sprintf(buf, "%d\n", udev->persist_enabled);
185}
186
187static ssize_t
188set_persist(struct device *dev, struct device_attribute *attr,
189 const char *buf, size_t count)
190{
191 struct usb_device *udev = to_usb_device(dev);
192 int value;
193
194 /* Hubs are always enabled for USB_PERSIST */
195 if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
196 return -EPERM;
197
198 if (sscanf(buf, "%d", &value) != 1)
199 return -EINVAL;
200 usb_pm_lock(udev);
201 udev->persist_enabled = !!value;
202 usb_pm_unlock(udev);
203 return count;
204}
205
206static DEVICE_ATTR(persist, S_IRUGO | S_IWUSR, show_persist, set_persist);
207
208static int add_persist_attributes(struct device *dev)
209{
210 int rc = 0;
211
212 if (is_usb_device(dev)) {
213 struct usb_device *udev = to_usb_device(dev);
214
215 /* Hubs are automatically enabled for USB_PERSIST */
216 if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
217 udev->persist_enabled = 1;
218 rc = sysfs_add_file_to_group(&dev->kobj,
219 &dev_attr_persist.attr,
220 power_group);
221 }
222 return rc;
223}
224
225static void remove_persist_attributes(struct device *dev)
226{
227 sysfs_remove_file_from_group(&dev->kobj,
228 &dev_attr_persist.attr,
229 power_group);
230}
231
232#else
233
234#define add_persist_attributes(dev) 0
235#define remove_persist_attributes(dev) do {} while (0)
236
237#endif /* CONFIG_USB_PERSIST */
238
172#ifdef CONFIG_USB_SUSPEND 239#ifdef CONFIG_USB_SUSPEND
173 240
174static ssize_t 241static ssize_t
@@ -276,8 +343,6 @@ set_level(struct device *dev, struct device_attribute *attr,
276 343
277static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level); 344static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
278 345
279static char power_group[] = "power";
280
281static int add_power_attributes(struct device *dev) 346static int add_power_attributes(struct device *dev)
282{ 347{
283 int rc = 0; 348 int rc = 0;
@@ -311,6 +376,7 @@ static void remove_power_attributes(struct device *dev)
311 376
312#endif /* CONFIG_USB_SUSPEND */ 377#endif /* CONFIG_USB_SUSPEND */
313 378
379
314/* Descriptor fields */ 380/* Descriptor fields */
315#define usb_descriptor_attr_le16(field, format_string) \ 381#define usb_descriptor_attr_le16(field, format_string) \
316static ssize_t \ 382static ssize_t \
@@ -384,6 +450,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
384 if (retval) 450 if (retval)
385 return retval; 451 return retval;
386 452
453 retval = add_persist_attributes(dev);
454 if (retval)
455 goto error;
456
387 retval = add_power_attributes(dev); 457 retval = add_power_attributes(dev);
388 if (retval) 458 if (retval)
389 goto error; 459 goto error;
@@ -421,6 +491,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
421 device_remove_file(dev, &dev_attr_product); 491 device_remove_file(dev, &dev_attr_product);
422 device_remove_file(dev, &dev_attr_serial); 492 device_remove_file(dev, &dev_attr_serial);
423 remove_power_attributes(dev); 493 remove_power_attributes(dev);
494 remove_persist_attributes(dev);
424 sysfs_remove_group(&dev->kobj, &dev_attr_grp); 495 sysfs_remove_group(&dev->kobj, &dev_attr_grp);
425} 496}
426 497