summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common
diff options
context:
space:
mode:
authorKonsta Holtta <kholtta@nvidia.com>2017-11-22 08:57:11 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2017-11-22 20:18:56 -0500
commitba2e59dc41f593bb011e0ec58c969337a35f4cf1 (patch)
tree12a4fcec144516a0e903e5495898e9072d7db27c /drivers/gpu/nvgpu/common
parentb498f4c5c0a0a5f1a59a9210a1ee4d1d8ae98be7 (diff)
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 <kholtta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1589321 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common')
-rw-r--r--drivers/gpu/nvgpu/common/linux/channel.c157
-rw-r--r--drivers/gpu/nvgpu/common/linux/channel.h32
-rw-r--r--drivers/gpu/nvgpu/common/linux/module.c26
-rw-r--r--drivers/gpu/nvgpu/common/linux/os_linux.h2
4 files changed, 217 insertions, 0 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
40static 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
60static 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
70static 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
81static 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
89static 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
97struct 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
119static void nvgpu_channel_open_linux(struct channel_gk20a *ch)
120{
121}
122
123static void nvgpu_channel_close_linux(struct channel_gk20a *ch)
124{
125 nvgpu_channel_work_completion_clear(ch);
126}
127
128static 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
144static void nvgpu_channel_free_linux(struct gk20a *g, struct channel_gk20a *ch)
145{
146 nvgpu_kfree(g, ch->os_priv);
147}
148
149int 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
172err_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
181void 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
37u32 nvgpu_get_gpfifo_entry_size(void) 194u32 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
21struct channel_gk20a; 23struct channel_gk20a;
@@ -24,6 +26,36 @@ struct nvgpu_submit_gpfifo_args;
24struct nvgpu_fence; 26struct nvgpu_fence;
25struct gk20a_fence; 27struct gk20a_fence;
26struct fifo_profile_gk20a; 28struct fifo_profile_gk20a;
29struct nvgpu_os_linux;
30
31struct 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
45struct nvgpu_channel_linux {
46 struct channel_gk20a *ch;
47
48 struct nvgpu_channel_completion_cb completion_cb;
49};
50
51int nvgpu_init_channel_support_linux(struct nvgpu_os_linux *l);
52void nvgpu_remove_channel_support_linux(struct nvgpu_os_linux *l);
53
54struct 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
28int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, 60int 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
189static 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
188int gk20a_pm_finalize_poweron(struct device *dev) 208int 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
154static inline struct nvgpu_os_linux *nvgpu_os_linux_from_gk20a(struct gk20a *g) 156static inline struct nvgpu_os_linux *nvgpu_os_linux_from_gk20a(struct gk20a *g)