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 c13dae8b..81aebb7d 100644 --- a/drivers/gpu/nvgpu/common/linux/dma.c +++ b/drivers/gpu/nvgpu/common/linux/dma.c | |||
@@ -222,6 +222,16 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, | |||
222 | void *alloc_ret; | 222 | void *alloc_ret; |
223 | 223 | ||
224 | /* | 224 | /* |
225 | * WAR for IO coherent chips: the DMA API does not seem to generate | ||
226 | * mappings that work correctly. Unclear why - Bug ID: 2040115. | ||
227 | * | ||
228 | * Basically we just tell the DMA API not to map with NO_KERNEL_MAPPING | ||
229 | * and then make a vmap() ourselves. | ||
230 | */ | ||
231 | if (nvgpu_is_enabled(g, NVGPU_USE_COHERENT_SYSMEM)) | ||
232 | flags |= NVGPU_DMA_NO_KERNEL_MAPPING; | ||
233 | |||
234 | /* | ||
225 | * Before the debug print so we see this in the total. But during | 235 | * Before the debug print so we see this in the total. But during |
226 | * cleanup in the fail path this has to be subtracted. | 236 | * cleanup in the fail path this has to be subtracted. |
227 | */ | 237 | */ |
@@ -255,7 +265,17 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, | |||
255 | iova, size, flags); | 265 | iova, size, flags); |
256 | } | 266 | } |
257 | if (err) | 267 | if (err) |
258 | goto fail_free; | 268 | goto fail_free_dma; |
269 | |||
270 | if (nvgpu_is_enabled(g, NVGPU_USE_COHERENT_SYSMEM)) { | ||
271 | mem->cpu_va = vmap(mem->priv.pages, | ||
272 | size >> PAGE_SHIFT, | ||
273 | 0, PAGE_KERNEL); | ||
274 | if (!mem->cpu_va) { | ||
275 | err = -ENOMEM; | ||
276 | goto fail_free_sgt; | ||
277 | } | ||
278 | } | ||
259 | 279 | ||
260 | mem->aligned_size = size; | 280 | mem->aligned_size = size; |
261 | mem->aperture = APERTURE_SYSMEM; | 281 | mem->aperture = APERTURE_SYSMEM; |
@@ -265,12 +285,14 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, | |||
265 | 285 | ||
266 | return 0; | 286 | return 0; |
267 | 287 | ||
268 | fail_free: | 288 | fail_free_sgt: |
269 | g->dma_memory_used -= mem->aligned_size; | 289 | nvgpu_free_sgtable(g, &mem->priv.sgt); |
290 | fail_free_dma: | ||
270 | dma_free_attrs(d, size, alloc_ret, iova, NVGPU_DMA_ATTR(dma_attrs)); | 291 | dma_free_attrs(d, size, alloc_ret, iova, NVGPU_DMA_ATTR(dma_attrs)); |
271 | mem->cpu_va = NULL; | 292 | mem->cpu_va = NULL; |
272 | mem->priv.sgt = NULL; | 293 | mem->priv.sgt = NULL; |
273 | mem->size = 0; | 294 | mem->size = 0; |
295 | g->dma_memory_used -= mem->aligned_size; | ||
274 | return err; | 296 | return err; |
275 | } | 297 | } |
276 | 298 | ||
@@ -466,6 +488,12 @@ static void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem) | |||
466 | if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) && | 488 | if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) && |
467 | !(mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) && | 489 | !(mem->mem_flags & __NVGPU_MEM_FLAG_NO_DMA) && |
468 | (mem->cpu_va || mem->priv.pages)) { | 490 | (mem->cpu_va || mem->priv.pages)) { |
491 | /* | ||
492 | * Free side of WAR for bug 2040115. | ||
493 | */ | ||
494 | if (nvgpu_is_enabled(g, NVGPU_USE_COHERENT_SYSMEM)) | ||
495 | vunmap(mem->cpu_va); | ||
496 | |||
469 | if (mem->priv.flags) { | 497 | if (mem->priv.flags) { |
470 | NVGPU_DEFINE_DMA_ATTRS(dma_attrs); | 498 | NVGPU_DEFINE_DMA_ATTRS(dma_attrs); |
471 | 499 | ||