mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 09:12:24 +03:00
gpu:nvgpu: fix the nvs mmap issues
- As part of mmap call handler mmap_sem is being acquired which is causing an BUG: scheduling while atomic:. This is happening because mmap callback gets called with mmap_sem held. The mmap file handler is called via call_mmap() via mmap_region() via do_mmap(), and the caller of do_mmap() must hold down_write(¤t->mm->mmap_sem). To fix this issue removing the mmap_sem locking from nvs mmap handler. - If remap_vmalloc_range() is used to map the pages to userspace then allocated pages should be mapped into virtually contiguous space by passing VM_USERMAP flag to vmap(). Passing VM_USERMAP to vmap() call if API nvgpu_dma_alloc_flags_sys() is called with flag NVGPU_DMA_VM_USERMAP_ADDRESS. Bug 3884011 Change-Id: I64264f6f6e0dd75b1f828dc58355d740e6ef5ccb Signed-off-by: prsethi <prsethi@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2820781 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
0e6c8bb521
commit
b4494a4b86
@@ -507,7 +507,8 @@ int nvgpu_nvs_buffer_alloc(struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl,
|
|||||||
(void)memset(buf, 0, sizeof(*buf));
|
(void)memset(buf, 0, sizeof(*buf));
|
||||||
buf->g = g;
|
buf->g = g;
|
||||||
|
|
||||||
err = nvgpu_dma_alloc_map_sys(system_vm, bytes, &buf->mem);
|
err = nvgpu_dma_alloc_map_flags_sys(system_vm,
|
||||||
|
NVGPU_DMA_VM_USERMAP_ADDRESS, bytes, &buf->mem);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
nvgpu_err(g, "failed to allocate memory for dma");
|
nvgpu_err(g, "failed to allocate memory for dma");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -62,6 +62,13 @@ struct nvgpu_mem;
|
|||||||
*/
|
*/
|
||||||
#define NVGPU_DMA_PHYSICALLY_ADDRESSED BIT64(2)
|
#define NVGPU_DMA_PHYSICALLY_ADDRESSED BIT64(2)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If remap_vmalloc_range() is used to map the pages to userspace then allocated
|
||||||
|
* pages should be mapped into virtually contiguous space by passing VM_USERMAP
|
||||||
|
* flag to vmap().
|
||||||
|
*/
|
||||||
|
#define NVGPU_DMA_VM_USERMAP_ADDRESS BIT64(3)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nvgpu_iommuable - Check if GPU is behind IOMMU
|
* nvgpu_iommuable - Check if GPU is behind IOMMU
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags,
|
|||||||
gfp_t gfps = GFP_KERNEL|__GFP_ZERO;
|
gfp_t gfps = GFP_KERNEL|__GFP_ZERO;
|
||||||
dma_addr_t iova;
|
dma_addr_t iova;
|
||||||
unsigned long dma_attrs = 0;
|
unsigned long dma_attrs = 0;
|
||||||
|
unsigned long vma_flags = 0;
|
||||||
void *alloc_ret;
|
void *alloc_ret;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@@ -309,8 +310,18 @@ int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags,
|
|||||||
|
|
||||||
/* Map the page list from the non-contiguous allocation */
|
/* Map the page list from the non-contiguous allocation */
|
||||||
if (nvgpu_nvlink_non_contig(g, flags)) {
|
if (nvgpu_nvlink_non_contig(g, flags)) {
|
||||||
|
/*
|
||||||
|
* If remap_vmalloc_range() is going to be used to map cpu_va to
|
||||||
|
* userspace then VM_USERMAP flag should be passed to vmap() to
|
||||||
|
* get appropriate cpu_va.
|
||||||
|
*/
|
||||||
|
if (flags & NVGPU_DMA_VM_USERMAP_ADDRESS) {
|
||||||
|
vma_flags |= VM_USERMAP;
|
||||||
|
}
|
||||||
|
|
||||||
mem->cpu_va = vmap(mem->priv.pages, size >> PAGE_SHIFT,
|
mem->cpu_va = vmap(mem->priv.pages, size >> PAGE_SHIFT,
|
||||||
0, PAGE_KERNEL);
|
vma_flags, PAGE_KERNEL);
|
||||||
|
|
||||||
if (!mem->cpu_va) {
|
if (!mem->cpu_va) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto fail_free_sgt;
|
goto fail_free_sgt;
|
||||||
@@ -365,12 +376,6 @@ int nvgpu_dma_mmap_sys(struct gk20a *g, struct vm_area_struct *vma, struct nvgpu
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
|
||||||
mmap_write_lock(vma->vm_mm);
|
|
||||||
#else
|
|
||||||
down_write(&vma->vm_mm->mmap_sem);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vma_exists = find_vma_intersection(vma->vm_mm, vma->vm_start, vma->vm_end);
|
vma_exists = find_vma_intersection(vma->vm_mm, vma->vm_start, vma->vm_end);
|
||||||
if (vma_exists != NULL) {
|
if (vma_exists != NULL) {
|
||||||
err = -EEXIST;
|
err = -EEXIST;
|
||||||
@@ -395,14 +400,9 @@ int nvgpu_dma_mmap_sys(struct gk20a *g, struct vm_area_struct *vma, struct nvgpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
|
||||||
mmap_write_unlock(vma->vm_mm);
|
|
||||||
#else
|
|
||||||
up_write(&vma->vm_mm->mmap_sem);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
nvgpu_err(g, "failed to map mem into userspace vma");
|
nvgpu_err(g, "failed to map mem into userspace vma %d", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
Reference in New Issue
Block a user