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 <kholtta@nvidia.com>
Reviewed-on: http://git-master/r/552014
Reviewed-by: Arto Merilainen <amerilainen@nvidia.com>
Tested-by: Arto Merilainen <amerilainen@nvidia.com>
This commit is contained in:
Konsta Holtta
2014-09-30 13:23:35 +03:00
committed by Dan Willemsen
parent 5ce4438380
commit b564dc87b6
2 changed files with 41 additions and 0 deletions

View File

@@ -674,6 +674,9 @@ void gk20a_free_channel(struct channel_gk20a *ch, bool finish)
else else
gk20a_vm_put(ch_vm); gk20a_vm_put(ch_vm);
ch->update_fn = NULL;
ch->update_fn_data = NULL;
unbind: unbind:
if (gk20a_is_channel_marked_as_tsg(ch)) if (gk20a_is_channel_marked_as_tsg(ch))
gk20a_tsg_unbind_channel(ch); gk20a_tsg_unbind_channel(ch);
@@ -730,6 +733,27 @@ int gk20a_channel_release(struct inode *inode, struct file *filp)
return 0; 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 channel_gk20a *gk20a_open_new_channel(struct gk20a *g)
{ {
struct fifo_gk20a *f = &g->fifo; 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.events_enabled = false;
ch->poll_events.num_pending_events = 0; 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; 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->jobs_lock);
mutex_unlock(&c->submit_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) void add_wait_cmd(u32 *ptr, u32 id, u32 thresh)

View File

@@ -157,6 +157,12 @@ struct channel_gk20a {
/* event support */ /* event support */
struct channel_gk20a_poll_events poll_events; 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) 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); 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(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); void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a);
int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,