vdpa: make sure set_features is invoked for legacy
[linux-block.git] / drivers / vdpa / vdpa.c
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
15 static DEFINE_IDA(vdpa_index_ida);
16
17 static 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
29 static 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
40 static struct bus_type vdpa_bus = {
41         .name  = "vdpa",
42         .probe = vdpa_dev_probe,
43         .remove = vdpa_dev_remove,
44 };
45
46 static 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  * Driver should use vdpa_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  */
72 struct 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         vdev->features_valid = false;
100
101         err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index);
102         if (err)
103                 goto err_name;
104
105         device_initialize(&vdev->dev);
106
107         return vdev;
108
109 err_name:
110         ida_simple_remove(&vdpa_index_ida, vdev->index);
111 err_ida:
112         kfree(vdev);
113 err:
114         return ERR_PTR(err);
115 }
116 EXPORT_SYMBOL_GPL(__vdpa_alloc_device);
117
118 /**
119  * vdpa_register_device - register a vDPA device
120  * Callers must have a succeed call of vdpa_alloc_device() before.
121  * @vdev: the vdpa device to be registered to vDPA bus
122  *
123  * Returns an error when fail to add to vDPA bus
124  */
125 int vdpa_register_device(struct vdpa_device *vdev)
126 {
127         return device_add(&vdev->dev);
128 }
129 EXPORT_SYMBOL_GPL(vdpa_register_device);
130
131 /**
132  * vdpa_unregister_device - unregister a vDPA device
133  * @vdev: the vdpa device to be unregisted from vDPA bus
134  */
135 void vdpa_unregister_device(struct vdpa_device *vdev)
136 {
137         device_unregister(&vdev->dev);
138 }
139 EXPORT_SYMBOL_GPL(vdpa_unregister_device);
140
141 /**
142  * __vdpa_register_driver - register a vDPA device driver
143  * @drv: the vdpa device driver to be registered
144  * @owner: module owner of the driver
145  *
146  * Returns an err when fail to do the registration
147  */
148 int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner)
149 {
150         drv->driver.bus = &vdpa_bus;
151         drv->driver.owner = owner;
152
153         return driver_register(&drv->driver);
154 }
155 EXPORT_SYMBOL_GPL(__vdpa_register_driver);
156
157 /**
158  * vdpa_unregister_driver - unregister a vDPA device driver
159  * @drv: the vdpa device driver to be unregistered
160  */
161 void vdpa_unregister_driver(struct vdpa_driver *drv)
162 {
163         driver_unregister(&drv->driver);
164 }
165 EXPORT_SYMBOL_GPL(vdpa_unregister_driver);
166
167 static int vdpa_init(void)
168 {
169         return bus_register(&vdpa_bus);
170 }
171
172 static void __exit vdpa_exit(void)
173 {
174         bus_unregister(&vdpa_bus);
175         ida_destroy(&vdpa_index_ida);
176 }
177 core_initcall(vdpa_init);
178 module_exit(vdpa_exit);
179
180 MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>");
181 MODULE_LICENSE("GPL v2");