summaryrefslogtreecommitdiff
path: root/lib/dynamic_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dynamic_debug.c')
-rw-r--r--lib/dynamic_debug.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 8136e5236b7b..fdd6d9800a70 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1223,7 +1223,7 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt,
* Allocate a new ddebug_table for the given module
* and add it to the global list.
*/
-static int __ddebug_add_module(struct _ddebug_info *di, const char *modname)
+static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
{
struct ddebug_table *dt;
@@ -1262,11 +1262,6 @@ static int __ddebug_add_module(struct _ddebug_info *di, const char *modname)
return 0;
}
-int ddebug_add_module(struct _ddebug_info *di, const char *modname)
-{
- return __ddebug_add_module(di, modname);
-}
-
/* helper for ddebug_dyndbg_(boot|module)_param_cb */
static int ddebug_dyndbg_param_cb(char *param, char *val,
const char *modname, int on_err)
@@ -1313,11 +1308,13 @@ static void ddebug_table_free(struct ddebug_table *dt)
kfree(dt);
}
+#ifdef CONFIG_MODULES
+
/*
* Called in response to a module being unloaded. Removes
* any ddebug_table's which point at the module.
*/
-int ddebug_remove_module(const char *mod_name)
+static int ddebug_remove_module(const char *mod_name)
{
struct ddebug_table *dt, *nextdt;
int ret = -ENOENT;
@@ -1336,6 +1333,33 @@ int ddebug_remove_module(const char *mod_name)
return ret;
}
+static int ddebug_module_notify(struct notifier_block *self, unsigned long val,
+ void *data)
+{
+ struct module *mod = data;
+ int ret = 0;
+
+ switch (val) {
+ case MODULE_STATE_COMING:
+ ret = ddebug_add_module(&mod->dyndbg_info, mod->name);
+ if (ret)
+ WARN(1, "Failed to allocate memory: dyndbg may not work properly.\n");
+ break;
+ case MODULE_STATE_GOING:
+ ddebug_remove_module(mod->name);
+ break;
+ }
+
+ return notifier_from_errno(ret);
+}
+
+static struct notifier_block ddebug_module_nb = {
+ .notifier_call = ddebug_module_notify,
+ .priority = 0, /* dynamic debug depends on jump label */
+};
+
+#endif /* CONFIG_MODULES */
+
static void ddebug_remove_all_tables(void)
{
mutex_lock(&ddebug_lock);
@@ -1387,6 +1411,14 @@ static int __init dynamic_debug_init(void)
.num_classes = __stop___dyndbg_classes - __start___dyndbg_classes,
};
+#ifdef CONFIG_MODULES
+ ret = register_module_notifier(&ddebug_module_nb);
+ if (ret) {
+ pr_warn("Failed to register dynamic debug module notifier\n");
+ return ret;
+ }
+#endif /* CONFIG_MODULES */
+
if (&__start___dyndbg == &__stop___dyndbg) {
if (IS_ENABLED(CONFIG_DYNAMIC_DEBUG)) {
pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
@@ -1407,7 +1439,7 @@ static int __init dynamic_debug_init(void)
mod_ct++;
di.num_descs = mod_sites;
di.descs = iter_mod_start;
- ret = __ddebug_add_module(&di, modname);
+ ret = ddebug_add_module(&di, modname);
if (ret)
goto out_err;
@@ -1418,7 +1450,7 @@ static int __init dynamic_debug_init(void)
}
di.num_descs = mod_sites;
di.descs = iter_mod_start;
- ret = __ddebug_add_module(&di, modname);
+ ret = ddebug_add_module(&di, modname);
if (ret)
goto out_err;