diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 972f1679d1c9..f467fe5edf09 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -632,6 +632,7 @@ struct radeon_ib { uint32_t *ptr; struct radeon_fence *fence; unsigned vm_id; + bool is_const_ib; }; /* @@ -836,7 +837,9 @@ struct radeon_cs_parser { int chunk_ib_idx; int chunk_relocs_idx; int chunk_flags_idx; + int chunk_const_ib_idx; struct radeon_ib *ib; + struct radeon_ib *const_ib; void *track; unsigned family; int parser_error; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index d9d9f5a59c42..087bd5053774 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -170,6 +170,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) p->chunk_ib_idx = -1; p->chunk_relocs_idx = -1; p->chunk_flags_idx = -1; + p->chunk_const_ib_idx = -1; p->chunks_array = kcalloc(cs->num_chunks, sizeof(uint64_t), GFP_KERNEL); if (p->chunks_array == NULL) { return -ENOMEM; @@ -208,6 +209,12 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) if (p->chunks[i].length_dw == 0) return -EINVAL; } + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_CONST_IB) { + p->chunk_const_ib_idx = i; + /* zero length CONST IB isn't useful */ + if (p->chunks[i].length_dw == 0) + return -EINVAL; + } if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { p->chunk_flags_idx = i; /* zero length flags aren't useful */ @@ -389,6 +396,32 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) return 0; + if ((rdev->family >= CHIP_TAHITI) && + (parser->chunk_const_ib_idx != -1)) { + ib_chunk = &parser->chunks[parser->chunk_const_ib_idx]; + if (ib_chunk->length_dw > RADEON_IB_VM_MAX_SIZE) { + DRM_ERROR("cs IB CONST too big: %d\n", ib_chunk->length_dw); + return -EINVAL; + } + r = radeon_ib_get(rdev, parser->ring, &parser->const_ib, + ib_chunk->length_dw * 4); + if (r) { + DRM_ERROR("Failed to get const ib !\n"); + return r; + } + parser->const_ib->is_const_ib = true; + parser->const_ib->length_dw = ib_chunk->length_dw; + /* Copy the packet into the IB */ + if (DRM_COPY_FROM_USER(parser->const_ib->ptr, ib_chunk->user_ptr, + ib_chunk->length_dw * 4)) { + return -EFAULT; + } + r = radeon_ring_ib_parse(rdev, parser->ring, parser->const_ib); + if (r) { + return r; + } + } + ib_chunk = &parser->chunks[parser->chunk_ib_idx]; if (ib_chunk->length_dw > RADEON_IB_VM_MAX_SIZE) { DRM_ERROR("cs IB too big: %d\n", ib_chunk->length_dw); @@ -424,11 +457,25 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, if (r) { DRM_ERROR("Failed to synchronize rings !\n"); } + + if ((rdev->family >= CHIP_TAHITI) && + (parser->chunk_const_ib_idx != -1)) { + parser->const_ib->vm_id = vm->id; + /* ib pool is bind at 0 in virtual address space to gpu_addr is the + * offset inside the pool bo + */ + parser->const_ib->gpu_addr = parser->const_ib->sa_bo.offset; + r = radeon_ib_schedule(rdev, parser->const_ib); + if (r) + goto out; + } + parser->ib->vm_id = vm->id; /* ib pool is bind at 0 in virtual address space to gpu_addr is the * offset inside the pool bo */ parser->ib->gpu_addr = parser->ib->sa_bo.offset; + parser->ib->is_const_ib = false; r = radeon_ib_schedule(rdev, parser->ib); out: if (!r) { diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 30566201dffb..cc33b3d7c33b 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -133,6 +133,7 @@ retry: (*ib)->gpu_addr += (*ib)->sa_bo.offset; (*ib)->fence = fence; (*ib)->vm_id = 0; + (*ib)->is_const_ib = false; /* ib are most likely to be allocated in a ring fashion * thus rdev->ib_pool.head_id should be the id of the * oldest ib diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 6cde931d8e68..7c491b4bcf65 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -908,6 +908,7 @@ struct drm_radeon_gem_va { #define RADEON_CHUNK_ID_RELOCS 0x01 #define RADEON_CHUNK_ID_IB 0x02 #define RADEON_CHUNK_ID_FLAGS 0x03 +#define RADEON_CHUNK_ID_CONST_IB 0x04 /* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */ #define RADEON_CS_KEEP_TILING_FLAGS 0x01