aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/usb.c')
-rw-r--r--drivers/usb/core/usb.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index f026991d0bd..55b8d3a22d2 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -184,11 +184,16 @@ EXPORT_SYMBOL_GPL(usb_find_interface);
184static void usb_release_dev(struct device *dev) 184static 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);
@@ -348,6 +353,13 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
348 kfree(dev); 353 kfree(dev);
349 return NULL; 354 return NULL;
350 } 355 }
356 /* Root hubs aren't true devices, so don't allocate HCD resources */
357 if (usb_hcd->driver->alloc_dev && parent &&
358 !usb_hcd->driver->alloc_dev(usb_hcd, dev)) {
359 usb_put_hcd(bus_to_hcd(bus));
360 kfree(dev);
361 return NULL;
362 }
351 363
352 device_initialize(&dev->dev); 364 device_initialize(&dev->dev);
353 dev->dev.bus = &usb_bus_type; 365 dev->dev.bus = &usb_bus_type;