ASoC: pcm: Check for ops before deferencing them
authorMark Brown <broonie@linaro.org>
Thu, 31 Oct 2013 00:47:39 +0000 (17:47 -0700)
committerMark Brown <broonie@linaro.org>
Thu, 31 Oct 2013 17:57:47 +0000 (10:57 -0700)
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>
sound/soc/soc-pcm.c

index d4498723b375025cfacc21246f6f018be1c8e321..d81b7925176006977f96df74cd61134c41294e41 100644 (file)
@@ -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"
@@ -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"
@@ -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",
@@ -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",
@@ -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:"
@@ -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",
@@ -559,11 +559,11 @@ out:
        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:
@@ -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);
@@ -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;
@@ -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;
@@ -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;
@@ -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)
@@ -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);
 }
@@ -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;
@@ -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;
 }