diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_drv.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 16884db272de..28034c21f6bc 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -6,6 +6,7 @@ */ #include <linux/dma-mapping.h> +#include <linux/fault-inject.h> #include <linux/kthread.h> #include <linux/sched/mm.h> #include <linux/uaccess.h> @@ -78,6 +79,11 @@ static bool modeset = true; MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)"); module_param(modeset, bool, 0600); +#ifdef CONFIG_FAULT_INJECTION +DECLARE_FAULT_ATTR(fail_gem_alloc); +DECLARE_FAULT_ATTR(fail_gem_iova); +#endif + static irqreturn_t msm_irq(int irq, void *arg) { struct drm_device *dev = arg; @@ -355,7 +361,7 @@ static int msm_init_vram(struct drm_device *dev) DRM_INFO("using VRAM carveout: %lx@%pa\n", size, &r.start); /* if we have no IOMMU, then we need to use carveout allocator. - * Grab the entire CMA chunk carved out in early startup in + * Grab the entire DMA chunk carved out in early startup in * mach-msm: */ } else if (!msm_use_mmu(dev)) { @@ -418,14 +424,18 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) INIT_LIST_HEAD(&priv->objects); mutex_init(&priv->obj_lock); - INIT_LIST_HEAD(&priv->inactive_willneed); - INIT_LIST_HEAD(&priv->inactive_dontneed); - INIT_LIST_HEAD(&priv->inactive_unpinned); - mutex_init(&priv->mm_lock); + /* + * Initialize the LRUs: + */ + mutex_init(&priv->lru.lock); + drm_gem_lru_init(&priv->lru.unbacked, &priv->lru.lock); + drm_gem_lru_init(&priv->lru.pinned, &priv->lru.lock); + drm_gem_lru_init(&priv->lru.willneed, &priv->lru.lock); + drm_gem_lru_init(&priv->lru.dontneed, &priv->lru.lock); /* Teach lockdep about lock ordering wrt. shrinker: */ fs_reclaim_acquire(GFP_KERNEL); - might_lock(&priv->mm_lock); + might_lock(&priv->lru.lock); fs_reclaim_release(GFP_KERNEL); drm_mode_config_init(ddev); @@ -699,6 +709,9 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data, flags |= MSM_BO_WC; } + if (should_fail(&fail_gem_alloc, args->size)) + return -ENOMEM; + return msm_gem_new_handle(dev, file, args->size, args->flags, &args->handle, NULL); } @@ -760,6 +773,9 @@ static int msm_ioctl_gem_info_iova(struct drm_device *dev, if (!priv->gpu) return -EINVAL; + if (should_fail(&fail_gem_iova, obj->size)) + return -ENOMEM; + /* * Don't pin the memory here - just get an address so that userspace can * be productive @@ -781,6 +797,9 @@ static int msm_ioctl_gem_info_set_iova(struct drm_device *dev, if (priv->gpu->aspace == ctx->aspace) return -EOPNOTSUPP; + if (should_fail(&fail_gem_iova, obj->size)) + return -ENOMEM; + return msm_gem_set_iova(obj, ctx->aspace, iova); } @@ -885,13 +904,13 @@ static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id, * retired, so if the fence is not found it means there is nothing * to wait for */ - ret = mutex_lock_interruptible(&queue->lock); + ret = mutex_lock_interruptible(&queue->idr_lock); if (ret) return ret; fence = idr_find(&queue->fence_idr, fence_id); if (fence) fence = dma_fence_get_rcu(fence); - mutex_unlock(&queue->lock); + mutex_unlock(&queue->idr_lock); if (!fence) return 0; @@ -1244,10 +1263,15 @@ void msm_drv_shutdown(struct platform_device *pdev) struct msm_drm_private *priv = platform_get_drvdata(pdev); struct drm_device *drm = priv ? priv->dev : NULL; - if (!priv || !priv->kms) - return; - - drm_atomic_helper_shutdown(drm); + /* + * 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 (drm && drm->registered) + drm_atomic_helper_shutdown(drm); } static struct platform_driver msm_platform_driver = { |