diff options
author | Bharat Bhushan <Bharat.Bhushan@nxp.com> | 2017-07-24 05:33:37 (GMT) |
---|---|---|
committer | Xie Xiaobo <xiaobo.xie@nxp.com> | 2017-09-25 07:25:33 (GMT) |
commit | 8d906bfa78de44c491c0210a6fdb7d570866344b (patch) | |
tree | c220275d13f8aebcdf5c6565e8424cc5963da504 /drivers/vfio/fsl-mc/vfio_fsl_mc.c | |
parent | 081ea506784a4afb798c16ab100a65eadd61456a (diff) | |
download | linux-8d906bfa78de44c491c0210a6fdb7d570866344b.tar.xz |
vfio/fsl-mc: Add VFIO framework for fsl-mc devices
commit f8adf3ce07cf0623b3e8e0df67f3bc12a110416f
[context adjustment]
This patch add framework of VFIO support for FSL-MC devices.
Subsequent patches will add support for binding and secure
assigning these devices using VFIO.
FSL-MC is a new bus (driver/bus/fsl-mc/) which is different
from PCI and Platform bus.
Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
Integrated-by: Zhao Qiang <qiang.zhao@nxp.com>
Diffstat (limited to 'drivers/vfio/fsl-mc/vfio_fsl_mc.c')
-rw-r--r-- | drivers/vfio/fsl-mc/vfio_fsl_mc.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c new file mode 100644 index 0000000..26b8c29 --- /dev/null +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c @@ -0,0 +1,174 @@ +/* + * Freescale Management Complex (MC) device passthrough using VFIO + * + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * Author: Bharat Bhushan <bharat.bhushan@nxp.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/device.h> +#include <linux/iommu.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <linux/vfio.h> + +#include "../../staging/fsl-mc/include/mc.h" +#include "vfio_fsl_mc_private.h" + +#define DRIVER_VERSION "0.10" +#define DRIVER_AUTHOR "Bharat Bhushan <bharat.bhushan@nxp.com>" +#define DRIVER_DESC "VFIO for FSL-MC devices - User Level meta-driver" + +static int vfio_fsl_mc_open(void *device_data) +{ + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + + return 0; +} + +static void vfio_fsl_mc_release(void *device_data) +{ + module_put(THIS_MODULE); +} + +static long vfio_fsl_mc_ioctl(void *device_data, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case VFIO_DEVICE_GET_INFO: + { + return -EINVAL; + } + case VFIO_DEVICE_GET_REGION_INFO: + { + return -EINVAL; + } + case VFIO_DEVICE_GET_IRQ_INFO: + { + return -EINVAL; + } + case VFIO_DEVICE_SET_IRQS: + { + return -EINVAL; + } + case VFIO_DEVICE_RESET: + { + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static ssize_t vfio_fsl_mc_read(void *device_data, char __user *buf, + size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +static ssize_t vfio_fsl_mc_write(void *device_data, const char __user *buf, + size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +static int vfio_fsl_mc_mmap(void *device_data, struct vm_area_struct *vma) +{ + return -EINVAL; +} + +static const struct vfio_device_ops vfio_fsl_mc_ops = { + .name = "vfio-fsl-mc", + .open = vfio_fsl_mc_open, + .release = vfio_fsl_mc_release, + .ioctl = vfio_fsl_mc_ioctl, + .read = vfio_fsl_mc_read, + .write = vfio_fsl_mc_write, + .mmap = vfio_fsl_mc_mmap, +}; + +static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev) +{ + struct iommu_group *group; + struct vfio_fsl_mc_device *vdev; + struct device *dev = &mc_dev->dev; + int ret; + + group = vfio_iommu_group_get(dev); + if (!group) { + dev_err(dev, "%s: VFIO: No IOMMU group\n", __func__); + return -EINVAL; + } + + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); + if (!vdev) { + vfio_iommu_group_put(group, dev); + return -ENOMEM; + } + + vdev->mc_dev = mc_dev; + + ret = vfio_add_group_dev(dev, &vfio_fsl_mc_ops, vdev); + if (ret) { + dev_err(dev, "%s: Failed to add to vfio group\n", __func__); + kfree(vdev); + vfio_iommu_group_put(group, dev); + return ret; + } + + return ret; +} + +static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) +{ + struct vfio_fsl_mc_device *vdev; + struct device *dev = &mc_dev->dev; + + vdev = vfio_del_group_dev(dev); + if (!vdev) + return -EINVAL; + + vfio_iommu_group_put(mc_dev->dev.iommu_group, dev); + kfree(vdev); + + return 0; +} + +/* + * vfio-fsl_mc is a meta-driver, so use driver_override interface to + * bind a fsl_mc container with this driver and match_id_table is NULL. + */ +static struct fsl_mc_driver vfio_fsl_mc_driver = { + .probe = vfio_fsl_mc_probe, + .remove = vfio_fsl_mc_remove, + .match_id_table = NULL, + .driver = { + .name = "vfio-fsl-mc", + .owner = THIS_MODULE, + }, +}; + +static int __init vfio_fsl_mc_driver_init(void) +{ + return fsl_mc_driver_register(&vfio_fsl_mc_driver); +} + +static void __exit vfio_fsl_mc_driver_exit(void) +{ + fsl_mc_driver_unregister(&vfio_fsl_mc_driver); +} + +module_init(vfio_fsl_mc_driver_init); +module_exit(vfio_fsl_mc_driver_exit); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); |