From 733fb79b39869665addcd80ccdf1c15f4a5aaa29 Mon Sep 17 00:00:00 2001 From: Sachit Kadle Date: Mon, 15 Aug 2016 14:32:39 -0700 Subject: gpu: nvgpu: add support for pre-allocated resources Add support for pre-allocation of job tracking resources w/ new (extended) ioctl. Goal is to avoid dynamic memory allocation in the submit path. This patch does the following: 1) Intoduces a new ioctl, NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX, which enables pre-allocation of tracking resources per job: a) 2x priv_cmd_entry b) 2x gk20a_fence 2) Implements circular ring buffer for job tracking to avoid lock contention between producer (submitter) and consumer (clean-up) Bug 1795076 Change-Id: I6b52e5c575871107ff380f9a5790f440a6969347 Signed-off-by: Sachit Kadle Reviewed-on: http://git-master/r/1203300 (cherry picked from commit 9fd270c22b860935dffe244753dabd87454bef39) Reviewed-on: http://git-master/r/1223934 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gk20a/fence_gk20a.c | 70 +++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a/fence_gk20a.c') diff --git a/drivers/gpu/nvgpu/gk20a/fence_gk20a.c b/drivers/gpu/nvgpu/gk20a/fence_gk20a.c index f788829f..c11d363e 100644 --- a/drivers/gpu/nvgpu/gk20a/fence_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fence_gk20a.c @@ -47,7 +47,12 @@ static void gk20a_fence_free(struct kref *ref) #endif if (f->semaphore) gk20a_semaphore_put(f->semaphore); - kfree(f); + + if (f->allocator) { + if (gk20a_alloc_initialized(f->allocator)) + gk20a_free(f->allocator, (u64)f); + } else + kfree(f); } void gk20a_fence_put(struct gk20a_fence *f) @@ -109,15 +114,66 @@ int gk20a_fence_install_fd(struct gk20a_fence *f) #endif } -struct gk20a_fence *gk20a_alloc_fence(struct channel_gk20a *c) +int gk20a_alloc_fence_pool(struct channel_gk20a *c, int count) +{ + int err; + size_t size; + struct gk20a_fence *fence_pool = NULL; + + size = sizeof(struct gk20a_fence); + if (count <= ULONG_MAX / size) { + size = count * size; + fence_pool = vzalloc(size); + } + + if (!fence_pool) + return -ENOMEM; + + err = gk20a_lockless_allocator_init(&c->fence_allocator, + "fence_pool", (u64)fence_pool, size, + sizeof(struct gk20a_fence), 0); + if (err) + goto fail; + + return 0; + +fail: + vfree(fence_pool); + return err; +} + +void gk20a_free_fence_pool(struct channel_gk20a *c) { - struct gk20a_fence *fence; + if (gk20a_alloc_initialized(&c->fence_allocator)) { + void *base = (void *)gk20a_alloc_base(&c->fence_allocator); + + gk20a_alloc_destroy(&c->fence_allocator); + vfree(base); + } +} - fence = kzalloc(sizeof(struct gk20a_fence), GFP_KERNEL); - if (!fence) - return NULL; +struct gk20a_fence *gk20a_alloc_fence(struct channel_gk20a *c) +{ + struct gk20a_fence *fence = NULL; + + if (channel_gk20a_is_prealloc_enabled(c)) { + if (gk20a_alloc_initialized(&c->fence_allocator)) { + fence = (struct gk20a_fence *) + gk20a_alloc(&c->fence_allocator, + sizeof(struct gk20a_fence)); + + /* clear the node and reset the allocator pointer */ + if (fence) { + memset(fence, 0, sizeof(*fence)); + fence->allocator = &c->fence_allocator; + } + } + } else + fence = kzalloc(sizeof(struct gk20a_fence), GFP_KERNEL); + + if (fence) + kref_init(&fence->ref); - kref_init(&fence->ref); return fence; } -- cgit v1.2.2