1*fb1ff4c1SBharat Bhushan // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 2*fb1ff4c1SBharat Bhushan /* 3*fb1ff4c1SBharat Bhushan * Copyright 2013-2016 Freescale Semiconductor Inc. 4*fb1ff4c1SBharat Bhushan * Copyright 2016-2017,2019-2020 NXP 5*fb1ff4c1SBharat Bhushan */ 6*fb1ff4c1SBharat Bhushan 7*fb1ff4c1SBharat Bhushan #include <linux/device.h> 8*fb1ff4c1SBharat Bhushan #include <linux/iommu.h> 9*fb1ff4c1SBharat Bhushan #include <linux/module.h> 10*fb1ff4c1SBharat Bhushan #include <linux/mutex.h> 11*fb1ff4c1SBharat Bhushan #include <linux/slab.h> 12*fb1ff4c1SBharat Bhushan #include <linux/types.h> 13*fb1ff4c1SBharat Bhushan #include <linux/vfio.h> 14*fb1ff4c1SBharat Bhushan #include <linux/fsl/mc.h> 15*fb1ff4c1SBharat Bhushan 16*fb1ff4c1SBharat Bhushan #include "vfio_fsl_mc_private.h" 17*fb1ff4c1SBharat Bhushan 18*fb1ff4c1SBharat Bhushan static int vfio_fsl_mc_open(void *device_data) 19*fb1ff4c1SBharat Bhushan { 20*fb1ff4c1SBharat Bhushan if (!try_module_get(THIS_MODULE)) 21*fb1ff4c1SBharat Bhushan return -ENODEV; 22*fb1ff4c1SBharat Bhushan 23*fb1ff4c1SBharat Bhushan return 0; 24*fb1ff4c1SBharat Bhushan } 25*fb1ff4c1SBharat Bhushan 26*fb1ff4c1SBharat Bhushan static void vfio_fsl_mc_release(void *device_data) 27*fb1ff4c1SBharat Bhushan { 28*fb1ff4c1SBharat Bhushan module_put(THIS_MODULE); 29*fb1ff4c1SBharat Bhushan } 30*fb1ff4c1SBharat Bhushan 31*fb1ff4c1SBharat Bhushan static long vfio_fsl_mc_ioctl(void *device_data, unsigned int cmd, 32*fb1ff4c1SBharat Bhushan unsigned long arg) 33*fb1ff4c1SBharat Bhushan { 34*fb1ff4c1SBharat Bhushan switch (cmd) { 35*fb1ff4c1SBharat Bhushan case VFIO_DEVICE_GET_INFO: 36*fb1ff4c1SBharat Bhushan { 37*fb1ff4c1SBharat Bhushan return -ENOTTY; 38*fb1ff4c1SBharat Bhushan } 39*fb1ff4c1SBharat Bhushan case VFIO_DEVICE_GET_REGION_INFO: 40*fb1ff4c1SBharat Bhushan { 41*fb1ff4c1SBharat Bhushan return -ENOTTY; 42*fb1ff4c1SBharat Bhushan } 43*fb1ff4c1SBharat Bhushan case VFIO_DEVICE_GET_IRQ_INFO: 44*fb1ff4c1SBharat Bhushan { 45*fb1ff4c1SBharat Bhushan return -ENOTTY; 46*fb1ff4c1SBharat Bhushan } 47*fb1ff4c1SBharat Bhushan case VFIO_DEVICE_SET_IRQS: 48*fb1ff4c1SBharat Bhushan { 49*fb1ff4c1SBharat Bhushan return -ENOTTY; 50*fb1ff4c1SBharat Bhushan } 51*fb1ff4c1SBharat Bhushan case VFIO_DEVICE_RESET: 52*fb1ff4c1SBharat Bhushan { 53*fb1ff4c1SBharat Bhushan return -ENOTTY; 54*fb1ff4c1SBharat Bhushan } 55*fb1ff4c1SBharat Bhushan default: 56*fb1ff4c1SBharat Bhushan return -ENOTTY; 57*fb1ff4c1SBharat Bhushan } 58*fb1ff4c1SBharat Bhushan } 59*fb1ff4c1SBharat Bhushan 60*fb1ff4c1SBharat Bhushan static ssize_t vfio_fsl_mc_read(void *device_data, char __user *buf, 61*fb1ff4c1SBharat Bhushan size_t count, loff_t *ppos) 62*fb1ff4c1SBharat Bhushan { 63*fb1ff4c1SBharat Bhushan return -EINVAL; 64*fb1ff4c1SBharat Bhushan } 65*fb1ff4c1SBharat Bhushan 66*fb1ff4c1SBharat Bhushan static ssize_t vfio_fsl_mc_write(void *device_data, const char __user *buf, 67*fb1ff4c1SBharat Bhushan size_t count, loff_t *ppos) 68*fb1ff4c1SBharat Bhushan { 69*fb1ff4c1SBharat Bhushan return -EINVAL; 70*fb1ff4c1SBharat Bhushan } 71*fb1ff4c1SBharat Bhushan 72*fb1ff4c1SBharat Bhushan static int vfio_fsl_mc_mmap(void *device_data, struct vm_area_struct *vma) 73*fb1ff4c1SBharat Bhushan { 74*fb1ff4c1SBharat Bhushan return -EINVAL; 75*fb1ff4c1SBharat Bhushan } 76*fb1ff4c1SBharat Bhushan 77*fb1ff4c1SBharat Bhushan static const struct vfio_device_ops vfio_fsl_mc_ops = { 78*fb1ff4c1SBharat Bhushan .name = "vfio-fsl-mc", 79*fb1ff4c1SBharat Bhushan .open = vfio_fsl_mc_open, 80*fb1ff4c1SBharat Bhushan .release = vfio_fsl_mc_release, 81*fb1ff4c1SBharat Bhushan .ioctl = vfio_fsl_mc_ioctl, 82*fb1ff4c1SBharat Bhushan .read = vfio_fsl_mc_read, 83*fb1ff4c1SBharat Bhushan .write = vfio_fsl_mc_write, 84*fb1ff4c1SBharat Bhushan .mmap = vfio_fsl_mc_mmap, 85*fb1ff4c1SBharat Bhushan }; 86*fb1ff4c1SBharat Bhushan 87*fb1ff4c1SBharat Bhushan static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev) 88*fb1ff4c1SBharat Bhushan { 89*fb1ff4c1SBharat Bhushan struct iommu_group *group; 90*fb1ff4c1SBharat Bhushan struct vfio_fsl_mc_device *vdev; 91*fb1ff4c1SBharat Bhushan struct device *dev = &mc_dev->dev; 92*fb1ff4c1SBharat Bhushan int ret; 93*fb1ff4c1SBharat Bhushan 94*fb1ff4c1SBharat Bhushan group = vfio_iommu_group_get(dev); 95*fb1ff4c1SBharat Bhushan if (!group) { 96*fb1ff4c1SBharat Bhushan dev_err(dev, "VFIO_FSL_MC: No IOMMU group\n"); 97*fb1ff4c1SBharat Bhushan return -EINVAL; 98*fb1ff4c1SBharat Bhushan } 99*fb1ff4c1SBharat Bhushan 100*fb1ff4c1SBharat Bhushan vdev = devm_kzalloc(dev, sizeof(*vdev), GFP_KERNEL); 101*fb1ff4c1SBharat Bhushan if (!vdev) { 102*fb1ff4c1SBharat Bhushan ret = -ENOMEM; 103*fb1ff4c1SBharat Bhushan goto out_group_put; 104*fb1ff4c1SBharat Bhushan } 105*fb1ff4c1SBharat Bhushan 106*fb1ff4c1SBharat Bhushan vdev->mc_dev = mc_dev; 107*fb1ff4c1SBharat Bhushan 108*fb1ff4c1SBharat Bhushan ret = vfio_add_group_dev(dev, &vfio_fsl_mc_ops, vdev); 109*fb1ff4c1SBharat Bhushan if (ret) { 110*fb1ff4c1SBharat Bhushan dev_err(dev, "VFIO_FSL_MC: Failed to add to vfio group\n"); 111*fb1ff4c1SBharat Bhushan goto out_group_put; 112*fb1ff4c1SBharat Bhushan } 113*fb1ff4c1SBharat Bhushan return 0; 114*fb1ff4c1SBharat Bhushan 115*fb1ff4c1SBharat Bhushan out_group_put: 116*fb1ff4c1SBharat Bhushan vfio_iommu_group_put(group, dev); 117*fb1ff4c1SBharat Bhushan return ret; 118*fb1ff4c1SBharat Bhushan } 119*fb1ff4c1SBharat Bhushan 120*fb1ff4c1SBharat Bhushan static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) 121*fb1ff4c1SBharat Bhushan { 122*fb1ff4c1SBharat Bhushan struct vfio_fsl_mc_device *vdev; 123*fb1ff4c1SBharat Bhushan struct device *dev = &mc_dev->dev; 124*fb1ff4c1SBharat Bhushan 125*fb1ff4c1SBharat Bhushan vdev = vfio_del_group_dev(dev); 126*fb1ff4c1SBharat Bhushan if (!vdev) 127*fb1ff4c1SBharat Bhushan return -EINVAL; 128*fb1ff4c1SBharat Bhushan 129*fb1ff4c1SBharat Bhushan vfio_iommu_group_put(mc_dev->dev.iommu_group, dev); 130*fb1ff4c1SBharat Bhushan 131*fb1ff4c1SBharat Bhushan return 0; 132*fb1ff4c1SBharat Bhushan } 133*fb1ff4c1SBharat Bhushan 134*fb1ff4c1SBharat Bhushan static struct fsl_mc_driver vfio_fsl_mc_driver = { 135*fb1ff4c1SBharat Bhushan .probe = vfio_fsl_mc_probe, 136*fb1ff4c1SBharat Bhushan .remove = vfio_fsl_mc_remove, 137*fb1ff4c1SBharat Bhushan .driver = { 138*fb1ff4c1SBharat Bhushan .name = "vfio-fsl-mc", 139*fb1ff4c1SBharat Bhushan .owner = THIS_MODULE, 140*fb1ff4c1SBharat Bhushan }, 141*fb1ff4c1SBharat Bhushan }; 142*fb1ff4c1SBharat Bhushan 143*fb1ff4c1SBharat Bhushan static int __init vfio_fsl_mc_driver_init(void) 144*fb1ff4c1SBharat Bhushan { 145*fb1ff4c1SBharat Bhushan return fsl_mc_driver_register(&vfio_fsl_mc_driver); 146*fb1ff4c1SBharat Bhushan } 147*fb1ff4c1SBharat Bhushan 148*fb1ff4c1SBharat Bhushan static void __exit vfio_fsl_mc_driver_exit(void) 149*fb1ff4c1SBharat Bhushan { 150*fb1ff4c1SBharat Bhushan fsl_mc_driver_unregister(&vfio_fsl_mc_driver); 151*fb1ff4c1SBharat Bhushan } 152*fb1ff4c1SBharat Bhushan 153*fb1ff4c1SBharat Bhushan module_init(vfio_fsl_mc_driver_init); 154*fb1ff4c1SBharat Bhushan module_exit(vfio_fsl_mc_driver_exit); 155*fb1ff4c1SBharat Bhushan 156*fb1ff4c1SBharat Bhushan MODULE_LICENSE("Dual BSD/GPL"); 157*fb1ff4c1SBharat Bhushan MODULE_DESCRIPTION("VFIO for FSL-MC devices - User Level meta-driver"); 158