1 // SPDX-License-Identifier: GPL-2.0
3 * configfs.c - Implementation of configfs interface to the driver stack
5 * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
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>
16 #define MAX_STRING_SIZE 80
19 struct config_item item
;
20 struct list_head list
;
28 char datatype
[MAX_STRING_SIZE
];
29 char direction
[MAX_STRING_SIZE
];
30 char name
[MAX_STRING_SIZE
];
31 char device
[MAX_STRING_SIZE
];
32 char channel
[MAX_STRING_SIZE
];
33 char comp
[MAX_STRING_SIZE
];
34 char comp_params
[MAX_STRING_SIZE
];
37 static struct list_head mdev_link_list
;
39 static int set_cfg_buffer_size(struct mdev_link
*link
)
41 return most_set_cfg_buffer_size(link
->device
, link
->channel
,
45 static int set_cfg_subbuffer_size(struct mdev_link
*link
)
47 return most_set_cfg_subbuffer_size(link
->device
, link
->channel
,
48 link
->subbuffer_size
);
51 static int set_cfg_dbr_size(struct mdev_link
*link
)
53 return most_set_cfg_dbr_size(link
->device
, link
->channel
,
57 static int set_cfg_num_buffers(struct mdev_link
*link
)
59 return most_set_cfg_num_buffers(link
->device
, link
->channel
,
63 static int set_cfg_packets_xact(struct mdev_link
*link
)
65 return most_set_cfg_packets_xact(link
->device
, link
->channel
,
66 link
->packets_per_xact
);
69 static int set_cfg_direction(struct mdev_link
*link
)
71 return most_set_cfg_direction(link
->device
, link
->channel
,
75 static int set_cfg_datatype(struct mdev_link
*link
)
77 return most_set_cfg_datatype(link
->device
, link
->channel
,
81 static int (*set_config_val
[])(struct mdev_link
*link
) = {
83 set_cfg_subbuffer_size
,
91 static struct mdev_link
*to_mdev_link(struct config_item
*item
)
93 return container_of(item
, struct mdev_link
, item
);
96 static int set_config_and_add_link(struct mdev_link
*mdev_link
)
101 for (i
= 0; i
< ARRAY_SIZE(set_config_val
); i
++) {
102 ret
= set_config_val
[i
](mdev_link
);
103 if (ret
< 0 && ret
!= -ENODEV
) {
104 pr_err("Config failed\n");
109 return most_add_link(mdev_link
->device
, mdev_link
->channel
,
110 mdev_link
->comp
, mdev_link
->name
,
111 mdev_link
->comp_params
);
114 static ssize_t
mdev_link_create_link_store(struct config_item
*item
,
115 const char *page
, size_t count
)
117 struct mdev_link
*mdev_link
= to_mdev_link(item
);
121 ret
= kstrtobool(page
, &tmp
);
126 ret
= set_config_and_add_link(mdev_link
);
127 if (ret
&& ret
!= -ENODEV
)
129 list_add_tail(&mdev_link
->list
, &mdev_link_list
);
130 mdev_link
->create_link
= tmp
;
131 mdev_link
->destroy_link
= false;
136 static ssize_t
mdev_link_destroy_link_store(struct config_item
*item
,
137 const char *page
, size_t count
)
139 struct mdev_link
*mdev_link
= to_mdev_link(item
);
143 ret
= kstrtobool(page
, &tmp
);
149 ret
= most_remove_link(mdev_link
->device
, mdev_link
->channel
,
153 if (!list_empty(&mdev_link_list
))
154 list_del(&mdev_link
->list
);
156 mdev_link
->destroy_link
= tmp
;
161 static ssize_t
mdev_link_direction_show(struct config_item
*item
, char *page
)
163 return snprintf(page
, PAGE_SIZE
, "%s\n", to_mdev_link(item
)->direction
);
166 static ssize_t
mdev_link_direction_store(struct config_item
*item
,
167 const char *page
, size_t count
)
169 struct mdev_link
*mdev_link
= to_mdev_link(item
);
171 if (!sysfs_streq(page
, "dir_rx") && !sysfs_streq(page
, "rx") &&
172 !sysfs_streq(page
, "dir_tx") && !sysfs_streq(page
, "tx"))
174 strcpy(mdev_link
->direction
, page
);
175 strim(mdev_link
->direction
);
179 static ssize_t
mdev_link_datatype_show(struct config_item
*item
, char *page
)
181 return snprintf(page
, PAGE_SIZE
, "%s\n", to_mdev_link(item
)->datatype
);
184 static ssize_t
mdev_link_datatype_store(struct config_item
*item
,
185 const char *page
, size_t count
)
187 struct mdev_link
*mdev_link
= to_mdev_link(item
);
189 if (!sysfs_streq(page
, "control") && !sysfs_streq(page
, "async") &&
190 !sysfs_streq(page
, "sync") && !sysfs_streq(page
, "isoc") &&
191 !sysfs_streq(page
, "isoc_avp"))
193 strcpy(mdev_link
->datatype
, page
);
194 strim(mdev_link
->datatype
);
198 static ssize_t
mdev_link_device_show(struct config_item
*item
, char *page
)
200 return snprintf(page
, PAGE_SIZE
, "%s\n", to_mdev_link(item
)->device
);
203 static ssize_t
mdev_link_device_store(struct config_item
*item
,
204 const char *page
, size_t count
)
206 struct mdev_link
*mdev_link
= to_mdev_link(item
);
208 strlcpy(mdev_link
->device
, page
, sizeof(mdev_link
->device
));
209 strim(mdev_link
->device
);
213 static ssize_t
mdev_link_channel_show(struct config_item
*item
, char *page
)
215 return snprintf(page
, PAGE_SIZE
, "%s\n", to_mdev_link(item
)->channel
);
218 static ssize_t
mdev_link_channel_store(struct config_item
*item
,
219 const char *page
, size_t count
)
221 struct mdev_link
*mdev_link
= to_mdev_link(item
);
223 strlcpy(mdev_link
->channel
, page
, sizeof(mdev_link
->channel
));
224 strim(mdev_link
->channel
);
228 static ssize_t
mdev_link_comp_show(struct config_item
*item
, char *page
)
230 return snprintf(page
, PAGE_SIZE
, "%s\n", to_mdev_link(item
)->comp
);
233 static ssize_t
mdev_link_comp_store(struct config_item
*item
,
234 const char *page
, size_t count
)
236 struct mdev_link
*mdev_link
= to_mdev_link(item
);
238 strlcpy(mdev_link
->comp
, page
, sizeof(mdev_link
->comp
));
239 strim(mdev_link
->comp
);
243 static ssize_t
mdev_link_comp_params_show(struct config_item
*item
, char *page
)
245 return snprintf(page
, PAGE_SIZE
, "%s\n",
246 to_mdev_link(item
)->comp_params
);
249 static ssize_t
mdev_link_comp_params_store(struct config_item
*item
,
250 const char *page
, size_t count
)
252 struct mdev_link
*mdev_link
= to_mdev_link(item
);
254 strlcpy(mdev_link
->comp_params
, page
, sizeof(mdev_link
->comp_params
));
255 strim(mdev_link
->comp_params
);
259 static ssize_t
mdev_link_num_buffers_show(struct config_item
*item
, char *page
)
261 return snprintf(page
, PAGE_SIZE
, "%d\n",
262 to_mdev_link(item
)->num_buffers
);
265 static ssize_t
mdev_link_num_buffers_store(struct config_item
*item
,
266 const char *page
, size_t count
)
268 struct mdev_link
*mdev_link
= to_mdev_link(item
);
271 ret
= kstrtou16(page
, 0, &mdev_link
->num_buffers
);
277 static ssize_t
mdev_link_buffer_size_show(struct config_item
*item
, char *page
)
279 return snprintf(page
, PAGE_SIZE
, "%d\n",
280 to_mdev_link(item
)->buffer_size
);
283 static ssize_t
mdev_link_buffer_size_store(struct config_item
*item
,
284 const char *page
, size_t count
)
286 struct mdev_link
*mdev_link
= to_mdev_link(item
);
289 ret
= kstrtou16(page
, 0, &mdev_link
->buffer_size
);
295 static ssize_t
mdev_link_subbuffer_size_show(struct config_item
*item
,
298 return snprintf(page
, PAGE_SIZE
, "%d\n",
299 to_mdev_link(item
)->subbuffer_size
);
302 static ssize_t
mdev_link_subbuffer_size_store(struct config_item
*item
,
303 const char *page
, size_t count
)
305 struct mdev_link
*mdev_link
= to_mdev_link(item
);
308 ret
= kstrtou16(page
, 0, &mdev_link
->subbuffer_size
);
314 static ssize_t
mdev_link_packets_per_xact_show(struct config_item
*item
,
317 return snprintf(page
, PAGE_SIZE
, "%d\n",
318 to_mdev_link(item
)->packets_per_xact
);
321 static ssize_t
mdev_link_packets_per_xact_store(struct config_item
*item
,
322 const char *page
, size_t count
)
324 struct mdev_link
*mdev_link
= to_mdev_link(item
);
327 ret
= kstrtou16(page
, 0, &mdev_link
->packets_per_xact
);
333 static ssize_t
mdev_link_dbr_size_show(struct config_item
*item
, char *page
)
335 return snprintf(page
, PAGE_SIZE
, "%d\n", to_mdev_link(item
)->dbr_size
);
338 static ssize_t
mdev_link_dbr_size_store(struct config_item
*item
,
339 const char *page
, size_t count
)
341 struct mdev_link
*mdev_link
= to_mdev_link(item
);
344 ret
= kstrtou16(page
, 0, &mdev_link
->dbr_size
);
350 CONFIGFS_ATTR_WO(mdev_link_
, create_link
);
351 CONFIGFS_ATTR_WO(mdev_link_
, destroy_link
);
352 CONFIGFS_ATTR(mdev_link_
, device
);
353 CONFIGFS_ATTR(mdev_link_
, channel
);
354 CONFIGFS_ATTR(mdev_link_
, comp
);
355 CONFIGFS_ATTR(mdev_link_
, comp_params
);
356 CONFIGFS_ATTR(mdev_link_
, num_buffers
);
357 CONFIGFS_ATTR(mdev_link_
, buffer_size
);
358 CONFIGFS_ATTR(mdev_link_
, subbuffer_size
);
359 CONFIGFS_ATTR(mdev_link_
, packets_per_xact
);
360 CONFIGFS_ATTR(mdev_link_
, datatype
);
361 CONFIGFS_ATTR(mdev_link_
, direction
);
362 CONFIGFS_ATTR(mdev_link_
, dbr_size
);
364 static struct configfs_attribute
*mdev_link_attrs
[] = {
365 &mdev_link_attr_create_link
,
366 &mdev_link_attr_destroy_link
,
367 &mdev_link_attr_device
,
368 &mdev_link_attr_channel
,
369 &mdev_link_attr_comp
,
370 &mdev_link_attr_comp_params
,
371 &mdev_link_attr_num_buffers
,
372 &mdev_link_attr_buffer_size
,
373 &mdev_link_attr_subbuffer_size
,
374 &mdev_link_attr_packets_per_xact
,
375 &mdev_link_attr_datatype
,
376 &mdev_link_attr_direction
,
377 &mdev_link_attr_dbr_size
,
381 static void mdev_link_release(struct config_item
*item
)
383 struct mdev_link
*mdev_link
= to_mdev_link(item
);
386 if (mdev_link
->destroy_link
)
389 ret
= most_remove_link(mdev_link
->device
, mdev_link
->channel
,
392 pr_err("Removing link failed.\n");
396 if (!list_empty(&mdev_link_list
))
397 list_del(&mdev_link
->list
);
400 kfree(to_mdev_link(item
));
403 static struct configfs_item_operations mdev_link_item_ops
= {
404 .release
= mdev_link_release
,
407 static const struct config_item_type mdev_link_type
= {
408 .ct_item_ops
= &mdev_link_item_ops
,
409 .ct_attrs
= mdev_link_attrs
,
410 .ct_owner
= THIS_MODULE
,
414 struct config_group group
;
416 struct configfs_subsystem subsys
;
419 static struct most_common
*to_most_common(struct configfs_subsystem
*subsys
)
421 return container_of(subsys
, struct most_common
, subsys
);
424 static struct config_item
*most_common_make_item(struct config_group
*group
,
427 struct mdev_link
*mdev_link
;
428 struct most_common
*mc
= to_most_common(group
->cg_subsys
);
430 mdev_link
= kzalloc(sizeof(*mdev_link
), GFP_KERNEL
);
432 return ERR_PTR(-ENOMEM
);
434 if (!try_module_get(mc
->mod
)) {
436 return ERR_PTR(-ENOLCK
);
438 config_item_init_type_name(&mdev_link
->item
, name
,
441 if (!strcmp(group
->cg_item
.ci_namebuf
, "most_cdev"))
442 strcpy(mdev_link
->comp
, "cdev");
443 else if (!strcmp(group
->cg_item
.ci_namebuf
, "most_net"))
444 strcpy(mdev_link
->comp
, "net");
445 else if (!strcmp(group
->cg_item
.ci_namebuf
, "most_video"))
446 strcpy(mdev_link
->comp
, "video");
447 strcpy(mdev_link
->name
, name
);
448 return &mdev_link
->item
;
451 static void most_common_release(struct config_item
*item
)
453 struct config_group
*group
= to_config_group(item
);
455 kfree(to_most_common(group
->cg_subsys
));
458 static struct configfs_item_operations most_common_item_ops
= {
459 .release
= most_common_release
,
462 static void most_common_disconnect(struct config_group
*group
,
463 struct config_item
*item
)
465 struct most_common
*mc
= to_most_common(group
->cg_subsys
);
470 static struct configfs_group_operations most_common_group_ops
= {
471 .make_item
= most_common_make_item
,
472 .disconnect_notify
= most_common_disconnect
,
475 static const struct config_item_type most_common_type
= {
476 .ct_item_ops
= &most_common_item_ops
,
477 .ct_group_ops
= &most_common_group_ops
,
478 .ct_owner
= THIS_MODULE
,
481 static struct most_common most_cdev
= {
485 .ci_namebuf
= "most_cdev",
486 .ci_type
= &most_common_type
,
492 static struct most_common most_net
= {
496 .ci_namebuf
= "most_net",
497 .ci_type
= &most_common_type
,
503 static struct most_common most_video
= {
507 .ci_namebuf
= "most_video",
508 .ci_type
= &most_common_type
,
514 struct most_snd_grp
{
515 struct config_group group
;
517 struct list_head list
;
520 static struct most_snd_grp
*to_most_snd_grp(struct config_item
*item
)
522 return container_of(to_config_group(item
), struct most_snd_grp
, group
);
525 static struct config_item
*most_snd_grp_make_item(struct config_group
*group
,
528 struct mdev_link
*mdev_link
;
530 mdev_link
= kzalloc(sizeof(*mdev_link
), GFP_KERNEL
);
532 return ERR_PTR(-ENOMEM
);
534 config_item_init_type_name(&mdev_link
->item
, name
, &mdev_link_type
);
535 mdev_link
->create_link
= false;
536 strcpy(mdev_link
->name
, name
);
537 strcpy(mdev_link
->comp
, "sound");
538 return &mdev_link
->item
;
541 static ssize_t
most_snd_grp_create_card_store(struct config_item
*item
,
542 const char *page
, size_t count
)
544 struct most_snd_grp
*snd_grp
= to_most_snd_grp(item
);
548 ret
= kstrtobool(page
, &tmp
);
552 ret
= most_cfg_complete("sound");
556 snd_grp
->create_card
= tmp
;
560 CONFIGFS_ATTR_WO(most_snd_grp_
, create_card
);
562 static struct configfs_attribute
*most_snd_grp_attrs
[] = {
563 &most_snd_grp_attr_create_card
,
567 static void most_snd_grp_release(struct config_item
*item
)
569 struct most_snd_grp
*group
= to_most_snd_grp(item
);
571 list_del(&group
->list
);
575 static struct configfs_item_operations most_snd_grp_item_ops
= {
576 .release
= most_snd_grp_release
,
579 static struct configfs_group_operations most_snd_grp_group_ops
= {
580 .make_item
= most_snd_grp_make_item
,
583 static const struct config_item_type most_snd_grp_type
= {
584 .ct_item_ops
= &most_snd_grp_item_ops
,
585 .ct_group_ops
= &most_snd_grp_group_ops
,
586 .ct_attrs
= most_snd_grp_attrs
,
587 .ct_owner
= THIS_MODULE
,
591 struct configfs_subsystem subsys
;
592 struct list_head soundcard_list
;
596 static struct config_group
*most_sound_make_group(struct config_group
*group
,
599 struct most_snd_grp
*most
;
600 struct most_sound
*ms
= container_of(group
->cg_subsys
,
601 struct most_sound
, subsys
);
603 list_for_each_entry(most
, &ms
->soundcard_list
, list
) {
604 if (!most
->create_card
) {
605 pr_info("adapter configuration still in progress.\n");
606 return ERR_PTR(-EPROTO
);
609 if (!try_module_get(ms
->mod
))
610 return ERR_PTR(-ENOLCK
);
611 most
= kzalloc(sizeof(*most
), GFP_KERNEL
);
614 return ERR_PTR(-ENOMEM
);
616 config_group_init_type_name(&most
->group
, name
, &most_snd_grp_type
);
617 list_add_tail(&most
->list
, &ms
->soundcard_list
);
621 static void most_sound_disconnect(struct config_group
*group
,
622 struct config_item
*item
)
624 struct most_sound
*ms
= container_of(group
->cg_subsys
,
625 struct most_sound
, subsys
);
629 static struct configfs_group_operations most_sound_group_ops
= {
630 .make_group
= most_sound_make_group
,
631 .disconnect_notify
= most_sound_disconnect
,
634 static const struct config_item_type most_sound_type
= {
635 .ct_group_ops
= &most_sound_group_ops
,
636 .ct_owner
= THIS_MODULE
,
639 static struct most_sound most_sound_subsys
= {
643 .ci_namebuf
= "most_sound",
644 .ci_type
= &most_sound_type
,
650 int most_register_configfs_subsys(struct most_component
*c
)
654 if (!strcmp(c
->name
, "cdev")) {
655 most_cdev
.mod
= c
->mod
;
656 ret
= configfs_register_subsystem(&most_cdev
.subsys
);
657 } else if (!strcmp(c
->name
, "net")) {
658 most_net
.mod
= c
->mod
;
659 ret
= configfs_register_subsystem(&most_net
.subsys
);
660 } else if (!strcmp(c
->name
, "video")) {
661 most_video
.mod
= c
->mod
;
662 ret
= configfs_register_subsystem(&most_video
.subsys
);
663 } else if (!strcmp(c
->name
, "sound")) {
664 most_sound_subsys
.mod
= c
->mod
;
665 ret
= configfs_register_subsystem(&most_sound_subsys
.subsys
);
671 pr_err("Error %d while registering subsystem %s\n",
676 EXPORT_SYMBOL_GPL(most_register_configfs_subsys
);
678 void most_interface_register_notify(const char *mdev
)
680 bool register_snd_card
= false;
681 struct mdev_link
*mdev_link
;
683 list_for_each_entry(mdev_link
, &mdev_link_list
, list
) {
684 if (!strcmp(mdev_link
->device
, mdev
)) {
685 set_config_and_add_link(mdev_link
);
686 if (!strcmp(mdev_link
->comp
, "sound"))
687 register_snd_card
= true;
690 if (register_snd_card
)
691 most_cfg_complete("sound");
694 void most_deregister_configfs_subsys(struct most_component
*c
)
696 if (!strcmp(c
->name
, "cdev"))
697 configfs_unregister_subsystem(&most_cdev
.subsys
);
698 else if (!strcmp(c
->name
, "net"))
699 configfs_unregister_subsystem(&most_net
.subsys
);
700 else if (!strcmp(c
->name
, "video"))
701 configfs_unregister_subsystem(&most_video
.subsys
);
702 else if (!strcmp(c
->name
, "sound"))
703 configfs_unregister_subsystem(&most_sound_subsys
.subsys
);
705 EXPORT_SYMBOL_GPL(most_deregister_configfs_subsys
);
707 int __init
configfs_init(void)
709 config_group_init(&most_cdev
.subsys
.su_group
);
710 mutex_init(&most_cdev
.subsys
.su_mutex
);
712 config_group_init(&most_net
.subsys
.su_group
);
713 mutex_init(&most_net
.subsys
.su_mutex
);
715 config_group_init(&most_video
.subsys
.su_group
);
716 mutex_init(&most_video
.subsys
.su_mutex
);
718 config_group_init(&most_sound_subsys
.subsys
.su_group
);
719 mutex_init(&most_sound_subsys
.subsys
.su_mutex
);
721 INIT_LIST_HEAD(&most_sound_subsys
.soundcard_list
);
722 INIT_LIST_HEAD(&mdev_link_list
);