From ba2e59dc41f593bb011e0ec58c969337a35f4cf1 Mon Sep 17 00:00:00 2001 From: Konsta Holtta Date: Wed, 22 Nov 2017 15:57:11 +0200 Subject: gpu: nvgpu: use submit callback only in linux code Move the implementation for channel job update callbacks that is based on Linux specific work_struct usage to Linux-specific code. This requires a bit of extra work for allocating OS-specific priv data for channels which is also done in this patch. The priv data will be used more when more OS-specific features are moved. Jira NVGPU-259 Change-Id: I24bc0148a827f375b56a1c96044685affc2d1e8c Signed-off-by: Konsta Holtta Reviewed-on: https://git-master.nvidia.com/r/1589321 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 57 ++++++--------------------------- drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 21 ++---------- drivers/gpu/nvgpu/gk20a/gk20a.h | 7 ++++ 3 files changed, 19 insertions(+), 66 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a') diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 4be232f1..e01d6cdb 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -444,6 +444,9 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force) trace_gk20a_free_channel(ch->chid); + if (g->os_channel.close) + g->os_channel.close(ch); + /* * Disable channel/TSG and unbind here. This should not be executed if * HW access is not available during shutdown/removal path as it will @@ -561,12 +564,6 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force) */ nvgpu_vm_put(ch_vm); - nvgpu_spinlock_acquire(&ch->update_fn_lock); - ch->update_fn = NULL; - ch->update_fn_data = NULL; - nvgpu_spinlock_release(&ch->update_fn_lock); - cancel_work_sync(&ch->update_fn_work); - /* make sure we don't have deferred interrupts pending that * could still touch the channel */ nvgpu_wait_for_deferred_interrupts(g); @@ -756,40 +753,6 @@ void __gk20a_channel_kill(struct channel_gk20a *ch) gk20a_free_channel(ch, true); } -static void gk20a_channel_update_runcb_fn(struct work_struct *work) -{ - struct channel_gk20a *ch = - container_of(work, struct channel_gk20a, update_fn_work); - void (*update_fn)(struct channel_gk20a *, void *); - void *update_fn_data; - - nvgpu_spinlock_acquire(&ch->update_fn_lock); - update_fn = ch->update_fn; - update_fn_data = ch->update_fn_data; - nvgpu_spinlock_release(&ch->update_fn_lock); - - if (update_fn) - update_fn(ch, update_fn_data); -} - -struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, - void (*update_fn)(struct channel_gk20a *, void *), - void *update_fn_data, - int runlist_id, - bool is_privileged_channel) -{ - struct channel_gk20a *ch = gk20a_open_new_channel(g, runlist_id, is_privileged_channel); - - if (ch) { - nvgpu_spinlock_acquire(&ch->update_fn_lock); - ch->update_fn = update_fn; - ch->update_fn_data = update_fn_data; - nvgpu_spinlock_release(&ch->update_fn_lock); - } - - return ch; -} - struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, s32 runlist_id, bool is_privileged_channel) @@ -872,10 +835,8 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, nvgpu_cond_init(&ch->notifier_wq); nvgpu_cond_init(&ch->semaphore_wq); - ch->update_fn = NULL; - ch->update_fn_data = NULL; - nvgpu_spinlock_init(&ch->update_fn_lock); - INIT_WORK(&ch->update_fn_work, gk20a_channel_update_runcb_fn); + if (g->os_channel.open) + g->os_channel.open(ch); /* Mark the channel alive, get-able, with 1 initial use * references. The initial reference will be decreased in @@ -2120,8 +2081,8 @@ void gk20a_channel_clean_up_jobs(struct channel_gk20a *c, nvgpu_mutex_release(&c->joblist.cleanup_lock); - if (job_finished && c->update_fn) - schedule_work(&c->update_fn_work); + if (job_finished && g->os_channel.work_completion_signal) + g->os_channel.work_completion_signal(c); gk20a_channel_put(c); } @@ -2322,8 +2283,8 @@ int gk20a_channel_suspend(struct gk20a *g) /* preempt the channel */ gk20a_fifo_preempt(g, ch); /* wait for channel update notifiers */ - if (ch->update_fn) - cancel_work_sync(&ch->update_fn_work); + if (g->os_channel.work_completion_cancel_sync) + g->os_channel.work_completion_cancel_sync(ch); channels_in_use = true; diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index d865849b..8c9095b2 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -24,9 +24,6 @@ #ifndef CHANNEL_GK20A_H #define CHANNEL_GK20A_H -/* TODO: To be removed when work_struct update_fn_work is moved out of common code */ -#include - #include #include #include @@ -288,16 +285,6 @@ struct channel_gk20a { u64 virt_ctx; #endif - /* - * Signal channel owner via a callback, if set, in job cleanup with - * schedule_work. Means that something finished on the channel (perhaps - * more than one job). - */ - void (*update_fn)(struct channel_gk20a *, void *); - void *update_fn_data; - struct nvgpu_spinlock update_fn_lock; /* make access to the two above atomic */ - struct work_struct update_fn_work; - u32 interleave_level; u32 runlist_id; @@ -306,6 +293,9 @@ struct channel_gk20a { #ifdef CONFIG_TEGRA_19x_GPU struct channel_t19x t19x; #endif + + /* Any operating system specific data. */ + void *os_priv; }; static inline struct channel_gk20a * @@ -382,11 +372,6 @@ int gk20a_wait_channel_idle(struct channel_gk20a *ch); struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, s32 runlist_id, bool is_privileged_channel); -struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, - void (*update_fn)(struct channel_gk20a *, void *), - void *update_fn_data, - int runlist_id, - bool is_privileged_channel); int gk20a_channel_alloc_gpfifo(struct channel_gk20a *c, unsigned int num_entries, diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 8d6db4c7..11a99bff 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -1255,6 +1255,13 @@ struct gk20a { struct nvgpu_mutex start_lock; } channel_worker; + struct { + void (*open)(struct channel_gk20a *ch); + void (*close)(struct channel_gk20a *ch); + void (*work_completion_signal)(struct channel_gk20a *ch); + void (*work_completion_cancel_sync)(struct channel_gk20a *ch); + } os_channel; + struct gk20a_scale_profile *scale_profile; unsigned long last_freq; -- cgit v1.2.2