diff options
Diffstat (limited to 'drivers/usb/core/usb.c')
-rw-r--r-- | drivers/usb/core/usb.c | 87 |
1 files changed, 72 insertions, 15 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 7eee400d3e32..a26f73880c32 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
35 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | #include <linux/debugfs.h> | ||
37 | 38 | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | #include <linux/scatterlist.h> | 40 | #include <linux/scatterlist.h> |
@@ -139,8 +140,7 @@ static int __find_interface(struct device *dev, void *data) | |||
139 | struct find_interface_arg *arg = data; | 140 | struct find_interface_arg *arg = data; |
140 | struct usb_interface *intf; | 141 | struct usb_interface *intf; |
141 | 142 | ||
142 | /* can't look at usb devices, only interfaces */ | 143 | if (!is_usb_interface(dev)) |
143 | if (is_usb_device(dev)) | ||
144 | return 0; | 144 | return 0; |
145 | 145 | ||
146 | intf = to_usb_interface(dev); | 146 | intf = to_usb_interface(dev); |
@@ -184,11 +184,16 @@ EXPORT_SYMBOL_GPL(usb_find_interface); | |||
184 | static void usb_release_dev(struct device *dev) | 184 | static void usb_release_dev(struct device *dev) |
185 | { | 185 | { |
186 | struct usb_device *udev; | 186 | struct usb_device *udev; |
187 | struct usb_hcd *hcd; | ||
187 | 188 | ||
188 | udev = to_usb_device(dev); | 189 | udev = to_usb_device(dev); |
190 | hcd = bus_to_hcd(udev->bus); | ||
189 | 191 | ||
190 | usb_destroy_configuration(udev); | 192 | usb_destroy_configuration(udev); |
191 | usb_put_hcd(bus_to_hcd(udev->bus)); | 193 | /* Root hubs aren't real devices, so don't free HCD resources */ |
194 | if (hcd->driver->free_dev && udev->parent) | ||
195 | hcd->driver->free_dev(hcd, udev); | ||
196 | usb_put_hcd(hcd); | ||
192 | kfree(udev->product); | 197 | kfree(udev->product); |
193 | kfree(udev->manufacturer); | 198 | kfree(udev->manufacturer); |
194 | kfree(udev->serial); | 199 | kfree(udev->serial); |
@@ -305,10 +310,21 @@ static struct dev_pm_ops usb_device_pm_ops = { | |||
305 | 310 | ||
306 | #endif /* CONFIG_PM */ | 311 | #endif /* CONFIG_PM */ |
307 | 312 | ||
313 | |||
314 | static char *usb_nodename(struct device *dev) | ||
315 | { | ||
316 | struct usb_device *usb_dev; | ||
317 | |||
318 | usb_dev = to_usb_device(dev); | ||
319 | return kasprintf(GFP_KERNEL, "bus/usb/%03d/%03d", | ||
320 | usb_dev->bus->busnum, usb_dev->devnum); | ||
321 | } | ||
322 | |||
308 | struct device_type usb_device_type = { | 323 | struct device_type usb_device_type = { |
309 | .name = "usb_device", | 324 | .name = "usb_device", |
310 | .release = usb_release_dev, | 325 | .release = usb_release_dev, |
311 | .uevent = usb_dev_uevent, | 326 | .uevent = usb_dev_uevent, |
327 | .nodename = usb_nodename, | ||
312 | .pm = &usb_device_pm_ops, | 328 | .pm = &usb_device_pm_ops, |
313 | }; | 329 | }; |
314 | 330 | ||
@@ -348,6 +364,13 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, | |||
348 | kfree(dev); | 364 | kfree(dev); |
349 | return NULL; | 365 | return NULL; |
350 | } | 366 | } |
367 | /* Root hubs aren't true devices, so don't allocate HCD resources */ | ||
368 | if (usb_hcd->driver->alloc_dev && parent && | ||
369 | !usb_hcd->driver->alloc_dev(usb_hcd, dev)) { | ||
370 | usb_put_hcd(bus_to_hcd(bus)); | ||
371 | kfree(dev); | ||
372 | return NULL; | ||
373 | } | ||
351 | 374 | ||
352 | device_initialize(&dev->dev); | 375 | device_initialize(&dev->dev); |
353 | dev->dev.bus = &usb_bus_type; | 376 | dev->dev.bus = &usb_bus_type; |
@@ -375,18 +398,24 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, | |||
375 | */ | 398 | */ |
376 | if (unlikely(!parent)) { | 399 | if (unlikely(!parent)) { |
377 | dev->devpath[0] = '0'; | 400 | dev->devpath[0] = '0'; |
401 | dev->route = 0; | ||
378 | 402 | ||
379 | dev->dev.parent = bus->controller; | 403 | dev->dev.parent = bus->controller; |
380 | dev_set_name(&dev->dev, "usb%d", bus->busnum); | 404 | dev_set_name(&dev->dev, "usb%d", bus->busnum); |
381 | root_hub = 1; | 405 | root_hub = 1; |
382 | } else { | 406 | } else { |
383 | /* match any labeling on the hubs; it's one-based */ | 407 | /* match any labeling on the hubs; it's one-based */ |
384 | if (parent->devpath[0] == '0') | 408 | if (parent->devpath[0] == '0') { |
385 | snprintf(dev->devpath, sizeof dev->devpath, | 409 | snprintf(dev->devpath, sizeof dev->devpath, |
386 | "%d", port1); | 410 | "%d", port1); |
387 | else | 411 | /* Root ports are not counted in route string */ |
412 | dev->route = 0; | ||
413 | } else { | ||
388 | snprintf(dev->devpath, sizeof dev->devpath, | 414 | snprintf(dev->devpath, sizeof dev->devpath, |
389 | "%s.%d", parent->devpath, port1); | 415 | "%s.%d", parent->devpath, port1); |
416 | dev->route = parent->route + | ||
417 | (port1 << ((parent->level - 1)*4)); | ||
418 | } | ||
390 | 419 | ||
391 | dev->dev.parent = &parent->dev; | 420 | dev->dev.parent = &parent->dev; |
392 | dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath); | 421 | dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath); |
@@ -799,12 +828,12 @@ void usb_buffer_dmasync(struct urb *urb) | |||
799 | return; | 828 | return; |
800 | 829 | ||
801 | if (controller->dma_mask) { | 830 | if (controller->dma_mask) { |
802 | dma_sync_single(controller, | 831 | dma_sync_single_for_cpu(controller, |
803 | urb->transfer_dma, urb->transfer_buffer_length, | 832 | urb->transfer_dma, urb->transfer_buffer_length, |
804 | usb_pipein(urb->pipe) | 833 | usb_pipein(urb->pipe) |
805 | ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | 834 | ? DMA_FROM_DEVICE : DMA_TO_DEVICE); |
806 | if (usb_pipecontrol(urb->pipe)) | 835 | if (usb_pipecontrol(urb->pipe)) |
807 | dma_sync_single(controller, | 836 | dma_sync_single_for_cpu(controller, |
808 | urb->setup_dma, | 837 | urb->setup_dma, |
809 | sizeof(struct usb_ctrlrequest), | 838 | sizeof(struct usb_ctrlrequest), |
810 | DMA_TO_DEVICE); | 839 | DMA_TO_DEVICE); |
@@ -922,8 +951,8 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in, | |||
922 | || !controller->dma_mask) | 951 | || !controller->dma_mask) |
923 | return; | 952 | return; |
924 | 953 | ||
925 | dma_sync_sg(controller, sg, n_hw_ents, | 954 | dma_sync_sg_for_cpu(controller, sg, n_hw_ents, |
926 | is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | 955 | is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); |
927 | } | 956 | } |
928 | EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg); | 957 | EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg); |
929 | #endif | 958 | #endif |
@@ -1001,6 +1030,35 @@ static struct notifier_block usb_bus_nb = { | |||
1001 | .notifier_call = usb_bus_notify, | 1030 | .notifier_call = usb_bus_notify, |
1002 | }; | 1031 | }; |
1003 | 1032 | ||
1033 | struct dentry *usb_debug_root; | ||
1034 | EXPORT_SYMBOL_GPL(usb_debug_root); | ||
1035 | |||
1036 | struct dentry *usb_debug_devices; | ||
1037 | |||
1038 | static int usb_debugfs_init(void) | ||
1039 | { | ||
1040 | usb_debug_root = debugfs_create_dir("usb", NULL); | ||
1041 | if (!usb_debug_root) | ||
1042 | return -ENOENT; | ||
1043 | |||
1044 | usb_debug_devices = debugfs_create_file("devices", 0444, | ||
1045 | usb_debug_root, NULL, | ||
1046 | &usbfs_devices_fops); | ||
1047 | if (!usb_debug_devices) { | ||
1048 | debugfs_remove(usb_debug_root); | ||
1049 | usb_debug_root = NULL; | ||
1050 | return -ENOENT; | ||
1051 | } | ||
1052 | |||
1053 | return 0; | ||
1054 | } | ||
1055 | |||
1056 | static void usb_debugfs_cleanup(void) | ||
1057 | { | ||
1058 | debugfs_remove(usb_debug_devices); | ||
1059 | debugfs_remove(usb_debug_root); | ||
1060 | } | ||
1061 | |||
1004 | /* | 1062 | /* |
1005 | * Init | 1063 | * Init |
1006 | */ | 1064 | */ |
@@ -1012,6 +1070,10 @@ static int __init usb_init(void) | |||
1012 | return 0; | 1070 | return 0; |
1013 | } | 1071 | } |
1014 | 1072 | ||
1073 | retval = usb_debugfs_init(); | ||
1074 | if (retval) | ||
1075 | goto out; | ||
1076 | |||
1015 | retval = ksuspend_usb_init(); | 1077 | retval = ksuspend_usb_init(); |
1016 | if (retval) | 1078 | if (retval) |
1017 | goto out; | 1079 | goto out; |
@@ -1021,9 +1083,6 @@ static int __init usb_init(void) | |||
1021 | retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); | 1083 | retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); |
1022 | if (retval) | 1084 | if (retval) |
1023 | goto bus_notifier_failed; | 1085 | goto bus_notifier_failed; |
1024 | retval = usb_host_init(); | ||
1025 | if (retval) | ||
1026 | goto host_init_failed; | ||
1027 | retval = usb_major_init(); | 1086 | retval = usb_major_init(); |
1028 | if (retval) | 1087 | if (retval) |
1029 | goto major_init_failed; | 1088 | goto major_init_failed; |
@@ -1053,8 +1112,6 @@ usb_devio_init_failed: | |||
1053 | driver_register_failed: | 1112 | driver_register_failed: |
1054 | usb_major_cleanup(); | 1113 | usb_major_cleanup(); |
1055 | major_init_failed: | 1114 | major_init_failed: |
1056 | usb_host_cleanup(); | ||
1057 | host_init_failed: | ||
1058 | bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); | 1115 | bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); |
1059 | bus_notifier_failed: | 1116 | bus_notifier_failed: |
1060 | bus_unregister(&usb_bus_type); | 1117 | bus_unregister(&usb_bus_type); |
@@ -1079,10 +1136,10 @@ static void __exit usb_exit(void) | |||
1079 | usb_deregister(&usbfs_driver); | 1136 | usb_deregister(&usbfs_driver); |
1080 | usb_devio_cleanup(); | 1137 | usb_devio_cleanup(); |
1081 | usb_hub_cleanup(); | 1138 | usb_hub_cleanup(); |
1082 | usb_host_cleanup(); | ||
1083 | bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); | 1139 | bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); |
1084 | bus_unregister(&usb_bus_type); | 1140 | bus_unregister(&usb_bus_type); |
1085 | ksuspend_usb_cleanup(); | 1141 | ksuspend_usb_cleanup(); |
1142 | usb_debugfs_cleanup(); | ||
1086 | } | 1143 | } |
1087 | 1144 | ||
1088 | subsys_initcall(usb_init); | 1145 | subsys_initcall(usb_init); |