diff options
author | Alex Waterman <alexw@nvidia.com> | 2018-01-17 19:19:23 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-01-18 21:10:18 -0500 |
commit | badfffe3ef3f5901a5ebd819d25310b3b17c31eb (patch) | |
tree | 936353ff6043bdf6e9428979f405e33a96a9b41e /drivers/gpu/nvgpu/common | |
parent | ea9cb56cf617f7fb4aa79a520f4ff5db2723152d (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')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.c | 44 |
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 | ||
1106 | static int gk20a_probe(struct platform_device *dev) | 1106 | static 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 | |||
1213 | return_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 | ||
1212 | int nvgpu_remove(struct device *dev, struct class *class) | 1238 | int nvgpu_remove(struct device *dev, struct class *class) |