]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
gpu: nvgpu: recycle the cmdbuf instead of freeing after job done
authorSagar Kadamati <skadamati@nvidia.com>
Fri, 12 Feb 2016 11:45:34 +0000 (17:15 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Wed, 9 Mar 2016 10:06:03 +0000 (02:06 -0800)
When adding new job for the channel
Just check, is there any expired cmdbuf from prev jobs
If so simply use the exiting cmdbuf, instead of creating one
If not just create cmdbuf

All allocated cmdbuf's are freed on channel release

we mostly avoid dynamic allocations for cmdbuf

By using this way, we have advantages of both the worlds
So we gain performance in both (app startup and runtime)

Bug 1652936

Change-Id: Ia2d8441a728e5225ef3e1d3775bfae710c46f3d2
Signed-off-by: Sagar Kadamati <skadamati@nvidia.com>
Reviewed-on: http://git-master/r/1013178
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
drivers/gpu/nvgpu/gk20a/channel_gk20a.c
drivers/gpu/nvgpu/gk20a/mm_gk20a.h

index 2938317421df8a2839f779d389140d77190013c7..0c8bf77b01f2231a3bd9904edfc5b498b6f14810 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GK20A Graphics channel
  *
- * Copyright (c) 2011-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2011-2016, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -1161,6 +1161,8 @@ static int channel_gk20a_alloc_priv_cmdbuf(struct channel_gk20a *c)
 
        q->size = q->mem.size / sizeof (u32);
 
+       INIT_LIST_HEAD(&q->free);
+
        return 0;
 
 clean_up:
@@ -1172,12 +1174,21 @@ static void channel_gk20a_free_priv_cmdbuf(struct channel_gk20a *c)
 {
        struct vm_gk20a *ch_vm = c->vm;
        struct priv_cmd_queue *q = &c->priv_cmd_q;
+       struct priv_cmd_entry *e;
+       struct list_head *pos, *tmp, *head;
 
        if (q->size == 0)
                return;
 
        gk20a_gmmu_unmap_free(ch_vm, &q->mem);
 
+       /* free free list */
+       head = &q->free;
+       list_for_each_safe(pos, tmp, head) {
+               e = container_of(pos, struct priv_cmd_entry, list);
+               kfree(e);
+       }
+
        memset(q, 0, sizeof(struct priv_cmd_queue));
 }
 
@@ -1207,7 +1218,13 @@ int gk20a_channel_alloc_priv_cmdbuf(struct channel_gk20a *c, u32 orig_size,
        if (size > free_count)
                return -EAGAIN;
 
-       e = kzalloc(sizeof(struct priv_cmd_entry), GFP_KERNEL);
+       if (list_empty(&q->free))
+               e = kzalloc(sizeof(struct priv_cmd_entry), GFP_KERNEL);
+       else {
+               e = container_of((&q->free)->next,
+                                struct priv_cmd_entry, list);
+               list_del(&e->list);
+       }
        if (!e) {
                gk20a_err(dev_from_gk20a(c->g),
                        "ch %d: fail to allocate priv cmd entry",
@@ -1247,7 +1264,9 @@ int gk20a_channel_alloc_priv_cmdbuf(struct channel_gk20a *c, u32 orig_size,
 static void free_priv_cmdbuf(struct channel_gk20a *c,
                             struct priv_cmd_entry *e)
 {
-       kfree(e);
+       struct priv_cmd_queue *q = &c->priv_cmd_q;
+
+       list_add(&e->list, &q->free);
 }
 
 int gk20a_alloc_channel_gpfifo(struct channel_gk20a *c,
index 18fa415c10b0e0c3240c87197c7c5fbf00f9b95e..48dfaa7cca512921136af8fc8c023c7ff244452e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GK20A memory management
  *
- * Copyright (c) 2011-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2011-2016, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -156,6 +156,7 @@ struct priv_cmd_queue {
        u32 size;       /* num of entries in words */
        u32 put;        /* put for priv cmd queue */
        u32 get;        /* get for priv cmd queue */
+       struct list_head free;  /* list of buffered entries */
 };
 
 struct priv_cmd_entry {