From badfffe3ef3f5901a5ebd819d25310b3b17c31eb Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Wed, 17 Jan 2018 16:19:23 -0800 Subject: gpu: nvgpu: add cleanup in gk20a_probe() Add cleanup to the gk20a_probe() function since it will often fail due to probe deferal. These "failures" cause this function to be called multiple times and potentially allocate many resources over and over again, leaking the old allocations. Bug 200369627 Change-Id: Ic0bba0ae6542485135d9cb7393086e4460cd271d Signed-off-by: Alex Waterman Reviewed-on: https://git-master.nvidia.com/r/1640628 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/linux/module.c | 44 ++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/nvgpu/common/linux/module.c') diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index 2e288ce2..d74d824f 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c @@ -1105,7 +1105,7 @@ static int nvgpu_read_fuse_overrides(struct gk20a *g) static int gk20a_probe(struct platform_device *dev) { - struct nvgpu_os_linux *l; + struct nvgpu_os_linux *l = NULL; struct gk20a *gk20a; int err; struct gk20a_platform *platform = NULL; @@ -1147,15 +1147,17 @@ static int gk20a_probe(struct platform_device *dev) err = nvgpu_init_enabled_flags(gk20a); if (err) - return err; + goto return_err; if (nvgpu_platform_is_simulation(gk20a)) __nvgpu_set_enabled(gk20a, NVGPU_IS_FMODEL, true); gk20a->irq_stall = platform_get_irq(dev, 0); gk20a->irq_nonstall = platform_get_irq(dev, 1); - if (gk20a->irq_stall < 0 || gk20a->irq_nonstall < 0) - return -ENXIO; + if (gk20a->irq_stall < 0 || gk20a->irq_nonstall < 0) { + err = -ENXIO; + goto return_err; + } err = devm_request_threaded_irq(&dev->dev, gk20a->irq_stall, @@ -1166,7 +1168,7 @@ static int gk20a_probe(struct platform_device *dev) dev_err(&dev->dev, "failed to request stall intr irq @ %d\n", gk20a->irq_stall); - return err; + goto return_err; } err = devm_request_irq(&dev->dev, gk20a->irq_nonstall, @@ -1176,7 +1178,7 @@ static int gk20a_probe(struct platform_device *dev) dev_err(&dev->dev, "failed to request non-stall intr irq @ %d\n", gk20a->irq_nonstall); - return err; + goto return_err; } disable_irq(gk20a->irq_stall); if (gk20a->irq_stall != gk20a->irq_nonstall) @@ -1184,7 +1186,7 @@ static int gk20a_probe(struct platform_device *dev) err = gk20a_init_support(dev); if (err) - return err; + goto return_err; err = nvgpu_read_fuse_overrides(gk20a); @@ -1196,17 +1198,41 @@ static int gk20a_probe(struct platform_device *dev) err = nvgpu_probe(gk20a, "gpu.0", INTERFACE_NAME, &nvgpu_class); if (err) - return err; + goto return_err; err = gk20a_pm_init(&dev->dev); if (err) { dev_err(&dev->dev, "pm init failed"); - return err; + goto return_err; } gk20a->mm.has_physical_mode = !nvgpu_is_hypervisor_mode(gk20a); return 0; + +return_err: + /* + * Make sure to clean up any memory allocs made in this function - + * especially since we can be called many times due to probe deferal. + */ + if (gk20a->sim) { + struct sim_gk20a_linux *sim_linux; + sim_linux = container_of(gk20a->sim, + struct sim_gk20a_linux, + sim); + nvgpu_kfree(gk20a, sim_linux); + } + + nvgpu_free_enabled_flags(gk20a); + + /* + * Last since the above allocs may use data structures in here. + */ + nvgpu_kmem_fini(gk20a, NVGPU_KMEM_FINI_FORCE_CLEANUP); + + kfree(l); + + return err; } int nvgpu_remove(struct device *dev, struct class *class) -- cgit v1.2.2