diff options
author | Jerome Glisse <jglisse@redhat.com> | 2011-12-21 12:13:47 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-01-05 05:03:53 -0500 |
commit | c1341e52802ab401be7addb55408e23307f9074b (patch) | |
tree | 84319dfa10da13769fd9562eda73a8e60f069088 /drivers | |
parent | 69e130a6a42270f94e6ee0bce34c3480a6b9da61 (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.h | 67 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ring.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_semaphore.c | 157 |
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); | |||
243 | int radeon_fence_count_emitted(struct radeon_device *rdev, int ring); | 243 | int radeon_fence_count_emitted(struct radeon_device *rdev, int ring); |
244 | 244 | ||
245 | /* | 245 | /* |
246 | * Semaphores. | ||
247 | */ | ||
248 | struct radeon_ring; | ||
249 | |||
250 | struct radeon_semaphore_driver { | ||
251 | rwlock_t lock; | ||
252 | struct list_head free; | ||
253 | }; | ||
254 | |||
255 | struct radeon_semaphore { | ||
256 | struct radeon_bo *robj; | ||
257 | struct list_head list; | ||
258 | uint64_t gpu_addr; | ||
259 | }; | ||
260 | |||
261 | void radeon_semaphore_driver_fini(struct radeon_device *rdev); | ||
262 | int radeon_semaphore_create(struct radeon_device *rdev, | ||
263 | struct radeon_semaphore **semaphore); | ||
264 | void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, | ||
265 | struct radeon_semaphore *semaphore); | ||
266 | void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, | ||
267 | struct radeon_semaphore *semaphore); | ||
268 | void radeon_semaphore_free(struct radeon_device *rdev, | ||
269 | struct radeon_semaphore *semaphore); | ||
270 | |||
271 | /* | ||
272 | * Tiling registers | 246 | * Tiling registers |
273 | */ | 247 | */ |
274 | struct radeon_surface_reg { | 248 | struct 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 | */ | ||
366 | struct radeon_ring; | ||
367 | |||
368 | #define RADEON_SEMAPHORE_BO_SIZE 256 | ||
369 | |||
370 | struct radeon_semaphore_driver { | ||
371 | rwlock_t lock; | ||
372 | struct list_head bo; | ||
373 | }; | ||
374 | |||
375 | struct radeon_semaphore_bo; | ||
376 | |||
377 | /* everything here is constant */ | ||
378 | struct 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 | |||
385 | struct 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 | |||
393 | void radeon_semaphore_driver_fini(struct radeon_device *rdev); | ||
394 | int radeon_semaphore_create(struct radeon_device *rdev, | ||
395 | struct radeon_semaphore **semaphore); | ||
396 | void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, | ||
397 | struct radeon_semaphore *semaphore); | ||
398 | void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, | ||
399 | struct radeon_semaphore *semaphore); | ||
400 | void 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 | */ |
392 | struct radeon_mc; | 406 | struct radeon_mc; |
@@ -641,6 +655,7 @@ void r600_blit_suspend(struct radeon_device *rdev); | |||
641 | int radeon_ib_get(struct radeon_device *rdev, int ring, | 655 | int radeon_ib_get(struct radeon_device *rdev, int ring, |
642 | struct radeon_ib **ib, unsigned size); | 656 | struct radeon_ib **ib, unsigned size); |
643 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib); | 657 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib); |
658 | bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib); | ||
644 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); | 659 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); |
645 | int radeon_ib_pool_init(struct radeon_device *rdev); | 660 | int radeon_ib_pool_init(struct radeon_device *rdev); |
646 | void radeon_ib_pool_fini(struct radeon_device *rdev); | 661 | void 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 | */ |
80 | static bool radeon_ib_try_free(struct radeon_device *rdev, | 80 | bool 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 | ||
34 | static int allocate_semaphores(struct radeon_device *rdev) | 34 | static 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)); | 75 | static 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; | 84 | void 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 | ||
99 | int radeon_semaphore_create(struct radeon_device *rdev, | 103 | int 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 | ||
111 | retry: | ||
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 | ||
133 | void radeon_semaphore_free(struct radeon_device *rdev, | 152 | void 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 | ||
143 | void radeon_semaphore_driver_fini(struct radeon_device *rdev) | 164 | void 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 | } |