mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 09:12:24 +03:00
gpu: nvgpu: expose device creation
Allow gk20a_create_device() to happen outside the main ioctl logic and rename it to have the modern nvgpu_ prefix. Add a separate function to do cdev allocation and refactor the existing two callers slightly to avoid repetition on the cdev struct initialization. As a side effect, this modification fixes the error path that used to not return an error if adding a device fails and also leaked the allocated cdev memory. Jira NVGPU-6788 Change-Id: Ia1f018b88d78fafdfcf4e95f6aa66e2368e58974 Signed-off-by: Konsta Hölttä <kholtta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2674426 Reviewed-by: Alex Waterman <alexw@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
mobile promotions
parent
82df5b0219
commit
f11ca4c300
@@ -251,11 +251,10 @@ static char *nvgpu_mig_fgpu_devnode(struct device *dev, umode_t *mode)
|
|||||||
priv_data->minor_instance_id, dev_name(dev));
|
priv_data->minor_instance_id, dev_name(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gk20a_create_device(
|
int nvgpu_create_device(
|
||||||
struct device *dev, int devno,
|
struct device *dev, int devno,
|
||||||
const char *cdev_name,
|
const char *cdev_name,
|
||||||
struct cdev *cdev, struct device **out,
|
struct cdev *cdev, struct device **out,
|
||||||
const struct file_operations *ops,
|
|
||||||
struct nvgpu_class *class)
|
struct nvgpu_class *class)
|
||||||
{
|
{
|
||||||
struct device *subdev;
|
struct device *subdev;
|
||||||
@@ -265,9 +264,6 @@ static int gk20a_create_device(
|
|||||||
|
|
||||||
nvgpu_log_fn(g, " ");
|
nvgpu_log_fn(g, " ");
|
||||||
|
|
||||||
cdev_init(cdev, ops);
|
|
||||||
cdev->owner = THIS_MODULE;
|
|
||||||
|
|
||||||
err = cdev_add(cdev, devno, 1);
|
err = cdev_add(cdev, devno, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(dev, "failed to add %s cdev\n", cdev_name);
|
dev_err(dev, "failed to add %s cdev\n", cdev_name);
|
||||||
@@ -297,6 +293,45 @@ static int gk20a_create_device(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nvgpu_alloc_and_create_device(
|
||||||
|
struct device *dev, int devno,
|
||||||
|
const char *cdev_name,
|
||||||
|
const struct file_operations *ops,
|
||||||
|
struct nvgpu_class *class)
|
||||||
|
{
|
||||||
|
struct gk20a *g = gk20a_from_dev(dev);
|
||||||
|
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
|
||||||
|
struct nvgpu_cdev *cdev;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
cdev = nvgpu_kzalloc(g, sizeof(*cdev));
|
||||||
|
if (cdev == NULL) {
|
||||||
|
dev_err(dev, "failed to allocate cdev\n");
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdev_init(&cdev->cdev, ops);
|
||||||
|
cdev->cdev.owner = THIS_MODULE;
|
||||||
|
|
||||||
|
err = nvgpu_create_device(dev, devno, cdev_name,
|
||||||
|
&cdev->cdev, &cdev->node, class);
|
||||||
|
if (err) {
|
||||||
|
goto free_cdev;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdev->class = class;
|
||||||
|
nvgpu_init_list_node(&cdev->list_entry);
|
||||||
|
nvgpu_list_add(&cdev->list_entry, &l->cdev_list_head);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
free_cdev:
|
||||||
|
nvgpu_kfree(g, cdev);
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
void gk20a_remove_devices_and_classes(struct gk20a *g, bool power_node)
|
void gk20a_remove_devices_and_classes(struct gk20a *g, bool power_node)
|
||||||
{
|
{
|
||||||
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
|
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
|
||||||
@@ -568,7 +603,6 @@ int gk20a_power_node_init(struct device *dev)
|
|||||||
struct nvgpu_class *class;
|
struct nvgpu_class *class;
|
||||||
u32 total_cdevs;
|
u32 total_cdevs;
|
||||||
u32 num_classes;
|
u32 num_classes;
|
||||||
struct nvgpu_cdev *cdev;
|
|
||||||
|
|
||||||
if (!l->cdev_list_init_done) {
|
if (!l->cdev_list_init_done) {
|
||||||
nvgpu_init_list_node(&l->cdev_list_head);
|
nvgpu_init_list_node(&l->cdev_list_head);
|
||||||
@@ -591,28 +625,17 @@ int gk20a_power_node_init(struct device *dev)
|
|||||||
|
|
||||||
l->power_cdev_region = devno;
|
l->power_cdev_region = devno;
|
||||||
nvgpu_list_for_each_entry(class, &l->class_list_head, nvgpu_class, list_entry) {
|
nvgpu_list_for_each_entry(class, &l->class_list_head, nvgpu_class, list_entry) {
|
||||||
cdev = nvgpu_kzalloc(g, sizeof(*cdev));
|
|
||||||
if (cdev == NULL) {
|
|
||||||
dev_err(dev, "failed to allocate cdev\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dev_node_list[0] is the power node to issue
|
* dev_node_list[0] is the power node to issue
|
||||||
* power-on to the GPU.
|
* power-on to the GPU.
|
||||||
*/
|
*/
|
||||||
err = gk20a_create_device(dev, devno++,
|
err = nvgpu_alloc_and_create_device(dev, devno++,
|
||||||
dev_node_list[0].name,
|
dev_node_list[0].name,
|
||||||
&cdev->cdev, &cdev->node,
|
|
||||||
dev_node_list[0].fops,
|
dev_node_list[0].fops,
|
||||||
class);
|
class);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdev->class = class;
|
|
||||||
nvgpu_init_list_node(&cdev->list_entry);
|
|
||||||
nvgpu_list_add(&cdev->list_entry, &l->cdev_list_head);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l->power_cdevs = total_cdevs;
|
l->power_cdevs = total_cdevs;
|
||||||
@@ -632,7 +655,6 @@ int gk20a_user_nodes_init(struct device *dev)
|
|||||||
struct nvgpu_class *class;
|
struct nvgpu_class *class;
|
||||||
u32 num_cdevs, total_cdevs;
|
u32 num_cdevs, total_cdevs;
|
||||||
u32 num_classes;
|
u32 num_classes;
|
||||||
struct nvgpu_cdev *cdev;
|
|
||||||
u32 cdev_index;
|
u32 cdev_index;
|
||||||
|
|
||||||
if (!l->cdev_list_init_done) {
|
if (!l->cdev_list_init_done) {
|
||||||
@@ -683,24 +705,13 @@ int gk20a_user_nodes_init(struct device *dev)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdev = nvgpu_kzalloc(g, sizeof(*cdev));
|
err = nvgpu_alloc_and_create_device(dev, devno++,
|
||||||
if (cdev == NULL) {
|
|
||||||
dev_err(dev, "failed to allocate cdev\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gk20a_create_device(dev, devno++,
|
|
||||||
dev_node_list[cdev_index].name,
|
dev_node_list[cdev_index].name,
|
||||||
&cdev->cdev, &cdev->node,
|
|
||||||
dev_node_list[cdev_index].fops,
|
dev_node_list[cdev_index].fops,
|
||||||
class);
|
class);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdev->class = class;
|
|
||||||
nvgpu_init_list_node(&cdev->list_entry);
|
|
||||||
nvgpu_list_add(&cdev->list_entry, &l->cdev_list_head);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,4 +75,10 @@ unsigned int nvgpu_allocate_cdev_minor(struct gk20a *g);
|
|||||||
struct gk20a *nvgpu_get_gk20a_from_cdev(struct nvgpu_cdev *cdev);
|
struct gk20a *nvgpu_get_gk20a_from_cdev(struct nvgpu_cdev *cdev);
|
||||||
u32 nvgpu_get_gpu_instance_id_from_cdev(struct gk20a *g, struct nvgpu_cdev *cdev);
|
u32 nvgpu_get_gpu_instance_id_from_cdev(struct gk20a *g, struct nvgpu_cdev *cdev);
|
||||||
|
|
||||||
|
int nvgpu_create_device(
|
||||||
|
struct device *dev, int devno,
|
||||||
|
const char *cdev_name,
|
||||||
|
struct cdev *cdev, struct device **out,
|
||||||
|
struct nvgpu_class *class);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user