summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h')
-rw-r--r--drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h318
1 files changed, 0 insertions, 318 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h b/drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h
deleted file mode 100644
index 8e09fcfc..00000000
--- a/drivers/gpu/nvgpu/gk20a/semaphore_gk20a.h
+++ /dev/null
@@ -1,318 +0,0 @@
1/*
2 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#ifndef SEMAPHORE_GK20A_H
15#define SEMAPHORE_GK20A_H
16
17#include <linux/kref.h>
18#include <linux/list.h>
19#include <linux/delay.h>
20
21#include <nvgpu/allocator.h>
22
23#include "gk20a.h"
24#include "mm_gk20a.h"
25#include "channel_gk20a.h"
26
27#define gpu_sema_dbg(fmt, args...) \
28 gk20a_dbg(gpu_dbg_sema, fmt, ##args)
29#define gpu_sema_verbose_dbg(fmt, args...) \
30 gk20a_dbg(gpu_dbg_sema_v, fmt, ##args)
31
32/*
33 * Max number of channels that can be used is 512. This of course needs to be
34 * fixed to be dynamic but still fast.
35 */
36#define SEMAPHORE_POOL_COUNT 512
37#define SEMAPHORE_SIZE 16
38#define SEMAPHORE_SEA_GROWTH_RATE 32
39
40struct gk20a_semaphore_sea;
41
42/*
43 * Underlying semaphore data structure. This semaphore can be shared amongst
44 * other semaphore instances.
45 */
46struct gk20a_semaphore_int {
47 int idx; /* Semaphore index. */
48 u32 offset; /* Offset into the pool. */
49 atomic_t next_value; /* Next available value. */
50 u32 *value; /* Current value (access w/ readl()). */
51 u32 nr_incrs; /* Number of increments programmed. */
52 struct gk20a_semaphore_pool *p; /* Pool that owns this sema. */
53 struct channel_gk20a *ch; /* Channel that owns this sema. */
54 struct list_head hw_sema_list; /* List of HW semaphores. */
55};
56
57/*
58 * A semaphore which the rest of the driver actually uses. This consists of a
59 * pointer to a real semaphore and a value to wait for. This allows one physical
60 * semaphore to be shared among an essentially infinite number of submits.
61 */
62struct gk20a_semaphore {
63 struct gk20a_semaphore_int *hw_sema;
64
65 atomic_t value;
66 int incremented;
67
68 struct kref ref;
69};
70
71/*
72 * A semaphore pool. Each address space will own exactly one of these.
73 */
74struct gk20a_semaphore_pool {
75 struct page *page; /* This pool's page of memory */
76 struct list_head pool_list_entry; /* Node for list of pools. */
77 void *cpu_va; /* CPU access to the pool. */
78 u64 gpu_va; /* GPU access to the pool. */
79 u64 gpu_va_ro; /* GPU access to the pool. */
80 int page_idx; /* Index into sea bitmap. */
81
82 struct list_head hw_semas; /* List of HW semas. */
83 DECLARE_BITMAP(semas_alloced, PAGE_SIZE / SEMAPHORE_SIZE);
84
85 struct gk20a_semaphore_sea *sema_sea; /* Sea that owns this pool. */
86
87 struct mutex pool_lock;
88
89 /*
90 * This is the address spaces's personal RW table. Other channels will
91 * ultimately map this page as RO.
92 */
93 struct sg_table *rw_sg_table;
94
95 /*
96 * This is to keep track of whether the pool has had its sg_table
97 * updated during sea resizing.
98 */
99 struct sg_table *ro_sg_table;
100
101 int mapped;
102
103 /*
104 * Sometimes a channel can be released before other channels are
105 * done waiting on it. This ref count ensures that the pool doesn't
106 * go away until all semaphores using this pool are cleaned up first.
107 */
108 struct kref ref;
109};
110
111/*
112 * A sea of semaphores pools. Each pool is owned by a single VM. Since multiple
113 * channels can share a VM each channel gets it's own HW semaphore from the
114 * pool. Channels then allocate regular semaphores - basically just a value that
115 * signifies when a particular job is done.
116 */
117struct gk20a_semaphore_sea {
118 struct list_head pool_list; /* List of pools in this sea. */
119 struct gk20a *gk20a;
120
121 size_t size; /* Number of pages available. */
122 u64 gpu_va; /* GPU virtual address of sema sea. */
123 u64 map_size; /* Size of the mapping. */
124
125 /*
126 * TODO:
127 * List of pages that we use to back the pools. The number of pages
128 * can grow dynamically since allocating 512 pages for all channels at
129 * once would be a tremendous waste.
130 */
131 int page_count; /* Pages allocated to pools. */
132
133 struct sg_table *ro_sg_table;
134 /*
135 struct page *pages[SEMAPHORE_POOL_COUNT];
136 */
137
138 struct mem_desc sea_mem;
139
140 /*
141 * Can't use a regular allocator here since the full range of pools are
142 * not always allocated. Instead just use a bitmap.
143 */
144 DECLARE_BITMAP(pools_alloced, SEMAPHORE_POOL_COUNT);
145
146 struct mutex sea_lock; /* Lock alloc/free calls. */
147};
148
149enum gk20a_mem_rw_flag {
150 gk20a_mem_flag_none = 0,
151 gk20a_mem_flag_read_only = 1,
152 gk20a_mem_flag_write_only = 2,
153};
154
155/*
156 * Semaphore sea functions.
157 */
158struct gk20a_semaphore_sea *gk20a_semaphore_sea_create(struct gk20a *gk20a);
159int gk20a_semaphore_sea_map(struct gk20a_semaphore_pool *sea,
160 struct vm_gk20a *vm);
161void gk20a_semaphore_sea_unmap(struct gk20a_semaphore_pool *sea,
162 struct vm_gk20a *vm);
163struct gk20a_semaphore_sea *gk20a_semaphore_get_sea(struct gk20a *g);
164
165/*
166 * Semaphore pool functions.
167 */
168struct gk20a_semaphore_pool *gk20a_semaphore_pool_alloc(
169 struct gk20a_semaphore_sea *sea);
170int gk20a_semaphore_pool_map(struct gk20a_semaphore_pool *pool,
171 struct vm_gk20a *vm);
172void gk20a_semaphore_pool_unmap(struct gk20a_semaphore_pool *pool,
173 struct vm_gk20a *vm);
174u64 __gk20a_semaphore_pool_gpu_va(struct gk20a_semaphore_pool *p, bool global);
175void gk20a_semaphore_pool_get(struct gk20a_semaphore_pool *p);
176void gk20a_semaphore_pool_put(struct gk20a_semaphore_pool *p);
177
178/*
179 * Semaphore functions.
180 */
181struct gk20a_semaphore *gk20a_semaphore_alloc(struct channel_gk20a *ch);
182void gk20a_semaphore_put(struct gk20a_semaphore *s);
183void gk20a_semaphore_get(struct gk20a_semaphore *s);
184void gk20a_semaphore_free_hw_sema(struct channel_gk20a *ch);
185
186/*
187 * Return the address of a specific semaphore.
188 *
189 * Don't call this on a semaphore you don't own - the VA returned will make no
190 * sense in your specific channel's VM.
191 */
192static inline u64 gk20a_semaphore_gpu_rw_va(struct gk20a_semaphore *s)
193{
194 return __gk20a_semaphore_pool_gpu_va(s->hw_sema->p, false) +
195 s->hw_sema->offset;
196}
197
198/*
199 * Get the global RO address for the semaphore. Can be called on any semaphore
200 * regardless of whether you own it.
201 */
202static inline u64 gk20a_semaphore_gpu_ro_va(struct gk20a_semaphore *s)
203{
204 return __gk20a_semaphore_pool_gpu_va(s->hw_sema->p, true) +
205 s->hw_sema->offset;
206}
207
208static inline u64 gk20a_hw_sema_addr(struct gk20a_semaphore_int *hw_sema)
209{
210 return __gk20a_semaphore_pool_gpu_va(hw_sema->p, true) +
211 hw_sema->offset;
212}
213
214/*
215 * TODO: handle wrap around... Hmm, how to do this?
216 */
217static inline bool gk20a_semaphore_is_released(struct gk20a_semaphore *s)
218{
219 u32 sema_val = readl(s->hw_sema->value);
220
221 /*
222 * If the underlying semaphore value is greater than or equal to
223 * the value of the semaphore then the semaphore has been signaled
224 * (a.k.a. released).
225 */
226 return (int)sema_val >= atomic_read(&s->value);
227}
228
229static inline bool gk20a_semaphore_is_acquired(struct gk20a_semaphore *s)
230{
231 return !gk20a_semaphore_is_released(s);
232}
233
234/*
235 * Read the underlying value from a semaphore.
236 */
237static inline u32 gk20a_semaphore_read(struct gk20a_semaphore *s)
238{
239 return readl(s->hw_sema->value);
240}
241
242static inline u32 gk20a_semaphore_get_value(struct gk20a_semaphore *s)
243{
244 return (u32)atomic_read(&s->value);
245}
246
247static inline u32 gk20a_semaphore_next_value(struct gk20a_semaphore *s)
248{
249 return (u32)atomic_read(&s->hw_sema->next_value);
250}
251
252/*
253 * If @force is set then this will not wait for the underlying semaphore to
254 * catch up to the passed semaphore.
255 */
256static inline void __gk20a_semaphore_release(struct gk20a_semaphore *s,
257 bool force)
258{
259 u32 current_val;
260 u32 val = gk20a_semaphore_get_value(s);
261 int attempts = 0;
262
263 /*
264 * Wait until the sema value is 1 less than the write value. That
265 * way this function is essentially an increment.
266 *
267 * TODO: tune the wait a little better.
268 */
269 while ((current_val = gk20a_semaphore_read(s)) < (val - 1)) {
270 if (force)
271 break;
272 msleep(100);
273 attempts += 1;
274 if (attempts > 100) {
275 WARN(1, "Stall on sema release!");
276 return;
277 }
278 }
279
280 /*
281 * If the semaphore has already passed the value we would write then
282 * this is really just a NO-OP.
283 */
284 if (current_val >= val)
285 return;
286
287 writel(val, s->hw_sema->value);
288
289 gpu_sema_verbose_dbg("(c=%d) WRITE %u",
290 s->hw_sema->ch->hw_chid, val);
291}
292
293static inline void gk20a_semaphore_release(struct gk20a_semaphore *s)
294{
295 __gk20a_semaphore_release(s, false);
296}
297
298/*
299 * Configure a software based increment on this semaphore. This is useful for
300 * when we want the GPU to wait on a SW event before processing a channel.
301 * Another way to describe this is when the GPU needs to wait on a SW pre-fence.
302 * The pre-fence signals SW which in turn calls gk20a_semaphore_release() which
303 * then allows the GPU to continue.
304 *
305 * Also used to prep a semaphore for an INCR by the GPU.
306 */
307static inline void gk20a_semaphore_incr(struct gk20a_semaphore *s)
308{
309 BUG_ON(s->incremented);
310
311 atomic_set(&s->value, atomic_add_return(1, &s->hw_sema->next_value));
312 s->incremented = 1;
313
314 gpu_sema_verbose_dbg("INCR sema for c=%d (%u)",
315 s->hw_sema->ch->hw_chid,
316 gk20a_semaphore_next_value(s));
317}
318#endif