@@ -43,10 +43,8 @@ extern struct _ddebug __start___dyndbg[];
extern struct _ddebug __stop___dyndbg[];
struct ddebug_table {
- struct list_head link;
+ struct list_head link, maps;
const char *mod_name;
- /* a module can have multiple class-sets eventually, but not yet */
- struct ddebug_known_classes_map const *map;
unsigned int num_ddebugs;
struct _ddebug *ddebugs;
};
@@ -149,28 +147,18 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
/* return <0 if class-name is unknown/invalid, 0..CLASS_DFLT otherwise */
static int ddebug_validate_classname(struct ddebug_table *dt, const char *class_string)
{
- int query_class = -ENOENT;
+ struct ddebug_known_classes_map *map;
int idx;
if (!class_string)
- /* all queries w/o class given work only on default class */
return _DPRINTK_CLASS_DFLT;
- /*
- * XXX single list will need to be a for-list
- * so that modules can have 2 sets of class-decls
- */
- if (!dt->map)
- return -ENOENT;
-
- idx = match_string(dt->map->classes, dt->map->length, class_string);
- if (idx < 0) {
- v3pr_info("class: %s.%s unknown\n", dt->mod_name, class_string);
- return -ENOENT;
+ list_for_each_entry(map, &dt->maps, link) {
+ idx = match_string(map->classes, map->length, class_string);
+ if (idx >= 0)
+ return idx + map->base;
}
- query_class = idx + dt->map->base;
-
- return query_class;
+ return -ENOENT;
}
/*
@@ -1032,8 +1020,14 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
static const char *ddebug_class_name(struct ddebug_iter *iter, struct _ddebug *dp)
{
- if (iter->table->map)
- return iter->table->map->classes[dp->class_id];
+ struct ddebug_known_classes_map *map;
+
+ list_for_each_entry(map, &iter->table->maps, link) {
+ if (dp->class_id < map->base ||
+ dp->class_id >= map->base + map->length)
+ continue;
+ return map->classes[dp->class_id - map->base];
+ }
return NULL;
}
@@ -1124,6 +1118,7 @@ int dynamic_debug_register_classes(struct ddebug_known_classes_map *map)
struct ddebug_table *dt;
int rc = -ENOENT;
+ INIT_LIST_HEAD(&map->link);
mutex_lock(&ddebug_lock);
#ifdef CONFIG_MODULES
if (map->mod) {
@@ -1131,7 +1126,7 @@ int dynamic_debug_register_classes(struct ddebug_known_classes_map *map)
list_for_each_entry(dt, &ddebug_tables, link) {
if (dt->mod_name == map->mod->name) {
rc = 0;
- dt->map = map;
+ list_add(&map->link, &dt->maps);
break;
}
}
@@ -1142,7 +1137,7 @@ int dynamic_debug_register_classes(struct ddebug_known_classes_map *map)
list_for_each_entry(dt, &ddebug_tables, link) {
if (!strcmp(dt->mod_name, map->mod_name)) {
rc = 0;
- dt->map = map;
+ list_add(&map->link, &dt->maps);
break;
}
}
@@ -1159,8 +1154,38 @@ EXPORT_SYMBOL(dynamic_debug_register_classes);
void dynamic_debug_unregister_classes(struct ddebug_known_classes_map *map)
{
- vpr_info("unregister_classes: %s\n", map->mod_name);
+ int rc = -ENOENT;
+
+ mutex_lock(&ddebug_lock);
+#ifdef CONFIG_MODULES
+ if (map->mod) {
+ struct ddebug_known_classes_map *dmap;
+ struct ddebug_table *dt;
+
+ list_for_each_entry(dt, &ddebug_tables, link) {
+ if (dt->mod_name != map->mod->name)
+ continue;
+ list_for_each_entry(dmap, &dt->maps, link) {
+ if (dmap != map)
+ continue;
+ rc = 0;
+ list_del(&map->link);
+ break;
+ }
+ }
+ }
+#endif
+ if (!map->mod) {
+ pr_err("shouldn't be unloading a builtin module: %s\n",
+ map->mod_name);
+ }
+ mutex_unlock(&ddebug_lock);
+ if (rc)
+ pr_warn("unregister_classes: module %s not found\n", map->mod_name);
+ else
+ vpr_info("unregister_classes: %s\n", map->mod_name);
}
+EXPORT_SYMBOL(dynamic_debug_unregister_classes);
/*
* Allocate a new ddebug_table for the given module
@@ -1186,6 +1211,9 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
dt->num_ddebugs = n;
dt->ddebugs = tab;
+ INIT_LIST_HEAD(&dt->link);
+ INIT_LIST_HEAD(&dt->maps);
+
mutex_lock(&ddebug_lock);
list_add(&dt->link, &ddebug_tables);
mutex_unlock(&ddebug_lock);
Upgrade single classes-map to list of them: This allows multiple DYNAMIC_DEBUG_CLASSES(class-map)s per module, using _base to segment the 0..30 classid space. alter struct ddebug table: replace .classes (a &map) with maps (list-head) dynamic_debug_register_classes(map) - adds new map to maps list. dynamic_debug_unregister_classes(map) - deletes map after ID-check. ddebug_validate_classname() - check all maps in list before failing. ddebug_class_name() - which supports ```cat control``` now walks maps list, finds the map whose sub-range of .class_id's spans the one in the callsite, and returns that class-name. Signed-off-by: Jim Cromie <jim.cromie@gmail.com> --- . split out validate_classnames() . fold in fixes for multi class-maps --- lib/dynamic_debug.c | 76 +++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 24 deletions(-)