cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

configfs.c (18024B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * configfs.c - Implementation of configfs interface to the driver stack
      4 *
      5 * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
      6 */
      7
      8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      9#include <linux/module.h>
     10#include <linux/slab.h>
     11#include <linux/init.h>
     12#include <linux/configfs.h>
     13#include <linux/most.h>
     14
     15#define MAX_STRING_SIZE 80
     16
     17struct mdev_link {
     18	struct config_item item;
     19	struct list_head list;
     20	bool create_link;
     21	bool destroy_link;
     22	u16 num_buffers;
     23	u16 buffer_size;
     24	u16 subbuffer_size;
     25	u16 packets_per_xact;
     26	u16 dbr_size;
     27	char datatype[MAX_STRING_SIZE];
     28	char direction[MAX_STRING_SIZE];
     29	char name[MAX_STRING_SIZE];
     30	char device[MAX_STRING_SIZE];
     31	char channel[MAX_STRING_SIZE];
     32	char comp[MAX_STRING_SIZE];
     33	char comp_params[MAX_STRING_SIZE];
     34};
     35
     36static struct list_head mdev_link_list;
     37
     38static int set_cfg_buffer_size(struct mdev_link *link)
     39{
     40	return most_set_cfg_buffer_size(link->device, link->channel,
     41					link->buffer_size);
     42}
     43
     44static int set_cfg_subbuffer_size(struct mdev_link *link)
     45{
     46	return most_set_cfg_subbuffer_size(link->device, link->channel,
     47					   link->subbuffer_size);
     48}
     49
     50static int set_cfg_dbr_size(struct mdev_link *link)
     51{
     52	return most_set_cfg_dbr_size(link->device, link->channel,
     53				     link->dbr_size);
     54}
     55
     56static int set_cfg_num_buffers(struct mdev_link *link)
     57{
     58	return most_set_cfg_num_buffers(link->device, link->channel,
     59					link->num_buffers);
     60}
     61
     62static int set_cfg_packets_xact(struct mdev_link *link)
     63{
     64	return most_set_cfg_packets_xact(link->device, link->channel,
     65					 link->packets_per_xact);
     66}
     67
     68static int set_cfg_direction(struct mdev_link *link)
     69{
     70	return most_set_cfg_direction(link->device, link->channel,
     71				      link->direction);
     72}
     73
     74static int set_cfg_datatype(struct mdev_link *link)
     75{
     76	return most_set_cfg_datatype(link->device, link->channel,
     77				     link->datatype);
     78}
     79
     80static int (*set_config_val[])(struct mdev_link *link) = {
     81	set_cfg_buffer_size,
     82	set_cfg_subbuffer_size,
     83	set_cfg_dbr_size,
     84	set_cfg_num_buffers,
     85	set_cfg_packets_xact,
     86	set_cfg_direction,
     87	set_cfg_datatype,
     88};
     89
     90static struct mdev_link *to_mdev_link(struct config_item *item)
     91{
     92	return container_of(item, struct mdev_link, item);
     93}
     94
     95static int set_config_and_add_link(struct mdev_link *mdev_link)
     96{
     97	int i;
     98	int ret;
     99
    100	for (i = 0; i < ARRAY_SIZE(set_config_val); i++) {
    101		ret = set_config_val[i](mdev_link);
    102		if (ret < 0 && ret != -ENODEV) {
    103			pr_err("Config failed\n");
    104			return ret;
    105		}
    106	}
    107
    108	return most_add_link(mdev_link->device, mdev_link->channel,
    109			     mdev_link->comp, mdev_link->name,
    110			     mdev_link->comp_params);
    111}
    112
    113static ssize_t mdev_link_create_link_store(struct config_item *item,
    114					   const char *page, size_t count)
    115{
    116	struct mdev_link *mdev_link = to_mdev_link(item);
    117	bool tmp;
    118	int ret;
    119
    120	ret = kstrtobool(page, &tmp);
    121	if (ret)
    122		return ret;
    123	if (!tmp)
    124		return count;
    125	ret = set_config_and_add_link(mdev_link);
    126	if (ret && ret != -ENODEV)
    127		return ret;
    128	list_add_tail(&mdev_link->list, &mdev_link_list);
    129	mdev_link->create_link = tmp;
    130	mdev_link->destroy_link = false;
    131
    132	return count;
    133}
    134
    135static ssize_t mdev_link_destroy_link_store(struct config_item *item,
    136					    const char *page, size_t count)
    137{
    138	struct mdev_link *mdev_link = to_mdev_link(item);
    139	bool tmp;
    140	int ret;
    141
    142	ret = kstrtobool(page, &tmp);
    143	if (ret)
    144		return ret;
    145	if (!tmp)
    146		return count;
    147
    148	ret = most_remove_link(mdev_link->device, mdev_link->channel,
    149			       mdev_link->comp);
    150	if (ret)
    151		return ret;
    152	if (!list_empty(&mdev_link_list))
    153		list_del(&mdev_link->list);
    154
    155	mdev_link->destroy_link = tmp;
    156
    157	return count;
    158}
    159
    160static ssize_t mdev_link_direction_show(struct config_item *item, char *page)
    161{
    162	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->direction);
    163}
    164
    165static ssize_t mdev_link_direction_store(struct config_item *item,
    166					 const char *page, size_t count)
    167{
    168	struct mdev_link *mdev_link = to_mdev_link(item);
    169
    170	if (!sysfs_streq(page, "dir_rx") && !sysfs_streq(page, "rx") &&
    171	    !sysfs_streq(page, "dir_tx") && !sysfs_streq(page, "tx"))
    172		return -EINVAL;
    173	strcpy(mdev_link->direction, page);
    174	strim(mdev_link->direction);
    175	return count;
    176}
    177
    178static ssize_t mdev_link_datatype_show(struct config_item *item, char *page)
    179{
    180	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->datatype);
    181}
    182
    183static ssize_t mdev_link_datatype_store(struct config_item *item,
    184					const char *page, size_t count)
    185{
    186	struct mdev_link *mdev_link = to_mdev_link(item);
    187
    188	if (!sysfs_streq(page, "control") && !sysfs_streq(page, "async") &&
    189	    !sysfs_streq(page, "sync") && !sysfs_streq(page, "isoc") &&
    190	    !sysfs_streq(page, "isoc_avp"))
    191		return -EINVAL;
    192	strcpy(mdev_link->datatype, page);
    193	strim(mdev_link->datatype);
    194	return count;
    195}
    196
    197static ssize_t mdev_link_device_show(struct config_item *item, char *page)
    198{
    199	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->device);
    200}
    201
    202static ssize_t mdev_link_device_store(struct config_item *item,
    203				      const char *page, size_t count)
    204{
    205	struct mdev_link *mdev_link = to_mdev_link(item);
    206
    207	strlcpy(mdev_link->device, page, sizeof(mdev_link->device));
    208	strim(mdev_link->device);
    209	return count;
    210}
    211
    212static ssize_t mdev_link_channel_show(struct config_item *item, char *page)
    213{
    214	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->channel);
    215}
    216
    217static ssize_t mdev_link_channel_store(struct config_item *item,
    218				       const char *page, size_t count)
    219{
    220	struct mdev_link *mdev_link = to_mdev_link(item);
    221
    222	strlcpy(mdev_link->channel, page, sizeof(mdev_link->channel));
    223	strim(mdev_link->channel);
    224	return count;
    225}
    226
    227static ssize_t mdev_link_comp_show(struct config_item *item, char *page)
    228{
    229	return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->comp);
    230}
    231
    232static ssize_t mdev_link_comp_store(struct config_item *item,
    233				    const char *page, size_t count)
    234{
    235	struct mdev_link *mdev_link = to_mdev_link(item);
    236
    237	strlcpy(mdev_link->comp, page, sizeof(mdev_link->comp));
    238	strim(mdev_link->comp);
    239	return count;
    240}
    241
    242static ssize_t mdev_link_comp_params_show(struct config_item *item, char *page)
    243{
    244	return snprintf(page, PAGE_SIZE, "%s\n",
    245			to_mdev_link(item)->comp_params);
    246}
    247
    248static ssize_t mdev_link_comp_params_store(struct config_item *item,
    249					   const char *page, size_t count)
    250{
    251	struct mdev_link *mdev_link = to_mdev_link(item);
    252
    253	strlcpy(mdev_link->comp_params, page, sizeof(mdev_link->comp_params));
    254	strim(mdev_link->comp_params);
    255	return count;
    256}
    257
    258static ssize_t mdev_link_num_buffers_show(struct config_item *item, char *page)
    259{
    260	return snprintf(page, PAGE_SIZE, "%d\n",
    261			to_mdev_link(item)->num_buffers);
    262}
    263
    264static ssize_t mdev_link_num_buffers_store(struct config_item *item,
    265					   const char *page, size_t count)
    266{
    267	struct mdev_link *mdev_link = to_mdev_link(item);
    268	int ret;
    269
    270	ret = kstrtou16(page, 0, &mdev_link->num_buffers);
    271	if (ret)
    272		return ret;
    273	return count;
    274}
    275
    276static ssize_t mdev_link_buffer_size_show(struct config_item *item, char *page)
    277{
    278	return snprintf(page, PAGE_SIZE, "%d\n",
    279			to_mdev_link(item)->buffer_size);
    280}
    281
    282static ssize_t mdev_link_buffer_size_store(struct config_item *item,
    283					   const char *page, size_t count)
    284{
    285	struct mdev_link *mdev_link = to_mdev_link(item);
    286	int ret;
    287
    288	ret = kstrtou16(page, 0, &mdev_link->buffer_size);
    289	if (ret)
    290		return ret;
    291	return count;
    292}
    293
    294static ssize_t mdev_link_subbuffer_size_show(struct config_item *item,
    295					     char *page)
    296{
    297	return snprintf(page, PAGE_SIZE, "%d\n",
    298			to_mdev_link(item)->subbuffer_size);
    299}
    300
    301static ssize_t mdev_link_subbuffer_size_store(struct config_item *item,
    302					      const char *page, size_t count)
    303{
    304	struct mdev_link *mdev_link = to_mdev_link(item);
    305	int ret;
    306
    307	ret = kstrtou16(page, 0, &mdev_link->subbuffer_size);
    308	if (ret)
    309		return ret;
    310	return count;
    311}
    312
    313static ssize_t mdev_link_packets_per_xact_show(struct config_item *item,
    314					       char *page)
    315{
    316	return snprintf(page, PAGE_SIZE, "%d\n",
    317			to_mdev_link(item)->packets_per_xact);
    318}
    319
    320static ssize_t mdev_link_packets_per_xact_store(struct config_item *item,
    321						const char *page, size_t count)
    322{
    323	struct mdev_link *mdev_link = to_mdev_link(item);
    324	int ret;
    325
    326	ret = kstrtou16(page, 0, &mdev_link->packets_per_xact);
    327	if (ret)
    328		return ret;
    329	return count;
    330}
    331
    332static ssize_t mdev_link_dbr_size_show(struct config_item *item, char *page)
    333{
    334	return snprintf(page, PAGE_SIZE, "%d\n", to_mdev_link(item)->dbr_size);
    335}
    336
    337static ssize_t mdev_link_dbr_size_store(struct config_item *item,
    338					const char *page, size_t count)
    339{
    340	struct mdev_link *mdev_link = to_mdev_link(item);
    341	int ret;
    342
    343	ret = kstrtou16(page, 0, &mdev_link->dbr_size);
    344	if (ret)
    345		return ret;
    346	return count;
    347}
    348
    349CONFIGFS_ATTR_WO(mdev_link_, create_link);
    350CONFIGFS_ATTR_WO(mdev_link_, destroy_link);
    351CONFIGFS_ATTR(mdev_link_, device);
    352CONFIGFS_ATTR(mdev_link_, channel);
    353CONFIGFS_ATTR(mdev_link_, comp);
    354CONFIGFS_ATTR(mdev_link_, comp_params);
    355CONFIGFS_ATTR(mdev_link_, num_buffers);
    356CONFIGFS_ATTR(mdev_link_, buffer_size);
    357CONFIGFS_ATTR(mdev_link_, subbuffer_size);
    358CONFIGFS_ATTR(mdev_link_, packets_per_xact);
    359CONFIGFS_ATTR(mdev_link_, datatype);
    360CONFIGFS_ATTR(mdev_link_, direction);
    361CONFIGFS_ATTR(mdev_link_, dbr_size);
    362
    363static struct configfs_attribute *mdev_link_attrs[] = {
    364	&mdev_link_attr_create_link,
    365	&mdev_link_attr_destroy_link,
    366	&mdev_link_attr_device,
    367	&mdev_link_attr_channel,
    368	&mdev_link_attr_comp,
    369	&mdev_link_attr_comp_params,
    370	&mdev_link_attr_num_buffers,
    371	&mdev_link_attr_buffer_size,
    372	&mdev_link_attr_subbuffer_size,
    373	&mdev_link_attr_packets_per_xact,
    374	&mdev_link_attr_datatype,
    375	&mdev_link_attr_direction,
    376	&mdev_link_attr_dbr_size,
    377	NULL,
    378};
    379
    380static void mdev_link_release(struct config_item *item)
    381{
    382	struct mdev_link *mdev_link = to_mdev_link(item);
    383	int ret;
    384
    385	if (mdev_link->destroy_link)
    386		goto free_item;
    387
    388	ret = most_remove_link(mdev_link->device, mdev_link->channel,
    389			       mdev_link->comp);
    390	if (ret) {
    391		pr_err("Removing link failed.\n");
    392		goto free_item;
    393	}
    394
    395	if (!list_empty(&mdev_link_list))
    396		list_del(&mdev_link->list);
    397
    398free_item:
    399	kfree(to_mdev_link(item));
    400}
    401
    402static struct configfs_item_operations mdev_link_item_ops = {
    403	.release		= mdev_link_release,
    404};
    405
    406static const struct config_item_type mdev_link_type = {
    407	.ct_item_ops	= &mdev_link_item_ops,
    408	.ct_attrs	= mdev_link_attrs,
    409	.ct_owner	= THIS_MODULE,
    410};
    411
    412struct most_common {
    413	struct config_group group;
    414	struct module *mod;
    415	struct configfs_subsystem subsys;
    416};
    417
    418static struct most_common *to_most_common(struct configfs_subsystem *subsys)
    419{
    420	return container_of(subsys, struct most_common, subsys);
    421}
    422
    423static struct config_item *most_common_make_item(struct config_group *group,
    424						 const char *name)
    425{
    426	struct mdev_link *mdev_link;
    427	struct most_common *mc = to_most_common(group->cg_subsys);
    428
    429	mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL);
    430	if (!mdev_link)
    431		return ERR_PTR(-ENOMEM);
    432
    433	if (!try_module_get(mc->mod)) {
    434		kfree(mdev_link);
    435		return ERR_PTR(-ENOLCK);
    436	}
    437	config_item_init_type_name(&mdev_link->item, name,
    438				   &mdev_link_type);
    439
    440	if (!strcmp(group->cg_item.ci_namebuf, "most_cdev"))
    441		strcpy(mdev_link->comp, "cdev");
    442	else if (!strcmp(group->cg_item.ci_namebuf, "most_net"))
    443		strcpy(mdev_link->comp, "net");
    444	else if (!strcmp(group->cg_item.ci_namebuf, "most_video"))
    445		strcpy(mdev_link->comp, "video");
    446	strcpy(mdev_link->name, name);
    447	return &mdev_link->item;
    448}
    449
    450static void most_common_release(struct config_item *item)
    451{
    452	struct config_group *group = to_config_group(item);
    453
    454	kfree(to_most_common(group->cg_subsys));
    455}
    456
    457static struct configfs_item_operations most_common_item_ops = {
    458	.release	= most_common_release,
    459};
    460
    461static void most_common_disconnect(struct config_group *group,
    462				   struct config_item *item)
    463{
    464	struct most_common *mc = to_most_common(group->cg_subsys);
    465
    466	module_put(mc->mod);
    467}
    468
    469static struct configfs_group_operations most_common_group_ops = {
    470	.make_item	= most_common_make_item,
    471	.disconnect_notify = most_common_disconnect,
    472};
    473
    474static const struct config_item_type most_common_type = {
    475	.ct_item_ops	= &most_common_item_ops,
    476	.ct_group_ops	= &most_common_group_ops,
    477	.ct_owner	= THIS_MODULE,
    478};
    479
    480static struct most_common most_cdev = {
    481	.subsys = {
    482		.su_group = {
    483			.cg_item = {
    484				.ci_namebuf = "most_cdev",
    485				.ci_type = &most_common_type,
    486			},
    487		},
    488	},
    489};
    490
    491static struct most_common most_net = {
    492	.subsys = {
    493		.su_group = {
    494			.cg_item = {
    495				.ci_namebuf = "most_net",
    496				.ci_type = &most_common_type,
    497			},
    498		},
    499	},
    500};
    501
    502static struct most_common most_video = {
    503	.subsys = {
    504		.su_group = {
    505			.cg_item = {
    506				.ci_namebuf = "most_video",
    507				.ci_type = &most_common_type,
    508			},
    509		},
    510	},
    511};
    512
    513struct most_snd_grp {
    514	struct config_group group;
    515	bool create_card;
    516	struct list_head list;
    517};
    518
    519static struct most_snd_grp *to_most_snd_grp(struct config_item *item)
    520{
    521	return container_of(to_config_group(item), struct most_snd_grp, group);
    522}
    523
    524static struct config_item *most_snd_grp_make_item(struct config_group *group,
    525						  const char *name)
    526{
    527	struct mdev_link *mdev_link;
    528
    529	mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL);
    530	if (!mdev_link)
    531		return ERR_PTR(-ENOMEM);
    532
    533	config_item_init_type_name(&mdev_link->item, name, &mdev_link_type);
    534	mdev_link->create_link = false;
    535	strcpy(mdev_link->name, name);
    536	strcpy(mdev_link->comp, "sound");
    537	return &mdev_link->item;
    538}
    539
    540static ssize_t most_snd_grp_create_card_store(struct config_item *item,
    541					      const char *page, size_t count)
    542{
    543	struct most_snd_grp *snd_grp = to_most_snd_grp(item);
    544	int ret;
    545	bool tmp;
    546
    547	ret = kstrtobool(page, &tmp);
    548	if (ret)
    549		return ret;
    550	if (tmp) {
    551		ret = most_cfg_complete("sound");
    552		if (ret)
    553			return ret;
    554	}
    555	snd_grp->create_card = tmp;
    556	return count;
    557}
    558
    559CONFIGFS_ATTR_WO(most_snd_grp_, create_card);
    560
    561static struct configfs_attribute *most_snd_grp_attrs[] = {
    562	&most_snd_grp_attr_create_card,
    563	NULL,
    564};
    565
    566static void most_snd_grp_release(struct config_item *item)
    567{
    568	struct most_snd_grp *group = to_most_snd_grp(item);
    569
    570	list_del(&group->list);
    571	kfree(group);
    572}
    573
    574static struct configfs_item_operations most_snd_grp_item_ops = {
    575	.release	= most_snd_grp_release,
    576};
    577
    578static struct configfs_group_operations most_snd_grp_group_ops = {
    579	.make_item	= most_snd_grp_make_item,
    580};
    581
    582static const struct config_item_type most_snd_grp_type = {
    583	.ct_item_ops	= &most_snd_grp_item_ops,
    584	.ct_group_ops	= &most_snd_grp_group_ops,
    585	.ct_attrs	= most_snd_grp_attrs,
    586	.ct_owner	= THIS_MODULE,
    587};
    588
    589struct most_sound {
    590	struct configfs_subsystem subsys;
    591	struct list_head soundcard_list;
    592	struct module *mod;
    593};
    594
    595static struct config_group *most_sound_make_group(struct config_group *group,
    596						  const char *name)
    597{
    598	struct most_snd_grp *most;
    599	struct most_sound *ms = container_of(group->cg_subsys,
    600					     struct most_sound, subsys);
    601
    602	list_for_each_entry(most, &ms->soundcard_list, list) {
    603		if (!most->create_card) {
    604			pr_info("adapter configuration still in progress.\n");
    605			return ERR_PTR(-EPROTO);
    606		}
    607	}
    608	if (!try_module_get(ms->mod))
    609		return ERR_PTR(-ENOLCK);
    610	most = kzalloc(sizeof(*most), GFP_KERNEL);
    611	if (!most) {
    612		module_put(ms->mod);
    613		return ERR_PTR(-ENOMEM);
    614	}
    615	config_group_init_type_name(&most->group, name, &most_snd_grp_type);
    616	list_add_tail(&most->list, &ms->soundcard_list);
    617	return &most->group;
    618}
    619
    620static void most_sound_disconnect(struct config_group *group,
    621				  struct config_item *item)
    622{
    623	struct most_sound *ms = container_of(group->cg_subsys,
    624					     struct most_sound, subsys);
    625	module_put(ms->mod);
    626}
    627
    628static struct configfs_group_operations most_sound_group_ops = {
    629	.make_group	= most_sound_make_group,
    630	.disconnect_notify = most_sound_disconnect,
    631};
    632
    633static const struct config_item_type most_sound_type = {
    634	.ct_group_ops	= &most_sound_group_ops,
    635	.ct_owner	= THIS_MODULE,
    636};
    637
    638static struct most_sound most_sound_subsys = {
    639	.subsys = {
    640		.su_group = {
    641			.cg_item = {
    642				.ci_namebuf = "most_sound",
    643				.ci_type = &most_sound_type,
    644			},
    645		},
    646	},
    647};
    648
    649int most_register_configfs_subsys(struct most_component *c)
    650{
    651	int ret;
    652
    653	if (!strcmp(c->name, "cdev")) {
    654		most_cdev.mod = c->mod;
    655		ret = configfs_register_subsystem(&most_cdev.subsys);
    656	} else if (!strcmp(c->name, "net")) {
    657		most_net.mod = c->mod;
    658		ret = configfs_register_subsystem(&most_net.subsys);
    659	} else if (!strcmp(c->name, "video")) {
    660		most_video.mod = c->mod;
    661		ret = configfs_register_subsystem(&most_video.subsys);
    662	} else if (!strcmp(c->name, "sound")) {
    663		most_sound_subsys.mod = c->mod;
    664		ret = configfs_register_subsystem(&most_sound_subsys.subsys);
    665	} else {
    666		return -ENODEV;
    667	}
    668
    669	if (ret) {
    670		pr_err("Error %d while registering subsystem %s\n",
    671		       ret, c->name);
    672	}
    673	return ret;
    674}
    675EXPORT_SYMBOL_GPL(most_register_configfs_subsys);
    676
    677void most_interface_register_notify(const char *mdev)
    678{
    679	bool register_snd_card = false;
    680	struct mdev_link *mdev_link;
    681
    682	list_for_each_entry(mdev_link, &mdev_link_list, list) {
    683		if (!strcmp(mdev_link->device, mdev)) {
    684			set_config_and_add_link(mdev_link);
    685			if (!strcmp(mdev_link->comp, "sound"))
    686				register_snd_card = true;
    687		}
    688	}
    689	if (register_snd_card)
    690		most_cfg_complete("sound");
    691}
    692
    693void most_deregister_configfs_subsys(struct most_component *c)
    694{
    695	if (!strcmp(c->name, "cdev"))
    696		configfs_unregister_subsystem(&most_cdev.subsys);
    697	else if (!strcmp(c->name, "net"))
    698		configfs_unregister_subsystem(&most_net.subsys);
    699	else if (!strcmp(c->name, "video"))
    700		configfs_unregister_subsystem(&most_video.subsys);
    701	else if (!strcmp(c->name, "sound"))
    702		configfs_unregister_subsystem(&most_sound_subsys.subsys);
    703}
    704EXPORT_SYMBOL_GPL(most_deregister_configfs_subsys);
    705
    706int __init configfs_init(void)
    707{
    708	config_group_init(&most_cdev.subsys.su_group);
    709	mutex_init(&most_cdev.subsys.su_mutex);
    710
    711	config_group_init(&most_net.subsys.su_group);
    712	mutex_init(&most_net.subsys.su_mutex);
    713
    714	config_group_init(&most_video.subsys.su_group);
    715	mutex_init(&most_video.subsys.su_mutex);
    716
    717	config_group_init(&most_sound_subsys.subsys.su_group);
    718	mutex_init(&most_sound_subsys.subsys.su_mutex);
    719
    720	INIT_LIST_HEAD(&most_sound_subsys.soundcard_list);
    721	INIT_LIST_HEAD(&mdev_link_list);
    722
    723	return 0;
    724}