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 * @nvqs: number of virtqueues supported by this device 65 * @size: size of the parent structure that contains private data 66 * 67 * Driver should use vdpa_alloc_device() wrapper macro instead of 68 * using this directly. 69 * 70 * Returns an error when parent/config/dma_dev is not set or fail to get 71 * ida. 72 */ 73 struct vdpa_device *__vdpa_alloc_device(struct device *parent, 74 const struct vdpa_config_ops *config, 75 int nvqs, 76 size_t size) 77 { 78 struct vdpa_device *vdev; 79 int err = -EINVAL; 80 81 if (!config) 82 goto err; 83 84 if (!!config->dma_map != !!config->dma_unmap) 85 goto err; 86 87 err = -ENOMEM; 88 vdev = kzalloc(size, GFP_KERNEL); 89 if (!vdev) 90 goto err; 91 92 err = ida_simple_get(&vdpa_index_ida, 0, 0, GFP_KERNEL); 93 if (err < 0) 94 goto err_ida; 95 96 vdev->dev.bus = &vdpa_bus; 97 vdev->dev.parent = parent; 98 vdev->dev.release = vdpa_release_dev; 99 vdev->index = err; 100 vdev->config = config; 101 vdev->features_valid = false; 102 vdev->nvqs = nvqs; 103 104 err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index); 105 if (err) 106 goto err_name; 107 108 device_initialize(&vdev->dev); 109 110 return vdev; 111 112 err_name: 113 ida_simple_remove(&vdpa_index_ida, vdev->index); 114 err_ida: 115 kfree(vdev); 116 err: 117 return ERR_PTR(err); 118 } 119 EXPORT_SYMBOL_GPL(__vdpa_alloc_device); 120 121 /** 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 125 * 126 * Returns an error when fail to add to vDPA bus 127 */ 128 int vdpa_register_device(struct vdpa_device *vdev) 129 { 130 return device_add(&vdev->dev); 131 } 132 EXPORT_SYMBOL_GPL(vdpa_register_device); 133 134 /** 135 * vdpa_unregister_device - unregister a vDPA device 136 * @vdev: the vdpa device to be unregisted from vDPA bus 137 */ 138 void vdpa_unregister_device(struct vdpa_device *vdev) 139 { 140 device_unregister(&vdev->dev); 141 } 142 EXPORT_SYMBOL_GPL(vdpa_unregister_device); 143 144 /** 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 148 * 149 * Returns an err when fail to do the registration 150 */ 151 int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner) 152 { 153 drv->driver.bus = &vdpa_bus; 154 drv->driver.owner = owner; 155 156 return driver_register(&drv->driver); 157 } 158 EXPORT_SYMBOL_GPL(__vdpa_register_driver); 159 160 /** 161 * vdpa_unregister_driver - unregister a vDPA device driver 162 * @drv: the vdpa device driver to be unregistered 163 */ 164 void vdpa_unregister_driver(struct vdpa_driver *drv) 165 { 166 driver_unregister(&drv->driver); 167 } 168 EXPORT_SYMBOL_GPL(vdpa_unregister_driver); 169 170 static int vdpa_init(void) 171 { 172 return bus_register(&vdpa_bus); 173 } 174 175 static void __exit vdpa_exit(void) 176 { 177 bus_unregister(&vdpa_bus); 178 ida_destroy(&vdpa_index_ida); 179 } 180 core_initcall(vdpa_init); 181 module_exit(vdpa_exit); 182 183 MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>"); 184 MODULE_LICENSE("GPL v2"); 185