Commit fcbd6215 authored by Robin Murphy's avatar Robin Murphy Committed by Will Deacon
Browse files

iommu/arm-smmu-v3: Clean up more on probe failure



kmemleak noticed that the iopf queue allocated deep down within
arm_smmu_init_structures() can be leaked by a subsequent error return
from arm_smmu_device_probe(). Furthermore, after arm_smmu_device_reset()
we will also leave the SMMU enabled with an empty Stream Table, silently
blocking all DMA. This proves rather annoying for debugging said probe
failure, so let's handle it a bit better by putting the SMMU back into
(more or less) the same state as if it hadn't probed at all.

Signed-off-by: default avatarRobin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/5137901958471cf67f2fad5c2229f8a8f1ae901a.1733406914.git.robin.murphy@arm.com


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 97cb1fa0
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -4777,7 +4777,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
	/* Initialise in-memory data structures */
	ret = arm_smmu_init_structures(smmu);
	if (ret)
		return ret;
		goto err_free_iopf;

	/* Record our private device structure */
	platform_set_drvdata(pdev, smmu);
@@ -4788,22 +4788,29 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
	/* Reset the device */
	ret = arm_smmu_device_reset(smmu);
	if (ret)
		return ret;
		goto err_disable;

	/* And we're up. Go go go! */
	ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL,
				     "smmu3.%pa", &ioaddr);
	if (ret)
		return ret;
		goto err_disable;

	ret = iommu_device_register(&smmu->iommu, &arm_smmu_ops, dev);
	if (ret) {
		dev_err(dev, "Failed to register iommu\n");
		iommu_device_sysfs_remove(&smmu->iommu);
		return ret;
		goto err_free_sysfs;
	}

	return 0;

err_free_sysfs:
	iommu_device_sysfs_remove(&smmu->iommu);
err_disable:
	arm_smmu_device_disable(smmu);
err_free_iopf:
	iopf_queue_free(smmu->evtq.iopf);
	return ret;
}

static void arm_smmu_device_remove(struct platform_device *pdev)