summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2019-05-24 16:29:13 -0400
committerSean Paul <seanpaul@chromium.org>2019-06-20 17:00:50 -0400
commit2aa31767259722d159e07240b0b8482a54223c2a (patch)
treea80727101b6b242a079362ea3132e4d4737906b9
parent03436e3ec69c8e026224a5f172e5d0431f722305 (diff)
downloadlinux-2aa31767259722d159e07240b0b8482a54223c2a.tar.bz2
drm/msm: Re-order uninit function to work during probe defer
If bind fails, we can call msm_drm_uninit before kms elements have been created. In this case, drm_atomic_helper_shutdown will fail since there are no drm objects. Only call drm unregistration and shutdown if drm is registered. Also while we're in here move the workqueue destruction to below component_unbind since components could be actively using the wq during uninit or in their unbind routine. Reviewed-by: Rob Clark <robdclark@chromium.org> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20190524202919.179289-1-sean@poorly.run
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 72139ddcede6..229d49740677 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -259,13 +259,24 @@ static int msm_drm_uninit(struct device *dev)
struct msm_mdss *mdss = priv->mdss;
int i;
+ /*
+ * Shutdown the hw if we're far enough along where things might be on.
+ * If we run this too early, we'll end up panicking in any variety of
+ * places. Since we don't register the drm device until late in
+ * msm_drm_init, drm_dev->registered is used as an indicator that the
+ * shutdown will be successful.
+ */
+ if (ddev->registered) {
+ drm_dev_unregister(ddev);
+ drm_atomic_helper_shutdown(ddev);
+ }
+
/* We must cancel and cleanup any pending vblank enable/disable
* work before drm_irq_uninstall() to avoid work re-enabling an
* irq after uninstall has disabled it.
*/
flush_workqueue(priv->wq);
- destroy_workqueue(priv->wq);
/* clean up event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
@@ -279,8 +290,6 @@ static int msm_drm_uninit(struct device *dev)
drm_kms_helper_poll_fini(ddev);
- drm_dev_unregister(ddev);
-
msm_perf_debugfs_cleanup(priv);
msm_rd_debugfs_cleanup(priv);
@@ -288,7 +297,7 @@ static int msm_drm_uninit(struct device *dev)
if (fbdev && priv->fbdev)
msm_fbdev_free(ddev);
#endif
- drm_atomic_helper_shutdown(ddev);
+
drm_mode_config_cleanup(ddev);
pm_runtime_get_sync(dev);
@@ -313,6 +322,7 @@ static int msm_drm_uninit(struct device *dev)
ddev->dev_private = NULL;
drm_dev_put(ddev);
+ destroy_workqueue(priv->wq);
kfree(priv);
return 0;