Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 2edcb63b48c6f5a75d9ee64650edb25a41140cea)
+++ uspace/lib/c/generic/devman.c	(revision 398c4d7d49f35ea8c23f7957b353aad549ad55a9)
@@ -116,7 +116,8 @@
 {
 	ipc_call_t answer;
-	async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, &answer);
+	aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, &answer);
 	int retval = async_data_write_start(phone, match_id->id, str_size(match_id->id));
-	return retval;	
+	async_wait_for(req, NULL);
+	return retval;
 }
 
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 2edcb63b48c6f5a75d9ee64650edb25a41140cea)
+++ uspace/srv/devman/devman.c	(revision 398c4d7d49f35ea8c23f7957b353aad549ad55a9)
@@ -520,5 +520,5 @@
 	fibril_mutex_lock(&driver->driver_mutex);
 
-	phone = ipc_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
+	phone = async_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
 
 	if (phone < 0) {
@@ -583,4 +583,5 @@
 	 * immediately and possibly started here as well.
 	 */
+	printf(NAME ": driver %s goes into running state.\n", driver->name);
 	driver->state = DRIVER_RUNNING;
 
@@ -712,5 +713,5 @@
 		/* TODO handle error */
 	}
-	
+
 	/* Wait for answer from the driver. */
 	async_wait_for(req, &rc);
@@ -755,12 +756,18 @@
 	attach_driver(node, drv);
 	
+	fibril_mutex_lock(&drv->driver_mutex);
 	if (drv->state == DRIVER_NOT_STARTED) {
 		/* Start the driver. */
 		start_driver(drv);
 	}
-	
-	if (drv->state == DRIVER_RUNNING) {
+	fibril_mutex_unlock(&drv->driver_mutex);
+	
+	fibril_mutex_lock(&drv->driver_mutex);
+	bool is_running = drv->state == DRIVER_RUNNING;
+	fibril_mutex_unlock(&drv->driver_mutex);
+
+	if (is_running) {
 		/* Notify the driver about the new device. */
-		int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
+		int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
 		if (phone > 0) {
 			add_device(phone, drv, node, tree);
@@ -924,5 +931,4 @@
 	node->name = dev_name;
 	if (!set_dev_path(node, parent)) {
-		fibril_rwlock_write_unlock(&tree->rwlock);
 		return false;
 	}
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 2edcb63b48c6f5a75d9ee64650edb25a41140cea)
+++ uspace/srv/devman/main.c	(revision 398c4d7d49f35ea8c23f7957b353aad549ad55a9)
@@ -197,4 +197,11 @@
 }
 
+static int assign_driver_fibril(void *arg)
+{
+	node_t *node = (node_t *) arg;
+	assign_driver(node, &drivers_list, &device_tree);
+	return EOK;
+}
+
 /** Handle child device registration.
  *
@@ -237,10 +244,25 @@
 	
 	devman_receive_match_ids(match_count, &node->match_ids);
-	
+
+	/*
+	 * Try to find suitable driver and assign it to the device.
+	 * We do not want to block current fibril that is used to processing
+	 * incoming calls: we will launch a separate fibril to handle
+	 * the driver assigning. That is because assign_driver can actually
+	 * include task spawning which could take some time.
+	 */
+	fid_t assign_fibril = fibril_create(assign_driver_fibril, node);
+	if (assign_fibril == 0) {
+		/*
+		 * Fallback in case we are out of memory.
+		 * Probably not needed as we will die soon anyway ;-).
+		 */
+		(void) assign_driver_fibril(node);
+	} else {
+		fibril_add_ready(assign_fibril);
+	}
+
 	/* Return device handle to parent's driver. */
 	ipc_answer_1(callid, EOK, node->handle);
-	
-	/* Try to find suitable driver and assign it to the device. */
-	assign_driver(node, &drivers_list, &device_tree);
 }
 
@@ -297,5 +319,5 @@
 	printf(NAME ": device '%s' added to class '%s', class name '%s' was "
 	    "asigned to it\n", dev->pathname, class_name, class_info->dev_name);
-	
+
 	ipc_answer_0(callid, EOK);
 }
