in stm/core.c [989:1048]
static int stm_source_link_add(struct stm_source_device *src,
struct stm_device *stm)
{
char *ids[] = { NULL, "default", NULL };
int err = -ENOMEM;
mutex_lock(&stm->link_mutex);
spin_lock(&stm->link_lock);
spin_lock(&src->link_lock);
/* src->link is dereferenced under stm_source_srcu but not the list */
rcu_assign_pointer(src->link, stm);
list_add_tail(&src->link_entry, &stm->link_list);
spin_unlock(&src->link_lock);
spin_unlock(&stm->link_lock);
mutex_unlock(&stm->link_mutex);
ids[0] = kstrdup(src->data->name, GFP_KERNEL);
if (!ids[0])
goto fail_detach;
err = stm_assign_first_policy(stm, &src->output, ids,
src->data->nr_chans);
kfree(ids[0]);
if (err)
goto fail_detach;
/* this is to notify the STM device that a new link has been made */
if (stm->data->link)
err = stm->data->link(stm->data, src->output.master,
src->output.channel);
if (err)
goto fail_free_output;
/* this is to let the source carry out all necessary preparations */
if (src->data->link)
src->data->link(src->data);
return 0;
fail_free_output:
stm_output_free(stm, &src->output);
fail_detach:
mutex_lock(&stm->link_mutex);
spin_lock(&stm->link_lock);
spin_lock(&src->link_lock);
rcu_assign_pointer(src->link, NULL);
list_del_init(&src->link_entry);
spin_unlock(&src->link_lock);
spin_unlock(&stm->link_lock);
mutex_unlock(&stm->link_mutex);
return err;
}