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