diff --git a/drivers/gpu/nvgpu/common/linux/driver_common.c b/drivers/gpu/nvgpu/common/linux/driver_common.c index 62596d495..c36631172 100644 --- a/drivers/gpu/nvgpu/common/linux/driver_common.c +++ b/drivers/gpu/nvgpu/common/linux/driver_common.c @@ -77,9 +77,6 @@ static void nvgpu_init_vars(struct gk20a *g) dma_set_mask(dev, DMA_BIT_MASK(34)); dma_set_coherent_mask(dev, DMA_BIT_MASK(34)); - nvgpu_init_list_node(&g->pending_sema_waits); - nvgpu_raw_spinlock_init(&g->pending_sema_waits_lock); - nvgpu_init_list_node(&g->profiler_objects); nvgpu_init_list_node(&g->boardobj_head); diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index 84cc33992..d79de2119 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c @@ -1052,7 +1052,6 @@ void gk20a_driver_start_unload(struct gk20a *g) gk20a_wait_for_idle(g); nvgpu_wait_for_deferred_interrupts(g); - gk20a_channel_cancel_pending_sema_waits(g); if (l->nonstall_work_queue) { cancel_work_sync(&l->nonstall_fn_work); diff --git a/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c b/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c index 6f040603b..c3d95b4a7 100644 --- a/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c +++ b/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c @@ -80,9 +80,6 @@ static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform) l->regs_saved = l->regs; l->bar1_saved = l->bar1; - nvgpu_init_list_node(&g->pending_sema_waits); - nvgpu_raw_spinlock_init(&g->pending_sema_waits_lock); - g->aggressive_sync_destroy = platform->aggressive_sync_destroy; g->aggressive_sync_destroy_thresh = platform->aggressive_sync_destroy_thresh; g->has_syncpoints = platform->has_syncpoints; diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c index e896eb884..20460c800 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c @@ -379,127 +379,6 @@ struct gk20a_channel_semaphore { struct sync_timeline *timeline; }; -#ifdef CONFIG_SYNC -struct wait_fence_work { - struct sync_fence_waiter waiter; - struct sync_fence *fence; - struct channel_gk20a *ch; - struct nvgpu_semaphore *sema; - struct gk20a *g; - struct nvgpu_list_node entry; -}; - -static inline struct wait_fence_work * -wait_fence_work_from_entry(struct nvgpu_list_node *node) -{ - return (struct wait_fence_work *) - ((uintptr_t)node - offsetof(struct wait_fence_work, entry)); -}; - -/* - * Keep track of all the pending waits on semaphores that exist for a GPU. This - * has to be done because the waits on fences backed by semaphores are - * asynchronous so it's impossible to otherwise know when they will fire. During - * driver cleanup this list can be checked and all existing waits can be - * canceled. - */ -static void gk20a_add_pending_sema_wait(struct gk20a *g, - struct wait_fence_work *work) -{ - nvgpu_raw_spinlock_acquire(&g->pending_sema_waits_lock); - nvgpu_list_add(&work->entry, &g->pending_sema_waits); - nvgpu_raw_spinlock_release(&g->pending_sema_waits_lock); -} - -/* - * Copy the list head from the pending wait list to the passed list and - * then delete the entire pending list. - */ -static void gk20a_start_sema_wait_cancel(struct gk20a *g, - struct nvgpu_list_node *list) -{ - nvgpu_raw_spinlock_acquire(&g->pending_sema_waits_lock); - nvgpu_list_replace_init(&g->pending_sema_waits, list); - nvgpu_raw_spinlock_release(&g->pending_sema_waits_lock); -} - -/* - * During shutdown this should be called to make sure that any pending sema - * waits are canceled. This is a fairly delicate and tricky bit of code. Here's - * how it works. - * - * Every time a semaphore wait is initiated in SW the wait_fence_work struct is - * added to the pending_sema_waits list. When the semaphore launcher code runs - * it checks the pending_sema_waits list. If this list is non-empty that means - * that the wait_fence_work struct must be present and can be removed. - * - * When the driver shuts down one of the steps is to cancel pending sema waits. - * To do this the entire list of pending sema waits is removed (and stored in a - * separate local list). So now, if the semaphore launcher code runs it will see - * that the pending_sema_waits list is empty and knows that it no longer owns - * the wait_fence_work struct. - */ -void gk20a_channel_cancel_pending_sema_waits(struct gk20a *g) -{ - struct wait_fence_work *work; - struct nvgpu_list_node local_pending_sema_waits; - - gk20a_start_sema_wait_cancel(g, &local_pending_sema_waits); - - while (!nvgpu_list_empty(&local_pending_sema_waits)) { - int ret; - - work = nvgpu_list_first_entry(&local_pending_sema_waits, - wait_fence_work, - entry); - - nvgpu_list_del(&work->entry); - - /* - * Only nvgpu_kfree() work if the cancel is successful. - * Otherwise it's in use by the - * gk20a_channel_semaphore_launcher() code. - */ - ret = sync_fence_cancel_async(work->fence, &work->waiter); - if (ret == 0) - nvgpu_kfree(g, work); - } -} - -static void gk20a_channel_semaphore_launcher( - struct sync_fence *fence, - struct sync_fence_waiter *waiter) -{ - int err; - struct wait_fence_work *w = - container_of(waiter, struct wait_fence_work, waiter); - struct gk20a *g = w->g; - - /* - * This spinlock must protect a _very_ small critical section - - * otherwise it's possible that the deterministic submit path suffers. - */ - nvgpu_raw_spinlock_acquire(&g->pending_sema_waits_lock); - if (!nvgpu_list_empty(&g->pending_sema_waits)) - nvgpu_list_del(&w->entry); - nvgpu_raw_spinlock_release(&g->pending_sema_waits_lock); - - gk20a_dbg_info("waiting for pre fence %p '%s'", - fence, fence->name); - err = sync_fence_wait(fence, -1); - if (err < 0) - nvgpu_err(g, "error waiting pre-fence: %d", err); - - gk20a_dbg_info( - "wait completed (%d) for fence %p '%s', triggering gpu work", - err, fence, fence->name); - sync_fence_put(fence); - nvgpu_semaphore_release(w->sema, w->ch->hw_sema); - nvgpu_semaphore_put(w->sema); - nvgpu_kfree(g, w); -} -#endif - static void add_sema_cmd(struct gk20a *g, struct channel_gk20a *c, struct nvgpu_semaphore *s, struct priv_cmd_entry *cmd, u32 offset, bool acquire, bool wfi) @@ -638,102 +517,6 @@ put_fence: sync_fence_put(sync_fence); return err; } - -static int semaphore_wait_fd_proxy(struct channel_gk20a *c, int fd, - struct priv_cmd_entry *wait_cmd, - struct gk20a_fence *fence_out, - struct sync_timeline *timeline) -{ - const int wait_cmd_size = 8; - struct sync_fence *sync_fence; - struct wait_fence_work *w = NULL; - int err, status; - - sync_fence = sync_fence_fdget(fd); - if (!sync_fence) - return -EINVAL; - - /* If the fence has signaled there is no reason to wait on it. */ - status = atomic_read(&sync_fence->status); - if (status == 0) { - sync_fence_put(sync_fence); - return 0; - } - - err = gk20a_channel_alloc_priv_cmdbuf(c, wait_cmd_size, wait_cmd); - if (err) { - nvgpu_err(c->g, - "not enough priv cmd buffer space"); - goto clean_up_sync_fence; - } - - w = nvgpu_kzalloc(c->g, sizeof(*w)); - if (!w) { - err = -ENOMEM; - goto clean_up_priv_cmd; - } - - sync_fence_waiter_init(&w->waiter, gk20a_channel_semaphore_launcher); - w->fence = sync_fence; - w->g = c->g; - w->ch = c; - w->sema = nvgpu_semaphore_alloc(c); - if (!w->sema) { - nvgpu_err(c->g, "ran out of semaphores"); - err = -ENOMEM; - goto clean_up_worker; - } - - /* worker takes one reference */ - nvgpu_semaphore_get(w->sema); - nvgpu_semaphore_incr(w->sema, c->hw_sema); - - /* GPU unblocked when the semaphore value increments. */ - add_sema_cmd(c->g, c, w->sema, wait_cmd, 0, true, false); - - /* - * We need to create the fence before adding the waiter to ensure - * that we properly clean up in the event the sync_fence has - * already signaled - */ - err = gk20a_fence_from_semaphore(c->g, fence_out, timeline, - w->sema, &c->semaphore_wq, false); - if (err) - goto clean_up_sema; - - err = sync_fence_wait_async(sync_fence, &w->waiter); - gk20a_add_pending_sema_wait(c->g, w); - - /* - * If the sync_fence has already signaled then the above wait_async - * will not get scheduled; the fence completed just after doing the - * status check above before allocs and waiter init, and won the race. - * This causes the waiter to be skipped, so let's release the semaphore - * here and put the refs taken for the worker. - */ - if (err == 1) { - sync_fence_put(sync_fence); - nvgpu_semaphore_release(w->sema, c->hw_sema); - nvgpu_semaphore_put(w->sema); - } - - return 0; - -clean_up_sema: - /* - * Release the refs to the semaphore, including - * the one for the worker since it will never run. - */ - nvgpu_semaphore_put(w->sema); - nvgpu_semaphore_put(w->sema); -clean_up_worker: - nvgpu_kfree(c->g, w); -clean_up_priv_cmd: - gk20a_free_priv_cmdbuf(c, wait_cmd); -clean_up_sync_fence: - sync_fence_put(sync_fence); - return err; -} #endif static int gk20a_channel_semaphore_wait_fd( @@ -745,12 +528,8 @@ static int gk20a_channel_semaphore_wait_fd( container_of(s, struct gk20a_channel_semaphore, ops); struct channel_gk20a *c = sema->c; #ifdef CONFIG_SYNC - int err; - err = semaphore_wait_fd_native(c, fd, entry); - if (err) - err = semaphore_wait_fd_proxy(c, fd, entry, fence, sema->timeline); - return err; + return semaphore_wait_fd_native(c, fd, entry); #else nvgpu_err(c->g, "trying to use sync fds with CONFIG_SYNC disabled"); diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h index f4f541459..dd0213dce 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.h @@ -114,12 +114,4 @@ struct gk20a_channel_sync *gk20a_channel_sync_create(struct channel_gk20a *c, bool user_managed); bool gk20a_channel_sync_needs_sync_framework(struct gk20a *g); -#ifdef CONFIG_SYNC -void gk20a_channel_cancel_pending_sema_waits(struct gk20a *g); -#else -static inline void gk20a_channel_cancel_pending_sema_waits(struct gk20a *g) -{ -} -#endif - #endif diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index dd9cb3ce1..c1824b075 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -1306,10 +1306,6 @@ struct gk20a { */ struct nvgpu_semaphore_sea *sema_sea; - /* List of pending SW semaphore waits. */ - struct nvgpu_list_node pending_sema_waits; - struct nvgpu_raw_spinlock pending_sema_waits_lock; - /* held while manipulating # of debug/profiler sessions present */ /* also prevents debug sessions from attaching until released */ struct nvgpu_mutex dbg_sessions_lock;