similar to a file operations structure::
 
        struct vfio_device_ops {
-               int     (*open)(void *device_data);
-               void    (*release)(void *device_data);
-               ssize_t (*read)(void *device_data, char __user *buf,
+               int     (*open)(struct vfio_device *vdev);
+               void    (*release)(struct vfio_device *vdev);
+               ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
                                size_t count, loff_t *ppos);
-               ssize_t (*write)(void *device_data, const char __user *buf,
+               ssize_t (*write)(struct vfio_device *vdev,
+                                const char __user *buf,
                                 size_t size, loff_t *ppos);
-               long    (*ioctl)(void *device_data, unsigned int cmd,
+               long    (*ioctl)(struct vfio_device *vdev, unsigned int cmd,
                                 unsigned long arg);
-               int     (*mmap)(void *device_data, struct vm_area_struct *vma);
+               int     (*mmap)(struct vfio_device *vdev,
+                               struct vm_area_struct *vma);
        };
 
-Each function is passed the device_data that was originally registered
+Each function is passed the vdev that was originally registered
 in the vfio_register_group_dev() call above.  This allows the bus driver
-an easy place to store its opaque, private data.  The open/release
+to obtain its private data using container_of().  The open/release
 callbacks are issued when a new file descriptor is created for a
 device (via VFIO_GROUP_GET_DEVICE_FD).  The ioctl interface provides
 a direct pass through for VFIO_DEVICE_* ioctls.  The read/write/mmap
 
        kfree(vdev->regions);
 }
 
-static int vfio_fsl_mc_open(void *device_data)
+static int vfio_fsl_mc_open(struct vfio_device *core_vdev)
 {
-       struct vfio_fsl_mc_device *vdev = device_data;
+       struct vfio_fsl_mc_device *vdev =
+               container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
        int ret;
 
        if (!try_module_get(THIS_MODULE))
        return ret;
 }
 
-static void vfio_fsl_mc_release(void *device_data)
+static void vfio_fsl_mc_release(struct vfio_device *core_vdev)
 {
-       struct vfio_fsl_mc_device *vdev = device_data;
+       struct vfio_fsl_mc_device *vdev =
+               container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
        int ret;
 
        mutex_lock(&vdev->reflck->lock);
        module_put(THIS_MODULE);
 }
 
-static long vfio_fsl_mc_ioctl(void *device_data, unsigned int cmd,
-                             unsigned long arg)
+static long vfio_fsl_mc_ioctl(struct vfio_device *core_vdev,
+                             unsigned int cmd, unsigned long arg)
 {
        unsigned long minsz;
-       struct vfio_fsl_mc_device *vdev = device_data;
+       struct vfio_fsl_mc_device *vdev =
+               container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
        struct fsl_mc_device *mc_dev = vdev->mc_dev;
 
        switch (cmd) {
        }
 }
 
-static ssize_t vfio_fsl_mc_read(void *device_data, char __user *buf,
+static ssize_t vfio_fsl_mc_read(struct vfio_device *core_vdev, char __user *buf,
                                size_t count, loff_t *ppos)
 {
-       struct vfio_fsl_mc_device *vdev = device_data;
+       struct vfio_fsl_mc_device *vdev =
+               container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
        unsigned int index = VFIO_FSL_MC_OFFSET_TO_INDEX(*ppos);
        loff_t off = *ppos & VFIO_FSL_MC_OFFSET_MASK;
        struct fsl_mc_device *mc_dev = vdev->mc_dev;
        return 0;
 }
 
-static ssize_t vfio_fsl_mc_write(void *device_data, const char __user *buf,
-                                size_t count, loff_t *ppos)
+static ssize_t vfio_fsl_mc_write(struct vfio_device *core_vdev,
+                                const char __user *buf, size_t count,
+                                loff_t *ppos)
 {
-       struct vfio_fsl_mc_device *vdev = device_data;
+       struct vfio_fsl_mc_device *vdev =
+               container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
        unsigned int index = VFIO_FSL_MC_OFFSET_TO_INDEX(*ppos);
        loff_t off = *ppos & VFIO_FSL_MC_OFFSET_MASK;
        struct fsl_mc_device *mc_dev = vdev->mc_dev;
                               size, vma->vm_page_prot);
 }
 
-static int vfio_fsl_mc_mmap(void *device_data, struct vm_area_struct *vma)
+static int vfio_fsl_mc_mmap(struct vfio_device *core_vdev,
+                           struct vm_area_struct *vma)
 {
-       struct vfio_fsl_mc_device *vdev = device_data;
+       struct vfio_fsl_mc_device *vdev =
+               container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
        struct fsl_mc_device *mc_dev = vdev->mc_dev;
        unsigned int index;
 
 
 #define DRIVER_AUTHOR   "NVIDIA Corporation"
 #define DRIVER_DESC     "VFIO based driver for Mediated device"
 
-static int vfio_mdev_open(void *device_data)
+static int vfio_mdev_open(struct vfio_device *core_vdev)
 {
-       struct mdev_device *mdev = device_data;
+       struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
        struct mdev_parent *parent = mdev->parent;
+
        int ret;
 
        if (unlikely(!parent->ops->open))
        return ret;
 }
 
-static void vfio_mdev_release(void *device_data)
+static void vfio_mdev_release(struct vfio_device *core_vdev)
 {
-       struct mdev_device *mdev = device_data;
+       struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
        struct mdev_parent *parent = mdev->parent;
 
        if (likely(parent->ops->release))
        module_put(THIS_MODULE);
 }
 
-static long vfio_mdev_unlocked_ioctl(void *device_data,
+static long vfio_mdev_unlocked_ioctl(struct vfio_device *core_vdev,
                                     unsigned int cmd, unsigned long arg)
 {
-       struct mdev_device *mdev = device_data;
+       struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
        struct mdev_parent *parent = mdev->parent;
 
        if (unlikely(!parent->ops->ioctl))
        return parent->ops->ioctl(mdev, cmd, arg);
 }
 
-static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
+static ssize_t vfio_mdev_read(struct vfio_device *core_vdev, char __user *buf,
                              size_t count, loff_t *ppos)
 {
-       struct mdev_device *mdev = device_data;
+       struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
        struct mdev_parent *parent = mdev->parent;
 
        if (unlikely(!parent->ops->read))
        return parent->ops->read(mdev, buf, count, ppos);
 }
 
-static ssize_t vfio_mdev_write(void *device_data, const char __user *buf,
-                              size_t count, loff_t *ppos)
+static ssize_t vfio_mdev_write(struct vfio_device *core_vdev,
+                              const char __user *buf, size_t count,
+                              loff_t *ppos)
 {
-       struct mdev_device *mdev = device_data;
+       struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
        struct mdev_parent *parent = mdev->parent;
 
        if (unlikely(!parent->ops->write))
        return parent->ops->write(mdev, buf, count, ppos);
 }
 
-static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma)
+static int vfio_mdev_mmap(struct vfio_device *core_vdev,
+                         struct vm_area_struct *vma)
 {
-       struct mdev_device *mdev = device_data;
+       struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
        struct mdev_parent *parent = mdev->parent;
 
        if (unlikely(!parent->ops->mmap))
        return parent->ops->mmap(mdev, vma);
 }
 
-static void vfio_mdev_request(void *device_data, unsigned int count)
+static void vfio_mdev_request(struct vfio_device *core_vdev, unsigned int count)
 {
-       struct mdev_device *mdev = device_data;
+       struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
        struct mdev_parent *parent = mdev->parent;
 
        if (parent->ops->request)
 
        vfio_device_put(pf_dev);
 }
 
-static void vfio_pci_release(void *device_data)
+static void vfio_pci_release(struct vfio_device *core_vdev)
 {
-       struct vfio_pci_device *vdev = device_data;
+       struct vfio_pci_device *vdev =
+               container_of(core_vdev, struct vfio_pci_device, vdev);
 
        mutex_lock(&vdev->reflck->lock);
 
        module_put(THIS_MODULE);
 }
 
-static int vfio_pci_open(void *device_data)
+static int vfio_pci_open(struct vfio_device *core_vdev)
 {
-       struct vfio_pci_device *vdev = device_data;
+       struct vfio_pci_device *vdev =
+               container_of(core_vdev, struct vfio_pci_device, vdev);
        int ret = 0;
 
        if (!try_module_get(THIS_MODULE))
        int max_index;
 };
 
-static long vfio_pci_ioctl(void *device_data,
+static long vfio_pci_ioctl(struct vfio_device *core_vdev,
                           unsigned int cmd, unsigned long arg)
 {
-       struct vfio_pci_device *vdev = device_data;
+       struct vfio_pci_device *vdev =
+               container_of(core_vdev, struct vfio_pci_device, vdev);
        unsigned long minsz;
 
        if (cmd == VFIO_DEVICE_GET_INFO) {
        return -ENOTTY;
 }
 
-static ssize_t vfio_pci_rw(void *device_data, char __user *buf,
+static ssize_t vfio_pci_rw(struct vfio_pci_device *vdev, char __user *buf,
                           size_t count, loff_t *ppos, bool iswrite)
 {
        unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
-       struct vfio_pci_device *vdev = device_data;
 
        if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions)
                return -EINVAL;
        return -EINVAL;
 }
 
-static ssize_t vfio_pci_read(void *device_data, char __user *buf,
+static ssize_t vfio_pci_read(struct vfio_device *core_vdev, char __user *buf,
                             size_t count, loff_t *ppos)
 {
+       struct vfio_pci_device *vdev =
+               container_of(core_vdev, struct vfio_pci_device, vdev);
+
        if (!count)
                return 0;
 
-       return vfio_pci_rw(device_data, buf, count, ppos, false);
+       return vfio_pci_rw(vdev, buf, count, ppos, false);
 }
 
-static ssize_t vfio_pci_write(void *device_data, const char __user *buf,
+static ssize_t vfio_pci_write(struct vfio_device *core_vdev, const char __user *buf,
                              size_t count, loff_t *ppos)
 {
+       struct vfio_pci_device *vdev =
+               container_of(core_vdev, struct vfio_pci_device, vdev);
+
        if (!count)
                return 0;
 
-       return vfio_pci_rw(device_data, (char __user *)buf, count, ppos, true);
+       return vfio_pci_rw(vdev, (char __user *)buf, count, ppos, true);
 }
 
 /* Return 1 on zap and vma_lock acquired, 0 on contention (only with @try) */
        .fault = vfio_pci_mmap_fault,
 };
 
-static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
+static int vfio_pci_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma)
 {
-       struct vfio_pci_device *vdev = device_data;
+       struct vfio_pci_device *vdev =
+               container_of(core_vdev, struct vfio_pci_device, vdev);
        struct pci_dev *pdev = vdev->pdev;
        unsigned int index;
        u64 phys_len, req_len, pgoff, req_start;
        return 0;
 }
 
-static void vfio_pci_request(void *device_data, unsigned int count)
+static void vfio_pci_request(struct vfio_device *core_vdev, unsigned int count)
 {
-       struct vfio_pci_device *vdev = device_data;
+       struct vfio_pci_device *vdev =
+               container_of(core_vdev, struct vfio_pci_device, vdev);
        struct pci_dev *pdev = vdev->pdev;
 
        mutex_lock(&vdev->igate);
 
 #define VF_TOKEN_ARG "vf_token="
 
-static int vfio_pci_match(void *device_data, char *buf)
+static int vfio_pci_match(struct vfio_device *core_vdev, char *buf)
 {
-       struct vfio_pci_device *vdev = device_data;
+       struct vfio_pci_device *vdev =
+               container_of(core_vdev, struct vfio_pci_device, vdev);
        bool vf_token = false;
        uuid_t uuid;
        int ret;
 
        return -EINVAL;
 }
 
-static void vfio_platform_release(void *device_data)
+static void vfio_platform_release(struct vfio_device *core_vdev)
 {
-       struct vfio_platform_device *vdev = device_data;
+       struct vfio_platform_device *vdev =
+               container_of(core_vdev, struct vfio_platform_device, vdev);
 
        mutex_lock(&driver_lock);
 
        module_put(vdev->parent_module);
 }
 
-static int vfio_platform_open(void *device_data)
+static int vfio_platform_open(struct vfio_device *core_vdev)
 {
-       struct vfio_platform_device *vdev = device_data;
+       struct vfio_platform_device *vdev =
+               container_of(core_vdev, struct vfio_platform_device, vdev);
        int ret;
 
        if (!try_module_get(vdev->parent_module))
        return ret;
 }
 
-static long vfio_platform_ioctl(void *device_data,
+static long vfio_platform_ioctl(struct vfio_device *core_vdev,
                                unsigned int cmd, unsigned long arg)
 {
-       struct vfio_platform_device *vdev = device_data;
+       struct vfio_platform_device *vdev =
+               container_of(core_vdev, struct vfio_platform_device, vdev);
+
        unsigned long minsz;
 
        if (cmd == VFIO_DEVICE_GET_INFO) {
        return -EFAULT;
 }
 
-static ssize_t vfio_platform_read(void *device_data, char __user *buf,
-                                 size_t count, loff_t *ppos)
+static ssize_t vfio_platform_read(struct vfio_device *core_vdev,
+                                 char __user *buf, size_t count, loff_t *ppos)
 {
-       struct vfio_platform_device *vdev = device_data;
+       struct vfio_platform_device *vdev =
+               container_of(core_vdev, struct vfio_platform_device, vdev);
        unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
        loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
 
        return -EFAULT;
 }
 
-static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
+static ssize_t vfio_platform_write(struct vfio_device *core_vdev, const char __user *buf,
                                   size_t count, loff_t *ppos)
 {
-       struct vfio_platform_device *vdev = device_data;
+       struct vfio_platform_device *vdev =
+               container_of(core_vdev, struct vfio_platform_device, vdev);
        unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
        loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
 
                               req_len, vma->vm_page_prot);
 }
 
-static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
+static int vfio_platform_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma)
 {
-       struct vfio_platform_device *vdev = device_data;
+       struct vfio_platform_device *vdev =
+               container_of(core_vdev, struct vfio_platform_device, vdev);
        unsigned int index;
 
        index = vma->vm_pgoff >> (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT);
 
                int ret;
 
                if (it->ops->match) {
-                       ret = it->ops->match(it->device_data, buf);
+                       ret = it->ops->match(it, buf);
                        if (ret < 0) {
                                device = ERR_PTR(ret);
                                break;
        rc = try_wait_for_completion(&device->comp);
        while (rc <= 0) {
                if (device->ops->request)
-                       device->ops->request(device->device_data, i++);
+                       device->ops->request(device, i++);
 
                if (interrupted) {
                        rc = wait_for_completion_timeout(&device->comp,
        if (IS_ERR(device))
                return PTR_ERR(device);
 
-       ret = device->ops->open(device->device_data);
+       ret = device->ops->open(device);
        if (ret) {
                vfio_device_put(device);
                return ret;
         */
        ret = get_unused_fd_flags(O_CLOEXEC);
        if (ret < 0) {
-               device->ops->release(device->device_data);
+               device->ops->release(device);
                vfio_device_put(device);
                return ret;
        }
        if (IS_ERR(filep)) {
                put_unused_fd(ret);
                ret = PTR_ERR(filep);
-               device->ops->release(device->device_data);
+               device->ops->release(device);
                vfio_device_put(device);
                return ret;
        }
 {
        struct vfio_device *device = filep->private_data;
 
-       device->ops->release(device->device_data);
+       device->ops->release(device);
 
        vfio_group_try_dissolve_container(device->group);
 
        if (unlikely(!device->ops->ioctl))
                return -EINVAL;
 
-       return device->ops->ioctl(device->device_data, cmd, arg);
+       return device->ops->ioctl(device, cmd, arg);
 }
 
 static ssize_t vfio_device_fops_read(struct file *filep, char __user *buf,
        if (unlikely(!device->ops->read))
                return -EINVAL;
 
-       return device->ops->read(device->device_data, buf, count, ppos);
+       return device->ops->read(device, buf, count, ppos);
 }
 
 static ssize_t vfio_device_fops_write(struct file *filep,
        if (unlikely(!device->ops->write))
                return -EINVAL;
 
-       return device->ops->write(device->device_data, buf, count, ppos);
+       return device->ops->write(device, buf, count, ppos);
 }
 
 static int vfio_device_fops_mmap(struct file *filep, struct vm_area_struct *vma)
        if (unlikely(!device->ops->mmap))
                return -EINVAL;
 
-       return device->ops->mmap(device->device_data, vma);
+       return device->ops->mmap(device, vma);
 }
 
 static const struct file_operations vfio_device_fops = {
 
  */
 struct vfio_device_ops {
        char    *name;
-       int     (*open)(void *device_data);
-       void    (*release)(void *device_data);
-       ssize_t (*read)(void *device_data, char __user *buf,
+       int     (*open)(struct vfio_device *vdev);
+       void    (*release)(struct vfio_device *vdev);
+       ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
                        size_t count, loff_t *ppos);
-       ssize_t (*write)(void *device_data, const char __user *buf,
+       ssize_t (*write)(struct vfio_device *vdev, const char __user *buf,
                         size_t count, loff_t *size);
-       long    (*ioctl)(void *device_data, unsigned int cmd,
+       long    (*ioctl)(struct vfio_device *vdev, unsigned int cmd,
                         unsigned long arg);
-       int     (*mmap)(void *device_data, struct vm_area_struct *vma);
-       void    (*request)(void *device_data, unsigned int count);
-       int     (*match)(void *device_data, char *buf);
+       int     (*mmap)(struct vfio_device *vdev, struct vm_area_struct *vma);
+       void    (*request)(struct vfio_device *vdev, unsigned int count);
+       int     (*match)(struct vfio_device *vdev, char *buf);
 };
 
 extern struct iommu_group *vfio_iommu_group_get(struct device *dev);