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;
}