/* 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 */
 
                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
        *pdev = NULL;
        spin_unlock_irq(&device_state_lock);
 
+       hub_free_dev(udev);
+
        put_device(&udev->dev);
 }
 
 loop:
                usb_ep0_reinit(udev);
                release_address(udev);
+               hub_free_dev(udev);
                usb_put_dev(udev);
                if ((status == -ENOTCONN) || (status == -ENOTSUPP))
                        break;
 
        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);