mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
UPSTREAM: drm/tegra: sor: Fix AUX device reference leak
In the case where the AUX provides an I2C-over-AUX DDC channel, a reference is taken on the AUX parent device of the DDC channel rather than the DDC channel like it would be for regular I2C controllers. To make sure the correct reference is dropped, move the unreferencing code into the SOR driver and make sure not to drop the I2C adapter reference in that case. Change-Id: I8821ffa49629f808714dae30463d7bf4a3466415 Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2545951 Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Laxman Dewangan
parent
7cd5671ce4
commit
6e8e2ead9c
@@ -180,13 +180,10 @@ int tegra_output_probe(struct tegra_output *output)
|
|||||||
|
|
||||||
void tegra_output_remove(struct tegra_output *output)
|
void tegra_output_remove(struct tegra_output *output)
|
||||||
{
|
{
|
||||||
int connector_type = output->connector.connector_type;
|
|
||||||
|
|
||||||
if (output->hpd_gpio)
|
if (output->hpd_gpio)
|
||||||
free_irq(output->hpd_irq, output);
|
free_irq(output->hpd_irq, output);
|
||||||
|
|
||||||
if (connector_type != DRM_MODE_CONNECTOR_eDP &&
|
if (output->ddc)
|
||||||
connector_type != DRM_MODE_CONNECTOR_DisplayPort && output->ddc)
|
|
||||||
i2c_put_adapter(output->ddc);
|
i2c_put_adapter(output->ddc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3741,12 +3741,8 @@ static int tegra_sor_probe(struct platform_device *pdev)
|
|||||||
if (!sor->aux)
|
if (!sor->aux)
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
|
|
||||||
if (get_device(sor->aux->dev)) {
|
if (get_device(sor->aux->dev))
|
||||||
if (try_module_get(sor->aux->dev->driver->owner))
|
|
||||||
sor->output.ddc = &sor->aux->ddc;
|
sor->output.ddc = &sor->aux->ddc;
|
||||||
else
|
|
||||||
put_device(sor->aux->dev);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sor->aux) {
|
if (!sor->aux) {
|
||||||
@@ -3774,12 +3770,13 @@ static int tegra_sor_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
err = tegra_sor_parse_dt(sor);
|
err = tegra_sor_parse_dt(sor);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
goto put_aux;
|
||||||
|
|
||||||
err = tegra_output_probe(&sor->output);
|
err = tegra_output_probe(&sor->output);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
return dev_err_probe(&pdev->dev, err,
|
dev_err_probe(&pdev->dev, err, "failed to probe output\n");
|
||||||
"failed to probe output\n");
|
goto put_aux;
|
||||||
|
}
|
||||||
|
|
||||||
if (sor->ops && sor->ops->probe) {
|
if (sor->ops && sor->ops->probe) {
|
||||||
err = sor->ops->probe(sor);
|
err = sor->ops->probe(sor);
|
||||||
@@ -3966,7 +3963,14 @@ uninit:
|
|||||||
host1x_client_exit(&sor->client);
|
host1x_client_exit(&sor->client);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
remove:
|
remove:
|
||||||
|
if (sor->aux)
|
||||||
|
sor->output.ddc = NULL;
|
||||||
|
|
||||||
tegra_output_remove(&sor->output);
|
tegra_output_remove(&sor->output);
|
||||||
|
put_aux:
|
||||||
|
if (sor->aux)
|
||||||
|
put_device(sor->aux->dev);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3984,6 +3988,11 @@ static int tegra_sor_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
|
if (sor->aux) {
|
||||||
|
put_device(sor->aux->dev);
|
||||||
|
sor->output.ddc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tegra_output_remove(&sor->output);
|
tegra_output_remove(&sor->output);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user