Skip to content

Commit

Permalink
ALSA: hda - Avoid call of snd_jack_report at release
Browse files Browse the repository at this point in the history
Don't call snd_jack_report at release of sigmatel and conexnat codecs
which results in Oops at unloading the module.

The Oops is triggered by the power-up sequence during the free due to
the pincfg restoration.  Since the power-up sequence is involved with
the unsol handling, the jack reporting may be issued during that.
The Oops occurs with this jack reporting because the jack instances
have been already released but the codec doesn't do the proper
book-keeping.

This patch adds the book-keeping of jack instances to avoid the access
to bogus pointers.

Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
tiwai committed Apr 14, 2009
1 parent 9d59065 commit 95c0909
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
21 changes: 18 additions & 3 deletions sound/pci/hda/patch_conexant.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,20 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
}

#ifdef CONFIG_SND_JACK
static void conexant_free_jack_priv(struct snd_jack *jack)
{
struct conexant_jack *jacks = jack->private_data;
jacks->nid = 0;
jacks->jack = NULL;
}

static int conexant_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type)
{
struct conexant_spec *spec;
struct conexant_jack *jack;
const char *name;
int err;

spec = codec->spec;
snd_array_init(&spec->jacks, sizeof(*jack), 32);
Expand All @@ -368,7 +376,12 @@ static int conexant_add_jack(struct hda_codec *codec,
jack->nid = nid;
jack->type = type;

return snd_jack_new(codec->bus->card, name, type, &jack->jack);
err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
if (err < 0)
return err;
jack->jack->private_data = jack;
jack->jack->private_free = conexant_free_jack_priv;
return 0;
}

static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
Expand Down Expand Up @@ -455,8 +468,10 @@ static void conexant_free(struct hda_codec *codec)
if (spec->jacks.list) {
struct conexant_jack *jacks = spec->jacks.list;
int i;
for (i = 0; i < spec->jacks.used; i++)
snd_device_free(codec->bus->card, &jacks[i].jack);
for (i = 0; i < spec->jacks.used; i++, jacks++) {
if (jacks->jack)
snd_device_free(codec->bus->card, jacks->jack);
}
snd_array_free(&spec->jacks);
}
#endif
Expand Down
27 changes: 22 additions & 5 deletions sound/pci/hda/patch_sigmatel.c
Original file line number Diff line number Diff line change
Expand Up @@ -3851,6 +3851,15 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
}

#ifdef CONFIG_SND_JACK
static void stac92xx_free_jack_priv(struct snd_jack *jack)
{
struct sigmatel_jack *jacks = jack->private_data;
jacks->nid = 0;
jacks->jack = NULL;
}
#endif

static int stac92xx_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type)
{
Expand All @@ -3860,6 +3869,7 @@ static int stac92xx_add_jack(struct hda_codec *codec,
int def_conf = snd_hda_codec_get_pincfg(codec, nid);
int connectivity = get_defcfg_connect(def_conf);
char name[32];
int err;

if (connectivity && connectivity != AC_JACK_PORT_FIXED)
return 0;
Expand All @@ -3876,10 +3886,15 @@ static int stac92xx_add_jack(struct hda_codec *codec,
snd_hda_get_jack_connectivity(def_conf),
snd_hda_get_jack_location(def_conf));

return snd_jack_new(codec->bus->card, name, type, &jack->jack);
#else
return 0;
err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
if (err < 0) {
jack->nid = 0;
return err;
}
jack->jack->private_data = jack;
jack->jack->private_free = stac92xx_free_jack_priv;
#endif
return 0;
}

static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
Expand Down Expand Up @@ -4138,8 +4153,10 @@ static void stac92xx_free_jacks(struct hda_codec *codec)
if (!codec->bus->shutdown && spec->jacks.list) {
struct sigmatel_jack *jacks = spec->jacks.list;
int i;
for (i = 0; i < spec->jacks.used; i++)
snd_device_free(codec->bus->card, &jacks[i].jack);
for (i = 0; i < spec->jacks.used; i++, jacks++) {
if (jacks->jack)
snd_device_free(codec->bus->card, jacks->jack);
}
}
snd_array_free(&spec->jacks);
#endif
Expand Down

0 comments on commit 95c0909

Please sign in to comment.