Unverified Commit b442e7c4 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: stm32: sai: fix device and OF node leaks on

Merge series from Johan Hovold <johan@kernel.org>:

This series fixes device and OF node reference leaks during probe and
a clock prepare imbalance on probe failures.

Included is a related cleanup of an error path.
parents 84b7344c 3a03de36
Loading
Loading
Loading
Loading
+4 −10
Original line number Diff line number Diff line
@@ -138,30 +138,24 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,
	if (!pdev) {
		dev_err(&sai_client->pdev->dev,
			"Device not found for node %pOFn\n", np_provider);
		of_node_put(np_provider);
		return -ENODEV;
	}

	sai_provider = platform_get_drvdata(pdev);
	put_device(&pdev->dev);
	if (!sai_provider) {
		dev_err(&sai_client->pdev->dev,
			"SAI sync provider data not found\n");
		ret = -EINVAL;
		goto error;
		return -EINVAL;
	}

	/* Configure sync client */
	ret = stm32_sai_sync_conf_client(sai_client, synci);
	if (ret < 0)
		goto error;
		return ret;

	/* Configure sync provider */
	ret = stm32_sai_sync_conf_provider(sai_provider, synco);

error:
	put_device(&pdev->dev);
	of_node_put(np_provider);
	return ret;
	return stm32_sai_sync_conf_provider(sai_provider, synco);
}

static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai)
+40 −17
Original line number Diff line number Diff line
@@ -1586,7 +1586,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
				dev_err(&pdev->dev,
					"External synchro not supported\n");
				of_node_put(args.np);
				return -EINVAL;
				ret = -EINVAL;
				goto err_put_sync_provider;
			}
			sai->sync = SAI_SYNC_EXTERNAL;

@@ -1595,7 +1596,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
			    (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {
				dev_err(&pdev->dev, "Wrong SAI index\n");
				of_node_put(args.np);
				return -EINVAL;
				ret = -EINVAL;
				goto err_put_sync_provider;
			}

			if (of_property_match_string(args.np, "compatible",
@@ -1609,7 +1611,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
			if (!sai->synco) {
				dev_err(&pdev->dev, "Unknown SAI sub-block\n");
				of_node_put(args.np);
				return -EINVAL;
				ret = -EINVAL;
				goto err_put_sync_provider;
			}
		}

@@ -1619,13 +1622,15 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,

	of_node_put(args.np);
	sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
	if (IS_ERR(sai->sai_ck))
		return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
	if (IS_ERR(sai->sai_ck)) {
		ret = dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
				    "Missing kernel clock sai_ck\n");
		goto err_put_sync_provider;
	}

	ret = clk_prepare(sai->pdata->pclk);
	if (ret < 0)
		return ret;
		goto err_put_sync_provider;

	if (STM_SAI_IS_F4(sai->pdata))
		return 0;
@@ -1634,14 +1639,23 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
	if (of_property_present(np, "#clock-cells")) {
		ret = stm32_sai_add_mclk_provider(sai);
		if (ret < 0)
			return ret;
			goto err_unprepare_pclk;
	} else {
		sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
		if (IS_ERR(sai->sai_mclk))
			return PTR_ERR(sai->sai_mclk);
		if (IS_ERR(sai->sai_mclk)) {
			ret = PTR_ERR(sai->sai_mclk);
			goto err_unprepare_pclk;
		}
	}

	return 0;

err_unprepare_pclk:
	clk_unprepare(sai->pdata->pclk);
err_put_sync_provider:
	of_node_put(sai->np_sync_provider);

	return ret;
}

static int stm32_sai_sub_probe(struct platform_device *pdev)
@@ -1688,26 +1702,34 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
			       IRQF_SHARED, dev_name(&pdev->dev), sai);
	if (ret) {
		dev_err(&pdev->dev, "IRQ request returned %d\n", ret);
		return ret;
		goto err_unprepare_pclk;
	}

	if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
		conf = &stm32_sai_pcm_config_spdif;

	ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
	if (ret)
		return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
	if (ret) {
		ret = dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
		goto err_unprepare_pclk;
	}

	ret = snd_soc_register_component(&pdev->dev, &stm32_component,
					 &sai->cpu_dai_drv, 1);
	if (ret) {
		snd_dmaengine_pcm_unregister(&pdev->dev);
		return ret;
	}
	if (ret)
		goto err_deregister_pcm_dma;

	pm_runtime_enable(&pdev->dev);

	return 0;

err_deregister_pcm_dma:
	snd_dmaengine_pcm_unregister(&pdev->dev);
err_unprepare_pclk:
	clk_unprepare(sai->pdata->pclk);
	of_node_put(sai->np_sync_provider);

	return ret;
}

static void stm32_sai_sub_remove(struct platform_device *pdev)
@@ -1718,6 +1740,7 @@ static void stm32_sai_sub_remove(struct platform_device *pdev)
	snd_dmaengine_pcm_unregister(&pdev->dev);
	snd_soc_unregister_component(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
	of_node_put(sai->np_sync_provider);
}

static int stm32_sai_sub_suspend(struct device *dev)