in vdpa_user/vduse_dev.c [1297:1369]
static int vduse_create_dev(struct vduse_dev_config *config,
void *config_buf, u64 api_version)
{
int i, ret;
struct vduse_dev *dev;
ret = -EEXIST;
if (vduse_find_dev(config->name))
goto err;
ret = -ENOMEM;
dev = vduse_dev_create();
if (!dev)
goto err;
dev->api_version = api_version;
dev->device_features = config->features;
dev->device_id = config->device_id;
dev->vendor_id = config->vendor_id;
dev->name = kstrdup(config->name, GFP_KERNEL);
if (!dev->name)
goto err_str;
dev->domain = vduse_domain_create(VDUSE_IOVA_SIZE - 1,
VDUSE_BOUNCE_SIZE);
if (!dev->domain)
goto err_domain;
dev->config = config_buf;
dev->config_size = config->config_size;
dev->vq_align = config->vq_align;
dev->vq_num = config->vq_num;
dev->vqs = kcalloc(dev->vq_num, sizeof(*dev->vqs), GFP_KERNEL);
if (!dev->vqs)
goto err_vqs;
for (i = 0; i < dev->vq_num; i++) {
dev->vqs[i].index = i;
INIT_WORK(&dev->vqs[i].inject, vduse_vq_irq_inject);
INIT_WORK(&dev->vqs[i].kick, vduse_vq_kick_work);
spin_lock_init(&dev->vqs[i].kick_lock);
spin_lock_init(&dev->vqs[i].irq_lock);
}
ret = idr_alloc(&vduse_idr, dev, 1, VDUSE_DEV_MAX, GFP_KERNEL);
if (ret < 0)
goto err_idr;
dev->minor = ret;
dev->msg_timeout = VDUSE_MSG_DEFAULT_TIMEOUT;
dev->dev = device_create(vduse_class, NULL,
MKDEV(MAJOR(vduse_major), dev->minor),
dev, "%s", config->name);
if (IS_ERR(dev->dev)) {
ret = PTR_ERR(dev->dev);
goto err_dev;
}
__module_get(THIS_MODULE);
return 0;
err_dev:
idr_remove(&vduse_idr, dev->minor);
err_idr:
kfree(dev->vqs);
err_vqs:
vduse_domain_destroy(dev->domain);
err_domain:
kfree(dev->name);
err_str:
vduse_dev_destroy(dev);
err:
return ret;
}