diff mbox series

[2/6] mdev: introduce device specific ops

Message ID 20190923130331.29324-3-jasowang@redhat.com (mailing list archive)
State New, archived
Headers show
Series mdev based hardware virtio offloading support | expand

Commit Message

Jason Wang Sept. 23, 2019, 1:03 p.m. UTC
Currently, except for the create and remove. The rest of
mdev_parent_ops is designed for vfio-mdev driver only and may not help
for kernel mdev driver. Follow the class id support by previous patch,
this patch introduces device specific ops pointer inside parent ops
which points to device specific ops (e.g vfio ops). This allows the
future drivers like virtio-mdev to implement its own device specific
ops.

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 .../driver-api/vfio-mediated-device.rst       |  4 +-
 MAINTAINERS                                   |  1 +
 drivers/gpu/drm/i915/gvt/kvmgt.c              | 15 +++---
 drivers/s390/cio/vfio_ccw_ops.c               | 15 ++++--
 drivers/s390/crypto/vfio_ap_ops.c             | 11 ++--
 drivers/vfio/mdev/vfio_mdev.c                 | 31 ++++++-----
 include/linux/mdev.h                          | 36 ++-----------
 include/linux/vfio_mdev.h                     | 53 +++++++++++++++++++
 samples/vfio-mdev/mbochs.c                    | 17 +++---
 samples/vfio-mdev/mdpy.c                      | 17 +++---
 samples/vfio-mdev/mtty.c                      | 15 ++++--
 11 files changed, 138 insertions(+), 77 deletions(-)
 create mode 100644 include/linux/vfio_mdev.h

Comments

Michael S. Tsirkin Sept. 23, 2019, 3:36 p.m. UTC | #1
On Mon, Sep 23, 2019 at 11:20:12PM +0800, kbuild test robot wrote:
> Hi Jason,
> 
> I love your patch! Yet something to improve:
> 
> [auto build test ERROR on linus/master]
> [cannot apply to v5.3 next-20190920]
> [if your patch is applied to the wrong git tree, please drop us a note to help
> improve the system. BTW, we also suggest to use '--base' option to specify the
> base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
> 
> url:    https://github.com/0day-ci/linux/commits/Jason-Wang/mdev-based-hardware-virtio-offloading-support/20190923-210738
> config: ia64-allmodconfig (attached as .config)
> compiler: ia64-linux-gcc (GCC) 7.4.0
> reproduce:
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         GCC_VERSION=7.4.0 make.cross ARCH=ia64 
> 
> If you fix the issue, kindly add following tag
> Reported-by: kbuild test robot <lkp@intel.com>
> 
> All error/warnings (new ones prefixed by >>):

Looks like a bunch of includes missing. I guess they happen to
be pulled in on some platforms but not others - ideally
headers should be self contained though, pulling in
all their dependencies.


>    In file included from include/linux/vfio_mdev.h:10:0,
>                     from <command-line>:0:
> >> include/linux/mdev.h:25:34: warning: 'struct device' declared inside parameter list will not be visible outside of this definition or declaration
>     int mdev_set_iommu_device(struct device *dev, struct device *iommu_device);
>                                      ^~~~~~
> >> include/linux/mdev.h:62:27: warning: 'struct kobject' declared inside parameter list will not be visible outside of this definition or declaration
>      int     (*create)(struct kobject *kobj, struct mdev_device *mdev);
>                               ^~~~~~~
> >> include/linux/mdev.h:69:19: error: field 'attr' has incomplete type
>      struct attribute attr;
>                       ^~~~
>    include/linux/mdev.h:70:25: warning: 'struct kobject' declared inside parameter list will not be visible outside of this definition or declaration
>      ssize_t (*show)(struct kobject *kobj, struct device *dev, char *buf);
>                             ^~~~~~~
>    include/linux/mdev.h:71:26: warning: 'struct kobject' declared inside parameter list will not be visible outside of this definition or declaration
>      ssize_t (*store)(struct kobject *kobj, struct device *dev,
>                              ^~~~~~~
> >> include/linux/mdev.h:98:23: error: field 'driver' has incomplete type
>      struct device_driver driver;
>                           ^~~~~~
> >> include/linux/mdev.h:106:7: error: unknown type name 'guid_t'
>     const guid_t *mdev_uuid(struct mdev_device *mdev);
>           ^~~~~~
>    In file included from <command-line>:0:0:
> >> include/linux/vfio_mdev.h:50:47: warning: 'struct vm_area_struct' declared inside parameter list will not be visible outside of this definition or declaration
>      int (*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma);
>                                                   ^~~~~~~~~~~~~~
> 
> vim +/attr +69 include/linux/mdev.h
> 
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   14  
> 8ac13175cbe985 Lu Baolu        2019-04-12   15  /*
> 8ac13175cbe985 Lu Baolu        2019-04-12   16   * Called by the parent device driver to set the device which represents
> 8ac13175cbe985 Lu Baolu        2019-04-12   17   * this mdev in iommu protection scope. By default, the iommu device is
> 8ac13175cbe985 Lu Baolu        2019-04-12   18   * NULL, that indicates using vendor defined isolation.
> 8ac13175cbe985 Lu Baolu        2019-04-12   19   *
> 8ac13175cbe985 Lu Baolu        2019-04-12   20   * @dev: the mediated device that iommu will isolate.
> 8ac13175cbe985 Lu Baolu        2019-04-12   21   * @iommu_device: a pci device which represents the iommu for @dev.
> 8ac13175cbe985 Lu Baolu        2019-04-12   22   *
> 8ac13175cbe985 Lu Baolu        2019-04-12   23   * Return 0 for success, otherwise negative error value.
> 8ac13175cbe985 Lu Baolu        2019-04-12   24   */
> 8ac13175cbe985 Lu Baolu        2019-04-12  @25  int mdev_set_iommu_device(struct device *dev, struct device *iommu_device);
> 8ac13175cbe985 Lu Baolu        2019-04-12   26  
> 8ac13175cbe985 Lu Baolu        2019-04-12   27  struct device *mdev_get_iommu_device(struct device *dev);
> 8ac13175cbe985 Lu Baolu        2019-04-12   28  
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   29  /**
> 42930553a7c11f Alex Williamson 2016-12-30   30   * struct mdev_parent_ops - Structure to be registered for each parent device to
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   31   * register the device to mdev module.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   32   *
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   33   * @owner:		The module owner.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   34   * @dev_attr_groups:	Attributes of the parent device.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   35   * @mdev_attr_groups:	Attributes of the mediated device.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   36   * @supported_type_groups: Attributes to define supported types. It is mandatory
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   37   *			to provide supported types.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   38   * @create:		Called to allocate basic resources in parent device's
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   39   *			driver for a particular mediated device. It is
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   40   *			mandatory to provide create ops.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   41   *			@kobj: kobject of type for which 'create' is called.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   42   *			@mdev: mdev_device structure on of mediated device
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   43   *			      that is being created
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   44   *			Returns integer: success (0) or error (< 0)
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   45   * @remove:		Called to free resources in parent device's driver for a
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   46   *			a mediated device. It is mandatory to provide 'remove'
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   47   *			ops.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   48   *			@mdev: mdev_device device structure which is being
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   49   *			       destroyed
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   50   *			Returns integer: success (0) or error (< 0)
> 0baad8a6f6fefa Jason Wang      2019-09-23   51   * @device_ops:         Device specific emulation callback.
> 0baad8a6f6fefa Jason Wang      2019-09-23   52   *
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   53   * Parent device that support mediated device should be registered with mdev
> 42930553a7c11f Alex Williamson 2016-12-30   54   * module with mdev_parent_ops structure.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   55   **/
> 42930553a7c11f Alex Williamson 2016-12-30   56  struct mdev_parent_ops {
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   57  	struct module   *owner;
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   58  	const struct attribute_group **dev_attr_groups;
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   59  	const struct attribute_group **mdev_attr_groups;
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   60  	struct attribute_group **supported_type_groups;
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   61  
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  @62  	int     (*create)(struct kobject *kobj, struct mdev_device *mdev);
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   63  	int     (*remove)(struct mdev_device *mdev);
> 0baad8a6f6fefa Jason Wang      2019-09-23   64  	const void *device_ops;
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   65  };
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   66  
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   67  /* interface for exporting mdev supported type attributes */
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   68  struct mdev_type_attribute {
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  @69  	struct attribute attr;
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  @70  	ssize_t (*show)(struct kobject *kobj, struct device *dev, char *buf);
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   71  	ssize_t (*store)(struct kobject *kobj, struct device *dev,
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   72  			 const char *buf, size_t count);
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   73  };
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   74  
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   75  #define MDEV_TYPE_ATTR(_name, _mode, _show, _store)		\
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   76  struct mdev_type_attribute mdev_type_attr_##_name =		\
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   77  	__ATTR(_name, _mode, _show, _store)
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   78  #define MDEV_TYPE_ATTR_RW(_name) \
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   79  	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RW(_name)
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   80  #define MDEV_TYPE_ATTR_RO(_name) \
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   81  	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RO(_name)
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   82  #define MDEV_TYPE_ATTR_WO(_name) \
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   83  	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_WO(_name)
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   84  
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   85  /**
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   86   * struct mdev_driver - Mediated device driver
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   87   * @name: driver name
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   88   * @probe: called when new device created
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   89   * @remove: called when device removed
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   90   * @driver: device driver structure
> 6294ee8e0b5153 Jason Wang      2019-09-23   91   * @id_table: the ids serviced by this driver.
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   92   *
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   93   **/
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   94  struct mdev_driver {
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   95  	const char *name;
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   96  	int  (*probe)(struct device *dev);
> 7b96953bc640b6 Kirti Wankhede  2016-11-17   97  	void (*remove)(struct device *dev);
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  @98  	struct device_driver driver;
> 6294ee8e0b5153 Jason Wang      2019-09-23   99  	const struct mdev_class_id *id_table;
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  100  };
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  101  
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  102  #define to_mdev_driver(drv)	container_of(drv, struct mdev_driver, driver)
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  103  
> 50732af3b65691 Parav Pandit    2019-04-30  104  void *mdev_get_drvdata(struct mdev_device *mdev);
> 50732af3b65691 Parav Pandit    2019-04-30  105  void mdev_set_drvdata(struct mdev_device *mdev, void *data);
> 50732af3b65691 Parav Pandit    2019-04-30 @106  const guid_t *mdev_uuid(struct mdev_device *mdev);
> 7b96953bc640b6 Kirti Wankhede  2016-11-17  107  
> 
> :::::: The code at line 69 was first introduced by commit
> :::::: 7b96953bc640b6b25665fe17ffca4b668b371f14 vfio: Mediated device Core driver
> 
> :::::: TO: Kirti Wankhede <kwankhede@nvidia.com>
> :::::: CC: Alex Williamson <alex.williamson@redhat.com>
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Parav Pandit Sept. 23, 2019, 10:59 p.m. UTC | #2
> -----Original Message-----
> From: Jason Wang <jasowang@redhat.com>
> Sent: Monday, September 23, 2019 8:03 AM
> To: kvm@vger.kernel.org; linux-s390@vger.kernel.org; linux-
> kernel@vger.kernel.org; dri-devel@lists.freedesktop.org; intel-
> gfx@lists.freedesktop.org; intel-gvt-dev@lists.freedesktop.org;
> kwankhede@nvidia.com; alex.williamson@redhat.com; mst@redhat.com;
> tiwei.bie@intel.com
> Cc: virtualization@lists.linux-foundation.org; netdev@vger.kernel.org;
> cohuck@redhat.com; maxime.coquelin@redhat.com;
> cunming.liang@intel.com; zhihong.wang@intel.com;
> rob.miller@broadcom.com; xiao.w.wang@intel.com;
> haotian.wang@sifive.com; zhenyuw@linux.intel.com; zhi.a.wang@intel.com;
> jani.nikula@linux.intel.com; joonas.lahtinen@linux.intel.com;
> rodrigo.vivi@intel.com; airlied@linux.ie; daniel@ffwll.ch;
> farman@linux.ibm.com; pasic@linux.ibm.com; sebott@linux.ibm.com;
> oberpar@linux.ibm.com; heiko.carstens@de.ibm.com; gor@linux.ibm.com;
> borntraeger@de.ibm.com; akrowiak@linux.ibm.com; freude@linux.ibm.com;
> lingshan.zhu@intel.com; Ido Shamay <idos@mellanox.com>;
> eperezma@redhat.com; lulu@redhat.com; Parav Pandit
> <parav@mellanox.com>; Jason Wang <jasowang@redhat.com>
> Subject: [PATCH 2/6] mdev: introduce device specific ops
> 
> Currently, except for the create and remove. The rest of mdev_parent_ops is
> designed for vfio-mdev driver only and may not help for kernel mdev driver.
> Follow the class id support by previous patch, this patch introduces device
> specific ops pointer inside parent ops which points to device specific ops (e.g
> vfio ops). This allows the future drivers like virtio-mdev to implement its own
> device specific ops.
> 
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
>  .../driver-api/vfio-mediated-device.rst       |  4 +-
>  MAINTAINERS                                   |  1 +
>  drivers/gpu/drm/i915/gvt/kvmgt.c              | 15 +++---
>  drivers/s390/cio/vfio_ccw_ops.c               | 15 ++++--
>  drivers/s390/crypto/vfio_ap_ops.c             | 11 ++--
>  drivers/vfio/mdev/vfio_mdev.c                 | 31 ++++++-----
>  include/linux/mdev.h                          | 36 ++-----------
>  include/linux/vfio_mdev.h                     | 53 +++++++++++++++++++
>  samples/vfio-mdev/mbochs.c                    | 17 +++---
>  samples/vfio-mdev/mdpy.c                      | 17 +++---
>  samples/vfio-mdev/mtty.c                      | 15 ++++--
>  11 files changed, 138 insertions(+), 77 deletions(-)  create mode 100644
> include/linux/vfio_mdev.h
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index 0e052072e1d8..3ab00e48212f 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -152,7 +152,9 @@ callbacks per mdev parent device, per mdev type, or
> any other categorization.
>  Vendor drivers are expected to be fully asynchronous in this respect or
> provide their own internal resource protection.)
> 
> -The callbacks in the mdev_parent_ops structure are as follows:
> +The device specific callbacks are referred through device_ops pointer
> +in mdev_parent_ops. For vfio-mdev device, its callbacks in device_ops
> +are as follows:
> 
>  * open: open callback of mediated device
>  * close: close callback of mediated device diff --git a/MAINTAINERS
> b/MAINTAINERS index b2326dece28e..89832b316500 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17075,6 +17075,7 @@ S:	Maintained
>  F:	Documentation/driver-api/vfio-mediated-device.rst
>  F:	drivers/vfio/mdev/
>  F:	include/linux/mdev.h
> +F:	include/linux/vfio_mdev.h
>  F:	samples/vfio-mdev/
> 
>  VFIO PLATFORM DRIVER
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 19d51a35f019..8ea86b1e69f1 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -42,6 +42,7 @@
>  #include <linux/kvm_host.h>
>  #include <linux/vfio.h>
>  #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
>  #include <linux/debugfs.h>
> 
>  #include <linux/nospec.h>
> @@ -1600,20 +1601,22 @@ static const struct attribute_group
> *intel_vgpu_groups[] = {
>  	NULL,
>  };
> 
> -static struct mdev_parent_ops intel_vgpu_ops = {
> -	.mdev_attr_groups       = intel_vgpu_groups,
> -	.create			= intel_vgpu_create,
> -	.remove			= intel_vgpu_remove,
> -
> +static struct vfio_mdev_parent_ops intel_vfio_vgpu_ops = {

Naming it with _dev prefix as intel_vfio_vgpu_dev_ops is better to differentiate with parent_ops.

>  	.open			= intel_vgpu_open,
>  	.release		= intel_vgpu_release,
> -
>  	.read			= intel_vgpu_read,
>  	.write			= intel_vgpu_write,
>  	.mmap			= intel_vgpu_mmap,
>  	.ioctl			= intel_vgpu_ioctl,
>  };
> 
> +static struct mdev_parent_ops intel_vgpu_ops = {
> +	.mdev_attr_groups       = intel_vgpu_groups,
> +	.create			= intel_vgpu_create,
> +	.remove			= intel_vgpu_remove,
> +	.device_ops	        = &intel_vfio_vgpu_ops,
> +};
> +
>  static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)  {
>  	struct attribute **kvm_type_attrs;
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
> index 246ff0f80944..02122bbc213e 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -12,6 +12,7 @@
> 
>  #include <linux/vfio.h>
>  #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
>  #include <linux/nospec.h>
>  #include <linux/slab.h>
> 
> @@ -574,11 +575,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct
> mdev_device *mdev,
>  	}
>  }
> 
> -static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
> -	.owner			= THIS_MODULE,
> -	.supported_type_groups  = mdev_type_groups,
> -	.create			= vfio_ccw_mdev_create,
> -	.remove			= vfio_ccw_mdev_remove,
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
>  	.open			= vfio_ccw_mdev_open,
>  	.release		= vfio_ccw_mdev_release,
>  	.read			= vfio_ccw_mdev_read,
> @@ -586,6 +583,14 @@ static const struct mdev_parent_ops
> vfio_ccw_mdev_ops = {
>  	.ioctl			= vfio_ccw_mdev_ioctl,
>  };
> 
> +static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
> +	.owner			= THIS_MODULE,
> +	.supported_type_groups  = mdev_type_groups,
> +	.create			= vfio_ccw_mdev_create,
> +	.remove			= vfio_ccw_mdev_remove,
> +	.device_ops		= &vfio_mdev_ops,
> +};
> +
>  int vfio_ccw_mdev_reg(struct subchannel *sch)  {
>  	return mdev_register_vfio_device(&sch->dev, &vfio_ccw_mdev_ops);
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 7487fc39d2c5..4251becc7a6d 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -16,6 +16,7 @@
>  #include <linux/bitops.h>
>  #include <linux/kvm_host.h>
>  #include <linux/module.h>
> +#include <linux/vfio_mdev.h>
>  #include <asm/kvm.h>
>  #include <asm/zcrypt.h>
> 
> @@ -1280,15 +1281,19 @@ static ssize_t vfio_ap_mdev_ioctl(struct
> mdev_device *mdev,
>  	return ret;
>  }
> 
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
> +	.open			= vfio_ap_mdev_open,
> +	.release		= vfio_ap_mdev_release,
> +	.ioctl			= vfio_ap_mdev_ioctl,
> +};
> +
>  static const struct mdev_parent_ops vfio_ap_matrix_ops = {
>  	.owner			= THIS_MODULE,
>  	.supported_type_groups	= vfio_ap_mdev_type_groups,
>  	.mdev_attr_groups	= vfio_ap_mdev_attr_groups,
>  	.create			= vfio_ap_mdev_create,
>  	.remove			= vfio_ap_mdev_remove,
> -	.open			= vfio_ap_mdev_open,
> -	.release		= vfio_ap_mdev_release,
> -	.ioctl			= vfio_ap_mdev_ioctl,
> +	.device_ops		= &vfio_mdev_ops,
>  };
> 
>  int vfio_ap_mdev_register(void)
> diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
> index fd2a4d9a3f26..d23c9f58c84f 100644
> --- a/drivers/vfio/mdev/vfio_mdev.c
> +++ b/drivers/vfio/mdev/vfio_mdev.c
> @@ -14,6 +14,7 @@
>  #include <linux/slab.h>
>  #include <linux/vfio.h>
>  #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
> 
>  #include "mdev_private.h"
> 
> @@ -25,15 +26,16 @@ static int vfio_mdev_open(void *device_data)  {
>  	struct mdev_device *mdev = device_data;
>  	struct mdev_parent *parent = mdev->parent;
> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>  	int ret;
> 
> -	if (unlikely(!parent->ops->open))
> +	if (unlikely(!ops->open))
>  		return -EINVAL;
> 
device_ops is optional and can be NULL for mdev devices which are not required to be mapped via vfio.
So please change to,

If (!ops || !ops->open)
	return -EINVAL;

and rest of the below places.

>  	if (!try_module_get(THIS_MODULE))
>  		return -ENODEV;
> 
> -	ret = parent->ops->open(mdev);
> +	ret = ops->open(mdev);
>  	if (ret)
>  		module_put(THIS_MODULE);
> 
> @@ -44,9 +46,10 @@ static void vfio_mdev_release(void *device_data)  {
>  	struct mdev_device *mdev = device_data;
>  	struct mdev_parent *parent = mdev->parent;
> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
> 
> -	if (likely(parent->ops->release))
> -		parent->ops->release(mdev);
> +	if (likely(ops->release))
> +		ops->release(mdev);
> 
>  	module_put(THIS_MODULE);
>  }
> @@ -56,11 +59,12 @@ static long vfio_mdev_unlocked_ioctl(void
> *device_data,  {
>  	struct mdev_device *mdev = device_data;
>  	struct mdev_parent *parent = mdev->parent;
> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
> 
> -	if (unlikely(!parent->ops->ioctl))
> +	if (unlikely(!ops->ioctl))
>  		return -EINVAL;
> 
> -	return parent->ops->ioctl(mdev, cmd, arg);
> +	return ops->ioctl(mdev, cmd, arg);
>  }
> 
>  static ssize_t vfio_mdev_read(void *device_data, char __user *buf, @@ -68,11
> +72,12 @@ static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
> {
>  	struct mdev_device *mdev = device_data;
>  	struct mdev_parent *parent = mdev->parent;
> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
> 
> -	if (unlikely(!parent->ops->read))
> +	if (unlikely(!ops->read))
>  		return -EINVAL;
> 
> -	return parent->ops->read(mdev, buf, count, ppos);
> +	return ops->read(mdev, buf, count, ppos);
>  }
> 
>  static ssize_t vfio_mdev_write(void *device_data, const char __user *buf, @@
> -80,22 +85,24 @@ static ssize_t vfio_mdev_write(void *device_data, const char
> __user *buf,  {
>  	struct mdev_device *mdev = device_data;
>  	struct mdev_parent *parent = mdev->parent;
> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
> 
> -	if (unlikely(!parent->ops->write))
> +	if (unlikely(!ops->write))
>  		return -EINVAL;
> 
> -	return parent->ops->write(mdev, buf, count, ppos);
> +	return ops->write(mdev, buf, count, ppos);
>  }
> 
>  static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma)  {
>  	struct mdev_device *mdev = device_data;
>  	struct mdev_parent *parent = mdev->parent;
> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
> 
> -	if (unlikely(!parent->ops->mmap))
> +	if (unlikely(!ops->mmap))
>  		return -EINVAL;
> 
> -	return parent->ops->mmap(mdev, vma);
> +	return ops->mmap(mdev, vma);
>  }
> 
>  static const struct vfio_device_ops vfio_mdev_dev_ops = { diff --git
> a/include/linux/mdev.h b/include/linux/mdev.h index
> 3ebae310f599..fa167bcb81e1 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -48,30 +48,8 @@ struct device *mdev_get_iommu_device(struct device
> *dev);
>   *			@mdev: mdev_device device structure which is being
>   *			       destroyed
>   *			Returns integer: success (0) or error (< 0)
> - * @open:		Open mediated device.
> - *			@mdev: mediated device.
> - *			Returns integer: success (0) or error (< 0)
> - * @release:		release mediated device
> - *			@mdev: mediated device.
> - * @read:		Read emulation callback
> - *			@mdev: mediated device structure
> - *			@buf: read buffer
> - *			@count: number of bytes to read
> - *			@ppos: address.
> - *			Retuns number on bytes read on success or error.
> - * @write:		Write emulation callback
> - *			@mdev: mediated device structure
> - *			@buf: write buffer
> - *			@count: number of bytes to be written
> - *			@ppos: address.
> - *			Retuns number on bytes written on success or error.
> - * @ioctl:		IOCTL callback
> - *			@mdev: mediated device structure
> - *			@cmd: ioctl command
> - *			@arg: arguments to ioctl
> - * @mmap:		mmap callback
> - *			@mdev: mediated device structure
> - *			@vma: vma structure
> + * @device_ops:         Device specific emulation callback.
> + *
>   * Parent device that support mediated device should be registered with mdev
>   * module with mdev_parent_ops structure.
>   **/
> @@ -83,15 +61,7 @@ struct mdev_parent_ops {
> 
>  	int     (*create)(struct kobject *kobj, struct mdev_device *mdev);
>  	int     (*remove)(struct mdev_device *mdev);
> -	int     (*open)(struct mdev_device *mdev);
> -	void    (*release)(struct mdev_device *mdev);
> -	ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
> -			size_t count, loff_t *ppos);
> -	ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
> -			 size_t count, loff_t *ppos);
> -	long	(*ioctl)(struct mdev_device *mdev, unsigned int cmd,
> -			 unsigned long arg);
> -	int	(*mmap)(struct mdev_device *mdev, struct vm_area_struct
> *vma);
> +	const void *device_ops;
>  };
> 
>  /* interface for exporting mdev supported type attributes */ diff --git
> a/include/linux/vfio_mdev.h b/include/linux/vfio_mdev.h new file mode
> 100644 index 000000000000..0c1b34f98f5d
> --- /dev/null
> +++ b/include/linux/vfio_mdev.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * VFIO Mediated device definition
> + */
> +
> +#ifndef VFIO_MDEV_H
> +#define VFIO_MDEV_H
> +
> +#include <linux/types.h>
> +#include <linux/mdev.h>
> +
> +/**
> + * struct vfio_mdev_parent_ops - Structure to be registered for each
> + * parent device to register the device to vfio-mdev module.
> + *
> + * @open:		Open mediated device.
> + *			@mdev: mediated device.
> + *			Returns integer: success (0) or error (< 0)
> + * @release:		release mediated device
> + *			@mdev: mediated device.
> + * @read:		Read emulation callback
> + *			@mdev: mediated device structure
> + *			@buf: read buffer
> + *			@count: number of bytes to read
> + *			@ppos: address.
> + *			Retuns number on bytes read on success or error.
> + * @write:		Write emulation callback
> + *			@mdev: mediated device structure
> + *			@buf: write buffer
> + *			@count: number of bytes to be written
> + *			@ppos: address.
> + *			Retuns number on bytes written on success or error.
> + * @ioctl:		IOCTL callback
> + *			@mdev: mediated device structure
> + *			@cmd: ioctl command
> + *			@arg: arguments to ioctl
> + * @mmap:		mmap callback
> + *			@mdev: mediated device structure
> + *			@vma: vma structure
> + */
> +struct vfio_mdev_parent_ops {
> +	int     (*open)(struct mdev_device *mdev);
> +	void    (*release)(struct mdev_device *mdev);
> +	ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
> +			size_t count, loff_t *ppos);
> +	ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
> +			 size_t count, loff_t *ppos);
> +	long	(*ioctl)(struct mdev_device *mdev, unsigned int cmd,
> +			 unsigned long arg);
> +	int	(*mmap)(struct mdev_device *mdev, struct vm_area_struct
> *vma);
> +};
> +
> +#endif
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c index
> 71a4469be85d..107cc30d0f45 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -30,6 +30,7 @@
>  #include <linux/iommu.h>
>  #include <linux/sysfs.h>
>  #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
>  #include <linux/pci.h>
>  #include <linux/dma-buf.h>
>  #include <linux/highmem.h>
> @@ -1418,12 +1419,7 @@ static struct attribute_group *mdev_type_groups[]
> = {
>  	NULL,
>  };
> 
> -static const struct mdev_parent_ops mdev_fops = {
> -	.owner			= THIS_MODULE,
> -	.mdev_attr_groups	= mdev_dev_groups,
> -	.supported_type_groups	= mdev_type_groups,
> -	.create			= mbochs_create,
> -	.remove			= mbochs_remove,
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
>  	.open			= mbochs_open,
>  	.release		= mbochs_close,
>  	.read			= mbochs_read,
> @@ -1432,6 +1428,15 @@ static const struct mdev_parent_ops mdev_fops = {
>  	.mmap			= mbochs_mmap,
>  };
> 
> +static const struct mdev_parent_ops mdev_fops = {
> +	.owner			= THIS_MODULE,
> +	.mdev_attr_groups	= mdev_dev_groups,
> +	.supported_type_groups	= mdev_type_groups,
> +	.create			= mbochs_create,
> +	.remove			= mbochs_remove,
> +	.device_ops		= &vfio_mdev_ops,
> +};
> +
>  static const struct file_operations vd_fops = {
>  	.owner		= THIS_MODULE,
>  };
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c index
> d3029dd27d91..2cd2018a53f9 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -26,6 +26,7 @@
>  #include <linux/iommu.h>
>  #include <linux/sysfs.h>
>  #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
>  #include <linux/pci.h>
>  #include <drm/drm_fourcc.h>
>  #include "mdpy-defs.h"
> @@ -725,12 +726,7 @@ static struct attribute_group *mdev_type_groups[] = {
>  	NULL,
>  };
> 
> -static const struct mdev_parent_ops mdev_fops = {
> -	.owner			= THIS_MODULE,
> -	.mdev_attr_groups	= mdev_dev_groups,
> -	.supported_type_groups	= mdev_type_groups,
> -	.create			= mdpy_create,
> -	.remove			= mdpy_remove,
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
>  	.open			= mdpy_open,
>  	.release		= mdpy_close,
>  	.read			= mdpy_read,
> @@ -739,6 +735,15 @@ static const struct mdev_parent_ops mdev_fops = {
>  	.mmap			= mdpy_mmap,
>  };
> 
> +static const struct mdev_parent_ops mdev_fops = {
> +	.owner			= THIS_MODULE,
> +	.mdev_attr_groups	= mdev_dev_groups,
> +	.supported_type_groups	= mdev_type_groups,
> +	.create			= mdpy_create,
> +	.remove			= mdpy_remove,
> +	.device_ops		= &vfio_mdev_ops,
> +};
> +
>  static const struct file_operations vd_fops = {
>  	.owner		= THIS_MODULE,
>  };
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c index
> 744c88a6b22c..e427425b5daf 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -27,6 +27,7 @@
>  #include <linux/ctype.h>
>  #include <linux/file.h>
>  #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
>  #include <linux/pci.h>
>  #include <linux/serial.h>
>  #include <uapi/linux/serial_reg.h>
> @@ -1410,6 +1411,14 @@ static struct attribute_group *mdev_type_groups[]
> = {
>  	NULL,
>  };
> 
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
> +	.open                   = mtty_open,
> +	.release                = mtty_close,
> +	.read                   = mtty_read,
> +	.write                  = mtty_write,
> +	.ioctl		        = mtty_ioctl,
> +};
> +
>  static const struct mdev_parent_ops mdev_fops = {
>  	.owner                  = THIS_MODULE,
>  	.dev_attr_groups        = mtty_dev_groups,
> @@ -1417,11 +1426,7 @@ static const struct mdev_parent_ops mdev_fops = {
>  	.supported_type_groups  = mdev_type_groups,
>  	.create                 = mtty_create,
>  	.remove			= mtty_remove,
> -	.open                   = mtty_open,
> -	.release                = mtty_close,
> -	.read                   = mtty_read,
> -	.write                  = mtty_write,
> -	.ioctl		        = mtty_ioctl,
> +	.device_ops             = &vfio_mdev_ops,
>  };
> 
>  static void mtty_device_release(struct device *dev)
> --
> 2.19.1
Jason Wang Sept. 24, 2019, 11:23 a.m. UTC | #3
On 2019/9/23 下午11:36, Michael S. Tsirkin wrote:
> On Mon, Sep 23, 2019 at 11:20:12PM +0800, kbuild test robot wrote:
>> Hi Jason,
>>
>> I love your patch! Yet something to improve:
>>
>> [auto build test ERROR on linus/master]
>> [cannot apply to v5.3 next-20190920]
>> [if your patch is applied to the wrong git tree, please drop us a note to help
>> improve the system. BTW, we also suggest to use '--base' option to specify the
>> base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
>>
>> url:    https://github.com/0day-ci/linux/commits/Jason-Wang/mdev-based-hardware-virtio-offloading-support/20190923-210738
>> config: ia64-allmodconfig (attached as .config)
>> compiler: ia64-linux-gcc (GCC) 7.4.0
>> reproduce:
>>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>         chmod +x ~/bin/make.cross
>>         # save the attached .config to linux build tree
>>         GCC_VERSION=7.4.0 make.cross ARCH=ia64 
>>
>> If you fix the issue, kindly add following tag
>> Reported-by: kbuild test robot <lkp@intel.com>
>>
>> All error/warnings (new ones prefixed by >>):
> Looks like a bunch of includes missing. I guess they happen to
> be pulled in on some platforms but not others - ideally
> headers should be self contained though, pulling in
> all their dependencies.


Right, will fix in V2.

Thanks


>
>
>>    In file included from include/linux/vfio_mdev.h:10:0,
>>                     from <command-line>:0:
>>>> include/linux/mdev.h:25:34: warning: 'struct device' declared inside parameter list will not be visible outside of this definition or declaration
>>     int mdev_set_iommu_device(struct device *dev, struct device *iommu_device);
>>                                      ^~~~~~
>>>> include/linux/mdev.h:62:27: warning: 'struct kobject' declared inside parameter list will not be visible outside of this definition or declaration
>>      int     (*create)(struct kobject *kobj, struct mdev_device *mdev);
>>                               ^~~~~~~
>>>> include/linux/mdev.h:69:19: error: field 'attr' has incomplete type
>>      struct attribute attr;
>>                       ^~~~
>>    include/linux/mdev.h:70:25: warning: 'struct kobject' declared inside parameter list will not be visible outside of this definition or declaration
>>      ssize_t (*show)(struct kobject *kobj, struct device *dev, char *buf);
>>                             ^~~~~~~
>>    include/linux/mdev.h:71:26: warning: 'struct kobject' declared inside parameter list will not be visible outside of this definition or declaration
>>      ssize_t (*store)(struct kobject *kobj, struct device *dev,
>>                              ^~~~~~~
>>>> include/linux/mdev.h:98:23: error: field 'driver' has incomplete type
>>      struct device_driver driver;
>>                           ^~~~~~
>>>> include/linux/mdev.h:106:7: error: unknown type name 'guid_t'
>>     const guid_t *mdev_uuid(struct mdev_device *mdev);
>>           ^~~~~~
>>    In file included from <command-line>:0:0:
>>>> include/linux/vfio_mdev.h:50:47: warning: 'struct vm_area_struct' declared inside parameter list will not be visible outside of this definition or declaration
>>      int (*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma);
>>                                                   ^~~~~~~~~~~~~~
>>
>> vim +/attr +69 include/linux/mdev.h
>>
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   14  
>> 8ac13175cbe985 Lu Baolu        2019-04-12   15  /*
>> 8ac13175cbe985 Lu Baolu        2019-04-12   16   * Called by the parent device driver to set the device which represents
>> 8ac13175cbe985 Lu Baolu        2019-04-12   17   * this mdev in iommu protection scope. By default, the iommu device is
>> 8ac13175cbe985 Lu Baolu        2019-04-12   18   * NULL, that indicates using vendor defined isolation.
>> 8ac13175cbe985 Lu Baolu        2019-04-12   19   *
>> 8ac13175cbe985 Lu Baolu        2019-04-12   20   * @dev: the mediated device that iommu will isolate.
>> 8ac13175cbe985 Lu Baolu        2019-04-12   21   * @iommu_device: a pci device which represents the iommu for @dev.
>> 8ac13175cbe985 Lu Baolu        2019-04-12   22   *
>> 8ac13175cbe985 Lu Baolu        2019-04-12   23   * Return 0 for success, otherwise negative error value.
>> 8ac13175cbe985 Lu Baolu        2019-04-12   24   */
>> 8ac13175cbe985 Lu Baolu        2019-04-12  @25  int mdev_set_iommu_device(struct device *dev, struct device *iommu_device);
>> 8ac13175cbe985 Lu Baolu        2019-04-12   26  
>> 8ac13175cbe985 Lu Baolu        2019-04-12   27  struct device *mdev_get_iommu_device(struct device *dev);
>> 8ac13175cbe985 Lu Baolu        2019-04-12   28  
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   29  /**
>> 42930553a7c11f Alex Williamson 2016-12-30   30   * struct mdev_parent_ops - Structure to be registered for each parent device to
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   31   * register the device to mdev module.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   32   *
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   33   * @owner:		The module owner.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   34   * @dev_attr_groups:	Attributes of the parent device.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   35   * @mdev_attr_groups:	Attributes of the mediated device.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   36   * @supported_type_groups: Attributes to define supported types. It is mandatory
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   37   *			to provide supported types.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   38   * @create:		Called to allocate basic resources in parent device's
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   39   *			driver for a particular mediated device. It is
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   40   *			mandatory to provide create ops.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   41   *			@kobj: kobject of type for which 'create' is called.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   42   *			@mdev: mdev_device structure on of mediated device
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   43   *			      that is being created
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   44   *			Returns integer: success (0) or error (< 0)
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   45   * @remove:		Called to free resources in parent device's driver for a
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   46   *			a mediated device. It is mandatory to provide 'remove'
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   47   *			ops.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   48   *			@mdev: mdev_device device structure which is being
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   49   *			       destroyed
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   50   *			Returns integer: success (0) or error (< 0)
>> 0baad8a6f6fefa Jason Wang      2019-09-23   51   * @device_ops:         Device specific emulation callback.
>> 0baad8a6f6fefa Jason Wang      2019-09-23   52   *
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   53   * Parent device that support mediated device should be registered with mdev
>> 42930553a7c11f Alex Williamson 2016-12-30   54   * module with mdev_parent_ops structure.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   55   **/
>> 42930553a7c11f Alex Williamson 2016-12-30   56  struct mdev_parent_ops {
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   57  	struct module   *owner;
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   58  	const struct attribute_group **dev_attr_groups;
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   59  	const struct attribute_group **mdev_attr_groups;
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   60  	struct attribute_group **supported_type_groups;
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   61  
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  @62  	int     (*create)(struct kobject *kobj, struct mdev_device *mdev);
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   63  	int     (*remove)(struct mdev_device *mdev);
>> 0baad8a6f6fefa Jason Wang      2019-09-23   64  	const void *device_ops;
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   65  };
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   66  
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   67  /* interface for exporting mdev supported type attributes */
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   68  struct mdev_type_attribute {
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  @69  	struct attribute attr;
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  @70  	ssize_t (*show)(struct kobject *kobj, struct device *dev, char *buf);
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   71  	ssize_t (*store)(struct kobject *kobj, struct device *dev,
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   72  			 const char *buf, size_t count);
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   73  };
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   74  
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   75  #define MDEV_TYPE_ATTR(_name, _mode, _show, _store)		\
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   76  struct mdev_type_attribute mdev_type_attr_##_name =		\
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   77  	__ATTR(_name, _mode, _show, _store)
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   78  #define MDEV_TYPE_ATTR_RW(_name) \
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   79  	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RW(_name)
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   80  #define MDEV_TYPE_ATTR_RO(_name) \
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   81  	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RO(_name)
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   82  #define MDEV_TYPE_ATTR_WO(_name) \
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   83  	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_WO(_name)
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   84  
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   85  /**
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   86   * struct mdev_driver - Mediated device driver
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   87   * @name: driver name
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   88   * @probe: called when new device created
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   89   * @remove: called when device removed
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   90   * @driver: device driver structure
>> 6294ee8e0b5153 Jason Wang      2019-09-23   91   * @id_table: the ids serviced by this driver.
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   92   *
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   93   **/
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   94  struct mdev_driver {
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   95  	const char *name;
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   96  	int  (*probe)(struct device *dev);
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17   97  	void (*remove)(struct device *dev);
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  @98  	struct device_driver driver;
>> 6294ee8e0b5153 Jason Wang      2019-09-23   99  	const struct mdev_class_id *id_table;
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  100  };
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  101  
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  102  #define to_mdev_driver(drv)	container_of(drv, struct mdev_driver, driver)
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  103  
>> 50732af3b65691 Parav Pandit    2019-04-30  104  void *mdev_get_drvdata(struct mdev_device *mdev);
>> 50732af3b65691 Parav Pandit    2019-04-30  105  void mdev_set_drvdata(struct mdev_device *mdev, void *data);
>> 50732af3b65691 Parav Pandit    2019-04-30 @106  const guid_t *mdev_uuid(struct mdev_device *mdev);
>> 7b96953bc640b6 Kirti Wankhede  2016-11-17  107  
>>
>> :::::: The code at line 69 was first introduced by commit
>> :::::: 7b96953bc640b6b25665fe17ffca4b668b371f14 vfio: Mediated device Core driver
>>
>> :::::: TO: Kirti Wankhede <kwankhede@nvidia.com>
>> :::::: CC: Alex Williamson <alex.williamson@redhat.com>
>>
>> ---
>> 0-DAY kernel test infrastructure                Open Source Technology Center
>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>
Jason Wang Sept. 24, 2019, 11:26 a.m. UTC | #4
On 2019/9/24 上午6:59, Parav Pandit wrote:
>
>> -----Original Message-----
>> From: Jason Wang <jasowang@redhat.com>
>> Sent: Monday, September 23, 2019 8:03 AM
>> To: kvm@vger.kernel.org; linux-s390@vger.kernel.org; linux-
>> kernel@vger.kernel.org; dri-devel@lists.freedesktop.org; intel-
>> gfx@lists.freedesktop.org; intel-gvt-dev@lists.freedesktop.org;
>> kwankhede@nvidia.com; alex.williamson@redhat.com; mst@redhat.com;
>> tiwei.bie@intel.com
>> Cc: virtualization@lists.linux-foundation.org; netdev@vger.kernel.org;
>> cohuck@redhat.com; maxime.coquelin@redhat.com;
>> cunming.liang@intel.com; zhihong.wang@intel.com;
>> rob.miller@broadcom.com; xiao.w.wang@intel.com;
>> haotian.wang@sifive.com; zhenyuw@linux.intel.com; zhi.a.wang@intel.com;
>> jani.nikula@linux.intel.com; joonas.lahtinen@linux.intel.com;
>> rodrigo.vivi@intel.com; airlied@linux.ie; daniel@ffwll.ch;
>> farman@linux.ibm.com; pasic@linux.ibm.com; sebott@linux.ibm.com;
>> oberpar@linux.ibm.com; heiko.carstens@de.ibm.com; gor@linux.ibm.com;
>> borntraeger@de.ibm.com; akrowiak@linux.ibm.com; freude@linux.ibm.com;
>> lingshan.zhu@intel.com; Ido Shamay <idos@mellanox.com>;
>> eperezma@redhat.com; lulu@redhat.com; Parav Pandit
>> <parav@mellanox.com>; Jason Wang <jasowang@redhat.com>
>> Subject: [PATCH 2/6] mdev: introduce device specific ops
>>
>> Currently, except for the create and remove. The rest of mdev_parent_ops is
>> designed for vfio-mdev driver only and may not help for kernel mdev driver.
>> Follow the class id support by previous patch, this patch introduces device
>> specific ops pointer inside parent ops which points to device specific ops (e.g
>> vfio ops). This allows the future drivers like virtio-mdev to implement its own
>> device specific ops.
>>
>> Signed-off-by: Jason Wang <jasowang@redhat.com>
>> ---
>>  .../driver-api/vfio-mediated-device.rst       |  4 +-
>>  MAINTAINERS                                   |  1 +
>>  drivers/gpu/drm/i915/gvt/kvmgt.c              | 15 +++---
>>  drivers/s390/cio/vfio_ccw_ops.c               | 15 ++++--
>>  drivers/s390/crypto/vfio_ap_ops.c             | 11 ++--
>>  drivers/vfio/mdev/vfio_mdev.c                 | 31 ++++++-----
>>  include/linux/mdev.h                          | 36 ++-----------
>>  include/linux/vfio_mdev.h                     | 53 +++++++++++++++++++
>>  samples/vfio-mdev/mbochs.c                    | 17 +++---
>>  samples/vfio-mdev/mdpy.c                      | 17 +++---
>>  samples/vfio-mdev/mtty.c                      | 15 ++++--
>>  11 files changed, 138 insertions(+), 77 deletions(-)  create mode 100644
>> include/linux/vfio_mdev.h
>>
>> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
>> b/Documentation/driver-api/vfio-mediated-device.rst
>> index 0e052072e1d8..3ab00e48212f 100644
>> --- a/Documentation/driver-api/vfio-mediated-device.rst
>> +++ b/Documentation/driver-api/vfio-mediated-device.rst
>> @@ -152,7 +152,9 @@ callbacks per mdev parent device, per mdev type, or
>> any other categorization.
>>  Vendor drivers are expected to be fully asynchronous in this respect or
>> provide their own internal resource protection.)
>>
>> -The callbacks in the mdev_parent_ops structure are as follows:
>> +The device specific callbacks are referred through device_ops pointer
>> +in mdev_parent_ops. For vfio-mdev device, its callbacks in device_ops
>> +are as follows:
>>
>>  * open: open callback of mediated device
>>  * close: close callback of mediated device diff --git a/MAINTAINERS
>> b/MAINTAINERS index b2326dece28e..89832b316500 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -17075,6 +17075,7 @@ S:	Maintained
>>  F:	Documentation/driver-api/vfio-mediated-device.rst
>>  F:	drivers/vfio/mdev/
>>  F:	include/linux/mdev.h
>> +F:	include/linux/vfio_mdev.h
>>  F:	samples/vfio-mdev/
>>
>>  VFIO PLATFORM DRIVER
>> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> index 19d51a35f019..8ea86b1e69f1 100644
>> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
>> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
>> @@ -42,6 +42,7 @@
>>  #include <linux/kvm_host.h>
>>  #include <linux/vfio.h>
>>  #include <linux/mdev.h>
>> +#include <linux/vfio_mdev.h>
>>  #include <linux/debugfs.h>
>>
>>  #include <linux/nospec.h>
>> @@ -1600,20 +1601,22 @@ static const struct attribute_group
>> *intel_vgpu_groups[] = {
>>  	NULL,
>>  };
>>
>> -static struct mdev_parent_ops intel_vgpu_ops = {
>> -	.mdev_attr_groups       = intel_vgpu_groups,
>> -	.create			= intel_vgpu_create,
>> -	.remove			= intel_vgpu_remove,
>> -
>> +static struct vfio_mdev_parent_ops intel_vfio_vgpu_ops = {
> Naming it with _dev prefix as intel_vfio_vgpu_dev_ops is better to differentiate with parent_ops.


Ok.


>>  	.open			= intel_vgpu_open,
>>  	.release		= intel_vgpu_release,
>> -
>>  	.read			= intel_vgpu_read,
>>  	.write			= intel_vgpu_write,
>>  	.mmap			= intel_vgpu_mmap,
>>  	.ioctl			= intel_vgpu_ioctl,
>>  };
>>
>> +static struct mdev_parent_ops intel_vgpu_ops = {
>> +	.mdev_attr_groups       = intel_vgpu_groups,
>> +	.create			= intel_vgpu_create,
>> +	.remove			= intel_vgpu_remove,
>> +	.device_ops	        = &intel_vfio_vgpu_ops,
>> +};
>> +
>>  static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)  {
>>  	struct attribute **kvm_type_attrs;
>> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
>> index 246ff0f80944..02122bbc213e 100644
>> --- a/drivers/s390/cio/vfio_ccw_ops.c
>> +++ b/drivers/s390/cio/vfio_ccw_ops.c
>> @@ -12,6 +12,7 @@
>>
>>  #include <linux/vfio.h>
>>  #include <linux/mdev.h>
>> +#include <linux/vfio_mdev.h>
>>  #include <linux/nospec.h>
>>  #include <linux/slab.h>
>>
>> @@ -574,11 +575,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct
>> mdev_device *mdev,
>>  	}
>>  }
>>
>> -static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
>> -	.owner			= THIS_MODULE,
>> -	.supported_type_groups  = mdev_type_groups,
>> -	.create			= vfio_ccw_mdev_create,
>> -	.remove			= vfio_ccw_mdev_remove,
>> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
>>  	.open			= vfio_ccw_mdev_open,
>>  	.release		= vfio_ccw_mdev_release,
>>  	.read			= vfio_ccw_mdev_read,
>> @@ -586,6 +583,14 @@ static const struct mdev_parent_ops
>> vfio_ccw_mdev_ops = {
>>  	.ioctl			= vfio_ccw_mdev_ioctl,
>>  };
>>
>> +static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
>> +	.owner			= THIS_MODULE,
>> +	.supported_type_groups  = mdev_type_groups,
>> +	.create			= vfio_ccw_mdev_create,
>> +	.remove			= vfio_ccw_mdev_remove,
>> +	.device_ops		= &vfio_mdev_ops,
>> +};
>> +
>>  int vfio_ccw_mdev_reg(struct subchannel *sch)  {
>>  	return mdev_register_vfio_device(&sch->dev, &vfio_ccw_mdev_ops);
>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
>> b/drivers/s390/crypto/vfio_ap_ops.c
>> index 7487fc39d2c5..4251becc7a6d 100644
>> --- a/drivers/s390/crypto/vfio_ap_ops.c
>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
>> @@ -16,6 +16,7 @@
>>  #include <linux/bitops.h>
>>  #include <linux/kvm_host.h>
>>  #include <linux/module.h>
>> +#include <linux/vfio_mdev.h>
>>  #include <asm/kvm.h>
>>  #include <asm/zcrypt.h>
>>
>> @@ -1280,15 +1281,19 @@ static ssize_t vfio_ap_mdev_ioctl(struct
>> mdev_device *mdev,
>>  	return ret;
>>  }
>>
>> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
>> +	.open			= vfio_ap_mdev_open,
>> +	.release		= vfio_ap_mdev_release,
>> +	.ioctl			= vfio_ap_mdev_ioctl,
>> +};
>> +
>>  static const struct mdev_parent_ops vfio_ap_matrix_ops = {
>>  	.owner			= THIS_MODULE,
>>  	.supported_type_groups	= vfio_ap_mdev_type_groups,
>>  	.mdev_attr_groups	= vfio_ap_mdev_attr_groups,
>>  	.create			= vfio_ap_mdev_create,
>>  	.remove			= vfio_ap_mdev_remove,
>> -	.open			= vfio_ap_mdev_open,
>> -	.release		= vfio_ap_mdev_release,
>> -	.ioctl			= vfio_ap_mdev_ioctl,
>> +	.device_ops		= &vfio_mdev_ops,
>>  };
>>
>>  int vfio_ap_mdev_register(void)
>> diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
>> index fd2a4d9a3f26..d23c9f58c84f 100644
>> --- a/drivers/vfio/mdev/vfio_mdev.c
>> +++ b/drivers/vfio/mdev/vfio_mdev.c
>> @@ -14,6 +14,7 @@
>>  #include <linux/slab.h>
>>  #include <linux/vfio.h>
>>  #include <linux/mdev.h>
>> +#include <linux/vfio_mdev.h>
>>
>>  #include "mdev_private.h"
>>
>> @@ -25,15 +26,16 @@ static int vfio_mdev_open(void *device_data)  {
>>  	struct mdev_device *mdev = device_data;
>>  	struct mdev_parent *parent = mdev->parent;
>> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>>  	int ret;
>>
>> -	if (unlikely(!parent->ops->open))
>> +	if (unlikely(!ops->open))
>>  		return -EINVAL;
>>
> device_ops is optional and can be NULL for mdev devices which are not required to be mapped via vfio.
> So please change to,
>
> If (!ops || !ops->open)
> 	return -EINVAL;
>
> and rest of the below places.


My understanding is vfio_mdev can not talk to non vfio mdev device with
the help of class id.

Thanks


>
>>  	if (!try_module_get(THIS_MODULE))
>>  		return -ENODEV;
>>
>> -	ret = parent->ops->open(mdev);
>> +	ret = ops->open(mdev);
>>  	if (ret)
>>  		module_put(THIS_MODULE);
>>
>> @@ -44,9 +46,10 @@ static void vfio_mdev_release(void *device_data)  {
>>  	struct mdev_device *mdev = device_data;
>>  	struct mdev_parent *parent = mdev->parent;
>> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>>
>> -	if (likely(parent->ops->release))
>> -		parent->ops->release(mdev);
>> +	if (likely(ops->release))
>> +		ops->release(mdev);
>>
>>  	module_put(THIS_MODULE);
>>  }
>> @@ -56,11 +59,12 @@ static long vfio_mdev_unlocked_ioctl(void
>> *device_data,  {
>>  	struct mdev_device *mdev = device_data;
>>  	struct mdev_parent *parent = mdev->parent;
>> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>>
>> -	if (unlikely(!parent->ops->ioctl))
>> +	if (unlikely(!ops->ioctl))
>>  		return -EINVAL;
>>
>> -	return parent->ops->ioctl(mdev, cmd, arg);
>> +	return ops->ioctl(mdev, cmd, arg);
>>  }
>>
>>  static ssize_t vfio_mdev_read(void *device_data, char __user *buf, @@ -68,11
>> +72,12 @@ static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
>> {
>>  	struct mdev_device *mdev = device_data;
>>  	struct mdev_parent *parent = mdev->parent;
>> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>>
>> -	if (unlikely(!parent->ops->read))
>> +	if (unlikely(!ops->read))
>>  		return -EINVAL;
>>
>> -	return parent->ops->read(mdev, buf, count, ppos);
>> +	return ops->read(mdev, buf, count, ppos);
>>  }
>>
>>  static ssize_t vfio_mdev_write(void *device_data, const char __user *buf, @@
>> -80,22 +85,24 @@ static ssize_t vfio_mdev_write(void *device_data, const char
>> __user *buf,  {
>>  	struct mdev_device *mdev = device_data;
>>  	struct mdev_parent *parent = mdev->parent;
>> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>>
>> -	if (unlikely(!parent->ops->write))
>> +	if (unlikely(!ops->write))
>>  		return -EINVAL;
>>
>> -	return parent->ops->write(mdev, buf, count, ppos);
>> +	return ops->write(mdev, buf, count, ppos);
>>  }
>>
>>  static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma)  {
>>  	struct mdev_device *mdev = device_data;
>>  	struct mdev_parent *parent = mdev->parent;
>> +	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>>
>> -	if (unlikely(!parent->ops->mmap))
>> +	if (unlikely(!ops->mmap))
>>  		return -EINVAL;
>>
>> -	return parent->ops->mmap(mdev, vma);
>> +	return ops->mmap(mdev, vma);
>>  }
>>
>>  static const struct vfio_device_ops vfio_mdev_dev_ops = { diff --git
>> a/include/linux/mdev.h b/include/linux/mdev.h index
>> 3ebae310f599..fa167bcb81e1 100644
>> --- a/include/linux/mdev.h
>> +++ b/include/linux/mdev.h
>> @@ -48,30 +48,8 @@ struct device *mdev_get_iommu_device(struct device
>> *dev);
>>   *			@mdev: mdev_device device structure which is being
>>   *			       destroyed
>>   *			Returns integer: success (0) or error (< 0)
>> - * @open:		Open mediated device.
>> - *			@mdev: mediated device.
>> - *			Returns integer: success (0) or error (< 0)
>> - * @release:		release mediated device
>> - *			@mdev: mediated device.
>> - * @read:		Read emulation callback
>> - *			@mdev: mediated device structure
>> - *			@buf: read buffer
>> - *			@count: number of bytes to read
>> - *			@ppos: address.
>> - *			Retuns number on bytes read on success or error.
>> - * @write:		Write emulation callback
>> - *			@mdev: mediated device structure
>> - *			@buf: write buffer
>> - *			@count: number of bytes to be written
>> - *			@ppos: address.
>> - *			Retuns number on bytes written on success or error.
>> - * @ioctl:		IOCTL callback
>> - *			@mdev: mediated device structure
>> - *			@cmd: ioctl command
>> - *			@arg: arguments to ioctl
>> - * @mmap:		mmap callback
>> - *			@mdev: mediated device structure
>> - *			@vma: vma structure
>> + * @device_ops:         Device specific emulation callback.
>> + *
>>   * Parent device that support mediated device should be registered with mdev
>>   * module with mdev_parent_ops structure.
>>   **/
>> @@ -83,15 +61,7 @@ struct mdev_parent_ops {
>>
>>  	int     (*create)(struct kobject *kobj, struct mdev_device *mdev);
>>  	int     (*remove)(struct mdev_device *mdev);
>> -	int     (*open)(struct mdev_device *mdev);
>> -	void    (*release)(struct mdev_device *mdev);
>> -	ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
>> -			size_t count, loff_t *ppos);
>> -	ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
>> -			 size_t count, loff_t *ppos);
>> -	long	(*ioctl)(struct mdev_device *mdev, unsigned int cmd,
>> -			 unsigned long arg);
>> -	int	(*mmap)(struct mdev_device *mdev, struct vm_area_struct
>> *vma);
>> +	const void *device_ops;
>>  };
>>
>>  /* interface for exporting mdev supported type attributes */ diff --git
>> a/include/linux/vfio_mdev.h b/include/linux/vfio_mdev.h new file mode
>> 100644 index 000000000000..0c1b34f98f5d
>> --- /dev/null
>> +++ b/include/linux/vfio_mdev.h
>> @@ -0,0 +1,53 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * VFIO Mediated device definition
>> + */
>> +
>> +#ifndef VFIO_MDEV_H
>> +#define VFIO_MDEV_H
>> +
>> +#include <linux/types.h>
>> +#include <linux/mdev.h>
>> +
>> +/**
>> + * struct vfio_mdev_parent_ops - Structure to be registered for each
>> + * parent device to register the device to vfio-mdev module.
>> + *
>> + * @open:		Open mediated device.
>> + *			@mdev: mediated device.
>> + *			Returns integer: success (0) or error (< 0)
>> + * @release:		release mediated device
>> + *			@mdev: mediated device.
>> + * @read:		Read emulation callback
>> + *			@mdev: mediated device structure
>> + *			@buf: read buffer
>> + *			@count: number of bytes to read
>> + *			@ppos: address.
>> + *			Retuns number on bytes read on success or error.
>> + * @write:		Write emulation callback
>> + *			@mdev: mediated device structure
>> + *			@buf: write buffer
>> + *			@count: number of bytes to be written
>> + *			@ppos: address.
>> + *			Retuns number on bytes written on success or error.
>> + * @ioctl:		IOCTL callback
>> + *			@mdev: mediated device structure
>> + *			@cmd: ioctl command
>> + *			@arg: arguments to ioctl
>> + * @mmap:		mmap callback
>> + *			@mdev: mediated device structure
>> + *			@vma: vma structure
>> + */
>> +struct vfio_mdev_parent_ops {
>> +	int     (*open)(struct mdev_device *mdev);
>> +	void    (*release)(struct mdev_device *mdev);
>> +	ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
>> +			size_t count, loff_t *ppos);
>> +	ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
>> +			 size_t count, loff_t *ppos);
>> +	long	(*ioctl)(struct mdev_device *mdev, unsigned int cmd,
>> +			 unsigned long arg);
>> +	int	(*mmap)(struct mdev_device *mdev, struct vm_area_struct
>> *vma);
>> +};
>> +
>> +#endif
>> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c index
>> 71a4469be85d..107cc30d0f45 100644
>> --- a/samples/vfio-mdev/mbochs.c
>> +++ b/samples/vfio-mdev/mbochs.c
>> @@ -30,6 +30,7 @@
>>  #include <linux/iommu.h>
>>  #include <linux/sysfs.h>
>>  #include <linux/mdev.h>
>> +#include <linux/vfio_mdev.h>
>>  #include <linux/pci.h>
>>  #include <linux/dma-buf.h>
>>  #include <linux/highmem.h>
>> @@ -1418,12 +1419,7 @@ static struct attribute_group *mdev_type_groups[]
>> = {
>>  	NULL,
>>  };
>>
>> -static const struct mdev_parent_ops mdev_fops = {
>> -	.owner			= THIS_MODULE,
>> -	.mdev_attr_groups	= mdev_dev_groups,
>> -	.supported_type_groups	= mdev_type_groups,
>> -	.create			= mbochs_create,
>> -	.remove			= mbochs_remove,
>> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
>>  	.open			= mbochs_open,
>>  	.release		= mbochs_close,
>>  	.read			= mbochs_read,
>> @@ -1432,6 +1428,15 @@ static const struct mdev_parent_ops mdev_fops = {
>>  	.mmap			= mbochs_mmap,
>>  };
>>
>> +static const struct mdev_parent_ops mdev_fops = {
>> +	.owner			= THIS_MODULE,
>> +	.mdev_attr_groups	= mdev_dev_groups,
>> +	.supported_type_groups	= mdev_type_groups,
>> +	.create			= mbochs_create,
>> +	.remove			= mbochs_remove,
>> +	.device_ops		= &vfio_mdev_ops,
>> +};
>> +
>>  static const struct file_operations vd_fops = {
>>  	.owner		= THIS_MODULE,
>>  };
>> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c index
>> d3029dd27d91..2cd2018a53f9 100644
>> --- a/samples/vfio-mdev/mdpy.c
>> +++ b/samples/vfio-mdev/mdpy.c
>> @@ -26,6 +26,7 @@
>>  #include <linux/iommu.h>
>>  #include <linux/sysfs.h>
>>  #include <linux/mdev.h>
>> +#include <linux/vfio_mdev.h>
>>  #include <linux/pci.h>
>>  #include <drm/drm_fourcc.h>
>>  #include "mdpy-defs.h"
>> @@ -725,12 +726,7 @@ static struct attribute_group *mdev_type_groups[] = {
>>  	NULL,
>>  };
>>
>> -static const struct mdev_parent_ops mdev_fops = {
>> -	.owner			= THIS_MODULE,
>> -	.mdev_attr_groups	= mdev_dev_groups,
>> -	.supported_type_groups	= mdev_type_groups,
>> -	.create			= mdpy_create,
>> -	.remove			= mdpy_remove,
>> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
>>  	.open			= mdpy_open,
>>  	.release		= mdpy_close,
>>  	.read			= mdpy_read,
>> @@ -739,6 +735,15 @@ static const struct mdev_parent_ops mdev_fops = {
>>  	.mmap			= mdpy_mmap,
>>  };
>>
>> +static const struct mdev_parent_ops mdev_fops = {
>> +	.owner			= THIS_MODULE,
>> +	.mdev_attr_groups	= mdev_dev_groups,
>> +	.supported_type_groups	= mdev_type_groups,
>> +	.create			= mdpy_create,
>> +	.remove			= mdpy_remove,
>> +	.device_ops		= &vfio_mdev_ops,
>> +};
>> +
>>  static const struct file_operations vd_fops = {
>>  	.owner		= THIS_MODULE,
>>  };
>> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c index
>> 744c88a6b22c..e427425b5daf 100644
>> --- a/samples/vfio-mdev/mtty.c
>> +++ b/samples/vfio-mdev/mtty.c
>> @@ -27,6 +27,7 @@
>>  #include <linux/ctype.h>
>>  #include <linux/file.h>
>>  #include <linux/mdev.h>
>> +#include <linux/vfio_mdev.h>
>>  #include <linux/pci.h>
>>  #include <linux/serial.h>
>>  #include <uapi/linux/serial_reg.h>
>> @@ -1410,6 +1411,14 @@ static struct attribute_group *mdev_type_groups[]
>> = {
>>  	NULL,
>>  };
>>
>> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
>> +	.open                   = mtty_open,
>> +	.release                = mtty_close,
>> +	.read                   = mtty_read,
>> +	.write                  = mtty_write,
>> +	.ioctl		        = mtty_ioctl,
>> +};
>> +
>>  static const struct mdev_parent_ops mdev_fops = {
>>  	.owner                  = THIS_MODULE,
>>  	.dev_attr_groups        = mtty_dev_groups,
>> @@ -1417,11 +1426,7 @@ static const struct mdev_parent_ops mdev_fops = {
>>  	.supported_type_groups  = mdev_type_groups,
>>  	.create                 = mtty_create,
>>  	.remove			= mtty_remove,
>> -	.open                   = mtty_open,
>> -	.release                = mtty_close,
>> -	.read                   = mtty_read,
>> -	.write                  = mtty_write,
>> -	.ioctl		        = mtty_ioctl,
>> +	.device_ops             = &vfio_mdev_ops,
>>  };
>>
>>  static void mtty_device_release(struct device *dev)
>> --
>> 2.19.1
diff mbox series

Patch

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index 0e052072e1d8..3ab00e48212f 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -152,7 +152,9 @@  callbacks per mdev parent device, per mdev type, or any other categorization.
 Vendor drivers are expected to be fully asynchronous in this respect or
 provide their own internal resource protection.)
 
-The callbacks in the mdev_parent_ops structure are as follows:
+The device specific callbacks are referred through device_ops pointer
+in mdev_parent_ops. For vfio-mdev device, its callbacks in device_ops
+are as follows:
 
 * open: open callback of mediated device
 * close: close callback of mediated device
diff --git a/MAINTAINERS b/MAINTAINERS
index b2326dece28e..89832b316500 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17075,6 +17075,7 @@  S:	Maintained
 F:	Documentation/driver-api/vfio-mediated-device.rst
 F:	drivers/vfio/mdev/
 F:	include/linux/mdev.h
+F:	include/linux/vfio_mdev.h
 F:	samples/vfio-mdev/
 
 VFIO PLATFORM DRIVER
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 19d51a35f019..8ea86b1e69f1 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -42,6 +42,7 @@ 
 #include <linux/kvm_host.h>
 #include <linux/vfio.h>
 #include <linux/mdev.h>
+#include <linux/vfio_mdev.h>
 #include <linux/debugfs.h>
 
 #include <linux/nospec.h>
@@ -1600,20 +1601,22 @@  static const struct attribute_group *intel_vgpu_groups[] = {
 	NULL,
 };
 
-static struct mdev_parent_ops intel_vgpu_ops = {
-	.mdev_attr_groups       = intel_vgpu_groups,
-	.create			= intel_vgpu_create,
-	.remove			= intel_vgpu_remove,
-
+static struct vfio_mdev_parent_ops intel_vfio_vgpu_ops = {
 	.open			= intel_vgpu_open,
 	.release		= intel_vgpu_release,
-
 	.read			= intel_vgpu_read,
 	.write			= intel_vgpu_write,
 	.mmap			= intel_vgpu_mmap,
 	.ioctl			= intel_vgpu_ioctl,
 };
 
+static struct mdev_parent_ops intel_vgpu_ops = {
+	.mdev_attr_groups       = intel_vgpu_groups,
+	.create			= intel_vgpu_create,
+	.remove			= intel_vgpu_remove,
+	.device_ops	        = &intel_vfio_vgpu_ops,
+};
+
 static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)
 {
 	struct attribute **kvm_type_attrs;
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 246ff0f80944..02122bbc213e 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -12,6 +12,7 @@ 
 
 #include <linux/vfio.h>
 #include <linux/mdev.h>
+#include <linux/vfio_mdev.h>
 #include <linux/nospec.h>
 #include <linux/slab.h>
 
@@ -574,11 +575,7 @@  static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
 	}
 }
 
-static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
-	.owner			= THIS_MODULE,
-	.supported_type_groups  = mdev_type_groups,
-	.create			= vfio_ccw_mdev_create,
-	.remove			= vfio_ccw_mdev_remove,
+static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
 	.open			= vfio_ccw_mdev_open,
 	.release		= vfio_ccw_mdev_release,
 	.read			= vfio_ccw_mdev_read,
@@ -586,6 +583,14 @@  static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
 	.ioctl			= vfio_ccw_mdev_ioctl,
 };
 
+static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
+	.owner			= THIS_MODULE,
+	.supported_type_groups  = mdev_type_groups,
+	.create			= vfio_ccw_mdev_create,
+	.remove			= vfio_ccw_mdev_remove,
+	.device_ops		= &vfio_mdev_ops,
+};
+
 int vfio_ccw_mdev_reg(struct subchannel *sch)
 {
 	return mdev_register_vfio_device(&sch->dev, &vfio_ccw_mdev_ops);
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 7487fc39d2c5..4251becc7a6d 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -16,6 +16,7 @@ 
 #include <linux/bitops.h>
 #include <linux/kvm_host.h>
 #include <linux/module.h>
+#include <linux/vfio_mdev.h>
 #include <asm/kvm.h>
 #include <asm/zcrypt.h>
 
@@ -1280,15 +1281,19 @@  static ssize_t vfio_ap_mdev_ioctl(struct mdev_device *mdev,
 	return ret;
 }
 
+static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
+	.open			= vfio_ap_mdev_open,
+	.release		= vfio_ap_mdev_release,
+	.ioctl			= vfio_ap_mdev_ioctl,
+};
+
 static const struct mdev_parent_ops vfio_ap_matrix_ops = {
 	.owner			= THIS_MODULE,
 	.supported_type_groups	= vfio_ap_mdev_type_groups,
 	.mdev_attr_groups	= vfio_ap_mdev_attr_groups,
 	.create			= vfio_ap_mdev_create,
 	.remove			= vfio_ap_mdev_remove,
-	.open			= vfio_ap_mdev_open,
-	.release		= vfio_ap_mdev_release,
-	.ioctl			= vfio_ap_mdev_ioctl,
+	.device_ops		= &vfio_mdev_ops,
 };
 
 int vfio_ap_mdev_register(void)
diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
index fd2a4d9a3f26..d23c9f58c84f 100644
--- a/drivers/vfio/mdev/vfio_mdev.c
+++ b/drivers/vfio/mdev/vfio_mdev.c
@@ -14,6 +14,7 @@ 
 #include <linux/slab.h>
 #include <linux/vfio.h>
 #include <linux/mdev.h>
+#include <linux/vfio_mdev.h>
 
 #include "mdev_private.h"
 
@@ -25,15 +26,16 @@  static int vfio_mdev_open(void *device_data)
 {
 	struct mdev_device *mdev = device_data;
 	struct mdev_parent *parent = mdev->parent;
+	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
 	int ret;
 
-	if (unlikely(!parent->ops->open))
+	if (unlikely(!ops->open))
 		return -EINVAL;
 
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
 
-	ret = parent->ops->open(mdev);
+	ret = ops->open(mdev);
 	if (ret)
 		module_put(THIS_MODULE);
 
@@ -44,9 +46,10 @@  static void vfio_mdev_release(void *device_data)
 {
 	struct mdev_device *mdev = device_data;
 	struct mdev_parent *parent = mdev->parent;
+	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
 
-	if (likely(parent->ops->release))
-		parent->ops->release(mdev);
+	if (likely(ops->release))
+		ops->release(mdev);
 
 	module_put(THIS_MODULE);
 }
@@ -56,11 +59,12 @@  static long vfio_mdev_unlocked_ioctl(void *device_data,
 {
 	struct mdev_device *mdev = device_data;
 	struct mdev_parent *parent = mdev->parent;
+	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
 
-	if (unlikely(!parent->ops->ioctl))
+	if (unlikely(!ops->ioctl))
 		return -EINVAL;
 
-	return parent->ops->ioctl(mdev, cmd, arg);
+	return ops->ioctl(mdev, cmd, arg);
 }
 
 static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
@@ -68,11 +72,12 @@  static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
 {
 	struct mdev_device *mdev = device_data;
 	struct mdev_parent *parent = mdev->parent;
+	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
 
-	if (unlikely(!parent->ops->read))
+	if (unlikely(!ops->read))
 		return -EINVAL;
 
-	return parent->ops->read(mdev, buf, count, ppos);
+	return ops->read(mdev, buf, count, ppos);
 }
 
 static ssize_t vfio_mdev_write(void *device_data, const char __user *buf,
@@ -80,22 +85,24 @@  static ssize_t vfio_mdev_write(void *device_data, const char __user *buf,
 {
 	struct mdev_device *mdev = device_data;
 	struct mdev_parent *parent = mdev->parent;
+	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
 
-	if (unlikely(!parent->ops->write))
+	if (unlikely(!ops->write))
 		return -EINVAL;
 
-	return parent->ops->write(mdev, buf, count, ppos);
+	return ops->write(mdev, buf, count, ppos);
 }
 
 static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma)
 {
 	struct mdev_device *mdev = device_data;
 	struct mdev_parent *parent = mdev->parent;
+	const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
 
-	if (unlikely(!parent->ops->mmap))
+	if (unlikely(!ops->mmap))
 		return -EINVAL;
 
-	return parent->ops->mmap(mdev, vma);
+	return ops->mmap(mdev, vma);
 }
 
 static const struct vfio_device_ops vfio_mdev_dev_ops = {
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 3ebae310f599..fa167bcb81e1 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -48,30 +48,8 @@  struct device *mdev_get_iommu_device(struct device *dev);
  *			@mdev: mdev_device device structure which is being
  *			       destroyed
  *			Returns integer: success (0) or error (< 0)
- * @open:		Open mediated device.
- *			@mdev: mediated device.
- *			Returns integer: success (0) or error (< 0)
- * @release:		release mediated device
- *			@mdev: mediated device.
- * @read:		Read emulation callback
- *			@mdev: mediated device structure
- *			@buf: read buffer
- *			@count: number of bytes to read
- *			@ppos: address.
- *			Retuns number on bytes read on success or error.
- * @write:		Write emulation callback
- *			@mdev: mediated device structure
- *			@buf: write buffer
- *			@count: number of bytes to be written
- *			@ppos: address.
- *			Retuns number on bytes written on success or error.
- * @ioctl:		IOCTL callback
- *			@mdev: mediated device structure
- *			@cmd: ioctl command
- *			@arg: arguments to ioctl
- * @mmap:		mmap callback
- *			@mdev: mediated device structure
- *			@vma: vma structure
+ * @device_ops:         Device specific emulation callback.
+ *
  * Parent device that support mediated device should be registered with mdev
  * module with mdev_parent_ops structure.
  **/
@@ -83,15 +61,7 @@  struct mdev_parent_ops {
 
 	int     (*create)(struct kobject *kobj, struct mdev_device *mdev);
 	int     (*remove)(struct mdev_device *mdev);
-	int     (*open)(struct mdev_device *mdev);
-	void    (*release)(struct mdev_device *mdev);
-	ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
-			size_t count, loff_t *ppos);
-	ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
-			 size_t count, loff_t *ppos);
-	long	(*ioctl)(struct mdev_device *mdev, unsigned int cmd,
-			 unsigned long arg);
-	int	(*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma);
+	const void *device_ops;
 };
 
 /* interface for exporting mdev supported type attributes */
diff --git a/include/linux/vfio_mdev.h b/include/linux/vfio_mdev.h
new file mode 100644
index 000000000000..0c1b34f98f5d
--- /dev/null
+++ b/include/linux/vfio_mdev.h
@@ -0,0 +1,53 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * VFIO Mediated device definition
+ */
+
+#ifndef VFIO_MDEV_H
+#define VFIO_MDEV_H
+
+#include <linux/types.h>
+#include <linux/mdev.h>
+
+/**
+ * struct vfio_mdev_parent_ops - Structure to be registered for each
+ * parent device to register the device to vfio-mdev module.
+ *
+ * @open:		Open mediated device.
+ *			@mdev: mediated device.
+ *			Returns integer: success (0) or error (< 0)
+ * @release:		release mediated device
+ *			@mdev: mediated device.
+ * @read:		Read emulation callback
+ *			@mdev: mediated device structure
+ *			@buf: read buffer
+ *			@count: number of bytes to read
+ *			@ppos: address.
+ *			Retuns number on bytes read on success or error.
+ * @write:		Write emulation callback
+ *			@mdev: mediated device structure
+ *			@buf: write buffer
+ *			@count: number of bytes to be written
+ *			@ppos: address.
+ *			Retuns number on bytes written on success or error.
+ * @ioctl:		IOCTL callback
+ *			@mdev: mediated device structure
+ *			@cmd: ioctl command
+ *			@arg: arguments to ioctl
+ * @mmap:		mmap callback
+ *			@mdev: mediated device structure
+ *			@vma: vma structure
+ */
+struct vfio_mdev_parent_ops {
+	int     (*open)(struct mdev_device *mdev);
+	void    (*release)(struct mdev_device *mdev);
+	ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
+			size_t count, loff_t *ppos);
+	ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
+			 size_t count, loff_t *ppos);
+	long	(*ioctl)(struct mdev_device *mdev, unsigned int cmd,
+			 unsigned long arg);
+	int	(*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma);
+};
+
+#endif
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 71a4469be85d..107cc30d0f45 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -30,6 +30,7 @@ 
 #include <linux/iommu.h>
 #include <linux/sysfs.h>
 #include <linux/mdev.h>
+#include <linux/vfio_mdev.h>
 #include <linux/pci.h>
 #include <linux/dma-buf.h>
 #include <linux/highmem.h>
@@ -1418,12 +1419,7 @@  static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
-static const struct mdev_parent_ops mdev_fops = {
-	.owner			= THIS_MODULE,
-	.mdev_attr_groups	= mdev_dev_groups,
-	.supported_type_groups	= mdev_type_groups,
-	.create			= mbochs_create,
-	.remove			= mbochs_remove,
+static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
 	.open			= mbochs_open,
 	.release		= mbochs_close,
 	.read			= mbochs_read,
@@ -1432,6 +1428,15 @@  static const struct mdev_parent_ops mdev_fops = {
 	.mmap			= mbochs_mmap,
 };
 
+static const struct mdev_parent_ops mdev_fops = {
+	.owner			= THIS_MODULE,
+	.mdev_attr_groups	= mdev_dev_groups,
+	.supported_type_groups	= mdev_type_groups,
+	.create			= mbochs_create,
+	.remove			= mbochs_remove,
+	.device_ops		= &vfio_mdev_ops,
+};
+
 static const struct file_operations vd_fops = {
 	.owner		= THIS_MODULE,
 };
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index d3029dd27d91..2cd2018a53f9 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -26,6 +26,7 @@ 
 #include <linux/iommu.h>
 #include <linux/sysfs.h>
 #include <linux/mdev.h>
+#include <linux/vfio_mdev.h>
 #include <linux/pci.h>
 #include <drm/drm_fourcc.h>
 #include "mdpy-defs.h"
@@ -725,12 +726,7 @@  static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
-static const struct mdev_parent_ops mdev_fops = {
-	.owner			= THIS_MODULE,
-	.mdev_attr_groups	= mdev_dev_groups,
-	.supported_type_groups	= mdev_type_groups,
-	.create			= mdpy_create,
-	.remove			= mdpy_remove,
+static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
 	.open			= mdpy_open,
 	.release		= mdpy_close,
 	.read			= mdpy_read,
@@ -739,6 +735,15 @@  static const struct mdev_parent_ops mdev_fops = {
 	.mmap			= mdpy_mmap,
 };
 
+static const struct mdev_parent_ops mdev_fops = {
+	.owner			= THIS_MODULE,
+	.mdev_attr_groups	= mdev_dev_groups,
+	.supported_type_groups	= mdev_type_groups,
+	.create			= mdpy_create,
+	.remove			= mdpy_remove,
+	.device_ops		= &vfio_mdev_ops,
+};
+
 static const struct file_operations vd_fops = {
 	.owner		= THIS_MODULE,
 };
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index 744c88a6b22c..e427425b5daf 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -27,6 +27,7 @@ 
 #include <linux/ctype.h>
 #include <linux/file.h>
 #include <linux/mdev.h>
+#include <linux/vfio_mdev.h>
 #include <linux/pci.h>
 #include <linux/serial.h>
 #include <uapi/linux/serial_reg.h>
@@ -1410,6 +1411,14 @@  static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
+static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
+	.open                   = mtty_open,
+	.release                = mtty_close,
+	.read                   = mtty_read,
+	.write                  = mtty_write,
+	.ioctl		        = mtty_ioctl,
+};
+
 static const struct mdev_parent_ops mdev_fops = {
 	.owner                  = THIS_MODULE,
 	.dev_attr_groups        = mtty_dev_groups,
@@ -1417,11 +1426,7 @@  static const struct mdev_parent_ops mdev_fops = {
 	.supported_type_groups  = mdev_type_groups,
 	.create                 = mtty_create,
 	.remove			= mtty_remove,
-	.open                   = mtty_open,
-	.release                = mtty_close,
-	.read                   = mtty_read,
-	.write                  = mtty_write,
-	.ioctl		        = mtty_ioctl,
+	.device_ops             = &vfio_mdev_ops,
 };
 
 static void mtty_device_release(struct device *dev)