Commit 9ee68b31 authored by Leonard Crestez's avatar Leonard Crestez Committed by Will Deacon
Browse files

perf/imx_ddr: Fix cpu hotplug state cleanup



This driver allocates a dynamic cpu hotplug state but never releases it.
If reloaded in a loop it will quickly trigger a WARN message:

	"No more dynamic states available for CPU hotplug"

Fix by calling cpuhp_remove_multi_state on remove like several other
perf pmu drivers.

Also fix the cleanup logic on probe error paths: add the missing
cpuhp_remove_multi_state call and properly check the return value from
cpuhp_state_add_instant_nocalls.

Fixes: 9a66d36c ("drivers/perf: imx_ddr: Add DDR performance counter support to perf")
Acked-by: default avatarJoakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: default avatarLeonard Crestez <leonard.crestez@nxp.com>
Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 73daf0bb
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -633,13 +633,17 @@ static int ddr_perf_probe(struct platform_device *pdev)

	if (ret < 0) {
		dev_err(&pdev->dev, "cpuhp_setup_state_multi failed\n");
		goto ddr_perf_err;
		goto cpuhp_state_err;
	}

	pmu->cpuhp_state = ret;

	/* Register the pmu instance for cpu hotplug */
	cpuhp_state_add_instance_nocalls(pmu->cpuhp_state, &pmu->node);
	ret = cpuhp_state_add_instance_nocalls(pmu->cpuhp_state, &pmu->node);
	if (ret) {
		dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
		goto cpuhp_instance_err;
	}

	/* Request irq */
	irq = of_irq_get(np, 0);
@@ -673,9 +677,10 @@ static int ddr_perf_probe(struct platform_device *pdev)
	return 0;

ddr_perf_err:
	if (pmu->cpuhp_state)
	cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node);

cpuhp_instance_err:
	cpuhp_remove_multi_state(pmu->cpuhp_state);
cpuhp_state_err:
	ida_simple_remove(&ddr_ida, pmu->id);
	dev_warn(&pdev->dev, "i.MX8 DDR Perf PMU failed (%d), disabled\n", ret);
	return ret;
@@ -686,6 +691,7 @@ static int ddr_perf_remove(struct platform_device *pdev)
	struct ddr_pmu *pmu = platform_get_drvdata(pdev);

	cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node);
	cpuhp_remove_multi_state(pmu->cpuhp_state);
	irq_set_affinity_hint(pmu->irq, NULL);

	perf_pmu_unregister(&pmu->pmu);