[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