diff options
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/channel.c | 157 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/channel.h | 32 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.c | 26 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/os_linux.h | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 57 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 21 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 7 |
7 files changed, 236 insertions, 66 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/channel.c b/drivers/gpu/nvgpu/common/linux/channel.c index 40b11b86..8366ed88 100644 --- a/drivers/gpu/nvgpu/common/linux/channel.c +++ b/drivers/gpu/nvgpu/common/linux/channel.c | |||
@@ -27,6 +27,9 @@ | |||
27 | 27 | ||
28 | #include "gk20a/gk20a.h" | 28 | #include "gk20a/gk20a.h" |
29 | 29 | ||
30 | #include "channel.h" | ||
31 | #include "os_linux.h" | ||
32 | |||
30 | #include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h> | 33 | #include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h> |
31 | 34 | ||
32 | #include <linux/uaccess.h> | 35 | #include <linux/uaccess.h> |
@@ -34,6 +37,160 @@ | |||
34 | #include <trace/events/gk20a.h> | 37 | #include <trace/events/gk20a.h> |
35 | #include <uapi/linux/nvgpu.h> | 38 | #include <uapi/linux/nvgpu.h> |
36 | 39 | ||
40 | static void gk20a_channel_update_runcb_fn(struct work_struct *work) | ||
41 | { | ||
42 | struct nvgpu_channel_completion_cb *completion_cb = | ||
43 | container_of(work, struct nvgpu_channel_completion_cb, work); | ||
44 | struct nvgpu_channel_linux *priv = | ||
45 | container_of(completion_cb, | ||
46 | struct nvgpu_channel_linux, completion_cb); | ||
47 | struct channel_gk20a *ch = priv->ch; | ||
48 | void (*fn)(struct channel_gk20a *, void *); | ||
49 | void *user_data; | ||
50 | |||
51 | nvgpu_spinlock_acquire(&completion_cb->lock); | ||
52 | fn = completion_cb->fn; | ||
53 | user_data = completion_cb->user_data; | ||
54 | nvgpu_spinlock_release(&completion_cb->lock); | ||
55 | |||
56 | if (fn) | ||
57 | fn(ch, user_data); | ||
58 | } | ||
59 | |||
60 | static void nvgpu_channel_work_completion_init(struct channel_gk20a *ch) | ||
61 | { | ||
62 | struct nvgpu_channel_linux *priv = ch->os_priv; | ||
63 | |||
64 | priv->completion_cb.fn = NULL; | ||
65 | priv->completion_cb.user_data = NULL; | ||
66 | nvgpu_spinlock_init(&priv->completion_cb.lock); | ||
67 | INIT_WORK(&priv->completion_cb.work, gk20a_channel_update_runcb_fn); | ||
68 | } | ||
69 | |||
70 | static void nvgpu_channel_work_completion_clear(struct channel_gk20a *ch) | ||
71 | { | ||
72 | struct nvgpu_channel_linux *priv = ch->os_priv; | ||
73 | |||
74 | nvgpu_spinlock_acquire(&priv->completion_cb.lock); | ||
75 | priv->completion_cb.fn = NULL; | ||
76 | priv->completion_cb.user_data = NULL; | ||
77 | nvgpu_spinlock_release(&priv->completion_cb.lock); | ||
78 | cancel_work_sync(&priv->completion_cb.work); | ||
79 | } | ||
80 | |||
81 | static void nvgpu_channel_work_completion_signal(struct channel_gk20a *ch) | ||
82 | { | ||
83 | struct nvgpu_channel_linux *priv = ch->os_priv; | ||
84 | |||
85 | if (priv->completion_cb.fn) | ||
86 | schedule_work(&priv->completion_cb.work); | ||
87 | } | ||
88 | |||
89 | static void nvgpu_channel_work_completion_cancel_sync(struct channel_gk20a *ch) | ||
90 | { | ||
91 | struct nvgpu_channel_linux *priv = ch->os_priv; | ||
92 | |||
93 | if (priv->completion_cb.fn) | ||
94 | cancel_work_sync(&priv->completion_cb.work); | ||
95 | } | ||
96 | |||
97 | struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, | ||
98 | void (*update_fn)(struct channel_gk20a *, void *), | ||
99 | void *update_fn_data, | ||
100 | int runlist_id, | ||
101 | bool is_privileged_channel) | ||
102 | { | ||
103 | struct channel_gk20a *ch; | ||
104 | struct nvgpu_channel_linux *priv; | ||
105 | |||
106 | ch = gk20a_open_new_channel(g, runlist_id, is_privileged_channel); | ||
107 | |||
108 | if (ch) { | ||
109 | priv = ch->os_priv; | ||
110 | nvgpu_spinlock_acquire(&priv->completion_cb.lock); | ||
111 | priv->completion_cb.fn = update_fn; | ||
112 | priv->completion_cb.user_data = update_fn_data; | ||
113 | nvgpu_spinlock_release(&priv->completion_cb.lock); | ||
114 | } | ||
115 | |||
116 | return ch; | ||
117 | } | ||
118 | |||
119 | static void nvgpu_channel_open_linux(struct channel_gk20a *ch) | ||
120 | { | ||
121 | } | ||
122 | |||
123 | static void nvgpu_channel_close_linux(struct channel_gk20a *ch) | ||
124 | { | ||
125 | nvgpu_channel_work_completion_clear(ch); | ||
126 | } | ||
127 | |||
128 | static int nvgpu_channel_alloc_linux(struct gk20a *g, struct channel_gk20a *ch) | ||
129 | { | ||
130 | struct nvgpu_channel_linux *priv; | ||
131 | |||
132 | priv = nvgpu_kzalloc(g, sizeof(*priv)); | ||
133 | if (!priv) | ||
134 | return -ENOMEM; | ||
135 | |||
136 | ch->os_priv = priv; | ||
137 | priv->ch = ch; | ||
138 | |||
139 | nvgpu_channel_work_completion_init(ch); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static void nvgpu_channel_free_linux(struct gk20a *g, struct channel_gk20a *ch) | ||
145 | { | ||
146 | nvgpu_kfree(g, ch->os_priv); | ||
147 | } | ||
148 | |||
149 | int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l) | ||
150 | { | ||
151 | struct gk20a *g = &l->g; | ||
152 | struct fifo_gk20a *f = &g->fifo; | ||
153 | int chid; | ||
154 | int err; | ||
155 | |||
156 | for (chid = 0; chid < (int)f->num_channels; chid++) { | ||
157 | struct channel_gk20a *ch = &f->channel[chid]; | ||
158 | |||
159 | err = nvgpu_channel_alloc_linux(g, ch); | ||
160 | if (err) | ||
161 | goto err_clean; | ||
162 | } | ||
163 | |||
164 | g->os_channel.open = nvgpu_channel_open_linux; | ||
165 | g->os_channel.close = nvgpu_channel_close_linux; | ||
166 | g->os_channel.work_completion_signal = | ||
167 | nvgpu_channel_work_completion_signal; | ||
168 | g->os_channel.work_completion_cancel_sync = | ||
169 | nvgpu_channel_work_completion_cancel_sync; | ||
170 | return 0; | ||
171 | |||
172 | err_clean: | ||
173 | for (; chid >= 0; chid--) { | ||
174 | struct channel_gk20a *ch = &f->channel[chid]; | ||
175 | |||
176 | nvgpu_channel_free_linux(g, ch); | ||
177 | } | ||
178 | return err; | ||
179 | } | ||
180 | |||
181 | void nvgpu_remove_channel_support_linux(struct nvgpu_os_linux *l) | ||
182 | { | ||
183 | struct gk20a *g = &l->g; | ||
184 | struct fifo_gk20a *f = &g->fifo; | ||
185 | unsigned int chid; | ||
186 | |||
187 | for (chid = 0; chid < f->num_channels; chid++) { | ||
188 | struct channel_gk20a *ch = &f->channel[chid]; | ||
189 | |||
190 | nvgpu_channel_free_linux(g, ch); | ||
191 | } | ||
192 | } | ||
193 | |||
37 | u32 nvgpu_get_gpfifo_entry_size(void) | 194 | u32 nvgpu_get_gpfifo_entry_size(void) |
38 | { | 195 | { |
39 | return sizeof(struct nvgpu_gpfifo); | 196 | return sizeof(struct nvgpu_gpfifo); |
diff --git a/drivers/gpu/nvgpu/common/linux/channel.h b/drivers/gpu/nvgpu/common/linux/channel.h index 785c03d6..ba1935f3 100644 --- a/drivers/gpu/nvgpu/common/linux/channel.h +++ b/drivers/gpu/nvgpu/common/linux/channel.h | |||
@@ -16,6 +16,8 @@ | |||
16 | #ifndef __NVGPU_CHANNEL_H__ | 16 | #ifndef __NVGPU_CHANNEL_H__ |
17 | #define __NVGPU_CHANNEL_H__ | 17 | #define __NVGPU_CHANNEL_H__ |
18 | 18 | ||
19 | #include <linux/workqueue.h> | ||
20 | |||
19 | #include <nvgpu/types.h> | 21 | #include <nvgpu/types.h> |
20 | 22 | ||
21 | struct channel_gk20a; | 23 | struct channel_gk20a; |
@@ -24,6 +26,36 @@ struct nvgpu_submit_gpfifo_args; | |||
24 | struct nvgpu_fence; | 26 | struct nvgpu_fence; |
25 | struct gk20a_fence; | 27 | struct gk20a_fence; |
26 | struct fifo_profile_gk20a; | 28 | struct fifo_profile_gk20a; |
29 | struct nvgpu_os_linux; | ||
30 | |||
31 | struct nvgpu_channel_completion_cb { | ||
32 | /* | ||
33 | * Signal channel owner via a callback, if set, in job cleanup with | ||
34 | * schedule_work. Means that something finished on the channel (perhaps | ||
35 | * more than one job). | ||
36 | */ | ||
37 | void (*fn)(struct channel_gk20a *, void *); | ||
38 | void *user_data; | ||
39 | /* Make access to the two above atomic */ | ||
40 | struct nvgpu_spinlock lock; | ||
41 | /* Per-channel async work task, cannot reschedule itself */ | ||
42 | struct work_struct work; | ||
43 | }; | ||
44 | |||
45 | struct nvgpu_channel_linux { | ||
46 | struct channel_gk20a *ch; | ||
47 | |||
48 | struct nvgpu_channel_completion_cb completion_cb; | ||
49 | }; | ||
50 | |||
51 | int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l); | ||
52 | void nvgpu_remove_channel_support_linux(struct nvgpu_os_linux *l); | ||
53 | |||
54 | struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, | ||
55 | void (*update_fn)(struct channel_gk20a *, void *), | ||
56 | void *update_fn_data, | ||
57 | int runlist_id, | ||
58 | bool is_privileged_channel); | ||
27 | 59 | ||
28 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | 60 | int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, |
29 | struct nvgpu_gpfifo *gpfifo, | 61 | struct nvgpu_gpfifo *gpfifo, |
diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index 796507a9..5012d8b5 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include "cde_gp10b.h" | 59 | #include "cde_gp10b.h" |
60 | #include "ctxsw_trace.h" | 60 | #include "ctxsw_trace.h" |
61 | #include "driver_common.h" | 61 | #include "driver_common.h" |
62 | #include "channel.h" | ||
62 | 63 | ||
63 | #define CLASS_NAME "nvidia-gpu" | 64 | #define CLASS_NAME "nvidia-gpu" |
64 | /* TODO: Change to e.g. "nvidia-gpu%s" once we have symlinks in place. */ | 65 | /* TODO: Change to e.g. "nvidia-gpu%s" once we have symlinks in place. */ |
@@ -185,6 +186,25 @@ static int nvgpu_init_os_linux_ops(struct nvgpu_os_linux *l) | |||
185 | return 0; | 186 | return 0; |
186 | } | 187 | } |
187 | 188 | ||
189 | static int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l) | ||
190 | { | ||
191 | struct gk20a *g = &l->g; | ||
192 | int err; | ||
193 | |||
194 | if (l->init_done) | ||
195 | return 0; | ||
196 | |||
197 | err = nvgpu_init_channel_support_linux(l); | ||
198 | if (err) { | ||
199 | nvgpu_err(g, "failed to init linux channel support"); | ||
200 | return err; | ||
201 | } | ||
202 | |||
203 | l->init_done = true; | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
188 | int gk20a_pm_finalize_poweron(struct device *dev) | 208 | int gk20a_pm_finalize_poweron(struct device *dev) |
189 | { | 209 | { |
190 | struct gk20a *g = get_gk20a(dev); | 210 | struct gk20a *g = get_gk20a(dev); |
@@ -227,6 +247,10 @@ int gk20a_pm_finalize_poweron(struct device *dev) | |||
227 | if (err) | 247 | if (err) |
228 | goto done; | 248 | goto done; |
229 | 249 | ||
250 | err = nvgpu_finalize_poweron_linux(l); | ||
251 | if (err) | ||
252 | goto done; | ||
253 | |||
230 | trace_gk20a_finalize_poweron_done(dev_name(dev)); | 254 | trace_gk20a_finalize_poweron_done(dev_name(dev)); |
231 | 255 | ||
232 | err = nvgpu_init_os_linux_ops(l); | 256 | err = nvgpu_init_os_linux_ops(l); |
@@ -596,6 +620,8 @@ void gk20a_remove_support(struct gk20a *g) | |||
596 | 620 | ||
597 | nvgpu_kfree(g, g->dbg_regops_tmp_buf); | 621 | nvgpu_kfree(g, g->dbg_regops_tmp_buf); |
598 | 622 | ||
623 | nvgpu_remove_channel_support_linux(l); | ||
624 | |||
599 | if (g->pmu.remove_support) | 625 | if (g->pmu.remove_support) |
600 | g->pmu.remove_support(&g->pmu); | 626 | g->pmu.remove_support(&g->pmu); |
601 | 627 | ||
diff --git a/drivers/gpu/nvgpu/common/linux/os_linux.h b/drivers/gpu/nvgpu/common/linux/os_linux.h index 07be7edc..9b95ed84 100644 --- a/drivers/gpu/nvgpu/common/linux/os_linux.h +++ b/drivers/gpu/nvgpu/common/linux/os_linux.h | |||
@@ -149,6 +149,8 @@ struct nvgpu_os_linux { | |||
149 | struct rw_semaphore busy_lock; | 149 | struct rw_semaphore busy_lock; |
150 | 150 | ||
151 | struct gk20a_sched_ctrl sched_ctrl; | 151 | struct gk20a_sched_ctrl sched_ctrl; |
152 | |||
153 | bool init_done; | ||
152 | }; | 154 | }; |
153 | 155 | ||
154 | static inline struct nvgpu_os_linux *nvgpu_os_linux_from_gk20a(struct gk20a *g) | 156 | static inline struct nvgpu_os_linux *nvgpu_os_linux_from_gk20a(struct gk20a *g) |
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) | |||
444 | 444 | ||
445 | trace_gk20a_free_channel(ch->chid); | 445 | trace_gk20a_free_channel(ch->chid); |
446 | 446 | ||
447 | if (g->os_channel.close) | ||
448 | g->os_channel.close(ch); | ||
449 | |||
447 | /* | 450 | /* |
448 | * Disable channel/TSG and unbind here. This should not be executed if | 451 | * Disable channel/TSG and unbind here. This should not be executed if |
449 | * HW access is not available during shutdown/removal path as it will | 452 | * 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) | |||
561 | */ | 564 | */ |
562 | nvgpu_vm_put(ch_vm); | 565 | nvgpu_vm_put(ch_vm); |
563 | 566 | ||
564 | nvgpu_spinlock_acquire(&ch->update_fn_lock); | ||
565 | ch->update_fn = NULL; | ||
566 | ch->update_fn_data = NULL; | ||
567 | nvgpu_spinlock_release(&ch->update_fn_lock); | ||
568 | cancel_work_sync(&ch->update_fn_work); | ||
569 | |||
570 | /* make sure we don't have deferred interrupts pending that | 567 | /* make sure we don't have deferred interrupts pending that |
571 | * could still touch the channel */ | 568 | * could still touch the channel */ |
572 | nvgpu_wait_for_deferred_interrupts(g); | 569 | nvgpu_wait_for_deferred_interrupts(g); |
@@ -756,40 +753,6 @@ void __gk20a_channel_kill(struct channel_gk20a *ch) | |||
756 | gk20a_free_channel(ch, true); | 753 | gk20a_free_channel(ch, true); |
757 | } | 754 | } |
758 | 755 | ||
759 | static void gk20a_channel_update_runcb_fn(struct work_struct *work) | ||
760 | { | ||
761 | struct channel_gk20a *ch = | ||
762 | container_of(work, struct channel_gk20a, update_fn_work); | ||
763 | void (*update_fn)(struct channel_gk20a *, void *); | ||
764 | void *update_fn_data; | ||
765 | |||
766 | nvgpu_spinlock_acquire(&ch->update_fn_lock); | ||
767 | update_fn = ch->update_fn; | ||
768 | update_fn_data = ch->update_fn_data; | ||
769 | nvgpu_spinlock_release(&ch->update_fn_lock); | ||
770 | |||
771 | if (update_fn) | ||
772 | update_fn(ch, update_fn_data); | ||
773 | } | ||
774 | |||
775 | struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, | ||
776 | void (*update_fn)(struct channel_gk20a *, void *), | ||
777 | void *update_fn_data, | ||
778 | int runlist_id, | ||
779 | bool is_privileged_channel) | ||
780 | { | ||
781 | struct channel_gk20a *ch = gk20a_open_new_channel(g, runlist_id, is_privileged_channel); | ||
782 | |||
783 | if (ch) { | ||
784 | nvgpu_spinlock_acquire(&ch->update_fn_lock); | ||
785 | ch->update_fn = update_fn; | ||
786 | ch->update_fn_data = update_fn_data; | ||
787 | nvgpu_spinlock_release(&ch->update_fn_lock); | ||
788 | } | ||
789 | |||
790 | return ch; | ||
791 | } | ||
792 | |||
793 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, | 756 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, |
794 | s32 runlist_id, | 757 | s32 runlist_id, |
795 | bool is_privileged_channel) | 758 | bool is_privileged_channel) |
@@ -872,10 +835,8 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, | |||
872 | nvgpu_cond_init(&ch->notifier_wq); | 835 | nvgpu_cond_init(&ch->notifier_wq); |
873 | nvgpu_cond_init(&ch->semaphore_wq); | 836 | nvgpu_cond_init(&ch->semaphore_wq); |
874 | 837 | ||
875 | ch->update_fn = NULL; | 838 | if (g->os_channel.open) |
876 | ch->update_fn_data = NULL; | 839 | g->os_channel.open(ch); |
877 | nvgpu_spinlock_init(&ch->update_fn_lock); | ||
878 | INIT_WORK(&ch->update_fn_work, gk20a_channel_update_runcb_fn); | ||
879 | 840 | ||
880 | /* Mark the channel alive, get-able, with 1 initial use | 841 | /* Mark the channel alive, get-able, with 1 initial use |
881 | * references. The initial reference will be decreased in | 842 | * references. The initial reference will be decreased in |
@@ -2120,8 +2081,8 @@ void gk20a_channel_clean_up_jobs(struct channel_gk20a *c, | |||
2120 | 2081 | ||
2121 | nvgpu_mutex_release(&c->joblist.cleanup_lock); | 2082 | nvgpu_mutex_release(&c->joblist.cleanup_lock); |
2122 | 2083 | ||
2123 | if (job_finished && c->update_fn) | 2084 | if (job_finished && g->os_channel.work_completion_signal) |
2124 | schedule_work(&c->update_fn_work); | 2085 | g->os_channel.work_completion_signal(c); |
2125 | 2086 | ||
2126 | gk20a_channel_put(c); | 2087 | gk20a_channel_put(c); |
2127 | } | 2088 | } |
@@ -2322,8 +2283,8 @@ int gk20a_channel_suspend(struct gk20a *g) | |||
2322 | /* preempt the channel */ | 2283 | /* preempt the channel */ |
2323 | gk20a_fifo_preempt(g, ch); | 2284 | gk20a_fifo_preempt(g, ch); |
2324 | /* wait for channel update notifiers */ | 2285 | /* wait for channel update notifiers */ |
2325 | if (ch->update_fn) | 2286 | if (g->os_channel.work_completion_cancel_sync) |
2326 | cancel_work_sync(&ch->update_fn_work); | 2287 | g->os_channel.work_completion_cancel_sync(ch); |
2327 | 2288 | ||
2328 | channels_in_use = true; | 2289 | channels_in_use = true; |
2329 | 2290 | ||
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 @@ | |||
24 | #ifndef CHANNEL_GK20A_H | 24 | #ifndef CHANNEL_GK20A_H |
25 | #define CHANNEL_GK20A_H | 25 | #define CHANNEL_GK20A_H |
26 | 26 | ||
27 | /* TODO: To be removed when work_struct update_fn_work is moved out of common code */ | ||
28 | #include <linux/workqueue.h> | ||
29 | |||
30 | #include <nvgpu/list.h> | 27 | #include <nvgpu/list.h> |
31 | #include <nvgpu/lock.h> | 28 | #include <nvgpu/lock.h> |
32 | #include <nvgpu/timers.h> | 29 | #include <nvgpu/timers.h> |
@@ -288,16 +285,6 @@ struct channel_gk20a { | |||
288 | u64 virt_ctx; | 285 | u64 virt_ctx; |
289 | #endif | 286 | #endif |
290 | 287 | ||
291 | /* | ||
292 | * Signal channel owner via a callback, if set, in job cleanup with | ||
293 | * schedule_work. Means that something finished on the channel (perhaps | ||
294 | * more than one job). | ||
295 | */ | ||
296 | void (*update_fn)(struct channel_gk20a *, void *); | ||
297 | void *update_fn_data; | ||
298 | struct nvgpu_spinlock update_fn_lock; /* make access to the two above atomic */ | ||
299 | struct work_struct update_fn_work; | ||
300 | |||
301 | u32 interleave_level; | 288 | u32 interleave_level; |
302 | 289 | ||
303 | u32 runlist_id; | 290 | u32 runlist_id; |
@@ -306,6 +293,9 @@ struct channel_gk20a { | |||
306 | #ifdef CONFIG_TEGRA_19x_GPU | 293 | #ifdef CONFIG_TEGRA_19x_GPU |
307 | struct channel_t19x t19x; | 294 | struct channel_t19x t19x; |
308 | #endif | 295 | #endif |
296 | |||
297 | /* Any operating system specific data. */ | ||
298 | void *os_priv; | ||
309 | }; | 299 | }; |
310 | 300 | ||
311 | static inline struct channel_gk20a * | 301 | static inline struct channel_gk20a * |
@@ -382,11 +372,6 @@ int gk20a_wait_channel_idle(struct channel_gk20a *ch); | |||
382 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, | 372 | struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g, |
383 | s32 runlist_id, | 373 | s32 runlist_id, |
384 | bool is_privileged_channel); | 374 | bool is_privileged_channel); |
385 | struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, | ||
386 | void (*update_fn)(struct channel_gk20a *, void *), | ||
387 | void *update_fn_data, | ||
388 | int runlist_id, | ||
389 | bool is_privileged_channel); | ||
390 | 375 | ||
391 | int gk20a_channel_alloc_gpfifo(struct channel_gk20a *c, | 376 | int gk20a_channel_alloc_gpfifo(struct channel_gk20a *c, |
392 | unsigned int num_entries, | 377 | 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 { | |||
1255 | struct nvgpu_mutex start_lock; | 1255 | struct nvgpu_mutex start_lock; |
1256 | } channel_worker; | 1256 | } channel_worker; |
1257 | 1257 | ||
1258 | struct { | ||
1259 | void (*open)(struct channel_gk20a *ch); | ||
1260 | void (*close)(struct channel_gk20a *ch); | ||
1261 | void (*work_completion_signal)(struct channel_gk20a *ch); | ||
1262 | void (*work_completion_cancel_sync)(struct channel_gk20a *ch); | ||
1263 | } os_channel; | ||
1264 | |||
1258 | struct gk20a_scale_profile *scale_profile; | 1265 | struct gk20a_scale_profile *scale_profile; |
1259 | unsigned long last_freq; | 1266 | unsigned long last_freq; |
1260 | 1267 | ||