File Index
Files and directories
Sign in
FILE

audio_manager.c

File preview with syntax highlighting.

linux-6.19.14/drivers/staging/greybus/audio_manager.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Greybus operations
  4 *
  5 * Copyright 2015-2016 Google Inc.
  6 */
  7
  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>
 14
 15#include "audio_manager.h"
 16#include "audio_manager_private.h"
 17
 18static struct kset *manager_kset;
 19
 20static LIST_HEAD(modules_list);
 21static DECLARE_RWSEM(modules_rwsem);
 22static DEFINE_IDA(module_id);
 23
 24/* helpers */
 25static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id)
 26{
 27	struct gb_audio_manager_module *module;
 28
 29	if (id < 0)
 30		return NULL;
 31
 32	list_for_each_entry(module, &modules_list, list) {
 33		if (module->id == id)
 34			return module;
 35	}
 36
 37	return NULL;
 38}
 39
 40/* public API */
 41int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc)
 42{
 43	struct gb_audio_manager_module *module;
 44	int id;
 45	int err;
 46
 47	id = ida_alloc(&module_id, GFP_KERNEL);
 48	if (id < 0)
 49		return id;
 50
 51	err = gb_audio_manager_module_create(&module, manager_kset,
 52					     id, desc);
 53	if (err) {
 54		ida_free(&module_id, id);
 55		return err;
 56	}
 57
 58	/* Add it to the list */
 59	down_write(&modules_rwsem);
 60	list_add_tail(&module->list, &modules_list);
 61	up_write(&modules_rwsem);
 62
 63	return module->id;
 64}
 65EXPORT_SYMBOL_GPL(gb_audio_manager_add);
 66
 67int gb_audio_manager_remove(int id)
 68{
 69	struct gb_audio_manager_module *module;
 70
 71	down_write(&modules_rwsem);
 72
 73	module = gb_audio_manager_get_locked(id);
 74	if (!module) {
 75		up_write(&modules_rwsem);
 76		return -EINVAL;
 77	}
 78	list_del(&module->list);
 79	kobject_put(&module->kobj);
 80	up_write(&modules_rwsem);
 81	ida_free(&module_id, id);
 82	return 0;
 83}
 84EXPORT_SYMBOL_GPL(gb_audio_manager_remove);
 85
 86void gb_audio_manager_remove_all(void)
 87{
 88	struct gb_audio_manager_module *module, *next;
 89	int is_empty;
 90
 91	down_write(&modules_rwsem);
 92
 93	list_for_each_entry_safe(module, next, &modules_list, list) {
 94		list_del(&module->list);
 95		ida_free(&module_id, module->id);
 96		kobject_put(&module->kobj);
 97	}
 98
 99	is_empty = list_empty(&modules_list);
100
101	up_write(&modules_rwsem);
102
103	if (!is_empty)
104		pr_warn("Not all nodes were deleted\n");
105}
106EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all);
107
108struct gb_audio_manager_module *gb_audio_manager_get_module(int id)
109{
110	struct gb_audio_manager_module *module;
111
112	down_read(&modules_rwsem);
113	module = gb_audio_manager_get_locked(id);
114	kobject_get(&module->kobj);
115	up_read(&modules_rwsem);
116	return module;
117}
118EXPORT_SYMBOL_GPL(gb_audio_manager_get_module);
119
120void gb_audio_manager_put_module(struct gb_audio_manager_module *module)
121{
122	kobject_put(&module->kobj);
123}
124EXPORT_SYMBOL_GPL(gb_audio_manager_put_module);
125
126int gb_audio_manager_dump_module(int id)
127{
128	struct gb_audio_manager_module *module;
129
130	down_read(&modules_rwsem);
131	module = gb_audio_manager_get_locked(id);
132	up_read(&modules_rwsem);
133
134	if (!module)
135		return -EINVAL;
136
137	gb_audio_manager_module_dump(module);
138	return 0;
139}
140EXPORT_SYMBOL_GPL(gb_audio_manager_dump_module);
141
142void gb_audio_manager_dump_all(void)
143{
144	struct gb_audio_manager_module *module;
145	int count = 0;
146
147	down_read(&modules_rwsem);
148	list_for_each_entry(module, &modules_list, list) {
149		gb_audio_manager_module_dump(module);
150		count++;
151	}
152	up_read(&modules_rwsem);
153
154	pr_info("Number of connected modules: %d\n", count);
155}
156EXPORT_SYMBOL_GPL(gb_audio_manager_dump_all);
157
158/*
159 * module init/deinit
160 */
161static int __init manager_init(void)
162{
163	manager_kset = kset_create_and_add(GB_AUDIO_MANAGER_NAME, NULL,
164					   kernel_kobj);
165	if (!manager_kset)
166		return -ENOMEM;
167
168#ifdef GB_AUDIO_MANAGER_SYSFS
169	gb_audio_manager_sysfs_init(&manager_kset->kobj);
170#endif
171
172	return 0;
173}
174
175static void __exit manager_exit(void)
176{
177	gb_audio_manager_remove_all();
178	kset_unregister(manager_kset);
179	ida_destroy(&module_id);
180}
181
182module_init(manager_init);
183module_exit(manager_exit);
184
185MODULE_DESCRIPTION("Greybus audio operations manager");
186MODULE_LICENSE("GPL");
187MODULE_AUTHOR("Svetlin Ankov <ankov_svetlin@projectara.com>");
~/ Read-only file preview.