diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/usb/core/sysfs.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/usb/core/sysfs.c')
-rw-r--r-- | drivers/usb/core/sysfs.c | 156 |
1 files changed, 110 insertions, 46 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 7ec3041ae79e..43c002e3a9aa 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -82,9 +82,13 @@ static ssize_t show_##name(struct device *dev, \ | |||
82 | struct device_attribute *attr, char *buf) \ | 82 | struct device_attribute *attr, char *buf) \ |
83 | { \ | 83 | { \ |
84 | struct usb_device *udev; \ | 84 | struct usb_device *udev; \ |
85 | int retval; \ | ||
85 | \ | 86 | \ |
86 | udev = to_usb_device(dev); \ | 87 | udev = to_usb_device(dev); \ |
87 | return sprintf(buf, "%s\n", udev->name); \ | 88 | usb_lock_device(udev); \ |
89 | retval = sprintf(buf, "%s\n", udev->name); \ | ||
90 | usb_unlock_device(udev); \ | ||
91 | return retval; \ | ||
88 | } \ | 92 | } \ |
89 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); | 93 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); |
90 | 94 | ||
@@ -111,6 +115,12 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf) | |||
111 | case USB_SPEED_HIGH: | 115 | case USB_SPEED_HIGH: |
112 | speed = "480"; | 116 | speed = "480"; |
113 | break; | 117 | break; |
118 | case USB_SPEED_WIRELESS: | ||
119 | speed = "480"; | ||
120 | break; | ||
121 | case USB_SPEED_SUPER: | ||
122 | speed = "5000"; | ||
123 | break; | ||
114 | default: | 124 | default: |
115 | speed = "unknown"; | 125 | speed = "unknown"; |
116 | } | 126 | } |
@@ -139,6 +149,16 @@ show_devnum(struct device *dev, struct device_attribute *attr, char *buf) | |||
139 | static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL); | 149 | static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL); |
140 | 150 | ||
141 | static ssize_t | 151 | static ssize_t |
152 | show_devpath(struct device *dev, struct device_attribute *attr, char *buf) | ||
153 | { | ||
154 | struct usb_device *udev; | ||
155 | |||
156 | udev = to_usb_device(dev); | ||
157 | return sprintf(buf, "%s\n", udev->devpath); | ||
158 | } | ||
159 | static DEVICE_ATTR(devpath, S_IRUGO, show_devpath, NULL); | ||
160 | |||
161 | static ssize_t | ||
142 | show_version(struct device *dev, struct device_attribute *attr, char *buf) | 162 | show_version(struct device *dev, struct device_attribute *attr, char *buf) |
143 | { | 163 | { |
144 | struct usb_device *udev; | 164 | struct usb_device *udev; |
@@ -171,6 +191,36 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf) | |||
171 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); | 191 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); |
172 | 192 | ||
173 | static ssize_t | 193 | static ssize_t |
194 | show_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, char *buf) | ||
195 | { | ||
196 | struct usb_device *udev; | ||
197 | |||
198 | udev = to_usb_device(dev); | ||
199 | return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET_MORPHS)); | ||
200 | } | ||
201 | |||
202 | static ssize_t | ||
203 | set_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, | ||
204 | const char *buf, size_t count) | ||
205 | { | ||
206 | struct usb_device *udev = to_usb_device(dev); | ||
207 | int config; | ||
208 | |||
209 | if (sscanf(buf, "%d", &config) != 1 || config < 0 || config > 1) | ||
210 | return -EINVAL; | ||
211 | usb_lock_device(udev); | ||
212 | if (config) | ||
213 | udev->quirks |= USB_QUIRK_RESET_MORPHS; | ||
214 | else | ||
215 | udev->quirks &= ~USB_QUIRK_RESET_MORPHS; | ||
216 | usb_unlock_device(udev); | ||
217 | return count; | ||
218 | } | ||
219 | |||
220 | static DEVICE_ATTR(avoid_reset_quirk, S_IRUGO | S_IWUSR, | ||
221 | show_avoid_reset_quirk, set_avoid_reset_quirk); | ||
222 | |||
223 | static ssize_t | ||
174 | show_urbnum(struct device *dev, struct device_attribute *attr, char *buf) | 224 | show_urbnum(struct device *dev, struct device_attribute *attr, char *buf) |
175 | { | 225 | { |
176 | struct usb_device *udev; | 226 | struct usb_device *udev; |
@@ -206,9 +256,10 @@ set_persist(struct device *dev, struct device_attribute *attr, | |||
206 | 256 | ||
207 | if (sscanf(buf, "%d", &value) != 1) | 257 | if (sscanf(buf, "%d", &value) != 1) |
208 | return -EINVAL; | 258 | return -EINVAL; |
209 | usb_pm_lock(udev); | 259 | |
260 | usb_lock_device(udev); | ||
210 | udev->persist_enabled = !!value; | 261 | udev->persist_enabled = !!value; |
211 | usb_pm_unlock(udev); | 262 | usb_unlock_device(udev); |
212 | return count; | 263 | return count; |
213 | } | 264 | } |
214 | 265 | ||
@@ -295,20 +346,34 @@ set_autosuspend(struct device *dev, struct device_attribute *attr, | |||
295 | const char *buf, size_t count) | 346 | const char *buf, size_t count) |
296 | { | 347 | { |
297 | struct usb_device *udev = to_usb_device(dev); | 348 | struct usb_device *udev = to_usb_device(dev); |
298 | int value; | 349 | int value, old_delay; |
350 | int rc; | ||
299 | 351 | ||
300 | if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ || | 352 | if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ || |
301 | value <= - INT_MAX/HZ) | 353 | value <= - INT_MAX/HZ) |
302 | return -EINVAL; | 354 | return -EINVAL; |
303 | value *= HZ; | 355 | value *= HZ; |
304 | 356 | ||
357 | usb_lock_device(udev); | ||
358 | old_delay = udev->autosuspend_delay; | ||
305 | udev->autosuspend_delay = value; | 359 | udev->autosuspend_delay = value; |
306 | if (value >= 0) | 360 | |
307 | usb_try_autosuspend_device(udev); | 361 | if (old_delay < 0) { /* Autosuspend wasn't allowed */ |
308 | else { | 362 | if (value >= 0) |
309 | if (usb_autoresume_device(udev) == 0) | ||
310 | usb_autosuspend_device(udev); | 363 | usb_autosuspend_device(udev); |
364 | } else { /* Autosuspend was allowed */ | ||
365 | if (value < 0) { | ||
366 | rc = usb_autoresume_device(udev); | ||
367 | if (rc < 0) { | ||
368 | count = rc; | ||
369 | udev->autosuspend_delay = old_delay; | ||
370 | } | ||
371 | } else { | ||
372 | usb_try_autosuspend_device(udev); | ||
373 | } | ||
311 | } | 374 | } |
375 | |||
376 | usb_unlock_device(udev); | ||
312 | return count; | 377 | return count; |
313 | } | 378 | } |
314 | 379 | ||
@@ -317,7 +382,6 @@ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR, | |||
317 | 382 | ||
318 | static const char on_string[] = "on"; | 383 | static const char on_string[] = "on"; |
319 | static const char auto_string[] = "auto"; | 384 | static const char auto_string[] = "auto"; |
320 | static const char suspend_string[] = "suspend"; | ||
321 | 385 | ||
322 | static ssize_t | 386 | static ssize_t |
323 | show_level(struct device *dev, struct device_attribute *attr, char *buf) | 387 | show_level(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -325,13 +389,8 @@ show_level(struct device *dev, struct device_attribute *attr, char *buf) | |||
325 | struct usb_device *udev = to_usb_device(dev); | 389 | struct usb_device *udev = to_usb_device(dev); |
326 | const char *p = auto_string; | 390 | const char *p = auto_string; |
327 | 391 | ||
328 | if (udev->state == USB_STATE_SUSPENDED) { | 392 | if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled) |
329 | if (udev->autoresume_disabled) | 393 | p = on_string; |
330 | p = suspend_string; | ||
331 | } else { | ||
332 | if (udev->autosuspend_disabled) | ||
333 | p = on_string; | ||
334 | } | ||
335 | return sprintf(buf, "%s\n", p); | 394 | return sprintf(buf, "%s\n", p); |
336 | } | 395 | } |
337 | 396 | ||
@@ -342,45 +401,25 @@ set_level(struct device *dev, struct device_attribute *attr, | |||
342 | struct usb_device *udev = to_usb_device(dev); | 401 | struct usb_device *udev = to_usb_device(dev); |
343 | int len = count; | 402 | int len = count; |
344 | char *cp; | 403 | char *cp; |
345 | int rc = 0; | 404 | int rc; |
346 | int old_autosuspend_disabled, old_autoresume_disabled; | ||
347 | 405 | ||
348 | cp = memchr(buf, '\n', count); | 406 | cp = memchr(buf, '\n', count); |
349 | if (cp) | 407 | if (cp) |
350 | len = cp - buf; | 408 | len = cp - buf; |
351 | 409 | ||
352 | usb_lock_device(udev); | 410 | usb_lock_device(udev); |
353 | old_autosuspend_disabled = udev->autosuspend_disabled; | ||
354 | old_autoresume_disabled = udev->autoresume_disabled; | ||
355 | 411 | ||
356 | /* Setting the flags without calling usb_pm_lock is a subject to | ||
357 | * races, but who cares... | ||
358 | */ | ||
359 | if (len == sizeof on_string - 1 && | 412 | if (len == sizeof on_string - 1 && |
360 | strncmp(buf, on_string, len) == 0) { | 413 | strncmp(buf, on_string, len) == 0) |
361 | udev->autosuspend_disabled = 1; | 414 | rc = usb_disable_autosuspend(udev); |
362 | udev->autoresume_disabled = 0; | 415 | |
363 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); | 416 | else if (len == sizeof auto_string - 1 && |
364 | 417 | strncmp(buf, auto_string, len) == 0) | |
365 | } else if (len == sizeof auto_string - 1 && | 418 | rc = usb_enable_autosuspend(udev); |
366 | strncmp(buf, auto_string, len) == 0) { | 419 | |
367 | udev->autosuspend_disabled = 0; | 420 | else |
368 | udev->autoresume_disabled = 0; | ||
369 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); | ||
370 | |||
371 | } else if (len == sizeof suspend_string - 1 && | ||
372 | strncmp(buf, suspend_string, len) == 0) { | ||
373 | udev->autosuspend_disabled = 0; | ||
374 | udev->autoresume_disabled = 1; | ||
375 | rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND); | ||
376 | |||
377 | } else | ||
378 | rc = -EINVAL; | 421 | rc = -EINVAL; |
379 | 422 | ||
380 | if (rc) { | ||
381 | udev->autosuspend_disabled = old_autosuspend_disabled; | ||
382 | udev->autoresume_disabled = old_autoresume_disabled; | ||
383 | } | ||
384 | usb_unlock_device(udev); | 423 | usb_unlock_device(udev); |
385 | return (rc < 0 ? rc : count); | 424 | return (rc < 0 ? rc : count); |
386 | } | 425 | } |
@@ -508,6 +547,28 @@ static ssize_t usb_dev_authorized_store(struct device *dev, | |||
508 | static DEVICE_ATTR(authorized, 0644, | 547 | static DEVICE_ATTR(authorized, 0644, |
509 | usb_dev_authorized_show, usb_dev_authorized_store); | 548 | usb_dev_authorized_show, usb_dev_authorized_store); |
510 | 549 | ||
550 | /* "Safely remove a device" */ | ||
551 | static ssize_t usb_remove_store(struct device *dev, | ||
552 | struct device_attribute *attr, | ||
553 | const char *buf, size_t count) | ||
554 | { | ||
555 | struct usb_device *udev = to_usb_device(dev); | ||
556 | int rc = 0; | ||
557 | |||
558 | usb_lock_device(udev); | ||
559 | if (udev->state != USB_STATE_NOTATTACHED) { | ||
560 | |||
561 | /* To avoid races, first unconfigure and then remove */ | ||
562 | usb_set_configuration(udev, -1); | ||
563 | rc = usb_remove_device(udev); | ||
564 | } | ||
565 | if (rc == 0) | ||
566 | rc = count; | ||
567 | usb_unlock_device(udev); | ||
568 | return rc; | ||
569 | } | ||
570 | static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store); | ||
571 | |||
511 | 572 | ||
512 | static struct attribute *dev_attrs[] = { | 573 | static struct attribute *dev_attrs[] = { |
513 | /* current configuration's attributes */ | 574 | /* current configuration's attributes */ |
@@ -516,8 +577,8 @@ static struct attribute *dev_attrs[] = { | |||
516 | &dev_attr_bConfigurationValue.attr, | 577 | &dev_attr_bConfigurationValue.attr, |
517 | &dev_attr_bmAttributes.attr, | 578 | &dev_attr_bmAttributes.attr, |
518 | &dev_attr_bMaxPower.attr, | 579 | &dev_attr_bMaxPower.attr, |
519 | &dev_attr_urbnum.attr, | ||
520 | /* device attributes */ | 580 | /* device attributes */ |
581 | &dev_attr_urbnum.attr, | ||
521 | &dev_attr_idVendor.attr, | 582 | &dev_attr_idVendor.attr, |
522 | &dev_attr_idProduct.attr, | 583 | &dev_attr_idProduct.attr, |
523 | &dev_attr_bcdDevice.attr, | 584 | &dev_attr_bcdDevice.attr, |
@@ -529,10 +590,13 @@ static struct attribute *dev_attrs[] = { | |||
529 | &dev_attr_speed.attr, | 590 | &dev_attr_speed.attr, |
530 | &dev_attr_busnum.attr, | 591 | &dev_attr_busnum.attr, |
531 | &dev_attr_devnum.attr, | 592 | &dev_attr_devnum.attr, |
593 | &dev_attr_devpath.attr, | ||
532 | &dev_attr_version.attr, | 594 | &dev_attr_version.attr, |
533 | &dev_attr_maxchild.attr, | 595 | &dev_attr_maxchild.attr, |
534 | &dev_attr_quirks.attr, | 596 | &dev_attr_quirks.attr, |
597 | &dev_attr_avoid_reset_quirk.attr, | ||
535 | &dev_attr_authorized.attr, | 598 | &dev_attr_authorized.attr, |
599 | &dev_attr_remove.attr, | ||
536 | NULL, | 600 | NULL, |
537 | }; | 601 | }; |
538 | static struct attribute_group dev_attr_grp = { | 602 | static struct attribute_group dev_attr_grp = { |