summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_cs.c
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-03-20 17:18:14 -0400
committerDave Airlie <airlied@redhat.com>2012-03-21 06:55:53 +0000
commitdfcf5f36529d69eb35f4fdedfa6f244c5249698c (patch)
treeda1fc31a5ef8d53c63786121f16f29fe3b12a92a /drivers/gpu/drm/radeon/radeon_cs.c
parentd2800ee59ed28a5eaf3a4a8645feca040eacf7df (diff)
downloadblackbird-op-linux-dfcf5f36529d69eb35f4fdedfa6f244c5249698c.tar.gz
blackbird-op-linux-dfcf5f36529d69eb35f4fdedfa6f244c5249698c.zip
drm/radeon/kms: add support for the CONST IB to the CS ioctl
This adds a new chunk id to the CS ioctl to support the INDIRECT_BUFFER_CONST packet. On SI, the CP adds a new engine called the CE (Constant Engine) which runs simulatenously with the DE (Drawing Engine, formerly called the ME). This allows the CP to process two related IBs simultaneously. The CE is tasked with loading the constant data (constant buffers, resource descriptors, samplers, etc.) while the DE loads context register state and issues drawing commands. It's up to the userspace application to sychronize the CE and the DE using special synchronization packets. Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_cs.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c47
1 files changed, 47 insertions, 0 deletions
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) {
OpenPOWER on IntegriCloud