RE: [PATCH v3 3/3] drm/amdgpu/vcn: Factor out vcn_v{3,4}_0_dec_msg
[AMD Official Use Only - AMD Internal Distribution Only] Reviewed-by: Ruijing Dong Thanks, Ruijing -Original Message- From: Benjamin Cheng Sent: Wednesday, April 8, 2026 8:54 AM To: Deucher, Alexander ; Koenig, Christian ; Liu, Leo ; [email protected] Cc: Wu, David ; Dong, Ruijing ; Cheng, Benjamin Subject: [PATCH v3 3/3] drm/amdgpu/vcn: Factor out vcn_v{3,4}_0_dec_msg Both vcn_v3_0 and vcn_v4_0 use the same interface, so unify the code. Signed-off-by: Benjamin Cheng --- v2: Moved RDECODE_* defines to header in patch #1. drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 100 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 5 ++ drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 102 +--- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 101 +-- 4 files changed, 109 insertions(+), 199 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 03d95dca93d7..10aff7da52b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -1641,3 +1641,103 @@ void amdgpu_vcn_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_prin } } } + +int amdgpu_vcn_dec_msg_limit_sched(struct amdgpu_cs_parser *p, + struct amdgpu_job *job, uint64_t addr, + int (*limit_sched)(struct amdgpu_cs_parser *, + struct amdgpu_job *)) +{ + struct ttm_operation_ctx ctx = { false, false }; + struct amdgpu_device *adev = p->adev; + struct amdgpu_bo_va_mapping *map; + uint32_t *msg, num_buffers, len_dw; + struct amdgpu_bo *bo; + uint64_t start, end; + unsigned int i; + void *ptr; + int r; + + addr &= AMDGPU_GMC_HOLE_MASK; + r = amdgpu_cs_find_mapping(p, addr, &bo, &map); + if (r) { + DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr); + return r; + } + + start = map->start * AMDGPU_GPU_PAGE_SIZE; + end = (map->last + 1) * AMDGPU_GPU_PAGE_SIZE; + if (addr & 0x7) { + DRM_ERROR("VCN messages must be 8 byte aligned!\n"); + return -EINVAL; + } + + if (end - addr < 16) { + DRM_ERROR("VCN messages must be at least 4 DWORDs!\n"); + return -EINVAL; + } + + bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; + amdgpu_bo_placement_from_domain(bo, bo->allowed_domains); + r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); + if (r) { + DRM_ERROR("Failed validating the VCN message BO (%d)!\n", r); + return r; + } + + r = amdgpu_bo_kmap(bo, &ptr); + if (r) { + DRM_ERROR("Failed mapping the VCN message (%d)!\n", r); + return r; + } + + msg = ptr + addr - start; + + if (msg[1] > end - addr) { + DRM_ERROR("VCN message header does not fit in BO!\n"); + r = -EINVAL; + goto out; + } + + if (msg[3] != VCN_DEC_MSG_CREATE) + goto out; + + len_dw = msg[1] / 4; + num_buffers = msg[2]; + + /* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */ + if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) { + DRM_ERROR("VCN message has too many buffers!\n"); + r = -EINVAL; + goto out; + } + + for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) { + uint32_t offset, size, *create; + + if (msg[0] != VCN_DEC_MESSAGE_CREATE) + continue; + + offset = msg[1]; + size = msg[2]; + + if (size < 4 || offset + size > end - addr) { + DRM_ERROR("VCN message buffer exceeds BO bounds!\n"); + r = -EINVAL; + goto out; + } + + create = ptr + addr + offset - start; + + /* H264, HEVC and VP9 can run on any instance */ + if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11) + continue; + + r = limit_sched(p, job); + if (r) + goto out; + } + +out: + amdgpu_bo_kunmap(bo); + return r; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index e72687246235..ad6ca7aa74bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -573,4 +573,9 @@ void amdgpu_vcn_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_prin void amdgpu_vcn_get_profile(struct amdgpu_device *adev); void amdgpu_vcn_put_profile(struct amdgpu_device *adev); +int amdgpu_vcn_dec_msg_limit_sched(struct amdgpu_cs_parser
Re: [PATCH v3 3/3] drm/amdgpu/vcn: Factor out vcn_v{3,4}_0_dec_msg
On 4/8/26 14:54, Benjamin Cheng wrote:
> Both vcn_v3_0 and vcn_v4_0 use the same interface, so unify the code.
>
> Signed-off-by: Benjamin Cheng
Looks good of hand, but somebody from Leo's team should take a closer look.
Acked-by: Christian König
> ---
> v2: Moved RDECODE_* defines to header in patch #1.
>
> drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 100 +++
> drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 5 ++
> drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 102 +---
> drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 101 +--
> 4 files changed, 109 insertions(+), 199 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 03d95dca93d7..10aff7da52b6 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -1641,3 +1641,103 @@ void amdgpu_vcn_print_ip_state(struct amdgpu_ip_block
> *ip_block, struct drm_prin
> }
> }
> }
> +
> +int amdgpu_vcn_dec_msg_limit_sched(struct amdgpu_cs_parser *p,
> +struct amdgpu_job *job, uint64_t addr,
> +int (*limit_sched)(struct amdgpu_cs_parser *,
> + struct amdgpu_job *))
> +{
> + struct ttm_operation_ctx ctx = { false, false };
> + struct amdgpu_device *adev = p->adev;
> + struct amdgpu_bo_va_mapping *map;
> + uint32_t *msg, num_buffers, len_dw;
> + struct amdgpu_bo *bo;
> + uint64_t start, end;
> + unsigned int i;
> + void *ptr;
> + int r;
> +
> + addr &= AMDGPU_GMC_HOLE_MASK;
> + r = amdgpu_cs_find_mapping(p, addr, &bo, &map);
> + if (r) {
> + DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr);
> + return r;
> + }
> +
> + start = map->start * AMDGPU_GPU_PAGE_SIZE;
> + end = (map->last + 1) * AMDGPU_GPU_PAGE_SIZE;
> + if (addr & 0x7) {
> + DRM_ERROR("VCN messages must be 8 byte aligned!\n");
> + return -EINVAL;
> + }
> +
> + if (end - addr < 16) {
> + DRM_ERROR("VCN messages must be at least 4 DWORDs!\n");
> + return -EINVAL;
> + }
> +
> + bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
> + amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
> + r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
> + if (r) {
> + DRM_ERROR("Failed validating the VCN message BO (%d)!\n", r);
> + return r;
> + }
> +
> + r = amdgpu_bo_kmap(bo, &ptr);
> + if (r) {
> + DRM_ERROR("Failed mapping the VCN message (%d)!\n", r);
> + return r;
> + }
> +
> + msg = ptr + addr - start;
> +
> + if (msg[1] > end - addr) {
> + DRM_ERROR("VCN message header does not fit in BO!\n");
> + r = -EINVAL;
> + goto out;
> + }
> +
> + if (msg[3] != VCN_DEC_MSG_CREATE)
> + goto out;
> +
> + len_dw = msg[1] / 4;
> + num_buffers = msg[2];
> +
> + /* Verify that all indices fit within the claimed length. Each index is
> 4 DWORDs */
> + if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
> + DRM_ERROR("VCN message has too many buffers!\n");
> + r = -EINVAL;
> + goto out;
> + }
> +
> + for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
> + uint32_t offset, size, *create;
> +
> + if (msg[0] != VCN_DEC_MESSAGE_CREATE)
> + continue;
> +
> + offset = msg[1];
> + size = msg[2];
> +
> + if (size < 4 || offset + size > end - addr) {
> + DRM_ERROR("VCN message buffer exceeds BO bounds!\n");
> + r = -EINVAL;
> + goto out;
> + }
> +
> + create = ptr + addr + offset - start;
> +
> + /* H264, HEVC and VP9 can run on any instance */
> + if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
> + continue;
> +
> + r = limit_sched(p, job);
> + if (r)
> + goto out;
> + }
> +
> +out:
> + amdgpu_bo_kunmap(bo);
> + return r;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index e72687246235..ad6ca7aa74bd 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -573,4 +573,9 @@ void amdgpu_vcn_print_ip_state(struct amdgpu_ip_block
> *ip_block, struct drm_prin
> void amdgpu_vcn_get_profile(struct amdgpu_device *adev);
> void amdgpu_vcn_put_profile(struct amdgpu_device *adev);
>
> +int amdgpu_vcn_dec_msg_limit_sched(struct amdgpu_cs_parser *p, struct
> amdgpu_job *job,
> +uint64_t addr,
> +int (*limit_sched)(struct amdgp
RE: [PATCH v3 3/3] drm/amdgpu/vcn: Factor out vcn_v{3,4}_0_dec_msg
[AMD Official Use Only - AMD Internal Distribution Only] The series is: Reviewed-by: Leo Liu > -Original Message- > From: Benjamin Cheng > Sent: April 8, 2026 8:54 AM > To: Deucher, Alexander ; Koenig, Christian > ; Liu, Leo ; amd- > [email protected] > Cc: Wu, David ; Dong, Ruijing > ; Cheng, Benjamin > Subject: [PATCH v3 3/3] drm/amdgpu/vcn: Factor out vcn_v{3,4}_0_dec_msg > > Both vcn_v3_0 and vcn_v4_0 use the same interface, so unify the code. > > Signed-off-by: Benjamin Cheng > --- > v2: Moved RDECODE_* defines to header in patch #1. > > drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 100 > +++ > drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 5 ++ > drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 102 +--- > drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 101 +-- > 4 files changed, 109 insertions(+), 199 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c > index 03d95dca93d7..10aff7da52b6 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c > @@ -1641,3 +1641,103 @@ void amdgpu_vcn_print_ip_state(struct > amdgpu_ip_block *ip_block, struct drm_prin > } > } > } > + > +int amdgpu_vcn_dec_msg_limit_sched(struct amdgpu_cs_parser *p, > +struct amdgpu_job *job, uint64_t addr, > +int (*limit_sched)(struct > amdgpu_cs_parser *, > + struct amdgpu_job *)) > +{ > + struct ttm_operation_ctx ctx = { false, false }; > + struct amdgpu_device *adev = p->adev; > + struct amdgpu_bo_va_mapping *map; > + uint32_t *msg, num_buffers, len_dw; > + struct amdgpu_bo *bo; > + uint64_t start, end; > + unsigned int i; > + void *ptr; > + int r; > + > + addr &= AMDGPU_GMC_HOLE_MASK; > + r = amdgpu_cs_find_mapping(p, addr, &bo, &map); > + if (r) { > + DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr); > + return r; > + } > + > + start = map->start * AMDGPU_GPU_PAGE_SIZE; > + end = (map->last + 1) * AMDGPU_GPU_PAGE_SIZE; > + if (addr & 0x7) { > + DRM_ERROR("VCN messages must be 8 byte aligned!\n"); > + return -EINVAL; > + } > + > + if (end - addr < 16) { > + DRM_ERROR("VCN messages must be at least 4 > DWORDs!\n"); > + return -EINVAL; > + } > + > + bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; > + amdgpu_bo_placement_from_domain(bo, bo->allowed_domains); > + r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); > + if (r) { > + DRM_ERROR("Failed validating the VCN message BO > (%d)!\n", r); > + return r; > + } > + > + r = amdgpu_bo_kmap(bo, &ptr); > + if (r) { > + DRM_ERROR("Failed mapping the VCN message (%d)!\n", > r); > + return r; > + } > + > + msg = ptr + addr - start; > + > + if (msg[1] > end - addr) { > + DRM_ERROR("VCN message header does not fit in BO!\n"); > + r = -EINVAL; > + goto out; > + } > + > + if (msg[3] != VCN_DEC_MSG_CREATE) > + goto out; > + > + len_dw = msg[1] / 4; > + num_buffers = msg[2]; > + > + /* Verify that all indices fit within the claimed length. Each index is > 4 > DWORDs */ > + if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) { > + DRM_ERROR("VCN message has too many buffers!\n"); > + r = -EINVAL; > + goto out; > + } > + > + for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) { > + uint32_t offset, size, *create; > + > + if (msg[0] != VCN_DEC_MESSAGE_CREATE) > + continue; > + > + offset = msg[1]; > + size = msg[2]; > + > + if (size < 4 || offset + size > end - addr) { > + DRM_ERROR("VCN message buffer exceeds BO > bounds!\n"); > + r = -EINVAL; > + goto out; > + } > + > + create = ptr + addr + offset - start; > + > + /* H264, HEVC and VP9 can run on any instance */ > + if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11) > + continue; > + > + r = limit_sched(p, job); > + if (r) > + goto out; > + } > + > +out: > + amdgpu_bo_kunmap(bo); > + return r; > +} > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h > index e72687246235..ad6ca7aa74bd 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h > @@ -573,4 +573,9 @@ void amdgpu_vcn_print_ip_state(struct > amdgpu_ip_block *ip_block, struct drm_prin > void amdgpu_vcn_get_profile(struct amdgpu_device *adev); > void
