Commit c472a0b0 authored by Thierry Reding's avatar Thierry Reding

drm/tegra: sor: Initialize runtime PM before use

Commit fd67e9c6 ("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: fd67e9c6 ("drm/tegra: Do not implement runtime PM")
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent ad2139cb
...@@ -3914,6 +3914,17 @@ static int tegra_sor_probe(struct platform_device *pdev) ...@@ -3914,6 +3914,17 @@ static int tegra_sor_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sor); platform_set_drvdata(pdev, sor);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
INIT_LIST_HEAD(&sor->client.list);
sor->client.ops = &sor_client_ops;
sor->client.dev = &pdev->dev;
err = host1x_client_register(&sor->client);
if (err < 0) {
dev_err(&pdev->dev, "failed to register host1x client: %d\n",
err);
goto rpm_disable;
}
/* /*
* On Tegra210 and earlier, provide our own implementation for the * On Tegra210 and earlier, provide our own implementation for the
* pad output clock. * pad output clock.
...@@ -3925,13 +3936,13 @@ static int tegra_sor_probe(struct platform_device *pdev) ...@@ -3925,13 +3936,13 @@ static int tegra_sor_probe(struct platform_device *pdev)
sor->index); sor->index);
if (!name) { if (!name) {
err = -ENOMEM; err = -ENOMEM;
goto rpm_disable; goto unregister;
} }
err = host1x_client_resume(&sor->client); err = host1x_client_resume(&sor->client);
if (err < 0) { if (err < 0) {
dev_err(sor->dev, "failed to resume: %d\n", err); dev_err(sor->dev, "failed to resume: %d\n", err);
goto rpm_disable; goto unregister;
} }
sor->clk_pad = tegra_clk_sor_pad_register(sor, name); sor->clk_pad = tegra_clk_sor_pad_register(sor, name);
...@@ -3940,24 +3951,15 @@ static int tegra_sor_probe(struct platform_device *pdev) ...@@ -3940,24 +3951,15 @@ static int tegra_sor_probe(struct platform_device *pdev)
if (IS_ERR(sor->clk_pad)) { if (IS_ERR(sor->clk_pad)) {
err = PTR_ERR(sor->clk_pad); err = PTR_ERR(sor->clk_pad);
dev_err(&pdev->dev, "failed to register SOR pad clock: %d\n", dev_err(sor->dev, "failed to register SOR pad clock: %d\n",
err); err);
goto rpm_disable; goto unregister;
}
INIT_LIST_HEAD(&sor->client.list);
sor->client.ops = &sor_client_ops;
sor->client.dev = &pdev->dev;
err = host1x_client_register(&sor->client);
if (err < 0) {
dev_err(&pdev->dev, "failed to register host1x client: %d\n",
err);
goto rpm_disable;
} }
return 0; return 0;
unregister:
host1x_client_unregister(&sor->client);
rpm_disable: rpm_disable:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
remove: remove:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment