summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/module.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2018-01-17 19:19:23 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2018-01-18 21:10:18 -0500
commitbadfffe3ef3f5901a5ebd819d25310b3b17c31eb (patch)
tree936353ff6043bdf6e9428979f405e33a96a9b41e /drivers/gpu/nvgpu/common/linux/module.c
parentea9cb56cf617f7fb4aa79a520f4ff5db2723152d (diff)
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 <alexw@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1640628 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/module.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/module.c44
1 files changed, 35 insertions, 9 deletions
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)
1105 1105
1106static int gk20a_probe(struct platform_device *dev) 1106static int gk20a_probe(struct platform_device *dev)
1107{ 1107{
1108 struct nvgpu_os_linux *l; 1108 struct nvgpu_os_linux *l = NULL;
1109 struct gk20a *gk20a; 1109 struct gk20a *gk20a;
1110 int err; 1110 int err;
1111 struct gk20a_platform *platform = NULL; 1111 struct gk20a_platform *platform = NULL;
@@ -1147,15 +1147,17 @@ static int gk20a_probe(struct platform_device *dev)
1147 1147
1148 err = nvgpu_init_enabled_flags(gk20a); 1148 err = nvgpu_init_enabled_flags(gk20a);
1149 if (err) 1149 if (err)
1150 return err; 1150 goto return_err;
1151 1151
1152 if (nvgpu_platform_is_simulation(gk20a)) 1152 if (nvgpu_platform_is_simulation(gk20a))
1153 __nvgpu_set_enabled(gk20a, NVGPU_IS_FMODEL, true); 1153 __nvgpu_set_enabled(gk20a, NVGPU_IS_FMODEL, true);
1154 1154
1155 gk20a->irq_stall = platform_get_irq(dev, 0); 1155 gk20a->irq_stall = platform_get_irq(dev, 0);
1156 gk20a->irq_nonstall = platform_get_irq(dev, 1); 1156 gk20a->irq_nonstall = platform_get_irq(dev, 1);
1157 if (gk20a->irq_stall < 0 || gk20a->irq_nonstall < 0) 1157 if (gk20a->irq_stall < 0 || gk20a->irq_nonstall < 0) {
1158 return -ENXIO; 1158 err = -ENXIO;
1159 goto return_err;
1160 }
1159 1161
1160 err = devm_request_threaded_irq(&dev->dev, 1162 err = devm_request_threaded_irq(&dev->dev,
1161 gk20a->irq_stall, 1163 gk20a->irq_stall,
@@ -1166,7 +1168,7 @@ static int gk20a_probe(struct platform_device *dev)
1166 dev_err(&dev->dev, 1168 dev_err(&dev->dev,
1167 "failed to request stall intr irq @ %d\n", 1169 "failed to request stall intr irq @ %d\n",
1168 gk20a->irq_stall); 1170 gk20a->irq_stall);
1169 return err; 1171 goto return_err;
1170 } 1172 }
1171 err = devm_request_irq(&dev->dev, 1173 err = devm_request_irq(&dev->dev,
1172 gk20a->irq_nonstall, 1174 gk20a->irq_nonstall,
@@ -1176,7 +1178,7 @@ static int gk20a_probe(struct platform_device *dev)
1176 dev_err(&dev->dev, 1178 dev_err(&dev->dev,
1177 "failed to request non-stall intr irq @ %d\n", 1179 "failed to request non-stall intr irq @ %d\n",
1178 gk20a->irq_nonstall); 1180 gk20a->irq_nonstall);
1179 return err; 1181 goto return_err;
1180 } 1182 }
1181 disable_irq(gk20a->irq_stall); 1183 disable_irq(gk20a->irq_stall);
1182 if (gk20a->irq_stall != gk20a->irq_nonstall) 1184 if (gk20a->irq_stall != gk20a->irq_nonstall)
@@ -1184,7 +1186,7 @@ static int gk20a_probe(struct platform_device *dev)
1184 1186
1185 err = gk20a_init_support(dev); 1187 err = gk20a_init_support(dev);
1186 if (err) 1188 if (err)
1187 return err; 1189 goto return_err;
1188 1190
1189 err = nvgpu_read_fuse_overrides(gk20a); 1191 err = nvgpu_read_fuse_overrides(gk20a);
1190 1192
@@ -1196,17 +1198,41 @@ static int gk20a_probe(struct platform_device *dev)
1196 1198
1197 err = nvgpu_probe(gk20a, "gpu.0", INTERFACE_NAME, &nvgpu_class); 1199 err = nvgpu_probe(gk20a, "gpu.0", INTERFACE_NAME, &nvgpu_class);
1198 if (err) 1200 if (err)
1199 return err; 1201 goto return_err;
1200 1202
1201 err = gk20a_pm_init(&dev->dev); 1203 err = gk20a_pm_init(&dev->dev);
1202 if (err) { 1204 if (err) {
1203 dev_err(&dev->dev, "pm init failed"); 1205 dev_err(&dev->dev, "pm init failed");
1204 return err; 1206 goto return_err;
1205 } 1207 }
1206 1208
1207 gk20a->mm.has_physical_mode = !nvgpu_is_hypervisor_mode(gk20a); 1209 gk20a->mm.has_physical_mode = !nvgpu_is_hypervisor_mode(gk20a);
1208 1210
1209 return 0; 1211 return 0;
1212
1213return_err:
1214 /*
1215 * Make sure to clean up any memory allocs made in this function -
1216 * especially since we can be called many times due to probe deferal.
1217 */
1218 if (gk20a->sim) {
1219 struct sim_gk20a_linux *sim_linux;
1220 sim_linux = container_of(gk20a->sim,
1221 struct sim_gk20a_linux,
1222 sim);
1223 nvgpu_kfree(gk20a, sim_linux);
1224 }
1225
1226 nvgpu_free_enabled_flags(gk20a);
1227
1228 /*
1229 * Last since the above allocs may use data structures in here.
1230 */
1231 nvgpu_kmem_fini(gk20a, NVGPU_KMEM_FINI_FORCE_CLEANUP);
1232
1233 kfree(l);
1234
1235 return err;
1210} 1236}
1211 1237
1212int nvgpu_remove(struct device *dev, struct class *class) 1238int nvgpu_remove(struct device *dev, struct class *class)