diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_drv.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 31deb87abfc6..ab64ab470de7 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/kthread.h> @@ -259,13 +248,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 +279,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 +286,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 +311,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; @@ -611,6 +610,7 @@ static void load_gpu(struct drm_device *dev) static int context_init(struct drm_device *dev, struct drm_file *file) { + struct msm_drm_private *priv = dev->dev_private; struct msm_file_private *ctx; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); @@ -619,6 +619,7 @@ static int context_init(struct drm_device *dev, struct drm_file *file) msm_submitqueue_init(dev, ctx); + ctx->aspace = priv->gpu->aspace; file->driver_priv = ctx; return 0; @@ -1317,16 +1318,24 @@ static int msm_pdev_probe(struct platform_device *pdev) ret = add_gpu_components(&pdev->dev, &match); if (ret) - return ret; + goto fail; /* on all devices that I am aware of, iommu's which can map * any address the cpu can see are used: */ ret = dma_set_mask_and_coherent(&pdev->dev, ~0); if (ret) - return ret; + goto fail; + + ret = component_master_add_with_match(&pdev->dev, &msm_drm_ops, match); + if (ret) + goto fail; - return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match); + return 0; + +fail: + of_platform_depopulate(&pdev->dev); + return ret; } static int msm_pdev_remove(struct platform_device *pdev) |