Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 33fc3aeab329e1c9379060b6ba8f5568ad21d9fa)
+++ uspace/srv/devman/devman.c	(revision affaf2e32d63acee2b44deef78a9bc2876c0cde3)
@@ -1052,5 +1052,4 @@
 }
 
-
 /** Find the device node structure of the device witch has the specified handle.
  *
@@ -1142,4 +1141,5 @@
 	fun->state = FUN_INIT;
 	atomic_set(&fun->refcnt, 0);
+	fibril_mutex_initialize(&fun->busy_lock);
 	link_initialize(&fun->dev_functions);
 	list_initialize(&fun->match_ids.ids);
@@ -1184,4 +1184,16 @@
 	if (atomic_predec(&fun->refcnt) == 0)
 		delete_fun_node(fun);
+}
+
+/** Make function busy for reconfiguration operations. */
+void fun_busy_lock(fun_node_t *fun)
+{
+	fibril_mutex_lock(&fun->busy_lock);
+}
+
+/** Mark end of reconfiguration operation. */
+void fun_busy_unlock(fun_node_t *fun)
+{
+	fibril_mutex_unlock(&fun->busy_lock);
 }
 
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 33fc3aeab329e1c9379060b6ba8f5568ad21d9fa)
+++ uspace/srv/devman/devman.h	(revision affaf2e32d63acee2b44deef78a9bc2876c0cde3)
@@ -174,4 +174,6 @@
 	/** State */
 	fun_state_t state;
+	/** Locked while performing reconfiguration operations */
+	fibril_mutex_t busy_lock;
 	
 	/** The global unique identifier of the function */
@@ -279,4 +281,5 @@
 extern void dev_add_ref(dev_node_t *);
 extern void dev_del_ref(dev_node_t *);
+
 extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree,
     devman_handle_t handle);
@@ -290,4 +293,6 @@
 extern void fun_add_ref(fun_node_t *);
 extern void fun_del_ref(fun_node_t *);
+extern void fun_busy_lock(fun_node_t *);
+extern void fun_busy_unlock(fun_node_t *);
 extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree,
     devman_handle_t handle);
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 33fc3aeab329e1c9379060b6ba8f5568ad21d9fa)
+++ uspace/srv/devman/main.c	(revision affaf2e32d63acee2b44deef78a9bc2876c0cde3)
@@ -432,10 +432,20 @@
 	
 	fun_node_t *fun = create_fun_node();
+	/* One reference for creation, one for us */
+	fun_add_ref(fun);
 	fun_add_ref(fun);
 	fun->ftype = ftype;
+	
+	/*
+	 * We can lock the function here even when holding the tree because
+	 * we know it cannot be held by anyone else yet.
+	 */
+	fun_busy_lock(fun);
 	
 	if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
 		dev_del_ref(pdev);
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
 		delete_fun_node(fun);
 		async_answer_0(callid, ENOMEM);
@@ -450,8 +460,13 @@
 	rc = online_function(fun);
 	if (rc != EOK) {
-		/* XXX clean up */
+		/* XXX Set some failed state? */
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
 		async_answer_0(callid, rc);
 		return;
 	}
+	
+	fun_busy_unlock(fun);
+	fun_del_ref(fun);
 	
 	/* Return device handle to parent's driver. */
@@ -522,7 +537,10 @@
 	}
 	
+	fun_busy_lock(fun);
+	
 	fibril_rwlock_read_lock(&device_tree.rwlock);
 	if (fun->dev == NULL || fun->dev->drv != drv) {
 		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		fun_busy_unlock(fun);
 		fun_del_ref(fun);
 		async_answer_0(iid, ENOENT);
@@ -533,4 +551,5 @@
 	rc = online_function(fun);
 	if (rc != EOK) {
+		fun_busy_unlock(fun);
 		fun_del_ref(fun);
 		async_answer_0(iid, (sysarg_t) rc);
@@ -538,4 +557,5 @@
 	}
 	
+	fun_busy_unlock(fun);
 	fun_del_ref(fun);
 	
@@ -559,6 +579,9 @@
 	}
 	
+	fun_busy_lock(fun);
+	
 	fibril_rwlock_write_lock(&device_tree.rwlock);
 	if (fun->dev == NULL || fun->dev->drv != drv) {
+		fun_busy_unlock(fun);
 		fun_del_ref(fun);
 		async_answer_0(iid, ENOENT);
@@ -569,4 +592,5 @@
 	rc = offline_function(fun);
 	if (rc != EOK) {
+		fun_busy_unlock(fun);
 		fun_del_ref(fun);
 		async_answer_0(iid, (sysarg_t) rc);
@@ -574,4 +598,5 @@
 	}
 	
+	fun_busy_unlock(fun);
 	fun_del_ref(fun);
 	async_answer_0(iid, (sysarg_t) EOK);
@@ -591,4 +616,6 @@
 	}
 	
+	fun_busy_lock(fun);
+	
 	fibril_rwlock_write_lock(&tree->rwlock);
 	
@@ -598,4 +625,6 @@
 	if (fun->state == FUN_REMOVED) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
 		async_answer_0(callid, ENOENT);
 		return;
@@ -638,4 +667,6 @@
 				if (gone_rc == EOK)
 					gone_rc = ENOTSUP;
+				fun_busy_unlock(fun);
+				fun_del_ref(fun);
 				async_answer_0(callid, gone_rc);
 				return;
@@ -664,4 +695,5 @@
 				    "service.");
 				fibril_rwlock_write_unlock(&tree->rwlock);
+				fun_busy_unlock(fun);
 				fun_del_ref(fun);
 				async_answer_0(callid, EIO);
@@ -673,4 +705,5 @@
 	remove_fun_node(&device_tree, fun);
 	fibril_rwlock_write_unlock(&tree->rwlock);
+	fun_busy_unlock(fun);
 	
 	/* Delete ref added when inserting function into tree */
