Index: uspace/drv/bus/usb/xhci/hc.c
===================================================================
--- uspace/drv/bus/usb/xhci/hc.c	(revision 2ca5a198f7308b0c892b04c0fcda44f5e83eb8f0)
+++ uspace/drv/bus/usb/xhci/hc.c	(revision 53fdf8cbac47a41c493c58222638a856360e9a84)
@@ -277,16 +277,11 @@
 		goto err_cmd;
 
-	fid_t fid = fibril_create(&event_worker, hc);
-	if (!fid)
+	hc->event_worker = joinable_fibril_create(&event_worker, hc);
+	if (!hc->event_worker)
 		goto err_bus;
 
-	// TODO: completion_reset
-	hc->event_fibril_completion.active = true;
-	fibril_mutex_initialize(&hc->event_fibril_completion.guard);
-	fibril_condvar_initialize(&hc->event_fibril_completion.cv);
-
 	xhci_sw_ring_init(&hc->sw_ring, PAGE_SIZE / sizeof(xhci_trb_t));
 
-	fibril_add_ready(fid);
+	joinable_fibril_start(hc->event_worker);
 
 	return EOK;
@@ -598,11 +593,5 @@
 	}
 
-	// TODO: completion_complete
-	fibril_mutex_lock(&hc->event_fibril_completion.guard);
-	hc->event_fibril_completion.active = false;
-	fibril_condvar_broadcast(&hc->event_fibril_completion.cv);
-	fibril_mutex_unlock(&hc->event_fibril_completion.guard);
-
-	return EOK;
+	return 0;
 }
 
@@ -688,11 +677,5 @@
 {
 	xhci_sw_ring_stop(&hc->sw_ring);
-
-	// TODO: completion_wait
-	fibril_mutex_lock(&hc->event_fibril_completion.guard);
-	while (hc->event_fibril_completion.active)
-		fibril_condvar_wait(&hc->event_fibril_completion.cv,
-		    &hc->event_fibril_completion.guard);
-	fibril_mutex_unlock(&hc->event_fibril_completion.guard);
+	joinable_fibril_join(hc->event_worker);
 	xhci_sw_ring_fini(&hc->sw_ring);
 
Index: uspace/drv/bus/usb/xhci/hc.h
===================================================================
--- uspace/drv/bus/usb/xhci/hc.h	(revision 2ca5a198f7308b0c892b04c0fcda44f5e83eb8f0)
+++ uspace/drv/bus/usb/xhci/hc.h	(revision 53fdf8cbac47a41c493c58222638a856360e9a84)
@@ -39,4 +39,5 @@
 #include <fibril_synch.h>
 #include <usb/host/usb_transfer_batch.h>
+#include <usb/host/utility.h>
 #include "hw_struct/regs.h"
 #include "hw_struct/context.h"
@@ -78,9 +79,6 @@
 	xhci_sw_ring_t sw_ring;
 
-	struct {
-		fibril_mutex_t guard;
-		fibril_condvar_t cv;
-		bool active;
-	} event_fibril_completion;
+	/** Event handling fibril */
+	joinable_fibril_t *event_worker;
 
 	/* Root hub emulation */
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision 2ca5a198f7308b0c892b04c0fcda44f5e83eb8f0)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision 53fdf8cbac47a41c493c58222638a856360e9a84)
@@ -96,6 +96,6 @@
 	}
 
-	fid_t fid = fibril_create(&rh_worker, rh);
-	if (!fid) {
+	rh->event_worker = joinable_fibril_create(&rh_worker, rh);
+	if (!rh->event_worker) {
 		free(rh->ports);
 		return err;
@@ -113,9 +113,5 @@
 	xhci_sw_ring_init(&rh->event_ring, rh->max_ports);
 
-	hc->event_fibril_completion.active = true;
-	fibril_mutex_initialize(&hc->event_fibril_completion.guard);
-	fibril_condvar_initialize(&hc->event_fibril_completion.cv);
-
-	fibril_add_ready(fid);
+	joinable_fibril_start(rh->event_worker);
 
 	return EOK;
@@ -132,11 +128,5 @@
 
 	xhci_sw_ring_stop(&rh->event_ring);
-
-	// TODO: completion_wait
-	fibril_mutex_lock(&rh->event_fibril_completion.guard);
-	while (rh->event_fibril_completion.active)
-		fibril_condvar_wait(&rh->event_fibril_completion.cv,
-		    &rh->event_fibril_completion.guard);
-	fibril_mutex_unlock(&rh->event_fibril_completion.guard);
+	joinable_fibril_join(rh->event_worker);
 	xhci_sw_ring_fini(&rh->event_ring);
 	return EOK;
@@ -332,11 +322,5 @@
 	}
 
-	// TODO: completion_complete
-	fibril_mutex_lock(&rh->event_fibril_completion.guard);
-	rh->event_fibril_completion.active = false;
-	fibril_condvar_broadcast(&rh->event_fibril_completion.cv);
-	fibril_mutex_unlock(&rh->event_fibril_completion.guard);
-
-	return EOK;
+	return 0;
 }
 
Index: uspace/drv/bus/usb/xhci/rh.h
===================================================================
--- uspace/drv/bus/usb/xhci/rh.h	(revision 2ca5a198f7308b0c892b04c0fcda44f5e83eb8f0)
+++ uspace/drv/bus/usb/xhci/rh.h	(revision 53fdf8cbac47a41c493c58222638a856360e9a84)
@@ -37,6 +37,7 @@
 #define XHCI_RH_H
 
+#include <usb/host/bus.h>
 #include <usb/host/usb_transfer_batch.h>
-#include <usb/host/bus.h>
+#include <usb/host/utility.h>
 
 #include "hw_struct/regs.h"
@@ -77,9 +78,5 @@
 	xhci_sw_ring_t event_ring;
 
-	struct {
-		fibril_mutex_t guard;
-		fibril_condvar_t cv;
-		bool active;
-	} event_fibril_completion;
+	joinable_fibril_t *event_worker;
 } xhci_rh_t;
 
