![Greg Kroah-Hartman](/assets/img/avatar_default.png)
Now that the SPDX tag is in all greybus files, that identifies the license in a specific and legally-defined manner. So the extra GPL text wording can be removed as it is no longer needed at all. This is done on a quest to remove the 700+ different ways that files in the kernel describe the GPL license text. And there's unneeded stuff like the address (sometimes incorrect) for the FSF which is never needed. No copyright headers or other non-license-description text was removed. Cc: Vaibhav Hiremath <hvaibhav.linux@gmail.com> Reviewed-by: Alex Elder <elder@linaro.org> Acked-by: Vaibhav Agarwal <vaibhav.sr@gmail.com> Acked-by: David Lin <dtwlin@gmail.com> Acked-by: Johan Hovold <johan@kernel.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Mark Greer <mgreer@animalcreek.com> Acked-by: Rui Miguel Silva <rmfrfs@gmail.com> Acked-by: "Bryan O'Donoghue" <pure.logic@nexus-software.ie> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
184 lines
3.8 KiB
C
184 lines
3.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Greybus operations
|
|
*
|
|
* Copyright 2015-2016 Google Inc.
|
|
*/
|
|
|
|
#include <linux/string.h>
|
|
#include <linux/sysfs.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/idr.h>
|
|
|
|
#include "audio_manager.h"
|
|
#include "audio_manager_private.h"
|
|
|
|
static struct kset *manager_kset;
|
|
|
|
static LIST_HEAD(modules_list);
|
|
static DECLARE_RWSEM(modules_rwsem);
|
|
static DEFINE_IDA(module_id);
|
|
|
|
/* helpers */
|
|
static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id)
|
|
{
|
|
struct gb_audio_manager_module *module;
|
|
|
|
if (id < 0)
|
|
return NULL;
|
|
|
|
list_for_each_entry(module, &modules_list, list) {
|
|
if (module->id == id)
|
|
return module;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* public API */
|
|
int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc)
|
|
{
|
|
struct gb_audio_manager_module *module;
|
|
int id;
|
|
int err;
|
|
|
|
id = ida_simple_get(&module_id, 0, 0, GFP_KERNEL);
|
|
err = gb_audio_manager_module_create(&module, manager_kset,
|
|
id, desc);
|
|
if (err) {
|
|
ida_simple_remove(&module_id, id);
|
|
return err;
|
|
}
|
|
|
|
/* Add it to the list */
|
|
down_write(&modules_rwsem);
|
|
list_add_tail(&module->list, &modules_list);
|
|
up_write(&modules_rwsem);
|
|
|
|
return module->id;
|
|
}
|
|
EXPORT_SYMBOL_GPL(gb_audio_manager_add);
|
|
|
|
int gb_audio_manager_remove(int id)
|
|
{
|
|
struct gb_audio_manager_module *module;
|
|
|
|
down_write(&modules_rwsem);
|
|
|
|
module = gb_audio_manager_get_locked(id);
|
|
if (!module) {
|
|
up_write(&modules_rwsem);
|
|
return -EINVAL;
|
|
}
|
|
list_del(&module->list);
|
|
kobject_put(&module->kobj);
|
|
up_write(&modules_rwsem);
|
|
ida_simple_remove(&module_id, id);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(gb_audio_manager_remove);
|
|
|
|
void gb_audio_manager_remove_all(void)
|
|
{
|
|
struct gb_audio_manager_module *module, *next;
|
|
int is_empty = 1;
|
|
|
|
down_write(&modules_rwsem);
|
|
|
|
list_for_each_entry_safe(module, next, &modules_list, list) {
|
|
list_del(&module->list);
|
|
kobject_put(&module->kobj);
|
|
ida_simple_remove(&module_id, module->id);
|
|
}
|
|
|
|
is_empty = list_empty(&modules_list);
|
|
|
|
up_write(&modules_rwsem);
|
|
|
|
if (!is_empty)
|
|
pr_warn("Not all nodes were deleted\n");
|
|
}
|
|
EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all);
|
|
|
|
struct gb_audio_manager_module *gb_audio_manager_get_module(int id)
|
|
{
|
|
struct gb_audio_manager_module *module;
|
|
|
|
down_read(&modules_rwsem);
|
|
module = gb_audio_manager_get_locked(id);
|
|
kobject_get(&module->kobj);
|
|
up_read(&modules_rwsem);
|
|
return module;
|
|
}
|
|
EXPORT_SYMBOL_GPL(gb_audio_manager_get_module);
|
|
|
|
void gb_audio_manager_put_module(struct gb_audio_manager_module *module)
|
|
{
|
|
kobject_put(&module->kobj);
|
|
}
|
|
EXPORT_SYMBOL_GPL(gb_audio_manager_put_module);
|
|
|
|
int gb_audio_manager_dump_module(int id)
|
|
{
|
|
struct gb_audio_manager_module *module;
|
|
|
|
down_read(&modules_rwsem);
|
|
module = gb_audio_manager_get_locked(id);
|
|
up_read(&modules_rwsem);
|
|
|
|
if (!module)
|
|
return -EINVAL;
|
|
|
|
gb_audio_manager_module_dump(module);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(gb_audio_manager_dump_module);
|
|
|
|
void gb_audio_manager_dump_all(void)
|
|
{
|
|
struct gb_audio_manager_module *module;
|
|
int count = 0;
|
|
|
|
down_read(&modules_rwsem);
|
|
list_for_each_entry(module, &modules_list, list) {
|
|
gb_audio_manager_module_dump(module);
|
|
count++;
|
|
}
|
|
up_read(&modules_rwsem);
|
|
|
|
pr_info("Number of connected modules: %d\n", count);
|
|
}
|
|
EXPORT_SYMBOL_GPL(gb_audio_manager_dump_all);
|
|
|
|
/*
|
|
* module init/deinit
|
|
*/
|
|
static int __init manager_init(void)
|
|
{
|
|
manager_kset = kset_create_and_add(GB_AUDIO_MANAGER_NAME, NULL,
|
|
kernel_kobj);
|
|
if (!manager_kset)
|
|
return -ENOMEM;
|
|
|
|
#ifdef GB_AUDIO_MANAGER_SYSFS
|
|
gb_audio_manager_sysfs_init(&manager_kset->kobj);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void __exit manager_exit(void)
|
|
{
|
|
gb_audio_manager_remove_all();
|
|
kset_unregister(manager_kset);
|
|
ida_destroy(&module_id);
|
|
}
|
|
|
|
module_init(manager_init);
|
|
module_exit(manager_exit);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Svetlin Ankov <ankov_svetlin@projectara.com>");
|