static int comp_probe()

in most_cdev.c [412:476]


static int comp_probe(struct most_interface *iface, int channel_id,
		      struct most_channel_config *cfg, char *name, char *args)
{
	struct comp_channel *c;
	unsigned long cl_flags;
	int retval;
	int current_minor;

	if (!cfg || !name)
		return -EINVAL;

	c = get_channel(iface, channel_id);
	if (c)
		return -EEXIST;

	current_minor = ida_simple_get(&comp.minor_id, 0, 0, GFP_KERNEL);
	if (current_minor < 0)
		return current_minor;

	c = kzalloc(sizeof(*c), GFP_KERNEL);
	if (!c) {
		retval = -ENOMEM;
		goto err_remove_ida;
	}

	c->devno = MKDEV(comp.major, current_minor);
	cdev_init(&c->cdev, &channel_fops);
	c->cdev.owner = THIS_MODULE;
	retval = cdev_add(&c->cdev, c->devno, 1);
	if (retval < 0)
		goto err_free_c;
	c->iface = iface;
	c->cfg = cfg;
	c->channel_id = channel_id;
	c->access_ref = 0;
	spin_lock_init(&c->unlink);
	INIT_KFIFO(c->fifo);
	retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL);
	if (retval)
		goto err_del_cdev_and_free_channel;
	init_waitqueue_head(&c->wq);
	mutex_init(&c->io_mutex);
	spin_lock_irqsave(&ch_list_lock, cl_flags);
	list_add_tail(&c->list, &channel_list);
	spin_unlock_irqrestore(&ch_list_lock, cl_flags);
	c->dev = device_create(comp.class, NULL, c->devno, NULL, "%s", name);

	if (IS_ERR(c->dev)) {
		retval = PTR_ERR(c->dev);
		goto err_free_kfifo_and_del_list;
	}
	kobject_uevent(&c->dev->kobj, KOBJ_ADD);
	return 0;

err_free_kfifo_and_del_list:
	kfifo_free(&c->fifo);
	list_del(&c->list);
err_del_cdev_and_free_channel:
	cdev_del(&c->cdev);
err_free_c:
	kfree(c);
err_remove_ida:
	ida_simple_remove(&comp.minor_id, current_minor);
	return retval;
}