Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision a3044b414267e474d1d1d8154cf82ce42ea0d017)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 6b2930bfefb987dc1d4ba5cbee4cf72814ef52ce)
@@ -188,12 +188,4 @@
 	xhci_device_t *xhci_dev = xhci_device_get(dev);
 
-	/* If the device is still attached, end DDF drivers gracefully. */
-	if (!xhci_dev->detached) {
-		if ((err = ddf_fun_offline(dev->fun))) {
-			usb_log_warning("Failed to offline DDF function of device '%s': %s",
-			    ddf_fun_get_name(dev->fun), str_error(err));
-		}
-	}
-
 	/* Block creation of new endpoints and transfers. */
 	usb_log_debug2("Device '%s' going offline.", ddf_fun_get_name(dev->fun));
@@ -227,12 +219,4 @@
 	}
 
-	/* Deconfigure device if it's still attached. */
-	if (!xhci_dev->detached) {
-		if ((err = hc_deconfigure_device(hc, xhci_dev->slot_id))) {
-			usb_log_warning("Failed to deconfigure device '%s': %s",
-			    ddf_fun_get_name(dev->fun), str_error(err));
-		}
-	}
-
 	/* Unregister remaining endpoints. */
 	for (unsigned i = 0; i < ARRAY_SIZE(xhci_dev->endpoints); ++i) {
@@ -256,4 +240,8 @@
 	bus->devices_by_slot[xhci_dev->slot_id] = NULL;
 
+	/* Destroy DDF device. */
+	/* XXX: Not a good idea, this method should not destroy devices. */
+	hcd_ddf_device_destroy(dev);
+
 	return EOK;
 }
@@ -301,5 +289,14 @@
 	assert(dev);
 
-	// TODO: Prepare the device for use. Reset? Configure?
+	/* Transition the device from the Addressed to the Configured state. */
+	if ((err = hc_configure_device(hc, dev->slot_id))) {
+		usb_log_warning("Failed to configure device %d.", dev_base->address);
+	}
+
+	/* Block creation of new endpoints and transfers. */
+	usb_log_debug2("Device '%s' going online.", ddf_fun_get_name(dev_base->fun));
+	fibril_mutex_lock(&dev_base->guard);
+	dev->online = true;
+	fibril_mutex_unlock(&dev_base->guard);
 
 	if ((err = ddf_fun_online(dev_base->fun))) {
@@ -328,5 +325,41 @@
 	}
 
-	// TODO: We want to keep the device addressed. Deconfigure?
+	/* Block creation of new endpoints and transfers. */
+	usb_log_debug2("Device '%s' going offline.", ddf_fun_get_name(dev_base->fun));
+	fibril_mutex_lock(&dev_base->guard);
+	dev->online = false;
+	fibril_mutex_unlock(&dev_base->guard);
+
+	/* We will need the endpoint array later for DS deallocation. */
+	xhci_endpoint_t *endpoints[ARRAY_SIZE(dev->endpoints)];
+	memcpy(endpoints, dev->endpoints, sizeof(dev->endpoints));
+
+	/* Remove all endpoints except zero. */
+	for (unsigned i = 1; i < ARRAY_SIZE(endpoints); ++i) {
+		if (!endpoints[i])
+			continue;
+
+		/* FIXME: Asserting here that the endpoint is not active. If not, EBUSY? */
+
+		xhci_device_remove_endpoint(endpoints[i]);
+	}
+
+	/* Issue one HC command to simultaneously drop all endpoints except zero. */
+	if ((err = hc_deconfigure_device(hc, dev->slot_id))) {
+		usb_log_warning("Failed to deconfigure device %d.", dev_base->address);
+	}
+
+	/* Tear down TRB ring / PSA. */
+	/* TODO: Make this method "noexcept" */
+	for (unsigned i = 1; i < ARRAY_SIZE(endpoints); ++i) {
+		if (!endpoints[i])
+			continue;
+
+		if ((err = xhci_endpoint_free_transfer_ds(endpoints[i]))) {
+			usb_log_warning("Failed to free resources of EP (%u:%u): %s", dev_base->address, i, str_error(err));
+		}
+	}
+
+	/* FIXME: What happens to unregistered endpoints now? Destroy them? */
 
 	return EOK;
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision a3044b414267e474d1d1d8154cf82ce42ea0d017)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision 6b2930bfefb987dc1d4ba5cbee4cf72814ef52ce)
@@ -125,7 +125,4 @@
 	/** True if the device can add new endpoints and schedule transfers. */
 	volatile bool online;
-
-	/** True if the device has been physically detached from the socket. */
-	volatile bool detached;
 } xhci_device_t;
 
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision a3044b414267e474d1d1d8154cf82ce42ea0d017)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision 6b2930bfefb987dc1d4ba5cbee4cf72814ef52ce)
@@ -188,8 +188,4 @@
 
 	/* Mark the device as detached. */
-	fibril_mutex_lock(&dev->base.guard);
-	dev->detached = true;
-	fibril_mutex_unlock(&dev->base.guard);
-
 	fibril_mutex_lock(&rh->device.base.guard);
 	list_remove(&dev->base.link);
@@ -202,9 +198,4 @@
 		    ddf_fun_get_name(dev->base.fun), str_error(err));
 	}
-
-	/* Destroy DDF device. */
-	hcd_ddf_device_destroy(&dev->base);
-
-	/* TODO: Figure out what was forgotten and free that as well. */
 
 	return EOK;
