int most_register_interface()

in core.c [1279:1371]


int most_register_interface(struct most_interface *iface)
{
	unsigned int i;
	int id;
	struct most_channel *c;

	if (!iface || !iface->enqueue || !iface->configure ||
	    !iface->poison_channel || (iface->num_channels > MAX_CHANNELS))
		return -EINVAL;

	id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
	if (id < 0) {
		dev_err(iface->dev, "Failed to allocate device ID\n");
		return id;
	}

	iface->p = kzalloc(sizeof(*iface->p), GFP_KERNEL);
	if (!iface->p) {
		ida_simple_remove(&mdev_id, id);
		return -ENOMEM;
	}

	INIT_LIST_HEAD(&iface->p->channel_list);
	iface->p->dev_id = id;
	strscpy(iface->p->name, iface->description, sizeof(iface->p->name));
	iface->dev->bus = &mostbus;
	iface->dev->groups = interface_attr_groups;
	dev_set_drvdata(iface->dev, iface);
	if (device_register(iface->dev)) {
		dev_err(iface->dev, "Failed to register interface device\n");
		kfree(iface->p);
		put_device(iface->dev);
		ida_simple_remove(&mdev_id, id);
		return -ENOMEM;
	}

	for (i = 0; i < iface->num_channels; i++) {
		const char *name_suffix = iface->channel_vector[i].name_suffix;

		c = kzalloc(sizeof(*c), GFP_KERNEL);
		if (!c)
			goto err_free_resources;
		if (!name_suffix)
			snprintf(c->name, STRING_SIZE, "ch%d", i);
		else
			snprintf(c->name, STRING_SIZE, "%s", name_suffix);
		c->dev.init_name = c->name;
		c->dev.parent = iface->dev;
		c->dev.groups = channel_attr_groups;
		c->dev.release = release_channel;
		iface->p->channel[i] = c;
		c->is_starving = 0;
		c->iface = iface;
		c->channel_id = i;
		c->keep_mbo = false;
		c->enqueue_halt = false;
		c->is_poisoned = false;
		c->cfg.direction = 0;
		c->cfg.data_type = 0;
		c->cfg.num_buffers = 0;
		c->cfg.buffer_size = 0;
		c->cfg.subbuffer_size = 0;
		c->cfg.packets_per_xact = 0;
		spin_lock_init(&c->fifo_lock);
		INIT_LIST_HEAD(&c->fifo);
		INIT_LIST_HEAD(&c->trash_fifo);
		INIT_LIST_HEAD(&c->halt_fifo);
		init_completion(&c->cleanup);
		atomic_set(&c->mbo_ref, 0);
		mutex_init(&c->start_mutex);
		mutex_init(&c->nq_mutex);
		list_add_tail(&c->list, &iface->p->channel_list);
		if (device_register(&c->dev)) {
			dev_err(&c->dev, "Failed to register channel device\n");
			goto err_free_most_channel;
		}
	}
	most_interface_register_notify(iface->description);
	return 0;

err_free_most_channel:
	put_device(&c->dev);

err_free_resources:
	while (i > 0) {
		c = iface->p->channel[--i];
		device_unregister(&c->dev);
	}
	kfree(iface->p);
	device_unregister(iface->dev);
	ida_simple_remove(&mdev_id, id);
	return -ENOMEM;
}