summaryrefslogtreecommitdiffstats
path: root/drivers/vfio/cdx/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio/cdx/main.c')
-rw-r--r--drivers/vfio/cdx/main.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/drivers/vfio/cdx/main.c b/drivers/vfio/cdx/main.c
index de56686581..9cff8d7578 100644
--- a/drivers/vfio/cdx/main.c
+++ b/drivers/vfio/cdx/main.c
@@ -14,7 +14,7 @@ static int vfio_cdx_open_device(struct vfio_device *core_vdev)
container_of(core_vdev, struct vfio_cdx_device, vdev);
struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
int count = cdx_dev->res_count;
- int i;
+ int i, ret;
vdev->regions = kcalloc(count, sizeof(struct vfio_cdx_region),
GFP_KERNEL_ACCOUNT);
@@ -39,6 +39,17 @@ static int vfio_cdx_open_device(struct vfio_device *core_vdev)
if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY))
vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE;
}
+ ret = cdx_dev_reset(core_vdev->dev);
+ if (ret) {
+ kfree(vdev->regions);
+ vdev->regions = NULL;
+ return ret;
+ }
+ ret = cdx_clear_master(cdx_dev);
+ if (ret)
+ vdev->flags &= ~BME_SUPPORT;
+ else
+ vdev->flags |= BME_SUPPORT;
return 0;
}
@@ -52,6 +63,49 @@ static void vfio_cdx_close_device(struct vfio_device *core_vdev)
cdx_dev_reset(core_vdev->dev);
}
+static int vfio_cdx_bm_ctrl(struct vfio_device *core_vdev, u32 flags,
+ void __user *arg, size_t argsz)
+{
+ size_t minsz =
+ offsetofend(struct vfio_device_feature_bus_master, op);
+ struct vfio_cdx_device *vdev =
+ container_of(core_vdev, struct vfio_cdx_device, vdev);
+ struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
+ struct vfio_device_feature_bus_master ops;
+ int ret;
+
+ if (!(vdev->flags & BME_SUPPORT))
+ return -ENOTTY;
+
+ ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET,
+ sizeof(ops));
+ if (ret != 1)
+ return ret;
+
+ if (copy_from_user(&ops, arg, minsz))
+ return -EFAULT;
+
+ switch (ops.op) {
+ case VFIO_DEVICE_FEATURE_CLEAR_MASTER:
+ return cdx_clear_master(cdx_dev);
+ case VFIO_DEVICE_FEATURE_SET_MASTER:
+ return cdx_set_master(cdx_dev);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vfio_cdx_ioctl_feature(struct vfio_device *device, u32 flags,
+ void __user *arg, size_t argsz)
+{
+ switch (flags & VFIO_DEVICE_FEATURE_MASK) {
+ case VFIO_DEVICE_FEATURE_BUS_MASTER:
+ return vfio_cdx_bm_ctrl(device, flags, arg, argsz);
+ default:
+ return -ENOTTY;
+ }
+}
+
static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device *vdev,
struct vfio_device_info __user *arg)
{
@@ -169,6 +223,7 @@ static const struct vfio_device_ops vfio_cdx_ops = {
.open_device = vfio_cdx_open_device,
.close_device = vfio_cdx_close_device,
.ioctl = vfio_cdx_ioctl,
+ .device_feature = vfio_cdx_ioctl_feature,
.mmap = vfio_cdx_mmap,
.bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind,
@@ -231,3 +286,4 @@ module_driver(vfio_cdx_driver, cdx_driver_register, cdx_driver_unregister);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver");
+MODULE_IMPORT_NS(CDX_BUS);