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@xxxxxxxxx> --- . split out validate_classnames() . fold in fixes for multi class-maps --- lib/dynamic_debug.c | 76 +++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 8e1b9159e881..f9c5bbf9d43b 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -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); -- 2.35.3