Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab3dd30d authored by Lloyd Atkinson's avatar Lloyd Atkinson Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm: fix crashes on probe failure



Fix issues that occur on the probe failure path. First, remove
an extraneous call to destroy the power handle client. Second,
upstream moved the location of the drm_dev_register call to be
last in the init sequence, as intended by that API. In failure
path we need to make sure to only call drm_dev_unregister if the
driver was previously registered. Moving the drm_drv_register
also requires changing sde_connector to avoid registering the
connector, which tries to create sysfs nodes, before the
drm_drv_regiter has created the overall sysfs root for the
device.

Change-Id: I18caae1d2b2fa2086d5b86676a250b2b06044081
Signed-off-by: default avatarLloyd Atkinson <latkinso@codeaurora.org>
parent 943c6703
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -258,7 +258,10 @@ static int msm_drm_uninit(struct device *dev)
	drm_mode_config_cleanup(ddev);
	drm_vblank_cleanup(ddev);

	if (priv->registered) {
		drm_dev_unregister(ddev);
		priv->registered = false;
	}

#ifdef CONFIG_DRM_FBDEV_EMULATION
	if (fbdev && priv->fbdev)
@@ -298,8 +301,6 @@ static int msm_drm_uninit(struct device *dev)

	component_unbind_all(dev, ddev);

	sde_power_client_destroy(&priv->phandle, priv->pclient);

	sde_power_resource_deinit(pdev, &priv->phandle);

	msm_mdss_destroy(ddev);
@@ -457,10 +458,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
	platform_set_drvdata(pdev, ddev);
	ddev->platformdev = pdev;

	ret = drm_dev_register(ddev, 0);
	if (ret)
		goto fail;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		ret = -ENOMEM;
@@ -592,6 +589,10 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
		}
	}

	ret = drm_dev_register(ddev, 0);
	if (ret)
		goto fail;
	priv->registered = true;

	drm_mode_config_reset(ddev);

+3 −0
Original line number Diff line number Diff line
@@ -346,6 +346,9 @@ struct msm_drm_private {

	/* list of clients waiting for events */
	struct list_head client_event_list;

	/* whether registered and drm_dev_unregister should be called */
	bool registered;
};

struct msm_format {
+5 −13
Original line number Diff line number Diff line
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -526,23 +526,17 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
		goto error_cleanup_conn;
	}

	rc = drm_connector_register(&c_conn->base);
	if (rc) {
		SDE_ERROR("failed to register drm connector, %d\n", rc);
		goto error_cleanup_fence;
	}

	rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
	if (rc) {
		SDE_ERROR("failed to attach encoder to connector, %d\n", rc);
		goto error_unregister_conn;
		goto error_cleanup_fence;
	}

	if (c_conn->ops.set_backlight) {
		rc = sde_backlight_setup(&c_conn->base);
		if (rc) {
			pr_err("failed to setup backlight, rc=%d\n", rc);
			goto error_unregister_conn;
			goto error_cleanup_fence;
		}
	}

@@ -557,7 +551,7 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
		if (!info) {
			SDE_ERROR("failed to allocate info buffer\n");
			rc = -ENOMEM;
			goto error_unregister_conn;
			goto error_cleanup_fence;
		}

		sde_kms_info_reset(info);
@@ -565,7 +559,7 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
		if (rc) {
			SDE_ERROR("post-init failed, %d\n", rc);
			kfree(info);
			goto error_unregister_conn;
			goto error_cleanup_fence;
		}

		msm_property_install_blob(&c_conn->property_info,
@@ -611,8 +605,6 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
	if (c_conn->blob_caps)
		drm_property_unreference_blob(c_conn->blob_caps);
	msm_property_destroy(&c_conn->property_info);
error_unregister_conn:
	drm_connector_unregister(&c_conn->base);
error_cleanup_fence:
	sde_fence_deinit(&c_conn->retire_fence);
error_cleanup_conn: