diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/vidmem.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/vidmem.c | 43 |
1 files changed, 20 insertions, 23 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/vidmem.c b/drivers/gpu/nvgpu/common/linux/vidmem.c index ea8e552f..92e7e504 100644 --- a/drivers/gpu/nvgpu/common/linux/vidmem.c +++ b/drivers/gpu/nvgpu/common/linux/vidmem.c | |||
@@ -84,6 +84,8 @@ static void gk20a_vidbuf_release(struct dma_buf *dmabuf) | |||
84 | 84 | ||
85 | nvgpu_kfree(g, linux_buf); | 85 | nvgpu_kfree(g, linux_buf); |
86 | nvgpu_vidmem_buf_free(g, buf); | 86 | nvgpu_vidmem_buf_free(g, buf); |
87 | |||
88 | gk20a_put(g); | ||
87 | } | 89 | } |
88 | 90 | ||
89 | static void *gk20a_vidbuf_kmap(struct dma_buf *dmabuf, unsigned long page_num) | 91 | static void *gk20a_vidbuf_kmap(struct dma_buf *dmabuf, unsigned long page_num) |
@@ -160,13 +162,21 @@ struct gk20a *nvgpu_vidmem_buf_owner(struct dma_buf *dmabuf) | |||
160 | 162 | ||
161 | int nvgpu_vidmem_export_linux(struct gk20a *g, size_t bytes) | 163 | int nvgpu_vidmem_export_linux(struct gk20a *g, size_t bytes) |
162 | { | 164 | { |
163 | struct nvgpu_vidmem_buf *buf; | 165 | struct nvgpu_vidmem_buf *buf = NULL; |
164 | struct nvgpu_vidmem_linux *priv; | 166 | struct nvgpu_vidmem_linux *priv; |
165 | int err, fd; | 167 | int err, fd; |
166 | 168 | ||
169 | /* | ||
170 | * This ref is released when the dma_buf is closed. | ||
171 | */ | ||
172 | if (!gk20a_get(g)) | ||
173 | return -ENODEV; | ||
174 | |||
167 | priv = nvgpu_kzalloc(g, sizeof(*priv)); | 175 | priv = nvgpu_kzalloc(g, sizeof(*priv)); |
168 | if (!priv) | 176 | if (!priv) { |
169 | return -ENOMEM; | 177 | err = -ENOMEM; |
178 | goto fail; | ||
179 | } | ||
170 | 180 | ||
171 | buf = nvgpu_vidmem_user_alloc(g, bytes); | 181 | buf = nvgpu_vidmem_user_alloc(g, bytes); |
172 | if (!buf) { | 182 | if (!buf) { |
@@ -195,8 +205,10 @@ int nvgpu_vidmem_export_linux(struct gk20a *g, size_t bytes) | |||
195 | return fd; | 205 | return fd; |
196 | 206 | ||
197 | fail: | 207 | fail: |
198 | nvgpu_kfree(g, priv); | ||
199 | nvgpu_vidmem_buf_free(g, buf); | 208 | nvgpu_vidmem_buf_free(g, buf); |
209 | nvgpu_kfree(g, priv); | ||
210 | gk20a_put(g); | ||
211 | |||
200 | return err; | 212 | return err; |
201 | } | 213 | } |
202 | 214 | ||
@@ -229,24 +241,9 @@ int nvgpu_vidmem_buf_access_memory(struct gk20a *g, struct dma_buf *dmabuf, | |||
229 | return err; | 241 | return err; |
230 | } | 242 | } |
231 | 243 | ||
232 | void nvgpu_vidmem_clear_mem_worker(struct work_struct *work) | 244 | void __nvgpu_mem_free_vidmem_alloc(struct gk20a *g, struct nvgpu_mem *vidmem) |
233 | { | 245 | { |
234 | struct mm_gk20a *mm = container_of(work, struct mm_gk20a, | 246 | nvgpu_free(vidmem->allocator, |
235 | vidmem.clear_mem_worker); | 247 | (u64)nvgpu_vidmem_get_page_alloc(vidmem->priv.sgt->sgl)); |
236 | struct gk20a *g = mm->g; | 248 | nvgpu_free_sgtable(g, &vidmem->priv.sgt); |
237 | struct nvgpu_mem *mem; | ||
238 | |||
239 | while ((mem = nvgpu_vidmem_get_pending_alloc(mm)) != NULL) { | ||
240 | nvgpu_vidmem_clear(g, mem); | ||
241 | nvgpu_free(mem->allocator, | ||
242 | (u64)nvgpu_vidmem_get_page_alloc(mem->priv.sgt->sgl)); | ||
243 | nvgpu_free_sgtable(g, &mem->priv.sgt); | ||
244 | |||
245 | WARN_ON(nvgpu_atomic64_sub_return(mem->aligned_size, | ||
246 | &g->mm.vidmem.bytes_pending) < 0); | ||
247 | mem->size = 0; | ||
248 | mem->aperture = APERTURE_INVALID; | ||
249 | |||
250 | nvgpu_kfree(g, mem); | ||
251 | } | ||
252 | } | 249 | } |