diff options
Diffstat (limited to 'drivers/base/devres.c')
-rw-r--r-- | drivers/base/devres.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 438c91a43508..4aaf00d2098b 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -11,6 +11,8 @@ #include <linux/slab.h> #include <linux/percpu.h> +#include <asm/sections.h> + #include "base.h" struct devres_node { @@ -823,6 +825,28 @@ char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) EXPORT_SYMBOL_GPL(devm_kstrdup); /** + * devm_kstrdup_const - resource managed conditional string duplication + * @dev: device for which to duplicate the string + * @s: the string to duplicate + * @gfp: the GFP mask used in the kmalloc() call when allocating memory + * + * Strings allocated by devm_kstrdup_const will be automatically freed when + * the associated device is detached. + * + * RETURNS: + * Source string if it is in .rodata section otherwise it falls back to + * devm_kstrdup. + */ +const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp) +{ + if (is_kernel_rodata((unsigned long)s)) + return s; + + return devm_kstrdup(dev, s, gfp); +} +EXPORT_SYMBOL_GPL(devm_kstrdup_const); + +/** * devm_kvasprintf - Allocate resource managed space and format a string * into that. * @dev: Device to allocate memory for @@ -889,6 +913,13 @@ void devm_kfree(struct device *dev, const void *p) { int rc; + /* + * Special case: pointer to a string in .rodata returned by + * devm_kstrdup_const(). + */ + if (unlikely(is_kernel_rodata((unsigned long)p))) + return; + rc = devres_destroy(dev, devm_kmalloc_release, devm_kmalloc_match, (void *)p); WARN_ON(rc); |