diff options
Diffstat (limited to 'lib/dynamic_debug.c')
| -rw-r--r-- | lib/dynamic_debug.c | 51 | 
1 files changed, 41 insertions, 10 deletions
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 009f2ead09c1..fdd6d9800a70 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -1223,8 +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, unsigned int base, -			       const char *modname) +static int ddebug_add_module(struct _ddebug_info *di, const char *modname)  {  	struct ddebug_table *dt; @@ -1263,11 +1262,6 @@ static int __ddebug_add_module(struct _ddebug_info *di, unsigned int base,  	return 0;  } -int ddebug_add_module(struct _ddebug_info *di, const char *modname) -{ -	return __ddebug_add_module(di, 0, 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) @@ -1314,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; @@ -1337,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); @@ -1388,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"); @@ -1408,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, i - mod_sites, modname); +			ret = ddebug_add_module(&di, modname);  			if (ret)  				goto out_err; @@ -1419,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, i - mod_sites, modname); +	ret = ddebug_add_module(&di, modname);  	if (ret)  		goto out_err;  |