Commit 76c49909 authored by Mark Brown's avatar Mark Brown

Merge series "ASoC: topology: fix error handling flow" from Pierre-Louis...

Merge series "ASoC: topology: fix error handling flow" from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

While experimenting and introducing errors in Baytrail topology files
until I got them right, I encountered multiple kernel oopses and
memory leaks. This is a first batch to harden the code, but we should
probably think of a tool to fuzz the topology...

Pierre-Louis Bossart (5):
  ASoC: topology: fix kernel oops on route addition error
  ASoC: topology: fix tlvs in error handling for widget_dmixer
  ASoC: topology: use break on errors, not continue
  ASoC: topology: factor kfree(se) in error handling
  ASoC: topology: add more logs when topology load fails.

 sound/soc/soc-topology.c | 97 ++++++++++++++++++++++++----------------
 1 file changed, 58 insertions(+), 39 deletions(-)

base-commit: a5911ac5
--
2.25.1
parents 81e7d4ce 8bf9475f
...@@ -6956,6 +6956,7 @@ M: Timur Tabi <timur@kernel.org> ...@@ -6956,6 +6956,7 @@ M: Timur Tabi <timur@kernel.org>
M: Nicolin Chen <nicoleotsuka@gmail.com> M: Nicolin Chen <nicoleotsuka@gmail.com>
M: Xiubo Li <Xiubo.Lee@gmail.com> M: Xiubo Li <Xiubo.Lee@gmail.com>
R: Fabio Estevam <festevam@gmail.com> R: Fabio Estevam <festevam@gmail.com>
R: Shengjiu Wang <shengjiu.wang@gmail.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
L: linuxppc-dev@lists.ozlabs.org L: linuxppc-dev@lists.ozlabs.org
S: Maintained S: Maintained
...@@ -11333,17 +11334,17 @@ F: drivers/iio/adc/at91-sama5d2_adc.c ...@@ -11333,17 +11334,17 @@ F: drivers/iio/adc/at91-sama5d2_adc.c
F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h
MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER
M: Nicolas Ferre <nicolas.ferre@microchip.com> M: Claudiu Beznea <claudiu.beznea@microchip.com>
S: Supported S: Supported
F: drivers/power/reset/at91-sama5d2_shdwc.c F: drivers/power/reset/at91-sama5d2_shdwc.c
MICROCHIP SPI DRIVER MICROCHIP SPI DRIVER
M: Nicolas Ferre <nicolas.ferre@microchip.com> M: Tudor Ambarus <tudor.ambarus@microchip.com>
S: Supported S: Supported
F: drivers/spi/spi-atmel.* F: drivers/spi/spi-atmel.*
MICROCHIP SSC DRIVER MICROCHIP SSC DRIVER
M: Nicolas Ferre <nicolas.ferre@microchip.com> M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported S: Supported
F: drivers/misc/atmel-ssc.c F: drivers/misc/atmel-ssc.c
......
...@@ -426,6 +426,8 @@ int devm_snd_soc_register_component(struct device *dev, ...@@ -426,6 +426,8 @@ int devm_snd_soc_register_component(struct device *dev,
const struct snd_soc_component_driver *component_driver, const struct snd_soc_component_driver *component_driver,
struct snd_soc_dai_driver *dai_drv, int num_dai); struct snd_soc_dai_driver *dai_drv, int num_dai);
void snd_soc_unregister_component(struct device *dev); void snd_soc_unregister_component(struct device *dev);
void snd_soc_unregister_component_by_driver(struct device *dev,
const struct snd_soc_component_driver *component_driver);
struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev,
const char *driver_name); const char *driver_name);
struct snd_soc_component *snd_soc_lookup_component(struct device *dev, struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
......
...@@ -232,9 +232,7 @@ static int snd_acp3x_probe(struct pci_dev *pci, ...@@ -232,9 +232,7 @@ static int snd_acp3x_probe(struct pci_dev *pci,
} }
pm_runtime_set_autosuspend_delay(&pci->dev, 2000); pm_runtime_set_autosuspend_delay(&pci->dev, 2000);
pm_runtime_use_autosuspend(&pci->dev); pm_runtime_use_autosuspend(&pci->dev);
pm_runtime_set_active(&pci->dev);
pm_runtime_put_noidle(&pci->dev); pm_runtime_put_noidle(&pci->dev);
pm_runtime_enable(&pci->dev);
pm_runtime_allow(&pci->dev); pm_runtime_allow(&pci->dev);
return 0; return 0;
...@@ -303,7 +301,7 @@ static void snd_acp3x_remove(struct pci_dev *pci) ...@@ -303,7 +301,7 @@ static void snd_acp3x_remove(struct pci_dev *pci)
ret = acp3x_deinit(adata->acp3x_base); ret = acp3x_deinit(adata->acp3x_base);
if (ret) if (ret)
dev_err(&pci->dev, "ACP de-init failed\n"); dev_err(&pci->dev, "ACP de-init failed\n");
pm_runtime_disable(&pci->dev); pm_runtime_forbid(&pci->dev);
pm_runtime_get_noresume(&pci->dev); pm_runtime_get_noresume(&pci->dev);
pci_disable_msi(pci); pci_disable_msi(pci);
pci_release_regions(pci); pci_release_regions(pci);
......
...@@ -992,16 +992,17 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, ...@@ -992,16 +992,17 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
rt5682->hs_jack = hs_jack; rt5682->hs_jack = hs_jack;
if (!rt5682->is_sdw) {
if (!hs_jack) { if (!hs_jack) {
regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
RT5682_JD1_EN_MASK, RT5682_JD1_DIS); RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
RT5682_POW_JDH | RT5682_POW_JDL, 0); RT5682_POW_JDH | RT5682_POW_JDL, 0);
cancel_delayed_work_sync(&rt5682->jack_detect_work); cancel_delayed_work_sync(&rt5682->jack_detect_work);
return 0; return 0;
} }
if (!rt5682->is_sdw) {
switch (rt5682->pdata.jd_src) { switch (rt5682->pdata.jd_src) {
case RT5682_JD1: case RT5682_JD1:
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
......
...@@ -219,19 +219,32 @@ static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream, ...@@ -219,19 +219,32 @@ static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static int rockchip_sound_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
8000, 96000);
}
static const struct snd_soc_ops rockchip_sound_max98357a_ops = { static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
.startup = rockchip_sound_startup,
.hw_params = rockchip_sound_max98357a_hw_params, .hw_params = rockchip_sound_max98357a_hw_params,
}; };
static const struct snd_soc_ops rockchip_sound_rt5514_ops = { static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
.startup = rockchip_sound_startup,
.hw_params = rockchip_sound_rt5514_hw_params, .hw_params = rockchip_sound_rt5514_hw_params,
}; };
static const struct snd_soc_ops rockchip_sound_da7219_ops = { static const struct snd_soc_ops rockchip_sound_da7219_ops = {
.startup = rockchip_sound_startup,
.hw_params = rockchip_sound_da7219_hw_params, .hw_params = rockchip_sound_da7219_hw_params,
}; };
static const struct snd_soc_ops rockchip_sound_dmic_ops = { static const struct snd_soc_ops rockchip_sound_dmic_ops = {
.startup = rockchip_sound_startup,
.hw_params = rockchip_sound_dmic_hw_params, .hw_params = rockchip_sound_dmic_hw_params,
}; };
......
...@@ -2513,6 +2513,33 @@ int snd_soc_register_component(struct device *dev, ...@@ -2513,6 +2513,33 @@ int snd_soc_register_component(struct device *dev,
} }
EXPORT_SYMBOL_GPL(snd_soc_register_component); EXPORT_SYMBOL_GPL(snd_soc_register_component);
/**
* snd_soc_unregister_component_by_driver - Unregister component using a given driver
* from the ASoC core
*
* @dev: The device to unregister
* @component_driver: The component driver to unregister
*/
void snd_soc_unregister_component_by_driver(struct device *dev,
const struct snd_soc_component_driver *component_driver)
{
struct snd_soc_component *component;
if (!component_driver)
return;
mutex_lock(&client_mutex);
component = snd_soc_lookup_component_nolocked(dev, component_driver->name);
if (!component)
goto out;
snd_soc_del_component_unlocked(component);
out:
mutex_unlock(&client_mutex);
}
EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver);
/** /**
* snd_soc_unregister_component - Unregister all related component * snd_soc_unregister_component - Unregister all related component
* from the ASoC core * from the ASoC core
......
...@@ -48,7 +48,9 @@ EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai); ...@@ -48,7 +48,9 @@ EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai);
static void devm_component_release(struct device *dev, void *res) static void devm_component_release(struct device *dev, void *res)
{ {
snd_soc_unregister_component(*(struct device **)res); const struct snd_soc_component_driver **cmpnt_drv = res;
snd_soc_unregister_component_by_driver(dev, *cmpnt_drv);
} }
/** /**
...@@ -65,7 +67,7 @@ int devm_snd_soc_register_component(struct device *dev, ...@@ -65,7 +67,7 @@ int devm_snd_soc_register_component(struct device *dev,
const struct snd_soc_component_driver *cmpnt_drv, const struct snd_soc_component_driver *cmpnt_drv,
struct snd_soc_dai_driver *dai_drv, int num_dai) struct snd_soc_dai_driver *dai_drv, int num_dai)
{ {
struct device **ptr; const struct snd_soc_component_driver **ptr;
int ret; int ret;
ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL); ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
...@@ -74,7 +76,7 @@ int devm_snd_soc_register_component(struct device *dev, ...@@ -74,7 +76,7 @@ int devm_snd_soc_register_component(struct device *dev,
ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai); ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
if (ret == 0) { if (ret == 0) {
*ptr = dev; *ptr = cmpnt_drv;
devres_add(dev, ptr); devres_add(dev, ptr);
} else { } else {
devres_free(ptr); devres_free(ptr);
......
...@@ -478,7 +478,7 @@ void snd_dmaengine_pcm_unregister(struct device *dev) ...@@ -478,7 +478,7 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
pcm = soc_component_to_pcm(component); pcm = soc_component_to_pcm(component);
snd_soc_unregister_component(dev); snd_soc_unregister_component_by_driver(dev, component->driver);
dmaengine_pcm_release_chan(pcm); dmaengine_pcm_release_chan(pcm);
kfree(pcm); kfree(pcm);
} }
......
...@@ -741,7 +741,8 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, ...@@ -741,7 +741,8 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count,
struct snd_soc_tplg_bytes_control *be; struct snd_soc_tplg_bytes_control *be;
struct soc_bytes_ext *sbe; struct soc_bytes_ext *sbe;
struct snd_kcontrol_new kc; struct snd_kcontrol_new kc;
int i, err; int i;
int err = 0;
if (soc_tplg_check_elem_count(tplg, if (soc_tplg_check_elem_count(tplg,
sizeof(struct snd_soc_tplg_bytes_control), count, sizeof(struct snd_soc_tplg_bytes_control), count,
...@@ -786,7 +787,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, ...@@ -786,7 +787,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count,
if (err) { if (err) {
soc_control_err(tplg, &be->hdr, be->hdr.name); soc_control_err(tplg, &be->hdr, be->hdr.name);
kfree(sbe); kfree(sbe);
continue; break;
} }
/* pass control to driver for optional further init */ /* pass control to driver for optional further init */
...@@ -796,7 +797,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, ...@@ -796,7 +797,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count,
dev_err(tplg->dev, "ASoC: failed to init %s\n", dev_err(tplg->dev, "ASoC: failed to init %s\n",
be->hdr.name); be->hdr.name);
kfree(sbe); kfree(sbe);
continue; break;
} }
/* register control here */ /* register control here */
...@@ -806,12 +807,12 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, ...@@ -806,12 +807,12 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count,
dev_err(tplg->dev, "ASoC: failed to add %s\n", dev_err(tplg->dev, "ASoC: failed to add %s\n",
be->hdr.name); be->hdr.name);
kfree(sbe); kfree(sbe);
continue; break;
} }
list_add(&sbe->dobj.list, &tplg->comp->dobj_list); list_add(&sbe->dobj.list, &tplg->comp->dobj_list);
} }
return 0; return err;
} }
...@@ -821,7 +822,8 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, ...@@ -821,7 +822,8 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
struct snd_soc_tplg_mixer_control *mc; struct snd_soc_tplg_mixer_control *mc;
struct soc_mixer_control *sm; struct soc_mixer_control *sm;
struct snd_kcontrol_new kc; struct snd_kcontrol_new kc;
int i, err; int i;
int err = 0;
if (soc_tplg_check_elem_count(tplg, if (soc_tplg_check_elem_count(tplg,
sizeof(struct snd_soc_tplg_mixer_control), sizeof(struct snd_soc_tplg_mixer_control),
...@@ -880,7 +882,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, ...@@ -880,7 +882,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
if (err) { if (err) {
soc_control_err(tplg, &mc->hdr, mc->hdr.name); soc_control_err(tplg, &mc->hdr, mc->hdr.name);
kfree(sm); kfree(sm);
continue; break;
} }
/* create any TLV data */ /* create any TLV data */
...@@ -889,7 +891,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, ...@@ -889,7 +891,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
mc->hdr.name); mc->hdr.name);
kfree(sm); kfree(sm);
continue; break;
} }
/* pass control to driver for optional further init */ /* pass control to driver for optional further init */
...@@ -900,7 +902,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, ...@@ -900,7 +902,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
mc->hdr.name); mc->hdr.name);
soc_tplg_free_tlv(tplg, &kc); soc_tplg_free_tlv(tplg, &kc);
kfree(sm); kfree(sm);
continue; break;
} }
/* register control here */ /* register control here */
...@@ -911,13 +913,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, ...@@ -911,13 +913,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
mc->hdr.name); mc->hdr.name);
soc_tplg_free_tlv(tplg, &kc); soc_tplg_free_tlv(tplg, &kc);
kfree(sm); kfree(sm);
continue; break;
} }
list_add(&sm->dobj.list, &tplg->comp->dobj_list); list_add(&sm->dobj.list, &tplg->comp->dobj_list);
} }
return 0; return err;
} }
static int soc_tplg_denum_create_texts(struct soc_enum *se, static int soc_tplg_denum_create_texts(struct soc_enum *se,
...@@ -997,7 +999,8 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, ...@@ -997,7 +999,8 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count,
struct snd_soc_tplg_enum_control *ec; struct snd_soc_tplg_enum_control *ec;
struct soc_enum *se; struct soc_enum *se;
struct snd_kcontrol_new kc; struct snd_kcontrol_new kc;
int i, ret, err; int i;
int err = 0;
if (soc_tplg_check_elem_count(tplg, if (soc_tplg_check_elem_count(tplg,
sizeof(struct snd_soc_tplg_enum_control), sizeof(struct snd_soc_tplg_enum_control),
...@@ -1052,8 +1055,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, ...@@ -1052,8 +1055,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count,
dev_err(tplg->dev, dev_err(tplg->dev,
"ASoC: could not create values for %s\n", "ASoC: could not create values for %s\n",
ec->hdr.name); ec->hdr.name);
kfree(se); goto err_denum;
continue;
} }
/* fall through */ /* fall through */
case SND_SOC_TPLG_CTL_ENUM: case SND_SOC_TPLG_CTL_ENUM:
...@@ -1064,24 +1066,22 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, ...@@ -1064,24 +1066,22 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count,
dev_err(tplg->dev, dev_err(tplg->dev,
"ASoC: could not create texts for %s\n", "ASoC: could not create texts for %s\n",
ec->hdr.name); ec->hdr.name);
kfree(se); goto err_denum;
continue;
} }
break; break;
default: default:
err = -EINVAL;
dev_err(tplg->dev, dev_err(tplg->dev,
"ASoC: invalid enum control type %d for %s\n", "ASoC: invalid enum control type %d for %s\n",
ec->hdr.ops.info, ec->hdr.name); ec->hdr.ops.info, ec->hdr.name);
kfree(se); goto err_denum;
continue;
} }
/* map io handlers */ /* map io handlers */
err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg);
if (err) { if (err) {
soc_control_err(tplg, &ec->hdr, ec->hdr.name); soc_control_err(tplg, &ec->hdr, ec->hdr.name);
kfree(se); goto err_denum;
continue;
} }
/* pass control to driver for optional further init */ /* pass control to driver for optional further init */
...@@ -1090,24 +1090,25 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, ...@@ -1090,24 +1090,25 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count,
if (err < 0) { if (err < 0) {
dev_err(tplg->dev, "ASoC: failed to init %s\n", dev_err(tplg->dev, "ASoC: failed to init %s\n",
ec->hdr.name); ec->hdr.name);
kfree(se); goto err_denum;
continue;
} }
/* register control here */ /* register control here */
ret = soc_tplg_add_kcontrol(tplg, err = soc_tplg_add_kcontrol(tplg,
&kc, &se->dobj.control.kcontrol); &kc, &se->dobj.control.kcontrol);
if (ret < 0) { if (err < 0) {
dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n", dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n",
ec->hdr.name); ec->hdr.name);
kfree(se); goto err_denum;
continue;
} }
list_add(&se->dobj.list, &tplg->comp->dobj_list); list_add(&se->dobj.list, &tplg->comp->dobj_list);
} }
return 0; return 0;
err_denum:
kfree(se);
return err;
} }
static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
...@@ -1261,17 +1262,30 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, ...@@ -1261,17 +1262,30 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list); list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list);
ret = soc_tplg_add_route(tplg, routes[i]); ret = soc_tplg_add_route(tplg, routes[i]);
if (ret < 0) if (ret < 0) {
dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret);
/*
* this route was added to the list, it will
* be freed in remove_route() so increment the
* counter to skip it in the error handling
* below.
*/
i++;
break; break;
}
/* add route, but keep going if some fail */ /* add route, but keep going if some fail */
snd_soc_dapm_add_routes(dapm, routes[i], 1); snd_soc_dapm_add_routes(dapm, routes[i], 1);
} }
/* free memory allocated for all dapm routes in case of error */ /*
if (ret < 0) * free memory allocated for all dapm routes not added to the
for (i = 0; i < count ; i++) * list in case of error
kfree(routes[i]); */
if (ret < 0) {
while (i < count)
kfree(routes[i++]);
}
/* /*
* free pointer to array of dapm routes as this is no longer needed. * free pointer to array of dapm routes as this is no longer needed.
...@@ -1349,8 +1363,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( ...@@ -1349,8 +1363,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
if (err < 0) { if (err < 0) {
dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
mc->hdr.name); mc->hdr.name);
kfree(sm); goto err_sm;
continue;
} }
/* pass control to driver for optional further init */ /* pass control to driver for optional further init */
...@@ -1359,7 +1372,6 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( ...@@ -1359,7 +1372,6 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
if (err < 0) { if (err < 0) {
dev_err(tplg->dev, "ASoC: failed to init %s\n", dev_err(tplg->dev, "ASoC: failed to init %s\n",
mc->hdr.name); mc->hdr.name);
soc_tplg_free_tlv(tplg, &kc[i]);
goto err_sm; goto err_sm;
} }
} }
...@@ -1367,6 +1379,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( ...@@ -1367,6 +1379,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
err_sm: err_sm:
for (; i >= 0; i--) { for (; i >= 0; i--) {
soc_tplg_free_tlv(tplg, &kc[i]);
sm = (struct soc_mixer_control *)kc[i].private_value; sm = (struct soc_mixer_control *)kc[i].private_value;
kfree(sm); kfree(sm);
kfree(kc[i].name); kfree(kc[i].name);
...@@ -2731,15 +2744,21 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg) ...@@ -2731,15 +2744,21 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg)
/* make sure header is valid before loading */ /* make sure header is valid before loading */
ret = soc_valid_header(tplg, hdr); ret = soc_valid_header(tplg, hdr);
if (ret < 0) if (ret < 0) {
dev_err(tplg->dev,
"ASoC: topology: invalid header: %d\n", ret);
return ret; return ret;
else if (ret == 0) } else if (ret == 0) {
break; break;
}
/* load the header object */ /* load the header object */
ret = soc_tplg_load_header(tplg, hdr); ret = soc_tplg_load_header(tplg, hdr);
if (ret < 0) if (ret < 0) {
dev_err(tplg->dev,
"ASoC: topology: could not load header: %d\n", ret);
return ret; return ret;
}
/* goto next header */ /* goto next header */
tplg->hdr_pos += le32_to_cpu(hdr->payload_size) + tplg->hdr_pos += le32_to_cpu(hdr->payload_size) +
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment