diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/fence_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fence_gk20a.c | 70 |
1 files changed, 63 insertions, 7 deletions
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) | |||
47 | #endif | 47 | #endif |
48 | if (f->semaphore) | 48 | if (f->semaphore) |
49 | gk20a_semaphore_put(f->semaphore); | 49 | gk20a_semaphore_put(f->semaphore); |
50 | kfree(f); | 50 | |
51 | if (f->allocator) { | ||
52 | if (gk20a_alloc_initialized(f->allocator)) | ||
53 | gk20a_free(f->allocator, (u64)f); | ||
54 | } else | ||
55 | kfree(f); | ||
51 | } | 56 | } |
52 | 57 | ||
53 | void gk20a_fence_put(struct gk20a_fence *f) | 58 | void gk20a_fence_put(struct gk20a_fence *f) |
@@ -109,15 +114,66 @@ int gk20a_fence_install_fd(struct gk20a_fence *f) | |||
109 | #endif | 114 | #endif |
110 | } | 115 | } |
111 | 116 | ||
112 | struct gk20a_fence *gk20a_alloc_fence(struct channel_gk20a *c) | 117 | int gk20a_alloc_fence_pool(struct channel_gk20a *c, int count) |
118 | { | ||
119 | int err; | ||
120 | size_t size; | ||
121 | struct gk20a_fence *fence_pool = NULL; | ||
122 | |||
123 | size = sizeof(struct gk20a_fence); | ||
124 | if (count <= ULONG_MAX / size) { | ||
125 | size = count * size; | ||
126 | fence_pool = vzalloc(size); | ||
127 | } | ||
128 | |||
129 | if (!fence_pool) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | err = gk20a_lockless_allocator_init(&c->fence_allocator, | ||
133 | "fence_pool", (u64)fence_pool, size, | ||
134 | sizeof(struct gk20a_fence), 0); | ||
135 | if (err) | ||
136 | goto fail; | ||
137 | |||
138 | return 0; | ||
139 | |||
140 | fail: | ||
141 | vfree(fence_pool); | ||
142 | return err; | ||
143 | } | ||
144 | |||
145 | void gk20a_free_fence_pool(struct channel_gk20a *c) | ||
113 | { | 146 | { |
114 | struct gk20a_fence *fence; | 147 | if (gk20a_alloc_initialized(&c->fence_allocator)) { |
148 | void *base = (void *)gk20a_alloc_base(&c->fence_allocator); | ||
149 | |||
150 | gk20a_alloc_destroy(&c->fence_allocator); | ||
151 | vfree(base); | ||
152 | } | ||
153 | } | ||
115 | 154 | ||
116 | fence = kzalloc(sizeof(struct gk20a_fence), GFP_KERNEL); | 155 | struct gk20a_fence *gk20a_alloc_fence(struct channel_gk20a *c) |
117 | if (!fence) | 156 | { |
118 | return NULL; | 157 | struct gk20a_fence *fence = NULL; |
158 | |||
159 | if (channel_gk20a_is_prealloc_enabled(c)) { | ||
160 | if (gk20a_alloc_initialized(&c->fence_allocator)) { | ||
161 | fence = (struct gk20a_fence *) | ||
162 | gk20a_alloc(&c->fence_allocator, | ||
163 | sizeof(struct gk20a_fence)); | ||
164 | |||
165 | /* clear the node and reset the allocator pointer */ | ||
166 | if (fence) { | ||
167 | memset(fence, 0, sizeof(*fence)); | ||
168 | fence->allocator = &c->fence_allocator; | ||
169 | } | ||
170 | } | ||
171 | } else | ||
172 | fence = kzalloc(sizeof(struct gk20a_fence), GFP_KERNEL); | ||
173 | |||
174 | if (fence) | ||
175 | kref_init(&fence->ref); | ||
119 | 176 | ||
120 | kref_init(&fence->ref); | ||
121 | return fence; | 177 | return fence; |
122 | } | 178 | } |
123 | 179 | ||