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