diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 4a23c13..7c70753 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -7,4 +7,4 @@ obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
 obj-$(CONFIG_VFIO_PCI) += pci/
 obj-$(CONFIG_VFIO_PLATFORM) += platform/
-obj-$(CONFIG_VFIO_MDEV) += mdev/
+obj-$(CONFIG_MDEV) += mdev/
diff --git a/drivers/vfio/mdev/Kconfig b/drivers/vfio/mdev/Kconfig
index 703abd0..d25439f 100644
--- a/drivers/vfio/mdev/Kconfig
+++ b/drivers/vfio/mdev/Kconfig
@@ -1,5 +1,5 @@
 
-config VFIO_MDEV
+config MDEV
     tristate "Mediated device driver framework"
     depends on VFIO
     default n
@@ -8,11 +8,3 @@ config VFIO_MDEV
 	See Documentation/vfio-mediated-device.txt for more details.
 
         If you don't know what do here, say N.
-
-config VFIO_MDEV_DEVICE
-    tristate "VFIO support for Mediated devices"
-    depends on VFIO && VFIO_MDEV
-    default n
-    help
-        VFIO based driver for mediated devices.
-
diff --git a/drivers/vfio/mdev/Makefile b/drivers/vfio/mdev/Makefile
index e5087ed..8bd78b5 100644
--- a/drivers/vfio/mdev/Makefile
+++ b/drivers/vfio/mdev/Makefile
@@ -1,6 +1,4 @@
 
 mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o
 
-obj-$(CONFIG_VFIO_MDEV) += mdev.o
-obj-$(CONFIG_VFIO_MDEV_DEVICE) += vfio_mdev.o
-
+obj-$(CONFIG_MDEV) += mdev.o
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 9f278c7..cb27ccf 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -5,6 +5,11 @@
  *     Author: Neo Jia <cjia@nvidia.com>
  *	       Kirti Wankhede <kwankhede@nvidia.com>
  *
+ * Copyright (c) 2016 Intel Corporation.
+ * Author:
+ *	Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *	Jike Song <jike.song@intel.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -23,316 +28,144 @@
 
 #include "mdev_private.h"
 
-#define DRIVER_VERSION		"0.1"
+#define DRIVER_VERSION		"0.2"
 #define DRIVER_AUTHOR		"NVIDIA Corporation"
-#define DRIVER_DESC		"Mediated device Core Driver"
-
-static LIST_HEAD(parent_list);
-static DEFINE_MUTEX(parent_list_lock);
-
-static int mdev_add_attribute_group(struct device *dev,
-				    const struct attribute_group **groups)
-{
-	return sysfs_create_groups(&dev->kobj, groups);
-}
-
-static void mdev_remove_attribute_group(struct device *dev,
-					const struct attribute_group **groups)
-{
-	sysfs_remove_groups(&dev->kobj, groups);
-}
-
-/* Should be called holding parent->mdev_list_lock */
-static struct mdev_device *__find_mdev_device(struct parent_device *parent,
-					      uuid_le uuid)
-{
-	struct mdev_device *mdev;
-
-	list_for_each_entry(mdev, &parent->mdev_list, next) {
-		if (uuid_le_cmp(mdev->uuid, uuid) == 0)
-			return mdev;
-	}
-	return NULL;
-}
-
-/* Should be called holding parent_list_lock */
-static struct parent_device *__find_parent_device(struct device *dev)
-{
-	struct parent_device *parent;
-
-	list_for_each_entry(parent, &parent_list, next) {
-		if (parent->dev == dev)
-			return parent;
-	}
-	return NULL;
-}
+#define DRIVER_DESC		"Mediated Device Core Driver"
 
-static void mdev_release_parent(struct kref *kref)
-{
-	struct parent_device *parent = container_of(kref, struct parent_device,
-						    ref);
-	kfree(parent);
-}
 
-static
-inline struct parent_device *mdev_get_parent(struct parent_device *parent)
+static int __find_mdev_device(struct device *dev, void *data)
 {
-	if (parent)
-		kref_get(&parent->ref);
-
-	return parent;
-}
+	struct mdev_device *mdev = dev_to_mdev(dev);
 
-static inline void mdev_put_parent(struct parent_device *parent)
-{
-	if (parent)
-		kref_put(&parent->ref, mdev_release_parent);
+	return (uuid_le_cmp(mdev->uuid, *(uuid_le *)data) == 0);
 }
 
-static struct parent_device *mdev_get_parent_from_dev(struct device *dev)
+static struct mdev_device *find_mdev_device(struct mdev_host *host,
+					    uuid_le uuid)
 {
-	struct parent_device *parent;
+	struct device *dev;
 
-	mutex_lock(&parent_list_lock);
-	parent = mdev_get_parent(__find_parent_device(dev));
-	mutex_unlock(&parent_list_lock);
+	dev = device_find_child(&host->dev, &uuid, __find_mdev_device);
+	if (!dev)
+		return NULL;
 
-	return parent;
+	return dev_to_mdev(dev);
 }
 
 static int mdev_device_create_ops(struct mdev_device *mdev, char *mdev_params)
 {
-	struct parent_device *parent = mdev->parent;
-	int ret;
-
-	ret = parent->ops->create(mdev, mdev_params);
-	if (ret)
-		return ret;
-
-	ret = mdev_add_attribute_group(&mdev->dev,
-					parent->ops->mdev_attr_groups);
-	if (ret)
-		parent->ops->destroy(mdev);
+	struct mdev_host *host = dev_to_host(mdev->dev.parent);
 
-	return ret;
+	return host->ops->create(mdev, mdev_params);
 }
 
-static int mdev_device_destroy_ops(struct mdev_device *mdev, bool force)
+static void mdev_device_destroy_ops(struct mdev_device *mdev)
 {
-	struct parent_device *parent = mdev->parent;
-	int ret = 0;
+	struct mdev_host *host = dev_to_host(mdev->dev.parent);
 
-	/*
-	 * If vendor driver doesn't return success that means vendor
-	 * driver doesn't support hot-unplug
-	 */
-	ret = parent->ops->destroy(mdev);
-	if (ret && !force)
-		return -EBUSY;
-
-	mdev_remove_attribute_group(&mdev->dev,
-				    parent->ops->mdev_attr_groups);
-
-	return ret;
-}
-
-static void mdev_release_device(struct kref *kref)
-{
-	struct mdev_device *mdev = container_of(kref, struct mdev_device, ref);
-	struct parent_device *parent = mdev->parent;
-
-	list_del(&mdev->next);
-
-	/*
-	 * This unlock pairs with mutex held by mdev_put_device() through
-	 * kref_put_mutex()
-	 */
-	mutex_unlock(&parent->mdev_list_lock);
-
-	device_unregister(&mdev->dev);
-	wake_up(&parent->release_done);
-	mdev_put_parent(parent);
-}
-
-struct mdev_device *mdev_get_device(struct mdev_device *mdev)
-{
-	if (mdev)
-		kref_get(&mdev->ref);
-	return mdev;
+	host->ops->destroy(mdev);
 }
-EXPORT_SYMBOL(mdev_get_device);
-
-void mdev_put_device(struct mdev_device *mdev)
-{
-	struct parent_device *parent;
-
-	if (!mdev)
-		return;
-
-	parent = mdev->parent;
-	kref_put_mutex(&mdev->ref, mdev_release_device,
-		       &parent->mdev_list_lock);
-}
-EXPORT_SYMBOL(mdev_put_device);
 
 /*
- * mdev_register_device : Register a device
- * @dev: device structure representing parent device.
+ * mdev_register_host_device : register a mdev host device
+ * @dev: device structure of the physical device under which the created
+ *       host device will be.
  * @ops: Parent device operation structure to be registered.
  *
- * Add device to list of registered parent devices.
- * Returns a negative value on error, otherwise 0.
+ * Register a mdev host device as the mediator of mdev devices.
+ * Returns the pointer of mdev host device structure for success, NULL
+ * for errors.
  */
-int mdev_register_device(struct device *dev, const struct parent_ops *ops)
+struct mdev_host *mdev_register_host_device(struct device *pdev,
+				const struct mdev_host_ops *ops)
 {
-	int ret = 0;
-	struct parent_device *parent;
+	int rc = 0;
+	struct mdev_host *host;
 
-	if (!dev || !ops)
-		return -EINVAL;
+	if (!pdev || !ops) {
+		dev_warn(pdev, "dev or ops is NULL\n");
+		return NULL;
+	}
 
 	/* check for mandatory ops */
-	if (!ops->create || !ops->destroy)
-		return -EINVAL;
-
-	mutex_lock(&parent_list_lock);
-
-	/* Check for duplicate */
-	parent = __find_parent_device(dev);
-	if (parent) {
-		ret = -EEXIST;
-		goto add_dev_err;
+	if (!ops->create || !ops->destroy) {
+		dev_warn(pdev, "create and destroy methods are necessary\n");
+		return NULL;
 	}
 
-	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
-	if (!parent) {
-		ret = -ENOMEM;
-		goto add_dev_err;
-	}
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
 
-	kref_init(&parent->ref);
-	list_add(&parent->next, &parent_list);
+	host->dev.parent = pdev;
+	host->ops = ops;
+	dev_set_name(&host->dev, "mdev-host");
 
-	parent->dev = dev;
-	parent->ops = ops;
-	mutex_init(&parent->mdev_list_lock);
-	INIT_LIST_HEAD(&parent->mdev_list);
-	init_waitqueue_head(&parent->release_done);
-	mutex_unlock(&parent_list_lock);
+	rc = device_register(&host->dev);
+	if (rc)
+		goto register_error;
 
-	ret = parent_create_sysfs_files(dev);
-	if (ret)
+	rc = mdev_create_sysfs_files(&host->dev);
+	if (rc)
 		goto add_sysfs_error;
 
-	ret = mdev_add_attribute_group(dev, ops->dev_attr_groups);
-	if (ret)
+	rc = sysfs_create_groups(&host->dev.kobj, ops->hdev_attr_groups);
+	if (rc)
 		goto add_group_error;
 
-	dev_info(dev, "MDEV: Registered\n");
-	return 0;
+	dev_info(&host->dev, "mdev host device registered\n");
+	return host;
 
 add_group_error:
-	mdev_remove_sysfs_files(dev);
+	mdev_remove_sysfs_files(&host->dev);
+
 add_sysfs_error:
-	mutex_lock(&parent_list_lock);
-	list_del(&parent->next);
-	mutex_unlock(&parent_list_lock);
-	mdev_put_parent(parent);
-	return ret;
+	device_unregister(&host->dev);
 
-add_dev_err:
-	mutex_unlock(&parent_list_lock);
-	return ret;
+register_error:
+	kfree(host);
+	return NULL;
 }
-EXPORT_SYMBOL(mdev_register_device);
-
-/*
- * mdev_unregister_device : Unregister a parent device
- * @dev: device structure representing parent device.
- *
- * Remove device from list of registered parent devices. Give a chance to free
- * existing mediated devices for given device.
- */
+EXPORT_SYMBOL(mdev_register_host_device);
 
-void mdev_unregister_device(struct device *dev)
+static int __mdev_device_destroy(struct device *dev, void *data)
 {
-	struct parent_device *parent;
-	struct mdev_device *mdev = NULL;
-	int ret;
+	struct mdev_device *mdev = dev_to_mdev(dev);
 
-	mutex_lock(&parent_list_lock);
-	parent = __find_parent_device(dev);
-
-	if (!parent) {
-		mutex_unlock(&parent_list_lock);
-		return;
-	}
-	dev_info(dev, "MDEV: Unregistering\n");
-
-	/*
-	 * Remove parent from the list and remove "mdev_create" and
-	 * "mdev_destroy" sysfs files so that no new mediated device could be
-	 * created for this parent
-	 */
-	list_del(&parent->next);
-	parent_remove_sysfs_files(dev);
-	mutex_unlock(&parent_list_lock);
-
-	mdev_remove_attribute_group(dev,
-				    parent->ops->dev_attr_groups);
-
-	while (!list_empty(&parent->mdev_list)) {
-		mutex_lock(&parent->mdev_list_lock);
-		if (!list_empty(&parent->mdev_list)) {
-			mdev = list_first_entry(&parent->mdev_list,
-						struct mdev_device, next);
-			mdev_device_destroy_ops(mdev, true);
-		}
-		mutex_unlock(&parent->mdev_list_lock);
-
-		if (mdev)
-			mdev_put_device(mdev);
-	}
+	mdev_device_destroy_ops(mdev);
+	device_unregister(&mdev->dev);
 
-	do {
-		ret = wait_event_interruptible_timeout(parent->release_done,
-				list_empty(&parent->mdev_list), HZ * 10);
-		if (ret == -ERESTARTSYS) {
-			dev_warn(dev, "Mediated devices are in use, task"
-				      " \"%s\" (%d) "
-				      "blocked until all are released",
-				      current->comm, task_pid_nr(current));
-		}
-	} while (ret <= 0);
-
-	mdev_put_parent(parent);
+	return 0;
 }
-EXPORT_SYMBOL(mdev_unregister_device);
 
 /*
- * Functions required for mdev_sysfs
+ * mdev_unregister_host_device : unregister a mdev host device
+ * @host: the mdev host device structure
+ *
+ * Unregister a mdev host device as the mediator
  */
-static void mdev_device_release(struct device *dev)
+void mdev_unregister_host_device(struct mdev_host *host)
 {
-	struct mdev_device *mdev = to_mdev_device(dev);
+	if (!host)
+		return;
 
-	dev_dbg(&mdev->dev, "MDEV: destroying\n");
-	kfree(mdev);
+	dev_info(&host->dev, "mdev host device unregistered\n");
+
+	mdev_remove_sysfs_files(&host->dev);
+	sysfs_remove_groups(&host->dev.kobj, host->ops->hdev_attr_groups);
+	device_for_each_child(&host->dev, NULL,  __mdev_device_destroy);
+	device_unregister(&host->dev);
 }
+EXPORT_SYMBOL(mdev_unregister_host_device);
 
 int mdev_device_create(struct device *dev, uuid_le uuid, char *mdev_params)
 {
 	int ret;
 	struct mdev_device *mdev;
-	struct parent_device *parent;
-
-	parent = mdev_get_parent_from_dev(dev);
-	if (!parent)
-		return -EINVAL;
+	struct mdev_host *host = dev_to_host(dev);
 
-	mutex_lock(&parent->mdev_list_lock);
 	/* Check for duplicate */
-	mdev = __find_mdev_device(parent, uuid);
+	mdev = find_mdev_device(host, uuid);
 	if (mdev) {
 		ret = -EEXIST;
 		goto create_err;
@@ -345,12 +178,10 @@ int mdev_device_create(struct device *dev, uuid_le uuid, char *mdev_params)
 	}
 
 	memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
-	mdev->parent = parent;
-	kref_init(&mdev->ref);
 
-	mdev->dev.parent  = dev;
-	mdev->dev.bus     = &mdev_bus_type;
-	mdev->dev.release = mdev_device_release;
+	mdev->dev.parent = dev;
+	mdev->dev.bus = &mdev_bus_type;
+	mdev->dev.groups = host->ops->mdev_attr_groups;
 	dev_set_name(&mdev->dev, "%pUl", uuid.b);
 
 	ret = device_register(&mdev->dev);
@@ -363,123 +194,35 @@ int mdev_device_create(struct device *dev, uuid_le uuid, char *mdev_params)
 	if (ret)
 		goto create_failed;
 
-	ret = mdev_create_sysfs_files(&mdev->dev);
-	if (ret)
-		goto create_sysfs_error;
-
-	list_add(&mdev->next, &parent->mdev_list);
-	mutex_unlock(&parent->mdev_list_lock);
-
 	dev_dbg(&mdev->dev, "MDEV: created\n");
 
 	return ret;
 
-create_sysfs_error:
-	mdev_device_destroy_ops(mdev, true);
-
 create_failed:
 	device_unregister(&mdev->dev);
 
 create_err:
-	mutex_unlock(&parent->mdev_list_lock);
-	mdev_put_parent(parent);
 	return ret;
 }
 
 int mdev_device_destroy(struct device *dev, uuid_le uuid)
 {
 	struct mdev_device *mdev;
-	struct parent_device *parent;
-	int ret;
+	struct mdev_host *host = dev_to_host(dev);
 
-	parent = mdev_get_parent_from_dev(dev);
-	if (!parent)
+	mdev = find_mdev_device(host, uuid);
+	if (!mdev)
 		return -ENODEV;
 
-	mutex_lock(&parent->mdev_list_lock);
-	mdev = __find_mdev_device(parent, uuid);
-	if (!mdev) {
-		ret = -EINVAL;
-		goto destroy_err;
-	}
-
-	mdev_remove_sysfs_files(&mdev->dev);
-	ret = mdev_device_destroy_ops(mdev, false);
-	if (ret)
-		goto destroy_err;
-
-	mutex_unlock(&parent->mdev_list_lock);
-	mdev_put_device(mdev);
-
-	mdev_put_parent(parent);
-	return ret;
-
-destroy_err:
-	mutex_unlock(&parent->mdev_list_lock);
-	mdev_put_parent(parent);
-	return ret;
+	return __mdev_device_destroy(&mdev->dev, NULL);
 }
 
 void mdev_device_supported_config(struct device *dev, char *str)
 {
-	struct parent_device *parent;
-
-	parent = mdev_get_parent_from_dev(dev);
+	struct mdev_host *host = dev_to_host(dev);
 
-	if (parent) {
-		if (parent->ops->supported_config)
-			parent->ops->supported_config(parent->dev, str);
-		mdev_put_parent(parent);
-	}
-}
-
-int mdev_device_set_online_status(struct device *dev, bool online)
-{
-	int ret = 0;
-	struct mdev_device *mdev;
-	struct parent_device *parent;
-
-	mdev = mdev_get_device(to_mdev_device(dev));
-	if (!mdev)
-		return -EINVAL;
-
-	parent = mdev->parent;
-
-	if (parent->ops->set_online_status)
-		ret = parent->ops->set_online_status(mdev, online);
-
-	if (ret)
-		pr_err("mdev online failed  %d\n", ret);
-	else {
-		if (online)
-			kobject_uevent(&mdev->dev.kobj, KOBJ_ONLINE);
-		else
-			kobject_uevent(&mdev->dev.kobj, KOBJ_OFFLINE);
-	}
-
-	mdev_put_device(mdev);
-
-	return ret;
-}
-
-int mdev_device_get_online_status(struct device *dev, bool *online)
-{
-	int ret = 0;
-	struct mdev_device *mdev;
-	struct parent_device *parent;
-
-	mdev = mdev_get_device(to_mdev_device(dev));
-	if (!mdev)
-		return -EINVAL;
-
-	parent = mdev->parent;
-
-	if (parent->ops->get_online_status)
-		ret = parent->ops->get_online_status(mdev, online);
-
-	mdev_put_device(mdev);
-
-	return ret;
+	if (host->ops->supported_config)
+		host->ops->supported_config(&host->dev, str);
 }
 
 static int __init mdev_init(void)
@@ -487,10 +230,8 @@ static int __init mdev_init(void)
 	int ret;
 
 	ret = mdev_bus_register();
-	if (ret) {
-		pr_err("Failed to register mdev bus\n");
-		return ret;
-	}
+	if (ret)
+		pr_err("failed to register mdev bus: %d\n", ret);
 
 	return ret;
 }
diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
index 8afc2d8..d298aaf 100644
--- a/drivers/vfio/mdev/mdev_driver.c
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -5,6 +5,8 @@
  *     Author: Neo Jia <cjia@nvidia.com>
  *	       Kirti Wankhede <kwankhede@nvidia.com>
  *
+ * Copyright (c) 2016 Intel Corporation.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -52,7 +54,7 @@ static void mdev_detach_iommu(struct mdev_device *mdev)
 static int mdev_probe(struct device *dev)
 {
 	struct mdev_driver *drv = to_mdev_driver(dev->driver);
-	struct mdev_device *mdev = to_mdev_device(dev);
+	struct mdev_device *mdev = dev_to_mdev(dev);
 	int ret;
 
 	ret = mdev_attach_iommu(mdev);
@@ -73,7 +75,7 @@ static int mdev_probe(struct device *dev)
 static int mdev_remove(struct device *dev)
 {
 	struct mdev_driver *drv = to_mdev_driver(dev->driver);
-	struct mdev_device *mdev = to_mdev_device(dev);
+	struct mdev_device *mdev = dev_to_mdev(dev);
 
 	if (drv && drv->remove)
 		drv->remove(dev);
@@ -83,10 +85,32 @@ static int mdev_remove(struct device *dev)
 	return 0;
 }
 
+static int mdev_online(struct device *dev)
+{
+	struct mdev_driver *drv = to_mdev_driver(dev->driver);
+
+	if (drv && drv->online)
+		return drv->online(dev);
+
+	return 0;
+}
+
+static int mdev_offline(struct device *dev)
+{
+	struct mdev_driver *drv = to_mdev_driver(dev->driver);
+
+	if (drv && drv->offline)
+		return drv->offline(dev);
+
+	return 0;
+}
+
 struct bus_type mdev_bus_type = {
 	.name		= "mdev",
 	.probe		= mdev_probe,
 	.remove		= mdev_remove,
+	.online		= mdev_online,
+	.offline	= mdev_offline,
 };
 EXPORT_SYMBOL_GPL(mdev_bus_type);
 
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index 07ad1b3..f153292 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -5,6 +5,8 @@
  *     Author: Neo Jia <cjia@nvidia.com>
  *	       Kirti Wankhede <kwankhede@nvidia.com>
  *
+ * Copyright (c) 2016 Intel Corporation.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -17,12 +19,6 @@ int  mdev_bus_register(void);
 void mdev_bus_unregister(void);
 
 /* Function prototypes for mdev_sysfs */
-
-extern struct class_attribute mdev_class_attrs[];
-
-int  parent_create_sysfs_files(struct device *dev);
-void parent_remove_sysfs_files(struct device *dev);
-
 int  mdev_create_sysfs_files(struct device *dev);
 void mdev_remove_sysfs_files(struct device *dev);
 
@@ -30,7 +26,4 @@ int  mdev_device_create(struct device *dev, uuid_le uuid, char *mdev_params);
 int  mdev_device_destroy(struct device *dev, uuid_le uuid);
 void mdev_device_supported_config(struct device *dev, char *str);
 
-int mdev_device_set_online_status(struct device *dev, bool online);
-int mdev_device_get_online_status(struct device *dev, bool *online);
-
 #endif /* MDEV_PRIVATE_H */
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index ed55cd5..7d55188 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -5,6 +5,10 @@
  *     Author: Neo Jia <cjia@nvidia.com>
  *	       Kirti Wankhede <kwankhede@nvidia.com>
  *
+ * Copyright (c) 2016 Intel Corporation.
+ * Author:
+ *	Jike Song <jike.song@intel.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -35,17 +39,17 @@ static ssize_t mdev_destroy_store(struct device *dev,
 				  const char *buf, size_t count);
 static DEVICE_ATTR_WO(mdev_destroy);
 
-static ssize_t online_store(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count);
-static ssize_t online_show(struct device *dev, struct device_attribute *attr,
-			   char *buf);
-static DEVICE_ATTR_RW(online);
+static const struct attribute *mdev_host_attrs[] = {
+	&dev_attr_mdev_supported_types.attr,
+	&dev_attr_mdev_create.attr,
+	&dev_attr_mdev_destroy.attr,
+	NULL,
+};
 
-/* Static functions */
 
 #define SUPPORTED_TYPE_BUFFER_LENGTH	4096
 
-/* mdev sysfs Functions */
+/* mdev host sysfs functions */
 static ssize_t mdev_supported_types_show(struct device *dev,
 					 struct device_attribute *attr,
 					 char *buf)
@@ -70,25 +74,24 @@ static ssize_t mdev_create_store(struct device *dev,
 				 struct device_attribute *attr,
 				 const char *buf, size_t count)
 {
-	char *str, *pstr;
-	char *uuid_str, *mdev_params = NULL, *params = NULL;
+	char *str;
+	char *uuid_str, *params = NULL;
 	uuid_le uuid;
 	int ret;
 
-	pstr = str = kstrndup(buf, count, GFP_KERNEL);
-
+	str = kstrndup(buf, count, GFP_KERNEL);
 	if (!str)
 		return -ENOMEM;
 
 	uuid_str = strsep(&str, ":");
 	if (!uuid_str) {
-		pr_err("mdev_create: Empty UUID string %s\n", buf);
+		pr_err("mdev_create: empty UUID string %s\n", buf);
 		ret = -EINVAL;
 		goto create_error;
 	}
 
 	if (str)
-		params = mdev_params = kstrdup(str, GFP_KERNEL);
+		params = kstrdup(str, GFP_KERNEL);
 
 	ret = uuid_le_to_bin(uuid_str, &uuid);
 	if (ret) {
@@ -96,7 +99,7 @@ static ssize_t mdev_create_store(struct device *dev,
 		goto create_error;
 	}
 
-	ret = mdev_device_create(dev, uuid, mdev_params);
+	ret = mdev_device_create(dev, uuid, params);
 	if (ret)
 		pr_err("mdev_create: Failed to create mdev device\n");
 	else
@@ -104,7 +107,7 @@ static ssize_t mdev_create_store(struct device *dev,
 
 create_error:
 	kfree(params);
-	kfree(pstr);
+	kfree(str);
 	return ret;
 }
 
@@ -112,23 +115,15 @@ static ssize_t mdev_destroy_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
 {
-	char *uuid_str, *str, *pstr;
+	char *str;
 	uuid_le uuid;
 	int ret;
 
-	str = pstr = kstrndup(buf, count, GFP_KERNEL);
-
+	str = kstrndup(buf, count, GFP_KERNEL);
 	if (!str)
 		return -ENOMEM;
 
-	uuid_str = strsep(&str, ":");
-	if (!uuid_str) {
-		pr_err("mdev_destroy: Empty UUID string %s\n", buf);
-		ret = -EINVAL;
-		goto destroy_error;
-	}
-
-	ret = uuid_le_to_bin(uuid_str, &uuid);
+	ret = uuid_le_to_bin(str, &uuid);
 	if (ret) {
 		pr_err("mdev_destroy: UUID parse error  %s\n", buf);
 		goto destroy_error;
@@ -139,102 +134,22 @@ static ssize_t mdev_destroy_store(struct device *dev,
 		ret = count;
 
 destroy_error:
-	kfree(pstr);
-	return ret;
-}
-
-static ssize_t online_store(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	char *str;
-	int ret;
-	uint32_t online_status;
-	bool online;
-
-	str = kstrndup(buf, count, GFP_KERNEL);
-	if (!str)
-		return -ENOMEM;
-
-	ret = kstrtouint(str, 0, &online_status);
 	kfree(str);
-
-	if (ret) {
-		pr_err("online: parsing error %s\n", buf);
-		return ret;
-	}
-
-	online = online_status > 0 ? true : false;
-
-	ret = mdev_device_set_online_status(dev, online);
-	if (ret)
-		return ret;
-
-	return count;
-}
-
-static ssize_t online_show(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	int ret;
-	bool online = false;
-
-	ret = mdev_device_get_online_status(dev, &online);
-	if (ret)
-		return ret;
-
-	ret = sprintf(buf, "%d\n", online);
 	return ret;
 }
 
-int parent_create_sysfs_files(struct device *dev)
-{
-	int ret;
-
-	ret = sysfs_create_file(&dev->kobj,
-				&dev_attr_mdev_supported_types.attr);
-	if (ret) {
-		pr_err("Failed to create mdev_supported_types sysfs entry\n");
-		return ret;
-	}
-
-	ret = sysfs_create_file(&dev->kobj, &dev_attr_mdev_create.attr);
-	if (ret) {
-		pr_err("Failed to create mdev_create sysfs entry\n");
-		goto create_sysfs_failed;
-	}
-
-	ret = sysfs_create_file(&dev->kobj, &dev_attr_mdev_destroy.attr);
-	if (ret) {
-		pr_err("Failed to create mdev_destroy sysfs entry\n");
-		sysfs_remove_file(&dev->kobj, &dev_attr_mdev_create.attr);
-	} else
-		return ret;
-
-create_sysfs_failed:
-	sysfs_remove_file(&dev->kobj, &dev_attr_mdev_supported_types.attr);
-	return ret;
-}
-
-void parent_remove_sysfs_files(struct device *dev)
-{
-	sysfs_remove_file(&dev->kobj, &dev_attr_mdev_supported_types.attr);
-	sysfs_remove_file(&dev->kobj, &dev_attr_mdev_create.attr);
-	sysfs_remove_file(&dev->kobj, &dev_attr_mdev_destroy.attr);
-}
-
 int mdev_create_sysfs_files(struct device *dev)
 {
 	int ret;
 
-	ret = sysfs_create_file(&dev->kobj, &dev_attr_online.attr);
+	ret = sysfs_create_files(&dev->kobj, mdev_host_attrs);
 	if (ret)
-		pr_err("Failed to create 'online' entry\n");
+		pr_err("sysfs_create_files failed: %d\n", ret);
 
 	return ret;
 }
 
 void mdev_remove_sysfs_files(struct device *dev)
 {
-	sysfs_remove_file(&dev->kobj, &dev_attr_online.attr);
+	sysfs_remove_files(&dev->kobj, mdev_host_attrs);
 }
-
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index babcb72..1236200 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -5,6 +5,8 @@
  *     Author: Neo Jia <cjia@nvidia.com>
  *	       Kirti Wankhede <kwankhede@nvidia.com>
  *
+ * Copyright (c) 2016 Intel Corporation.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -15,65 +17,50 @@
 
 #include <uapi/linux/vfio.h>
 
-struct parent_device;
-
-/*
- * Mediated device
- */
 
+/* mediated device */
 struct mdev_device {
 	struct device		dev;
-	struct parent_device	*parent;
 	struct iommu_group	*group;
 	uuid_le			uuid;
 	void			*driver_data;
-
-	/* internal only */
-	struct kref		ref;
-	struct list_head	next;
 };
 
-
 /**
- * struct parent_ops - Structure to be registered for each parent device to
- * register the device to mdev module.
+ * struct mdev_host_ops - Structure to be registered for each host device to
+ * to mdev.
  *
  * @owner:		The module owner.
- * @dev_attr_groups:	Default attributes of the parent device.
- * @mdev_attr_groups:	Default attributes of the mediated device.
+ * @hdev_attr_groups:	Default attributes of the host device.
+ * @mdev_attr_groups:	Default attributes of the mdev device.
  * @supported_config:	Called to get information about supported types.
- *			@dev : device structure of parent device.
+ *			@dev : device structure of host device.
  *			@config: should return string listing supported config
  *			Returns integer: success (0) or error (< 0)
- * @create:		Called to allocate basic resources in parent device's
+ * @create:		Called to allocate basic resources in host device's
  *			driver for a particular mediated device. It is
  *			mandatory to provide create ops.
  *			@mdev: mdev_device structure on of mediated device
  *			      that is being created
- *			@mdev_params: extra parameters required by parent
+ *			@mdev_params: extra parameters required by host
  *			device's driver.
  *			Returns integer: success (0) or error (< 0)
- * @destroy:		Called to free resources in parent device's driver for a
- *			a mediated device. It is mandatory to provide destroy
- *			ops.
+ * @destroy:		Called to free resources in host device's driver for a
+ *			a mediated device instance. It is mandatory to provide
+ *			destroy ops.
  *			@mdev: mdev_device device structure which is being
- *			       destroyed
+ *				destroyed
  *			Returns integer: success (0) or error (< 0)
  *			If VMM is running and destroy() is called that means the
  *			mdev is being hotunpluged. Return error if VMM is
  *			running and driver doesn't support mediated device
  *			hotplug.
- * @reset:		Called to reset mediated device.
- *			@mdev: mdev_device device structure.
- *			Returns integer: success (0) or error (< 0)
- * @set_online_status:	Called to change to status of mediated device.
- *			@mdev: mediated device.
- *			@online: set true or false to make mdev device online or
- *			offline.
+ * @start:		Called to initiate mediated device initialization
+ *			process in host device's driver before VMM starts.
+ *			@mdev: mediated device structure
  *			Returns integer: success (0) or error (< 0)
- * @get_online_status:	Called to get online/offline status of  mediated device
- *			@mdev: mediated device.
- *			@online: Returns status of mediated device.
+ * @stop:		Called to teardown mediated device related resources
+ *			@mdev: mediated device structure
  *			Returns integer: success (0) or error (< 0)
  * @read:		Read emulation callback
  *			@mdev: mediated device structure
@@ -87,75 +74,47 @@ struct mdev_device {
  *			@count: number of bytes to be written
  *			@pos: address.
  *			Retuns number on bytes written on success or error.
- * @get_irq_info:	Called to retrieve information about mediated device IRQ
- *			@mdev: mediated device structure
- *			@irq_info: VFIO IRQ flags and count.
- *			Returns integer: success (0) or error (< 0)
- * @set_irqs:		Called to send about interrupts configuration
- *			information that VMM sets.
+ * @mmap:		Memory Map
  *			@mdev: mediated device structure
- *			@flags, index, start, count and *data : same as that of
- *			struct vfio_irq_set of VFIO_DEVICE_SET_IRQS API.
- * @get_device_info:	Called to get VFIO device information for a mediated
- *			device.
- *			@vfio_device_info: VFIO device info.
- *			Returns integer: success (0) or error (< 0)
- * @get_region_info:	Called to get VFIO region size and flags of mediated
- *			device.
- *			@mdev: mediated device structure
- *			@region_info: output, returns size and flags of
- *				      requested region.
- *			@cap_type_id: returns id of capability.
- *			@cap_type: returns pointer to capability structure
- *			corresponding to capability id.
+ *			@pos: address
+ *			@virtaddr: target user address to start at. Vendor
+ *			driver can change if required.
+ *			@pfn: host address of kernel memory, vendor driver
+ *			can change if required.
+ *			@size: size of map area, vendor driver can change the
+ *			size of map area if desired.
+ *			@prot: page protection flags for this mapping, vendor
+ *			driver can change, if required.
  *			Returns integer: success (0) or error (< 0)
  *
- * Parent device that support mediated device should be registered with mdev
- * module with parent_ops structure.
+ * Host device that support mediated device should be registered with mdev
+ * module with mdev_host_ops structure.
  */
-
-struct parent_ops {
-	struct module   *owner;
-	const struct attribute_group **dev_attr_groups;
+struct mdev_host_ops {
+	struct module *owner;
+	const struct attribute_group **hdev_attr_groups;
 	const struct attribute_group **mdev_attr_groups;
 
-	int	(*supported_config)(struct device *dev, char *config);
-	int     (*create)(struct mdev_device *mdev, char *mdev_params);
-	int     (*destroy)(struct mdev_device *mdev);
-	int     (*reset)(struct mdev_device *mdev);
-	int     (*set_online_status)(struct mdev_device *mdev, bool online);
-	int     (*get_online_status)(struct mdev_device *mdev, bool *online);
-	ssize_t (*read)(struct mdev_device *mdev, char *buf, size_t count,
-			loff_t pos);
-	ssize_t (*write)(struct mdev_device *mdev, char *buf, size_t count,
-			 loff_t pos);
-	int	(*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma);
-	int	(*get_irq_info)(struct mdev_device *mdev,
-				struct vfio_irq_info *irq_info);
-	int     (*set_irqs)(struct mdev_device *mdev, uint32_t flags,
-			    unsigned int index, unsigned int start,
-			    unsigned int count, void *data);
-	int	(*get_device_info)(struct mdev_device *mdev,
-				   struct vfio_device_info *dev_info);
-	int	(*get_region_info)(struct mdev_device *mdev,
-				   struct vfio_region_info *region_info,
-				   u16 *cap_type_id, void **cap_type);
-};
+	int (*supported_config)(struct device *dev, char *config);
+	int (*create)(struct mdev_device *mdev, char *mdev_params);
+	void (*destroy)(struct mdev_device *mdev);
 
-/*
- * Parent Device
- */
+	int (*start)(struct mdev_device *mdev);
+	int (*stop)(struct mdev_device *mdev);
 
-struct parent_device {
-	struct device		*dev;
-	const struct parent_ops	*ops;
+	ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
+			size_t count, loff_t *pos);
+	ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
+			size_t count, loff_t *pos);
+	int (*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma);
+	long (*ioctl)(struct mdev_device *mdev, unsigned int cmd,
+			unsigned long arg);
+};
 
-	/* internal */
-	struct kref		ref;
-	struct list_head	next;
-	struct list_head	mdev_list;
-	struct mutex		mdev_list_lock;
-	wait_queue_head_t	release_done;
+/* mdev host device */
+struct mdev_host {
+	struct device dev;
+	const struct mdev_host_ops *ops;
 };
 
 /**
@@ -164,25 +123,16 @@ struct parent_device {
  * @probe: called when new device created
  * @remove: called when device removed
  * @driver: device driver structure
- *
  **/
 struct mdev_driver {
 	const char *name;
-	int  (*probe)(struct device *dev);
+	int (*probe)(struct device *dev);
 	void (*remove)(struct device *dev);
+	int (*online)(struct device *dev);
+	int (*offline)(struct device *dev);
 	struct device_driver driver;
 };
 
-static inline struct mdev_driver *to_mdev_driver(struct device_driver *drv)
-{
-	return drv ? container_of(drv, struct mdev_driver, driver) : NULL;
-}
-
-static inline struct mdev_device *to_mdev_device(struct device *dev)
-{
-	return dev ? container_of(dev, struct mdev_device, dev) : NULL;
-}
-
 static inline void *mdev_get_drvdata(struct mdev_device *mdev)
 {
 	return mdev->driver_data;
@@ -195,18 +145,15 @@ static inline void mdev_set_drvdata(struct mdev_device *mdev, void *data)
 
 extern struct bus_type mdev_bus_type;
 
-#define dev_is_mdev(d) ((d)->bus == &mdev_bus_type)
-
-extern int  mdev_register_device(struct device *dev,
-				 const struct parent_ops *ops);
-extern void mdev_unregister_device(struct device *dev);
-
-extern int  mdev_register_driver(struct mdev_driver *drv, struct module *owner);
-extern void mdev_unregister_driver(struct mdev_driver *drv);
+#define to_mdev_driver(drv) container_of(drv, struct mdev_driver, driver)
+#define dev_to_host(_dev) container_of((_dev), struct mdev_host, dev)
+#define dev_to_mdev(_dev) container_of((_dev), struct mdev_device, dev)
 
-extern struct mdev_device *mdev_get_device(struct mdev_device *mdev);
-extern void mdev_put_device(struct mdev_device *mdev);
+struct mdev_host *mdev_register_host_device(struct device *dev,
+				 const struct mdev_host_ops *ops);
+void mdev_unregister_host_device(struct mdev_host *host);
 
-extern struct mdev_device *mdev_get_device_by_group(struct iommu_group *group);
+int mdev_register_driver(struct mdev_driver *drv, struct module *owner);
+void mdev_unregister_driver(struct mdev_driver *drv);
 
 #endif /* MDEV_H */
