diff options
author | Christian König <deathsimple@vodafone.de> | 2012-01-05 22:11:06 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-01-06 04:16:09 -0500 |
commit | 93504fce28b1a387ec01f81b26637d237dca2b36 (patch) | |
tree | 7544b4fd960cbcbbfc17dea87aadd129eecf7b45 /drivers/gpu | |
parent | 721604a15b934f0a8d1909acb8017f029128be2f (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/gpu')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_cs.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fence.c | 3 |
3 files changed, 50 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5e3542384b21..3483ed9b38e9 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 | ||
235 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); | 236 | int 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 4d595403b50c..17af0e83c328 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 | ||
119 | static 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 | |||
112 | int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) | 149 | int 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 ae9e3da594a1..64ea3dd9e6ff 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); |