18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * configfs.c - Implementation of configfs interface to the driver stack
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/slab.h>
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <linux/configfs.h>
138c2ecf20Sopenharmony_ci#include <linux/most.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define MAX_STRING_SIZE 80
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistruct mdev_link {
188c2ecf20Sopenharmony_ci	struct config_item item;
198c2ecf20Sopenharmony_ci	struct list_head list;
208c2ecf20Sopenharmony_ci	bool create_link;
218c2ecf20Sopenharmony_ci	bool destroy_link;
228c2ecf20Sopenharmony_ci	u16 num_buffers;
238c2ecf20Sopenharmony_ci	u16 buffer_size;
248c2ecf20Sopenharmony_ci	u16 subbuffer_size;
258c2ecf20Sopenharmony_ci	u16 packets_per_xact;
268c2ecf20Sopenharmony_ci	u16 dbr_size;
278c2ecf20Sopenharmony_ci	char datatype[MAX_STRING_SIZE];
288c2ecf20Sopenharmony_ci	char direction[MAX_STRING_SIZE];
298c2ecf20Sopenharmony_ci	char name[MAX_STRING_SIZE];
308c2ecf20Sopenharmony_ci	char device[MAX_STRING_SIZE];
318c2ecf20Sopenharmony_ci	char channel[MAX_STRING_SIZE];
328c2ecf20Sopenharmony_ci	char comp[MAX_STRING_SIZE];
338c2ecf20Sopenharmony_ci	char comp_params[MAX_STRING_SIZE];
348c2ecf20Sopenharmony_ci};
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistatic struct list_head mdev_link_list;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic int set_cfg_buffer_size(struct mdev_link *link)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	return most_set_cfg_buffer_size(link->device, link->channel,
418c2ecf20Sopenharmony_ci					link->buffer_size);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic int set_cfg_subbuffer_size(struct mdev_link *link)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	return most_set_cfg_subbuffer_size(link->device, link->channel,
478c2ecf20Sopenharmony_ci					   link->subbuffer_size);
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic int set_cfg_dbr_size(struct mdev_link *link)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	return most_set_cfg_dbr_size(link->device, link->channel,
538c2ecf20Sopenharmony_ci				     link->dbr_size);
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic int set_cfg_num_buffers(struct mdev_link *link)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	return most_set_cfg_num_buffers(link->device, link->channel,
598c2ecf20Sopenharmony_ci					link->num_buffers);
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic int set_cfg_packets_xact(struct mdev_link *link)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	return most_set_cfg_packets_xact(link->device, link->channel,
658c2ecf20Sopenharmony_ci					 link->packets_per_xact);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic int set_cfg_direction(struct mdev_link *link)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	return most_set_cfg_direction(link->device, link->channel,
718c2ecf20Sopenharmony_ci				      link->direction);
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic int set_cfg_datatype(struct mdev_link *link)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	return most_set_cfg_datatype(link->device, link->channel,
778c2ecf20Sopenharmony_ci				     link->datatype);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic int (*set_config_val[])(struct mdev_link *link) = {
818c2ecf20Sopenharmony_ci	set_cfg_buffer_size,
828c2ecf20Sopenharmony_ci	set_cfg_subbuffer_size,
838c2ecf20Sopenharmony_ci	set_cfg_dbr_size,
848c2ecf20Sopenharmony_ci	set_cfg_num_buffers,
858c2ecf20Sopenharmony_ci	set_cfg_packets_xact,
868c2ecf20Sopenharmony_ci	set_cfg_direction,
878c2ecf20Sopenharmony_ci	set_cfg_datatype,
888c2ecf20Sopenharmony_ci};
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistatic struct mdev_link *to_mdev_link(struct config_item *item)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	return container_of(item, struct mdev_link, item);
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic int set_config_and_add_link(struct mdev_link *mdev_link)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	int i;
988c2ecf20Sopenharmony_ci	int ret;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(set_config_val); i++) {
1018c2ecf20Sopenharmony_ci		ret = set_config_val[i](mdev_link);
1028c2ecf20Sopenharmony_ci		if (ret < 0 && ret != -ENODEV) {
1038c2ecf20Sopenharmony_ci			pr_err("Config failed\n");
1048c2ecf20Sopenharmony_ci			return ret;
1058c2ecf20Sopenharmony_ci		}
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	return most_add_link(mdev_link->device, mdev_link->channel,
1098c2ecf20Sopenharmony_ci			     mdev_link->comp, mdev_link->name,
1108c2ecf20Sopenharmony_ci			     mdev_link->comp_params);
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic ssize_t mdev_link_create_link_store(struct config_item *item,
1148c2ecf20Sopenharmony_ci					   const char *page, size_t count)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
1178c2ecf20Sopenharmony_ci	bool tmp;
1188c2ecf20Sopenharmony_ci	int ret;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	ret = kstrtobool(page, &tmp);
1218c2ecf20Sopenharmony_ci	if (ret)
1228c2ecf20Sopenharmony_ci		return ret;
1238c2ecf20Sopenharmony_ci	if (!tmp)
1248c2ecf20Sopenharmony_ci		return count;
1258c2ecf20Sopenharmony_ci	ret = set_config_and_add_link(mdev_link);
1268c2ecf20Sopenharmony_ci	if (ret && ret != -ENODEV)
1278c2ecf20Sopenharmony_ci		return ret;
1288c2ecf20Sopenharmony_ci	list_add_tail(&mdev_link->list, &mdev_link_list);
1298c2ecf20Sopenharmony_ci	mdev_link->create_link = tmp;
1308c2ecf20Sopenharmony_ci	mdev_link->destroy_link = false;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	return count;
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic ssize_t mdev_link_destroy_link_store(struct config_item *item,
1368c2ecf20Sopenharmony_ci					    const char *page, size_t count)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
1398c2ecf20Sopenharmony_ci	bool tmp;
1408c2ecf20Sopenharmony_ci	int ret;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	ret = kstrtobool(page, &tmp);
1438c2ecf20Sopenharmony_ci	if (ret)
1448c2ecf20Sopenharmony_ci		return ret;
1458c2ecf20Sopenharmony_ci	if (!tmp)
1468c2ecf20Sopenharmony_ci		return count;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	ret = most_remove_link(mdev_link->device, mdev_link->channel,
1498c2ecf20Sopenharmony_ci			       mdev_link->comp);
1508c2ecf20Sopenharmony_ci	if (ret)
1518c2ecf20Sopenharmony_ci		return ret;
1528c2ecf20Sopenharmony_ci	if (!list_empty(&mdev_link_list))
1538c2ecf20Sopenharmony_ci		list_del(&mdev_link->list);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	mdev_link->destroy_link = tmp;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	return count;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic ssize_t mdev_link_direction_show(struct config_item *item, char *page)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->direction);
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic ssize_t mdev_link_direction_store(struct config_item *item,
1668c2ecf20Sopenharmony_ci					 const char *page, size_t count)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	if (!sysfs_streq(page, "dir_rx") && !sysfs_streq(page, "rx") &&
1718c2ecf20Sopenharmony_ci	    !sysfs_streq(page, "dir_tx") && !sysfs_streq(page, "tx"))
1728c2ecf20Sopenharmony_ci		return -EINVAL;
1738c2ecf20Sopenharmony_ci	strcpy(mdev_link->direction, page);
1748c2ecf20Sopenharmony_ci	strim(mdev_link->direction);
1758c2ecf20Sopenharmony_ci	return count;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic ssize_t mdev_link_datatype_show(struct config_item *item, char *page)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->datatype);
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic ssize_t mdev_link_datatype_store(struct config_item *item,
1848c2ecf20Sopenharmony_ci					const char *page, size_t count)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	if (!sysfs_streq(page, "control") && !sysfs_streq(page, "async") &&
1898c2ecf20Sopenharmony_ci	    !sysfs_streq(page, "sync") && !sysfs_streq(page, "isoc") &&
1908c2ecf20Sopenharmony_ci	    !sysfs_streq(page, "isoc_avp"))
1918c2ecf20Sopenharmony_ci		return -EINVAL;
1928c2ecf20Sopenharmony_ci	strcpy(mdev_link->datatype, page);
1938c2ecf20Sopenharmony_ci	strim(mdev_link->datatype);
1948c2ecf20Sopenharmony_ci	return count;
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic ssize_t mdev_link_device_show(struct config_item *item, char *page)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->device);
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic ssize_t mdev_link_device_store(struct config_item *item,
2038c2ecf20Sopenharmony_ci				      const char *page, size_t count)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	strlcpy(mdev_link->device, page, sizeof(mdev_link->device));
2088c2ecf20Sopenharmony_ci	strim(mdev_link->device);
2098c2ecf20Sopenharmony_ci	return count;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic ssize_t mdev_link_channel_show(struct config_item *item, char *page)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->channel);
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic ssize_t mdev_link_channel_store(struct config_item *item,
2188c2ecf20Sopenharmony_ci				       const char *page, size_t count)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	strlcpy(mdev_link->channel, page, sizeof(mdev_link->channel));
2238c2ecf20Sopenharmony_ci	strim(mdev_link->channel);
2248c2ecf20Sopenharmony_ci	return count;
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic ssize_t mdev_link_comp_show(struct config_item *item, char *page)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->comp);
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic ssize_t mdev_link_comp_store(struct config_item *item,
2338c2ecf20Sopenharmony_ci				    const char *page, size_t count)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	strlcpy(mdev_link->comp, page, sizeof(mdev_link->comp));
2388c2ecf20Sopenharmony_ci	strim(mdev_link->comp);
2398c2ecf20Sopenharmony_ci	return count;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic ssize_t mdev_link_comp_params_show(struct config_item *item, char *page)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%s\n",
2458c2ecf20Sopenharmony_ci			to_mdev_link(item)->comp_params);
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cistatic ssize_t mdev_link_comp_params_store(struct config_item *item,
2498c2ecf20Sopenharmony_ci					   const char *page, size_t count)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	strlcpy(mdev_link->comp_params, page, sizeof(mdev_link->comp_params));
2548c2ecf20Sopenharmony_ci	strim(mdev_link->comp_params);
2558c2ecf20Sopenharmony_ci	return count;
2568c2ecf20Sopenharmony_ci}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_cistatic ssize_t mdev_link_num_buffers_show(struct config_item *item, char *page)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%d\n",
2618c2ecf20Sopenharmony_ci			to_mdev_link(item)->num_buffers);
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_cistatic ssize_t mdev_link_num_buffers_store(struct config_item *item,
2658c2ecf20Sopenharmony_ci					   const char *page, size_t count)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
2688c2ecf20Sopenharmony_ci	int ret;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	ret = kstrtou16(page, 0, &mdev_link->num_buffers);
2718c2ecf20Sopenharmony_ci	if (ret)
2728c2ecf20Sopenharmony_ci		return ret;
2738c2ecf20Sopenharmony_ci	return count;
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_cistatic ssize_t mdev_link_buffer_size_show(struct config_item *item, char *page)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%d\n",
2798c2ecf20Sopenharmony_ci			to_mdev_link(item)->buffer_size);
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistatic ssize_t mdev_link_buffer_size_store(struct config_item *item,
2838c2ecf20Sopenharmony_ci					   const char *page, size_t count)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
2868c2ecf20Sopenharmony_ci	int ret;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	ret = kstrtou16(page, 0, &mdev_link->buffer_size);
2898c2ecf20Sopenharmony_ci	if (ret)
2908c2ecf20Sopenharmony_ci		return ret;
2918c2ecf20Sopenharmony_ci	return count;
2928c2ecf20Sopenharmony_ci}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic ssize_t mdev_link_subbuffer_size_show(struct config_item *item,
2958c2ecf20Sopenharmony_ci					     char *page)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%d\n",
2988c2ecf20Sopenharmony_ci			to_mdev_link(item)->subbuffer_size);
2998c2ecf20Sopenharmony_ci}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_cistatic ssize_t mdev_link_subbuffer_size_store(struct config_item *item,
3028c2ecf20Sopenharmony_ci					      const char *page, size_t count)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
3058c2ecf20Sopenharmony_ci	int ret;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	ret = kstrtou16(page, 0, &mdev_link->subbuffer_size);
3088c2ecf20Sopenharmony_ci	if (ret)
3098c2ecf20Sopenharmony_ci		return ret;
3108c2ecf20Sopenharmony_ci	return count;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cistatic ssize_t mdev_link_packets_per_xact_show(struct config_item *item,
3148c2ecf20Sopenharmony_ci					       char *page)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%d\n",
3178c2ecf20Sopenharmony_ci			to_mdev_link(item)->packets_per_xact);
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic ssize_t mdev_link_packets_per_xact_store(struct config_item *item,
3218c2ecf20Sopenharmony_ci						const char *page, size_t count)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
3248c2ecf20Sopenharmony_ci	int ret;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	ret = kstrtou16(page, 0, &mdev_link->packets_per_xact);
3278c2ecf20Sopenharmony_ci	if (ret)
3288c2ecf20Sopenharmony_ci		return ret;
3298c2ecf20Sopenharmony_ci	return count;
3308c2ecf20Sopenharmony_ci}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_cistatic ssize_t mdev_link_dbr_size_show(struct config_item *item, char *page)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	return snprintf(page, PAGE_SIZE, "%d\n", to_mdev_link(item)->dbr_size);
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic ssize_t mdev_link_dbr_size_store(struct config_item *item,
3388c2ecf20Sopenharmony_ci					const char *page, size_t count)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
3418c2ecf20Sopenharmony_ci	int ret;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	ret = kstrtou16(page, 0, &mdev_link->dbr_size);
3448c2ecf20Sopenharmony_ci	if (ret)
3458c2ecf20Sopenharmony_ci		return ret;
3468c2ecf20Sopenharmony_ci	return count;
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ciCONFIGFS_ATTR_WO(mdev_link_, create_link);
3508c2ecf20Sopenharmony_ciCONFIGFS_ATTR_WO(mdev_link_, destroy_link);
3518c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, device);
3528c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, channel);
3538c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, comp);
3548c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, comp_params);
3558c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, num_buffers);
3568c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, buffer_size);
3578c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, subbuffer_size);
3588c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, packets_per_xact);
3598c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, datatype);
3608c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, direction);
3618c2ecf20Sopenharmony_ciCONFIGFS_ATTR(mdev_link_, dbr_size);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic struct configfs_attribute *mdev_link_attrs[] = {
3648c2ecf20Sopenharmony_ci	&mdev_link_attr_create_link,
3658c2ecf20Sopenharmony_ci	&mdev_link_attr_destroy_link,
3668c2ecf20Sopenharmony_ci	&mdev_link_attr_device,
3678c2ecf20Sopenharmony_ci	&mdev_link_attr_channel,
3688c2ecf20Sopenharmony_ci	&mdev_link_attr_comp,
3698c2ecf20Sopenharmony_ci	&mdev_link_attr_comp_params,
3708c2ecf20Sopenharmony_ci	&mdev_link_attr_num_buffers,
3718c2ecf20Sopenharmony_ci	&mdev_link_attr_buffer_size,
3728c2ecf20Sopenharmony_ci	&mdev_link_attr_subbuffer_size,
3738c2ecf20Sopenharmony_ci	&mdev_link_attr_packets_per_xact,
3748c2ecf20Sopenharmony_ci	&mdev_link_attr_datatype,
3758c2ecf20Sopenharmony_ci	&mdev_link_attr_direction,
3768c2ecf20Sopenharmony_ci	&mdev_link_attr_dbr_size,
3778c2ecf20Sopenharmony_ci	NULL,
3788c2ecf20Sopenharmony_ci};
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_cistatic void mdev_link_release(struct config_item *item)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link = to_mdev_link(item);
3838c2ecf20Sopenharmony_ci	int ret;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	if (mdev_link->destroy_link)
3868c2ecf20Sopenharmony_ci		goto free_item;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	ret = most_remove_link(mdev_link->device, mdev_link->channel,
3898c2ecf20Sopenharmony_ci			       mdev_link->comp);
3908c2ecf20Sopenharmony_ci	if (ret) {
3918c2ecf20Sopenharmony_ci		pr_err("Removing link failed.\n");
3928c2ecf20Sopenharmony_ci		goto free_item;
3938c2ecf20Sopenharmony_ci	}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	if (!list_empty(&mdev_link_list))
3968c2ecf20Sopenharmony_ci		list_del(&mdev_link->list);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cifree_item:
3998c2ecf20Sopenharmony_ci	kfree(to_mdev_link(item));
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_cistatic struct configfs_item_operations mdev_link_item_ops = {
4038c2ecf20Sopenharmony_ci	.release		= mdev_link_release,
4048c2ecf20Sopenharmony_ci};
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cistatic const struct config_item_type mdev_link_type = {
4078c2ecf20Sopenharmony_ci	.ct_item_ops	= &mdev_link_item_ops,
4088c2ecf20Sopenharmony_ci	.ct_attrs	= mdev_link_attrs,
4098c2ecf20Sopenharmony_ci	.ct_owner	= THIS_MODULE,
4108c2ecf20Sopenharmony_ci};
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_cistruct most_common {
4138c2ecf20Sopenharmony_ci	struct config_group group;
4148c2ecf20Sopenharmony_ci	struct module *mod;
4158c2ecf20Sopenharmony_ci	struct configfs_subsystem subsys;
4168c2ecf20Sopenharmony_ci};
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_cistatic struct most_common *to_most_common(struct configfs_subsystem *subsys)
4198c2ecf20Sopenharmony_ci{
4208c2ecf20Sopenharmony_ci	return container_of(subsys, struct most_common, subsys);
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cistatic struct config_item *most_common_make_item(struct config_group *group,
4248c2ecf20Sopenharmony_ci						 const char *name)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link;
4278c2ecf20Sopenharmony_ci	struct most_common *mc = to_most_common(group->cg_subsys);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL);
4308c2ecf20Sopenharmony_ci	if (!mdev_link)
4318c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	if (!try_module_get(mc->mod)) {
4348c2ecf20Sopenharmony_ci		kfree(mdev_link);
4358c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOLCK);
4368c2ecf20Sopenharmony_ci	}
4378c2ecf20Sopenharmony_ci	config_item_init_type_name(&mdev_link->item, name,
4388c2ecf20Sopenharmony_ci				   &mdev_link_type);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	if (!strcmp(group->cg_item.ci_namebuf, "most_cdev"))
4418c2ecf20Sopenharmony_ci		strcpy(mdev_link->comp, "cdev");
4428c2ecf20Sopenharmony_ci	else if (!strcmp(group->cg_item.ci_namebuf, "most_net"))
4438c2ecf20Sopenharmony_ci		strcpy(mdev_link->comp, "net");
4448c2ecf20Sopenharmony_ci	else if (!strcmp(group->cg_item.ci_namebuf, "most_video"))
4458c2ecf20Sopenharmony_ci		strcpy(mdev_link->comp, "video");
4468c2ecf20Sopenharmony_ci	strcpy(mdev_link->name, name);
4478c2ecf20Sopenharmony_ci	return &mdev_link->item;
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_cistatic void most_common_release(struct config_item *item)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	struct config_group *group = to_config_group(item);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	kfree(to_most_common(group->cg_subsys));
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic struct configfs_item_operations most_common_item_ops = {
4588c2ecf20Sopenharmony_ci	.release	= most_common_release,
4598c2ecf20Sopenharmony_ci};
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_cistatic void most_common_disconnect(struct config_group *group,
4628c2ecf20Sopenharmony_ci				   struct config_item *item)
4638c2ecf20Sopenharmony_ci{
4648c2ecf20Sopenharmony_ci	struct most_common *mc = to_most_common(group->cg_subsys);
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	module_put(mc->mod);
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_cistatic struct configfs_group_operations most_common_group_ops = {
4708c2ecf20Sopenharmony_ci	.make_item	= most_common_make_item,
4718c2ecf20Sopenharmony_ci	.disconnect_notify = most_common_disconnect,
4728c2ecf20Sopenharmony_ci};
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_cistatic const struct config_item_type most_common_type = {
4758c2ecf20Sopenharmony_ci	.ct_item_ops	= &most_common_item_ops,
4768c2ecf20Sopenharmony_ci	.ct_group_ops	= &most_common_group_ops,
4778c2ecf20Sopenharmony_ci	.ct_owner	= THIS_MODULE,
4788c2ecf20Sopenharmony_ci};
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic struct most_common most_cdev = {
4818c2ecf20Sopenharmony_ci	.subsys = {
4828c2ecf20Sopenharmony_ci		.su_group = {
4838c2ecf20Sopenharmony_ci			.cg_item = {
4848c2ecf20Sopenharmony_ci				.ci_namebuf = "most_cdev",
4858c2ecf20Sopenharmony_ci				.ci_type = &most_common_type,
4868c2ecf20Sopenharmony_ci			},
4878c2ecf20Sopenharmony_ci		},
4888c2ecf20Sopenharmony_ci	},
4898c2ecf20Sopenharmony_ci};
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistatic struct most_common most_net = {
4928c2ecf20Sopenharmony_ci	.subsys = {
4938c2ecf20Sopenharmony_ci		.su_group = {
4948c2ecf20Sopenharmony_ci			.cg_item = {
4958c2ecf20Sopenharmony_ci				.ci_namebuf = "most_net",
4968c2ecf20Sopenharmony_ci				.ci_type = &most_common_type,
4978c2ecf20Sopenharmony_ci			},
4988c2ecf20Sopenharmony_ci		},
4998c2ecf20Sopenharmony_ci	},
5008c2ecf20Sopenharmony_ci};
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistatic struct most_common most_video = {
5038c2ecf20Sopenharmony_ci	.subsys = {
5048c2ecf20Sopenharmony_ci		.su_group = {
5058c2ecf20Sopenharmony_ci			.cg_item = {
5068c2ecf20Sopenharmony_ci				.ci_namebuf = "most_video",
5078c2ecf20Sopenharmony_ci				.ci_type = &most_common_type,
5088c2ecf20Sopenharmony_ci			},
5098c2ecf20Sopenharmony_ci		},
5108c2ecf20Sopenharmony_ci	},
5118c2ecf20Sopenharmony_ci};
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_cistruct most_snd_grp {
5148c2ecf20Sopenharmony_ci	struct config_group group;
5158c2ecf20Sopenharmony_ci	bool create_card;
5168c2ecf20Sopenharmony_ci	struct list_head list;
5178c2ecf20Sopenharmony_ci};
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_cistatic struct most_snd_grp *to_most_snd_grp(struct config_item *item)
5208c2ecf20Sopenharmony_ci{
5218c2ecf20Sopenharmony_ci	return container_of(to_config_group(item), struct most_snd_grp, group);
5228c2ecf20Sopenharmony_ci}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_cistatic struct config_item *most_snd_grp_make_item(struct config_group *group,
5258c2ecf20Sopenharmony_ci						  const char *name)
5268c2ecf20Sopenharmony_ci{
5278c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL);
5308c2ecf20Sopenharmony_ci	if (!mdev_link)
5318c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	config_item_init_type_name(&mdev_link->item, name, &mdev_link_type);
5348c2ecf20Sopenharmony_ci	mdev_link->create_link = false;
5358c2ecf20Sopenharmony_ci	strcpy(mdev_link->name, name);
5368c2ecf20Sopenharmony_ci	strcpy(mdev_link->comp, "sound");
5378c2ecf20Sopenharmony_ci	return &mdev_link->item;
5388c2ecf20Sopenharmony_ci}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_cistatic ssize_t most_snd_grp_create_card_store(struct config_item *item,
5418c2ecf20Sopenharmony_ci					      const char *page, size_t count)
5428c2ecf20Sopenharmony_ci{
5438c2ecf20Sopenharmony_ci	struct most_snd_grp *snd_grp = to_most_snd_grp(item);
5448c2ecf20Sopenharmony_ci	int ret;
5458c2ecf20Sopenharmony_ci	bool tmp;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	ret = kstrtobool(page, &tmp);
5488c2ecf20Sopenharmony_ci	if (ret)
5498c2ecf20Sopenharmony_ci		return ret;
5508c2ecf20Sopenharmony_ci	if (tmp) {
5518c2ecf20Sopenharmony_ci		ret = most_cfg_complete("sound");
5528c2ecf20Sopenharmony_ci		if (ret)
5538c2ecf20Sopenharmony_ci			return ret;
5548c2ecf20Sopenharmony_ci	}
5558c2ecf20Sopenharmony_ci	snd_grp->create_card = tmp;
5568c2ecf20Sopenharmony_ci	return count;
5578c2ecf20Sopenharmony_ci}
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ciCONFIGFS_ATTR_WO(most_snd_grp_, create_card);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_cistatic struct configfs_attribute *most_snd_grp_attrs[] = {
5628c2ecf20Sopenharmony_ci	&most_snd_grp_attr_create_card,
5638c2ecf20Sopenharmony_ci	NULL,
5648c2ecf20Sopenharmony_ci};
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_cistatic void most_snd_grp_release(struct config_item *item)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	struct most_snd_grp *group = to_most_snd_grp(item);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	list_del(&group->list);
5718c2ecf20Sopenharmony_ci	kfree(group);
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic struct configfs_item_operations most_snd_grp_item_ops = {
5758c2ecf20Sopenharmony_ci	.release	= most_snd_grp_release,
5768c2ecf20Sopenharmony_ci};
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_cistatic struct configfs_group_operations most_snd_grp_group_ops = {
5798c2ecf20Sopenharmony_ci	.make_item	= most_snd_grp_make_item,
5808c2ecf20Sopenharmony_ci};
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic const struct config_item_type most_snd_grp_type = {
5838c2ecf20Sopenharmony_ci	.ct_item_ops	= &most_snd_grp_item_ops,
5848c2ecf20Sopenharmony_ci	.ct_group_ops	= &most_snd_grp_group_ops,
5858c2ecf20Sopenharmony_ci	.ct_attrs	= most_snd_grp_attrs,
5868c2ecf20Sopenharmony_ci	.ct_owner	= THIS_MODULE,
5878c2ecf20Sopenharmony_ci};
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_cistruct most_sound {
5908c2ecf20Sopenharmony_ci	struct configfs_subsystem subsys;
5918c2ecf20Sopenharmony_ci	struct list_head soundcard_list;
5928c2ecf20Sopenharmony_ci	struct module *mod;
5938c2ecf20Sopenharmony_ci};
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_cistatic struct config_group *most_sound_make_group(struct config_group *group,
5968c2ecf20Sopenharmony_ci						  const char *name)
5978c2ecf20Sopenharmony_ci{
5988c2ecf20Sopenharmony_ci	struct most_snd_grp *most;
5998c2ecf20Sopenharmony_ci	struct most_sound *ms = container_of(group->cg_subsys,
6008c2ecf20Sopenharmony_ci					     struct most_sound, subsys);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	list_for_each_entry(most, &ms->soundcard_list, list) {
6038c2ecf20Sopenharmony_ci		if (!most->create_card) {
6048c2ecf20Sopenharmony_ci			pr_info("adapter configuration still in progress.\n");
6058c2ecf20Sopenharmony_ci			return ERR_PTR(-EPROTO);
6068c2ecf20Sopenharmony_ci		}
6078c2ecf20Sopenharmony_ci	}
6088c2ecf20Sopenharmony_ci	if (!try_module_get(ms->mod))
6098c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOLCK);
6108c2ecf20Sopenharmony_ci	most = kzalloc(sizeof(*most), GFP_KERNEL);
6118c2ecf20Sopenharmony_ci	if (!most) {
6128c2ecf20Sopenharmony_ci		module_put(ms->mod);
6138c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
6148c2ecf20Sopenharmony_ci	}
6158c2ecf20Sopenharmony_ci	config_group_init_type_name(&most->group, name, &most_snd_grp_type);
6168c2ecf20Sopenharmony_ci	list_add_tail(&most->list, &ms->soundcard_list);
6178c2ecf20Sopenharmony_ci	return &most->group;
6188c2ecf20Sopenharmony_ci}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_cistatic void most_sound_disconnect(struct config_group *group,
6218c2ecf20Sopenharmony_ci				  struct config_item *item)
6228c2ecf20Sopenharmony_ci{
6238c2ecf20Sopenharmony_ci	struct most_sound *ms = container_of(group->cg_subsys,
6248c2ecf20Sopenharmony_ci					     struct most_sound, subsys);
6258c2ecf20Sopenharmony_ci	module_put(ms->mod);
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_cistatic struct configfs_group_operations most_sound_group_ops = {
6298c2ecf20Sopenharmony_ci	.make_group	= most_sound_make_group,
6308c2ecf20Sopenharmony_ci	.disconnect_notify = most_sound_disconnect,
6318c2ecf20Sopenharmony_ci};
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cistatic const struct config_item_type most_sound_type = {
6348c2ecf20Sopenharmony_ci	.ct_group_ops	= &most_sound_group_ops,
6358c2ecf20Sopenharmony_ci	.ct_owner	= THIS_MODULE,
6368c2ecf20Sopenharmony_ci};
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_cistatic struct most_sound most_sound_subsys = {
6398c2ecf20Sopenharmony_ci	.subsys = {
6408c2ecf20Sopenharmony_ci		.su_group = {
6418c2ecf20Sopenharmony_ci			.cg_item = {
6428c2ecf20Sopenharmony_ci				.ci_namebuf = "most_sound",
6438c2ecf20Sopenharmony_ci				.ci_type = &most_sound_type,
6448c2ecf20Sopenharmony_ci			},
6458c2ecf20Sopenharmony_ci		},
6468c2ecf20Sopenharmony_ci	},
6478c2ecf20Sopenharmony_ci};
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ciint most_register_configfs_subsys(struct most_component *c)
6508c2ecf20Sopenharmony_ci{
6518c2ecf20Sopenharmony_ci	int ret;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	if (!strcmp(c->name, "cdev")) {
6548c2ecf20Sopenharmony_ci		most_cdev.mod = c->mod;
6558c2ecf20Sopenharmony_ci		ret = configfs_register_subsystem(&most_cdev.subsys);
6568c2ecf20Sopenharmony_ci	} else if (!strcmp(c->name, "net")) {
6578c2ecf20Sopenharmony_ci		most_net.mod = c->mod;
6588c2ecf20Sopenharmony_ci		ret = configfs_register_subsystem(&most_net.subsys);
6598c2ecf20Sopenharmony_ci	} else if (!strcmp(c->name, "video")) {
6608c2ecf20Sopenharmony_ci		most_video.mod = c->mod;
6618c2ecf20Sopenharmony_ci		ret = configfs_register_subsystem(&most_video.subsys);
6628c2ecf20Sopenharmony_ci	} else if (!strcmp(c->name, "sound")) {
6638c2ecf20Sopenharmony_ci		most_sound_subsys.mod = c->mod;
6648c2ecf20Sopenharmony_ci		ret = configfs_register_subsystem(&most_sound_subsys.subsys);
6658c2ecf20Sopenharmony_ci	} else {
6668c2ecf20Sopenharmony_ci		return -ENODEV;
6678c2ecf20Sopenharmony_ci	}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	if (ret) {
6708c2ecf20Sopenharmony_ci		pr_err("Error %d while registering subsystem %s\n",
6718c2ecf20Sopenharmony_ci		       ret, c->name);
6728c2ecf20Sopenharmony_ci	}
6738c2ecf20Sopenharmony_ci	return ret;
6748c2ecf20Sopenharmony_ci}
6758c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(most_register_configfs_subsys);
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_civoid most_interface_register_notify(const char *mdev)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci	bool register_snd_card = false;
6808c2ecf20Sopenharmony_ci	struct mdev_link *mdev_link;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	list_for_each_entry(mdev_link, &mdev_link_list, list) {
6838c2ecf20Sopenharmony_ci		if (!strcmp(mdev_link->device, mdev)) {
6848c2ecf20Sopenharmony_ci			set_config_and_add_link(mdev_link);
6858c2ecf20Sopenharmony_ci			if (!strcmp(mdev_link->comp, "sound"))
6868c2ecf20Sopenharmony_ci				register_snd_card = true;
6878c2ecf20Sopenharmony_ci		}
6888c2ecf20Sopenharmony_ci	}
6898c2ecf20Sopenharmony_ci	if (register_snd_card)
6908c2ecf20Sopenharmony_ci		most_cfg_complete("sound");
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_civoid most_deregister_configfs_subsys(struct most_component *c)
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	if (!strcmp(c->name, "cdev"))
6968c2ecf20Sopenharmony_ci		configfs_unregister_subsystem(&most_cdev.subsys);
6978c2ecf20Sopenharmony_ci	else if (!strcmp(c->name, "net"))
6988c2ecf20Sopenharmony_ci		configfs_unregister_subsystem(&most_net.subsys);
6998c2ecf20Sopenharmony_ci	else if (!strcmp(c->name, "video"))
7008c2ecf20Sopenharmony_ci		configfs_unregister_subsystem(&most_video.subsys);
7018c2ecf20Sopenharmony_ci	else if (!strcmp(c->name, "sound"))
7028c2ecf20Sopenharmony_ci		configfs_unregister_subsystem(&most_sound_subsys.subsys);
7038c2ecf20Sopenharmony_ci}
7048c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(most_deregister_configfs_subsys);
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ciint __init configfs_init(void)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	config_group_init(&most_cdev.subsys.su_group);
7098c2ecf20Sopenharmony_ci	mutex_init(&most_cdev.subsys.su_mutex);
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	config_group_init(&most_net.subsys.su_group);
7128c2ecf20Sopenharmony_ci	mutex_init(&most_net.subsys.su_mutex);
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	config_group_init(&most_video.subsys.su_group);
7158c2ecf20Sopenharmony_ci	mutex_init(&most_video.subsys.su_mutex);
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	config_group_init(&most_sound_subsys.subsys.su_group);
7188c2ecf20Sopenharmony_ci	mutex_init(&most_sound_subsys.subsys.su_mutex);
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&most_sound_subsys.soundcard_list);
7218c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&mdev_link_list);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	return 0;
7248c2ecf20Sopenharmony_ci}
725