aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChristian König <deathsimple@vodafone.de>2012-01-05 22:11:06 -0500
committerDave Airlie <airlied@redhat.com>2012-01-06 04:16:09 -0500
commit93504fce28b1a387ec01f81b26637d237dca2b36 (patch)
tree7544b4fd960cbcbbfc17dea87aadd129eecf7b45 /drivers
parent721604a15b934f0a8d1909acb8017f029128be2f (diff)
drm/radeon/kms: Add support for multi-ring sync in CS ioctl (v2)
Use semaphores to sync buffers across rings in the CS ioctl. Add a reloc flag to allow userspace to skip sync for buffers. agd5f: port to latest CS ioctl changes. v2: add ring lock/unlock to make sure changes hit the ring. Signed-off-by: Christian König <deathsimple@vodafone.de> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/radeon/radeon.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c45
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c3
3 files changed, 50 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5e3542384b2..3483ed9b38e 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -230,6 +230,7 @@ struct radeon_fence {
230 bool signaled; 230 bool signaled;
231 /* RB, DMA, etc. */ 231 /* RB, DMA, etc. */
232 int ring; 232 int ring;
233 struct radeon_semaphore *semaphore;
233}; 234};
234 235
235int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); 236int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
@@ -789,6 +790,7 @@ struct radeon_cs_parser {
789 struct radeon_cs_reloc *relocs; 790 struct radeon_cs_reloc *relocs;
790 struct radeon_cs_reloc **relocs_ptr; 791 struct radeon_cs_reloc **relocs_ptr;
791 struct list_head validated; 792 struct list_head validated;
793 bool sync_to_ring[RADEON_NUM_RINGS];
792 /* indices of various chunks */ 794 /* indices of various chunks */
793 int chunk_ib_idx; 795 int chunk_ib_idx;
794 int chunk_relocs_idx; 796 int chunk_relocs_idx;
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 4d595403b50..17af0e83c32 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -84,6 +84,13 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
84 p->relocs[i].flags = r->flags; 84 p->relocs[i].flags = r->flags;
85 radeon_bo_list_add_object(&p->relocs[i].lobj, 85 radeon_bo_list_add_object(&p->relocs[i].lobj,
86 &p->validated); 86 &p->validated);
87
88 if (p->relocs[i].robj->tbo.sync_obj && !(r->flags & RADEON_RELOC_DONT_SYNC)) {
89 struct radeon_fence *fence = p->relocs[i].robj->tbo.sync_obj;
90 if (!radeon_fence_signaled(fence)) {
91 p->sync_to_ring[fence->ring] = true;
92 }
93 }
87 } else 94 } else
88 p->relocs[i].handle = 0; 95 p->relocs[i].handle = 0;
89 } 96 }
@@ -109,6 +116,36 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
109 return 0; 116 return 0;
110} 117}
111 118
119static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
120{
121 int i, r;
122
123 for (i = 0; i < RADEON_NUM_RINGS; ++i) {
124 /* no need to sync to our own or unused rings */
125 if (i == p->ring || !p->sync_to_ring[i] || !p->rdev->ring[i].ready)
126 continue;
127
128 if (!p->ib->fence->semaphore) {
129 r = radeon_semaphore_create(p->rdev, &p->ib->fence->semaphore);
130 if (r)
131 return r;
132 }
133
134 r = radeon_ring_lock(p->rdev, &p->rdev->ring[i], 3);
135 if (r)
136 return r;
137 radeon_semaphore_emit_signal(p->rdev, i, p->ib->fence->semaphore);
138 radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[i]);
139
140 r = radeon_ring_lock(p->rdev, &p->rdev->ring[p->ring], 3);
141 if (r)
142 return r;
143 radeon_semaphore_emit_wait(p->rdev, p->ring, p->ib->fence->semaphore);
144 radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[p->ring]);
145 }
146 return 0;
147}
148
112int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) 149int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
113{ 150{
114 struct drm_radeon_cs *cs = data; 151 struct drm_radeon_cs *cs = data;
@@ -314,6 +351,10 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
314 DRM_ERROR("Invalid command stream !\n"); 351 DRM_ERROR("Invalid command stream !\n");
315 return r; 352 return r;
316 } 353 }
354 r = radeon_cs_sync_rings(parser);
355 if (r) {
356 DRM_ERROR("Failed to synchronize rings !\n");
357 }
317 parser->ib->vm_id = 0; 358 parser->ib->vm_id = 0;
318 r = radeon_ib_schedule(rdev, parser->ib); 359 r = radeon_ib_schedule(rdev, parser->ib);
319 if (r) { 360 if (r) {
@@ -384,6 +425,10 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
384 if (r) { 425 if (r) {
385 goto out; 426 goto out;
386 } 427 }
428 r = radeon_cs_sync_rings(parser);
429 if (r) {
430 DRM_ERROR("Failed to synchronize rings !\n");
431 }
387 parser->ib->vm_id = vm->id; 432 parser->ib->vm_id = vm->id;
388 /* ib pool is bind at 0 in virtual address space to gpu_addr is the 433 /* ib pool is bind at 0 in virtual address space to gpu_addr is the
389 * offset inside the pool bo 434 * offset inside the pool bo
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index ae9e3da594a..64ea3dd9e6f 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -153,6 +153,8 @@ static void radeon_fence_destroy(struct kref *kref)
153 list_del(&fence->list); 153 list_del(&fence->list);
154 fence->emitted = false; 154 fence->emitted = false;
155 write_unlock_irqrestore(&fence->rdev->fence_lock, irq_flags); 155 write_unlock_irqrestore(&fence->rdev->fence_lock, irq_flags);
156 if (fence->semaphore)
157 radeon_semaphore_free(fence->rdev, fence->semaphore);
156 kfree(fence); 158 kfree(fence);
157} 159}
158 160
@@ -172,6 +174,7 @@ int radeon_fence_create(struct radeon_device *rdev,
172 (*fence)->signaled = false; 174 (*fence)->signaled = false;
173 (*fence)->seq = 0; 175 (*fence)->seq = 0;
174 (*fence)->ring = ring; 176 (*fence)->ring = ring;
177 (*fence)->semaphore = NULL;
175 INIT_LIST_HEAD(&(*fence)->list); 178 INIT_LIST_HEAD(&(*fence)->list);
176 179
177 write_lock_irqsave(&rdev->fence_lock, irq_flags); 180 write_lock_irqsave(&rdev->fence_lock, irq_flags);