root/drivers/staging/greybus/audio_manager.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gb_audio_manager_get_locked
  2. gb_audio_manager_add
  3. gb_audio_manager_remove
  4. gb_audio_manager_remove_all
  5. gb_audio_manager_get_module
  6. gb_audio_manager_put_module
  7. gb_audio_manager_dump_module
  8. gb_audio_manager_dump_all
  9. manager_init
  10. manager_exit

   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 
  18 static struct kset *manager_kset;
  19 
  20 static LIST_HEAD(modules_list);
  21 static DECLARE_RWSEM(modules_rwsem);
  22 static DEFINE_IDA(module_id);
  23 
  24 /* helpers */
  25 static 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 */
  41 int 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_simple_get(&module_id, 0, 0, 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_simple_remove(&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 }
  65 EXPORT_SYMBOL_GPL(gb_audio_manager_add);
  66 
  67 int 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_simple_remove(&module_id, id);
  82         return 0;
  83 }
  84 EXPORT_SYMBOL_GPL(gb_audio_manager_remove);
  85 
  86 void 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_simple_remove(&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 }
 106 EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all);
 107 
 108 struct 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 }
 118 EXPORT_SYMBOL_GPL(gb_audio_manager_get_module);
 119 
 120 void gb_audio_manager_put_module(struct gb_audio_manager_module *module)
 121 {
 122         kobject_put(&module->kobj);
 123 }
 124 EXPORT_SYMBOL_GPL(gb_audio_manager_put_module);
 125 
 126 int 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 }
 140 EXPORT_SYMBOL_GPL(gb_audio_manager_dump_module);
 141 
 142 void 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 }
 156 EXPORT_SYMBOL_GPL(gb_audio_manager_dump_all);
 157 
 158 /*
 159  * module init/deinit
 160  */
 161 static 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 
 175 static void __exit manager_exit(void)
 176 {
 177         gb_audio_manager_remove_all();
 178         kset_unregister(manager_kset);
 179         ida_destroy(&module_id);
 180 }
 181 
 182 module_init(manager_init);
 183 module_exit(manager_exit);
 184 
 185 MODULE_LICENSE("GPL");
 186 MODULE_AUTHOR("Svetlin Ankov <ankov_svetlin@projectara.com>");

/* [<][>][^][v][top][bottom][index][help] */