diff options
author | Mark Brown <broonie@linaro.org> | 2013-10-30 20:47:39 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-10-31 13:57:47 -0400 |
commit | c5914b0aaea6494aaa9e415cbd32f8b7eb604af0 (patch) | |
tree | 942c1b91cbd885c74b80879a6fd23d61498dd9d1 | |
parent | a19685cb72bb6a80ac453e76b3ab3bb7770e1742 (diff) |
ASoC: pcm: Check for ops before deferencing them
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>
-rw-r--r-- | sound/soc/soc-pcm.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d4498723b375..d81b79251760 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -190,7 +190,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
190 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 190 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
191 | 191 | ||
192 | /* startup the audio subsystem */ | 192 | /* startup the audio subsystem */ |
193 | if (cpu_dai->driver->ops->startup) { | 193 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->startup) { |
194 | ret = cpu_dai->driver->ops->startup(substream, cpu_dai); | 194 | ret = cpu_dai->driver->ops->startup(substream, cpu_dai); |
195 | if (ret < 0) { | 195 | if (ret < 0) { |
196 | dev_err(cpu_dai->dev, "ASoC: can't open interface" | 196 | dev_err(cpu_dai->dev, "ASoC: can't open interface" |
@@ -208,7 +208,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | if (codec_dai->driver->ops->startup) { | 211 | if (codec_dai->driver->ops && codec_dai->driver->ops->startup) { |
212 | ret = codec_dai->driver->ops->startup(substream, codec_dai); | 212 | ret = codec_dai->driver->ops->startup(substream, codec_dai); |
213 | if (ret < 0) { | 213 | if (ret < 0) { |
214 | dev_err(codec_dai->dev, "ASoC: can't open codec" | 214 | dev_err(codec_dai->dev, "ASoC: can't open codec" |
@@ -463,7 +463,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
463 | } | 463 | } |
464 | } | 464 | } |
465 | 465 | ||
466 | if (codec_dai->driver->ops->prepare) { | 466 | if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) { |
467 | ret = codec_dai->driver->ops->prepare(substream, codec_dai); | 467 | ret = codec_dai->driver->ops->prepare(substream, codec_dai); |
468 | if (ret < 0) { | 468 | if (ret < 0) { |
469 | dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n", | 469 | 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) | |||
472 | } | 472 | } |
473 | } | 473 | } |
474 | 474 | ||
475 | if (cpu_dai->driver->ops->prepare) { | 475 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->prepare) { |
476 | ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); | 476 | ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); |
477 | if (ret < 0) { | 477 | if (ret < 0) { |
478 | dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n", | 478 | 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, | |||
523 | } | 523 | } |
524 | } | 524 | } |
525 | 525 | ||
526 | if (codec_dai->driver->ops->hw_params) { | 526 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_params) { |
527 | ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); | 527 | ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); |
528 | if (ret < 0) { | 528 | if (ret < 0) { |
529 | dev_err(codec_dai->dev, "ASoC: can't set %s hw params:" | 529 | 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, | |||
532 | } | 532 | } |
533 | } | 533 | } |
534 | 534 | ||
535 | if (cpu_dai->driver->ops->hw_params) { | 535 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_params) { |
536 | ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); | 536 | ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); |
537 | if (ret < 0) { | 537 | if (ret < 0) { |
538 | dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n", | 538 | dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n", |
@@ -559,11 +559,11 @@ out: | |||
559 | return ret; | 559 | return ret; |
560 | 560 | ||
561 | platform_err: | 561 | platform_err: |
562 | if (cpu_dai->driver->ops->hw_free) | 562 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free) |
563 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 563 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
564 | 564 | ||
565 | interface_err: | 565 | interface_err: |
566 | if (codec_dai->driver->ops->hw_free) | 566 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) |
567 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 567 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
568 | 568 | ||
569 | codec_err: | 569 | codec_err: |
@@ -600,10 +600,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
600 | platform->driver->ops->hw_free(substream); | 600 | platform->driver->ops->hw_free(substream); |
601 | 601 | ||
602 | /* now free hw params for the DAIs */ | 602 | /* now free hw params for the DAIs */ |
603 | if (codec_dai->driver->ops->hw_free) | 603 | if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free) |
604 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 604 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
605 | 605 | ||
606 | if (cpu_dai->driver->ops->hw_free) | 606 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free) |
607 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 607 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
608 | 608 | ||
609 | mutex_unlock(&rtd->pcm_mutex); | 609 | mutex_unlock(&rtd->pcm_mutex); |
@@ -618,7 +618,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
618 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 618 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
619 | int ret; | 619 | int ret; |
620 | 620 | ||
621 | if (codec_dai->driver->ops->trigger) { | 621 | if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) { |
622 | ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); | 622 | ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); |
623 | if (ret < 0) | 623 | if (ret < 0) |
624 | return ret; | 624 | return ret; |
@@ -630,7 +630,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
630 | return ret; | 630 | return ret; |
631 | } | 631 | } |
632 | 632 | ||
633 | if (cpu_dai->driver->ops->trigger) { | 633 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->trigger) { |
634 | ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); | 634 | ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); |
635 | if (ret < 0) | 635 | if (ret < 0) |
636 | return ret; | 636 | return ret; |
@@ -647,19 +647,20 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
647 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 647 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
648 | int ret; | 648 | int ret; |
649 | 649 | ||
650 | if (codec_dai->driver->ops->bespoke_trigger) { | 650 | if (codec_dai->driver->ops && |
651 | codec_dai->driver->ops->bespoke_trigger) { | ||
651 | ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai); | 652 | ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai); |
652 | if (ret < 0) | 653 | if (ret < 0) |
653 | return ret; | 654 | return ret; |
654 | } | 655 | } |
655 | 656 | ||
656 | if (platform->driver->bespoke_trigger) { | 657 | if (platform->driver->ops && platform->driver->bespoke_trigger) { |
657 | ret = platform->driver->bespoke_trigger(substream, cmd); | 658 | ret = platform->driver->bespoke_trigger(substream, cmd); |
658 | if (ret < 0) | 659 | if (ret < 0) |
659 | return ret; | 660 | return ret; |
660 | } | 661 | } |
661 | 662 | ||
662 | if (cpu_dai->driver->ops->bespoke_trigger) { | 663 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->bespoke_trigger) { |
663 | ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai); | 664 | ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai); |
664 | if (ret < 0) | 665 | if (ret < 0) |
665 | return ret; | 666 | return ret; |
@@ -684,10 +685,10 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
684 | if (platform->driver->ops && platform->driver->ops->pointer) | 685 | if (platform->driver->ops && platform->driver->ops->pointer) |
685 | offset = platform->driver->ops->pointer(substream); | 686 | offset = platform->driver->ops->pointer(substream); |
686 | 687 | ||
687 | if (cpu_dai->driver->ops->delay) | 688 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay) |
688 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); | 689 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); |
689 | 690 | ||
690 | if (codec_dai->driver->ops->delay) | 691 | if (codec_dai->driver->ops && codec_dai->driver->ops->delay) |
691 | delay += codec_dai->driver->ops->delay(substream, codec_dai); | 692 | delay += codec_dai->driver->ops->delay(substream, codec_dai); |
692 | 693 | ||
693 | if (platform->driver->delay) | 694 | if (platform->driver->delay) |
@@ -1673,7 +1674,7 @@ static int soc_pcm_ioctl(struct snd_pcm_substream *substream, | |||
1673 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1674 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1674 | struct snd_soc_platform *platform = rtd->platform; | 1675 | struct snd_soc_platform *platform = rtd->platform; |
1675 | 1676 | ||
1676 | if (platform->driver->ops->ioctl) | 1677 | if (platform->driver->ops && platform->driver->ops->ioctl) |
1677 | return platform->driver->ops->ioctl(substream, cmd, arg); | 1678 | return platform->driver->ops->ioctl(substream, cmd, arg); |
1678 | return snd_pcm_lib_ioctl(substream, cmd, arg); | 1679 | return snd_pcm_lib_ioctl(substream, cmd, arg); |
1679 | } | 1680 | } |
@@ -1934,8 +1935,8 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) | |||
1934 | 1935 | ||
1935 | dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name); | 1936 | dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name); |
1936 | 1937 | ||
1937 | if (drv->ops->digital_mute && dai->playback_active) | 1938 | if (drv->ops && drv->ops->digital_mute && dai->playback_active) |
1938 | drv->ops->digital_mute(dai, mute); | 1939 | drv->ops->digital_mute(dai, mute); |
1939 | } | 1940 | } |
1940 | 1941 | ||
1941 | return 0; | 1942 | return 0; |
@@ -2224,7 +2225,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); | |||
2224 | int snd_soc_platform_trigger(struct snd_pcm_substream *substream, | 2225 | int snd_soc_platform_trigger(struct snd_pcm_substream *substream, |
2225 | int cmd, struct snd_soc_platform *platform) | 2226 | int cmd, struct snd_soc_platform *platform) |
2226 | { | 2227 | { |
2227 | if (platform->driver->ops->trigger) | 2228 | if (platform->driver->ops && platform->driver->ops->trigger) |
2228 | return platform->driver->ops->trigger(substream, cmd); | 2229 | return platform->driver->ops->trigger(substream, cmd); |
2229 | return 0; | 2230 | return 0; |
2230 | } | 2231 | } |