1,introduce a member field guilty for amdgpu_ctx
2,free ctx if found it guilty in amdgpu_ctx_get,
3,change interface of amdgpu_ctx_get :
  return -ENODEV if an alive ctx is detected guilty
  return -EINVAL if ctx hanler invalid
  the amdgpu_ctx* will be hold in the @out parm

this way we can let UMD differentiate a guilty ctx or a wrong
ctx handler.

Change-Id: Ib9cd3230e982b72ceb3b7b2fb14e48c32f63493f
Signed-off-by: Monk Liu <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h     |  3 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c  | 24 +++++++++++-------------
 drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 30 ++++++++++++++++++++++++------
 3 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 8e031d6..6312cc5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -793,6 +793,7 @@ struct amdgpu_ctx {
        struct fence            **fences;
        struct amdgpu_ctx_ring  rings[AMDGPU_MAX_RINGS];
        bool preamble_presented;
+       bool guilty; /* if this context is considered guilty so will be removed 
 */
 };
 
 struct amdgpu_ctx_mgr {
@@ -802,7 +803,7 @@ struct amdgpu_ctx_mgr {
        struct idr              ctx_handles;
 };
 
-struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id);
+int amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id, struct amdgpu_ctx 
**out);
 int amdgpu_ctx_put(struct amdgpu_ctx *ctx);
 struct amdgpu_ctx *amdgpu_ctx_kref_get(struct amdgpu_ctx *ctx);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 267fb65..baa90dd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -154,11 +154,9 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void 
*data)
        if (!chunk_array)
                return -ENOMEM;
 
-       p->ctx = amdgpu_ctx_get(fpriv, cs->in.ctx_id);
-       if (!p->ctx) {
-               ret = -EINVAL;
+       ret = amdgpu_ctx_get(fpriv, cs->in.ctx_id, &p->ctx);
+       if (ret)
                goto free_chunk;
-       }
 
        /* get chunks */
        chunk_array_user = (uint64_t __user *)(uintptr_t)(cs->in.chunks);
@@ -1026,9 +1024,9 @@ static int amdgpu_cs_dependencies(struct amdgpu_device 
*adev,
                        if (r)
                                return r;
 
-                       ctx = amdgpu_ctx_get(fpriv, deps[j].ctx_id);
-                       if (ctx == NULL)
-                               return -EINVAL;
+                       r = amdgpu_ctx_get(fpriv, deps[j].ctx_id, &ctx);
+                       if (r)
+                               return r;
 
                        fence = amdgpu_ctx_get_fence(ctx, ring,
                                                     deps[j].handle);
@@ -1164,9 +1162,9 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void 
*data,
        if (r)
                return r;
 
-       ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id);
-       if (ctx == NULL)
-               return -EINVAL;
+       r = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id, &ctx);
+       if (r)
+               return r;
 
        fence = amdgpu_ctx_get_fence(ctx, ring, wait->in.handle);
        if (IS_ERR(fence))
@@ -1208,9 +1206,9 @@ static struct fence *amdgpu_cs_get_fence(struct 
amdgpu_device *adev,
        if (r)
                return ERR_PTR(r);
 
-       ctx = amdgpu_ctx_get(filp->driver_priv, user->ctx_id);
-       if (ctx == NULL)
-               return ERR_PTR(-EINVAL);
+       r = amdgpu_ctx_get(filp->driver_priv, user->ctx_id, &ctx);
+       if (r)
+               return r;
 
        fence = amdgpu_ctx_get_fence(ctx, ring, user->seq_no);
        amdgpu_ctx_put(ctx);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index 81438af..3947f63 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -146,6 +146,9 @@ static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv, 
uint32_t id)
        mutex_lock(&mgr->lock);
        ctx = idr_find(&mgr->ctx_handles, id);
        if (ctx) {
+               if (ctx->guilty)
+                       DRM_ERROR("Guilty context:%u detected! ID removed\n", 
id);
+
                idr_remove(&mgr->ctx_handles, id);
                kref_put(&ctx->refcount, amdgpu_ctx_do_release);
                mutex_unlock(&mgr->lock);
@@ -222,22 +225,37 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
        return r;
 }
 
-struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id)
+int amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id, struct amdgpu_ctx 
**out)
 {
        struct amdgpu_ctx *ctx;
        struct amdgpu_ctx_mgr *mgr;
+       int r = -EINVAL;
 
-       if (!fpriv)
-               return NULL;
+       if (!fpriv || !out)
+               return r;
 
        mgr = &fpriv->ctx_mgr;
 
        mutex_lock(&mgr->lock);
        ctx = idr_find(&mgr->ctx_handles, id);
-       if (ctx)
-               kref_get(&ctx->refcount);
+       if (ctx) {
+               if (!ctx->guilty) {
+                       kref_get(&ctx->refcount);
+                       *out = ctx;
+                       r = 0;
+               } else {
+                       DRM_ERROR("Guilty context:%u detected! handler 
removed\n", id);
+                       /* if a guilty context is alive but used by upper 
client, we distory it
+                        * manually and return NULL, thus libdrm_amdgpu should 
re-create one.
+                        */
+                       idr_remove(&mgr->ctx_handles, id);
+                       kref_put(&ctx->refcount, amdgpu_ctx_do_release);
+                       r = -ENODEV;
+               }
+       }
+
        mutex_unlock(&mgr->lock);
-       return ctx;
+       return r;
 }
 
 int amdgpu_ctx_put(struct amdgpu_ctx *ctx)
-- 
2.7.4

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to