summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.h')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.h431
1 files changed, 431 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
new file mode 100644
index 00000000..d865849b
--- /dev/null
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
@@ -0,0 +1,431 @@
1/*
2 * GK20A graphics channel
3 *
4 * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#ifndef CHANNEL_GK20A_H
25#define CHANNEL_GK20A_H
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>
31#include <nvgpu/lock.h>
32#include <nvgpu/timers.h>
33#include <nvgpu/cond.h>
34#include <nvgpu/atomic.h>
35
36struct gk20a;
37struct gr_gk20a;
38struct dbg_session_gk20a;
39struct gk20a_fence;
40struct fifo_profile_gk20a;
41
42#include "channel_sync_gk20a.h"
43
44#include "mm_gk20a.h"
45#include "gr_gk20a.h"
46#include "fence_gk20a.h"
47#ifdef CONFIG_TEGRA_19x_GPU
48#include "channel_t19x.h"
49#endif
50
51/* Flags to be passed to gk20a_channel_alloc_gpfifo() */
52#define NVGPU_GPFIFO_FLAGS_SUPPORT_VPR (1 << 0)
53#define NVGPU_GPFIFO_FLAGS_SUPPORT_DETERMINISTIC (1 << 1)
54
55/* Flags to be passed to g->ops.gr.alloc_obj_ctx() */
56#define NVGPU_OBJ_CTX_FLAGS_SUPPORT_GFXP (1 << 1)
57#define NVGPU_OBJ_CTX_FLAGS_SUPPORT_CILP (1 << 2)
58
59struct notification {
60 struct {
61 u32 nanoseconds[2];
62 } timestamp;
63 u32 info32;
64 u16 info16;
65 u16 status;
66};
67
68/* contexts associated with a channel */
69struct channel_ctx_gk20a {
70 struct gr_ctx_desc *gr_ctx;
71 struct patch_desc patch_ctx;
72 struct zcull_ctx_desc zcull_ctx;
73 struct pm_ctx_desc pm_ctx;
74 u64 global_ctx_buffer_va[NR_GLOBAL_CTX_BUF_VA];
75 u64 global_ctx_buffer_size[NR_GLOBAL_CTX_BUF_VA];
76 int global_ctx_buffer_index[NR_GLOBAL_CTX_BUF_VA];
77 bool global_ctx_buffer_mapped;
78 struct ctx_header_desc ctx_header;
79};
80
81struct channel_gk20a_job {
82 struct nvgpu_mapped_buf **mapped_buffers;
83 int num_mapped_buffers;
84 struct gk20a_fence *pre_fence;
85 struct gk20a_fence *post_fence;
86 struct priv_cmd_entry *wait_cmd;
87 struct priv_cmd_entry *incr_cmd;
88 struct nvgpu_list_node list;
89};
90
91static inline struct channel_gk20a_job *
92channel_gk20a_job_from_list(struct nvgpu_list_node *node)
93{
94 return (struct channel_gk20a_job *)
95 ((uintptr_t)node - offsetof(struct channel_gk20a_job, list));
96};
97
98struct channel_gk20a_joblist {
99 struct {
100 bool enabled;
101 unsigned int length;
102 unsigned int put;
103 unsigned int get;
104 struct channel_gk20a_job *jobs;
105 struct nvgpu_mutex read_lock;
106 } pre_alloc;
107
108 struct {
109 struct nvgpu_list_node jobs;
110 struct nvgpu_spinlock lock;
111 } dynamic;
112
113 /*
114 * Synchronize abort cleanup (when closing a channel) and job cleanup
115 * (asynchronously from worker) - protect from concurrent access when
116 * job resources are being freed.
117 */
118 struct nvgpu_mutex cleanup_lock;
119};
120
121struct channel_gk20a_timeout {
122 struct nvgpu_raw_spinlock lock;
123 struct nvgpu_timeout timer;
124 bool running;
125 u32 gp_get;
126 u64 pb_get;
127};
128
129struct gk20a_event_id_data {
130 struct gk20a *g;
131
132 int id; /* ch or tsg */
133 bool is_tsg;
134 u32 event_id;
135
136 bool event_posted;
137
138 struct nvgpu_cond event_id_wq;
139 struct nvgpu_mutex lock;
140 struct nvgpu_list_node event_id_node;
141};
142
143static inline struct gk20a_event_id_data *
144gk20a_event_id_data_from_event_id_node(struct nvgpu_list_node *node)
145{
146 return (struct gk20a_event_id_data *)
147 ((uintptr_t)node - offsetof(struct gk20a_event_id_data, event_id_node));
148};
149
150/*
151 * Track refcount actions, saving their stack traces. This number specifies how
152 * many most recent actions are stored in a buffer. Set to 0 to disable. 128
153 * should be enough to track moderately hard problems from the start.
154 */
155#define GK20A_CHANNEL_REFCOUNT_TRACKING 0
156/* Stack depth for the saved actions. */
157#define GK20A_CHANNEL_REFCOUNT_TRACKING_STACKLEN 8
158
159/*
160 * Because the puts and gets are not linked together explicitly (although they
161 * should always come in pairs), it's not possible to tell which ref holder to
162 * delete from the list when doing a put. So, just store some number of most
163 * recent gets and puts in a ring buffer, to obtain a history.
164 *
165 * These are zeroed when a channel is closed, so a new one starts fresh.
166 */
167
168enum channel_gk20a_ref_action_type {
169 channel_gk20a_ref_action_get,
170 channel_gk20a_ref_action_put
171};
172
173#if GK20A_CHANNEL_REFCOUNT_TRACKING
174
175#include <linux/stacktrace.h>
176
177struct channel_gk20a_ref_action {
178 enum channel_gk20a_ref_action_type type;
179 s64 timestamp_ms;
180 /*
181 * Many of these traces will be similar. Simpler to just capture
182 * duplicates than to have a separate database for the entries.
183 */
184 struct stack_trace trace;
185 unsigned long trace_entries[GK20A_CHANNEL_REFCOUNT_TRACKING_STACKLEN];
186};
187#endif
188
189/* this is the priv element of struct nvhost_channel */
190struct channel_gk20a {
191 struct gk20a *g; /* set only when channel is active */
192
193 struct nvgpu_list_node free_chs;
194
195 struct nvgpu_spinlock ref_obtain_lock;
196 bool referenceable;
197 nvgpu_atomic_t ref_count;
198 struct nvgpu_cond ref_count_dec_wq;
199#if GK20A_CHANNEL_REFCOUNT_TRACKING
200 /*
201 * Ring buffer for most recent refcount gets and puts. Protected by
202 * ref_actions_lock when getting or putting refs (i.e., adding
203 * entries), and when reading entries.
204 */
205 struct channel_gk20a_ref_action ref_actions[
206 GK20A_CHANNEL_REFCOUNT_TRACKING];
207 size_t ref_actions_put; /* index of next write */
208 struct nvgpu_spinlock ref_actions_lock;
209#endif
210
211 struct nvgpu_semaphore_int *hw_sema;
212
213 int chid;
214 bool wdt_enabled;
215 nvgpu_atomic_t bound;
216 bool first_init;
217 bool vpr;
218 bool deterministic;
219 /* deterministic, but explicitly idle and submits disallowed */
220 bool deterministic_railgate_allowed;
221 bool cde;
222 pid_t pid;
223 pid_t tgid;
224 struct nvgpu_mutex ioctl_lock;
225
226 int tsgid;
227 struct nvgpu_list_node ch_entry; /* channel's entry in TSG */
228
229 struct channel_gk20a_joblist joblist;
230 struct nvgpu_allocator fence_allocator;
231
232 struct vm_gk20a *vm;
233
234 struct gpfifo_desc gpfifo;
235
236 struct channel_ctx_gk20a ch_ctx;
237
238 struct nvgpu_mem inst_block;
239
240 u64 userd_iova;
241 u64 userd_gpu_va;
242
243 u32 obj_class; /* we support only one obj per channel */
244
245 struct priv_cmd_queue priv_cmd_q;
246
247 struct nvgpu_cond notifier_wq;
248 struct nvgpu_cond semaphore_wq;
249
250 u32 timeout_accumulated_ms;
251 u32 timeout_gpfifo_get;
252
253 struct channel_gk20a_timeout timeout;
254 /* for job cleanup handling in the background worker */
255 struct nvgpu_list_node worker_item;
256
257#if defined(CONFIG_GK20A_CYCLE_STATS)
258 struct {
259 void *cyclestate_buffer;
260 u32 cyclestate_buffer_size;
261 struct dma_buf *cyclestate_buffer_handler;
262 struct nvgpu_mutex cyclestate_buffer_mutex;
263 } cyclestate;
264
265 struct nvgpu_mutex cs_client_mutex;
266 struct gk20a_cs_snapshot_client *cs_client;
267#endif
268 struct nvgpu_mutex dbg_s_lock;
269 struct nvgpu_list_node dbg_s_list;
270
271 struct nvgpu_list_node event_id_list;
272 struct nvgpu_mutex event_id_list_lock;
273
274 bool has_timedout;
275 u32 timeout_ms_max;
276 bool timeout_debug_dump;
277 unsigned int timeslice_us;
278
279 struct dma_buf *error_notifier_ref;
280 struct nvgpu_notification *error_notifier;
281 void *error_notifier_va;
282 struct nvgpu_mutex error_notifier_mutex;
283
284 struct nvgpu_mutex sync_lock;
285 struct gk20a_channel_sync *sync;
286
287#ifdef CONFIG_TEGRA_GR_VIRTUALIZATION
288 u64 virt_ctx;
289#endif
290
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;
302
303 u32 runlist_id;
304
305 bool is_privileged_channel;
306#ifdef CONFIG_TEGRA_19x_GPU
307 struct channel_t19x t19x;
308#endif
309};
310
311static inline struct channel_gk20a *
312channel_gk20a_from_free_chs(struct nvgpu_list_node *node)
313{
314 return (struct channel_gk20a *)
315 ((uintptr_t)node - offsetof(struct channel_gk20a, free_chs));
316};
317
318static inline struct channel_gk20a *
319channel_gk20a_from_ch_entry(struct nvgpu_list_node *node)
320{
321 return (struct channel_gk20a *)
322 ((uintptr_t)node - offsetof(struct channel_gk20a, ch_entry));
323};
324
325static inline struct channel_gk20a *
326channel_gk20a_from_worker_item(struct nvgpu_list_node *node)
327{
328 return (struct channel_gk20a *)
329 ((uintptr_t)node - offsetof(struct channel_gk20a, worker_item));
330};
331
332static inline bool gk20a_channel_as_bound(struct channel_gk20a *ch)
333{
334 return !!ch->vm;
335}
336int channel_gk20a_commit_va(struct channel_gk20a *c);
337int gk20a_init_channel_support(struct gk20a *, u32 chid);
338
339/* must be inside gk20a_busy()..gk20a_idle() */
340void gk20a_channel_close(struct channel_gk20a *ch);
341void __gk20a_channel_kill(struct channel_gk20a *ch);
342
343bool gk20a_channel_update_and_check_timeout(struct channel_gk20a *ch,
344 u32 timeout_delta_ms, bool *progress);
345void gk20a_disable_channel(struct channel_gk20a *ch);
346void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt);
347void gk20a_channel_abort_clean_up(struct channel_gk20a *ch);
348void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error);
349void gk20a_set_error_notifier_locked(struct channel_gk20a *ch, __u32 error);
350void gk20a_channel_semaphore_wakeup(struct gk20a *g, bool post_events);
351int gk20a_channel_alloc_priv_cmdbuf(struct channel_gk20a *c, u32 size,
352 struct priv_cmd_entry *entry);
353int gk20a_free_priv_cmdbuf(struct channel_gk20a *c, struct priv_cmd_entry *e);
354
355int gk20a_enable_channel_tsg(struct gk20a *g, struct channel_gk20a *ch);
356int gk20a_disable_channel_tsg(struct gk20a *g, struct channel_gk20a *ch);
357
358int gk20a_channel_suspend(struct gk20a *g);
359int gk20a_channel_resume(struct gk20a *g);
360
361void gk20a_channel_deterministic_idle(struct gk20a *g);
362void gk20a_channel_deterministic_unidle(struct gk20a *g);
363
364int nvgpu_channel_worker_init(struct gk20a *g);
365void nvgpu_channel_worker_deinit(struct gk20a *g);
366
367struct channel_gk20a *gk20a_get_channel_from_file(int fd);
368void gk20a_channel_update(struct channel_gk20a *c);
369
370/* returns ch if reference was obtained */
371struct channel_gk20a *__must_check _gk20a_channel_get(struct channel_gk20a *ch,
372 const char *caller);
373#define gk20a_channel_get(ch) _gk20a_channel_get(ch, __func__)
374
375
376void _gk20a_channel_put(struct channel_gk20a *ch, const char *caller);
377#define gk20a_channel_put(ch) _gk20a_channel_put(ch, __func__)
378
379int gk20a_wait_channel_idle(struct channel_gk20a *ch);
380
381/* runlist_id -1 is synonym for ENGINE_GR_GK20A runlist id */
382struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g,
383 s32 runlist_id,
384 bool is_privileged_channel);
385struct 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
391int gk20a_channel_alloc_gpfifo(struct channel_gk20a *c,
392 unsigned int num_entries,
393 unsigned int num_inflight_jobs,
394 u32 flags);
395void gk20a_channel_free_cycle_stats_buffer(struct channel_gk20a *ch);
396int gk20a_channel_free_cycle_stats_snapshot(struct channel_gk20a *ch);
397
398void gk20a_channel_timeout_restart_all_channels(struct gk20a *g);
399
400bool channel_gk20a_is_prealloc_enabled(struct channel_gk20a *c);
401void channel_gk20a_joblist_lock(struct channel_gk20a *c);
402void channel_gk20a_joblist_unlock(struct channel_gk20a *c);
403bool channel_gk20a_joblist_is_empty(struct channel_gk20a *c);
404
405int channel_gk20a_update_runlist(struct channel_gk20a *c, bool add);
406u32 gk20a_channel_get_timeslice(struct channel_gk20a *ch);
407int gk20a_channel_get_timescale_from_timeslice(struct gk20a *g,
408 int timeslice_period,
409 int *__timeslice_timeout, int *__timeslice_scale);
410int gk20a_channel_set_runlist_interleave(struct channel_gk20a *ch,
411 u32 level);
412void gk20a_channel_event_id_post_event(struct channel_gk20a *ch,
413 u32 event_id);
414
415int channel_gk20a_alloc_job(struct channel_gk20a *c,
416 struct channel_gk20a_job **job_out);
417void channel_gk20a_free_job(struct channel_gk20a *c,
418 struct channel_gk20a_job *job);
419u32 nvgpu_get_gp_free_count(struct channel_gk20a *c);
420u32 nvgpu_gp_free_count(struct channel_gk20a *c);
421int gk20a_channel_add_job(struct channel_gk20a *c,
422 struct channel_gk20a_job *job,
423 bool skip_buffer_refcounting);
424void free_priv_cmdbuf(struct channel_gk20a *c,
425 struct priv_cmd_entry *e);
426void gk20a_channel_clean_up_jobs(struct channel_gk20a *c,
427 bool clean_all);
428
429u32 nvgpu_get_gpfifo_entry_size(void);
430
431#endif /* CHANNEL_GK20A_H */