diff options
author | Marek Olšák | 2016-01-12 15:13:07 -0600 |
---|---|---|
committer | Marek Olšák | 2016-01-19 19:14:46 -0600 |
commit | 6afadeaf13279fcdbc48999f522e1dc90a9dfdaf (patch) | |
tree | 4401a7685e86ec8bf24c70637bd8bef19bb7dfa0 /amdgpu/amdgpu_cs.c | |
parent | f06c9928198d9348fb31325a2a480afbc29c04b8 (diff) | |
download | external-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.c | 173 |
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 | ||
43 | static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem); | ||
44 | static 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 | ||
81 | error: | 93 | error: |
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: | |||
94 | int amdgpu_cs_ctx_free(amdgpu_context_handle context) | 107 | int 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; | |
250 | error_unlock: | 314 | error_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 | ||
438 | int 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 | |||
455 | int 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 | |||
483 | int 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 | |||
507 | static 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 | |||
523 | static 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 | |||
533 | int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem) | ||
534 | { | ||
535 | return amdgpu_cs_unreference_sem(sem); | ||
536 | } | ||