aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2011-12-21 12:13:47 -0500
committerDave Airlie <airlied@redhat.com>2012-01-05 05:03:53 -0500
commitc1341e52802ab401be7addb55408e23307f9074b (patch)
tree84319dfa10da13769fd9562eda73a8e60f069088 /drivers
parent69e130a6a42270f94e6ee0bce34c3480a6b9da61 (diff)
drm/radeon: allocate semaphore from the ib pool
This allow to share the ib pool with semaphore and avoid having more bo around. Signed-off-by: Jerome Glisse <jglisse@redhat.com> 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.h67
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_semaphore.c157
4 files changed, 131 insertions, 100 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 0301896ac15..374f9a4d94e 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -243,32 +243,6 @@ void radeon_fence_unref(struct radeon_fence **fence);
243int radeon_fence_count_emitted(struct radeon_device *rdev, int ring); 243int radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
244 244
245/* 245/*
246 * Semaphores.
247 */
248struct radeon_ring;
249
250struct radeon_semaphore_driver {
251 rwlock_t lock;
252 struct list_head free;
253};
254
255struct radeon_semaphore {
256 struct radeon_bo *robj;
257 struct list_head list;
258 uint64_t gpu_addr;
259};
260
261void radeon_semaphore_driver_fini(struct radeon_device *rdev);
262int radeon_semaphore_create(struct radeon_device *rdev,
263 struct radeon_semaphore **semaphore);
264void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
265 struct radeon_semaphore *semaphore);
266void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
267 struct radeon_semaphore *semaphore);
268void radeon_semaphore_free(struct radeon_device *rdev,
269 struct radeon_semaphore *semaphore);
270
271/*
272 * Tiling registers 246 * Tiling registers
273 */ 247 */
274struct radeon_surface_reg { 248struct radeon_surface_reg {
@@ -387,6 +361,46 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv,
387 uint32_t handle); 361 uint32_t handle);
388 362
389/* 363/*
364 * Semaphores.
365 */
366struct radeon_ring;
367
368#define RADEON_SEMAPHORE_BO_SIZE 256
369
370struct radeon_semaphore_driver {
371 rwlock_t lock;
372 struct list_head bo;
373};
374
375struct radeon_semaphore_bo;
376
377/* everything here is constant */
378struct radeon_semaphore {
379 struct list_head list;
380 uint64_t gpu_addr;
381 uint32_t *cpu_ptr;
382 struct radeon_semaphore_bo *bo;
383};
384
385struct radeon_semaphore_bo {
386 struct list_head list;
387 struct radeon_ib *ib;
388 struct list_head free;
389 struct radeon_semaphore semaphores[RADEON_SEMAPHORE_BO_SIZE/8];
390 unsigned nused;
391};
392
393void radeon_semaphore_driver_fini(struct radeon_device *rdev);
394int radeon_semaphore_create(struct radeon_device *rdev,
395 struct radeon_semaphore **semaphore);
396void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
397 struct radeon_semaphore *semaphore);
398void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
399 struct radeon_semaphore *semaphore);
400void radeon_semaphore_free(struct radeon_device *rdev,
401 struct radeon_semaphore *semaphore);
402
403/*
390 * GART structures, functions & helpers 404 * GART structures, functions & helpers
391 */ 405 */
392struct radeon_mc; 406struct radeon_mc;
@@ -641,6 +655,7 @@ void r600_blit_suspend(struct radeon_device *rdev);
641int radeon_ib_get(struct radeon_device *rdev, int ring, 655int radeon_ib_get(struct radeon_device *rdev, int ring,
642 struct radeon_ib **ib, unsigned size); 656 struct radeon_ib **ib, unsigned size);
643void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib); 657void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
658bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib);
644int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); 659int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
645int radeon_ib_pool_init(struct radeon_device *rdev); 660int radeon_ib_pool_init(struct radeon_device *rdev);
646void radeon_ib_pool_fini(struct radeon_device *rdev); 661void radeon_ib_pool_fini(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index e81c333e0f9..846eeb852e5 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -731,7 +731,7 @@ int radeon_device_init(struct radeon_device *rdev,
731 INIT_LIST_HEAD(&rdev->gem.objects); 731 INIT_LIST_HEAD(&rdev->gem.objects);
732 init_waitqueue_head(&rdev->irq.vblank_queue); 732 init_waitqueue_head(&rdev->irq.vblank_queue);
733 init_waitqueue_head(&rdev->irq.idle_queue); 733 init_waitqueue_head(&rdev->irq.idle_queue);
734 INIT_LIST_HEAD(&rdev->semaphore_drv.free); 734 INIT_LIST_HEAD(&rdev->semaphore_drv.bo);
735 735
736 /* Set asic functions */ 736 /* Set asic functions */
737 r = radeon_asic_init(rdev); 737 r = radeon_asic_init(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index bc844fe86ae..465fb34c197 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -77,8 +77,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
77/* 77/*
78 * IB. 78 * IB.
79 */ 79 */
80static bool radeon_ib_try_free(struct radeon_device *rdev, 80bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib)
81 struct radeon_ib *ib)
82{ 81{
83 bool done = false; 82 bool done = false;
84 83
@@ -148,7 +147,7 @@ retry:
148 /* this should be rare event, ie all ib scheduled none signaled yet. 147 /* this should be rare event, ie all ib scheduled none signaled yet.
149 */ 148 */
150 for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { 149 for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
151 if (rdev->ib_pool.ibs[idx].fence) { 150 if (rdev->ib_pool.ibs[idx].fence && rdev->ib_pool.ibs[idx].fence->emitted) {
152 r = radeon_fence_wait(rdev->ib_pool.ibs[idx].fence, false); 151 r = radeon_fence_wait(rdev->ib_pool.ibs[idx].fence, false);
153 if (!r) { 152 if (!r) {
154 goto retry; 153 goto retry;
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c
index f8cf04499a5..61dd4e3c920 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
@@ -31,90 +31,109 @@
31#include "drm.h" 31#include "drm.h"
32#include "radeon.h" 32#include "radeon.h"
33 33
34static int allocate_semaphores(struct radeon_device *rdev) 34static int radeon_semaphore_add_bo(struct radeon_device *rdev)
35{ 35{
36 const unsigned long bo_size = PAGE_SIZE * 4; 36 struct radeon_semaphore_bo *bo;
37
38 struct radeon_bo *bo;
39 struct list_head new_entrys;
40 unsigned long irq_flags; 37 unsigned long irq_flags;
41 uint64_t gpu_addr; 38 uint64_t gpu_addr;
42 void *map; 39 uint32_t *cpu_ptr;
43 int i, r; 40 int r, i;
44 41
45 r = radeon_bo_create(rdev, bo_size, RADEON_GPU_PAGE_SIZE, true,
46 RADEON_GEM_DOMAIN_GTT, &bo);
47 if (r) {
48 dev_err(rdev->dev, "(%d) failed to allocate semaphore bo\n", r);
49 return r;
50 }
51
52 r = radeon_bo_reserve(bo, false);
53 if (r) {
54 radeon_bo_unref(&bo);
55 dev_err(rdev->dev, "(%d) failed to reserve semaphore bo\n", r);
56 return r;
57 }
58 42
59 r = radeon_bo_kmap(bo, &map); 43 bo = kmalloc(sizeof(struct radeon_semaphore_bo), GFP_KERNEL);
60 if (r) { 44 if (bo == NULL) {
61 radeon_bo_unreserve(bo); 45 return -ENOMEM;
62 radeon_bo_unref(&bo);
63 dev_err(rdev->dev, "(%d) semaphore map failed\n", r);
64 return r;
65 } 46 }
66 memset(map, 0, bo_size); 47 INIT_LIST_HEAD(&bo->free);
67 radeon_bo_kunmap(bo); 48 INIT_LIST_HEAD(&bo->list);
49 bo->nused = 0;
68 50
69 r = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); 51 r = radeon_ib_get(rdev, 0, &bo->ib, RADEON_SEMAPHORE_BO_SIZE);
70 if (r) { 52 if (r) {
71 radeon_bo_unreserve(bo); 53 dev_err(rdev->dev, "failed to get a bo after 5 retry\n");
72 radeon_bo_unref(&bo); 54 kfree(bo);
73 dev_err(rdev->dev, "(%d) semaphore pin failed\n", r);
74 return r; 55 return r;
75 } 56 }
76 57 gpu_addr = rdev->ib_pool.sa_manager.gpu_addr;
77 INIT_LIST_HEAD(&new_entrys); 58 gpu_addr += bo->ib->sa_bo.offset;
78 for (i = 0; i < bo_size/8; ++i) { 59 cpu_ptr = rdev->ib_pool.sa_manager.cpu_ptr;
79 struct radeon_semaphore *sem = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); 60 cpu_ptr += (bo->ib->sa_bo.offset >> 2);
80 ttm_bo_reference(&bo->tbo); 61 for (i = 0; i < (RADEON_SEMAPHORE_BO_SIZE/8); i++) {
81 sem->robj = bo; 62 bo->semaphores[i].gpu_addr = gpu_addr;
82 sem->gpu_addr = gpu_addr; 63 bo->semaphores[i].cpu_ptr = cpu_ptr;
64 bo->semaphores[i].bo = bo;
65 list_add_tail(&bo->semaphores[i].list, &bo->free);
83 gpu_addr += 8; 66 gpu_addr += 8;
84 list_add_tail(&sem->list, &new_entrys); 67 cpu_ptr += 2;
85 } 68 }
86
87 radeon_bo_unreserve(bo);
88 radeon_bo_unref(&bo);
89
90 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); 69 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
91 list_splice_tail(&new_entrys, &rdev->semaphore_drv.free); 70 list_add_tail(&bo->list, &rdev->semaphore_drv.bo);
92 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); 71 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
72 return 0;
73}
93 74
94 DRM_INFO("%d new semaphores allocated\n", (int)(bo_size/8)); 75static void radeon_semaphore_del_bo_locked(struct radeon_device *rdev,
76 struct radeon_semaphore_bo *bo)
77{
78 radeon_sa_bo_free(rdev, &bo->ib->sa_bo);
79 radeon_fence_unref(&bo->ib->fence);
80 list_del(&bo->list);
81 kfree(bo);
82}
95 83
96 return 0; 84void radeon_semaphore_shrink_locked(struct radeon_device *rdev)
85{
86 struct radeon_semaphore_bo *bo, *n;
87
88 if (list_empty(&rdev->semaphore_drv.bo)) {
89 return;
90 }
91 /* only shrink if first bo has free semaphore */
92 bo = list_first_entry(&rdev->semaphore_drv.bo, struct radeon_semaphore_bo, list);
93 if (list_empty(&bo->free)) {
94 return;
95 }
96 list_for_each_entry_safe_continue(bo, n, &rdev->semaphore_drv.bo, list) {
97 if (bo->nused)
98 continue;
99 radeon_semaphore_del_bo_locked(rdev, bo);
100 }
97} 101}
98 102
99int radeon_semaphore_create(struct radeon_device *rdev, 103int radeon_semaphore_create(struct radeon_device *rdev,
100 struct radeon_semaphore **semaphore) 104 struct radeon_semaphore **semaphore)
101{ 105{
106 struct radeon_semaphore_bo *bo;
102 unsigned long irq_flags; 107 unsigned long irq_flags;
108 bool do_retry = true;
109 int r;
103 110
111retry:
112 *semaphore = NULL;
104 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); 113 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
105 if (list_empty(&rdev->semaphore_drv.free)) { 114 list_for_each_entry(bo, &rdev->semaphore_drv.bo, list) {
106 int r; 115 if (list_empty(&bo->free))
107 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); 116 continue;
108 r = allocate_semaphores(rdev); 117 *semaphore = list_first_entry(&bo->free, struct radeon_semaphore, list);
109 if (r) 118 (*semaphore)->cpu_ptr[0] = 0;
110 return r; 119 (*semaphore)->cpu_ptr[1] = 0;
111 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); 120 list_del(&(*semaphore)->list);
121 bo->nused++;
122 break;
112 } 123 }
124 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
113 125
114 *semaphore = list_first_entry(&rdev->semaphore_drv.free, struct radeon_semaphore, list); 126 if (*semaphore == NULL) {
115 list_del(&(*semaphore)->list); 127 if (do_retry) {
128 do_retry = false;
129 r = radeon_semaphore_add_bo(rdev);
130 if (r)
131 return r;
132 goto retry;
133 }
134 return -ENOMEM;
135 }
116 136
117 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
118 return 0; 137 return 0;
119} 138}
120 139
@@ -131,31 +150,29 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
131} 150}
132 151
133void radeon_semaphore_free(struct radeon_device *rdev, 152void radeon_semaphore_free(struct radeon_device *rdev,
134 struct radeon_semaphore *semaphore) 153 struct radeon_semaphore *semaphore)
135{ 154{
136 unsigned long irq_flags; 155 unsigned long irq_flags;
137 156
138 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); 157 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
139 list_add_tail(&semaphore->list, &rdev->semaphore_drv.free); 158 semaphore->bo->nused--;
159 list_add_tail(&semaphore->list, &semaphore->bo->free);
160 radeon_semaphore_shrink_locked(rdev);
140 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); 161 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
141} 162}
142 163
143void radeon_semaphore_driver_fini(struct radeon_device *rdev) 164void radeon_semaphore_driver_fini(struct radeon_device *rdev)
144{ 165{
145 struct radeon_semaphore *i, *n; 166 struct radeon_semaphore_bo *bo, *n;
146 struct list_head entrys;
147 unsigned long irq_flags; 167 unsigned long irq_flags;
148 168
149 INIT_LIST_HEAD(&entrys);
150 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags); 169 write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
151 if (!list_empty(&rdev->semaphore_drv.free)) { 170 /* we force to free everything */
152 list_splice(&rdev->semaphore_drv.free, &entrys); 171 list_for_each_entry_safe(bo, n, &rdev->semaphore_drv.bo, list) {
172 if (!list_empty(&bo->free)) {
173 dev_err(rdev->dev, "still in use semaphore\n");
174 }
175 radeon_semaphore_del_bo_locked(rdev, bo);
153 } 176 }
154 INIT_LIST_HEAD(&rdev->semaphore_drv.free);
155 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags); 177 write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
156
157 list_for_each_entry_safe(i, n, &entrys, list) {
158 radeon_bo_unref(&i->robj);
159 kfree(i);
160 }
161} 178}