Commit 6f2a35d6 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Chanwoo Choi
Browse files

PM / devfreq: tegra30: Move clk-notifier's registration to governor's start



There is no point in receiving of the notifications while governor is
stopped, let's keep them disabled like we do for the CPU freq-change
notifications. This also fixes a potential use-after-free bug if
notification happens after device's removal.

Reviewed-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
Tested-by: default avatarPeter Geis <pgwipeout@gmail.com>
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
parent 11eb6ec5
Loading
Loading
Loading
Loading
+23 −16
Original line number Diff line number Diff line
@@ -514,6 +514,21 @@ static int tegra_actmon_start(struct tegra_devfreq *tegra)
	actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1,
		      ACTMON_GLB_PERIOD_CTRL);

	/*
	 * CLK notifications are needed in order to reconfigure the upper
	 * consecutive watermark in accordance to the actual clock rate
	 * to avoid unnecessary upper interrupts.
	 */
	err = clk_notifier_register(tegra->emc_clock,
				    &tegra->clk_rate_change_nb);
	if (err) {
		dev_err(tegra->devfreq->dev.parent,
			"Failed to register rate change notifier\n");
		return err;
	}

	tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ;

	for (i = 0; i < ARRAY_SIZE(tegra->devices); i++)
		tegra_actmon_configure_device(tegra, &tegra->devices[i]);

@@ -539,6 +554,8 @@ static int tegra_actmon_start(struct tegra_devfreq *tegra)
err_stop:
	tegra_actmon_stop_devices(tegra);

	clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb);

	return err;
}

@@ -552,6 +569,8 @@ static void tegra_actmon_stop(struct tegra_devfreq *tegra)
	cancel_delayed_work_sync(&tegra->cpufreq_update_work);

	tegra_actmon_stop_devices(tegra);

	clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb);
}

static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
@@ -768,7 +787,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
		return rate;
	}

	tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ;
	tegra->max_freq = rate / KHZ;

	for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) {
@@ -796,27 +814,20 @@ static int tegra_devfreq_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, tegra);

	tegra->clk_rate_change_nb.notifier_call = tegra_actmon_clk_notify_cb;
	tegra->cpu_rate_change_nb.notifier_call = tegra_actmon_cpu_notify_cb;

	INIT_DELAYED_WORK(&tegra->cpufreq_update_work,
			  tegra_actmon_delayed_update);

	tegra->clk_rate_change_nb.notifier_call = tegra_actmon_clk_notify_cb;
	err = clk_notifier_register(tegra->emc_clock,
				    &tegra->clk_rate_change_nb);
	if (err) {
		dev_err(&pdev->dev,
			"Failed to register rate change notifier\n");
		goto remove_opps;
	}

	err = devfreq_add_governor(&tegra_devfreq_governor);
	if (err) {
		dev_err(&pdev->dev, "Failed to add governor: %d\n", err);
		goto unreg_notifier;
		goto remove_opps;
	}

	tegra_devfreq_profile.initial_freq = tegra->cur_freq;
	tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock);
	tegra_devfreq_profile.initial_freq /= KHZ;

	devfreq = devfreq_add_device(&pdev->dev, &tegra_devfreq_profile,
				     "tegra_actmon", NULL);
@@ -830,9 +841,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
remove_governor:
	devfreq_remove_governor(&tegra_devfreq_governor);

unreg_notifier:
	clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb);

remove_opps:
	dev_pm_opp_remove_all_dynamic(&pdev->dev);

@@ -849,7 +857,6 @@ static int tegra_devfreq_remove(struct platform_device *pdev)
	devfreq_remove_device(tegra->devfreq);
	devfreq_remove_governor(&tegra_devfreq_governor);

	clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb);
	dev_pm_opp_remove_all_dynamic(&pdev->dev);

	reset_control_reset(tegra->reset);