Skip to content

Commit

Permalink
drm/tegra: sor: Fix AUX device reference leak
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
  • Loading branch information
Thierry Reding committed May 27, 2021
1 parent 1d15a10 commit b79b608
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 14 deletions.
5 changes: 1 addition & 4 deletions drivers/gpu/drm/tegra/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,10 @@ int tegra_output_probe(struct tegra_output *output)

void tegra_output_remove(struct tegra_output *output)
{
int connector_type = output->connector.connector_type;

if (output->hpd_gpio)
free_irq(output->hpd_irq, output);

if (connector_type != DRM_MODE_CONNECTOR_eDP &&
connector_type != DRM_MODE_CONNECTOR_DisplayPort && output->ddc)
if (output->ddc)
i2c_put_adapter(output->ddc);
}

Expand Down
29 changes: 19 additions & 10 deletions drivers/gpu/drm/tegra/sor.c
Original file line number Diff line number Diff line change
Expand Up @@ -3745,12 +3745,8 @@ static int tegra_sor_probe(struct platform_device *pdev)
if (!sor->aux)
return -EPROBE_DEFER;

if (get_device(sor->aux->dev)) {
if (try_module_get(sor->aux->dev->driver->owner))
sor->output.ddc = &sor->aux->ddc;
else
put_device(sor->aux->dev);
}
if (get_device(sor->aux->dev))
sor->output.ddc = &sor->aux->ddc;
}

if (!sor->aux) {
Expand Down Expand Up @@ -3778,12 +3774,13 @@ static int tegra_sor_probe(struct platform_device *pdev)

err = tegra_sor_parse_dt(sor);
if (err < 0)
return err;
goto put_aux;

err = tegra_output_probe(&sor->output);
if (err < 0)
return dev_err_probe(&pdev->dev, err,
"failed to probe output\n");
if (err < 0) {
dev_err_probe(&pdev->dev, err, "failed to probe output\n");
goto put_aux;
}

if (sor->ops && sor->ops->probe) {
err = sor->ops->probe(sor);
Expand Down Expand Up @@ -3970,7 +3967,14 @@ static int tegra_sor_probe(struct platform_device *pdev)
host1x_client_exit(&sor->client);
pm_runtime_disable(&pdev->dev);
remove:
if (sor->aux)
sor->output.ddc = NULL;

tegra_output_remove(&sor->output);
put_aux:
if (sor->aux)
put_device(sor->aux->dev);

return err;
}

Expand All @@ -3988,6 +3992,11 @@ static int tegra_sor_remove(struct platform_device *pdev)

pm_runtime_disable(&pdev->dev);

if (sor->aux) {
put_device(sor->aux->dev);
sor->output.ddc = NULL;
}

tegra_output_remove(&sor->output);

return 0;
Expand Down

0 comments on commit b79b608

Please sign in to comment.