ALSA: hda - Fix double free of jack instances
authorTakashi Iwai <tiwai@suse.de>
Fri, 21 Nov 2008 08:08:06 +0000 (09:08 +0100)
committerTakashi Iwai <tiwai@suse.de>
Fri, 21 Nov 2008 08:08:06 +0000 (09:08 +0100)
The jack instances created in patch_sigmatel.c may be double-freed.
The device management code checks the invalid element, and thus there
is no real breakage, but it spews annoying warning messages.
But, we can't simply remove the release calls of these jack instances
because they have to be freed when the codec is re-configured.

Now, a new flag, bus->shutdown is introduced to indicate that the bus
is really being unloaded, i.e. the objects managed by the device
manager will be automatically deleted.  We release these objects only
when this flag isn't set.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/patch_sigmatel.c

index 5d5e8012d6a5aea4de4acf71256ea54b8316e8f8..a98ce5b111881cad759a5aae3d444f5f069e70d4 100644 (file)
@@ -464,6 +464,7 @@ static int snd_hda_bus_free(struct hda_bus *bus)
 static int snd_hda_bus_dev_free(struct snd_device *device)
 {
        struct hda_bus *bus = device->device_data;
+       bus->shutdown = 1;
        return snd_hda_bus_free(bus);
 }
 
index ee122b009fd439faa13e67dd6a9d7909fdee9d04..a70b181bbacedcb1d587280d1d59245e9eef00bd 100644 (file)
@@ -617,6 +617,7 @@ struct hda_bus {
 
        /* misc op flags */
        unsigned int needs_damn_long_delay :1;
+       unsigned int shutdown :1;       /* being unloaded */
 };
 
 /*
index a501c9121649d01e0ff15381f3155ec53fc03163..4fa5189264b74c7954aa7761842af4be8190a542 100644 (file)
@@ -3921,8 +3921,9 @@ static int stac92xx_init(struct hda_codec *codec)
 static void stac92xx_free_jacks(struct hda_codec *codec)
 {
 #ifdef CONFIG_SND_JACK
+       /* free jack instances manually when clearing/reconfiguring */
        struct sigmatel_spec *spec = codec->spec;
-       if (spec->jacks.list) {
+       if (!codec->bus->shutdown && spec->jacks.list) {
                struct sigmatel_jack *jacks = spec->jacks.list;
                int i;
                for (i = 0; i < spec->jacks.used; i++)