[PATCH 2/5] drm/amdgpu:some modifications in amdgpu_ctx

Monk Liu Monk.Liu at amd.com
Mon May 1 07:22:48 UTC 2017


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 <Monk.Liu at amd.com>
---
 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



More information about the amd-gfx mailing list