All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] drm/radeon: make VCE handle check more strict
@ 2015-05-07 13:19 Christian König
  2015-05-07 13:19 ` [PATCH 2/4] drm/radeon: make UVD handle checking " Christian König
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Christian König @ 2015-05-07 13:19 UTC (permalink / raw)
  To: alexdeucher; +Cc: dri-devel

From: Christian König <christian.koenig@amd.com>

Invalid handles can crash the hw.

Signed-off-by: Christian König <christian.koenig@amd.com>
CC: stable@vger.kernel.org
---
 drivers/gpu/drm/radeon/radeon_vce.c | 65 +++++++++++++++++++++++++++----------
 1 file changed, 48 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
index 24f849f..0de5711 100644
--- a/drivers/gpu/drm/radeon/radeon_vce.c
+++ b/drivers/gpu/drm/radeon/radeon_vce.c
@@ -493,18 +493,27 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi,
  *
  * @p: parser context
  * @handle: handle to validate
+ * @allocated: allocated a new handle?
  *
  * Validates the handle and return the found session index or -EINVAL
  * we we don't have another free session index.
  */
-int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
+static int radeon_vce_validate_handle(struct radeon_cs_parser *p,
+				      uint32_t handle, bool *allocated)
 {
 	unsigned i;
 
+	*allocated = false;
+
 	/* validate the handle */
 	for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
-		if (atomic_read(&p->rdev->vce.handles[i]) == handle)
+		if (atomic_read(&p->rdev->vce.handles[i]) == handle) {
+			if (p->rdev->vce.filp[i] != p->filp) {
+				DRM_ERROR("VCE handle collision detected!\n");
+				return -EINVAL;
+			}
 			return i;
+		}
 	}
 
 	/* handle not found try to alloc a new one */
@@ -512,6 +521,7 @@ int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
 		if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) {
 			p->rdev->vce.filp[i] = p->filp;
 			p->rdev->vce.img_size[i] = 0;
+			*allocated = true;
 			return i;
 		}
 	}
@@ -529,10 +539,10 @@ int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
 int radeon_vce_cs_parse(struct radeon_cs_parser *p)
 {
 	int session_idx = -1;
-	bool destroyed = false;
+	bool destroyed = false, created = false, allocated = false;
 	uint32_t tmp, handle = 0;
 	uint32_t *size = &tmp;
-	int i, r;
+	int i, r = 0;
 
 	while (p->idx < p->chunk_ib->length_dw) {
 		uint32_t len = radeon_get_ib_value(p, p->idx);
@@ -540,18 +550,21 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
 
 		if ((len < 8) || (len & 3)) {
 			DRM_ERROR("invalid VCE command length (%d)!\n", len);
-                	return -EINVAL;
+			r = -EINVAL;
+			goto out;
 		}
 
 		if (destroyed) {
 			DRM_ERROR("No other command allowed after destroy!\n");
-			return -EINVAL;
+			r = -EINVAL;
+			goto out;
 		}
 
 		switch (cmd) {
 		case 0x00000001: // session
 			handle = radeon_get_ib_value(p, p->idx + 2);
-			session_idx = radeon_vce_validate_handle(p, handle);
+			session_idx = radeon_vce_validate_handle(p, handle,
+								 &allocated);
 			if (session_idx < 0)
 				return session_idx;
 			size = &p->rdev->vce.img_size[session_idx];
@@ -561,6 +574,13 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
 			break;
 
 		case 0x01000001: // create
+			created = true;
+			if (!allocated) {
+				DRM_ERROR("Handle already in use!\n");
+				r = -EINVAL;
+				goto out;
+			}
+
 			*size = radeon_get_ib_value(p, p->idx + 8) *
 				radeon_get_ib_value(p, p->idx + 10) *
 				8 * 3 / 2;
@@ -578,12 +598,12 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
 			r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9,
 						*size);
 			if (r)
-				return r;
+				goto out;
 
 			r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11,
 						*size / 3);
 			if (r)
-				return r;
+				goto out;
 			break;
 
 		case 0x02000001: // destroy
@@ -594,7 +614,7 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
 			r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
 						*size * 2);
 			if (r)
-				return r;
+				goto out;
 			break;
 
 		case 0x05000004: // video bitstream buffer
@@ -602,36 +622,47 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
 			r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
 						tmp);
 			if (r)
-				return r;
+				goto out;
 			break;
 
 		case 0x05000005: // feedback buffer
 			r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
 						4096);
 			if (r)
-				return r;
+				goto out;
 			break;
 
 		default:
 			DRM_ERROR("invalid VCE command (0x%x)!\n", cmd);
-			return -EINVAL;
+			r = -EINVAL;
+			goto out;
 		}
 
 		if (session_idx == -1) {
 			DRM_ERROR("no session command at start of IB\n");
-			return -EINVAL;
+			r = -EINVAL;
+			goto out;
 		}
 
 		p->idx += len / 4;
 	}
 
-	if (destroyed) {
-		/* IB contains a destroy msg, free the handle */
+	if (allocated && !created) {
+		DRM_ERROR("New session without create command!\n");
+		r = -ENOENT;
+	}
+
+out:
+	if ((!r && destroyed) || (r && allocated)) {
+		/*
+		 * IB contains a destroy msg or we have allocated an
+		 * handle and got an error, anyway free the handle
+		 */
 		for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i)
 			atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0);
 	}
 
-	return 0;
+	return r;
 }
 
 /**
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] drm/radeon: make UVD handle checking more strict
  2015-05-07 13:19 [PATCH 1/4] drm/radeon: make VCE handle check more strict Christian König
@ 2015-05-07 13:19 ` Christian König
  2015-05-07 13:19 ` [PATCH 3/4] drm/radeon: more strictly validate the UVD codec Christian König
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Christian König @ 2015-05-07 13:19 UTC (permalink / raw)
  To: alexdeucher; +Cc: dri-devel

From: Christian König <christian.koenig@amd.com>

Invalid messages can crash the hw otherwise.

Signed-off-by: Christian König <christian.koenig@amd.com>
CC: stable@vger.kernel.org
---
 drivers/gpu/drm/radeon/radeon_uvd.c | 72 ++++++++++++++++++++++---------------
 1 file changed, 43 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index c10b2ae..f67a6aa 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -436,50 +436,64 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 		return -EINVAL;
 	}
 
-	if (msg_type == 1) {
+	switch (msg_type) {
+	case 0:
+		/* it's a create msg, calc image size (width * height) */
+		img_size = msg[7] * msg[8];
+		radeon_bo_kunmap(bo);
+
+		/* try to alloc a new handle */
+		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+			if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
+				DRM_ERROR("Handle 0x%x already in use!\n", handle);
+				return -EINVAL;
+			}
+
+			if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
+				p->rdev->uvd.filp[i] = p->filp;
+				p->rdev->uvd.img_size[i] = img_size;
+				return 0;
+			}
+		}
+
+		DRM_ERROR("No more free UVD handles!\n");
+		return -EINVAL;
+
+	case 1:
 		/* it's a decode msg, calc buffer sizes */
 		r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
-		/* calc image size (width * height) */
-		img_size = msg[6] * msg[7];
 		radeon_bo_kunmap(bo);
 		if (r)
 			return r;
 
-	} else if (msg_type == 2) {
+		/* validate the handle */
+		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+			if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
+				if (p->rdev->uvd.filp[i] != p->filp) {
+					DRM_ERROR("UVD handle collision detected!\n");
+					return -EINVAL;
+				}
+				return 0;
+			}
+		}
+
+		DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);
+		return -ENOENT;
+
+	case 2:
 		/* it's a destroy msg, free the handle */
 		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
 			atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
 		radeon_bo_kunmap(bo);
 		return 0;
-	} else {
-		/* it's a create msg, calc image size (width * height) */
-		img_size = msg[7] * msg[8];
-		radeon_bo_kunmap(bo);
 
-		if (msg_type != 0) {
-			DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
-			return -EINVAL;
-		}
-
-		/* it's a create msg, no special handling needed */
-	}
-
-	/* create or decode, validate the handle */
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
-		if (atomic_read(&p->rdev->uvd.handles[i]) == handle)
-			return 0;
-	}
+	default:
 
-	/* handle not found try to alloc a new one */
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
-		if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
-			p->rdev->uvd.filp[i] = p->filp;
-			p->rdev->uvd.img_size[i] = img_size;
-			return 0;
-		}
+		DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
+		return -EINVAL;
 	}
 
-	DRM_ERROR("No more free UVD handles!\n");
+	BUG();
 	return -EINVAL;
 }
 
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] drm/radeon: more strictly validate the UVD codec
  2015-05-07 13:19 [PATCH 1/4] drm/radeon: make VCE handle check more strict Christian König
  2015-05-07 13:19 ` [PATCH 2/4] drm/radeon: make UVD handle checking " Christian König
@ 2015-05-07 13:19 ` Christian König
  2015-05-07 13:19 ` [PATCH 4/4] drm/radeon: stop trying to suspend UVD sessions Christian König
  2015-05-07 16:29 ` [PATCH 1/4] drm/radeon: make VCE handle check more strict Alex Deucher
  3 siblings, 0 replies; 5+ messages in thread
From: Christian König @ 2015-05-07 13:19 UTC (permalink / raw)
  To: alexdeucher; +Cc: dri-devel

From: Christian König <christian.koenig@amd.com>

MPEG 2/4 are only supported since UVD3.

Signed-off-by: Christian König <christian.koenig@amd.com>
CC: stable@vger.kernel.org
---
 drivers/gpu/drm/radeon/radeon_uvd.c | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index f67a6aa..cd63028 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -396,6 +396,29 @@ static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
 	return 0;
 }
 
+static int radeon_uvd_validate_codec(struct radeon_cs_parser *p,
+				     unsigned stream_type)
+{
+	switch (stream_type) {
+	case 0: /* H264 */
+	case 1: /* VC1 */
+		/* always supported */
+		return 0;
+
+	case 3: /* MPEG2 */
+	case 4: /* MPEG4 */
+		/* only since UVD 3 */
+		if (p->rdev->family >= CHIP_PALM)
+			return 0;
+
+		/* fall through */
+	default:
+		DRM_ERROR("UVD codec not supported by hardware %d!\n",
+			  stream_type);
+		return -EINVAL;
+	}
+}
+
 static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 			     unsigned offset, unsigned buf_sizes[])
 {
@@ -440,7 +463,11 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 	case 0:
 		/* it's a create msg, calc image size (width * height) */
 		img_size = msg[7] * msg[8];
+
+		r = radeon_uvd_validate_codec(p, msg[4]);
 		radeon_bo_kunmap(bo);
+		if (r)
+			return r;
 
 		/* try to alloc a new handle */
 		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
@@ -460,8 +487,10 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 		return -EINVAL;
 
 	case 1:
-		/* it's a decode msg, calc buffer sizes */
-		r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
+		/* it's a decode msg, validate codec and calc buffer sizes */
+		r = radeon_uvd_validate_codec(p, msg[4]);
+		if (!r)
+			r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
 		radeon_bo_kunmap(bo);
 		if (r)
 			return r;
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] drm/radeon: stop trying to suspend UVD sessions
  2015-05-07 13:19 [PATCH 1/4] drm/radeon: make VCE handle check more strict Christian König
  2015-05-07 13:19 ` [PATCH 2/4] drm/radeon: make UVD handle checking " Christian König
  2015-05-07 13:19 ` [PATCH 3/4] drm/radeon: more strictly validate the UVD codec Christian König
@ 2015-05-07 13:19 ` Christian König
  2015-05-07 16:29 ` [PATCH 1/4] drm/radeon: make VCE handle check more strict Alex Deucher
  3 siblings, 0 replies; 5+ messages in thread
From: Christian König @ 2015-05-07 13:19 UTC (permalink / raw)
  To: alexdeucher; +Cc: dri-devel

From: Christian König <christian.koenig@amd.com>

Saving the current UVD state on suspend and restoring it on resume
just doesn't work reliable. Just close cleanup all sessions on suspend.

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/radeon/radeon.h     |  1 -
 drivers/gpu/drm/radeon/radeon_uvd.c | 39 ++++++++++++++++++-------------------
 2 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index d2abe48..46eb0fa 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1673,7 +1673,6 @@ struct radeon_uvd {
 	struct radeon_bo	*vcpu_bo;
 	void			*cpu_addr;
 	uint64_t		gpu_addr;
-	void			*saved_bo;
 	atomic_t		handles[RADEON_MAX_UVD_HANDLES];
 	struct drm_file		*filp[RADEON_MAX_UVD_HANDLES];
 	unsigned		img_size[RADEON_MAX_UVD_HANDLES];
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index cd63028..6edcb54 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -204,28 +204,32 @@ void radeon_uvd_fini(struct radeon_device *rdev)
 
 int radeon_uvd_suspend(struct radeon_device *rdev)
 {
-	unsigned size;
-	void *ptr;
-	int i;
+	int i, r;
 
 	if (rdev->uvd.vcpu_bo == NULL)
 		return 0;
 
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
-		if (atomic_read(&rdev->uvd.handles[i]))
-			break;
+	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+		uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
+		if (handle != 0) {
+			struct radeon_fence *fence;
 
-	if (i == RADEON_MAX_UVD_HANDLES)
-		return 0;
+			radeon_uvd_note_usage(rdev);
 
-	size = radeon_bo_size(rdev->uvd.vcpu_bo);
-	size -= rdev->uvd_fw->size;
+			r = radeon_uvd_get_destroy_msg(rdev,
+				R600_RING_TYPE_UVD_INDEX, handle, &fence);
+			if (r) {
+				DRM_ERROR("Error destroying UVD (%d)!\n", r);
+				continue;
+			}
 
-	ptr = rdev->uvd.cpu_addr;
-	ptr += rdev->uvd_fw->size;
+			radeon_fence_wait(fence, false);
+			radeon_fence_unref(&fence);
 
-	rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
-	memcpy(rdev->uvd.saved_bo, ptr, size);
+			rdev->uvd.filp[i] = NULL;
+			atomic_set(&rdev->uvd.handles[i], 0);
+		}
+	}
 
 	return 0;
 }
@@ -246,12 +250,7 @@ int radeon_uvd_resume(struct radeon_device *rdev)
 	ptr = rdev->uvd.cpu_addr;
 	ptr += rdev->uvd_fw->size;
 
-	if (rdev->uvd.saved_bo != NULL) {
-		memcpy(ptr, rdev->uvd.saved_bo, size);
-		kfree(rdev->uvd.saved_bo);
-		rdev->uvd.saved_bo = NULL;
-	} else
-		memset(ptr, 0, size);
+	memset(ptr, 0, size);
 
 	return 0;
 }
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/4] drm/radeon: make VCE handle check more strict
  2015-05-07 13:19 [PATCH 1/4] drm/radeon: make VCE handle check more strict Christian König
                   ` (2 preceding siblings ...)
  2015-05-07 13:19 ` [PATCH 4/4] drm/radeon: stop trying to suspend UVD sessions Christian König
@ 2015-05-07 16:29 ` Alex Deucher
  3 siblings, 0 replies; 5+ messages in thread
From: Alex Deucher @ 2015-05-07 16:29 UTC (permalink / raw)
  To: Christian König; +Cc: Maling list - DRI developers

On Thu, May 7, 2015 at 9:19 AM, Christian König <deathsimple@vodafone.de> wrote:
> From: Christian König <christian.koenig@amd.com>
>
> Invalid handles can crash the hw.
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> CC: stable@vger.kernel.org

Applied the series to my -fixes tree.

Alex

> ---
>  drivers/gpu/drm/radeon/radeon_vce.c | 65 +++++++++++++++++++++++++++----------
>  1 file changed, 48 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
> index 24f849f..0de5711 100644
> --- a/drivers/gpu/drm/radeon/radeon_vce.c
> +++ b/drivers/gpu/drm/radeon/radeon_vce.c
> @@ -493,18 +493,27 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi,
>   *
>   * @p: parser context
>   * @handle: handle to validate
> + * @allocated: allocated a new handle?
>   *
>   * Validates the handle and return the found session index or -EINVAL
>   * we we don't have another free session index.
>   */
> -int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
> +static int radeon_vce_validate_handle(struct radeon_cs_parser *p,
> +                                     uint32_t handle, bool *allocated)
>  {
>         unsigned i;
>
> +       *allocated = false;
> +
>         /* validate the handle */
>         for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
> -               if (atomic_read(&p->rdev->vce.handles[i]) == handle)
> +               if (atomic_read(&p->rdev->vce.handles[i]) == handle) {
> +                       if (p->rdev->vce.filp[i] != p->filp) {
> +                               DRM_ERROR("VCE handle collision detected!\n");
> +                               return -EINVAL;
> +                       }
>                         return i;
> +               }
>         }
>
>         /* handle not found try to alloc a new one */
> @@ -512,6 +521,7 @@ int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
>                 if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) {
>                         p->rdev->vce.filp[i] = p->filp;
>                         p->rdev->vce.img_size[i] = 0;
> +                       *allocated = true;
>                         return i;
>                 }
>         }
> @@ -529,10 +539,10 @@ int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
>  int radeon_vce_cs_parse(struct radeon_cs_parser *p)
>  {
>         int session_idx = -1;
> -       bool destroyed = false;
> +       bool destroyed = false, created = false, allocated = false;
>         uint32_t tmp, handle = 0;
>         uint32_t *size = &tmp;
> -       int i, r;
> +       int i, r = 0;
>
>         while (p->idx < p->chunk_ib->length_dw) {
>                 uint32_t len = radeon_get_ib_value(p, p->idx);
> @@ -540,18 +550,21 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
>
>                 if ((len < 8) || (len & 3)) {
>                         DRM_ERROR("invalid VCE command length (%d)!\n", len);
> -                       return -EINVAL;
> +                       r = -EINVAL;
> +                       goto out;
>                 }
>
>                 if (destroyed) {
>                         DRM_ERROR("No other command allowed after destroy!\n");
> -                       return -EINVAL;
> +                       r = -EINVAL;
> +                       goto out;
>                 }
>
>                 switch (cmd) {
>                 case 0x00000001: // session
>                         handle = radeon_get_ib_value(p, p->idx + 2);
> -                       session_idx = radeon_vce_validate_handle(p, handle);
> +                       session_idx = radeon_vce_validate_handle(p, handle,
> +                                                                &allocated);
>                         if (session_idx < 0)
>                                 return session_idx;
>                         size = &p->rdev->vce.img_size[session_idx];
> @@ -561,6 +574,13 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
>                         break;
>
>                 case 0x01000001: // create
> +                       created = true;
> +                       if (!allocated) {
> +                               DRM_ERROR("Handle already in use!\n");
> +                               r = -EINVAL;
> +                               goto out;
> +                       }
> +
>                         *size = radeon_get_ib_value(p, p->idx + 8) *
>                                 radeon_get_ib_value(p, p->idx + 10) *
>                                 8 * 3 / 2;
> @@ -578,12 +598,12 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
>                         r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9,
>                                                 *size);
>                         if (r)
> -                               return r;
> +                               goto out;
>
>                         r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11,
>                                                 *size / 3);
>                         if (r)
> -                               return r;
> +                               goto out;
>                         break;
>
>                 case 0x02000001: // destroy
> @@ -594,7 +614,7 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
>                         r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
>                                                 *size * 2);
>                         if (r)
> -                               return r;
> +                               goto out;
>                         break;
>
>                 case 0x05000004: // video bitstream buffer
> @@ -602,36 +622,47 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
>                         r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
>                                                 tmp);
>                         if (r)
> -                               return r;
> +                               goto out;
>                         break;
>
>                 case 0x05000005: // feedback buffer
>                         r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
>                                                 4096);
>                         if (r)
> -                               return r;
> +                               goto out;
>                         break;
>
>                 default:
>                         DRM_ERROR("invalid VCE command (0x%x)!\n", cmd);
> -                       return -EINVAL;
> +                       r = -EINVAL;
> +                       goto out;
>                 }
>
>                 if (session_idx == -1) {
>                         DRM_ERROR("no session command at start of IB\n");
> -                       return -EINVAL;
> +                       r = -EINVAL;
> +                       goto out;
>                 }
>
>                 p->idx += len / 4;
>         }
>
> -       if (destroyed) {
> -               /* IB contains a destroy msg, free the handle */
> +       if (allocated && !created) {
> +               DRM_ERROR("New session without create command!\n");
> +               r = -ENOENT;
> +       }
> +
> +out:
> +       if ((!r && destroyed) || (r && allocated)) {
> +               /*
> +                * IB contains a destroy msg or we have allocated an
> +                * handle and got an error, anyway free the handle
> +                */
>                 for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i)
>                         atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0);
>         }
>
> -       return 0;
> +       return r;
>  }
>
>  /**
> --
> 1.9.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-05-07 16:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-07 13:19 [PATCH 1/4] drm/radeon: make VCE handle check more strict Christian König
2015-05-07 13:19 ` [PATCH 2/4] drm/radeon: make UVD handle checking " Christian König
2015-05-07 13:19 ` [PATCH 3/4] drm/radeon: more strictly validate the UVD codec Christian König
2015-05-07 13:19 ` [PATCH 4/4] drm/radeon: stop trying to suspend UVD sessions Christian König
2015-05-07 16:29 ` [PATCH 1/4] drm/radeon: make VCE handle check more strict Alex Deucher

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.