From ada9566114097cebd9471fdee421e7e3f2931041 Mon Sep 17 00:00:00 2001 From: "Hongbo.He" Date: Tue, 6 Dec 2016 16:23:39 +0800 Subject: [PATCH 0783/4131] Revert "drm/amdgpu: "revert fix exclusive mode game texture blank(v2)"" This reverts commit 3bf3029fd2416d63d5439fde2412e76ac77d081f. Change-Id: I10ce2f9a2d3716d3b0e0eced8e7c9a6b32411ba8 Conflicts: drivers/gpu/drm/amd/amdgpu/amdgpu.h drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 8 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 7 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c | 192 ++++++++++++++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_sem.h | 10 +- 5 files changed, 164 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 6cf1620..9db84c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -59,6 +59,7 @@ #include "amdgpu_sync.h" #include "amdgpu_ring.h" #include "amdgpu_vm.h" +#include "amdgpu_sem.h" #include "amd_powerplay.h" #include "amdgpu_dpm.h" #include "amdgpu_acp.h" @@ -757,6 +758,8 @@ struct amdgpu_fpriv { struct mutex bo_list_lock; struct idr bo_list_handles; struct amdgpu_ctx_mgr ctx_mgr; + spinlock_t sem_handles_lock; + struct idr sem_handles; u32 vram_lost_counter; }; @@ -1327,6 +1330,8 @@ int amdgpu_sem_ioctl(struct drm_device *dev, void *data, int amdgpu_sem_add_cs(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, struct amdgpu_sync *sync); +void amdgpu_sem_destroy(struct amdgpu_fpriv *fpriv, u32 handle); + int amdgpu_gem_dgma_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index cd84bd0..b502338 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -131,6 +131,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, unsigned i; int r = 0; bool need_pipe_sync = false; + unsigned extra_nop = 0; if (num_ibs == 0) return -EINVAL; @@ -157,6 +158,11 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, alloc_size = ring->funcs->emit_frame_size + num_ibs * ring->funcs->emit_ib_size; + if (job && !job->vm_needs_flush && ring->funcs->type == AMDGPU_RING_TYPE_GFX) { + extra_nop = 128; + alloc_size += extra_nop; + } + r = amdgpu_ring_alloc(ring, alloc_size); if (r) { dev_err(adev->dev, "scheduling IB failed (%d).\n", r); @@ -174,6 +180,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, ring->funcs->insert_start(ring); if (job) { + amdgpu_ring_insert_nop(ring, extra_nop); /* prevent CE go too fast than DE */ + r = amdgpu_vm_flush(ring, job, need_pipe_sync); if (r) { amdgpu_ring_undo(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index a5507b5..2e32262 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -877,6 +877,8 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) mutex_init(&fpriv->bo_list_lock); idr_init(&fpriv->bo_list_handles); + spin_lock_init(&fpriv->sem_handles_lock); + idr_init(&fpriv->sem_handles); amdgpu_ctx_mgr_init(&fpriv->ctx_mgr); @@ -904,6 +906,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_bo_list *list; + struct amdgpu_sem *sem; int handle; if (!fpriv) @@ -936,6 +939,10 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, idr_destroy(&fpriv->bo_list_handles); mutex_destroy(&fpriv->bo_list_lock); + idr_for_each_entry(&fpriv->sem_handles, sem, handle) + amdgpu_sem_destroy(fpriv, handle); + idr_destroy(&fpriv->sem_handles); + kfree(fpriv); file_priv->driver_priv = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c index 9fae1ef..d26b23f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c @@ -40,31 +40,17 @@ static int amdgpu_sem_cring_add(struct amdgpu_fpriv *fpriv, struct drm_amdgpu_sem_in *in, struct amdgpu_sem *sem); -static const struct file_operations amdgpu_sem_fops; - -static struct amdgpu_sem *amdgpu_sem_alloc(struct dma_fence *fence) +static void amdgpu_sem_core_free(struct kref *kref) { - struct amdgpu_sem *sem; - - sem = kzalloc(sizeof(struct amdgpu_sem), GFP_KERNEL); - if (!sem) - return NULL; + struct amdgpu_sem_core *core = container_of( + kref, struct amdgpu_sem_core, kref); - sem->file = anon_inode_getfile("sem_file", - &amdgpu_sem_fops, - sem, 0); - if (IS_ERR(sem->file)) - goto err; + if (core->file) + fput(core->file); - kref_init(&sem->kref); - INIT_LIST_HEAD(&sem->list); - /* fence should be get before passing here */ - sem->fence = fence; - - return sem; -err: - kfree(sem); - return NULL; + dma_fence_put(core->fence); + mutex_destroy(&core->lock); + kfree(core); } static void amdgpu_sem_free(struct kref *kref) @@ -72,15 +58,28 @@ static void amdgpu_sem_free(struct kref *kref) struct amdgpu_sem *sem = container_of( kref, struct amdgpu_sem, kref); - dma_fence_put(sem->fence); + list_del(&sem->list); + kref_put(&sem->base->kref, amdgpu_sem_core_free); kfree(sem); } +static inline void amdgpu_sem_get(struct amdgpu_sem *sem) +{ + if (sem) + kref_get(&sem->kref); +} + +static inline void amdgpu_sem_put(struct amdgpu_sem *sem) +{ + if (sem) + kref_put(&sem->kref, amdgpu_sem_free); +} + static int amdgpu_sem_release(struct inode *inode, struct file *file) { struct amdgpu_sem *sem = file->private_data; - kref_put(&sem->kref, amdgpu_sem_free); + amdgpu_sem_put(sem); return 0; } @@ -102,49 +101,128 @@ static const struct file_operations amdgpu_sem_fops = { .compat_ioctl = amdgpu_sem_file_ioctl, }; -static int amdgpu_sem_create(void) + +static inline struct amdgpu_sem *amdgpu_sem_lookup(struct amdgpu_fpriv *fpriv, u32 handle) { - return get_unused_fd_flags(O_CLOEXEC); + struct amdgpu_sem *sem; + + spin_lock(&fpriv->sem_handles_lock); + + /* Check if we currently have a reference on the object */ + sem = idr_find(&fpriv->sem_handles, handle); + amdgpu_sem_get(sem); + + spin_unlock(&fpriv->sem_handles_lock); + + return sem; } -static int amdgpu_sem_signal(int fd, struct dma_fence *fence) +static struct amdgpu_sem_core *amdgpu_sem_core_alloc(void) +{ + struct amdgpu_sem_core *core; + + core = kzalloc(sizeof(*core), GFP_KERNEL); + if (!core) + return NULL; + + kref_init(&core->kref); + mutex_init(&core->lock); + return core; +} + +static struct amdgpu_sem *amdgpu_sem_alloc(void) { struct amdgpu_sem *sem; - sem = amdgpu_sem_alloc(fence); + sem = kzalloc(sizeof(*sem), GFP_KERNEL); if (!sem) + return NULL; + + kref_init(&sem->kref); + INIT_LIST_HEAD(&sem->list); + + return sem; +} + +static int amdgpu_sem_create(struct amdgpu_fpriv *fpriv, u32 *handle) +{ + struct amdgpu_sem *sem; + struct amdgpu_sem_core *core; + int ret; + + sem = amdgpu_sem_alloc(); + core = amdgpu_sem_core_alloc(); + if (!sem || !core) { + kfree(sem); + kfree(core); return -ENOMEM; - fd_install(fd, sem->file); + } + + sem->base = core; + + idr_preload(GFP_KERNEL); + spin_lock(&fpriv->sem_handles_lock); + + ret = idr_alloc(&fpriv->sem_handles, sem, 1, 0, GFP_NOWAIT); + + spin_unlock(&fpriv->sem_handles_lock); + idr_preload_end(); + + if (ret < 0) + return ret; + + *handle = ret; + return 0; +} + +static int amdgpu_sem_signal(struct amdgpu_fpriv *fpriv, + u32 handle, struct dma_fence *fence) +{ + struct amdgpu_sem *sem; + struct amdgpu_sem_core *core; + + sem = amdgpu_sem_lookup(fpriv, handle); + if (!sem) + return -EINVAL; + + core = sem->base; + mutex_lock(&core->lock); + dma_fence_put(core->fence); + core->fence = dma_fence_get(fence); + mutex_unlock(&core->lock); + amdgpu_sem_put(sem); return 0; } -static int amdgpu_sem_wait(int fd, struct amdgpu_fpriv *fpriv, +static int amdgpu_sem_wait(struct amdgpu_fpriv *fpriv, struct drm_amdgpu_sem_in *in) { - struct file *file = fget(fd); struct amdgpu_sem *sem; - int r; + int ret; - if (!file) + sem = amdgpu_sem_lookup(fpriv, in->handle); + if (!sem) return -EINVAL; - sem = file->private_data; - if (!sem) { - r = -EINVAL; - goto err; - } - r = amdgpu_sem_cring_add(fpriv, in, sem); -err: - fput(file); - return r; + ret = amdgpu_sem_cring_add(fpriv, in, sem); + amdgpu_sem_put(sem); + + return ret; } -static void amdgpu_sem_destroy(void) +void amdgpu_sem_destroy(struct amdgpu_fpriv *fpriv, u32 handle) { - /* userspace should close fd when they try to destroy sem, - * closing fd will free semaphore object. - */ + struct amdgpu_sem *sem = amdgpu_sem_lookup(fpriv, handle); + if (!sem) + return; + + spin_lock(&fpriv->sem_handles_lock); + idr_remove(&fpriv->sem_handles, handle); + spin_unlock(&fpriv->sem_handles_lock); + + kref_put(&sem->kref, amdgpu_sem_free); + kref_put(&sem->kref, amdgpu_sem_free); } static struct dma_fence *amdgpu_sem_get_fence(struct amdgpu_fpriv *fpriv, @@ -219,12 +297,14 @@ int amdgpu_sem_add_cs(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, mutex_lock(&ctx->rings[ring->idx].sem_lock); list_for_each_entry_safe(sem, tmp, &ctx->rings[ring->idx].sem_list, list) { - r = amdgpu_sync_fence(ctx->adev, sync, sem->fence); - dma_fence_put(sem->fence); + r = amdgpu_sync_fence(ctx->adev, sync, sem->base->fence); if (r) goto err; - list_del(&sem->list); - kfree(sem); + mutex_lock(&sem->base->lock); + dma_fence_put(sem->base->fence); + sem->base->fence = NULL; + mutex_unlock(&sem->base->lock); + list_del_init(&sem->list); } err: mutex_unlock(&ctx->rings[ring->idx].sem_lock); @@ -238,14 +318,13 @@ int amdgpu_sem_ioctl(struct drm_device *dev, void *data, struct amdgpu_fpriv *fpriv = filp->driver_priv; struct dma_fence *fence; int r = 0; - int fd = args->in.fd; switch (args->in.op) { case AMDGPU_SEM_OP_CREATE_SEM: - args->out.fd = amdgpu_sem_create(); + r = amdgpu_sem_create(fpriv, &args->out.handle); break; case AMDGPU_SEM_OP_WAIT_SEM: - r = amdgpu_sem_wait(fd, fpriv, &args->in); + r = amdgpu_sem_wait(fpriv, &args->in); break; case AMDGPU_SEM_OP_SIGNAL_SEM: fence = amdgpu_sem_get_fence(fpriv, &args->in); @@ -253,14 +332,15 @@ int amdgpu_sem_ioctl(struct drm_device *dev, void *data, r = PTR_ERR(fence); return r; } - r = amdgpu_sem_signal(fd, fence); + r = amdgpu_sem_signal(fpriv, args->in.handle, fence); dma_fence_put(fence); break; case AMDGPU_SEM_OP_DESTROY_SEM: - amdgpu_sem_destroy(); + amdgpu_sem_destroy(fpriv, args->in.handle); break; default: - return -EINVAL; + r = -EINVAL; + break; } return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.h index 10ec58e..40854ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.h @@ -34,10 +34,16 @@ #include #include -struct amdgpu_sem { +struct amdgpu_sem_core { struct file *file; struct kref kref; - struct dam_fence *fence; + struct dma_fence *fence; + struct mutex lock; +}; + +struct amdgpu_sem { + struct amdgpu_sem_core *base; + struct kref kref; struct list_head list; }; -- 2.7.4