xref: /linux/drivers/vfio/mdev/mdev_driver.c (revision 7b96953bc640b6b25665fe17ffca4b668b371f14)
1*7b96953bSKirti Wankhede /*
2*7b96953bSKirti Wankhede  * MDEV driver
3*7b96953bSKirti Wankhede  *
4*7b96953bSKirti Wankhede  * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
5*7b96953bSKirti Wankhede  *     Author: Neo Jia <cjia@nvidia.com>
6*7b96953bSKirti Wankhede  *             Kirti Wankhede <kwankhede@nvidia.com>
7*7b96953bSKirti Wankhede  *
8*7b96953bSKirti Wankhede  * This program is free software; you can redistribute it and/or modify
9*7b96953bSKirti Wankhede  * it under the terms of the GNU General Public License version 2 as
10*7b96953bSKirti Wankhede  * published by the Free Software Foundation.
11*7b96953bSKirti Wankhede  */
12*7b96953bSKirti Wankhede 
13*7b96953bSKirti Wankhede #include <linux/device.h>
14*7b96953bSKirti Wankhede #include <linux/iommu.h>
15*7b96953bSKirti Wankhede #include <linux/mdev.h>
16*7b96953bSKirti Wankhede 
17*7b96953bSKirti Wankhede #include "mdev_private.h"
18*7b96953bSKirti Wankhede 
19*7b96953bSKirti Wankhede static int mdev_attach_iommu(struct mdev_device *mdev)
20*7b96953bSKirti Wankhede {
21*7b96953bSKirti Wankhede 	int ret;
22*7b96953bSKirti Wankhede 	struct iommu_group *group;
23*7b96953bSKirti Wankhede 
24*7b96953bSKirti Wankhede 	group = iommu_group_alloc();
25*7b96953bSKirti Wankhede 	if (IS_ERR(group))
26*7b96953bSKirti Wankhede 		return PTR_ERR(group);
27*7b96953bSKirti Wankhede 
28*7b96953bSKirti Wankhede 	ret = iommu_group_add_device(group, &mdev->dev);
29*7b96953bSKirti Wankhede 	if (!ret)
30*7b96953bSKirti Wankhede 		dev_info(&mdev->dev, "MDEV: group_id = %d\n",
31*7b96953bSKirti Wankhede 			 iommu_group_id(group));
32*7b96953bSKirti Wankhede 
33*7b96953bSKirti Wankhede 	iommu_group_put(group);
34*7b96953bSKirti Wankhede 	return ret;
35*7b96953bSKirti Wankhede }
36*7b96953bSKirti Wankhede 
37*7b96953bSKirti Wankhede static void mdev_detach_iommu(struct mdev_device *mdev)
38*7b96953bSKirti Wankhede {
39*7b96953bSKirti Wankhede 	iommu_group_remove_device(&mdev->dev);
40*7b96953bSKirti Wankhede 	dev_info(&mdev->dev, "MDEV: detaching iommu\n");
41*7b96953bSKirti Wankhede }
42*7b96953bSKirti Wankhede 
43*7b96953bSKirti Wankhede static int mdev_probe(struct device *dev)
44*7b96953bSKirti Wankhede {
45*7b96953bSKirti Wankhede 	struct mdev_driver *drv = to_mdev_driver(dev->driver);
46*7b96953bSKirti Wankhede 	struct mdev_device *mdev = to_mdev_device(dev);
47*7b96953bSKirti Wankhede 	int ret;
48*7b96953bSKirti Wankhede 
49*7b96953bSKirti Wankhede 	ret = mdev_attach_iommu(mdev);
50*7b96953bSKirti Wankhede 	if (ret)
51*7b96953bSKirti Wankhede 		return ret;
52*7b96953bSKirti Wankhede 
53*7b96953bSKirti Wankhede 	if (drv && drv->probe) {
54*7b96953bSKirti Wankhede 		ret = drv->probe(dev);
55*7b96953bSKirti Wankhede 		if (ret)
56*7b96953bSKirti Wankhede 			mdev_detach_iommu(mdev);
57*7b96953bSKirti Wankhede 	}
58*7b96953bSKirti Wankhede 
59*7b96953bSKirti Wankhede 	return ret;
60*7b96953bSKirti Wankhede }
61*7b96953bSKirti Wankhede 
62*7b96953bSKirti Wankhede static int mdev_remove(struct device *dev)
63*7b96953bSKirti Wankhede {
64*7b96953bSKirti Wankhede 	struct mdev_driver *drv = to_mdev_driver(dev->driver);
65*7b96953bSKirti Wankhede 	struct mdev_device *mdev = to_mdev_device(dev);
66*7b96953bSKirti Wankhede 
67*7b96953bSKirti Wankhede 	if (drv && drv->remove)
68*7b96953bSKirti Wankhede 		drv->remove(dev);
69*7b96953bSKirti Wankhede 
70*7b96953bSKirti Wankhede 	mdev_detach_iommu(mdev);
71*7b96953bSKirti Wankhede 
72*7b96953bSKirti Wankhede 	return 0;
73*7b96953bSKirti Wankhede }
74*7b96953bSKirti Wankhede 
75*7b96953bSKirti Wankhede struct bus_type mdev_bus_type = {
76*7b96953bSKirti Wankhede 	.name		= "mdev",
77*7b96953bSKirti Wankhede 	.probe		= mdev_probe,
78*7b96953bSKirti Wankhede 	.remove		= mdev_remove,
79*7b96953bSKirti Wankhede };
80*7b96953bSKirti Wankhede EXPORT_SYMBOL_GPL(mdev_bus_type);
81*7b96953bSKirti Wankhede 
82*7b96953bSKirti Wankhede /**
83*7b96953bSKirti Wankhede  * mdev_register_driver - register a new MDEV driver
84*7b96953bSKirti Wankhede  * @drv: the driver to register
85*7b96953bSKirti Wankhede  * @owner: module owner of driver to be registered
86*7b96953bSKirti Wankhede  *
87*7b96953bSKirti Wankhede  * Returns a negative value on error, otherwise 0.
88*7b96953bSKirti Wankhede  **/
89*7b96953bSKirti Wankhede int mdev_register_driver(struct mdev_driver *drv, struct module *owner)
90*7b96953bSKirti Wankhede {
91*7b96953bSKirti Wankhede 	/* initialize common driver fields */
92*7b96953bSKirti Wankhede 	drv->driver.name = drv->name;
93*7b96953bSKirti Wankhede 	drv->driver.bus = &mdev_bus_type;
94*7b96953bSKirti Wankhede 	drv->driver.owner = owner;
95*7b96953bSKirti Wankhede 
96*7b96953bSKirti Wankhede 	/* register with core */
97*7b96953bSKirti Wankhede 	return driver_register(&drv->driver);
98*7b96953bSKirti Wankhede }
99*7b96953bSKirti Wankhede EXPORT_SYMBOL(mdev_register_driver);
100*7b96953bSKirti Wankhede 
101*7b96953bSKirti Wankhede /*
102*7b96953bSKirti Wankhede  * mdev_unregister_driver - unregister MDEV driver
103*7b96953bSKirti Wankhede  * @drv: the driver to unregister
104*7b96953bSKirti Wankhede  */
105*7b96953bSKirti Wankhede void mdev_unregister_driver(struct mdev_driver *drv)
106*7b96953bSKirti Wankhede {
107*7b96953bSKirti Wankhede 	driver_unregister(&drv->driver);
108*7b96953bSKirti Wankhede }
109*7b96953bSKirti Wankhede EXPORT_SYMBOL(mdev_unregister_driver);
110*7b96953bSKirti Wankhede 
111*7b96953bSKirti Wankhede int mdev_bus_register(void)
112*7b96953bSKirti Wankhede {
113*7b96953bSKirti Wankhede 	return bus_register(&mdev_bus_type);
114*7b96953bSKirti Wankhede }
115*7b96953bSKirti Wankhede 
116*7b96953bSKirti Wankhede void mdev_bus_unregister(void)
117*7b96953bSKirti Wankhede {
118*7b96953bSKirti Wankhede 	bus_unregister(&mdev_bus_type);
119*7b96953bSKirti Wankhede }
120