Commit 46207625 authored by Johan Hovold's avatar Johan Hovold Committed by Joerg Roedel
Browse files

iommu/mediatek-v1: fix device leaks on probe()



Make sure to drop the references taken to the larb devices during
probe on probe failure (e.g. probe deferral) and on driver unbind.

Fixes: b17336c5 ("iommu/mediatek: add support for mtk iommu generation one HW")
Cc: stable@vger.kernel.org	# 4.8
Cc: Honghui Zhang <honghui.zhang@mediatek.com>
Acked-by: default avatarRobin Murphy <robin.murphy@arm.com>
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
Reviewed-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent c77ad28b
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -651,8 +651,10 @@ static int mtk_iommu_v1_probe(struct platform_device *pdev)
		struct platform_device *plarbdev;

		larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
		if (!larbnode)
			return -EINVAL;
		if (!larbnode) {
			ret = -EINVAL;
			goto out_put_larbs;
		}

		if (!of_device_is_available(larbnode)) {
			of_node_put(larbnode);
@@ -662,11 +664,14 @@ static int mtk_iommu_v1_probe(struct platform_device *pdev)
		plarbdev = of_find_device_by_node(larbnode);
		if (!plarbdev) {
			of_node_put(larbnode);
			return -ENODEV;
			ret = -ENODEV;
			goto out_put_larbs;
		}
		if (!plarbdev->dev.driver) {
			of_node_put(larbnode);
			return -EPROBE_DEFER;
			put_device(&plarbdev->dev);
			ret = -EPROBE_DEFER;
			goto out_put_larbs;
		}
		data->larb_imu[i].dev = &plarbdev->dev;

@@ -678,7 +683,7 @@ static int mtk_iommu_v1_probe(struct platform_device *pdev)

	ret = mtk_iommu_v1_hw_init(data);
	if (ret)
		return ret;
		goto out_put_larbs;

	ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL,
				     dev_name(&pdev->dev));
@@ -700,12 +705,17 @@ static int mtk_iommu_v1_probe(struct platform_device *pdev)
	iommu_device_sysfs_remove(&data->iommu);
out_clk_unprepare:
	clk_disable_unprepare(data->bclk);
out_put_larbs:
	for (i = 0; i < MTK_LARB_NR_MAX; i++)
		put_device(data->larb_imu[i].dev);

	return ret;
}

static void mtk_iommu_v1_remove(struct platform_device *pdev)
{
	struct mtk_iommu_v1_data *data = platform_get_drvdata(pdev);
	int i;

	iommu_device_sysfs_remove(&data->iommu);
	iommu_device_unregister(&data->iommu);
@@ -713,6 +723,9 @@ static void mtk_iommu_v1_remove(struct platform_device *pdev)
	clk_disable_unprepare(data->bclk);
	devm_free_irq(&pdev->dev, data->irq, data);
	component_master_del(&pdev->dev, &mtk_iommu_v1_com_ops);

	for (i = 0; i < MTK_LARB_NR_MAX; i++)
		put_device(data->larb_imu[i].dev);
}

static int __maybe_unused mtk_iommu_v1_suspend(struct device *dev)