[alsa-devel] snd_array_free - snd: bad kfree when HDA reconfig

Takashi Iwai tiwai at suse.de
Mon Sep 12 09:46:17 CEST 2011


At Fri, 2 Sep 2011 15:16:28 +0800,
Raymond Yau wrote:
> 
> These errors "snd: bad kfree" occur when reconfig HDA from model
> "6stack-dig-fp" to "auto" and vice versa

Doesn't this happen when you unload the device, right?
And, it happens when writing to /sys/class/sound/hwC0D0/clear?

> Is "HD-Audio reconfiguration" still experimental ?

Somehow yet, but mostly it worked for me :)

> BTW, it seem that HDA Digital PCBeep assigned to different input after
> each reconfig
> 
> input: HDA Digital PCBeep as /devices/pci0000:00/0000:00:1b.0/input/input7
> input: HDA Digital PCBeep as /devices/pci0000:00/0000:00:1b.0/input/input8
> input: HDA Digital PCBeep as /devices/pci0000:00/0000:00:1b.0/input/input9

This is unavoidable, unfortunately.  It's the designed implementation
of input layer.

> ALSA hda_hwdep.c:220: hda-codec: reconfiguring
> snd: bad kfree (called from f8be4636)

Hmm, this is a magic check in external alsa-driver builds.
I guess it's just a bug there -- the override of krealloc() is
missing.

Does the patch below (to alsa-driver tree) fix the problem?


thanks,

Takashi

---
diff --git a/acore/memory_debug.c b/acore/memory_debug.c
index 4527378..0baf9b9 100644
--- a/acore/memory_debug.c
+++ b/acore/memory_debug.c
@@ -128,6 +128,21 @@ void snd_hidden_kfree(const void *obj)
 	snd_wrapper_kfree(obj);
 }
 
+size_t snd_hidden_ksize(const void *obj)
+{
+	struct snd_alloc_track *t;
+	if (!obj)
+		return 0;
+	t = snd_alloc_track_entry(obj);
+	if (t->magic != KMALLOC_MAGIC) {
+		printk(KERN_WARNING "snd: bad ksize (called from %p)\n",
+		       __builtin_return_address(0));
+		dump_stack();
+		return 0;
+	}
+	return t->size;
+}
+
 char *snd_hidden_kstrdup(const char *s, gfp_t gfp_flags)
 {
 	int len;
diff --git a/include/adriver.h b/include/adriver.h
index 1418a5e..fe70442 100644
--- a/include/adriver.h
+++ b/include/adriver.h
@@ -892,6 +892,7 @@ void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags);
 char *snd_hidden_kstrdup(const char *s, gfp_t flags);
 char *snd_hidden_kstrndup(const char *s, size_t len, gfp_t flags);
 void snd_hidden_kfree(const void *obj);
+size_t snd_hidden_ksize(const void *obj);
 
 static inline void *snd_wrapper_kmalloc(size_t size, gfp_t flags)
 {
@@ -907,6 +908,7 @@ static inline void snd_wrapper_kfree(const void *obj)
 #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
 #define kstrdup(s, flags)  snd_hidden_kstrdup(s, flags)
 #define kstrndup(s, len, flags)  snd_hidden_kstrndup(s, len, flags)
+#define ksize(obj) snd_hidden_ksize(obj)
 #define kfree(obj) snd_hidden_kfree(obj)
 
 #define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags)
@@ -2000,9 +2002,9 @@ static inline bool flush_delayed_work_sync(struct delayed_work *dwork)
 #endif
 
 /* krealloc() wrapper */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)) || defined(CONFIG_SND_DEBUG_MEMORY)
 #include <linux/slab.h>
-static inline void *krealloc(const void *p, size_t new_size, gfp_t flags)
+static inline void *snd_compat_krealloc(const void *p, size_t new_size, gfp_t flags)
 {
 	void *n;
 	if (!p)
@@ -2018,6 +2020,7 @@ static inline void *krealloc(const void *p, size_t new_size, gfp_t flags)
 	kfree(p);
 	return n;
 }
+#define krealloc(p, s, f)	snd_compat_krealloc(p, s, f)
 #endif
 
 #endif /* __SOUND_LOCAL_DRIVER_H */


More information about the Alsa-devel mailing list