diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-24 20:27:43 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-24 20:27:43 +0300 |
commit | b4ecf26ea2ed744715753ae11e6928fbda9b65ad (patch) | |
tree | 3084d8cb71f073deeb4ee03f52c82ce4298e2ac2 /sound/soc/soc-topology.c | |
parent | 88412a4e00f6baab2752e99ffdbdb0ee661cac30 (diff) | |
parent | 8d6762af302d69f76fa788a277a56a9d9cd275d5 (diff) | |
download | linux-b4ecf26ea2ed744715753ae11e6928fbda9b65ad.tar.xz |
Merge tag 'sound-5.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"This became a slightly big pull request, as the accumulated ASoC fixes
are included here. Some highlights:
- Revert of ASoC DAI startup changes that caused regression on some
x86 platforms
- Regression fix in HD-audio power management and driver blacklist
- A collection of ASoC DAPM and topology fixes
- Continued USB-audio fixes and quirks
- Lots of small device-specific fixes
- Rockchip S/PDIF DT stuff update for validation issues"
* tag 'sound-5.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (51 commits)
ALSA: hda: Always use jackpoll helper for jack update after resume
ALSA: hda/realtek - Add new codec supported for ALC245
ALSA: usb-audio: Fix usb audio refcnt leak when getting spdif
ALSA: usb-audio: Add connector notifier delegation
ALSA: usb-audio: Apply async workaround for Scarlett 2i4 2nd gen
ASoC: wm8960: Fix wrong clock after suspend & resume
ALSA: usx2y: Fix potential NULL dereference
ALSA: usb-audio: Add quirk for Focusrite Scarlett 2i2
ASoC: wm89xx: Add missing dependency
ASoC: dapm: fixup dapm kcontrol widget
ASoC: rsnd: Fix "status check failed" spam for multi-SSI
ASoC: rsnd: Don't treat master SSI in multi SSI setup as parent
ASoC: meson: gx-card: fix codec-to-codec link setup
ASoC: meson: axg-card: fix codec-to-codec link setup
ALSA: usb-audio: Add static mapping table for ALC1220-VB-based mobos
ALSA: hda: Remove ASUS ROG Zenith from the blacklist
ALSA: hda/realtek - Fix unexpected init_amp override
ALSA: usb-audio: Filter out unsupported sample rates on Focusrite devices
ASoC: SOF: Intel: add min/max channels for SSP on Baytrail/Broadwell
ASoC: stm32: sai: fix sai probe
...
Diffstat (limited to 'sound/soc/soc-topology.c')
-rw-r--r-- | sound/soc/soc-topology.c | 115 |
1 files changed, 89 insertions, 26 deletions
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 87f75edba3dc..6df3b0d12d87 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -894,7 +894,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, } /* create any TLV data */ - soc_tplg_create_tlv(tplg, &kc, &mc->hdr); + err = soc_tplg_create_tlv(tplg, &kc, &mc->hdr); + if (err < 0) { + dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", + mc->hdr.name); + kfree(sm); + continue; + } /* pass control to driver for optional further init */ err = soc_tplg_init_kcontrol(tplg, &kc, @@ -1118,6 +1124,7 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { struct snd_soc_tplg_ctl_hdr *control_hdr; + int ret; int i; if (tplg->pass != SOC_TPLG_PASS_MIXER) { @@ -1146,25 +1153,30 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, case SND_SOC_TPLG_CTL_RANGE: case SND_SOC_TPLG_DAPM_CTL_VOLSW: case SND_SOC_TPLG_DAPM_CTL_PIN: - soc_tplg_dmixer_create(tplg, 1, - le32_to_cpu(hdr->payload_size)); + ret = soc_tplg_dmixer_create(tplg, 1, + le32_to_cpu(hdr->payload_size)); break; case SND_SOC_TPLG_CTL_ENUM: case SND_SOC_TPLG_CTL_ENUM_VALUE: case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: - soc_tplg_denum_create(tplg, 1, - le32_to_cpu(hdr->payload_size)); + ret = soc_tplg_denum_create(tplg, 1, + le32_to_cpu(hdr->payload_size)); break; case SND_SOC_TPLG_CTL_BYTES: - soc_tplg_dbytes_create(tplg, 1, - le32_to_cpu(hdr->payload_size)); + ret = soc_tplg_dbytes_create(tplg, 1, + le32_to_cpu(hdr->payload_size)); break; default: soc_bind_err(tplg, control_hdr, i); return -EINVAL; } + if (ret < 0) { + dev_err(tplg->dev, "ASoC: invalid control\n"); + return ret; + } + } return 0; @@ -1272,7 +1284,9 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, routes[i]->dobj.index = tplg->index; list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list); - soc_tplg_add_route(tplg, routes[i]); + ret = soc_tplg_add_route(tplg, routes[i]); + if (ret < 0) + break; /* add route, but keep going if some fail */ snd_soc_dapm_add_routes(dapm, routes[i], 1); @@ -1355,7 +1369,13 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( } /* create any TLV data */ - soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr); + err = soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr); + if (err < 0) { + dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", + mc->hdr.name); + kfree(sm); + continue; + } /* pass control to driver for optional further init */ err = soc_tplg_init_kcontrol(tplg, &kc[i], @@ -1766,10 +1786,13 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg) return 0; } -static void set_stream_info(struct snd_soc_pcm_stream *stream, +static int set_stream_info(struct snd_soc_pcm_stream *stream, struct snd_soc_tplg_stream_caps *caps) { stream->stream_name = kstrdup(caps->name, GFP_KERNEL); + if (!stream->stream_name) + return -ENOMEM; + stream->channels_min = le32_to_cpu(caps->channels_min); stream->channels_max = le32_to_cpu(caps->channels_max); stream->rates = le32_to_cpu(caps->rates); @@ -1777,6 +1800,8 @@ static void set_stream_info(struct snd_soc_pcm_stream *stream, stream->rate_max = le32_to_cpu(caps->rate_max); stream->formats = le64_to_cpu(caps->formats); stream->sig_bits = le32_to_cpu(caps->sig_bits); + + return 0; } static void set_dai_flags(struct snd_soc_dai_driver *dai_drv, @@ -1812,20 +1837,29 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, if (dai_drv == NULL) return -ENOMEM; - if (strlen(pcm->dai_name)) + if (strlen(pcm->dai_name)) { dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL); + if (!dai_drv->name) { + ret = -ENOMEM; + goto err; + } + } dai_drv->id = le32_to_cpu(pcm->dai_id); if (pcm->playback) { stream = &dai_drv->playback; caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; - set_stream_info(stream, caps); + ret = set_stream_info(stream, caps); + if (ret < 0) + goto err; } if (pcm->capture) { stream = &dai_drv->capture; caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE]; - set_stream_info(stream, caps); + ret = set_stream_info(stream, caps); + if (ret < 0) + goto err; } if (pcm->compress) @@ -1835,11 +1869,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL); if (ret < 0) { dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n"); - kfree(dai_drv->playback.stream_name); - kfree(dai_drv->capture.stream_name); - kfree(dai_drv->name); - kfree(dai_drv); - return ret; + goto err; } dai_drv->dobj.index = tplg->index; @@ -1860,6 +1890,14 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, return ret; } + return 0; + +err: + kfree(dai_drv->playback.stream_name); + kfree(dai_drv->capture.stream_name); + kfree(dai_drv->name); + kfree(dai_drv); + return ret; } @@ -1916,11 +1954,20 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, if (strlen(pcm->pcm_name)) { link->name = kstrdup(pcm->pcm_name, GFP_KERNEL); link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL); + if (!link->name || !link->stream_name) { + ret = -ENOMEM; + goto err; + } } link->id = le32_to_cpu(pcm->pcm_id); - if (strlen(pcm->dai_name)) + if (strlen(pcm->dai_name)) { link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL); + if (!link->cpus->dai_name) { + ret = -ENOMEM; + goto err; + } + } link->codecs->name = "snd-soc-dummy"; link->codecs->dai_name = "snd-soc-dummy-dai"; @@ -2088,7 +2135,9 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, _pcm = pcm; } else { abi_match = false; - pcm_new_ver(tplg, pcm, &_pcm); + ret = pcm_new_ver(tplg, pcm, &_pcm); + if (ret < 0) + return ret; } /* create the FE DAIs and DAI links */ @@ -2436,13 +2485,17 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg, if (d->playback) { stream = &dai_drv->playback; caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; - set_stream_info(stream, caps); + ret = set_stream_info(stream, caps); + if (ret < 0) + goto err; } if (d->capture) { stream = &dai_drv->capture; caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE]; - set_stream_info(stream, caps); + ret = set_stream_info(stream, caps); + if (ret < 0) + goto err; } if (d->flag_mask) @@ -2454,10 +2507,15 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg, ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai); if (ret < 0) { dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n"); - return ret; + goto err; } return 0; + +err: + kfree(dai_drv->playback.stream_name); + kfree(dai_drv->capture.stream_name); + return ret; } /* load physical DAI elements */ @@ -2466,7 +2524,7 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg, { struct snd_soc_tplg_dai *dai; int count; - int i; + int i, ret; count = le32_to_cpu(hdr->count); @@ -2481,7 +2539,12 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg, return -EINVAL; } - soc_tplg_dai_config(tplg, dai); + ret = soc_tplg_dai_config(tplg, dai); + if (ret < 0) { + dev_err(tplg->dev, "ASoC: failed to configure DAI\n"); + return ret; + } + tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size)); } @@ -2589,7 +2652,7 @@ static int soc_valid_header(struct soc_tplg *tplg, } /* big endian firmware objects not supported atm */ - if (hdr->magic == SOC_TPLG_MAGIC_BIG_ENDIAN) { + if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) { dev_err(tplg->dev, "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n", tplg->pass, hdr->magic, |