interconnect: qcom: Fix Kconfig indentation
[linux/fpc-iii.git] / drivers / staging / most / configfs.c
blob34a9fb53985c1e2cef9ddc0c48837a637e00e9cd
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * configfs.c - Implementation of configfs interface to the driver stack
5 * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
6 */
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 <most/core.h>
15 struct mdev_link {
16 struct config_item item;
17 struct list_head list;
18 bool create_link;
19 bool destroy_link;
20 u16 num_buffers;
21 u16 buffer_size;
22 u16 subbuffer_size;
23 u16 packets_per_xact;
24 u16 dbr_size;
25 char datatype[PAGE_SIZE];
26 char direction[PAGE_SIZE];
27 char name[PAGE_SIZE];
28 char device[PAGE_SIZE];
29 char channel[PAGE_SIZE];
30 char comp[PAGE_SIZE];
31 char comp_params[PAGE_SIZE];
34 static struct list_head mdev_link_list;
36 static int set_cfg_buffer_size(struct mdev_link *link)
38 return most_set_cfg_buffer_size(link->device, link->channel,
39 link->buffer_size);
42 static int set_cfg_subbuffer_size(struct mdev_link *link)
44 return most_set_cfg_subbuffer_size(link->device, link->channel,
45 link->subbuffer_size);
48 static int set_cfg_dbr_size(struct mdev_link *link)
50 return most_set_cfg_dbr_size(link->device, link->channel,
51 link->dbr_size);
54 static int set_cfg_num_buffers(struct mdev_link *link)
56 return most_set_cfg_num_buffers(link->device, link->channel,
57 link->num_buffers);
60 static int set_cfg_packets_xact(struct mdev_link *link)
62 return most_set_cfg_packets_xact(link->device, link->channel,
63 link->packets_per_xact);
66 static int set_cfg_direction(struct mdev_link *link)
68 return most_set_cfg_direction(link->device, link->channel,
69 link->direction);
72 static int set_cfg_datatype(struct mdev_link *link)
74 return most_set_cfg_datatype(link->device, link->channel,
75 link->datatype);
78 static int (*set_config_val[])(struct mdev_link *link) = {
79 set_cfg_buffer_size,
80 set_cfg_subbuffer_size,
81 set_cfg_dbr_size,
82 set_cfg_num_buffers,
83 set_cfg_packets_xact,
84 set_cfg_direction,
85 set_cfg_datatype,
88 static struct mdev_link *to_mdev_link(struct config_item *item)
90 return container_of(item, struct mdev_link, item);
93 static int set_config_and_add_link(struct mdev_link *mdev_link)
95 int i;
96 int ret;
98 for (i = 0; i < ARRAY_SIZE(set_config_val); i++) {
99 ret = set_config_val[i](mdev_link);
100 if (ret < 0 && ret != -ENODEV) {
101 pr_err("Config failed\n");
102 return ret;
106 return most_add_link(mdev_link->device, mdev_link->channel,
107 mdev_link->comp, mdev_link->name,
108 mdev_link->comp_params);
111 static ssize_t mdev_link_create_link_store(struct config_item *item,
112 const char *page, size_t count)
114 struct mdev_link *mdev_link = to_mdev_link(item);
115 bool tmp;
116 int ret;
118 ret = kstrtobool(page, &tmp);
119 if (ret)
120 return ret;
121 if (!tmp)
122 return count;
123 ret = set_config_and_add_link(mdev_link);
124 if (ret && ret != -ENODEV)
125 return ret;
126 list_add_tail(&mdev_link->list, &mdev_link_list);
127 mdev_link->create_link = tmp;
128 return count;
131 static ssize_t mdev_link_destroy_link_store(struct config_item *item,
132 const char *page, size_t count)
134 struct mdev_link *mdev_link = to_mdev_link(item);
135 bool tmp;
136 int ret;
138 ret = kstrtobool(page, &tmp);
139 if (ret)
140 return ret;
141 if (!tmp)
142 return count;
143 mdev_link->destroy_link = tmp;
144 ret = most_remove_link(mdev_link->device, mdev_link->channel,
145 mdev_link->comp);
146 if (ret)
147 return ret;
148 if (!list_empty(&mdev_link_list))
149 list_del(&mdev_link->list);
150 return count;
153 static ssize_t mdev_link_direction_show(struct config_item *item, char *page)
155 return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->direction);
158 static ssize_t mdev_link_direction_store(struct config_item *item,
159 const char *page, size_t count)
161 struct mdev_link *mdev_link = to_mdev_link(item);
163 if (!sysfs_streq(page, "dir_rx") && !sysfs_streq(page, "rx") &&
164 !sysfs_streq(page, "dir_tx") && !sysfs_streq(page, "tx"))
165 return -EINVAL;
166 strcpy(mdev_link->direction, page);
167 strim(mdev_link->direction);
168 return count;
171 static ssize_t mdev_link_datatype_show(struct config_item *item, char *page)
173 return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->datatype);
176 static ssize_t mdev_link_datatype_store(struct config_item *item,
177 const char *page, size_t count)
179 struct mdev_link *mdev_link = to_mdev_link(item);
181 if (!sysfs_streq(page, "control") && !sysfs_streq(page, "async") &&
182 !sysfs_streq(page, "sync") && !sysfs_streq(page, "isoc") &&
183 !sysfs_streq(page, "isoc_avp"))
184 return -EINVAL;
185 strcpy(mdev_link->datatype, page);
186 strim(mdev_link->datatype);
187 return count;
190 static ssize_t mdev_link_device_show(struct config_item *item, char *page)
192 return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->device);
195 static ssize_t mdev_link_device_store(struct config_item *item,
196 const char *page, size_t count)
198 struct mdev_link *mdev_link = to_mdev_link(item);
200 strcpy(mdev_link->device, page);
201 strim(mdev_link->device);
202 return count;
205 static ssize_t mdev_link_channel_show(struct config_item *item, char *page)
207 return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->channel);
210 static ssize_t mdev_link_channel_store(struct config_item *item,
211 const char *page, size_t count)
213 struct mdev_link *mdev_link = to_mdev_link(item);
215 strcpy(mdev_link->channel, page);
216 strim(mdev_link->channel);
217 return count;
220 static ssize_t mdev_link_comp_show(struct config_item *item, char *page)
222 return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->comp);
225 static ssize_t mdev_link_comp_store(struct config_item *item,
226 const char *page, size_t count)
228 struct mdev_link *mdev_link = to_mdev_link(item);
230 strcpy(mdev_link->comp, page);
231 return count;
234 static ssize_t mdev_link_comp_params_show(struct config_item *item, char *page)
236 return snprintf(page, PAGE_SIZE, "%s\n",
237 to_mdev_link(item)->comp_params);
240 static ssize_t mdev_link_comp_params_store(struct config_item *item,
241 const char *page, size_t count)
243 struct mdev_link *mdev_link = to_mdev_link(item);
245 strcpy(mdev_link->comp_params, page);
246 return count;
249 static ssize_t mdev_link_num_buffers_show(struct config_item *item, char *page)
251 return snprintf(page, PAGE_SIZE, "%d\n",
252 to_mdev_link(item)->num_buffers);
255 static ssize_t mdev_link_num_buffers_store(struct config_item *item,
256 const char *page, size_t count)
258 struct mdev_link *mdev_link = to_mdev_link(item);
259 int ret;
261 ret = kstrtou16(page, 0, &mdev_link->num_buffers);
262 if (ret)
263 return ret;
264 return count;
267 static ssize_t mdev_link_buffer_size_show(struct config_item *item, char *page)
269 return snprintf(page, PAGE_SIZE, "%d\n",
270 to_mdev_link(item)->buffer_size);
273 static ssize_t mdev_link_buffer_size_store(struct config_item *item,
274 const char *page, size_t count)
276 struct mdev_link *mdev_link = to_mdev_link(item);
277 int ret;
279 ret = kstrtou16(page, 0, &mdev_link->buffer_size);
280 if (ret)
281 return ret;
282 return count;
285 static ssize_t mdev_link_subbuffer_size_show(struct config_item *item,
286 char *page)
288 return snprintf(page, PAGE_SIZE, "%d\n",
289 to_mdev_link(item)->subbuffer_size);
292 static ssize_t mdev_link_subbuffer_size_store(struct config_item *item,
293 const char *page, size_t count)
295 struct mdev_link *mdev_link = to_mdev_link(item);
296 int ret;
298 ret = kstrtou16(page, 0, &mdev_link->subbuffer_size);
299 if (ret)
300 return ret;
301 return count;
304 static ssize_t mdev_link_packets_per_xact_show(struct config_item *item,
305 char *page)
307 return snprintf(page, PAGE_SIZE, "%d\n",
308 to_mdev_link(item)->packets_per_xact);
311 static ssize_t mdev_link_packets_per_xact_store(struct config_item *item,
312 const char *page, size_t count)
314 struct mdev_link *mdev_link = to_mdev_link(item);
315 int ret;
317 ret = kstrtou16(page, 0, &mdev_link->packets_per_xact);
318 if (ret)
319 return ret;
320 return count;
323 static ssize_t mdev_link_dbr_size_show(struct config_item *item, char *page)
325 return snprintf(page, PAGE_SIZE, "%d\n", to_mdev_link(item)->dbr_size);
328 static ssize_t mdev_link_dbr_size_store(struct config_item *item,
329 const char *page, size_t count)
331 struct mdev_link *mdev_link = to_mdev_link(item);
332 int ret;
334 ret = kstrtou16(page, 0, &mdev_link->dbr_size);
335 if (ret)
336 return ret;
337 return count;
340 CONFIGFS_ATTR_WO(mdev_link_, create_link);
341 CONFIGFS_ATTR_WO(mdev_link_, destroy_link);
342 CONFIGFS_ATTR(mdev_link_, device);
343 CONFIGFS_ATTR(mdev_link_, channel);
344 CONFIGFS_ATTR(mdev_link_, comp);
345 CONFIGFS_ATTR(mdev_link_, comp_params);
346 CONFIGFS_ATTR(mdev_link_, num_buffers);
347 CONFIGFS_ATTR(mdev_link_, buffer_size);
348 CONFIGFS_ATTR(mdev_link_, subbuffer_size);
349 CONFIGFS_ATTR(mdev_link_, packets_per_xact);
350 CONFIGFS_ATTR(mdev_link_, datatype);
351 CONFIGFS_ATTR(mdev_link_, direction);
352 CONFIGFS_ATTR(mdev_link_, dbr_size);
354 static struct configfs_attribute *mdev_link_attrs[] = {
355 &mdev_link_attr_create_link,
356 &mdev_link_attr_destroy_link,
357 &mdev_link_attr_device,
358 &mdev_link_attr_channel,
359 &mdev_link_attr_comp,
360 &mdev_link_attr_comp_params,
361 &mdev_link_attr_num_buffers,
362 &mdev_link_attr_buffer_size,
363 &mdev_link_attr_subbuffer_size,
364 &mdev_link_attr_packets_per_xact,
365 &mdev_link_attr_datatype,
366 &mdev_link_attr_direction,
367 &mdev_link_attr_dbr_size,
368 NULL,
371 static void mdev_link_release(struct config_item *item)
373 struct mdev_link *mdev_link = to_mdev_link(item);
374 int ret;
376 if (!list_empty(&mdev_link_list)) {
377 ret = most_remove_link(mdev_link->device, mdev_link->channel,
378 mdev_link->comp);
379 if (ret && (ret != -ENODEV))
380 pr_err("Removing link failed.\n");
381 list_del(&mdev_link->list);
383 kfree(to_mdev_link(item));
386 static struct configfs_item_operations mdev_link_item_ops = {
387 .release = mdev_link_release,
390 static const struct config_item_type mdev_link_type = {
391 .ct_item_ops = &mdev_link_item_ops,
392 .ct_attrs = mdev_link_attrs,
393 .ct_owner = THIS_MODULE,
396 struct most_common {
397 struct config_group group;
398 struct module *mod;
399 struct configfs_subsystem subsys;
402 static struct most_common *to_most_common(struct configfs_subsystem *subsys)
404 return container_of(subsys, struct most_common, subsys);
407 static struct config_item *most_common_make_item(struct config_group *group,
408 const char *name)
410 struct mdev_link *mdev_link;
411 struct most_common *mc = to_most_common(group->cg_subsys);
413 mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL);
414 if (!mdev_link)
415 return ERR_PTR(-ENOMEM);
417 if (!try_module_get(mc->mod)) {
418 kfree(mdev_link);
419 return ERR_PTR(-ENOLCK);
421 config_item_init_type_name(&mdev_link->item, name,
422 &mdev_link_type);
424 if (!strcmp(group->cg_item.ci_namebuf, "most_cdev"))
425 strcpy(mdev_link->comp, "cdev");
426 else if (!strcmp(group->cg_item.ci_namebuf, "most_net"))
427 strcpy(mdev_link->comp, "net");
428 else if (!strcmp(group->cg_item.ci_namebuf, "most_video"))
429 strcpy(mdev_link->comp, "video");
430 strcpy(mdev_link->name, name);
431 return &mdev_link->item;
434 static void most_common_release(struct config_item *item)
436 struct config_group *group = to_config_group(item);
438 kfree(to_most_common(group->cg_subsys));
441 static struct configfs_item_operations most_common_item_ops = {
442 .release = most_common_release,
445 static void most_common_disconnect(struct config_group *group,
446 struct config_item *item)
448 struct most_common *mc = to_most_common(group->cg_subsys);
450 module_put(mc->mod);
453 static struct configfs_group_operations most_common_group_ops = {
454 .make_item = most_common_make_item,
455 .disconnect_notify = most_common_disconnect,
458 static const struct config_item_type most_common_type = {
459 .ct_item_ops = &most_common_item_ops,
460 .ct_group_ops = &most_common_group_ops,
461 .ct_owner = THIS_MODULE,
464 static struct most_common most_cdev = {
465 .subsys = {
466 .su_group = {
467 .cg_item = {
468 .ci_namebuf = "most_cdev",
469 .ci_type = &most_common_type,
475 static struct most_common most_net = {
476 .subsys = {
477 .su_group = {
478 .cg_item = {
479 .ci_namebuf = "most_net",
480 .ci_type = &most_common_type,
486 static struct most_common most_video = {
487 .subsys = {
488 .su_group = {
489 .cg_item = {
490 .ci_namebuf = "most_video",
491 .ci_type = &most_common_type,
497 struct most_snd_grp {
498 struct config_group group;
499 bool create_card;
500 struct list_head list;
503 static struct most_snd_grp *to_most_snd_grp(struct config_item *item)
505 return container_of(to_config_group(item), struct most_snd_grp, group);
508 static struct config_item *most_snd_grp_make_item(struct config_group *group,
509 const char *name)
511 struct mdev_link *mdev_link;
513 mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL);
514 if (!mdev_link)
515 return ERR_PTR(-ENOMEM);
517 config_item_init_type_name(&mdev_link->item, name, &mdev_link_type);
518 mdev_link->create_link = false;
519 strcpy(mdev_link->name, name);
520 strcpy(mdev_link->comp, "sound");
521 return &mdev_link->item;
524 static ssize_t most_snd_grp_create_card_store(struct config_item *item,
525 const char *page, size_t count)
527 struct most_snd_grp *snd_grp = to_most_snd_grp(item);
528 int ret;
529 bool tmp;
531 ret = kstrtobool(page, &tmp);
532 if (ret)
533 return ret;
534 if (tmp) {
535 ret = most_cfg_complete("sound");
536 if (ret)
537 return ret;
539 snd_grp->create_card = tmp;
540 return count;
543 CONFIGFS_ATTR_WO(most_snd_grp_, create_card);
545 static struct configfs_attribute *most_snd_grp_attrs[] = {
546 &most_snd_grp_attr_create_card,
547 NULL,
550 static void most_snd_grp_release(struct config_item *item)
552 struct most_snd_grp *group = to_most_snd_grp(item);
554 list_del(&group->list);
555 kfree(group);
558 static struct configfs_item_operations most_snd_grp_item_ops = {
559 .release = most_snd_grp_release,
562 static struct configfs_group_operations most_snd_grp_group_ops = {
563 .make_item = most_snd_grp_make_item,
566 static const struct config_item_type most_snd_grp_type = {
567 .ct_item_ops = &most_snd_grp_item_ops,
568 .ct_group_ops = &most_snd_grp_group_ops,
569 .ct_attrs = most_snd_grp_attrs,
570 .ct_owner = THIS_MODULE,
573 struct most_sound {
574 struct configfs_subsystem subsys;
575 struct list_head soundcard_list;
576 struct module *mod;
579 static struct config_group *most_sound_make_group(struct config_group *group,
580 const char *name)
582 struct most_snd_grp *most;
583 struct most_sound *ms = container_of(group->cg_subsys,
584 struct most_sound, subsys);
586 list_for_each_entry(most, &ms->soundcard_list, list) {
587 if (!most->create_card) {
588 pr_info("adapter configuration still in progress.\n");
589 return ERR_PTR(-EPROTO);
592 if (!try_module_get(ms->mod))
593 return ERR_PTR(-ENOLCK);
594 most = kzalloc(sizeof(*most), GFP_KERNEL);
595 if (!most) {
596 module_put(ms->mod);
597 return ERR_PTR(-ENOMEM);
599 config_group_init_type_name(&most->group, name, &most_snd_grp_type);
600 list_add_tail(&most->list, &ms->soundcard_list);
601 return &most->group;
604 static void most_sound_disconnect(struct config_group *group,
605 struct config_item *item)
607 struct most_sound *ms = container_of(group->cg_subsys,
608 struct most_sound, subsys);
609 module_put(ms->mod);
612 static struct configfs_group_operations most_sound_group_ops = {
613 .make_group = most_sound_make_group,
614 .disconnect_notify = most_sound_disconnect,
617 static const struct config_item_type most_sound_type = {
618 .ct_group_ops = &most_sound_group_ops,
619 .ct_owner = THIS_MODULE,
622 static struct most_sound most_sound_subsys = {
623 .subsys = {
624 .su_group = {
625 .cg_item = {
626 .ci_namebuf = "most_sound",
627 .ci_type = &most_sound_type,
633 int most_register_configfs_subsys(struct core_component *c)
635 int ret;
637 if (!strcmp(c->name, "cdev")) {
638 most_cdev.mod = c->mod;
639 ret = configfs_register_subsystem(&most_cdev.subsys);
640 } else if (!strcmp(c->name, "net")) {
641 most_net.mod = c->mod;
642 ret = configfs_register_subsystem(&most_net.subsys);
643 } else if (!strcmp(c->name, "video")) {
644 most_video.mod = c->mod;
645 ret = configfs_register_subsystem(&most_video.subsys);
646 } else if (!strcmp(c->name, "sound")) {
647 most_sound_subsys.mod = c->mod;
648 ret = configfs_register_subsystem(&most_sound_subsys.subsys);
649 } else {
650 return -ENODEV;
653 if (ret) {
654 pr_err("Error %d while registering subsystem %s\n",
655 ret, c->name);
657 return ret;
659 EXPORT_SYMBOL_GPL(most_register_configfs_subsys);
661 void most_interface_register_notify(const char *mdev)
663 bool register_snd_card = false;
664 struct mdev_link *mdev_link;
666 list_for_each_entry(mdev_link, &mdev_link_list, list) {
667 if (!strcmp(mdev_link->device, mdev)) {
668 set_config_and_add_link(mdev_link);
669 if (!strcmp(mdev_link->comp, "sound"))
670 register_snd_card = true;
673 if (register_snd_card)
674 most_cfg_complete("sound");
677 void most_deregister_configfs_subsys(struct core_component *c)
679 if (!strcmp(c->name, "cdev"))
680 configfs_unregister_subsystem(&most_cdev.subsys);
681 else if (!strcmp(c->name, "net"))
682 configfs_unregister_subsystem(&most_net.subsys);
683 else if (!strcmp(c->name, "video"))
684 configfs_unregister_subsystem(&most_video.subsys);
685 else if (!strcmp(c->name, "sound"))
686 configfs_unregister_subsystem(&most_sound_subsys.subsys);
688 EXPORT_SYMBOL_GPL(most_deregister_configfs_subsys);
690 int __init configfs_init(void)
692 config_group_init(&most_cdev.subsys.su_group);
693 mutex_init(&most_cdev.subsys.su_mutex);
695 config_group_init(&most_net.subsys.su_group);
696 mutex_init(&most_net.subsys.su_mutex);
698 config_group_init(&most_video.subsys.su_group);
699 mutex_init(&most_video.subsys.su_mutex);
701 config_group_init(&most_sound_subsys.subsys.su_group);
702 mutex_init(&most_sound_subsys.subsys.su_mutex);
704 INIT_LIST_HEAD(&most_sound_subsys.soundcard_list);
705 INIT_LIST_HEAD(&mdev_link_list);
707 return 0;