}
 EXPORT_SYMBOL_GPL(vfio_uninit_group_dev);
 
+/* Release helper called by vfio_put_device() */
+void vfio_device_release(struct kref *kref)
+{
+       struct vfio_device *device =
+                       container_of(kref, struct vfio_device, kref);
+
+       vfio_uninit_group_dev(device);
+
+       /*
+        * kvfree() cannot be done here due to a life cycle mess in
+        * vfio-ccw. Before the ccw part is fixed all drivers are
+        * required to support @release and call vfio_free_device()
+        * from there.
+        */
+       device->ops->release(device);
+}
+EXPORT_SYMBOL_GPL(vfio_device_release);
+
+/*
+ * Allocate and initialize vfio_device so it can be registered to vfio
+ * core.
+ *
+ * Drivers should use the wrapper vfio_alloc_device() for allocation.
+ * @size is the size of the structure to be allocated, including any
+ * private data used by the driver.
+ *
+ * Driver may provide an @init callback to cover device private data.
+ *
+ * Use vfio_put_device() to release the structure after success return.
+ */
+struct vfio_device *_vfio_alloc_device(size_t size, struct device *dev,
+                                      const struct vfio_device_ops *ops)
+{
+       struct vfio_device *device;
+       int ret;
+
+       if (WARN_ON(size < sizeof(struct vfio_device)))
+               return ERR_PTR(-EINVAL);
+
+       device = kvzalloc(size, GFP_KERNEL);
+       if (!device)
+               return ERR_PTR(-ENOMEM);
+
+       ret = vfio_init_device(device, dev, ops);
+       if (ret)
+               goto out_free;
+       return device;
+
+out_free:
+       kvfree(device);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(_vfio_alloc_device);
+
+/*
+ * Initialize a vfio_device so it can be registered to vfio core.
+ *
+ * Only vfio-ccw driver should call this interface.
+ */
+int vfio_init_device(struct vfio_device *device, struct device *dev,
+                    const struct vfio_device_ops *ops)
+{
+       int ret;
+
+       vfio_init_group_dev(device, dev, ops);
+
+       if (ops->init) {
+               ret = ops->init(device);
+               if (ret)
+                       goto out_uninit;
+       }
+
+       kref_init(&device->kref);
+       return 0;
+
+out_uninit:
+       vfio_uninit_group_dev(device);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(vfio_init_device);
+
+/*
+ * The helper called by driver @release callback to free the device
+ * structure. Drivers which don't have private data to clean can
+ * simply use this helper as its @release.
+ */
+void vfio_free_device(struct vfio_device *device)
+{
+       kvfree(device);
+}
+EXPORT_SYMBOL_GPL(vfio_free_device);
+
 static struct vfio_group *vfio_noiommu_group_alloc(struct device *dev,
                enum vfio_group_type type)
 {
 
        struct kvm *kvm;
 
        /* Members below here are private, not for driver use */
-       refcount_t refcount;
+       struct kref kref;       /* object life cycle */
+       refcount_t refcount;    /* user count on registered device*/
        unsigned int open_count;
        struct completion comp;
        struct list_head group_next;
 /**
  * struct vfio_device_ops - VFIO bus driver device callbacks
  *
+ * @init: initialize private fields in device structure
+ * @release: Reclaim private fields in device structure
  * @open_device: Called when the first file descriptor is opened for this device
  * @close_device: Opposite of open_device
  * @read: Perform read(2) on device file descriptor
  */
 struct vfio_device_ops {
        char    *name;
+       int     (*init)(struct vfio_device *vdev);
+       void    (*release)(struct vfio_device *vdev);
        int     (*open_device)(struct vfio_device *vdev);
        void    (*close_device)(struct vfio_device *vdev);
        ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
        return 1;
 }
 
+struct vfio_device *_vfio_alloc_device(size_t size, struct device *dev,
+                                      const struct vfio_device_ops *ops);
+#define vfio_alloc_device(dev_struct, member, dev, ops)                                \
+       container_of(_vfio_alloc_device(sizeof(struct dev_struct) +             \
+                                       BUILD_BUG_ON_ZERO(offsetof(             \
+                                               struct dev_struct, member)),    \
+                                       dev, ops),                              \
+                    struct dev_struct, member)
+
+int vfio_init_device(struct vfio_device *device, struct device *dev,
+                    const struct vfio_device_ops *ops);
+void vfio_free_device(struct vfio_device *device);
+void vfio_device_release(struct kref *kref);
+static inline void vfio_put_device(struct vfio_device *device)
+{
+       kref_put(&device->kref, vfio_device_release);
+}
+
 void vfio_init_group_dev(struct vfio_device *device, struct device *dev,
                         const struct vfio_device_ops *ops);
 void vfio_uninit_group_dev(struct vfio_device *device);