Commit b79b6081 authored by Thierry Reding's avatar Thierry Reding
Browse files

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.

Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 1d15a103
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -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);
}

+19 −10
Original line number Diff line number Diff line
@@ -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))
		if (get_device(sor->aux->dev))
			sor->output.ddc = &sor->aux->ddc;
			else
				put_device(sor->aux->dev);
		}
	}

	if (!sor->aux) {
@@ -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);
@@ -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;
}

@@ -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;