diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0153-drm-amdgpu-hybird-add-semaphore-object-support.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0153-drm-amdgpu-hybird-add-semaphore-object-support.patch | 803 |
1 files changed, 803 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0153-drm-amdgpu-hybird-add-semaphore-object-support.patch b/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0153-drm-amdgpu-hybird-add-semaphore-object-support.patch new file mode 100644 index 00000000..aff14a58 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/0153-drm-amdgpu-hybird-add-semaphore-object-support.patch @@ -0,0 +1,803 @@ +From a6b5392c2461a0528b074e490ce964e1e2847e23 Mon Sep 17 00:00:00 2001 +From: Kevin Wang <Kevin1.Wang@amd.com> +Date: Thu, 30 Aug 2018 12:14:28 +0800 +Subject: [PATCH 0153/2940] drm/amdgpu: [hybird] add semaphore object support + +Change-Id: I3acc0a92c9983189fe095272a775c2ebf2b36eac +Signed-off-by: Kevin Wang <Kevin1.Wang@amd.com> +Signed-off-by: Kalyan Alle <kalyan.alle@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 3 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 2 + + drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h | 2 + + drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | 6 + + drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 8 + + drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 8 + + drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c | 462 ++++++++++++++++++++ + drivers/gpu/drm/amd/amdgpu/amdgpu_sem.h | 55 +++ + include/uapi/drm/amdgpu_drm.h | 35 ++ + 11 files changed, 586 insertions(+), 3 deletions(-) + create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c + create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_sem.h + +diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile +index 860cb8731c7c..cf5c7ed1ac37 100644 +--- a/drivers/gpu/drm/amd/amdgpu/Makefile ++++ b/drivers/gpu/drm/amd/amdgpu/Makefile +@@ -51,7 +51,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ + amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ + amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ + amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_atomfirmware.o \ +- amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o ++ amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \ ++ amdgpu_sem.o + + # add asic specific block + amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index debab710f5be..f5fcee141fbb 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -64,6 +64,7 @@ + #include "amdgpu_sync.h" + #include "amdgpu_ring.h" + #include "amdgpu_vm.h" ++#include "amdgpu_sem.h" + #include "amdgpu_dpm.h" + #include "amdgpu_acp.h" + #include "amdgpu_uvd.h" +@@ -482,7 +483,6 @@ struct amdgpu_ib { + }; + + extern const struct drm_sched_backend_ops amdgpu_sched_ops; +- + /* + * file private structure + */ +@@ -494,6 +494,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; + }; + + int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, +@@ -665,6 +667,7 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *fi + int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); + ++ + int amdgpu_display_freesync_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +index 363d2cfcd7e9..9af07d366107 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +@@ -33,6 +33,7 @@ + #include "amdgpu_trace.h" + #include "amdgpu_gmc.h" + #include "amdgpu_gem.h" ++#include "amdgpu_display.h" + + static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, + struct drm_amdgpu_cs_chunk_fence *data, +@@ -1189,7 +1190,7 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, + } + } + +- return 0; ++ return amdgpu_sem_add_cs(p->ctx, p->entity, &p->job->sync); + } + + static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p) +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +index 987b7f256463..2d7e9fa6e82f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +@@ -104,6 +104,8 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, + + entity->sequence = 1; + entity->fences = &ctx->fences[amdgpu_sched_jobs * i]; ++ INIT_LIST_HEAD(&entity->sem_dep_list); ++ mutex_init(&entity->sem_lock); + } + for (i = 1; i < AMDGPU_HW_IP_NUM; ++i) + ctx->entities[i] = ctx->entities[i - 1] + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h +index d67c1d285a4f..f7486ea38286 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h +@@ -33,6 +33,8 @@ struct amdgpu_ctx_entity { + uint64_t sequence; + struct dma_fence **fences; + struct drm_sched_entity entity; ++ struct list_head sem_dep_list; ++ struct mutex sem_lock; + }; + + struct amdgpu_ctx { +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h +index 06b922fe0d42..ba7b9fb53864 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h +@@ -43,5 +43,11 @@ struct drm_framebuffer * + amdgpu_display_user_framebuffer_create(struct drm_device *dev, + struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd); ++int amdgpu_sem_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *filp); + ++int amdgpu_sem_add_cs(struct amdgpu_ctx *ctx, struct drm_sched_entity *entity, ++ struct amdgpu_sync *sync); ++ ++void amdgpu_sem_destroy(struct amdgpu_fpriv *fpriv, u32 handle); + #endif +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +index 47817e00f54f..29ce4264c1ea 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +@@ -133,6 +133,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; +@@ -159,6 +160,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); +@@ -182,6 +188,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 0b4e66c4c362..4b97d47252a2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +@@ -957,6 +957,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); + +@@ -993,6 +995,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; + struct amdgpu_bo *pd; + unsigned int pasid; + int handle; +@@ -1033,6 +1036,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; + +@@ -1163,6 +1170,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { + DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(AMDGPU_FREESYNC, amdgpu_display_freesync_ioctl, DRM_MASTER), + DRM_IOCTL_DEF_DRV(AMDGPU_GEM_DGMA, amdgpu_gem_dgma_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(AMDGPU_SEM, amdgpu_sem_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), + }; + const int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms); + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c +new file mode 100644 +index 000000000000..3d5beb00b0db +--- /dev/null ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.c +@@ -0,0 +1,462 @@ ++/* ++ * Copyright 2016 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: ++ * Chunming Zhou <david1.zhou@amd.com> ++ */ ++#include <linux/file.h> ++#include <linux/fs.h> ++#include <linux/kernel.h> ++#include <linux/poll.h> ++#include <linux/seq_file.h> ++#include <linux/export.h> ++#include <linux/sched.h> ++#include <linux/slab.h> ++#include <linux/uaccess.h> ++#include <linux/anon_inodes.h> ++#include "amdgpu_sem.h" ++#include "amdgpu.h" ++#include <drm/drmP.h> ++#include "amdgpu_display.h" ++ ++#define to_amdgpu_ctx_entity(e) \ ++ container_of((e), struct amdgpu_ctx_entity, entity) ++ ++static int amdgpu_sem_entity_add(struct amdgpu_fpriv *fpriv, ++ struct drm_amdgpu_sem_in *in, ++ struct amdgpu_sem *sem); ++ ++static void amdgpu_sem_core_free(struct kref *kref) ++{ ++ struct amdgpu_sem_core *core = container_of( ++ kref, struct amdgpu_sem_core, kref); ++ ++ dma_fence_put(core->fence); ++ mutex_destroy(&core->lock); ++ kfree(core); ++} ++ ++static void amdgpu_sem_free(struct kref *kref) ++{ ++ struct amdgpu_sem *sem = container_of( ++ kref, struct amdgpu_sem, kref); ++ ++ 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); ++} ++ ++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_core *core = file->private_data; ++ ++ /* set the core->file to null if file got released */ ++ mutex_lock(&core->lock); ++ core->file = NULL; ++ mutex_unlock(&core->lock); ++ ++ kref_put(&core->kref, amdgpu_sem_core_free); ++ return 0; ++} ++ ++static unsigned int amdgpu_sem_poll(struct file *file, poll_table *wait) ++{ ++ return 0; ++} ++ ++static long amdgpu_sem_file_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ return 0; ++} ++ ++static const struct file_operations amdgpu_sem_fops = { ++ .release = amdgpu_sem_release, ++ .poll = amdgpu_sem_poll, ++ .unlocked_ioctl = amdgpu_sem_file_ioctl, ++ .compat_ioctl = amdgpu_sem_file_ioctl, ++}; ++ ++ ++static inline struct amdgpu_sem *amdgpu_sem_lookup(struct amdgpu_fpriv *fpriv, u32 handle) ++{ ++ 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 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 = 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; ++ } ++ ++ 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(struct amdgpu_fpriv *fpriv, ++ struct drm_amdgpu_sem_in *in) ++{ ++ struct amdgpu_sem *sem; ++ int ret; ++ ++ sem = amdgpu_sem_lookup(fpriv, in->handle); ++ if (!sem) ++ return -EINVAL; ++ ++ ret = amdgpu_sem_entity_add(fpriv, in, sem); ++ amdgpu_sem_put(sem); ++ ++ return ret; ++} ++ ++static int amdgpu_sem_import(struct amdgpu_fpriv *fpriv, ++ int fd, u32 *handle) ++{ ++ struct file *file = fget(fd); ++ struct amdgpu_sem *sem; ++ struct amdgpu_sem_core *core; ++ int ret; ++ ++ if (!file) ++ return -EINVAL; ++ ++ core = file->private_data; ++ if (!core) { ++ fput(file); ++ return -EINVAL; ++ } ++ ++ kref_get(&core->kref); ++ sem = amdgpu_sem_alloc(); ++ if (!sem) { ++ ret = -ENOMEM; ++ goto err_sem; ++ } ++ ++ 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) ++ goto err_out; ++ ++ *handle = ret; ++ fput(file); ++ return 0; ++err_sem: ++ kref_put(&core->kref, amdgpu_sem_core_free); ++err_out: ++ amdgpu_sem_put(sem); ++ fput(file); ++ return ret; ++ ++} ++ ++static int amdgpu_sem_export(struct amdgpu_fpriv *fpriv, ++ u32 handle, int *fd) ++{ ++ struct amdgpu_sem *sem; ++ struct amdgpu_sem_core *core; ++ int ret; ++ ++ sem = amdgpu_sem_lookup(fpriv, handle); ++ if (!sem) ++ return -EINVAL; ++ ++ core = sem->base; ++ kref_get(&core->kref); ++ mutex_lock(&core->lock); ++ if (!core->file) { ++ core->file = anon_inode_getfile("sem_file", ++ &amdgpu_sem_fops, ++ core, 0); ++ if (IS_ERR(core->file)) { ++ mutex_unlock(&core->lock); ++ ret = -ENOMEM; ++ goto err_put_sem; ++ } ++ } else { ++ get_file(core->file); ++ } ++ mutex_unlock(&core->lock); ++ ++ ret = get_unused_fd_flags(O_CLOEXEC); ++ if (ret < 0) ++ goto err_put_file; ++ ++ fd_install(ret, core->file); ++ ++ *fd = ret; ++ amdgpu_sem_put(sem); ++ ++ return 0; ++ ++err_put_file: ++ fput(core->file); ++err_put_sem: ++ kref_put(&core->kref, amdgpu_sem_core_free); ++ amdgpu_sem_put(sem); ++ return ret; ++} ++ ++void amdgpu_sem_destroy(struct amdgpu_fpriv *fpriv, u32 handle) ++{ ++ 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, ++ struct drm_amdgpu_sem_in *in) ++{ ++ struct drm_sched_entity *entity; ++ struct amdgpu_ctx *ctx; ++ struct dma_fence *fence; ++ uint32_t ctx_id, ip_type, ip_instance, ring; ++ int r; ++ ++ ctx_id = in->ctx_id; ++ ip_type = in->ip_type; ++ ip_instance = in->ip_instance; ++ ring = in->ring; ++ ctx = amdgpu_ctx_get(fpriv, ctx_id); ++ if (!ctx) ++ return NULL; ++ r = amdgpu_ctx_get_entity(ctx, ip_type, ++ ip_instance, ring, &entity); ++ if (r) { ++ amdgpu_ctx_put(ctx); ++ return NULL; ++ } ++ /* get the last fence of this entity */ ++ fence = amdgpu_ctx_get_fence(ctx, entity, in->seq); ++ amdgpu_ctx_put(ctx); ++ ++ return fence; ++} ++ ++static int amdgpu_sem_entity_add(struct amdgpu_fpriv *fpriv, ++ struct drm_amdgpu_sem_in *in, ++ struct amdgpu_sem *sem) ++{ ++ struct amdgpu_ctx *ctx; ++ struct amdgpu_sem_dep *dep; ++ struct drm_sched_entity *entity; ++ struct amdgpu_ctx_entity *centity; ++ uint32_t ctx_id, ip_type, ip_instance, ring; ++ int r; ++ ++ ctx_id = in->ctx_id; ++ ip_type = in->ip_type; ++ ip_instance = in->ip_instance; ++ ring = in->ring; ++ ctx = amdgpu_ctx_get(fpriv, ctx_id); ++ if (!ctx) ++ return -EINVAL; ++ r = amdgpu_ctx_get_entity(ctx, ip_type, ++ ip_instance, ring, &entity); ++ if (r) ++ goto err; ++ ++ dep = kzalloc(sizeof(*dep), GFP_KERNEL); ++ if (!dep) ++ goto err; ++ ++ INIT_LIST_HEAD(&dep->list); ++ dep->fence = dma_fence_get(sem->base->fence); ++ ++ centity = to_amdgpu_ctx_entity(entity); ++ mutex_lock(¢ity->sem_lock); ++ list_add(&dep->list, ¢ity->sem_dep_list); ++ mutex_unlock(¢ity->sem_lock); ++ ++err: ++ amdgpu_ctx_put(ctx); ++ return r; ++} ++ ++int amdgpu_sem_add_cs(struct amdgpu_ctx *ctx, struct drm_sched_entity *entity, ++ struct amdgpu_sync *sync) ++{ ++ struct amdgpu_sem_dep *dep, *tmp; ++ struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity); ++ int r = 0; ++ ++ if (list_empty(¢ity->sem_dep_list)) ++ return 0; ++ ++ mutex_lock(¢ity->sem_lock); ++ list_for_each_entry_safe(dep, tmp, ¢ity->sem_dep_list, ++ list) { ++ r = amdgpu_sync_fence(ctx->adev, sync, dep->fence, true); ++ if (r) ++ goto err; ++ dma_fence_put(dep->fence); ++ list_del_init(&dep->list); ++ kfree(dep); ++ } ++err: ++ mutex_unlock(¢ity->sem_lock); ++ return r; ++} ++ ++int amdgpu_sem_ioctl(struct drm_device *dev, void *data, ++ struct drm_file *filp) ++{ ++ union drm_amdgpu_sem *args = data; ++ struct amdgpu_fpriv *fpriv = filp->driver_priv; ++ struct dma_fence *fence; ++ int r = 0; ++ ++ switch (args->in.op) { ++ case AMDGPU_SEM_OP_CREATE_SEM: ++ r = amdgpu_sem_create(fpriv, &args->out.handle); ++ break; ++ case AMDGPU_SEM_OP_WAIT_SEM: ++ r = amdgpu_sem_wait(fpriv, &args->in); ++ break; ++ case AMDGPU_SEM_OP_SIGNAL_SEM: ++ fence = amdgpu_sem_get_fence(fpriv, &args->in); ++ if (IS_ERR(fence)) { ++ r = PTR_ERR(fence); ++ return r; ++ } ++ r = amdgpu_sem_signal(fpriv, args->in.handle, fence); ++ dma_fence_put(fence); ++ break; ++ case AMDGPU_SEM_OP_IMPORT_SEM: ++ r = amdgpu_sem_import(fpriv, args->in.handle, &args->out.handle); ++ break; ++ case AMDGPU_SEM_OP_EXPORT_SEM: ++ r = amdgpu_sem_export(fpriv, args->in.handle, &args->out.fd); ++ break; ++ case AMDGPU_SEM_OP_DESTROY_SEM: ++ amdgpu_sem_destroy(fpriv, args->in.handle); ++ break; ++ default: ++ 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 +new file mode 100644 +index 000000000000..08cda204f177 +--- /dev/null ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sem.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2016 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: Chunming Zhou <david1.zhou@amd.com> ++ * ++ */ ++ ++ ++#ifndef _LINUX_AMDGPU_SEM_H ++#define _LINUX_AMDGPU_SEM_H ++ ++#include <linux/types.h> ++#include <linux/kref.h> ++#include <linux/ktime.h> ++#include <linux/list.h> ++#include <linux/spinlock.h> ++ ++struct amdgpu_sem_core { ++ struct file *file; ++ struct kref kref; ++ struct dma_fence *fence; ++ struct mutex lock; ++}; ++ ++struct amdgpu_sem_dep { ++ struct dma_fence *fence; ++ struct list_head list; ++}; ++ ++struct amdgpu_sem { ++ struct amdgpu_sem_core *base; ++ struct kref kref; ++ struct list_head list; ++}; ++ ++void amdgpu_sem_put(struct amdgpu_sem *sem); ++#endif /* _LINUX_AMDGPU_SEM_H */ +diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h +index 72822f593f57..34ebb2b7f72d 100644 +--- a/include/uapi/drm/amdgpu_drm.h ++++ b/include/uapi/drm/amdgpu_drm.h +@@ -58,6 +58,9 @@ extern "C" { + #define DRM_AMDGPU_FREESYNC 0x5d + #define DRM_AMDGPU_GEM_DGMA 0x5c + ++/* hybrid specific ioctls */ ++#define DRM_AMDGPU_SEM 0x5b ++ + #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) + #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) + #define DRM_IOCTL_AMDGPU_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CTX, union drm_amdgpu_ctx) +@@ -101,6 +104,9 @@ extern "C" { + * %AMDGPU_GEM_DOMAIN_OA Ordered append, used by 3D or Compute engines + * for appending data. + */ ++/* hybrid specific ioctls */ ++#define DRM_IOCTL_AMDGPU_SEM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_SEM, union drm_amdgpu_sem) ++ + #define AMDGPU_GEM_DOMAIN_CPU 0x1 + #define AMDGPU_GEM_DOMAIN_GTT 0x2 + #define AMDGPU_GEM_DOMAIN_VRAM 0x4 +@@ -264,6 +270,35 @@ union drm_amdgpu_ctx { + union drm_amdgpu_ctx_out out; + }; + ++/* sem related */ ++#define AMDGPU_SEM_OP_CREATE_SEM 1 ++#define AMDGPU_SEM_OP_WAIT_SEM 2 ++#define AMDGPU_SEM_OP_SIGNAL_SEM 3 ++#define AMDGPU_SEM_OP_DESTROY_SEM 4 ++#define AMDGPU_SEM_OP_IMPORT_SEM 5 ++#define AMDGPU_SEM_OP_EXPORT_SEM 6 ++ ++struct drm_amdgpu_sem_in { ++ /** AMDGPU_SEM_OP_* */ ++ uint32_t op; ++ uint32_t handle; ++ uint32_t ctx_id; ++ uint32_t ip_type; ++ uint32_t ip_instance; ++ uint32_t ring; ++ uint64_t seq; ++}; ++ ++union drm_amdgpu_sem_out { ++ int32_t fd; ++ uint32_t handle; ++}; ++ ++union drm_amdgpu_sem { ++ struct drm_amdgpu_sem_in in; ++ union drm_amdgpu_sem_out out; ++}; ++ + /* vm ioctl */ + #define AMDGPU_VM_OP_RESERVE_VMID 1 + #define AMDGPU_VM_OP_UNRESERVE_VMID 2 +-- +2.17.1 + |