Index: uspace/drv/bus/usb/ehci/ehci_bus.c
===================================================================
--- uspace/drv/bus/usb/ehci/ehci_bus.c	(revision 70108616235ce221aaa3a66cd84292e390a11def)
+++ uspace/drv/bus/usb/ehci/ehci_bus.c	(revision 8b8c164397f69eeebe6f33b2ef55e23bfa483828)
@@ -114,5 +114,5 @@
 
 
-static int ehci_register_ep(bus_t *bus_base, endpoint_t *ep, const usb_endpoint_desc_t *desc)
+static int ehci_register_ep(bus_t *bus_base, device_t *dev, endpoint_t *ep, const usb_endpoint_desc_t *desc)
 {
 	ehci_bus_t *bus = (ehci_bus_t *) bus_base;
@@ -121,5 +121,5 @@
 	// TODO utilize desc->usb2
 
-	const int err = bus->parent_ops.register_endpoint(bus_base, ep, desc);
+	const int err = bus->parent_ops.register_endpoint(bus_base, dev, ep, desc);
 	if (err)
 		return err;
Index: uspace/drv/bus/usb/ohci/ohci_bus.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_bus.c	(revision 70108616235ce221aaa3a66cd84292e390a11def)
+++ uspace/drv/bus/usb/ohci/ohci_bus.c	(revision 8b8c164397f69eeebe6f33b2ef55e23bfa483828)
@@ -115,10 +115,10 @@
 
 
-static int ohci_register_ep(bus_t *bus_base, endpoint_t *ep, const usb_endpoint_desc_t *desc)
+static int ohci_register_ep(bus_t *bus_base, device_t *dev, endpoint_t *ep, const usb_endpoint_desc_t *desc)
 {
 	ohci_bus_t *bus = (ohci_bus_t *) bus_base;
 	ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
 
-	const int err = bus->parent_ops.register_endpoint(bus_base, ep, desc);
+	const int err = bus->parent_ops.register_endpoint(bus_base, dev, ep, desc);
 	if (err)
 		return err;
Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision 70108616235ce221aaa3a66cd84292e390a11def)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 8b8c164397f69eeebe6f33b2ef55e23bfa483828)
@@ -96,5 +96,4 @@
 	endpoint_add_ref(ep0_base);
 
-	ep0_base->device = &dev->base;
 	xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base);
 
@@ -102,16 +101,22 @@
 		goto err_ep;
 
+	/* Register EP0 */
+	if ((err = xhci_device_add_endpoint(dev, ep0)))
+		goto err_prepared;
+
 	/* Address device */
 	if ((err = hc_address_device(hc, dev, ep0)))
-		goto err_prepared_ep;
-
-	/* Register EP0, passing Temporary reference */
-	dev->endpoints[0] = ep0;
-
-	return EOK;
-
-err_prepared_ep:
+		goto err_added;
+
+	/* Temporary reference */
+	endpoint_del_ref(ep0_base);
+	return EOK;
+
+err_added:
+	xhci_device_remove_endpoint(ep0);
+err_prepared:
 	xhci_endpoint_free_transfer_ds(ep0);
 err_ep:
+	/* Temporary reference */
 	endpoint_del_ref(ep0_base);
 err_slot:
@@ -251,34 +256,56 @@
 }
 
-static int register_endpoint(bus_t *bus_base, endpoint_t *ep, const usb_endpoint_desc_t *desc)
+static int register_endpoint(bus_t *bus_base, device_t *device, endpoint_t *ep_base, const usb_endpoint_desc_t *desc)
 {
 	int err;
 	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
-	assert(bus);
-
-	assert(ep->device);
-
-	xhci_device_t *xhci_dev = xhci_device_get(ep->device);
-	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
-
-	if ((err = prepare_endpoint(xhci_ep, desc)))
+	xhci_endpoint_t *ep = xhci_endpoint_get(ep_base);
+
+	xhci_device_t *dev = xhci_device_get(device);
+
+	if ((err = prepare_endpoint(ep, desc)))
 		return err;
 
-	usb_log_info("Endpoint(%d:%d) registered to XHCI bus.", ep->device->address, ep->endpoint);
-	return xhci_device_add_endpoint(bus->hc, xhci_dev, xhci_ep);
-}
-
-static int unregister_endpoint(bus_t *bus_base, endpoint_t *ep)
-{
+	if ((err = xhci_device_add_endpoint(dev, ep)))
+		goto err_prepared;
+
+	usb_log_info("Endpoint(%d:%d) registered to XHCI bus.", dev->base.address, ep->base.endpoint);
+
+	xhci_ep_ctx_t ep_ctx;
+	xhci_setup_endpoint_context(ep, &ep_ctx);
+
+	if ((err = hc_add_endpoint(bus->hc, dev->slot_id, xhci_endpoint_index(ep), &ep_ctx)))
+		goto err_added;
+
+	return EOK;
+
+err_added:
+	xhci_device_remove_endpoint(ep);
+err_prepared:
+	xhci_endpoint_free_transfer_ds(ep);
+	return err;
+}
+
+static int unregister_endpoint(bus_t *bus_base, endpoint_t *ep_base)
+{
+	int err;
 	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
-	assert(bus);
-
-	usb_log_info("Endpoint(%d:%d) unregistered from XHCI bus.", ep->device->address, ep->endpoint);
-
-	xhci_device_t *xhci_dev = xhci_device_get(ep->device);
-	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
-	const int res = xhci_device_remove_endpoint(bus->hc, xhci_dev, xhci_ep);
-	if (res != EOK)
-		return res;
+	xhci_endpoint_t *ep = xhci_endpoint_get(ep_base);
+	xhci_device_t *dev = xhci_device_get(ep_base->device);
+
+	usb_log_info("Endpoint(%d:%d) unregistered from XHCI bus.", dev->base.address, ep->base.endpoint);
+
+	xhci_device_remove_endpoint(ep);
+
+	/* Drop the endpoint. */
+	if ((err = hc_drop_endpoint(bus->hc, dev->slot_id, xhci_endpoint_index(ep)))) {
+		usb_log_error("Failed to drop endpoint: %s", str_error(err));
+	}
+
+	/* Tear down TRB ring / PSA. */
+	/* TODO: Make this method "noexcept" */
+	if ((err = xhci_endpoint_free_transfer_ds(ep))) {
+		usb_log_error("Failed to free resources of an endpoint.");
+	}
 
 	return EOK;
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision 70108616235ce221aaa3a66cd84292e390a11def)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision 8b8c164397f69eeebe6f33b2ef55e23bfa483828)
@@ -189,5 +189,5 @@
 {
 
-	usb_log_debug2("Allocating main transfer ring for endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep));
+	usb_log_debug2("Allocating main transfer ring for endpoint %u", xhci_ep->base.endpoint);
 
 	xhci_ep->primary_stream_ctx_array = NULL;
@@ -323,5 +323,5 @@
 }
 
-int xhci_device_add_endpoint(xhci_hc_t *hc, xhci_device_t *dev, xhci_endpoint_t *ep)
+int xhci_device_add_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep)
 {
 	assert(dev);
@@ -329,5 +329,5 @@
 
 	/* Offline devices don't create new endpoints other than EP0. */
-	if (!dev->online) {
+	if (!dev->online && ep->base.endpoint > 0) {
 		return EAGAIN;
 	}
@@ -335,60 +335,29 @@
 	const usb_endpoint_t ep_num = ep->base.endpoint;
 
-	assert(&dev->base == ep->base.device);
-
-	// TODO Do not fail hard on runtime conditions
-	assert(!dev->endpoints[ep_num]);
+	if (dev->endpoints[ep_num])
+		return EEXIST;
+
+	/* Device reference */
+	endpoint_add_ref(&ep->base);
+	ep->base.device = &dev->base;
 
 	dev->endpoints[ep_num] = ep;
 	++dev->active_endpoint_count;
 
-	if (ep_num == 0) {
-		/* EP 0 is initialized while setting up the device,
-		 * so we must not issue the command now. */
-		return EOK;
-	}
-
-	/* Add endpoint. */
-	xhci_ep_ctx_t ep_ctx;
-	xhci_setup_endpoint_context(ep, &ep_ctx);
-
-	return hc_add_endpoint(hc, dev->slot_id, xhci_endpoint_index(ep), &ep_ctx);
-}
-
-int xhci_device_remove_endpoint(xhci_hc_t *hc, xhci_device_t *dev, xhci_endpoint_t *ep)
-{
-	assert(&dev->base == ep->base.device);
+	return EOK;
+}
+
+void xhci_device_remove_endpoint(xhci_endpoint_t *ep)
+{
+	assert(ep);
+	xhci_device_t *dev = xhci_device_get(ep->base.device);
+
 	assert(dev->endpoints[ep->base.endpoint]);
-
-	int err = ENOMEM;
-	const usb_endpoint_t ep_num = ep->base.endpoint;
 
 	dev->endpoints[ep->base.endpoint] = NULL;
 	--dev->active_endpoint_count;
-
-	if (ep_num == 0) {
-		/* EP 0 is finalized while releasing the device,
-		 * so we must not issue the command now. */
-		return EOK;
-	}
-
-	/* Drop the endpoint. */
-	if ((err = hc_drop_endpoint(hc, dev->slot_id, xhci_endpoint_index(ep)))) {
-		goto err;
-	}
-
-	/* Tear down TRB ring / PSA. */
-	/* FIXME: For some reason, this causes crash at xhci_trb_ring_fini.
-	if ((err = xhci_endpoint_free_transfer_ds(ep))) {
-		goto err_cmd;
-	}
-	*/
-
-	return EOK;
-
-err:
-	dev->endpoints[ep_num] = ep;
-	++dev->active_endpoint_count;
-	return err;
+	ep->base.device = NULL;
+
+	endpoint_del_ref(&ep->base);
 }
 
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision 70108616235ce221aaa3a66cd84292e390a11def)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision 8b8c164397f69eeebe6f33b2ef55e23bfa483828)
@@ -139,6 +139,6 @@
 void xhci_setup_endpoint_context(xhci_endpoint_t *, xhci_ep_ctx_t *);
 
-int xhci_device_add_endpoint(xhci_hc_t *, xhci_device_t *, xhci_endpoint_t *);
-int xhci_device_remove_endpoint(xhci_hc_t *, xhci_device_t *, xhci_endpoint_t *);
+int xhci_device_add_endpoint(xhci_device_t *, xhci_endpoint_t *);
+void xhci_device_remove_endpoint(xhci_endpoint_t *);
 xhci_endpoint_t * xhci_device_get_endpoint(xhci_device_t *, usb_endpoint_t);
 
