From c1b302652e37950fc8637db6e2bd3269a65e245e Mon Sep 17 00:00:00 2001
From: dt
Date: Wed, 26 May 2021 16:07:23 +0000
Subject: [PATCH] gpu: nvgpu: Add fix for dev_node leak
This is adding fix for dev_node leak when user_deinit
called.
The dev_nodes in linux are created in two phases. In first
phase the power dev_nodes(one for legacy and other for v2)
are created. The second phase other dev_nodes are created.
While creating the dev_nodes the power cdev_region overwritten
by cdev_region. This is fixed by introducing new cdev_region and
updating respective nodes.
JIRA NVGPU-6721
Change-Id: Iec78db8e5fe40cc0b14fb3fecc35b8881dff716f
Signed-off-by: dt
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2535265
Reviewed-by: Debarshi Dutta
Reviewed-by: svcacv
Reviewed-by: svc_kernel_abi
Reviewed-by: Lakshmanan M
Reviewed-by: Vaibhav Kachore
Reviewed-by: mobile promotions
GVS: Gerrit_Virtual_Submit
Tested-by: mobile promotions
---
drivers/gpu/nvgpu/os/linux/ioctl.c | 10 +++++++---
drivers/gpu/nvgpu/os/linux/os_linux.h | 2 ++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/nvgpu/os/linux/ioctl.c b/drivers/gpu/nvgpu/os/linux/ioctl.c
index e72944c91..ce7c43871 100644
--- a/drivers/gpu/nvgpu/os/linux/ioctl.c
+++ b/drivers/gpu/nvgpu/os/linux/ioctl.c
@@ -314,6 +314,10 @@ void gk20a_user_deinit(struct device *dev)
nvgpu_kfree(g, cdev);
}
+ if (l->power_cdev_region) {
+ unregister_chrdev_region(l->power_cdev_region, l->power_cdevs);
+ }
+
if (l->cdev_region) {
unregister_chrdev_region(l->cdev_region, l->num_cdevs);
l->num_cdevs = 0;
@@ -560,7 +564,7 @@ int gk20a_power_node_init(struct device *dev)
goto fail;
}
- l->cdev_region = devno;
+ l->power_cdev_region = devno;
nvgpu_list_for_each_entry(class, &l->class_list_head, nvgpu_class, list_entry) {
cdev = nvgpu_kzalloc(g, sizeof(*cdev));
if (cdev == NULL) {
@@ -586,7 +590,7 @@ int gk20a_power_node_init(struct device *dev)
nvgpu_list_add(&cdev->list_entry, &l->cdev_list_head);
}
- l->num_cdevs = total_cdevs;
+ l->power_cdevs = total_cdevs;
return 0;
fail:
gk20a_user_deinit(dev);
@@ -674,7 +678,7 @@ int gk20a_user_init(struct device *dev)
}
}
- l->num_cdevs += total_cdevs;
+ l->num_cdevs = total_cdevs;
return 0;
fail:
diff --git a/drivers/gpu/nvgpu/os/linux/os_linux.h b/drivers/gpu/nvgpu/os/linux/os_linux.h
index de84c3486..00444d0de 100644
--- a/drivers/gpu/nvgpu/os/linux/os_linux.h
+++ b/drivers/gpu/nvgpu/os/linux/os_linux.h
@@ -77,10 +77,12 @@ struct nvgpu_os_linux {
struct nvgpu_list_node class_list_head;
struct nvgpu_list_node cdev_list_head;
+ u32 power_cdevs;
u32 num_cdevs;
bool dev_nodes_created;
bool cdev_list_init_done;
+ dev_t power_cdev_region;
dev_t cdev_region;
/* see gk20a_ctrl_priv */