drm/tegra: sor: Initialize runtime PM before use
Commitfd67e9c6ed
("drm/tegra: Do not implement runtime PM") replaced the generic runtime PM usage by a host1x bus-specific implementation in order to work around some assumptions baked into runtime PM that are in conflict with the requirements in the Tegra DRM driver. Unfortunately the new runtime PM callbacks are not setup yet at the time when the SOR driver first needs to resume the device to register the SOR pad clock, and accesses to register will cause the system to hang. Note that this only happens on Tegra124 and Tegra210 because those are the only SoCs where the SOR pad clock is registered from the SOR driver. Later generations use a SOR pad clock provided by the BPMP. Fix this by moving the registration of the SOR pad clock after the host1x client has been registered. That's somewhat suboptimal because this could potentially, though it's very unlikely, cause the Tegra DRM to be probed if the SOR happens to be the last subdevice to register, only to be immediately removed again if the SOR pad output clock fails to register. That's just a minor annoyance, though, and doesn't justify implementing a workaround. Fixes:fd67e9c6ed
("drm/tegra: Do not implement runtime PM") Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
ad2139cb80
commit
c472a0b0a1
@ -3914,37 +3914,6 @@ static int tegra_sor_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, sor);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/*
|
||||
* On Tegra210 and earlier, provide our own implementation for the
|
||||
* pad output clock.
|
||||
*/
|
||||
if (!sor->clk_pad) {
|
||||
char *name;
|
||||
|
||||
name = devm_kasprintf(sor->dev, GFP_KERNEL, "sor%u_pad_clkout",
|
||||
sor->index);
|
||||
if (!name) {
|
||||
err = -ENOMEM;
|
||||
goto rpm_disable;
|
||||
}
|
||||
|
||||
err = host1x_client_resume(&sor->client);
|
||||
if (err < 0) {
|
||||
dev_err(sor->dev, "failed to resume: %d\n", err);
|
||||
goto rpm_disable;
|
||||
}
|
||||
|
||||
sor->clk_pad = tegra_clk_sor_pad_register(sor, name);
|
||||
host1x_client_suspend(&sor->client);
|
||||
}
|
||||
|
||||
if (IS_ERR(sor->clk_pad)) {
|
||||
err = PTR_ERR(sor->clk_pad);
|
||||
dev_err(&pdev->dev, "failed to register SOR pad clock: %d\n",
|
||||
err);
|
||||
goto rpm_disable;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sor->client.list);
|
||||
sor->client.ops = &sor_client_ops;
|
||||
sor->client.dev = &pdev->dev;
|
||||
@ -3956,8 +3925,41 @@ static int tegra_sor_probe(struct platform_device *pdev)
|
||||
goto rpm_disable;
|
||||
}
|
||||
|
||||
/*
|
||||
* On Tegra210 and earlier, provide our own implementation for the
|
||||
* pad output clock.
|
||||
*/
|
||||
if (!sor->clk_pad) {
|
||||
char *name;
|
||||
|
||||
name = devm_kasprintf(sor->dev, GFP_KERNEL, "sor%u_pad_clkout",
|
||||
sor->index);
|
||||
if (!name) {
|
||||
err = -ENOMEM;
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
err = host1x_client_resume(&sor->client);
|
||||
if (err < 0) {
|
||||
dev_err(sor->dev, "failed to resume: %d\n", err);
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
sor->clk_pad = tegra_clk_sor_pad_register(sor, name);
|
||||
host1x_client_suspend(&sor->client);
|
||||
}
|
||||
|
||||
if (IS_ERR(sor->clk_pad)) {
|
||||
err = PTR_ERR(sor->clk_pad);
|
||||
dev_err(sor->dev, "failed to register SOR pad clock: %d\n",
|
||||
err);
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
unregister:
|
||||
host1x_client_unregister(&sor->client);
|
||||
rpm_disable:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
remove:
|
||||
|
Loading…
Reference in New Issue
Block a user