From b564dc87b66ac6411e5aac0065b7e63db9a96a06 Mon Sep 17 00:00:00 2001 From: Konsta Holtta Date: Tue, 30 Sep 2014 13:23:35 +0300 Subject: gpu: nvgpu: add update callback to gk20a channel Add support for a callback function with user data pointer to be scheduled from the end of gk20a_channel_update. The function and its private data are supplied when opening a new channel. Change-Id: Ib6b408855ea60d46a6a114a69c01904703019572 Signed-off-by: Konsta Holtta Reviewed-on: http://git-master/r/552014 Reviewed-by: Arto Merilainen Tested-by: Arto Merilainen --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 32 ++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 9 +++++++++ 2 files changed, 41 insertions(+) (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 eaea5a77..58dde415 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -674,6 +674,9 @@ void gk20a_free_channel(struct channel_gk20a *ch, bool finish) else gk20a_vm_put(ch_vm); + ch->update_fn = NULL; + ch->update_fn_data = NULL; + unbind: if (gk20a_is_channel_marked_as_tsg(ch)) gk20a_tsg_unbind_channel(ch); @@ -730,6 +733,27 @@ int gk20a_channel_release(struct inode *inode, struct file *filp) return 0; } +static void gk20a_channel_update_runcb_fn(struct work_struct *work) +{ + struct channel_gk20a *ch = + container_of(work, struct channel_gk20a, update_fn_work); + ch->update_fn(ch, 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) +{ + struct channel_gk20a *ch = gk20a_open_new_channel(g); + + if (ch) { + ch->update_fn = update_fn; + ch->update_fn_data = update_fn_data; + } + + return ch; +} + struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) { struct fifo_gk20a *f = &g->fifo; @@ -777,6 +801,11 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) ch->poll_events.events_enabled = false; ch->poll_events.num_pending_events = 0; + ch->update_fn = NULL; + ch->update_fn_data = NULL; + + INIT_WORK(&ch->update_fn_work, gk20a_channel_update_runcb_fn); + return ch; } @@ -1473,6 +1502,9 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) } mutex_unlock(&c->jobs_lock); mutex_unlock(&c->submit_lock); + + if (c->update_fn) + schedule_work(&c->update_fn_work); } void add_wait_cmd(u32 *ptr, u32 id, u32 thresh) diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index a17e6ea9..aa87464b 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -157,6 +157,12 @@ struct channel_gk20a { /* event support */ struct channel_gk20a_poll_events poll_events; + + /* signal channel owner via a callback, if set, in gk20a_channel_update + * via schedule_work */ + void (*update_fn)(struct channel_gk20a *, void *); + void *update_fn_data; + struct work_struct update_fn_work; }; static inline bool gk20a_channel_as_bound(struct channel_gk20a *ch) @@ -196,6 +202,9 @@ void gk20a_init_channel(struct gpu_ops *gops); int gk20a_wait_channel_idle(struct channel_gk20a *ch); struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g); +struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, + void (*update_fn)(struct channel_gk20a *, void *), + void *update_fn_data); void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a); int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, -- cgit v1.2.2