From b34e2f9554c31e2e49899979cfbdd4ea1ee906b0 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 10 Oct 2024 10:16:07 +0100 Subject: [PATCH] video: tegra: nvmap: Fix f_count for Linux v6.13 In Linux v6.13, 'f_count' has been replaced by 'f_ref' in the 'file' structure. Use conftest to detect if 'f_ref' is present and update the NVMAP driver accordingly. Please note that in most cases we can simply use the 'file_count' macro for getting the count and this has been supported since Linux v2.6. Bug 4991705 Change-Id: I3ccaf88bd6c3dca5b364205cf03a577945f62092 Signed-off-by: Jon Hunter Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3260939 Tested-by: mobile promotions Reviewed-by: mobile promotions GVS: buildbot_gerritrpt Reviewed-by: Ketan Patil Reviewed-by: svcacv --- drivers/video/tegra/nvmap/nvmap_handle.c | 6 +++++- drivers/video/tegra/nvmap/nvmap_ioctl.c | 12 ++++++------ drivers/video/tegra/nvmap/nvmap_sci_ipc.c | 2 +- scripts/conftest/Makefile | 1 + scripts/conftest/conftest.sh | 16 ++++++++++++++++ 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index eaa42527..8fa93bef 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -495,7 +495,11 @@ found: goto fail; BUG_ON(!h->dmabuf->file); /* This is same as get_dma_buf() if file->f_count was non-zero */ +#if defined(NV_FILE_STRUCT_HAS_F_REF) /* Linux v6.13 */ + if (file_ref_get(&h->dmabuf->file->f_ref) == 0) +#else if (atomic_long_inc_not_zero(&h->dmabuf->file->f_count) == 0) +#endif goto fail; mutex_unlock(&h->lock); @@ -788,7 +792,7 @@ void nvmap_free_handle_from_fd(struct nvmap_client *client, mutex_lock(&handle->lock); dmabuf = is_ro ? handle->dmabuf_ro : handle->dmabuf; if (dmabuf && dmabuf->file) { - dmabuf_ref = atomic_long_read(&dmabuf->file->f_count); + dmabuf_ref = file_count(dmabuf->file); } else { dmabuf_ref = 0; } diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c index d58a9fa8..ed176edd 100644 --- a/drivers/video/tegra/nvmap/nvmap_ioctl.c +++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c @@ -94,7 +94,7 @@ int nvmap_ioctl_getfd(struct file *filp, void __user *arg) if (!ret && !IS_ERR_OR_NULL(handle)) { mutex_lock(&handle->lock); if (dmabuf && dmabuf->file) { - dmabuf_ref = atomic_long_read(&dmabuf->file->f_count); + dmabuf_ref = file_count(dmabuf->file); } else { dmabuf_ref = 0; } @@ -171,7 +171,7 @@ alloc_op_done: mutex_lock(&handle->lock); dmabuf = is_ro ? handle->dmabuf_ro : handle->dmabuf; if (dmabuf && dmabuf->file) { - dmabuf_ref = atomic_long_read(&dmabuf->file->f_count); + dmabuf_ref = file_count(dmabuf->file); } else { dmabuf_ref = 0; } @@ -313,7 +313,7 @@ out: if (!ret && !IS_ERR_OR_NULL(handle)) { mutex_lock(&handle->lock); if (dmabuf && dmabuf->file) { - dmabuf_ref = atomic_long_read(&dmabuf->file->f_count); + dmabuf_ref = file_count(dmabuf->file); } else { dmabuf_ref = 0; } @@ -411,7 +411,7 @@ out: if (!err) { mutex_lock(&handle->lock); if (dmabuf && dmabuf->file) { - dmabuf_ref = atomic_long_read(&dmabuf->file->f_count); + dmabuf_ref = file_count(dmabuf->file); } else { dmabuf_ref = 0; } @@ -1052,7 +1052,7 @@ exit: mutex_lock(&handle->lock); dmabuf = is_ro ? handle->dmabuf_ro : handle->dmabuf; if (dmabuf && dmabuf->file) { - dmabuf_ref = atomic_long_read(&dmabuf->file->f_count); + dmabuf_ref = file_count(dmabuf->file); } else { dmabuf_ref = 0; } @@ -1238,7 +1238,7 @@ out: if (!ret && !IS_ERR_OR_NULL(handle)) trace_refcount_dup_handle(handle, dmabuf, atomic_read(&handle->ref), - atomic_long_read(&dmabuf->file->f_count), + file_count(dmabuf->file), is_ro ? "RO" : "RW"); if (!IS_ERR(ref)) diff --git a/drivers/video/tegra/nvmap/nvmap_sci_ipc.c b/drivers/video/tegra/nvmap/nvmap_sci_ipc.c index ca87650c..a06f3ed9 100644 --- a/drivers/video/tegra/nvmap/nvmap_sci_ipc.c +++ b/drivers/video/tegra/nvmap/nvmap_sci_ipc.c @@ -350,7 +350,7 @@ unlock: if (!ret) { mutex_lock(&h->lock); if (dmabuf && dmabuf->file) { - dmabuf_ref = atomic_long_read(&dmabuf->file->f_count); + dmabuf_ref = file_count(dmabuf->file); } else { dmabuf_ref = 0; } diff --git a/scripts/conftest/Makefile b/scripts/conftest/Makefile index b9888a60..6f3e1a5f 100644 --- a/scripts/conftest/Makefile +++ b/scripts/conftest/Makefile @@ -128,6 +128,7 @@ NV_CONFTEST_FUNCTION_COMPILE_TESTS += ethtool_ops_get_set_ringparam_has_ringpara NV_CONFTEST_FUNCTION_COMPILE_TESTS += ethtool_ops_get_set_rxfh_has_rxfh_param_args NV_CONFTEST_FUNCTION_COMPILE_TESTS += fd_empty NV_CONFTEST_FUNCTION_COMPILE_TESTS += fd_file +NV_CONFTEST_FUNCTION_COMPILE_TESTS += file_struct_has_f_ref NV_CONFTEST_FUNCTION_COMPILE_TESTS += folio_entire_mapcount NV_CONFTEST_FUNCTION_COMPILE_TESTS += genpd_xlate_t_has_const_of_phandle_args NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_file_rcu_has_double_ptr_file_arg diff --git a/scripts/conftest/conftest.sh b/scripts/conftest/conftest.sh index e6a5e8a7..ee10573e 100755 --- a/scripts/conftest/conftest.sh +++ b/scripts/conftest/conftest.sh @@ -7280,6 +7280,22 @@ compile_test() { compile_check_conftest "$CODE" "NV_FD_FILE_PRESENT" "" "functions" ;; + file_struct_has_f_ref) + # + # Determine if 'struct file' has the 'f_ref' member. + # + # Commit 90ee6ed776c0 ("fs: port files to file_ref") replaced the + # 'f_count' member of 'struct file' with 'f_ref' in Linux v6.13. + # + CODE=" + #include + int conftest_file_struct_has_f_ref(void) { + return offsetof(struct file, f_ref); + }" + + compile_check_conftest "$CODE" "NV_FILE_STRUCT_HAS_F_REF" "" "types" + ;; + folio_entire_mapcount) # # Determine if function folio_entire_mapcount() is present.