Skip to content

Commit

Permalink
ASoC: pcm: Check for ops before deferencing them
Browse files Browse the repository at this point in the history
Ensure that we always check that an ops structure is present before we
try to use it, improving the robustness of the system.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Mark Brown <broonie@linaro.org>
  • Loading branch information
Mark Brown committed Oct 31, 2013
1 parent a19685c commit c5914b0
Showing 1 changed file with 22 additions and 21 deletions.
43 changes: 22 additions & 21 deletions sound/soc/soc-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

/* startup the audio subsystem */
if (cpu_dai->driver->ops->startup) {
if (cpu_dai->driver->ops && cpu_dai->driver->ops->startup) {
ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
if (ret < 0) {
dev_err(cpu_dai->dev, "ASoC: can't open interface"
Expand All @@ -208,7 +208,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
}
}

if (codec_dai->driver->ops->startup) {
if (codec_dai->driver->ops && codec_dai->driver->ops->startup) {
ret = codec_dai->driver->ops->startup(substream, codec_dai);
if (ret < 0) {
dev_err(codec_dai->dev, "ASoC: can't open codec"
Expand Down Expand Up @@ -463,7 +463,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
}

if (codec_dai->driver->ops->prepare) {
if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) {
ret = codec_dai->driver->ops->prepare(substream, codec_dai);
if (ret < 0) {
dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n",
Expand All @@ -472,7 +472,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
}

if (cpu_dai->driver->ops->prepare) {
if (cpu_dai->driver->ops && cpu_dai->driver->ops->prepare) {
ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
if (ret < 0) {
dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n",
Expand Down Expand Up @@ -523,7 +523,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
}

if (codec_dai->driver->ops->hw_params) {
if (codec_dai->driver->ops && codec_dai->driver->ops->hw_params) {
ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
if (ret < 0) {
dev_err(codec_dai->dev, "ASoC: can't set %s hw params:"
Expand All @@ -532,7 +532,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
}

if (cpu_dai->driver->ops->hw_params) {
if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_params) {
ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
if (ret < 0) {
dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n",
Expand All @@ -559,11 +559,11 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
return ret;

platform_err:
if (cpu_dai->driver->ops->hw_free)
if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
cpu_dai->driver->ops->hw_free(substream, cpu_dai);

interface_err:
if (codec_dai->driver->ops->hw_free)
if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
codec_dai->driver->ops->hw_free(substream, codec_dai);

codec_err:
Expand Down Expand Up @@ -600,10 +600,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
platform->driver->ops->hw_free(substream);

/* now free hw params for the DAIs */
if (codec_dai->driver->ops->hw_free)
if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
codec_dai->driver->ops->hw_free(substream, codec_dai);

if (cpu_dai->driver->ops->hw_free)
if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
cpu_dai->driver->ops->hw_free(substream, cpu_dai);

mutex_unlock(&rtd->pcm_mutex);
Expand All @@ -618,7 +618,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;

if (codec_dai->driver->ops->trigger) {
if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) {
ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
if (ret < 0)
return ret;
Expand All @@ -630,7 +630,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return ret;
}

if (cpu_dai->driver->ops->trigger) {
if (cpu_dai->driver->ops && cpu_dai->driver->ops->trigger) {
ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
if (ret < 0)
return ret;
Expand All @@ -647,19 +647,20 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;

if (codec_dai->driver->ops->bespoke_trigger) {
if (codec_dai->driver->ops &&
codec_dai->driver->ops->bespoke_trigger) {
ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
if (ret < 0)
return ret;
}

if (platform->driver->bespoke_trigger) {
if (platform->driver->ops && platform->driver->bespoke_trigger) {
ret = platform->driver->bespoke_trigger(substream, cmd);
if (ret < 0)
return ret;
}

if (cpu_dai->driver->ops->bespoke_trigger) {
if (cpu_dai->driver->ops && cpu_dai->driver->ops->bespoke_trigger) {
ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
if (ret < 0)
return ret;
Expand All @@ -684,10 +685,10 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->pointer)
offset = platform->driver->ops->pointer(substream);

if (cpu_dai->driver->ops->delay)
if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay)
delay += cpu_dai->driver->ops->delay(substream, cpu_dai);

if (codec_dai->driver->ops->delay)
if (codec_dai->driver->ops && codec_dai->driver->ops->delay)
delay += codec_dai->driver->ops->delay(substream, codec_dai);

if (platform->driver->delay)
Expand Down Expand Up @@ -1673,7 +1674,7 @@ static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform;

if (platform->driver->ops->ioctl)
if (platform->driver->ops && platform->driver->ops->ioctl)
return platform->driver->ops->ioctl(substream, cmd, arg);
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
Expand Down Expand Up @@ -1934,8 +1935,8 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)

dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name);

if (drv->ops->digital_mute && dai->playback_active)
drv->ops->digital_mute(dai, mute);
if (drv->ops && drv->ops->digital_mute && dai->playback_active)
drv->ops->digital_mute(dai, mute);
}

return 0;
Expand Down Expand Up @@ -2224,7 +2225,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_platform *platform)
{
if (platform->driver->ops->trigger)
if (platform->driver->ops && platform->driver->ops->trigger)
return platform->driver->ops->trigger(substream, cmd);
return 0;
}
Expand Down

0 comments on commit c5914b0

Please sign in to comment.