diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 32 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 9 |
2 files changed, 41 insertions, 0 deletions
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) | |||
674 | else | 674 | else |
675 | gk20a_vm_put(ch_vm); | 675 | gk20a_vm_put(ch_vm); |
676 | 676 | ||
677 | ch->update_fn = NULL; | ||
678 | ch->update_fn_data = NULL; | ||
679 | |||
677 | unbind: | 680 | unbind: |
678 | if (gk20a_is_channel_marked_as_tsg(ch)) | 681 | if (gk20a_is_channel_marked_as_tsg(ch)) |
679 | gk20a_tsg_unbind_channel(ch); | 682 | gk20a_tsg_unbind_channel(ch); |
@@ -730,6 +733,27 @@ int gk20a_channel_release(struct inode *inode, struct file *filp) | |||
730 | return 0; | 733 | return 0; |
731 | } | 734 | } |
732 | 735 | ||
736 | static void gk20a_channel_update_runcb_fn(struct work_struct *work) | ||
737 | { | ||
738 | struct channel_gk20a *ch = | ||
739 | container_of(work, struct channel_gk20a, update_fn_work); | ||
740 | ch->update_fn(ch, ch->update_fn_data); | ||
741 | } | ||
742 | |||
743 | struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, | ||
744 | void (*update_fn)(struct channel_gk20a *, void *), | ||
745 | void *update_fn_data) | ||
746 | { | ||
747 | struct channel_gk20a *ch = gk20a_open_new_channel(g); | ||
748 | |||
749 | if (ch) { | ||
750 | ch->update_fn = update_fn; | ||
751 | ch->update_fn_data = update_fn_data; | ||
752 | } | ||
753 | |||
754 | return ch; | ||
755 | } | ||
756 | |||
733 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) | 757 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) |
734 | { | 758 | { |
735 | struct fifo_gk20a *f = &g->fifo; | 759 | struct fifo_gk20a *f = &g->fifo; |
@@ -777,6 +801,11 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g) | |||
777 | ch->poll_events.events_enabled = false; | 801 | ch->poll_events.events_enabled = false; |
778 | ch->poll_events.num_pending_events = 0; | 802 | ch->poll_events.num_pending_events = 0; |
779 | 803 | ||
804 | ch->update_fn = NULL; | ||
805 | ch->update_fn_data = NULL; | ||
806 | |||
807 | INIT_WORK(&ch->update_fn_work, gk20a_channel_update_runcb_fn); | ||
808 | |||
780 | return ch; | 809 | return ch; |
781 | } | 810 | } |
782 | 811 | ||
@@ -1473,6 +1502,9 @@ void gk20a_channel_update(struct channel_gk20a *c, int nr_completed) | |||
1473 | } | 1502 | } |
1474 | mutex_unlock(&c->jobs_lock); | 1503 | mutex_unlock(&c->jobs_lock); |
1475 | mutex_unlock(&c->submit_lock); | 1504 | mutex_unlock(&c->submit_lock); |
1505 | |||
1506 | if (c->update_fn) | ||
1507 | schedule_work(&c->update_fn_work); | ||
1476 | } | 1508 | } |
1477 | 1509 | ||
1478 | void add_wait_cmd(u32 *ptr, u32 id, u32 thresh) | 1510 | 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 { | |||
157 | 157 | ||
158 | /* event support */ | 158 | /* event support */ |
159 | struct channel_gk20a_poll_events poll_events; | 159 | struct channel_gk20a_poll_events poll_events; |
160 | |||
161 | /* signal channel owner via a callback, if set, in gk20a_channel_update | ||
162 | * via schedule_work */ | ||
163 | void (*update_fn)(struct channel_gk20a *, void *); | ||
164 | void *update_fn_data; | ||
165 | struct work_struct update_fn_work; | ||
160 | }; | 166 | }; |
161 | 167 | ||
162 | static inline bool gk20a_channel_as_bound(struct channel_gk20a *ch) | 168 | static inline bool gk20a_channel_as_bound(struct channel_gk20a *ch) |
@@ -196,6 +202,9 @@ void gk20a_init_channel(struct gpu_ops *gops); | |||
196 | 202 | ||
197 | int gk20a_wait_channel_idle(struct channel_gk20a *ch); | 203 | int gk20a_wait_channel_idle(struct channel_gk20a *ch); |
198 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g); | 204 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g); |
205 | struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, | ||
206 | void (*update_fn)(struct channel_gk20a *, void *), | ||
207 | void *update_fn_data); | ||
199 | void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a); | 208 | void channel_gk20a_unbind(struct channel_gk20a *ch_gk20a); |
200 | 209 | ||
201 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | 210 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, |