Index: uspace/drv/block/usbmast/main.c
===================================================================
--- uspace/drv/block/usbmast/main.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/block/usbmast/main.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -140,10 +140,4 @@
 }
 
-static int usbmast_device_removed(usb_device_t *dev)
-{
-	// TODO: Implement me!
-	return EOK;
-}
-
 /** Callback when new device is attached and recognized as a mass storage.
  *
@@ -397,5 +391,4 @@
 	.device_add = usbmast_device_add,
 	.device_remove = usbmast_device_remove,
-	.device_removed = usbmast_device_removed,
 	.device_gone = usbmast_device_gone,
 };
Index: uspace/drv/bus/usb/usbdiag/main.c
===================================================================
--- uspace/drv/bus/usb/usbdiag/main.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/bus/usb/usbdiag/main.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -77,4 +77,13 @@
 }
 
+static int device_cleanup(usbdiag_dev_t *diag_dev)
+{
+	/* TODO: Join some fibrils? */
+
+	/* Free memory. */
+	usbdiag_dev_destroy(diag_dev);
+	return EOK;
+}
+
 static int device_remove(usb_device_t *dev)
 {
@@ -91,25 +100,9 @@
 	}
 
-	return EOK;
+	usb_log_info("Device '%s' removed.", usb_device_get_name(dev));
+	return device_cleanup(diag_dev);
 
 err:
 	return rc;
-}
-
-static int device_cleanup(usbdiag_dev_t *diag_dev)
-{
-	/* TODO: Join some fibrils? */
-
-	/* Free memory. */
-	usbdiag_dev_destroy(diag_dev);
-	return EOK;
-}
-
-static int device_removed(usb_device_t *dev)
-{
-	usb_log_info("Device '%s' removed.", usb_device_get_name(dev));
-
-	usbdiag_dev_t *diag_dev = usb_device_to_usbdiag_dev(dev);
-	return device_cleanup(diag_dev);
 }
 
@@ -207,5 +200,4 @@
 	.device_add = device_add,
 	.device_remove = device_remove,
-	.device_removed = device_removed,
 	.device_gone = device_gone,
 	.function_online = function_online,
Index: uspace/drv/bus/usb/usbflbk/main.c
===================================================================
--- uspace/drv/bus/usb/usbflbk/main.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/bus/usb/usbflbk/main.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -69,11 +69,4 @@
 {
 	assert(dev);
-	usb_log_info("Device '%s' will be removed.", usb_device_get_name(dev));
-	return EOK;
-}
-
-static int usbfallback_device_removed(usb_device_t *dev)
-{
-	assert(dev);
 	usb_log_info("Device '%s' removed.", usb_device_get_name(dev));
 	return EOK;
@@ -84,5 +77,4 @@
 	.device_add = usbfallback_device_add,
 	.device_remove = usbfallback_device_remove,
-	.device_removed = usbfallback_device_removed,
 	.device_gone = usbfallback_device_gone,
 };
Index: uspace/drv/bus/usb/usbhub/main.c
===================================================================
--- uspace/drv/bus/usb/usbhub/main.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/bus/usb/usbhub/main.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -49,5 +49,4 @@
 	.device_add = usb_hub_device_add,
 	.device_remove = usb_hub_device_remove,
-	.device_removed = usb_hub_device_removed,
 	.device_gone = usb_hub_device_gone,
 };
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -99,5 +99,5 @@
 
 	/* Continue polling until the device is about to be removed. */
-	return hub->running && !hub->poll_stop;
+	return hub->running;
 }
 
@@ -123,9 +123,6 @@
 	hub_dev->pending_ops_count = 0;
 	hub_dev->running = false;
-	hub_dev->poll_stop = false;
 	fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
-	fibril_mutex_initialize(&hub_dev->poll_guard);
 	fibril_condvar_initialize(&hub_dev->pending_ops_cv);
-	fibril_condvar_initialize(&hub_dev->poll_cv);
 
 	/* Set hub's first configuration. (There should be only one) */
@@ -197,23 +194,4 @@
 }
 
-/**
- * Turn off power to all ports.
- *
- * @param usb_dev generic usb device information
- * @return error code
- */
-int usb_hub_device_remove(usb_device_t *usb_dev)
-{
-	assert(usb_dev);
-	usb_hub_dev_t *hub = usb_device_data_get(usb_dev);
-	assert(hub);
-
-	usb_log_info("(%p) USB hub will be removed.", hub);
-
-	/* Instruct the hub to stop once endpoints are unregistered. */
-	hub->poll_stop = true;
-	return EOK;
-}
-
 static int usb_hub_cleanup(usb_hub_dev_t *hub)
 {
@@ -241,5 +219,11 @@
 }
 
-int usb_hub_device_removed(usb_device_t *usb_dev)
+/**
+ * Turn off power to all ports.
+ *
+ * @param usb_dev generic usb device information
+ * @return error code
+ */
+int usb_hub_device_remove(usb_device_t *usb_dev)
 {
 	assert(usb_dev);
@@ -247,12 +231,8 @@
 	assert(hub);
 
-	usb_log_info("(%p) USB hub was removed, joining polling fibril.", hub);
+	usb_log_info("(%p) USB hub removed, joining polling fibril.", hub);
 
 	/* Join polling fibril. */
-	fibril_mutex_lock(&hub->poll_guard);
-	while (hub->running)
-		fibril_condvar_wait(&hub->poll_cv, &hub->poll_guard);
-	fibril_mutex_unlock(&hub->poll_guard);
-
+	usb_device_poll_join(hub->polling);
 	usb_log_info("(%p) USB hub polling stopped, freeing memory.", hub);
 
@@ -272,12 +252,9 @@
 	assert(hub);
 
-	hub->poll_stop = true;
 	usb_log_info("(%p) USB hub gone, joining polling fibril.", hub);
 
 	/* Join polling fibril. */
-	fibril_mutex_lock(&hub->poll_guard);
-	while (hub->running)
-		fibril_condvar_wait(&hub->poll_cv, &hub->poll_guard);
-	fibril_mutex_unlock(&hub->poll_guard);
+	usb_device_poll_join(hub->polling);
+	usb_log_info("(%p) USB hub polling stopped, freeing memory.", hub);
 
 	/* Destroy hub. */
@@ -592,10 +569,6 @@
 	fibril_mutex_unlock(&hub->pending_ops_mutex);
 	hub->running = false;
-
-	/* Signal polling end to joining thread. */
-	fibril_mutex_lock(&hub->poll_guard);
-	fibril_condvar_signal(&hub->poll_cv);
-	fibril_mutex_unlock(&hub->poll_guard);
-}
+}
+
 /**
  * @}
Index: uspace/drv/bus/usb/usbhub/usbhub.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.h	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/bus/usb/usbhub/usbhub.h	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -39,4 +39,5 @@
 
 #include <ddf/driver.h>
+#include <fibril_synch.h>
 
 #include <usb/classes/hub.h>
@@ -45,6 +46,4 @@
 #include <usb/dev/driver.h>
 #include <usb/dev/poll.h>
-
-#include <fibril_synch.h>
 
 #define NAME "usbhub"
@@ -81,8 +80,4 @@
 	/** Each port is switched individually. */
 	bool per_port_power;
-	/** True if the device should stop running as soon as possible. */
-	volatile bool poll_stop;
-	fibril_mutex_t poll_guard;
-	fibril_condvar_t poll_cv;
 };
 
@@ -91,5 +86,4 @@
 extern int usb_hub_device_add(usb_device_t *);
 extern int usb_hub_device_remove(usb_device_t *);
-extern int usb_hub_device_removed(usb_device_t *);
 extern int usb_hub_device_gone(usb_device_t *);
 
Index: uspace/drv/bus/usb/usbmid/main.c
===================================================================
--- uspace/drv/bus/usb/usbmid/main.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/bus/usb/usbmid/main.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -56,4 +56,25 @@
 }
 
+static int destroy_interfaces(usb_mid_t *usb_mid)
+{
+	int ret = EOK;
+
+	while (!list_empty(&usb_mid->interface_list)) {
+		link_t *item = list_first(&usb_mid->interface_list);
+		list_remove(item);
+
+		usbmid_interface_t *iface = usbmid_interface_from_link(item);
+
+		const int pret = usbmid_interface_destroy(iface);
+		if (pret != EOK) {
+			usb_log_error("Failed to remove child `%s': %s\n",
+			    ddf_fun_get_name(iface->fun), str_error(pret));
+			ret = pret;
+		}
+	}
+
+	return ret;
+}
+
 /** Callback when a MID device is about to be removed from the host.
  *
@@ -90,35 +111,4 @@
 	}
 
-	return ret;
-}
-
-static int destroy_interfaces(usb_mid_t *usb_mid)
-{
-	int ret = EOK;
-
-	while (!list_empty(&usb_mid->interface_list)) {
-		link_t *item = list_first(&usb_mid->interface_list);
-		list_remove(item);
-
-		usbmid_interface_t *iface = usbmid_interface_from_link(item);
-
-		const int pret = usbmid_interface_destroy(iface);
-		if (pret != EOK) {
-			usb_log_error("Failed to remove child `%s': %s\n",
-			    ddf_fun_get_name(iface->fun), str_error(pret));
-			ret = pret;
-		}
-	}
-
-	return ret;
-}
-
-static int usbmid_device_removed(usb_device_t *dev)
-{
-	assert(dev);
-	usb_mid_t *usb_mid = usb_device_data_get(dev);
-	assert(usb_mid);
-
-	/* Children are offline. Destroy them now. */
 	return destroy_interfaces(usb_mid);
 }
@@ -166,5 +156,4 @@
 	.device_add = usbmid_device_add,
 	.device_remove = usbmid_device_remove,
-	.device_removed = usbmid_device_removed,
 	.device_gone = usbmid_device_gone,
 	.function_online = usbmid_function_online,
Index: uspace/drv/hid/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/hid/usbhid/generic/hiddev.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/hid/usbhid/generic/hiddev.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -220,5 +220,5 @@
 {
 	/* Continue polling until the device is about to be removed. */
-	return !hid_dev->poll_stop;
+	return true;
 }
 
Index: uspace/drv/hid/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/hid/usbhid/kbd/kbddev.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/hid/usbhid/kbd/kbddev.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -710,5 +710,5 @@
 
 	/* Continue polling until the device is about to be removed. */
-	return !hid_dev->poll_stop;
+	return true;
 }
 
Index: uspace/drv/hid/usbhid/main.c
===================================================================
--- uspace/drv/hid/usbhid/main.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/hid/usbhid/main.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -40,5 +40,4 @@
 #include <errno.h>
 #include <str_error.h>
-#include <fibril_synch.h>
 
 #include <usb/dev/driver.h>
@@ -117,4 +116,20 @@
 }
 
+static int join_and_clean(usb_device_t *dev)
+{
+	assert(dev);
+	usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
+	assert(hid_dev);
+
+	/* Join polling fibril. */
+	usb_device_poll_join(hid_dev->polling);
+
+	/* Clean up. */
+	usb_hid_deinit(hid_dev);
+	usb_log_info("%s destruction complete.\n", usb_device_get_name(dev));
+
+	return EOK;
+}
+
 /**
  * Callback for a device about to be removed from the driver.
@@ -129,42 +144,5 @@
 	assert(hid_dev);
 
-	usb_log_info("%s will be removed, setting remove flag.\n", usb_device_get_name(dev));
-	usb_hid_prepare_deinit(hid_dev);
-
-	return EOK;
-}
-
-static int join_and_clean(usb_device_t *dev)
-{
-	assert(dev);
-	usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
-	assert(hid_dev);
-
-	/* Join polling fibril. */
-	fibril_mutex_lock(&hid_dev->poll_guard);
-	while (hid_dev->running)
-		fibril_condvar_wait(&hid_dev->poll_cv, &hid_dev->poll_guard);
-	fibril_mutex_unlock(&hid_dev->poll_guard);
-
-	/* Clean up. */
-	usb_hid_deinit(hid_dev);
-	usb_log_info("%s destruction complete.\n", usb_device_get_name(dev));
-
-	return EOK;
-}
-
-/**
- * Callback for when a device has just been from the driver.
- *
- * @param dev Structure representing the device.
- * @return Error code.
- */
-static int usb_hid_device_removed(usb_device_t *dev)
-{
-	assert(dev);
-	usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
-	assert(hid_dev);
-
-	usb_log_info("%s endpoints unregistered, joining polling fibril.\n", usb_device_get_name(dev));
+	usb_log_info("Device %s removed.\n", usb_device_get_name(dev));
 	return join_and_clean(dev);
 }
@@ -182,6 +160,5 @@
 	assert(hid_dev);
 
-	usb_log_info("Device %s gone, joining the polling fibril.\n", usb_device_get_name(dev));
-	usb_hid_prepare_deinit(hid_dev);
+	usb_log_info("Device %s gone.\n", usb_device_get_name(dev));
 	return join_and_clean(dev);
 }
@@ -191,5 +168,4 @@
 	.device_add = usb_hid_device_add,
 	.device_remove = usb_hid_device_remove,
-	.device_removed = usb_hid_device_removed,
 	.device_gone = usb_hid_device_gone,
 };
Index: uspace/drv/hid/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/hid/usbhid/mouse/mousedev.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/hid/usbhid/mouse/mousedev.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -415,5 +415,5 @@
 
 	/* Continue polling until the device is about to be removed. */
-	return !hid_dev->poll_stop;
+	return true;
 }
 
Index: uspace/drv/hid/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/hid/usbhid/multimedia/multimedia.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/hid/usbhid/multimedia/multimedia.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -246,5 +246,5 @@
 	usb_hid_report_path_t *path = usb_hid_report_path();
 	if (path == NULL)
-		return !hid_dev->poll_stop; /* This might be a temporary failure. */
+		return true; /* This might be a temporary failure. */
 
 	int ret =
@@ -252,5 +252,5 @@
 	if (ret != EOK) {
 		usb_hid_report_path_free(path);
-		return !hid_dev->poll_stop; /* This might be a temporary failure. */
+		return true; /* This might be a temporary failure. */
 	}
 
@@ -284,5 +284,5 @@
 	usb_hid_report_path_free(path);
 
-	return !hid_dev->poll_stop;
+	return true;
 }
 /**
Index: uspace/drv/hid/usbhid/usbhid.c
===================================================================
--- uspace/drv/hid/usbhid/usbhid.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/hid/usbhid/usbhid.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -355,8 +355,4 @@
 	hid_dev->poll_pipe_mapping = NULL;
 
-	hid_dev->poll_stop = false;
-	fibril_mutex_initialize(&hid_dev->poll_guard);
-	fibril_condvar_initialize(&hid_dev->poll_cv);
-
 	int rc = usb_hid_check_pipes(hid_dev, dev);
 	if (rc != EOK) {
@@ -506,5 +502,5 @@
 
 	/* Continue polling until the device is about to be removed. */
-	return hid_dev->running && !hid_dev->poll_stop;
+	return hid_dev->running;
 }
 
@@ -524,9 +520,4 @@
 
 	hid_dev->running = false;
-
-	/* Signal polling end to joining thread. */
-	fibril_mutex_lock(&hid_dev->poll_guard);
-	fibril_condvar_signal(&hid_dev->poll_cv);
-	fibril_mutex_unlock(&hid_dev->poll_guard);
 }
 
@@ -539,10 +530,4 @@
 {
 	return hid_dev->report_nr;
-}
-
-void usb_hid_prepare_deinit(usb_hid_dev_t *hid_dev)
-{
-	assert(hid_dev);
-	hid_dev->poll_stop = true;
 }
 
Index: uspace/drv/hid/usbhid/usbhid.h
===================================================================
--- uspace/drv/hid/usbhid/usbhid.h	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/drv/hid/usbhid/usbhid.h	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -46,5 +46,4 @@
 #include <usb/hid/hid.h>
 #include <stdbool.h>
-#include <fibril_synch.h>
 
 typedef struct usb_hid_dev usb_hid_dev_t;
@@ -135,11 +134,4 @@
 	int report_nr;
 	volatile bool running;
-
-	/** True if polling should stop as soon as possible */
-	volatile bool poll_stop;
-
-	/** Synchronization primitives for joining polling end. */
-	fibril_mutex_t poll_guard;
-	fibril_condvar_t poll_cv;
 };
 
@@ -147,6 +139,4 @@
 
 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
-
-void usb_hid_prepare_deinit(usb_hid_dev_t *hid_dev);
 
 void usb_hid_deinit(usb_hid_dev_t *hid_dev);
Index: uspace/lib/usbdev/include/usb/dev/driver.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/driver.h	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/lib/usbdev/include/usb/dev/driver.h	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -46,6 +46,4 @@
 	/** Callback when a device is about to be removed from the system. */
 	int (*device_remove)(usb_device_t *);
-	/** Callback when a device has just been removed from the system (optional). */
-	int (*device_removed)(usb_device_t *);
 	/** Callback when a device was removed from the system. */
 	int (*device_gone)(usb_device_t *);
Index: uspace/lib/usbdev/src/driver.c
===================================================================
--- uspace/lib/usbdev/src/driver.c	(revision 8a0c52aeaaac4a9b56e38889ad9b3f7105544319)
+++ uspace/lib/usbdev/src/driver.c	(revision 91173333ffad8030d872b4bac54acc3311e9e3c1)
@@ -94,12 +94,4 @@
 		return ret;
 
-	/* Notify the driver after endpoints were unregistered. */
-	usb_device_destroy_pipes(usb_dev);
-	if (driver->ops->device_removed != NULL) {
-		ret = driver->ops->device_removed(usb_dev);
-		if (ret != EOK)
-			return ret;
-	}
-
 	usb_device_destroy_ddf(gen_dev);
 	return EOK;
