Skip to content

Commit 6f2a35d

Browse files
digetxchanwoochoi
authored andcommitted
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: Chanwoo Choi <[email protected]> Tested-by: Peter Geis <[email protected]> Signed-off-by: Dmitry Osipenko <[email protected]> Signed-off-by: Chanwoo Choi <[email protected]>
1 parent 11eb6ec commit 6f2a35d

File tree

1 file changed

+23
-16
lines changed

1 file changed

+23
-16
lines changed

drivers/devfreq/tegra30-devfreq.c

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,21 @@ static int tegra_actmon_start(struct tegra_devfreq *tegra)
514514
actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1,
515515
ACTMON_GLB_PERIOD_CTRL);
516516

517+
/*
518+
* CLK notifications are needed in order to reconfigure the upper
519+
* consecutive watermark in accordance to the actual clock rate
520+
* to avoid unnecessary upper interrupts.
521+
*/
522+
err = clk_notifier_register(tegra->emc_clock,
523+
&tegra->clk_rate_change_nb);
524+
if (err) {
525+
dev_err(tegra->devfreq->dev.parent,
526+
"Failed to register rate change notifier\n");
527+
return err;
528+
}
529+
530+
tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ;
531+
517532
for (i = 0; i < ARRAY_SIZE(tegra->devices); i++)
518533
tegra_actmon_configure_device(tegra, &tegra->devices[i]);
519534

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

557+
clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb);
558+
542559
return err;
543560
}
544561

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

554571
tegra_actmon_stop_devices(tegra);
572+
573+
clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb);
555574
}
556575

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

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

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

797815
platform_set_drvdata(pdev, tegra);
798816

817+
tegra->clk_rate_change_nb.notifier_call = tegra_actmon_clk_notify_cb;
799818
tegra->cpu_rate_change_nb.notifier_call = tegra_actmon_cpu_notify_cb;
800819

801820
INIT_DELAYED_WORK(&tegra->cpufreq_update_work,
802821
tegra_actmon_delayed_update);
803822

804-
tegra->clk_rate_change_nb.notifier_call = tegra_actmon_clk_notify_cb;
805-
err = clk_notifier_register(tegra->emc_clock,
806-
&tegra->clk_rate_change_nb);
807-
if (err) {
808-
dev_err(&pdev->dev,
809-
"Failed to register rate change notifier\n");
810-
goto remove_opps;
811-
}
812-
813823
err = devfreq_add_governor(&tegra_devfreq_governor);
814824
if (err) {
815825
dev_err(&pdev->dev, "Failed to add governor: %d\n", err);
816-
goto unreg_notifier;
826+
goto remove_opps;
817827
}
818828

819-
tegra_devfreq_profile.initial_freq = tegra->cur_freq;
829+
tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock);
830+
tegra_devfreq_profile.initial_freq /= KHZ;
820831

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

833-
unreg_notifier:
834-
clk_notifier_unregister(tegra->emc_clock, &tegra->clk_rate_change_nb);
835-
836844
remove_opps:
837845
dev_pm_opp_remove_all_dynamic(&pdev->dev);
838846

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

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

855862
reset_control_reset(tegra->reset);

0 commit comments

Comments
 (0)