xref: /openbmc/linux/drivers/vfio/fsl-mc/vfio_fsl_mc.c (revision fb1ff4c1941573aea59e4cb575dc5a723303cd70)
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