diff options
author | David Nieto <dmartineznie@nvidia.com> | 2017-04-19 00:56:09 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-09-22 18:47:01 -0400 |
commit | 90568a2ce58c03f457bdd4fab6675cd327ed13fd (patch) | |
tree | 4095b7599083ac478dbfbb522f1abcc585dc2801 /drivers | |
parent | 7134e9e852116f86745cd23312bbfba34100bf6d (diff) |
gpu: nvgpu: allow bind to be interrupted
This change solves two problems:
(*) the possibility of a crash due to interrupting the gpu
initialization following a bind
(*) a IOVA memory leak that could prevent the GPU from binding after
about 200 bind/unbind cycles
A detailed list of fixes:
- chek that arbiter is initialized before freeing it.
- do not re-enable interrupts when MSI is enabled on unbind.
- free the semaphore sea on unbind.
- ensure we dont double load the vbios.
- check return value of nvgpu_mutex_init for semaphores.
- add corresponding nvgpu_mutex_destroy calls.
bug 1816516
Change-Id: Ia8af73019e0e1183998855d55bb3eea09672a8b7
Signed-off-by: David Nieto <dmartineznie@nvidia.com>
Reviewed-on: http://git-master/r/1465302
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: Thomas Fleury <tfleury@nvidia.com>
Reviewed-by: David Jarrett <djarrett@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1563019
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_arb.c | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/semaphore.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/bios_gp106.c | 28 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/semaphore.h | 2 |
6 files changed, 29 insertions, 11 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c index 4f09da74..0df9545a 100644 --- a/drivers/gpu/nvgpu/clk/clk_arb.c +++ b/drivers/gpu/nvgpu/clk/clk_arb.c | |||
@@ -490,9 +490,9 @@ void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g) | |||
490 | nvgpu_kfree(g, arb->vf_table_pool[index].mclk_points); | 490 | nvgpu_kfree(g, arb->vf_table_pool[index].mclk_points); |
491 | } | 491 | } |
492 | nvgpu_mutex_destroy(&g->clk_arb->pstate_lock); | 492 | nvgpu_mutex_destroy(&g->clk_arb->pstate_lock); |
493 | nvgpu_kfree(g, g->clk_arb); | ||
494 | g->clk_arb = NULL; | ||
493 | } | 495 | } |
494 | nvgpu_kfree(g, g->clk_arb); | ||
495 | g->clk_arb = NULL; | ||
496 | } | 496 | } |
497 | 497 | ||
498 | static int nvgpu_clk_arb_install_fd(struct gk20a *g, | 498 | static int nvgpu_clk_arb_install_fd(struct gk20a *g, |
diff --git a/drivers/gpu/nvgpu/common/semaphore.c b/drivers/gpu/nvgpu/common/semaphore.c index 5496f5ec..0d512e8f 100644 --- a/drivers/gpu/nvgpu/common/semaphore.c +++ b/drivers/gpu/nvgpu/common/semaphore.c | |||
@@ -66,11 +66,12 @@ out: | |||
66 | return ret; | 66 | return ret; |
67 | } | 67 | } |
68 | 68 | ||
69 | void gk20a_semaphore_sea_destroy(struct gk20a *g) | 69 | void nvgpu_semaphore_sea_destroy(struct gk20a *g) |
70 | { | 70 | { |
71 | if (!g->sema_sea) | 71 | if (!g->sema_sea) |
72 | return; | 72 | return; |
73 | 73 | ||
74 | nvgpu_dma_free(g, &g->sema_sea->sea_mem); | ||
74 | nvgpu_mutex_destroy(&g->sema_sea->sea_lock); | 75 | nvgpu_mutex_destroy(&g->sema_sea->sea_lock); |
75 | nvgpu_kfree(g, g->sema_sea); | 76 | nvgpu_kfree(g, g->sema_sea); |
76 | g->sema_sea = NULL; | 77 | g->sema_sea = NULL; |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 13c62691..0cd77d1e 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -1233,6 +1233,7 @@ struct gk20a { | |||
1233 | #ifdef CONFIG_DEBUG_FS | 1233 | #ifdef CONFIG_DEBUG_FS |
1234 | struct debugfs_blob_wrapper bios_blob; | 1234 | struct debugfs_blob_wrapper bios_blob; |
1235 | #endif | 1235 | #endif |
1236 | bool bios_is_init; | ||
1236 | 1237 | ||
1237 | struct nvgpu_clk_arb *clk_arb; | 1238 | struct nvgpu_clk_arb *clk_arb; |
1238 | 1239 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 0e0326dd..dd8b900d 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -393,7 +393,7 @@ static void gk20a_remove_mm_support(struct mm_gk20a *mm) | |||
393 | nvgpu_vm_put(mm->pmu.vm); | 393 | nvgpu_vm_put(mm->pmu.vm); |
394 | nvgpu_vm_put(mm->cde.vm); | 394 | nvgpu_vm_put(mm->cde.vm); |
395 | 395 | ||
396 | gk20a_semaphore_sea_destroy(g); | 396 | nvgpu_semaphore_sea_destroy(g); |
397 | gk20a_vidmem_destroy(g); | 397 | gk20a_vidmem_destroy(g); |
398 | nvgpu_pd_cache_fini(g); | 398 | nvgpu_pd_cache_fini(g); |
399 | } | 399 | } |
diff --git a/drivers/gpu/nvgpu/gp106/bios_gp106.c b/drivers/gpu/nvgpu/gp106/bios_gp106.c index f772e267..c728433f 100644 --- a/drivers/gpu/nvgpu/gp106/bios_gp106.c +++ b/drivers/gpu/nvgpu/gp106/bios_gp106.c | |||
@@ -177,6 +177,9 @@ int gp106_bios_init(struct gk20a *g) | |||
177 | 177 | ||
178 | gk20a_dbg_fn(""); | 178 | gk20a_dbg_fn(""); |
179 | 179 | ||
180 | if (g->bios_is_init) | ||
181 | return 0; | ||
182 | |||
180 | gk20a_dbg_info("reading bios from EEPROM"); | 183 | gk20a_dbg_info("reading bios from EEPROM"); |
181 | g->bios.size = BIOS_SIZE; | 184 | g->bios.size = BIOS_SIZE; |
182 | g->bios.data = nvgpu_vmalloc(g, BIOS_SIZE); | 185 | g->bios.data = nvgpu_vmalloc(g, BIOS_SIZE); |
@@ -195,12 +198,13 @@ int gp106_bios_init(struct gk20a *g) | |||
195 | 198 | ||
196 | err = nvgpu_bios_parse_rom(g); | 199 | err = nvgpu_bios_parse_rom(g); |
197 | if (err) | 200 | if (err) |
198 | return err; | 201 | goto free_firmware; |
199 | 202 | ||
200 | if (g->gpu_characteristics.vbios_version < g->vbios_min_version) { | 203 | if (g->gpu_characteristics.vbios_version < g->vbios_min_version) { |
201 | nvgpu_err(g, "unsupported VBIOS version %08x", | 204 | nvgpu_err(g, "unsupported VBIOS version %08x", |
202 | g->gpu_characteristics.vbios_version); | 205 | g->gpu_characteristics.vbios_version); |
203 | return -EINVAL; | 206 | err = -EINVAL; |
207 | goto free_firmware; | ||
204 | } | 208 | } |
205 | 209 | ||
206 | /* WAR for HW2.5 RevA (INA3221 is missing) */ | 210 | /* WAR for HW2.5 RevA (INA3221 is missing) */ |
@@ -216,25 +220,37 @@ int gp106_bios_init(struct gk20a *g) | |||
216 | 220 | ||
217 | d = debugfs_create_blob("bios", S_IRUGO, l->debugfs, | 221 | d = debugfs_create_blob("bios", S_IRUGO, l->debugfs, |
218 | &g->bios_blob); | 222 | &g->bios_blob); |
219 | if (!d) | 223 | if (!d) { |
224 | err = -EINVAL; | ||
220 | nvgpu_err(g, "No debugfs?"); | 225 | nvgpu_err(g, "No debugfs?"); |
226 | goto free_firmware; | ||
227 | } | ||
221 | #endif | 228 | #endif |
222 | |||
223 | gk20a_dbg_fn("done"); | 229 | gk20a_dbg_fn("done"); |
224 | 230 | ||
225 | err = gp106_bios_devinit(g); | 231 | err = gp106_bios_devinit(g); |
226 | if (err) { | 232 | if (err) { |
227 | nvgpu_err(g, "devinit failed"); | 233 | nvgpu_err(g, "devinit failed"); |
228 | return err; | 234 | goto free_debugfs; |
229 | } | 235 | } |
230 | 236 | ||
231 | if (nvgpu_is_enabled(g, NVGPU_PMU_RUN_PREOS)) { | 237 | if (nvgpu_is_enabled(g, NVGPU_PMU_RUN_PREOS)) { |
232 | err = gp106_bios_preos(g); | 238 | err = gp106_bios_preos(g); |
233 | if (err) { | 239 | if (err) { |
234 | nvgpu_err(g, "pre-os failed"); | 240 | nvgpu_err(g, "pre-os failed"); |
235 | return err; | 241 | goto free_debugfs; |
236 | } | 242 | } |
237 | } | 243 | } |
244 | g->bios_is_init = true; | ||
238 | 245 | ||
239 | return 0; | 246 | return 0; |
247 | free_debugfs: | ||
248 | #ifdef CONFIG_DEBUG_FS | ||
249 | debugfs_remove(d); | ||
250 | #endif | ||
251 | free_firmware: | ||
252 | if (g->bios.data) | ||
253 | nvgpu_vfree(g, g->bios.data); | ||
254 | return err; | ||
240 | } | 255 | } |
256 | |||
diff --git a/drivers/gpu/nvgpu/include/nvgpu/semaphore.h b/drivers/gpu/nvgpu/include/nvgpu/semaphore.h index 5c0019ae..8915b722 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/semaphore.h +++ b/drivers/gpu/nvgpu/include/nvgpu/semaphore.h | |||
@@ -160,7 +160,7 @@ struct nvgpu_semaphore_sea { | |||
160 | * Semaphore sea functions. | 160 | * Semaphore sea functions. |
161 | */ | 161 | */ |
162 | struct nvgpu_semaphore_sea *nvgpu_semaphore_sea_create(struct gk20a *gk20a); | 162 | struct nvgpu_semaphore_sea *nvgpu_semaphore_sea_create(struct gk20a *gk20a); |
163 | void gk20a_semaphore_sea_destroy(struct gk20a *g); | 163 | void nvgpu_semaphore_sea_destroy(struct gk20a *g); |
164 | int nvgpu_semaphore_sea_map(struct nvgpu_semaphore_pool *sea, | 164 | int nvgpu_semaphore_sea_map(struct nvgpu_semaphore_pool *sea, |
165 | struct vm_gk20a *vm); | 165 | struct vm_gk20a *vm); |
166 | void nvgpu_semaphore_sea_unmap(struct nvgpu_semaphore_pool *sea, | 166 | void nvgpu_semaphore_sea_unmap(struct nvgpu_semaphore_pool *sea, |