diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/dma.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/dma.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/dma.c b/drivers/gpu/nvgpu/common/linux/dma.c index c111d22b..53e54bc6 100644 --- a/drivers/gpu/nvgpu/common/linux/dma.c +++ b/drivers/gpu/nvgpu/common/linux/dma.c | |||
@@ -227,6 +227,16 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, | |||
227 | } | 227 | } |
228 | 228 | ||
229 | /* | 229 | /* |
230 | * WAR for IO coherent chips: the DMA API does not seem to generate | ||
231 | * mappings that work correctly. Unclear why - Bug ID: 2040115. | ||
232 | * | ||
233 | * Basically we just tell the DMA API not to map with NO_KERNEL_MAPPING | ||
234 | * and then make a vmap() ourselves. | ||
235 | */ | ||
236 | if (nvgpu_is_enabled(g, NVGPU_USE_COHERENT_SYSMEM)) | ||
237 | flags |= NVGPU_DMA_NO_KERNEL_MAPPING; | ||
238 | |||
239 | /* | ||
230 | * Before the debug print so we see this in the total. But during | 240 | * Before the debug print so we see this in the total. But during |
231 | * cleanup in the fail path this has to be subtracted. | 241 | * cleanup in the fail path this has to be subtracted. |
232 | */ | 242 | */ |
@@ -260,7 +270,17 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, | |||
260 | iova, size, flags); | 270 | iova, size, flags); |
261 | } | 271 | } |
262 | if (err) | 272 | if (err) |
263 | goto fail_free; | 273 | goto fail_free_dma; |
274 | |||
275 | if (nvgpu_is_enabled(g, NVGPU_USE_COHERENT_SYSMEM)) { | ||
276 | mem->cpu_va = vmap(mem->priv.pages, | ||
277 | size >> PAGE_SHIFT, | ||
278 | 0, PAGE_KERNEL); | ||
279 | if (!mem->cpu_va) { | ||
280 | err = -ENOMEM; | ||
281 | goto fail_free_sgt; | ||
282 | } | ||
283 | } | ||
264 | 284 | ||
265 | mem->aligned_size = size; | 285 | mem->aligned_size = size; |
266 | mem->aperture = APERTURE_SYSMEM; | 286 | mem->aperture = APERTURE_SYSMEM; |
@@ -270,12 +290,14 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, | |||
270 | 290 | ||
271 | return 0; | 291 | return 0; |
272 | 292 | ||
273 | fail_free: | 293 | fail_free_sgt: |
274 | g->dma_memory_used -= mem->aligned_size; | 294 | nvgpu_free_sgtable(g, &mem->priv.sgt); |
295 | fail_free_dma: | ||
275 | dma_free_attrs(d, size, alloc_ret, iova, NVGPU_DMA_ATTR(dma_attrs)); | 296 | dma_free_attrs(d, size, alloc_ret, iova, NVGPU_DMA_ATTR(dma_attrs)); |
276 | mem->cpu_va = NULL; | 297 | mem->cpu_va = NULL; |
277 | mem->priv.sgt = NULL; | 298 | mem->priv.sgt = NULL; |
278 | mem->size = 0; | 299 | mem->size = 0; |
300 | g->dma_memory_used -= mem->aligned_size; | ||
279 | return err; | 301 | return err; |
280 | } | 302 | } |
281 | 303 | ||
@@ -476,6 +498,12 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem) | |||
476 | if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) && | 498 | if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) && |
477 | !(mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) && | 499 | !(mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) && |
478 | (mem->cpu_va || mem->priv.pages)) { | 500 | (mem->cpu_va || mem->priv.pages)) { |
501 | /* | ||
502 | * Free side of WAR for bug 2040115. | ||
503 | */ | ||
504 | if (nvgpu_is_enabled(g, NVGPU_USE_COHERENT_SYSMEM)) | ||
505 | vunmap(mem->cpu_va); | ||
506 | |||
479 | if (mem->priv.flags) { | 507 | if (mem->priv.flags) { |
480 | NVGPU_DEFINE_DMA_ATTRS(dma_attrs); | 508 | NVGPU_DEFINE_DMA_ATTRS(dma_attrs); |
481 | 509 | ||