diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/mm_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 82 |
1 files changed, 80 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 3b21e843..9299266f 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -3213,6 +3213,17 @@ static void gk20a_vm_remove_support_nofree(struct vm_gk20a *vm) | |||
3213 | struct rb_node *node; | 3213 | struct rb_node *node; |
3214 | 3214 | ||
3215 | gk20a_dbg_fn(""); | 3215 | gk20a_dbg_fn(""); |
3216 | |||
3217 | /* | ||
3218 | * Do this outside of the update_gmmu_lock since unmapping the semaphore | ||
3219 | * pool involves unmapping a GMMU mapping which means aquiring the | ||
3220 | * update_gmmu_lock. | ||
3221 | */ | ||
3222 | if (!gk20a_platform_has_syncpoints(gk20a_from_vm(vm)->dev)) { | ||
3223 | gk20a_semaphore_pool_unmap(vm->sema_pool, vm); | ||
3224 | gk20a_semaphore_pool_put(vm->sema_pool); | ||
3225 | } | ||
3226 | |||
3216 | mutex_lock(&vm->update_gmmu_lock); | 3227 | mutex_lock(&vm->update_gmmu_lock); |
3217 | 3228 | ||
3218 | /* TBD: add a flag here for the unmap code to recognize teardown | 3229 | /* TBD: add a flag here for the unmap code to recognize teardown |
@@ -3286,6 +3297,64 @@ const struct gk20a_mmu_level gk20a_mm_levels_128k[] = { | |||
3286 | {.update_entry = NULL} | 3297 | {.update_entry = NULL} |
3287 | }; | 3298 | }; |
3288 | 3299 | ||
3300 | /* | ||
3301 | * Initialize a semaphore pool. Just return successfully if we do not need | ||
3302 | * semaphores (i.e when sync-pts are active). | ||
3303 | */ | ||
3304 | int gk20a_init_sema_pool(struct vm_gk20a *vm) | ||
3305 | { | ||
3306 | struct gk20a_semaphore_sea *sema_sea; | ||
3307 | struct mm_gk20a *mm = vm->mm; | ||
3308 | struct gk20a *g = mm->g; | ||
3309 | int err; | ||
3310 | |||
3311 | /* | ||
3312 | * Don't waste the memory on semaphores if we don't need them. | ||
3313 | */ | ||
3314 | if (gk20a_platform_has_syncpoints(g->dev)) | ||
3315 | return 0; | ||
3316 | |||
3317 | if (vm->sema_pool) | ||
3318 | return 0; | ||
3319 | |||
3320 | sema_sea = gk20a_semaphore_sea_create(g); | ||
3321 | if (!sema_sea) | ||
3322 | return -ENOMEM; | ||
3323 | |||
3324 | vm->sema_pool = gk20a_semaphore_pool_alloc(sema_sea); | ||
3325 | if (!vm->sema_pool) { | ||
3326 | gk20a_vm_put(vm); | ||
3327 | return -ENOMEM; | ||
3328 | } | ||
3329 | |||
3330 | /* | ||
3331 | * Allocate a chunk of GPU VA space for mapping the semaphores. We will | ||
3332 | * do a fixed alloc in the kernel VM so that all channels have the same | ||
3333 | * RO address range for the semaphores. | ||
3334 | * | ||
3335 | * !!! TODO: cleanup. | ||
3336 | */ | ||
3337 | sema_sea->gpu_va = gk20a_balloc_fixed(&vm->vma[gmmu_page_size_kernel], | ||
3338 | vm->va_limit - | ||
3339 | mm->channel.kernel_size, | ||
3340 | 512 * PAGE_SIZE); | ||
3341 | if (!sema_sea->gpu_va) { | ||
3342 | gk20a_bfree(&vm->vma[gmmu_page_size_small], sema_sea->gpu_va); | ||
3343 | gk20a_vm_put(vm); | ||
3344 | return -ENOMEM; | ||
3345 | } | ||
3346 | |||
3347 | err = gk20a_semaphore_pool_map(vm->sema_pool, vm); | ||
3348 | if (err) { | ||
3349 | gk20a_semaphore_pool_unmap(vm->sema_pool, vm); | ||
3350 | gk20a_bfree(&vm->vma[gmmu_page_size_small], | ||
3351 | vm->sema_pool->gpu_va); | ||
3352 | gk20a_vm_put(vm); | ||
3353 | } | ||
3354 | |||
3355 | return 0; | ||
3356 | } | ||
3357 | |||
3289 | int gk20a_init_vm(struct mm_gk20a *mm, | 3358 | int gk20a_init_vm(struct mm_gk20a *mm, |
3290 | struct vm_gk20a *vm, | 3359 | struct vm_gk20a *vm, |
3291 | u32 big_page_size, | 3360 | u32 big_page_size, |
@@ -3317,9 +3386,7 @@ int gk20a_init_vm(struct mm_gk20a *mm, | |||
3317 | vm->big_pages = big_pages; | 3386 | vm->big_pages = big_pages; |
3318 | 3387 | ||
3319 | vm->big_page_size = gmmu_page_sizes[gmmu_page_size_big]; | 3388 | vm->big_page_size = gmmu_page_sizes[gmmu_page_size_big]; |
3320 | |||
3321 | vm->userspace_managed = userspace_managed; | 3389 | vm->userspace_managed = userspace_managed; |
3322 | |||
3323 | vm->mmu_levels = vm->mm->g->ops.mm.get_mmu_levels(vm->mm->g, | 3390 | vm->mmu_levels = vm->mm->g->ops.mm.get_mmu_levels(vm->mm->g, |
3324 | vm->big_page_size); | 3391 | vm->big_page_size); |
3325 | 3392 | ||
@@ -3465,6 +3532,17 @@ int gk20a_init_vm(struct mm_gk20a *mm, | |||
3465 | kref_init(&vm->ref); | 3532 | kref_init(&vm->ref); |
3466 | INIT_LIST_HEAD(&vm->reserved_va_list); | 3533 | INIT_LIST_HEAD(&vm->reserved_va_list); |
3467 | 3534 | ||
3535 | /* | ||
3536 | * This is only necessary for channel address spaces. The best way to | ||
3537 | * distinguish channel address spaces from other address spaces is by | ||
3538 | * size - if the address space is 4GB or less, it's not a channel. | ||
3539 | */ | ||
3540 | if (vm->va_limit > SZ_4G) { | ||
3541 | err = gk20a_init_sema_pool(vm); | ||
3542 | if (err) | ||
3543 | goto clean_up_big_allocator; | ||
3544 | } | ||
3545 | |||
3468 | return 0; | 3546 | return 0; |
3469 | 3547 | ||
3470 | clean_up_big_allocator: | 3548 | clean_up_big_allocator: |