linux/drivers/most/configfs.c
<<
>>
Prefs
   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}
 725