4 * Copyright 2015-2016 Google Inc.
6 * Released under the GPLv2 only.
9 #include <linux/string.h>
10 #include <linux/sysfs.h>
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/rwlock.h>
14 #include <linux/idr.h>
16 #include "audio_manager.h"
17 #include "audio_manager_private.h"
19 static struct kset *manager_kset;
21 static LIST_HEAD(modules_list);
22 static DECLARE_RWSEM(modules_rwsem);
23 static DEFINE_IDA(module_id);
26 static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id)
28 struct gb_audio_manager_module *module;
33 list_for_each_entry(module, &modules_list, list) {
42 int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc)
44 struct gb_audio_manager_module *module;
48 id = ida_simple_get(&module_id, 0, 0, GFP_KERNEL);
49 err = gb_audio_manager_module_create(&module, manager_kset,
52 ida_simple_remove(&module_id, id);
56 /* Add it to the list */
57 down_write(&modules_rwsem);
58 list_add_tail(&module->list, &modules_list);
59 up_write(&modules_rwsem);
63 EXPORT_SYMBOL_GPL(gb_audio_manager_add);
65 int gb_audio_manager_remove(int id)
67 struct gb_audio_manager_module *module;
69 down_write(&modules_rwsem);
71 module = gb_audio_manager_get_locked(id);
73 up_write(&modules_rwsem);
76 list_del(&module->list);
77 kobject_put(&module->kobj);
78 up_write(&modules_rwsem);
79 ida_simple_remove(&module_id, id);
82 EXPORT_SYMBOL_GPL(gb_audio_manager_remove);
84 void gb_audio_manager_remove_all(void)
86 struct gb_audio_manager_module *module, *next;
89 down_write(&modules_rwsem);
91 list_for_each_entry_safe(module, next, &modules_list, list) {
92 list_del(&module->list);
93 ida_simple_remove(&module_id, module->id);
94 kobject_put(&module->kobj);
97 is_empty = list_empty(&modules_list);
99 up_write(&modules_rwsem);
102 pr_warn("Not all nodes were deleted\n");
104 EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all);
106 struct gb_audio_manager_module *gb_audio_manager_get_module(int id)
108 struct gb_audio_manager_module *module;
110 down_read(&modules_rwsem);
111 module = gb_audio_manager_get_locked(id);
112 kobject_get(&module->kobj);
113 up_read(&modules_rwsem);
116 EXPORT_SYMBOL_GPL(gb_audio_manager_get_module);
118 void gb_audio_manager_put_module(struct gb_audio_manager_module *module)
120 kobject_put(&module->kobj);
122 EXPORT_SYMBOL_GPL(gb_audio_manager_put_module);
124 int gb_audio_manager_dump_module(int id)
126 struct gb_audio_manager_module *module;
128 down_read(&modules_rwsem);
129 module = gb_audio_manager_get_locked(id);
130 up_read(&modules_rwsem);
135 gb_audio_manager_module_dump(module);
138 EXPORT_SYMBOL_GPL(gb_audio_manager_dump_module);
140 void gb_audio_manager_dump_all(void)
142 struct gb_audio_manager_module *module;
145 down_read(&modules_rwsem);
146 list_for_each_entry(module, &modules_list, list) {
147 gb_audio_manager_module_dump(module);
150 up_read(&modules_rwsem);
152 pr_info("Number of connected modules: %d\n", count);
154 EXPORT_SYMBOL_GPL(gb_audio_manager_dump_all);
159 static int __init manager_init(void)
161 manager_kset = kset_create_and_add(GB_AUDIO_MANAGER_NAME, NULL,
166 #ifdef GB_AUDIO_MANAGER_SYSFS
167 gb_audio_manager_sysfs_init(&manager_kset->kobj);
173 static void __exit manager_exit(void)
175 gb_audio_manager_remove_all();
176 kset_unregister(manager_kset);
177 ida_destroy(&module_id);
180 module_init(manager_init);
181 module_exit(manager_exit);
183 MODULE_LICENSE("GPL");
184 MODULE_AUTHOR("Svetlin Ankov <ankov_svetlin@projectara.com>");