]> git.ipfire.org Git - thirdparty/linux.git/blame - drivers/vdpa/vdpa.c
Merge tag 'drm/tegra/for-5.7-fixes' of git://anongit.freedesktop.org/tegra/linux...
[thirdparty/linux.git] / drivers / vdpa / vdpa.c
CommitLineData
961e9c84
JW
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * vDPA bus.
4 *
5 * Copyright (c) 2020, Red Hat. All rights reserved.
6 * Author: Jason Wang <jasowang@redhat.com>
7 *
8 */
9
10#include <linux/module.h>
11#include <linux/idr.h>
12#include <linux/slab.h>
13#include <linux/vdpa.h>
14
15static DEFINE_IDA(vdpa_index_ida);
16
17static int vdpa_dev_probe(struct device *d)
18{
19 struct vdpa_device *vdev = dev_to_vdpa(d);
20 struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver);
21 int ret = 0;
22
23 if (drv && drv->probe)
24 ret = drv->probe(vdev);
25
26 return ret;
27}
28
29static int vdpa_dev_remove(struct device *d)
30{
31 struct vdpa_device *vdev = dev_to_vdpa(d);
32 struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver);
33
34 if (drv && drv->remove)
35 drv->remove(vdev);
36
37 return 0;
38}
39
40static struct bus_type vdpa_bus = {
41 .name = "vdpa",
42 .probe = vdpa_dev_probe,
43 .remove = vdpa_dev_remove,
44};
45
46static void vdpa_release_dev(struct device *d)
47{
48 struct vdpa_device *vdev = dev_to_vdpa(d);
49 const struct vdpa_config_ops *ops = vdev->config;
50
51 if (ops->free)
52 ops->free(vdev);
53
54 ida_simple_remove(&vdpa_index_ida, vdev->index);
55 kfree(vdev);
56}
57
58/**
59 * __vdpa_alloc_device - allocate and initilaize a vDPA device
60 * This allows driver to some prepartion after device is
61 * initialized but before registered.
62 * @parent: the parent device
63 * @config: the bus operations that is supported by this device
64 * @size: size of the parent structure that contains private data
65 *
66 * Drvier should use vdap_alloc_device() wrapper macro instead of
67 * using this directly.
68 *
69 * Returns an error when parent/config/dma_dev is not set or fail to get
70 * ida.
71 */
72struct vdpa_device *__vdpa_alloc_device(struct device *parent,
73 const struct vdpa_config_ops *config,
74 size_t size)
75{
76 struct vdpa_device *vdev;
77 int err = -EINVAL;
78
79 if (!config)
80 goto err;
81
82 if (!!config->dma_map != !!config->dma_unmap)
83 goto err;
84
85 err = -ENOMEM;
86 vdev = kzalloc(size, GFP_KERNEL);
87 if (!vdev)
88 goto err;
89
90 err = ida_simple_get(&vdpa_index_ida, 0, 0, GFP_KERNEL);
91 if (err < 0)
92 goto err_ida;
93
94 vdev->dev.bus = &vdpa_bus;
95 vdev->dev.parent = parent;
96 vdev->dev.release = vdpa_release_dev;
97 vdev->index = err;
98 vdev->config = config;
99
100 err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index);
101 if (err)
102 goto err_name;
103
104 device_initialize(&vdev->dev);
105
106 return vdev;
107
108err_name:
109 ida_simple_remove(&vdpa_index_ida, vdev->index);
110err_ida:
111 kfree(vdev);
112err:
113 return ERR_PTR(err);
114}
115EXPORT_SYMBOL_GPL(__vdpa_alloc_device);
116
117/**
118 * vdpa_register_device - register a vDPA device
ac8b85f9 119 * Callers must have a succeed call of vdpa_alloc_device() before.
961e9c84
JW
120 * @vdev: the vdpa device to be registered to vDPA bus
121 *
122 * Returns an error when fail to add to vDPA bus
123 */
124int vdpa_register_device(struct vdpa_device *vdev)
125{
126 return device_add(&vdev->dev);
127}
128EXPORT_SYMBOL_GPL(vdpa_register_device);
129
130/**
131 * vdpa_unregister_device - unregister a vDPA device
132 * @vdev: the vdpa device to be unregisted from vDPA bus
133 */
134void vdpa_unregister_device(struct vdpa_device *vdev)
135{
136 device_unregister(&vdev->dev);
137}
138EXPORT_SYMBOL_GPL(vdpa_unregister_device);
139
140/**
141 * __vdpa_register_driver - register a vDPA device driver
142 * @drv: the vdpa device driver to be registered
143 * @owner: module owner of the driver
144 *
145 * Returns an err when fail to do the registration
146 */
147int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner)
148{
149 drv->driver.bus = &vdpa_bus;
150 drv->driver.owner = owner;
151
152 return driver_register(&drv->driver);
153}
154EXPORT_SYMBOL_GPL(__vdpa_register_driver);
155
156/**
157 * vdpa_unregister_driver - unregister a vDPA device driver
158 * @drv: the vdpa device driver to be unregistered
159 */
160void vdpa_unregister_driver(struct vdpa_driver *drv)
161{
162 driver_unregister(&drv->driver);
163}
164EXPORT_SYMBOL_GPL(vdpa_unregister_driver);
165
166static int vdpa_init(void)
167{
168 return bus_register(&vdpa_bus);
169}
170
171static void __exit vdpa_exit(void)
172{
173 bus_unregister(&vdpa_bus);
174 ida_destroy(&vdpa_index_ida);
175}
176core_initcall(vdpa_init);
177module_exit(vdpa_exit);
178
179MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>");
180MODULE_LICENSE("GPL v2");