From 69252b3fb629d9534e7a9c4e3b75d3462653f00d Mon Sep 17 00:00:00 2001 From: Konsta Holtta Date: Fri, 16 Mar 2018 18:10:33 +0200 Subject: gpu: nvgpu: remove support for foreign sema syncfds Delete the proxy waiter for non-semaphore-backed syncfds in sema wait path to simplify code, to remove dependencies to the sync framework (and thus Linux) and to support upcoming refactorings. This feature has never been used for actually foreign fences. Jira NVGPU-43 Jira NVGPU-66 Change-Id: I2b539aefd2d096a7bf5f40e61d48de7a9b3dccae Signed-off-by: Konsta Holtta Reviewed-on: https://git-master.nvidia.com/r/1665119 Reviewed-by: svc-mobile-coverity Reviewed-by: Alex Waterman GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | 223 +-------------------------- 1 file changed, 1 insertion(+), 222 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c') diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c index e896eb88..20460c80 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"); -- cgit v1.2.2