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 * @nvqs: number of virtqueues supported by this device
65 * @size: size of the parent structure that contains private data
67 * Driver should use vdpa_alloc_device() wrapper macro instead of
68 * using this directly.
70 * Returns an error when parent/config/dma_dev is not set or fail to get
73 struct vdpa_device
*__vdpa_alloc_device(struct device
*parent
,
74 const struct vdpa_config_ops
*config
,
78 struct vdpa_device
*vdev
;
84 if (!!config
->dma_map
!= !!config
->dma_unmap
)
88 vdev
= kzalloc(size
, GFP_KERNEL
);
92 err
= ida_alloc(&vdpa_index_ida
, GFP_KERNEL
);
96 vdev
->dev
.bus
= &vdpa_bus
;
97 vdev
->dev
.parent
= parent
;
98 vdev
->dev
.release
= vdpa_release_dev
;
100 vdev
->config
= config
;
101 vdev
->features_valid
= false;
104 err
= dev_set_name(&vdev
->dev
, "vdpa%u", vdev
->index
);
108 device_initialize(&vdev
->dev
);
113 ida_simple_remove(&vdpa_index_ida
, vdev
->index
);
119 EXPORT_SYMBOL_GPL(__vdpa_alloc_device
);
122 * vdpa_register_device - register a vDPA device
123 * Callers must have a succeed call of vdpa_alloc_device() before.
124 * @vdev: the vdpa device to be registered to vDPA bus
126 * Returns an error when fail to add to vDPA bus
128 int vdpa_register_device(struct vdpa_device
*vdev
)
130 return device_add(&vdev
->dev
);
132 EXPORT_SYMBOL_GPL(vdpa_register_device
);
135 * vdpa_unregister_device - unregister a vDPA device
136 * @vdev: the vdpa device to be unregisted from vDPA bus
138 void vdpa_unregister_device(struct vdpa_device
*vdev
)
140 device_unregister(&vdev
->dev
);
142 EXPORT_SYMBOL_GPL(vdpa_unregister_device
);
145 * __vdpa_register_driver - register a vDPA device driver
146 * @drv: the vdpa device driver to be registered
147 * @owner: module owner of the driver
149 * Returns an err when fail to do the registration
151 int __vdpa_register_driver(struct vdpa_driver
*drv
, struct module
*owner
)
153 drv
->driver
.bus
= &vdpa_bus
;
154 drv
->driver
.owner
= owner
;
156 return driver_register(&drv
->driver
);
158 EXPORT_SYMBOL_GPL(__vdpa_register_driver
);
161 * vdpa_unregister_driver - unregister a vDPA device driver
162 * @drv: the vdpa device driver to be unregistered
164 void vdpa_unregister_driver(struct vdpa_driver
*drv
)
166 driver_unregister(&drv
->driver
);
168 EXPORT_SYMBOL_GPL(vdpa_unregister_driver
);
170 static int vdpa_init(void)
172 return bus_register(&vdpa_bus
);
175 static void __exit
vdpa_exit(void)
177 bus_unregister(&vdpa_bus
);
178 ida_destroy(&vdpa_index_ida
);
180 core_initcall(vdpa_init
);
181 module_exit(vdpa_exit
);
183 MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>");
184 MODULE_LICENSE("GPL v2");