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: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
bbbc7e8502
commit
61ca4107a1
@ -4525,7 +4525,11 @@ int snd_hda_codec_prepare(struct hda_codec *codec,
|
||||
{
|
||||
int ret;
|
||||
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)
|
||||
purify_inactive_streams(codec);
|
||||
mutex_unlock(&codec->bus->prepare_mutex);
|
||||
@ -4546,7 +4550,8 @@ void snd_hda_codec_cleanup(struct hda_codec *codec,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
mutex_lock(&codec->bus->prepare_mutex);
|
||||
hinfo->ops.cleanup(hinfo, codec, substream);
|
||||
if (hinfo->ops.cleanup)
|
||||
hinfo->ops.cleanup(hinfo, codec, substream);
|
||||
mutex_unlock(&codec->bus->prepare_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup);
|
||||
|
@ -416,7 +416,8 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
|
||||
azx_dev->running = 0;
|
||||
spin_unlock_irqrestore(&chip->reg_lock, flags);
|
||||
azx_release_device(azx_dev);
|
||||
hinfo->ops.close(hinfo, apcm->codec, substream);
|
||||
if (hinfo->ops.close)
|
||||
hinfo->ops.close(hinfo, apcm->codec, substream);
|
||||
snd_hda_power_down(apcm->codec);
|
||||
mutex_unlock(&chip->open_mutex);
|
||||
return 0;
|
||||
@ -808,8 +809,8 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_lock(&chip->open_mutex);
|
||||
azx_dev = azx_assign_device(chip, substream);
|
||||
if (azx_dev == NULL) {
|
||||
mutex_unlock(&chip->open_mutex);
|
||||
return -EBUSY;
|
||||
err = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
runtime->hw = azx_pcm_hw;
|
||||
runtime->hw.channels_min = hinfo->channels_min;
|
||||
@ -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,
|
||||
buff_step);
|
||||
snd_hda_power_up(apcm->codec);
|
||||
err = hinfo->ops.open(hinfo, apcm->codec, substream);
|
||||
if (hinfo->ops.open)
|
||||
err = hinfo->ops.open(hinfo, apcm->codec, substream);
|
||||
else
|
||||
err = -ENODEV;
|
||||
if (err < 0) {
|
||||
azx_release_device(azx_dev);
|
||||
snd_hda_power_down(apcm->codec);
|
||||
mutex_unlock(&chip->open_mutex);
|
||||
return err;
|
||||
goto powerdown;
|
||||
}
|
||||
snd_pcm_limit_hw_rates(runtime);
|
||||
/* sanity check */
|
||||
@ -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.rates)) {
|
||||
azx_release_device(azx_dev);
|
||||
hinfo->ops.close(hinfo, apcm->codec, substream);
|
||||
snd_hda_power_down(apcm->codec);
|
||||
mutex_unlock(&chip->open_mutex);
|
||||
return -EINVAL;
|
||||
if (hinfo->ops.close)
|
||||
hinfo->ops.close(hinfo, apcm->codec, substream);
|
||||
err = -EINVAL;
|
||||
goto powerdown;
|
||||
}
|
||||
|
||||
/* disable LINK_ATIME timestamps for capture streams
|
||||
@ -880,6 +882,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
|
||||
snd_pcm_set_sync(substream);
|
||||
mutex_unlock(&chip->open_mutex);
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user