aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák2016-01-12 15:13:07 -0600
committerMarek Olšák2016-01-19 19:14:46 -0600
commit6afadeaf13279fcdbc48999f522e1dc90a9dfdaf (patch)
tree4401a7685e86ec8bf24c70637bd8bef19bb7dfa0 /amdgpu/amdgpu_cs.c
parentf06c9928198d9348fb31325a2a480afbc29c04b8 (diff)
downloadexternal-libgbm-6afadeaf13279fcdbc48999f522e1dc90a9dfdaf.tar.gz
external-libgbm-6afadeaf13279fcdbc48999f522e1dc90a9dfdaf.tar.xz
external-libgbm-6afadeaf13279fcdbc48999f522e1dc90a9dfdaf.zip
amdgpu: add semaphore support
the semaphore is a binary semaphore. the work flow is: 1. create sem 2. signal sem 3. wait sem, reset sem after signalled 4. destroy sem. Signed-off-by: Chunming Zhou <david1.zhou@amd.com> Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com>
Diffstat (limited to 'amdgpu/amdgpu_cs.c')
-rw-r--r--amdgpu/amdgpu_cs.c173
1 files changed, 169 insertions, 4 deletions
diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c
index 6747158c..1848ade5 100644
--- a/amdgpu/amdgpu_cs.c
+++ b/amdgpu/amdgpu_cs.c
@@ -40,6 +40,9 @@
40#include "amdgpu_drm.h" 40#include "amdgpu_drm.h"
41#include "amdgpu_internal.h" 41#include "amdgpu_internal.h"
42 42
43static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem);
44static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem);
45
43/** 46/**
44 * Create command submission context 47 * Create command submission context
45 * 48 *
@@ -53,6 +56,7 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
53{ 56{
54 struct amdgpu_context *gpu_context; 57 struct amdgpu_context *gpu_context;
55 union drm_amdgpu_ctx args; 58 union drm_amdgpu_ctx args;
59 int i, j, k;
56 int r; 60 int r;
57 61
58 if (NULL == dev) 62 if (NULL == dev)
@@ -66,6 +70,10 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
66 70
67 gpu_context->dev = dev; 71 gpu_context->dev = dev;
68 72
73 r = pthread_mutex_init(&gpu_context->sequence_mutex, NULL);
74 if (r)
75 goto error;
76
69 /* Create the context */ 77 /* Create the context */
70 memset(&args, 0, sizeof(args)); 78 memset(&args, 0, sizeof(args));
71 args.in.op = AMDGPU_CTX_OP_ALLOC_CTX; 79 args.in.op = AMDGPU_CTX_OP_ALLOC_CTX;
@@ -74,11 +82,16 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
74 goto error; 82 goto error;
75 83
76 gpu_context->id = args.out.alloc.ctx_id; 84 gpu_context->id = args.out.alloc.ctx_id;
85 for (i = 0; i < AMDGPU_HW_IP_NUM; i++)
86 for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++)
87 for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++)
88 list_inithead(&gpu_context->sem_list[i][j][k]);
77 *context = (amdgpu_context_handle)gpu_context; 89 *context = (amdgpu_context_handle)gpu_context;
78 90
79 return 0; 91 return 0;
80 92
81error: 93error:
94 pthread_mutex_destroy(&gpu_context->sequence_mutex);
82 free(gpu_context); 95 free(gpu_context);
83 return r; 96 return r;
84} 97}
@@ -94,18 +107,32 @@ error:
94int amdgpu_cs_ctx_free(amdgpu_context_handle context) 107int amdgpu_cs_ctx_free(amdgpu_context_handle context)
95{ 108{
96 union drm_amdgpu_ctx args; 109 union drm_amdgpu_ctx args;
110 int i, j, k;
97 int r; 111 int r;
98 112
99 if (NULL == context) 113 if (NULL == context)
100 return -EINVAL; 114 return -EINVAL;
101 115
116 pthread_mutex_destroy(&context->sequence_mutex);
117
102 /* now deal with kernel side */ 118 /* now deal with kernel side */
103 memset(&args, 0, sizeof(args)); 119 memset(&args, 0, sizeof(args));
104 args.in.op = AMDGPU_CTX_OP_FREE_CTX; 120 args.in.op = AMDGPU_CTX_OP_FREE_CTX;
105 args.in.ctx_id = context->id; 121 args.in.ctx_id = context->id;
106 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX, 122 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX,
107 &args, sizeof(args)); 123 &args, sizeof(args));
108 124 for (i = 0; i < AMDGPU_HW_IP_NUM; i++) {
125 for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) {
126 for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) {
127 amdgpu_semaphore_handle sem;
128 LIST_FOR_EACH_ENTRY(sem, &context->sem_list[i][j][k], list) {
129 list_del(&sem->list);
130 amdgpu_cs_reset_sem(sem);
131 amdgpu_cs_unreference_sem(sem);
132 }
133 }
134 }
135 }
109 free(context); 136 free(context);
110 137
111 return r; 138 return r;
@@ -150,7 +177,10 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context,
150 struct drm_amdgpu_cs_chunk *chunks; 177 struct drm_amdgpu_cs_chunk *chunks;
151 struct drm_amdgpu_cs_chunk_data *chunk_data; 178 struct drm_amdgpu_cs_chunk_data *chunk_data;
152 struct drm_amdgpu_cs_chunk_dep *dependencies = NULL; 179 struct drm_amdgpu_cs_chunk_dep *dependencies = NULL;
153 uint32_t i, size; 180 struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL;
181 struct list_head *sem_list;
182 amdgpu_semaphore_handle sem;
183 uint32_t i, size, sem_count = 0;
154 bool user_fence; 184 bool user_fence;
155 int r = 0; 185 int r = 0;
156 186
@@ -162,7 +192,7 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context,
162 return -EINVAL; 192 return -EINVAL;
163 user_fence = (ibs_request->fence_info.handle != NULL); 193 user_fence = (ibs_request->fence_info.handle != NULL);
164 194
165 size = ibs_request->number_of_ibs + (user_fence ? 2 : 1); 195 size = ibs_request->number_of_ibs + (user_fence ? 2 : 1) + 1;
166 196
167 chunk_array = alloca(sizeof(uint64_t) * size); 197 chunk_array = alloca(sizeof(uint64_t) * size);
168 chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size); 198 chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size);
@@ -196,6 +226,8 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context,
196 chunk_data[i].ib_data.flags = ib->flags; 226 chunk_data[i].ib_data.flags = ib->flags;
197 } 227 }
198 228
229 pthread_mutex_lock(&context->sequence_mutex);
230
199 if (user_fence) { 231 if (user_fence) {
200 i = cs.in.num_chunks++; 232 i = cs.in.num_chunks++;
201 233
@@ -240,15 +272,49 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context,
240 chunks[i].chunk_data = (uint64_t)(uintptr_t)dependencies; 272 chunks[i].chunk_data = (uint64_t)(uintptr_t)dependencies;
241 } 273 }
242 274
275 sem_list = &context->sem_list[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring];
276 LIST_FOR_EACH_ENTRY(sem, sem_list, list)
277 sem_count++;
278 if (sem_count) {
279 sem_dependencies = malloc(sizeof(struct drm_amdgpu_cs_chunk_dep) * sem_count);
280 if (!sem_dependencies) {
281 r = -ENOMEM;
282 goto error_unlock;
283 }
284 sem_count = 0;
285 LIST_FOR_EACH_ENTRY(sem, sem_list, list) {
286 struct amdgpu_cs_fence *info = &sem->signal_fence;
287 struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++];
288 dep->ip_type = info->ip_type;
289 dep->ip_instance = info->ip_instance;
290 dep->ring = info->ring;
291 dep->ctx_id = info->context->id;
292 dep->handle = info->fence;
293
294 list_del(&sem->list);
295 amdgpu_cs_reset_sem(sem);
296 amdgpu_cs_unreference_sem(sem);
297 }
298 i = cs.in.num_chunks++;
299
300 /* dependencies chunk */
301 chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i];
302 chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES;
303 chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 * sem_count;
304 chunks[i].chunk_data = (uint64_t)(uintptr_t)sem_dependencies;
305 }
306
243 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CS, 307 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CS,
244 &cs, sizeof(cs)); 308 &cs, sizeof(cs));
245 if (r) 309 if (r)
246 goto error_unlock; 310 goto error_unlock;
247 311
248 ibs_request->seq_no = cs.out.handle; 312 ibs_request->seq_no = cs.out.handle;
249 313 context->last_seq[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring] = ibs_request->seq_no;
250error_unlock: 314error_unlock:
315 pthread_mutex_unlock(&context->sequence_mutex);
251 free(dependencies); 316 free(dependencies);
317 free(sem_dependencies);
252 return r; 318 return r;
253} 319}
254 320
@@ -369,3 +435,102 @@ int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence,
369 return r; 435 return r;
370} 436}
371 437
438int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem)
439{
440 struct amdgpu_semaphore *gpu_semaphore;
441
442 if (NULL == sem)
443 return -EINVAL;
444
445 gpu_semaphore = calloc(1, sizeof(struct amdgpu_semaphore));
446 if (NULL == gpu_semaphore)
447 return -ENOMEM;
448
449 atomic_set(&gpu_semaphore->refcount, 1);
450 *sem = gpu_semaphore;
451
452 return 0;
453}
454
455int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx,
456 uint32_t ip_type,
457 uint32_t ip_instance,
458 uint32_t ring,
459 amdgpu_semaphore_handle sem)
460{
461 if (NULL == ctx)
462 return -EINVAL;
463 if (ip_type >= AMDGPU_HW_IP_NUM)
464 return -EINVAL;
465 if (ring >= AMDGPU_CS_MAX_RINGS)
466 return -EINVAL;
467 if (NULL == sem)
468 return -EINVAL;
469 /* sem has been signaled */
470 if (sem->signal_fence.context)
471 return -EINVAL;
472 pthread_mutex_lock(&ctx->sequence_mutex);
473 sem->signal_fence.context = ctx;
474 sem->signal_fence.ip_type = ip_type;
475 sem->signal_fence.ip_instance = ip_instance;
476 sem->signal_fence.ring = ring;
477 sem->signal_fence.fence = ctx->last_seq[ip_type][ip_instance][ring];
478 update_references(NULL, &sem->refcount);
479 pthread_mutex_unlock(&ctx->sequence_mutex);
480 return 0;
481}
482
483int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx,
484 uint32_t ip_type,
485 uint32_t ip_instance,
486 uint32_t ring,
487 amdgpu_semaphore_handle sem)
488{
489 if (NULL == ctx)
490 return -EINVAL;
491 if (ip_type >= AMDGPU_HW_IP_NUM)
492 return -EINVAL;
493 if (ring >= AMDGPU_CS_MAX_RINGS)
494 return -EINVAL;
495 if (NULL == sem)
496 return -EINVAL;
497 /* must signal first */
498 if (NULL == sem->signal_fence.context)
499 return -EINVAL;
500
501 pthread_mutex_lock(&ctx->sequence_mutex);
502 list_add(&sem->list, &ctx->sem_list[ip_type][ip_instance][ring]);
503 pthread_mutex_unlock(&ctx->sequence_mutex);
504 return 0;
505}
506
507static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem)
508{
509 if (NULL == sem)
510 return -EINVAL;
511 if (NULL == sem->signal_fence.context)
512 return -EINVAL;
513
514 sem->signal_fence.context = NULL;;
515 sem->signal_fence.ip_type = 0;
516 sem->signal_fence.ip_instance = 0;
517 sem->signal_fence.ring = 0;
518 sem->signal_fence.fence = 0;
519
520 return 0;
521}
522
523static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem)
524{
525 if (NULL == sem)
526 return -EINVAL;
527
528 if (update_references(&sem->refcount, NULL))
529 free(sem);
530 return 0;
531}
532
533int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem)
534{
535 return amdgpu_cs_unreference_sem(sem);
536}