Commit 61ca4107 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Don't assume non-NULL PCM ops

The PCM ops might be set NULL, or cleared to NULL when the driver is
unbound.  Give a proper NULL check at each place to be more robust.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent bbbc7e85
...@@ -4525,7 +4525,11 @@ int snd_hda_codec_prepare(struct hda_codec *codec, ...@@ -4525,7 +4525,11 @@ int snd_hda_codec_prepare(struct hda_codec *codec,
{ {
int ret; int ret;
mutex_lock(&codec->bus->prepare_mutex); mutex_lock(&codec->bus->prepare_mutex);
ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream); if (hinfo->ops.prepare)
ret = hinfo->ops.prepare(hinfo, codec, stream, format,
substream);
else
ret = -ENODEV;
if (ret >= 0) if (ret >= 0)
purify_inactive_streams(codec); purify_inactive_streams(codec);
mutex_unlock(&codec->bus->prepare_mutex); mutex_unlock(&codec->bus->prepare_mutex);
...@@ -4546,6 +4550,7 @@ void snd_hda_codec_cleanup(struct hda_codec *codec, ...@@ -4546,6 +4550,7 @@ void snd_hda_codec_cleanup(struct hda_codec *codec,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
mutex_lock(&codec->bus->prepare_mutex); mutex_lock(&codec->bus->prepare_mutex);
if (hinfo->ops.cleanup)
hinfo->ops.cleanup(hinfo, codec, substream); hinfo->ops.cleanup(hinfo, codec, substream);
mutex_unlock(&codec->bus->prepare_mutex); mutex_unlock(&codec->bus->prepare_mutex);
} }
......
...@@ -416,6 +416,7 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) ...@@ -416,6 +416,7 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
azx_dev->running = 0; azx_dev->running = 0;
spin_unlock_irqrestore(&chip->reg_lock, flags); spin_unlock_irqrestore(&chip->reg_lock, flags);
azx_release_device(azx_dev); azx_release_device(azx_dev);
if (hinfo->ops.close)
hinfo->ops.close(hinfo, apcm->codec, substream); hinfo->ops.close(hinfo, apcm->codec, substream);
snd_hda_power_down(apcm->codec); snd_hda_power_down(apcm->codec);
mutex_unlock(&chip->open_mutex); mutex_unlock(&chip->open_mutex);
...@@ -808,8 +809,8 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) ...@@ -808,8 +809,8 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
mutex_lock(&chip->open_mutex); mutex_lock(&chip->open_mutex);
azx_dev = azx_assign_device(chip, substream); azx_dev = azx_assign_device(chip, substream);
if (azx_dev == NULL) { if (azx_dev == NULL) {
mutex_unlock(&chip->open_mutex); err = -EBUSY;
return -EBUSY; goto unlock;
} }
runtime->hw = azx_pcm_hw; runtime->hw = azx_pcm_hw;
runtime->hw.channels_min = hinfo->channels_min; runtime->hw.channels_min = hinfo->channels_min;
...@@ -844,12 +845,13 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) ...@@ -844,12 +845,13 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
buff_step); buff_step);
snd_hda_power_up(apcm->codec); snd_hda_power_up(apcm->codec);
if (hinfo->ops.open)
err = hinfo->ops.open(hinfo, apcm->codec, substream); err = hinfo->ops.open(hinfo, apcm->codec, substream);
else
err = -ENODEV;
if (err < 0) { if (err < 0) {
azx_release_device(azx_dev); azx_release_device(azx_dev);
snd_hda_power_down(apcm->codec); goto powerdown;
mutex_unlock(&chip->open_mutex);
return err;
} }
snd_pcm_limit_hw_rates(runtime); snd_pcm_limit_hw_rates(runtime);
/* sanity check */ /* sanity check */
...@@ -858,10 +860,10 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) ...@@ -858,10 +860,10 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
snd_BUG_ON(!runtime->hw.formats) || snd_BUG_ON(!runtime->hw.formats) ||
snd_BUG_ON(!runtime->hw.rates)) { snd_BUG_ON(!runtime->hw.rates)) {
azx_release_device(azx_dev); azx_release_device(azx_dev);
if (hinfo->ops.close)
hinfo->ops.close(hinfo, apcm->codec, substream); hinfo->ops.close(hinfo, apcm->codec, substream);
snd_hda_power_down(apcm->codec); err = -EINVAL;
mutex_unlock(&chip->open_mutex); goto powerdown;
return -EINVAL;
} }
/* disable LINK_ATIME timestamps for capture streams /* disable LINK_ATIME timestamps for capture streams
...@@ -880,6 +882,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) ...@@ -880,6 +882,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
snd_pcm_set_sync(substream); snd_pcm_set_sync(substream);
mutex_unlock(&chip->open_mutex); mutex_unlock(&chip->open_mutex);
return 0; return 0;
powerdown:
snd_hda_power_down(apcm->codec);
unlock:
mutex_unlock(&chip->open_mutex);
return err;
} }
static int azx_pcm_mmap(struct snd_pcm_substream *substream, static int azx_pcm_mmap(struct snd_pcm_substream *substream,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment