diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 8953ded695411549b5c879ef429467c8b7f768bd..a3cdb09734abc52bc7cf9c10fcc44a787c38c5d3 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -248,7 +248,7 @@ struct hc_driver { /* xHCI specific functions */ /* Called by usb_alloc_dev to alloc HC device structures */ int (*alloc_dev)(struct usb_hcd *, struct usb_device *); - /* Called by usb_release_dev to free HC device structures */ + /* Called by usb_disconnect to free HC device structures */ void (*free_dev)(struct usb_hcd *, struct usb_device *); /* Bandwidth computation functions */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0e0a190bbd00d0b03896d3ae1535929fd2708e11..e198ff8a11c0646bb951d879213282ed2ba243cf 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1524,6 +1524,15 @@ static void update_address(struct usb_device *udev, int devnum) udev->devnum = devnum; } +static void hub_free_dev(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + /* Root hubs aren't real devices, so don't free HCD resources */ + if (hcd->driver->free_dev && udev->parent) + hcd->driver->free_dev(hcd, udev); +} + /** * usb_disconnect - disconnect a device (usbcore-internal) * @pdev: pointer to device being disconnected @@ -1592,6 +1601,8 @@ void usb_disconnect(struct usb_device **pdev) *pdev = NULL; spin_unlock_irq(&device_state_lock); + hub_free_dev(udev); + put_device(&udev->dev); } @@ -3166,6 +3177,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, loop: usb_ep0_reinit(udev); release_address(udev); + hub_free_dev(udev); usb_put_dev(udev); if ((status == -ENOTCONN) || (status == -ENOTSUPP)) break; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 32966ccdff633872a01f8857487022ca2722d5ac..1297e9b16a5101bb941dbfeda831b3c2c3be350d 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -225,9 +225,6 @@ static void usb_release_dev(struct device *dev) hcd = bus_to_hcd(udev->bus); usb_destroy_configuration(udev); - /* Root hubs aren't real devices, so don't free HCD resources */ - if (hcd->driver->free_dev && udev->parent) - hcd->driver->free_dev(hcd, udev); usb_put_hcd(hcd); kfree(udev->product); kfree(udev->manufacturer);