diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index ac64041e5..52f987b26 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1026,9 +1027,16 @@ int nvgpu_remove(struct device *dev, struct class *class) struct gk20a *g = get_gk20a(dev); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct gk20a_platform *platform = gk20a_get_platform(dev); + int err; gk20a_dbg_fn(""); + err = nvgpu_quiesce(g); + WARN(err, "gpu failed to idle during driver removal"); + + if (nvgpu_mem_is_valid(&g->syncpt_mem)) + nvgpu_dma_free(g, &g->syncpt_mem); + if (platform->has_cde) gk20a_cde_destroy(l); @@ -1061,7 +1069,7 @@ int nvgpu_remove(struct device *dev, struct class *class) gk20a_dbg_fn("removed"); - return 0; + return err; } static int __exit gk20a_remove(struct platform_device *pdev) diff --git a/drivers/gpu/nvgpu/common/mm/vm.c b/drivers/gpu/nvgpu/common/mm/vm.c index 354d6ce46..f8d583494 100644 --- a/drivers/gpu/nvgpu/common/mm/vm.c +++ b/drivers/gpu/nvgpu/common/mm/vm.c @@ -527,6 +527,12 @@ static void __nvgpu_vm_remove(struct vm_gk20a *vm) } } +#if defined(CONFIG_TEGRA_GK20A_NVHOST) && defined(CONFIG_TEGRA_19x_GPU) + if (nvgpu_mem_is_valid(&g->syncpt_mem) && vm->syncpt_ro_map_gpu_va) + nvgpu_gmmu_unmap(vm, &g->syncpt_mem, + vm->syncpt_ro_map_gpu_va); +#endif + nvgpu_mutex_acquire(&vm->update_gmmu_lock); nvgpu_rbtree_enum_start(0, &node, vm->mapped_buffers); diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c index 380ea0488..d83684e47 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c @@ -76,9 +76,9 @@ static int gk20a_channel_syncpt_wait_syncpt(struct gk20a_channel_sync *s, } nvgpu_log(c->g, gpu_dbg_info, "sp->id %d gpu va %llx", - id, sp->syncpt_buf.gpu_va); + id, sp->c->vm->syncpt_ro_map_gpu_va); c->g->ops.fifo.add_syncpt_wait_cmd(c->g, wait_cmd, 0, id, - thresh, sp->syncpt_buf.gpu_va); + thresh, c->vm->syncpt_ro_map_gpu_va); return 0; } @@ -147,7 +147,7 @@ static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, wait_id, sp->syncpt_buf.gpu_va); c->g->ops.fifo.add_syncpt_wait_cmd(c->g, wait_cmd, i * wait_cmd_size, wait_id, wait_value, - sp->syncpt_buf.gpu_va); + c->vm->syncpt_ro_map_gpu_va); } } diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index d1ad5992a..cac62db7d 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -154,6 +154,9 @@ int gk20a_finalize_poweron(struct gk20a *g) { struct gk20a_platform *platform = gk20a_get_platform(dev_from_gk20a(g)); int err; +#if defined(CONFIG_TEGRA_GK20A_NVHOST) && defined(CONFIG_TEGRA_19x_GPU) + u32 nr_pages; +#endif gk20a_dbg_fn(""); @@ -346,6 +349,14 @@ int gk20a_finalize_poweron(struct gk20a *g) } } +#if defined(CONFIG_TEGRA_GK20A_NVHOST) && defined(CONFIG_TEGRA_19x_GPU) + if (gk20a_platform_has_syncpoints(g) && g->syncpt_unit_size) { + nr_pages = DIV_ROUND_UP(g->syncpt_unit_size, PAGE_SIZE); + __nvgpu_mem_create_from_phys(g, &g->syncpt_mem, + g->syncpt_unit_base, nr_pages); + } +#endif + done: if (err) g->power_on = false; diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 72e47ec64..a45a7b4e6 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -1293,6 +1293,7 @@ struct gk20a { size_t syncpt_unit_size; u32 syncpt_size; #endif + struct nvgpu_mem syncpt_mem; }; static inline unsigned long gk20a_get_gr_idle_timeout(struct gk20a *g) diff --git a/drivers/gpu/nvgpu/include/nvgpu/vm.h b/drivers/gpu/nvgpu/include/nvgpu/vm.h index 4c5d3232d..f88680651 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/vm.h +++ b/drivers/gpu/nvgpu/include/nvgpu/vm.h @@ -175,6 +175,12 @@ struct vm_gk20a { * Each address space needs to have a semaphore pool. */ struct nvgpu_semaphore_pool *sema_pool; + + /* + * Create sync point read only map for sync point range. + * Channels sharing same vm will also share same sync point ro map + */ + u64 syncpt_ro_map_gpu_va; }; void nvgpu_vm_get(struct vm_gk20a *vm);