1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (c) 2020, Red Hat. All rights reserved.
6 * Author: Jason Wang <jasowang@redhat.com>
10 #include <linux/module.h>
11 #include <linux/idr.h>
12 #include <linux/slab.h>
13 #include <linux/vdpa.h>
15 static DEFINE_IDA(vdpa_index_ida);
17 static int vdpa_dev_probe(struct device *d)
19 struct vdpa_device *vdev = dev_to_vdpa(d);
20 struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver);
23 if (drv && drv->probe)
24 ret = drv->probe(vdev);
29 static int vdpa_dev_remove(struct device *d)
31 struct vdpa_device *vdev = dev_to_vdpa(d);
32 struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver);
34 if (drv && drv->remove)
40 static struct bus_type vdpa_bus = {
42 .probe = vdpa_dev_probe,
43 .remove = vdpa_dev_remove,
46 static void vdpa_release_dev(struct device *d)
48 struct vdpa_device *vdev = dev_to_vdpa(d);
49 const struct vdpa_config_ops *ops = vdev->config;
54 ida_simple_remove(&vdpa_index_ida, vdev->index);
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
66 * Driver should use vdpa_alloc_device() wrapper macro instead of
67 * using this directly.
69 * Returns an error when parent/config/dma_dev is not set or fail to get
72 struct vdpa_device *__vdpa_alloc_device(struct device *parent,
73 const struct vdpa_config_ops *config,
76 struct vdpa_device *vdev;
82 if (!!config->dma_map != !!config->dma_unmap)
86 vdev = kzalloc(size, GFP_KERNEL);
90 err = ida_simple_get(&vdpa_index_ida, 0, 0, GFP_KERNEL);
94 vdev->dev.bus = &vdpa_bus;
95 vdev->dev.parent = parent;
96 vdev->dev.release = vdpa_release_dev;
98 vdev->config = config;
99 vdev->features_valid = false;
101 err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index);
105 device_initialize(&vdev->dev);
110 ida_simple_remove(&vdpa_index_ida, vdev->index);
116 EXPORT_SYMBOL_GPL(__vdpa_alloc_device);
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
123 * Returns an error when fail to add to vDPA bus
125 int vdpa_register_device(struct vdpa_device *vdev)
127 return device_add(&vdev->dev);
129 EXPORT_SYMBOL_GPL(vdpa_register_device);
132 * vdpa_unregister_device - unregister a vDPA device
133 * @vdev: the vdpa device to be unregisted from vDPA bus
135 void vdpa_unregister_device(struct vdpa_device *vdev)
137 device_unregister(&vdev->dev);
139 EXPORT_SYMBOL_GPL(vdpa_unregister_device);
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
146 * Returns an err when fail to do the registration
148 int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner)
150 drv->driver.bus = &vdpa_bus;
151 drv->driver.owner = owner;
153 return driver_register(&drv->driver);
155 EXPORT_SYMBOL_GPL(__vdpa_register_driver);
158 * vdpa_unregister_driver - unregister a vDPA device driver
159 * @drv: the vdpa device driver to be unregistered
161 void vdpa_unregister_driver(struct vdpa_driver *drv)
163 driver_unregister(&drv->driver);
165 EXPORT_SYMBOL_GPL(vdpa_unregister_driver);
167 static int vdpa_init(void)
169 return bus_register(&vdpa_bus);
172 static void __exit vdpa_exit(void)
174 bus_unregister(&vdpa_bus);
175 ida_destroy(&vdpa_index_ida);
177 core_initcall(vdpa_init);
178 module_exit(vdpa_exit);
180 MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>");
181 MODULE_LICENSE("GPL v2");