Loading Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +1 −16 Original line number Diff line number Diff line Loading @@ -1433,25 +1433,10 @@ <informalexample> <programlisting> <![CDATA[ if (chip->res_port) { release_resource(chip->res_port); kfree_nocheck(chip->res_port); } release_and_free_resource(chip->res_port); ]]> </programlisting> </informalexample> As you can see, the resource pointer is also to be freed via <function>kfree_nocheck()</function> after <function>release_resource()</function> is called. You cannot use <function>kfree()</function> here, because on ALSA, <function>kfree()</function> may be a wrapper to its own allocator with the memory debugging. Since the resource pointer is allocated externally outside the ALSA, it must be released via the native <function>kfree()</function>. <function>kfree_nocheck()</function> is used for that; it calls the native <function>kfree()</function> without wrapper. </para> <para> Loading include/sound/core.h +1 −8 Original line number Diff line number Diff line Loading @@ -293,19 +293,13 @@ void *snd_hidden_kmalloc(size_t size, gfp_t flags); void *snd_hidden_kzalloc(size_t size, gfp_t flags); void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags); void snd_hidden_kfree(const void *obj); void *snd_hidden_vmalloc(unsigned long size); void snd_hidden_vfree(void *obj); char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) #define kzalloc(size, flags) snd_hidden_kzalloc(size, flags) #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) #define kfree(obj) snd_hidden_kfree(obj) #define vmalloc(size) snd_hidden_vmalloc(size) #define vfree(obj) snd_hidden_vfree(obj) #define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags) #define vmalloc_nocheck(size) snd_wrapper_vmalloc(size) #define kfree_nocheck(obj) snd_wrapper_kfree(obj) #define vfree_nocheck(obj) snd_wrapper_vfree(obj) #define kstrdup(s, flags) snd_hidden_kstrdup(s, flags) #else #define snd_memory_init() /*NOP*/ Loading @@ -313,9 +307,7 @@ char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define snd_memory_info_init() /*NOP*/ #define snd_memory_info_done() /*NOP*/ #define kmalloc_nocheck(size, flags) kmalloc(size, flags) #define vmalloc_nocheck(size) vmalloc(size) #define kfree_nocheck(obj) kfree(obj) #define vfree_nocheck(obj) vfree(obj) #endif int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count); int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count); Loading Loading @@ -372,6 +364,7 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); #endif /* misc.c */ void release_and_free_resource(struct resource *res); #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) Loading include/sound/driver.h +0 −4 Original line number Diff line number Diff line Loading @@ -55,10 +55,6 @@ void *snd_wrapper_kmalloc(size_t, gfp_t); #undef kmalloc void snd_wrapper_kfree(const void *); #undef kfree void *snd_wrapper_vmalloc(size_t); #undef vmalloc void snd_wrapper_vfree(void *); #undef vfree #endif #endif /* __SOUND_DRIVER_H */ sound/core/memory.c +0 −53 Original line number Diff line number Diff line Loading @@ -47,19 +47,14 @@ struct snd_alloc_track { #define snd_alloc_track_entry(obj) (struct snd_alloc_track *)((char*)obj - (unsigned long)((struct snd_alloc_track *)0)->data) static long snd_alloc_kmalloc; static long snd_alloc_vmalloc; static LIST_HEAD(snd_alloc_kmalloc_list); static LIST_HEAD(snd_alloc_vmalloc_list); static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock); static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock); #define KMALLOC_MAGIC 0x87654321 #define VMALLOC_MAGIC 0x87654320 static snd_info_entry_t *snd_memory_info_entry; void __init snd_memory_init(void) { snd_alloc_kmalloc = 0; snd_alloc_vmalloc = 0; } void snd_memory_done(void) Loading @@ -69,8 +64,6 @@ void snd_memory_done(void) if (snd_alloc_kmalloc > 0) snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc); if (snd_alloc_vmalloc > 0) snd_printk(KERN_ERR "Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc); list_for_each_prev(head, &snd_alloc_kmalloc_list) { t = list_entry(head, struct snd_alloc_track, list); if (t->magic != KMALLOC_MAGIC) { Loading @@ -79,14 +72,6 @@ void snd_memory_done(void) } snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); } list_for_each_prev(head, &snd_alloc_vmalloc_list) { t = list_entry(head, struct snd_alloc_track, list); if (t->magic != VMALLOC_MAGIC) { snd_printk(KERN_ERR "Corrupted vmalloc\n"); break; } snd_printk(KERN_ERR "vmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); } } static void *__snd_kmalloc(size_t size, gfp_t flags, void *caller) Loading Loading @@ -153,43 +138,6 @@ void snd_hidden_kfree(const void *obj) snd_wrapper_kfree(obj); } void *snd_hidden_vmalloc(unsigned long size) { void *ptr; ptr = snd_wrapper_vmalloc(size + sizeof(struct snd_alloc_track)); if (ptr) { struct snd_alloc_track *t = (struct snd_alloc_track *)ptr; t->magic = VMALLOC_MAGIC; t->caller = __builtin_return_address(0); spin_lock(&snd_alloc_vmalloc_lock); list_add_tail(&t->list, &snd_alloc_vmalloc_list); spin_unlock(&snd_alloc_vmalloc_lock); t->size = size; snd_alloc_vmalloc += size; ptr = t->data; } return ptr; } void snd_hidden_vfree(void *obj) { struct snd_alloc_track *t; if (obj == NULL) return; t = snd_alloc_track_entry(obj); if (t->magic != VMALLOC_MAGIC) { snd_printk(KERN_ERR "bad vfree (called from %p)\n", __builtin_return_address(0)); return; } spin_lock(&snd_alloc_vmalloc_lock); list_del(&t->list); spin_unlock(&snd_alloc_vmalloc_lock); t->magic = 0; snd_alloc_vmalloc -= t->size; obj = t; snd_wrapper_vfree(obj); } char *snd_hidden_kstrdup(const char *s, gfp_t flags) { int len; Loading @@ -207,7 +155,6 @@ char *snd_hidden_kstrdup(const char *s, gfp_t flags) static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); snd_iprintf(buffer, "vmalloc: %li bytes\n", snd_alloc_vmalloc); } int __init snd_memory_info_init(void) Loading sound/core/misc.c +9 −0 Original line number Diff line number Diff line Loading @@ -23,8 +23,17 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/time.h> #include <linux/ioport.h> #include <sound/core.h> void release_and_free_resource(struct resource *res) { if (res) { release_resource(res); kfree_nocheck(res); } } #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) { Loading Loading
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +1 −16 Original line number Diff line number Diff line Loading @@ -1433,25 +1433,10 @@ <informalexample> <programlisting> <![CDATA[ if (chip->res_port) { release_resource(chip->res_port); kfree_nocheck(chip->res_port); } release_and_free_resource(chip->res_port); ]]> </programlisting> </informalexample> As you can see, the resource pointer is also to be freed via <function>kfree_nocheck()</function> after <function>release_resource()</function> is called. You cannot use <function>kfree()</function> here, because on ALSA, <function>kfree()</function> may be a wrapper to its own allocator with the memory debugging. Since the resource pointer is allocated externally outside the ALSA, it must be released via the native <function>kfree()</function>. <function>kfree_nocheck()</function> is used for that; it calls the native <function>kfree()</function> without wrapper. </para> <para> Loading
include/sound/core.h +1 −8 Original line number Diff line number Diff line Loading @@ -293,19 +293,13 @@ void *snd_hidden_kmalloc(size_t size, gfp_t flags); void *snd_hidden_kzalloc(size_t size, gfp_t flags); void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags); void snd_hidden_kfree(const void *obj); void *snd_hidden_vmalloc(unsigned long size); void snd_hidden_vfree(void *obj); char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) #define kzalloc(size, flags) snd_hidden_kzalloc(size, flags) #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) #define kfree(obj) snd_hidden_kfree(obj) #define vmalloc(size) snd_hidden_vmalloc(size) #define vfree(obj) snd_hidden_vfree(obj) #define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags) #define vmalloc_nocheck(size) snd_wrapper_vmalloc(size) #define kfree_nocheck(obj) snd_wrapper_kfree(obj) #define vfree_nocheck(obj) snd_wrapper_vfree(obj) #define kstrdup(s, flags) snd_hidden_kstrdup(s, flags) #else #define snd_memory_init() /*NOP*/ Loading @@ -313,9 +307,7 @@ char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define snd_memory_info_init() /*NOP*/ #define snd_memory_info_done() /*NOP*/ #define kmalloc_nocheck(size, flags) kmalloc(size, flags) #define vmalloc_nocheck(size) vmalloc(size) #define kfree_nocheck(obj) kfree(obj) #define vfree_nocheck(obj) vfree(obj) #endif int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count); int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count); Loading Loading @@ -372,6 +364,7 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); #endif /* misc.c */ void release_and_free_resource(struct resource *res); #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) Loading
include/sound/driver.h +0 −4 Original line number Diff line number Diff line Loading @@ -55,10 +55,6 @@ void *snd_wrapper_kmalloc(size_t, gfp_t); #undef kmalloc void snd_wrapper_kfree(const void *); #undef kfree void *snd_wrapper_vmalloc(size_t); #undef vmalloc void snd_wrapper_vfree(void *); #undef vfree #endif #endif /* __SOUND_DRIVER_H */
sound/core/memory.c +0 −53 Original line number Diff line number Diff line Loading @@ -47,19 +47,14 @@ struct snd_alloc_track { #define snd_alloc_track_entry(obj) (struct snd_alloc_track *)((char*)obj - (unsigned long)((struct snd_alloc_track *)0)->data) static long snd_alloc_kmalloc; static long snd_alloc_vmalloc; static LIST_HEAD(snd_alloc_kmalloc_list); static LIST_HEAD(snd_alloc_vmalloc_list); static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock); static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock); #define KMALLOC_MAGIC 0x87654321 #define VMALLOC_MAGIC 0x87654320 static snd_info_entry_t *snd_memory_info_entry; void __init snd_memory_init(void) { snd_alloc_kmalloc = 0; snd_alloc_vmalloc = 0; } void snd_memory_done(void) Loading @@ -69,8 +64,6 @@ void snd_memory_done(void) if (snd_alloc_kmalloc > 0) snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc); if (snd_alloc_vmalloc > 0) snd_printk(KERN_ERR "Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc); list_for_each_prev(head, &snd_alloc_kmalloc_list) { t = list_entry(head, struct snd_alloc_track, list); if (t->magic != KMALLOC_MAGIC) { Loading @@ -79,14 +72,6 @@ void snd_memory_done(void) } snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); } list_for_each_prev(head, &snd_alloc_vmalloc_list) { t = list_entry(head, struct snd_alloc_track, list); if (t->magic != VMALLOC_MAGIC) { snd_printk(KERN_ERR "Corrupted vmalloc\n"); break; } snd_printk(KERN_ERR "vmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); } } static void *__snd_kmalloc(size_t size, gfp_t flags, void *caller) Loading Loading @@ -153,43 +138,6 @@ void snd_hidden_kfree(const void *obj) snd_wrapper_kfree(obj); } void *snd_hidden_vmalloc(unsigned long size) { void *ptr; ptr = snd_wrapper_vmalloc(size + sizeof(struct snd_alloc_track)); if (ptr) { struct snd_alloc_track *t = (struct snd_alloc_track *)ptr; t->magic = VMALLOC_MAGIC; t->caller = __builtin_return_address(0); spin_lock(&snd_alloc_vmalloc_lock); list_add_tail(&t->list, &snd_alloc_vmalloc_list); spin_unlock(&snd_alloc_vmalloc_lock); t->size = size; snd_alloc_vmalloc += size; ptr = t->data; } return ptr; } void snd_hidden_vfree(void *obj) { struct snd_alloc_track *t; if (obj == NULL) return; t = snd_alloc_track_entry(obj); if (t->magic != VMALLOC_MAGIC) { snd_printk(KERN_ERR "bad vfree (called from %p)\n", __builtin_return_address(0)); return; } spin_lock(&snd_alloc_vmalloc_lock); list_del(&t->list); spin_unlock(&snd_alloc_vmalloc_lock); t->magic = 0; snd_alloc_vmalloc -= t->size; obj = t; snd_wrapper_vfree(obj); } char *snd_hidden_kstrdup(const char *s, gfp_t flags) { int len; Loading @@ -207,7 +155,6 @@ char *snd_hidden_kstrdup(const char *s, gfp_t flags) static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); snd_iprintf(buffer, "vmalloc: %li bytes\n", snd_alloc_vmalloc); } int __init snd_memory_info_init(void) Loading
sound/core/misc.c +9 −0 Original line number Diff line number Diff line Loading @@ -23,8 +23,17 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/time.h> #include <linux/ioport.h> #include <sound/core.h> void release_and_free_resource(struct resource *res) { if (res) { release_resource(res); kfree_nocheck(res); } } #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) { Loading