diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_drv.c')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 139 |
1 files changed, 62 insertions, 77 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 0bdd93648761..c84f0a8b3f2c 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1,24 +1,22 @@ +// 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/dma-mapping.h> #include <linux/kthread.h> +#include <linux/uaccess.h> #include <uapi/linux/sched/types.h> + +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_ioctl.h> +#include <drm/drm_irq.h> +#include <drm/drm_prime.h> #include <drm/drm_of.h> +#include <drm/drm_vblank.h> #include "msm_drv.h" #include "msm_debugfs.h" @@ -28,7 +26,6 @@ #include "msm_kms.h" #include "adreno/adreno_gpu.h" - /* * MSM driver version: * - 1.0.0 - initial interface @@ -39,9 +36,10 @@ * MSM_GEM_INFO ioctl. * - 1.4.0 - softpin, MSM_RELOC_BO_DUMP, and GEM_INFO support to set/get * GEM object's debug name + * - 1.5.0 - Add SUBMITQUERY_QUERY ioctl */ #define MSM_VERSION_MAJOR 1 -#define MSM_VERSION_MINOR 4 +#define MSM_VERSION_MINOR 5 #define MSM_VERSION_PATCHLEVEL 0 static const struct drm_mode_config_funcs mode_config_funcs = { @@ -85,46 +83,6 @@ module_param(modeset, bool, 0600); * Util/helpers: */ -int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk) -{ - struct property *prop; - const char *name; - struct clk_bulk_data *local; - int i = 0, ret, count; - - count = of_property_count_strings(dev->of_node, "clock-names"); - if (count < 1) - return 0; - - local = devm_kcalloc(dev, sizeof(struct clk_bulk_data *), - count, GFP_KERNEL); - if (!local) - return -ENOMEM; - - of_property_for_each_string(dev->of_node, "clock-names", prop, name) { - local[i].id = devm_kstrdup(dev, name, GFP_KERNEL); - if (!local[i].id) { - devm_kfree(dev, local); - return -ENOMEM; - } - - i++; - } - - ret = devm_clk_bulk_get(dev, count, local); - - if (ret) { - for (i = 0; i < count; i++) - devm_kfree(dev, (void *) local[i].id); - devm_kfree(dev, local); - - return ret; - } - - *bulk = local; - return count; -} - struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count, const char *name) { @@ -258,13 +216,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++) { @@ -278,8 +247,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); @@ -287,7 +254,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); @@ -312,6 +279,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; @@ -457,6 +425,9 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) priv->wq = alloc_ordered_workqueue("msm", 0); + INIT_WORK(&priv->free_work, msm_gem_free_work); + init_llist_head(&priv->free_list); + INIT_LIST_HEAD(&priv->inactive_list); drm_mode_config_init(ddev); @@ -502,6 +473,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) ddev->mode_config.normalize_zpos = true; if (kms) { + kms->dev = ddev; ret = kms->funcs->hw_init(kms); if (ret) { DRM_DEV_ERROR(dev, "kms hw init failed: %d\n", ret); @@ -607,6 +579,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); @@ -615,6 +588,7 @@ static int context_init(struct drm_device *dev, struct drm_file *file) msm_submitqueue_init(dev, ctx); + ctx->aspace = priv->gpu ? priv->gpu->aspace : NULL; file->driver_priv = ctx; return 0; @@ -964,6 +938,11 @@ static int msm_ioctl_submitqueue_new(struct drm_device *dev, void *data, args->flags, &args->id); } +static int msm_ioctl_submitqueue_query(struct drm_device *dev, void *data, + struct drm_file *file) +{ + return msm_submitqueue_query(dev, file->driver_priv, data); +} static int msm_ioctl_submitqueue_close(struct drm_device *dev, void *data, struct drm_file *file) @@ -974,16 +953,17 @@ static int msm_ioctl_submitqueue_close(struct drm_device *dev, void *data, } static const struct drm_ioctl_desc msm_ioctls[] = { - DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_INFO, msm_ioctl_gem_info, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_INFO, msm_ioctl_gem_info, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW), }; static const struct vm_operations_struct vm_ops = { @@ -1006,7 +986,6 @@ static const struct file_operations fops = { static struct drm_driver msm_driver = { .driver_features = DRIVER_GEM | - DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC | DRIVER_MODESET, @@ -1019,15 +998,12 @@ static struct drm_driver msm_driver = { .irq_uninstall = msm_irq_uninstall, .enable_vblank = msm_enable_vblank, .disable_vblank = msm_disable_vblank, - .gem_free_object = msm_gem_free_object, + .gem_free_object_unlocked = msm_gem_free_object, .gem_vm_ops = &vm_ops, .dumb_create = msm_gem_dumb_create, .dumb_map_offset = msm_gem_dumb_map_offset, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_res_obj = msm_gem_prime_res_obj, .gem_prime_pin = msm_gem_prime_pin, .gem_prime_unpin = msm_gem_prime_unpin, .gem_prime_get_sg_table = msm_gem_prime_get_sg_table, @@ -1269,7 +1245,8 @@ static int add_gpu_components(struct device *dev, if (!np) return 0; - drm_of_component_match_add(dev, matchptr, compare_of, np); + if (of_device_is_available(np)) + drm_of_component_match_add(dev, matchptr, compare_of, np); of_node_put(np); @@ -1308,16 +1285,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 0; - return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match); +fail: + of_platform_depopulate(&pdev->dev); + return ret; } static int msm_pdev_remove(struct platform_device *pdev) |
