Index: uspace/drv/infrastructure/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision 1a5b2521ea58a25aa1f13d0850fa06ae93fba965)
+++ uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision 6641295fbdfb911a7ebc3925355a330624ef110f)
@@ -63,4 +63,5 @@
 
 static int rootvirt_add_device(ddf_dev_t *dev);
+static int rootvirt_dev_remove(ddf_dev_t *dev);
 static int rootvirt_fun_online(ddf_fun_t *fun);
 static int rootvirt_fun_offline(ddf_fun_t *fun);
@@ -68,4 +69,5 @@
 static driver_ops_t rootvirt_ops = {
 	.add_device = &rootvirt_add_device,
+	.dev_remove = &rootvirt_dev_remove,
 	.fun_online = &rootvirt_fun_online,
 	.fun_offline = &rootvirt_fun_offline
@@ -77,4 +79,19 @@
 };
 
+/* Device soft state */
+typedef struct {
+	ddf_dev_t *dev;
+	list_t functions;
+} rootvirt_t;
+
+/* Function soft state */
+typedef struct {
+	ddf_fun_t *fun;
+	link_t dev_link;
+} rootvirt_fun_t;
+
+static int instances = 0;
+
+
 /** Add function to the virtual device.
  *
@@ -83,7 +100,9 @@
  * @return		EOK on success or negative error code.
  */
-static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
-{
+static int rootvirt_add_fun(rootvirt_t *rootvirt, virtual_function_t *vfun)
+{
+	ddf_dev_t *vdev = rootvirt->dev;
 	ddf_fun_t *fun;
+	rootvirt_fun_t *rvfun;
 	int rc;
 
@@ -97,4 +116,14 @@
 	}
 
+	rvfun = ddf_fun_data_alloc(fun, sizeof(rootvirt_fun_t));
+	if (rvfun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating soft state for %s.",
+		    vfun->name);
+		ddf_fun_destroy(fun);
+		return ENOMEM;
+	}
+
+	rvfun->fun = fun;
+
 	rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
 	if (rc != EOK) {
@@ -113,21 +142,53 @@
 	}
 
+	list_append(&rvfun->dev_link, &rootvirt->functions);
+
 	ddf_msg(LVL_NOTE, "Registered child device `%s'", vfun->name);
 	return EOK;
 }
 
+static int rootvirt_fun_remove(rootvirt_fun_t *rvfun)
+{
+	int rc;
+	const char *name = rvfun->fun->name;
+
+	ddf_msg(LVL_DEBUG, "rootvirt_fun_remove('%s')", name);
+	rc = ddf_fun_offline(rvfun->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name);
+		return rc;
+	}
+
+	rc = ddf_fun_unbind(rvfun->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
+		return rc;
+	}
+
+	list_remove(&rvfun->dev_link);
+	ddf_fun_destroy(rvfun->fun);
+	return EOK;
+}
+
+
 static int rootvirt_add_device(ddf_dev_t *dev)
 {
-	static int instances = 0;
+	rootvirt_t *rootvirt;
 
 	/*
 	 * Allow only single instance of root virtual device.
 	 */
-	instances++;
-	if (instances > 1) {
+	if (++instances > 1) {
 		return ELIMIT;
 	}
 
 	ddf_msg(LVL_DEBUG, "add_device(handle=%d)", (int)dev->handle);
+
+	rootvirt = ddf_dev_data_alloc(dev, sizeof(rootvirt_t));
+	if (rootvirt == NULL)
+		return ENOMEM;
+
+	rootvirt->dev = dev;
+	list_initialize(&rootvirt->functions);
 
 	/*
@@ -137,8 +198,27 @@
 	virtual_function_t *vfun = virtual_functions;
 	while (vfun->name != NULL) {
-		(void) rootvirt_add_fun(dev, vfun);
+		(void) rootvirt_add_fun(rootvirt, vfun);
 		vfun++;
 	}
 
+	return EOK;
+}
+
+static int rootvirt_dev_remove(ddf_dev_t *dev)
+{
+	rootvirt_t *rootvirt = (rootvirt_t *)dev->driver_data;
+	int rc;
+
+	while (!list_empty(&rootvirt->functions)) {
+		rootvirt_fun_t *rvfun = list_get_instance(
+		    list_first(&rootvirt->functions), rootvirt_fun_t,
+			dev_link);
+
+		rc = rootvirt_fun_remove(rvfun);
+		if (rc != EOK)
+			return rc;
+	}
+
+	--instances;
 	return EOK;
 }
