diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-07-01 22:08:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 14:58:50 -0400 |
commit | 36e56a34586783c7986ce09d39db80b27c95ce24 (patch) | |
tree | 08637f4fbdd1fd46baba8a48645fcbe37b94cdf5 /drivers/usb | |
parent | 140d8f687457c40a66af362838fac0d7893e7df5 (diff) |
usbcore: move code among source files
This revised patch (as713b) moves a few routines among source files in
usbcore. Some driver-related code in usb.c (claiming interfaces and
matching IDs) is moved to driver.c, where it belongs. Also the
usb_generic stuff in driver.c is moved to a new source file: generic.c.
(That's the reason for revising the patch.) Although not very big now,
it will get bigger in a later patch.
None of the code has been changed; it has only been re-arranged.
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/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 348 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 53 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 307 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 2 |
5 files changed, 370 insertions, 342 deletions
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index ec510922af6..34e9bac319b 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ | 5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ |
6 | config.o file.o buffer.o sysfs.o endpoint.o \ | 6 | config.o file.o buffer.o sysfs.o endpoint.o \ |
7 | devio.o notify.o | 7 | devio.o notify.o generic.o |
8 | 8 | ||
9 | ifeq ($(CONFIG_PCI),y) | 9 | ifeq ($(CONFIG_PCI),y) |
10 | usbcore-objs += hcd-pci.o | 10 | usbcore-objs += hcd-pci.o |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ec890650141..8dcf2cd0c56 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -17,7 +17,8 @@ | |||
17 | * | 17 | * |
18 | * NOTE! This is not actually a driver at all, rather this is | 18 | * NOTE! This is not actually a driver at all, rather this is |
19 | * just a collection of helper routines that implement the | 19 | * just a collection of helper routines that implement the |
20 | * generic USB things that the real drivers can use.. | 20 | * matching, probing, releasing, suspending and resuming for |
21 | * real drivers. | ||
21 | * | 22 | * |
22 | */ | 23 | */ |
23 | 24 | ||
@@ -34,38 +35,6 @@ struct usb_dynid { | |||
34 | struct usb_device_id id; | 35 | struct usb_device_id id; |
35 | }; | 36 | }; |
36 | 37 | ||
37 | |||
38 | static int generic_probe(struct device *dev) | ||
39 | { | ||
40 | return 0; | ||
41 | } | ||
42 | static int generic_remove(struct device *dev) | ||
43 | { | ||
44 | struct usb_device *udev = to_usb_device(dev); | ||
45 | |||
46 | /* if this is only an unbind, not a physical disconnect, then | ||
47 | * unconfigure the device */ | ||
48 | if (udev->state == USB_STATE_CONFIGURED) | ||
49 | usb_set_configuration(udev, 0); | ||
50 | |||
51 | /* in case the call failed or the device was suspended */ | ||
52 | if (udev->state >= USB_STATE_CONFIGURED) | ||
53 | usb_disable_device(udev, 0); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | struct device_driver usb_generic_driver = { | ||
58 | .owner = THIS_MODULE, | ||
59 | .name = "usb", | ||
60 | .bus = &usb_bus_type, | ||
61 | .probe = generic_probe, | ||
62 | .remove = generic_remove, | ||
63 | }; | ||
64 | |||
65 | /* Fun hack to determine if the struct device is a | ||
66 | * usb device or a usb interface. */ | ||
67 | int usb_generic_driver_data; | ||
68 | |||
69 | #ifdef CONFIG_HOTPLUG | 38 | #ifdef CONFIG_HOTPLUG |
70 | 39 | ||
71 | /* | 40 | /* |
@@ -238,6 +207,89 @@ static int usb_unbind_interface(struct device *dev) | |||
238 | return 0; | 207 | return 0; |
239 | } | 208 | } |
240 | 209 | ||
210 | /** | ||
211 | * usb_driver_claim_interface - bind a driver to an interface | ||
212 | * @driver: the driver to be bound | ||
213 | * @iface: the interface to which it will be bound; must be in the | ||
214 | * usb device's active configuration | ||
215 | * @priv: driver data associated with that interface | ||
216 | * | ||
217 | * This is used by usb device drivers that need to claim more than one | ||
218 | * interface on a device when probing (audio and acm are current examples). | ||
219 | * No device driver should directly modify internal usb_interface or | ||
220 | * usb_device structure members. | ||
221 | * | ||
222 | * Few drivers should need to use this routine, since the most natural | ||
223 | * way to bind to an interface is to return the private data from | ||
224 | * the driver's probe() method. | ||
225 | * | ||
226 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | ||
227 | * writelock. So driver probe() entries don't need extra locking, | ||
228 | * but other call contexts may need to explicitly claim those locks. | ||
229 | */ | ||
230 | int usb_driver_claim_interface(struct usb_driver *driver, | ||
231 | struct usb_interface *iface, void* priv) | ||
232 | { | ||
233 | struct device *dev = &iface->dev; | ||
234 | |||
235 | if (dev->driver) | ||
236 | return -EBUSY; | ||
237 | |||
238 | dev->driver = &driver->driver; | ||
239 | usb_set_intfdata(iface, priv); | ||
240 | iface->condition = USB_INTERFACE_BOUND; | ||
241 | mark_active(iface); | ||
242 | |||
243 | /* if interface was already added, bind now; else let | ||
244 | * the future device_add() bind it, bypassing probe() | ||
245 | */ | ||
246 | if (device_is_registered(dev)) | ||
247 | device_bind_driver(dev); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | EXPORT_SYMBOL(usb_driver_claim_interface); | ||
252 | |||
253 | /** | ||
254 | * usb_driver_release_interface - unbind a driver from an interface | ||
255 | * @driver: the driver to be unbound | ||
256 | * @iface: the interface from which it will be unbound | ||
257 | * | ||
258 | * This can be used by drivers to release an interface without waiting | ||
259 | * for their disconnect() methods to be called. In typical cases this | ||
260 | * also causes the driver disconnect() method to be called. | ||
261 | * | ||
262 | * This call is synchronous, and may not be used in an interrupt context. | ||
263 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | ||
264 | * writelock. So driver disconnect() entries don't need extra locking, | ||
265 | * but other call contexts may need to explicitly claim those locks. | ||
266 | */ | ||
267 | void usb_driver_release_interface(struct usb_driver *driver, | ||
268 | struct usb_interface *iface) | ||
269 | { | ||
270 | struct device *dev = &iface->dev; | ||
271 | |||
272 | /* this should never happen, don't release something that's not ours */ | ||
273 | if (!dev->driver || dev->driver != &driver->driver) | ||
274 | return; | ||
275 | |||
276 | /* don't release from within disconnect() */ | ||
277 | if (iface->condition != USB_INTERFACE_BOUND) | ||
278 | return; | ||
279 | |||
280 | /* don't release if the interface hasn't been added yet */ | ||
281 | if (device_is_registered(dev)) { | ||
282 | iface->condition = USB_INTERFACE_UNBINDING; | ||
283 | device_release_driver(dev); | ||
284 | } | ||
285 | |||
286 | dev->driver = NULL; | ||
287 | usb_set_intfdata(iface, NULL); | ||
288 | iface->condition = USB_INTERFACE_UNBOUND; | ||
289 | mark_quiesced(iface); | ||
290 | } | ||
291 | EXPORT_SYMBOL(usb_driver_release_interface); | ||
292 | |||
241 | /* returns 0 if no match, 1 if match */ | 293 | /* returns 0 if no match, 1 if match */ |
242 | static int usb_match_one_id(struct usb_interface *interface, | 294 | static int usb_match_one_id(struct usb_interface *interface, |
243 | const struct usb_device_id *id) | 295 | const struct usb_device_id *id) |
@@ -402,6 +454,120 @@ int usb_device_match(struct device *dev, struct device_driver *drv) | |||
402 | return 0; | 454 | return 0; |
403 | } | 455 | } |
404 | 456 | ||
457 | #ifdef CONFIG_HOTPLUG | ||
458 | |||
459 | /* | ||
460 | * This sends an uevent to userspace, typically helping to load driver | ||
461 | * or other modules, configure the device, and more. Drivers can provide | ||
462 | * a MODULE_DEVICE_TABLE to help with module loading subtasks. | ||
463 | * | ||
464 | * We're called either from khubd (the typical case) or from root hub | ||
465 | * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle | ||
466 | * delays in event delivery. Use sysfs (and DEVPATH) to make sure the | ||
467 | * device (and this configuration!) are still present. | ||
468 | */ | ||
469 | static int usb_uevent(struct device *dev, char **envp, int num_envp, | ||
470 | char *buffer, int buffer_size) | ||
471 | { | ||
472 | struct usb_interface *intf; | ||
473 | struct usb_device *usb_dev; | ||
474 | struct usb_host_interface *alt; | ||
475 | int i = 0; | ||
476 | int length = 0; | ||
477 | |||
478 | if (!dev) | ||
479 | return -ENODEV; | ||
480 | |||
481 | /* driver is often null here; dev_dbg() would oops */ | ||
482 | pr_debug ("usb %s: uevent\n", dev->bus_id); | ||
483 | |||
484 | /* Must check driver_data here, as on remove driver is always NULL */ | ||
485 | if ((dev->driver == &usb_generic_driver) || | ||
486 | (dev->driver_data == &usb_generic_driver_data)) | ||
487 | return 0; | ||
488 | |||
489 | intf = to_usb_interface(dev); | ||
490 | usb_dev = interface_to_usbdev (intf); | ||
491 | alt = intf->cur_altsetting; | ||
492 | |||
493 | if (usb_dev->devnum < 0) { | ||
494 | pr_debug ("usb %s: already deleted?\n", dev->bus_id); | ||
495 | return -ENODEV; | ||
496 | } | ||
497 | if (!usb_dev->bus) { | ||
498 | pr_debug ("usb %s: bus removed?\n", dev->bus_id); | ||
499 | return -ENODEV; | ||
500 | } | ||
501 | |||
502 | #ifdef CONFIG_USB_DEVICEFS | ||
503 | /* If this is available, userspace programs can directly read | ||
504 | * all the device descriptors we don't tell them about. Or | ||
505 | * even act as usermode drivers. | ||
506 | * | ||
507 | * FIXME reduce hardwired intelligence here | ||
508 | */ | ||
509 | if (add_uevent_var(envp, num_envp, &i, | ||
510 | buffer, buffer_size, &length, | ||
511 | "DEVICE=/proc/bus/usb/%03d/%03d", | ||
512 | usb_dev->bus->busnum, usb_dev->devnum)) | ||
513 | return -ENOMEM; | ||
514 | #endif | ||
515 | |||
516 | /* per-device configurations are common */ | ||
517 | if (add_uevent_var(envp, num_envp, &i, | ||
518 | buffer, buffer_size, &length, | ||
519 | "PRODUCT=%x/%x/%x", | ||
520 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
521 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
522 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) | ||
523 | return -ENOMEM; | ||
524 | |||
525 | /* class-based driver binding models */ | ||
526 | if (add_uevent_var(envp, num_envp, &i, | ||
527 | buffer, buffer_size, &length, | ||
528 | "TYPE=%d/%d/%d", | ||
529 | usb_dev->descriptor.bDeviceClass, | ||
530 | usb_dev->descriptor.bDeviceSubClass, | ||
531 | usb_dev->descriptor.bDeviceProtocol)) | ||
532 | return -ENOMEM; | ||
533 | |||
534 | if (add_uevent_var(envp, num_envp, &i, | ||
535 | buffer, buffer_size, &length, | ||
536 | "INTERFACE=%d/%d/%d", | ||
537 | alt->desc.bInterfaceClass, | ||
538 | alt->desc.bInterfaceSubClass, | ||
539 | alt->desc.bInterfaceProtocol)) | ||
540 | return -ENOMEM; | ||
541 | |||
542 | if (add_uevent_var(envp, num_envp, &i, | ||
543 | buffer, buffer_size, &length, | ||
544 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", | ||
545 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
546 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
547 | le16_to_cpu(usb_dev->descriptor.bcdDevice), | ||
548 | usb_dev->descriptor.bDeviceClass, | ||
549 | usb_dev->descriptor.bDeviceSubClass, | ||
550 | usb_dev->descriptor.bDeviceProtocol, | ||
551 | alt->desc.bInterfaceClass, | ||
552 | alt->desc.bInterfaceSubClass, | ||
553 | alt->desc.bInterfaceProtocol)) | ||
554 | return -ENOMEM; | ||
555 | |||
556 | envp[i] = NULL; | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | #else | ||
562 | |||
563 | static int usb_uevent(struct device *dev, char **envp, | ||
564 | int num_envp, char *buffer, int buffer_size) | ||
565 | { | ||
566 | return -ENODEV; | ||
567 | } | ||
568 | |||
569 | #endif /* CONFIG_HOTPLUG */ | ||
570 | |||
405 | /** | 571 | /** |
406 | * usb_register_driver - register a USB driver | 572 | * usb_register_driver - register a USB driver |
407 | * @new_driver: USB operations for the driver | 573 | * @new_driver: USB operations for the driver |
@@ -469,3 +635,119 @@ void usb_deregister(struct usb_driver *driver) | |||
469 | usbfs_update_special(); | 635 | usbfs_update_special(); |
470 | } | 636 | } |
471 | EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); | 637 | EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); |
638 | |||
639 | #ifdef CONFIG_PM | ||
640 | |||
641 | static int verify_suspended(struct device *dev, void *unused) | ||
642 | { | ||
643 | if (dev->driver == NULL) | ||
644 | return 0; | ||
645 | return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; | ||
646 | } | ||
647 | |||
648 | static int usb_generic_suspend(struct device *dev, pm_message_t message) | ||
649 | { | ||
650 | struct usb_interface *intf; | ||
651 | struct usb_driver *driver; | ||
652 | int status; | ||
653 | |||
654 | /* USB devices enter SUSPEND state through their hubs, but can be | ||
655 | * marked for FREEZE as soon as their children are already idled. | ||
656 | * But those semantics are useless, so we equate the two (sigh). | ||
657 | */ | ||
658 | if (dev->driver == &usb_generic_driver) { | ||
659 | if (dev->power.power_state.event == message.event) | ||
660 | return 0; | ||
661 | /* we need to rule out bogus requests through sysfs */ | ||
662 | status = device_for_each_child(dev, NULL, verify_suspended); | ||
663 | if (status) | ||
664 | return status; | ||
665 | return usb_port_suspend(to_usb_device(dev)); | ||
666 | } | ||
667 | |||
668 | if ((dev->driver == NULL) || | ||
669 | (dev->driver_data == &usb_generic_driver_data)) | ||
670 | return 0; | ||
671 | |||
672 | intf = to_usb_interface(dev); | ||
673 | driver = to_usb_driver(dev->driver); | ||
674 | |||
675 | /* with no hardware, USB interfaces only use FREEZE and ON states */ | ||
676 | if (!is_active(intf)) | ||
677 | return 0; | ||
678 | |||
679 | if (driver->suspend && driver->resume) { | ||
680 | status = driver->suspend(intf, message); | ||
681 | if (status) | ||
682 | dev_err(dev, "%s error %d\n", "suspend", status); | ||
683 | else | ||
684 | mark_quiesced(intf); | ||
685 | } else { | ||
686 | // FIXME else if there's no suspend method, disconnect... | ||
687 | dev_warn(dev, "no suspend for driver %s?\n", driver->name); | ||
688 | mark_quiesced(intf); | ||
689 | status = 0; | ||
690 | } | ||
691 | return status; | ||
692 | } | ||
693 | |||
694 | static int usb_generic_resume(struct device *dev) | ||
695 | { | ||
696 | struct usb_interface *intf; | ||
697 | struct usb_driver *driver; | ||
698 | struct usb_device *udev; | ||
699 | int status; | ||
700 | |||
701 | if (dev->power.power_state.event == PM_EVENT_ON) | ||
702 | return 0; | ||
703 | |||
704 | /* mark things as "on" immediately, no matter what errors crop up */ | ||
705 | dev->power.power_state.event = PM_EVENT_ON; | ||
706 | |||
707 | /* devices resume through their hubs */ | ||
708 | if (dev->driver == &usb_generic_driver) { | ||
709 | udev = to_usb_device(dev); | ||
710 | if (udev->state == USB_STATE_NOTATTACHED) | ||
711 | return 0; | ||
712 | return usb_port_resume(udev); | ||
713 | } | ||
714 | |||
715 | if ((dev->driver == NULL) || | ||
716 | (dev->driver_data == &usb_generic_driver_data)) { | ||
717 | dev->power.power_state.event = PM_EVENT_FREEZE; | ||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | intf = to_usb_interface(dev); | ||
722 | driver = to_usb_driver(dev->driver); | ||
723 | |||
724 | udev = interface_to_usbdev(intf); | ||
725 | if (udev->state == USB_STATE_NOTATTACHED) | ||
726 | return 0; | ||
727 | |||
728 | /* if driver was suspended, it has a resume method; | ||
729 | * however, sysfs can wrongly mark things as suspended | ||
730 | * (on the "no suspend method" FIXME path above) | ||
731 | */ | ||
732 | if (driver->resume) { | ||
733 | status = driver->resume(intf); | ||
734 | if (status) { | ||
735 | dev_err(dev, "%s error %d\n", "resume", status); | ||
736 | mark_quiesced(intf); | ||
737 | } | ||
738 | } else | ||
739 | dev_warn(dev, "no resume for driver %s?\n", driver->name); | ||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | #endif /* CONFIG_PM */ | ||
744 | |||
745 | struct bus_type usb_bus_type = { | ||
746 | .name = "usb", | ||
747 | .match = usb_device_match, | ||
748 | .uevent = usb_uevent, | ||
749 | #ifdef CONFIG_PM | ||
750 | .suspend = usb_generic_suspend, | ||
751 | .resume = usb_generic_resume, | ||
752 | #endif | ||
753 | }; | ||
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c new file mode 100644 index 00000000000..7bab9769b34 --- /dev/null +++ b/drivers/usb/core/generic.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * drivers/usb/generic.c - generic driver for USB devices (not interfaces) | ||
3 | * | ||
4 | * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de> | ||
5 | * | ||
6 | * based on drivers/usb/usb.c which had the following copyrights: | ||
7 | * (C) Copyright Linus Torvalds 1999 | ||
8 | * (C) Copyright Johannes Erdfelt 1999-2001 | ||
9 | * (C) Copyright Andreas Gal 1999 | ||
10 | * (C) Copyright Gregory P. Smith 1999 | ||
11 | * (C) Copyright Deti Fliegl 1999 (new USB architecture) | ||
12 | * (C) Copyright Randy Dunlap 2000 | ||
13 | * (C) Copyright David Brownell 2000-2004 | ||
14 | * (C) Copyright Yggdrasil Computing, Inc. 2000 | ||
15 | * (usb_device_id matching changes by Adam J. Richter) | ||
16 | * (C) Copyright Greg Kroah-Hartman 2002-2003 | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include "usb.h" | ||
23 | |||
24 | static int generic_probe(struct device *dev) | ||
25 | { | ||
26 | return 0; | ||
27 | } | ||
28 | static int generic_remove(struct device *dev) | ||
29 | { | ||
30 | struct usb_device *udev = to_usb_device(dev); | ||
31 | |||
32 | /* if this is only an unbind, not a physical disconnect, then | ||
33 | * unconfigure the device */ | ||
34 | if (udev->state == USB_STATE_CONFIGURED) | ||
35 | usb_set_configuration(udev, 0); | ||
36 | |||
37 | /* in case the call failed or the device was suspended */ | ||
38 | if (udev->state >= USB_STATE_CONFIGURED) | ||
39 | usb_disable_device(udev, 0); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | struct device_driver usb_generic_driver = { | ||
44 | .owner = THIS_MODULE, | ||
45 | .name = "usb", | ||
46 | .bus = &usb_bus_type, | ||
47 | .probe = generic_probe, | ||
48 | .remove = generic_remove, | ||
49 | }; | ||
50 | |||
51 | /* Fun hack to determine if the struct device is a | ||
52 | * usb device or a usb interface. */ | ||
53 | int usb_generic_driver_data; | ||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b28a31b2030..0b8c67bcde6 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -112,87 +112,6 @@ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, | |||
112 | return NULL; | 112 | return NULL; |
113 | } | 113 | } |
114 | 114 | ||
115 | /** | ||
116 | * usb_driver_claim_interface - bind a driver to an interface | ||
117 | * @driver: the driver to be bound | ||
118 | * @iface: the interface to which it will be bound; must be in the | ||
119 | * usb device's active configuration | ||
120 | * @priv: driver data associated with that interface | ||
121 | * | ||
122 | * This is used by usb device drivers that need to claim more than one | ||
123 | * interface on a device when probing (audio and acm are current examples). | ||
124 | * No device driver should directly modify internal usb_interface or | ||
125 | * usb_device structure members. | ||
126 | * | ||
127 | * Few drivers should need to use this routine, since the most natural | ||
128 | * way to bind to an interface is to return the private data from | ||
129 | * the driver's probe() method. | ||
130 | * | ||
131 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | ||
132 | * writelock. So driver probe() entries don't need extra locking, | ||
133 | * but other call contexts may need to explicitly claim those locks. | ||
134 | */ | ||
135 | int usb_driver_claim_interface(struct usb_driver *driver, | ||
136 | struct usb_interface *iface, void* priv) | ||
137 | { | ||
138 | struct device *dev = &iface->dev; | ||
139 | |||
140 | if (dev->driver) | ||
141 | return -EBUSY; | ||
142 | |||
143 | dev->driver = &driver->driver; | ||
144 | usb_set_intfdata(iface, priv); | ||
145 | iface->condition = USB_INTERFACE_BOUND; | ||
146 | mark_active(iface); | ||
147 | |||
148 | /* if interface was already added, bind now; else let | ||
149 | * the future device_add() bind it, bypassing probe() | ||
150 | */ | ||
151 | if (device_is_registered(dev)) | ||
152 | device_bind_driver(dev); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * usb_driver_release_interface - unbind a driver from an interface | ||
159 | * @driver: the driver to be unbound | ||
160 | * @iface: the interface from which it will be unbound | ||
161 | * | ||
162 | * This can be used by drivers to release an interface without waiting | ||
163 | * for their disconnect() methods to be called. In typical cases this | ||
164 | * also causes the driver disconnect() method to be called. | ||
165 | * | ||
166 | * This call is synchronous, and may not be used in an interrupt context. | ||
167 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | ||
168 | * writelock. So driver disconnect() entries don't need extra locking, | ||
169 | * but other call contexts may need to explicitly claim those locks. | ||
170 | */ | ||
171 | void usb_driver_release_interface(struct usb_driver *driver, | ||
172 | struct usb_interface *iface) | ||
173 | { | ||
174 | struct device *dev = &iface->dev; | ||
175 | |||
176 | /* this should never happen, don't release something that's not ours */ | ||
177 | if (!dev->driver || dev->driver != &driver->driver) | ||
178 | return; | ||
179 | |||
180 | /* don't release from within disconnect() */ | ||
181 | if (iface->condition != USB_INTERFACE_BOUND) | ||
182 | return; | ||
183 | |||
184 | /* don't release if the interface hasn't been added yet */ | ||
185 | if (device_is_registered(dev)) { | ||
186 | iface->condition = USB_INTERFACE_UNBINDING; | ||
187 | device_release_driver(dev); | ||
188 | } | ||
189 | |||
190 | dev->driver = NULL; | ||
191 | usb_set_intfdata(iface, NULL); | ||
192 | iface->condition = USB_INTERFACE_UNBOUND; | ||
193 | mark_quiesced(iface); | ||
194 | } | ||
195 | |||
196 | struct find_interface_arg { | 115 | struct find_interface_arg { |
197 | int minor; | 116 | int minor; |
198 | struct usb_interface *interface; | 117 | struct usb_interface *interface; |
@@ -234,120 +153,6 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) | |||
234 | return argb.interface; | 153 | return argb.interface; |
235 | } | 154 | } |
236 | 155 | ||
237 | #ifdef CONFIG_HOTPLUG | ||
238 | |||
239 | /* | ||
240 | * This sends an uevent to userspace, typically helping to load driver | ||
241 | * or other modules, configure the device, and more. Drivers can provide | ||
242 | * a MODULE_DEVICE_TABLE to help with module loading subtasks. | ||
243 | * | ||
244 | * We're called either from khubd (the typical case) or from root hub | ||
245 | * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle | ||
246 | * delays in event delivery. Use sysfs (and DEVPATH) to make sure the | ||
247 | * device (and this configuration!) are still present. | ||
248 | */ | ||
249 | static int usb_uevent(struct device *dev, char **envp, int num_envp, | ||
250 | char *buffer, int buffer_size) | ||
251 | { | ||
252 | struct usb_interface *intf; | ||
253 | struct usb_device *usb_dev; | ||
254 | struct usb_host_interface *alt; | ||
255 | int i = 0; | ||
256 | int length = 0; | ||
257 | |||
258 | if (!dev) | ||
259 | return -ENODEV; | ||
260 | |||
261 | /* driver is often null here; dev_dbg() would oops */ | ||
262 | pr_debug ("usb %s: uevent\n", dev->bus_id); | ||
263 | |||
264 | /* Must check driver_data here, as on remove driver is always NULL */ | ||
265 | if ((dev->driver == &usb_generic_driver) || | ||
266 | (dev->driver_data == &usb_generic_driver_data)) | ||
267 | return 0; | ||
268 | |||
269 | intf = to_usb_interface(dev); | ||
270 | usb_dev = interface_to_usbdev (intf); | ||
271 | alt = intf->cur_altsetting; | ||
272 | |||
273 | if (usb_dev->devnum < 0) { | ||
274 | pr_debug ("usb %s: already deleted?\n", dev->bus_id); | ||
275 | return -ENODEV; | ||
276 | } | ||
277 | if (!usb_dev->bus) { | ||
278 | pr_debug ("usb %s: bus removed?\n", dev->bus_id); | ||
279 | return -ENODEV; | ||
280 | } | ||
281 | |||
282 | #ifdef CONFIG_USB_DEVICEFS | ||
283 | /* If this is available, userspace programs can directly read | ||
284 | * all the device descriptors we don't tell them about. Or | ||
285 | * even act as usermode drivers. | ||
286 | * | ||
287 | * FIXME reduce hardwired intelligence here | ||
288 | */ | ||
289 | if (add_uevent_var(envp, num_envp, &i, | ||
290 | buffer, buffer_size, &length, | ||
291 | "DEVICE=/proc/bus/usb/%03d/%03d", | ||
292 | usb_dev->bus->busnum, usb_dev->devnum)) | ||
293 | return -ENOMEM; | ||
294 | #endif | ||
295 | |||
296 | /* per-device configurations are common */ | ||
297 | if (add_uevent_var(envp, num_envp, &i, | ||
298 | buffer, buffer_size, &length, | ||
299 | "PRODUCT=%x/%x/%x", | ||
300 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
301 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
302 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) | ||
303 | return -ENOMEM; | ||
304 | |||
305 | /* class-based driver binding models */ | ||
306 | if (add_uevent_var(envp, num_envp, &i, | ||
307 | buffer, buffer_size, &length, | ||
308 | "TYPE=%d/%d/%d", | ||
309 | usb_dev->descriptor.bDeviceClass, | ||
310 | usb_dev->descriptor.bDeviceSubClass, | ||
311 | usb_dev->descriptor.bDeviceProtocol)) | ||
312 | return -ENOMEM; | ||
313 | |||
314 | if (add_uevent_var(envp, num_envp, &i, | ||
315 | buffer, buffer_size, &length, | ||
316 | "INTERFACE=%d/%d/%d", | ||
317 | alt->desc.bInterfaceClass, | ||
318 | alt->desc.bInterfaceSubClass, | ||
319 | alt->desc.bInterfaceProtocol)) | ||
320 | return -ENOMEM; | ||
321 | |||
322 | if (add_uevent_var(envp, num_envp, &i, | ||
323 | buffer, buffer_size, &length, | ||
324 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", | ||
325 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
326 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
327 | le16_to_cpu(usb_dev->descriptor.bcdDevice), | ||
328 | usb_dev->descriptor.bDeviceClass, | ||
329 | usb_dev->descriptor.bDeviceSubClass, | ||
330 | usb_dev->descriptor.bDeviceProtocol, | ||
331 | alt->desc.bInterfaceClass, | ||
332 | alt->desc.bInterfaceSubClass, | ||
333 | alt->desc.bInterfaceProtocol)) | ||
334 | return -ENOMEM; | ||
335 | |||
336 | envp[i] = NULL; | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | #else | ||
342 | |||
343 | static int usb_uevent(struct device *dev, char **envp, | ||
344 | int num_envp, char *buffer, int buffer_size) | ||
345 | { | ||
346 | return -ENODEV; | ||
347 | } | ||
348 | |||
349 | #endif /* CONFIG_HOTPLUG */ | ||
350 | |||
351 | /** | 156 | /** |
352 | * usb_release_dev - free a usb device structure when all users of it are finished. | 157 | * usb_release_dev - free a usb device structure when all users of it are finished. |
353 | * @dev: device that's been disconnected | 158 | * @dev: device that's been disconnected |
@@ -990,116 +795,6 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, | |||
990 | usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | 795 | usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); |
991 | } | 796 | } |
992 | 797 | ||
993 | static int verify_suspended(struct device *dev, void *unused) | ||
994 | { | ||
995 | if (dev->driver == NULL) | ||
996 | return 0; | ||
997 | return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; | ||
998 | } | ||
999 | |||
1000 | static int usb_generic_suspend(struct device *dev, pm_message_t message) | ||
1001 | { | ||
1002 | struct usb_interface *intf; | ||
1003 | struct usb_driver *driver; | ||
1004 | int status; | ||
1005 | |||
1006 | /* USB devices enter SUSPEND state through their hubs, but can be | ||
1007 | * marked for FREEZE as soon as their children are already idled. | ||
1008 | * But those semantics are useless, so we equate the two (sigh). | ||
1009 | */ | ||
1010 | if (dev->driver == &usb_generic_driver) { | ||
1011 | if (dev->power.power_state.event == message.event) | ||
1012 | return 0; | ||
1013 | /* we need to rule out bogus requests through sysfs */ | ||
1014 | status = device_for_each_child(dev, NULL, verify_suspended); | ||
1015 | if (status) | ||
1016 | return status; | ||
1017 | return usb_port_suspend(to_usb_device(dev)); | ||
1018 | } | ||
1019 | |||
1020 | if ((dev->driver == NULL) || | ||
1021 | (dev->driver_data == &usb_generic_driver_data)) | ||
1022 | return 0; | ||
1023 | |||
1024 | intf = to_usb_interface(dev); | ||
1025 | driver = to_usb_driver(dev->driver); | ||
1026 | |||
1027 | /* with no hardware, USB interfaces only use FREEZE and ON states */ | ||
1028 | if (!is_active(intf)) | ||
1029 | return 0; | ||
1030 | |||
1031 | if (driver->suspend && driver->resume) { | ||
1032 | status = driver->suspend(intf, message); | ||
1033 | if (status) | ||
1034 | dev_err(dev, "%s error %d\n", "suspend", status); | ||
1035 | else | ||
1036 | mark_quiesced(intf); | ||
1037 | } else { | ||
1038 | // FIXME else if there's no suspend method, disconnect... | ||
1039 | dev_warn(dev, "no suspend for driver %s?\n", driver->name); | ||
1040 | mark_quiesced(intf); | ||
1041 | status = 0; | ||
1042 | } | ||
1043 | return status; | ||
1044 | } | ||
1045 | |||
1046 | static int usb_generic_resume(struct device *dev) | ||
1047 | { | ||
1048 | struct usb_interface *intf; | ||
1049 | struct usb_driver *driver; | ||
1050 | struct usb_device *udev; | ||
1051 | int status; | ||
1052 | |||
1053 | if (dev->power.power_state.event == PM_EVENT_ON) | ||
1054 | return 0; | ||
1055 | |||
1056 | /* mark things as "on" immediately, no matter what errors crop up */ | ||
1057 | dev->power.power_state.event = PM_EVENT_ON; | ||
1058 | |||
1059 | /* devices resume through their hubs */ | ||
1060 | if (dev->driver == &usb_generic_driver) { | ||
1061 | udev = to_usb_device(dev); | ||
1062 | if (udev->state == USB_STATE_NOTATTACHED) | ||
1063 | return 0; | ||
1064 | return usb_port_resume(udev); | ||
1065 | } | ||
1066 | |||
1067 | if ((dev->driver == NULL) || | ||
1068 | (dev->driver_data == &usb_generic_driver_data)) { | ||
1069 | dev->power.power_state.event = PM_EVENT_FREEZE; | ||
1070 | return 0; | ||
1071 | } | ||
1072 | |||
1073 | intf = to_usb_interface(dev); | ||
1074 | driver = to_usb_driver(dev->driver); | ||
1075 | |||
1076 | udev = interface_to_usbdev(intf); | ||
1077 | if (udev->state == USB_STATE_NOTATTACHED) | ||
1078 | return 0; | ||
1079 | |||
1080 | /* if driver was suspended, it has a resume method; | ||
1081 | * however, sysfs can wrongly mark things as suspended | ||
1082 | * (on the "no suspend method" FIXME path above) | ||
1083 | */ | ||
1084 | if (driver->resume) { | ||
1085 | status = driver->resume(intf); | ||
1086 | if (status) { | ||
1087 | dev_err(dev, "%s error %d\n", "resume", status); | ||
1088 | mark_quiesced(intf); | ||
1089 | } | ||
1090 | } else | ||
1091 | dev_warn(dev, "no resume for driver %s?\n", driver->name); | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | struct bus_type usb_bus_type = { | ||
1096 | .name = "usb", | ||
1097 | .match = usb_device_match, | ||
1098 | .uevent = usb_uevent, | ||
1099 | .suspend = usb_generic_suspend, | ||
1100 | .resume = usb_generic_resume, | ||
1101 | }; | ||
1102 | |||
1103 | /* format to disable USB on kernel command line is: nousb */ | 798 | /* format to disable USB on kernel command line is: nousb */ |
1104 | __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444); | 799 | __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444); |
1105 | 800 | ||
@@ -1203,8 +898,6 @@ EXPORT_SYMBOL(usb_hub_tt_clear_buffer); | |||
1203 | 898 | ||
1204 | EXPORT_SYMBOL(usb_lock_device_for_reset); | 899 | EXPORT_SYMBOL(usb_lock_device_for_reset); |
1205 | 900 | ||
1206 | EXPORT_SYMBOL(usb_driver_claim_interface); | ||
1207 | EXPORT_SYMBOL(usb_driver_release_interface); | ||
1208 | EXPORT_SYMBOL(usb_find_interface); | 901 | EXPORT_SYMBOL(usb_find_interface); |
1209 | EXPORT_SYMBOL(usb_ifnum_to_if); | 902 | EXPORT_SYMBOL(usb_ifnum_to_if); |
1210 | EXPORT_SYMBOL(usb_altnum_to_altsetting); | 903 | EXPORT_SYMBOL(usb_altnum_to_altsetting); |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 5a4eff5eec8..82d397a6f77 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -33,9 +33,9 @@ extern void usb_host_cleanup(void); | |||
33 | extern int usb_port_suspend(struct usb_device *dev); | 33 | extern int usb_port_suspend(struct usb_device *dev); |
34 | extern int usb_port_resume(struct usb_device *dev); | 34 | extern int usb_port_resume(struct usb_device *dev); |
35 | 35 | ||
36 | extern struct bus_type usb_bus_type; | ||
36 | extern struct device_driver usb_generic_driver; | 37 | extern struct device_driver usb_generic_driver; |
37 | extern int usb_generic_driver_data; | 38 | extern int usb_generic_driver_data; |
38 | extern int usb_device_match(struct device *dev, struct device_driver *drv); | ||
39 | 39 | ||
40 | /* Interfaces and their "power state" are owned by usbcore */ | 40 | /* Interfaces and their "power state" are owned by usbcore */ |
41 | 41 | ||