diff --git a/common/inc/nv-mm.h b/common/inc/nv-mm.h index 919dacde86..70e284eacc 100644 --- a/common/inc/nv-mm.h +++ b/common/inc/nv-mm.h @@ -216,6 +216,16 @@ static inline void nv_vma_flags_clear_word(struct vm_area_struct *vma, unsigned ACCESS_PRIVATE(vma, __vm_flags) &= ~flags; #endif } + +static inline int nv_is_vma_write_locked(struct vm_area_struct *vma, unsigned int *mm_lock_seq) +{ +#if defined(NV_IS_VMA_WRITE_LOCKED_HAS_MM_LOCK_SEQ_ARG) + return __is_vma_write_locked(vma, mm_lock_seq); +#else + *mm_lock_seq = __vma_raw_mm_seqnum(vma); + return __is_vma_write_locked(vma); +#endif +} #endif // !NV_CAN_CALL_VMA_START_WRITE static inline void nv_vm_flags_set(struct vm_area_struct *vma, vm_flags_t flags) diff --git a/conftest.sh b/conftest.sh index 108df43651..6df97a5bea 100755 --- a/conftest.sh +++ b/conftest.sh @@ -5117,6 +5117,26 @@ compile_test() { compile_check_conftest "$CODE" "NV_DRM_CRTC_FUNCS_HAS_GET_VBLANK_TIMESTAMP" "" "types" ;; + is_vma_write_locked_has_mm_lock_seq_arg) + # + # Determine if __is_vma_write_locked() takes only a single + # 'struct vm_area_struct *' argument. + # + # Commit 22f7639f2f03 ("mm/vma: improve and document + # __is_vma_write_locked()") removed the 'unsigned int *mm_lock_seq' + # parameter in v7.0-rc1. + # + CODE=" + #include + #include + int conftest_is_vma_write_locked_has_mm_lock_seq_arg(struct vm_area_struct *vma) { + unsigned int mm_lock_seq; + return __is_vma_write_locked(vma, &mm_lock_seq); + }" + + compile_check_conftest "$CODE" "NV_IS_VMA_WRITE_LOCKED_HAS_MM_LOCK_SEQ_ARG" "" "types" + ;; + # When adding a new conftest entry, please use the correct format for # specifying the relevant upstream Linux kernel commit. Please # avoid specifying -rc kernels, and only use SHAs that actually exist diff --git a/nvidia/nv-mmap.c b/nvidia/nv-mmap.c index c518847c08..8a90f56e98 100644 --- a/nvidia/nv-mmap.c +++ b/nvidia/nv-mmap.c @@ -957,15 +957,22 @@ void NV_API_CALL nv_set_safe_to_mmap_locked( } #if !NV_CAN_CALL_VMA_START_WRITE + +#if defined(VM_REFCNT_EXCLUDE_READERS_FLAG) +#define NV_VMA_LOCK_OFFSET VM_REFCNT_EXCLUDE_READERS_FLAG +#else +#define NV_VMA_LOCK_OFFSET VMA_LOCK_OFFSET +#endif + static NvBool nv_vma_enter_locked(struct vm_area_struct *vma, NvBool detaching) { - NvU32 tgt_refcnt = VMA_LOCK_OFFSET; + NvU32 tgt_refcnt = NV_VMA_LOCK_OFFSET; NvBool interrupted = NV_FALSE; if (!detaching) { tgt_refcnt++; } - if (!refcount_add_not_zero(VMA_LOCK_OFFSET, &vma->vm_refcnt)) + if (!refcount_add_not_zero(NV_VMA_LOCK_OFFSET, &vma->vm_refcnt)) { return NV_FALSE; } @@ -995,7 +1002,7 @@ static NvBool nv_vma_enter_locked(struct vm_area_struct *vma, NvBool detaching) if (interrupted) { // Clean up on error: release refcount and dep_map - refcount_sub_and_test(VMA_LOCK_OFFSET, &vma->vm_refcnt); + refcount_sub_and_test(NV_VMA_LOCK_OFFSET, &vma->vm_refcnt); rwsem_release(&vma->vmlock_dep_map, _RET_IP_); return NV_FALSE; } @@ -1011,7 +1018,7 @@ void nv_vma_start_write(struct vm_area_struct *vma) { NvU32 mm_lock_seq; NvBool locked; - if (__is_vma_write_locked(vma, &mm_lock_seq)) + if (nv_is_vma_write_locked(vma, &mm_lock_seq)) return; locked = nv_vma_enter_locked(vma, NV_FALSE); @@ -1020,7 +1027,7 @@ void nv_vma_start_write(struct vm_area_struct *vma) if (locked) { NvBool detached; - detached = refcount_sub_and_test(VMA_LOCK_OFFSET, &vma->vm_refcnt); + detached = refcount_sub_and_test(NV_VMA_LOCK_OFFSET, &vma->vm_refcnt); rwsem_release(&vma->vmlock_dep_map, _RET_IP_); WARN_ON_ONCE(detached); }