1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright 2015-2016 Google Inc.
8 #include <linux/string.h>
9 #include <linux/sysfs.h>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/spinlock.h>
13 #include <linux/idr.h>
15 #include "audio_manager.h"
16 #include "audio_manager_private.h"
18 static struct kset *manager_kset;
20 static LIST_HEAD(modules_list);
21 static DECLARE_RWSEM(modules_rwsem);
22 static DEFINE_IDA(module_id);
25 static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id)
27 struct gb_audio_manager_module *module;
32 list_for_each_entry(module, &modules_list, list) {
41 int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc)
43 struct gb_audio_manager_module *module;
47 id = ida_simple_get(&module_id, 0, 0, GFP_KERNEL);
51 err = gb_audio_manager_module_create(&module, manager_kset,
54 ida_simple_remove(&module_id, id);
58 /* Add it to the list */
59 down_write(&modules_rwsem);
60 list_add_tail(&module->list, &modules_list);
61 up_write(&modules_rwsem);
65 EXPORT_SYMBOL_GPL(gb_audio_manager_add);
67 int gb_audio_manager_remove(int id)
69 struct gb_audio_manager_module *module;
71 down_write(&modules_rwsem);
73 module = gb_audio_manager_get_locked(id);
75 up_write(&modules_rwsem);
78 list_del(&module->list);
79 kobject_put(&module->kobj);
80 up_write(&modules_rwsem);
81 ida_simple_remove(&module_id, id);
84 EXPORT_SYMBOL_GPL(gb_audio_manager_remove);
86 void gb_audio_manager_remove_all(void)
88 struct gb_audio_manager_module *module, *next;
91 down_write(&modules_rwsem);
93 list_for_each_entry_safe(module, next, &modules_list, list) {
94 list_del(&module->list);
95 ida_simple_remove(&module_id, module->id);
96 kobject_put(&module->kobj);
99 is_empty = list_empty(&modules_list);
101 up_write(&modules_rwsem);
104 pr_warn("Not all nodes were deleted\n");
106 EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all);
108 struct gb_audio_manager_module *gb_audio_manager_get_module(int id)
110 struct gb_audio_manager_module *module;
112 down_read(&modules_rwsem);
113 module = gb_audio_manager_get_locked(id);
114 kobject_get(&module->kobj);
115 up_read(&modules_rwsem);
118 EXPORT_SYMBOL_GPL(gb_audio_manager_get_module);
120 void gb_audio_manager_put_module(struct gb_audio_manager_module *module)
122 kobject_put(&module->kobj);
124 EXPORT_SYMBOL_GPL(gb_audio_manager_put_module);
126 int gb_audio_manager_dump_module(int id)
128 struct gb_audio_manager_module *module;
130 down_read(&modules_rwsem);
131 module = gb_audio_manager_get_locked(id);
132 up_read(&modules_rwsem);
137 gb_audio_manager_module_dump(module);
140 EXPORT_SYMBOL_GPL(gb_audio_manager_dump_module);
142 void gb_audio_manager_dump_all(void)
144 struct gb_audio_manager_module *module;
147 down_read(&modules_rwsem);
148 list_for_each_entry(module, &modules_list, list) {
149 gb_audio_manager_module_dump(module);
152 up_read(&modules_rwsem);
154 pr_info("Number of connected modules: %d\n", count);
156 EXPORT_SYMBOL_GPL(gb_audio_manager_dump_all);
161 static int __init manager_init(void)
163 manager_kset = kset_create_and_add(GB_AUDIO_MANAGER_NAME, NULL,
168 #ifdef GB_AUDIO_MANAGER_SYSFS
169 gb_audio_manager_sysfs_init(&manager_kset->kobj);
175 static void __exit manager_exit(void)
177 gb_audio_manager_remove_all();
178 kset_unregister(manager_kset);
179 ida_destroy(&module_id);
182 module_init(manager_init);
183 module_exit(manager_exit);
185 MODULE_LICENSE("GPL");