blob: d0c6bfb68c4ee9d88c2a026e5908915d331733db [file] [log] [blame]
Eric Anholtd5b1a782015-11-30 12:13:37 -08001/*
2 * Copyright © 2014 Broadcom
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
Eric Anholt001bdb52016-02-05 17:41:49 -080026#include <linux/pm_runtime.h>
Eric Anholtd5b1a782015-11-30 12:13:37 -080027#include <linux/device.h>
28#include <linux/io.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010029#include <linux/sched/signal.h>
Eric Anholtd5b1a782015-11-30 12:13:37 -080030
31#include "uapi/drm/vc4_drm.h"
32#include "vc4_drv.h"
33#include "vc4_regs.h"
34#include "vc4_trace.h"
35
36static void
37vc4_queue_hangcheck(struct drm_device *dev)
38{
39 struct vc4_dev *vc4 = to_vc4_dev(dev);
40
41 mod_timer(&vc4->hangcheck.timer,
42 round_jiffies_up(jiffies + msecs_to_jiffies(100)));
43}
44
Eric Anholt21461362015-10-30 10:09:02 -070045struct vc4_hang_state {
46 struct drm_vc4_get_hang_state user_state;
47
48 u32 bo_count;
49 struct drm_gem_object **bo;
50};
51
52static void
53vc4_free_hang_state(struct drm_device *dev, struct vc4_hang_state *state)
54{
55 unsigned int i;
56
Eric Anholt21461362015-10-30 10:09:02 -070057 for (i = 0; i < state->user_state.bo_count; i++)
Cihangir Akturk1d5494e2017-08-03 14:58:40 +030058 drm_gem_object_put_unlocked(state->bo[i]);
Eric Anholt21461362015-10-30 10:09:02 -070059
60 kfree(state);
61}
62
63int
64vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
65 struct drm_file *file_priv)
66{
67 struct drm_vc4_get_hang_state *get_state = data;
68 struct drm_vc4_get_hang_state_bo *bo_state;
69 struct vc4_hang_state *kernel_state;
70 struct drm_vc4_get_hang_state *state;
71 struct vc4_dev *vc4 = to_vc4_dev(dev);
72 unsigned long irqflags;
73 u32 i;
Dan Carpenter65c47772015-12-17 15:36:28 +030074 int ret = 0;
Eric Anholt21461362015-10-30 10:09:02 -070075
76 spin_lock_irqsave(&vc4->job_lock, irqflags);
77 kernel_state = vc4->hang_state;
78 if (!kernel_state) {
79 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
80 return -ENOENT;
81 }
82 state = &kernel_state->user_state;
83
84 /* If the user's array isn't big enough, just return the
85 * required array size.
86 */
87 if (get_state->bo_count < state->bo_count) {
88 get_state->bo_count = state->bo_count;
89 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
90 return 0;
91 }
92
93 vc4->hang_state = NULL;
94 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
95
96 /* Save the user's BO pointer, so we don't stomp it with the memcpy. */
97 state->bo = get_state->bo;
98 memcpy(get_state, state, sizeof(*state));
99
100 bo_state = kcalloc(state->bo_count, sizeof(*bo_state), GFP_KERNEL);
101 if (!bo_state) {
102 ret = -ENOMEM;
103 goto err_free;
104 }
105
106 for (i = 0; i < state->bo_count; i++) {
107 struct vc4_bo *vc4_bo = to_vc4_bo(kernel_state->bo[i]);
108 u32 handle;
109
110 ret = drm_gem_handle_create(file_priv, kernel_state->bo[i],
111 &handle);
112
113 if (ret) {
Christophe JAILLETd0b1d252017-05-12 14:38:03 +0200114 state->bo_count = i;
115 goto err_delete_handle;
Eric Anholt21461362015-10-30 10:09:02 -0700116 }
117 bo_state[i].handle = handle;
118 bo_state[i].paddr = vc4_bo->base.paddr;
119 bo_state[i].size = vc4_bo->base.base.size;
120 }
121
Eric Anholt95d7cbc2017-07-25 11:27:16 -0700122 if (copy_to_user(u64_to_user_ptr(get_state->bo),
Dan Carpenter65c47772015-12-17 15:36:28 +0300123 bo_state,
124 state->bo_count * sizeof(*bo_state)))
125 ret = -EFAULT;
126
Christophe JAILLETd0b1d252017-05-12 14:38:03 +0200127err_delete_handle:
128 if (ret) {
129 for (i = 0; i < state->bo_count; i++)
130 drm_gem_handle_delete(file_priv, bo_state[i].handle);
131 }
Eric Anholt21461362015-10-30 10:09:02 -0700132
133err_free:
Eric Anholt21461362015-10-30 10:09:02 -0700134 vc4_free_hang_state(dev, kernel_state);
Christophe JAILLETd0b1d252017-05-12 14:38:03 +0200135 kfree(bo_state);
Eric Anholt21461362015-10-30 10:09:02 -0700136
Eric Anholt21461362015-10-30 10:09:02 -0700137 return ret;
138}
139
140static void
141vc4_save_hang_state(struct drm_device *dev)
142{
143 struct vc4_dev *vc4 = to_vc4_dev(dev);
144 struct drm_vc4_get_hang_state *state;
145 struct vc4_hang_state *kernel_state;
Varad Gautamca26d282016-02-17 19:08:21 +0530146 struct vc4_exec_info *exec[2];
Eric Anholt21461362015-10-30 10:09:02 -0700147 struct vc4_bo *bo;
148 unsigned long irqflags;
Varad Gautamca26d282016-02-17 19:08:21 +0530149 unsigned int i, j, unref_list_count, prev_idx;
Eric Anholt21461362015-10-30 10:09:02 -0700150
Dan Carpenter7e5082f2015-12-17 15:39:08 +0300151 kernel_state = kcalloc(1, sizeof(*kernel_state), GFP_KERNEL);
Eric Anholt21461362015-10-30 10:09:02 -0700152 if (!kernel_state)
153 return;
154
155 state = &kernel_state->user_state;
156
157 spin_lock_irqsave(&vc4->job_lock, irqflags);
Varad Gautamca26d282016-02-17 19:08:21 +0530158 exec[0] = vc4_first_bin_job(vc4);
159 exec[1] = vc4_first_render_job(vc4);
160 if (!exec[0] && !exec[1]) {
Eric Anholt21461362015-10-30 10:09:02 -0700161 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
162 return;
163 }
164
Varad Gautamca26d282016-02-17 19:08:21 +0530165 /* Get the bos from both binner and renderer into hang state. */
166 state->bo_count = 0;
167 for (i = 0; i < 2; i++) {
168 if (!exec[i])
169 continue;
Eric Anholt21461362015-10-30 10:09:02 -0700170
Varad Gautamca26d282016-02-17 19:08:21 +0530171 unref_list_count = 0;
172 list_for_each_entry(bo, &exec[i]->unref_list, unref_head)
173 unref_list_count++;
174 state->bo_count += exec[i]->bo_count + unref_list_count;
175 }
176
177 kernel_state->bo = kcalloc(state->bo_count,
178 sizeof(*kernel_state->bo), GFP_ATOMIC);
179
Eric Anholt21461362015-10-30 10:09:02 -0700180 if (!kernel_state->bo) {
181 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
182 return;
183 }
184
Varad Gautamca26d282016-02-17 19:08:21 +0530185 prev_idx = 0;
186 for (i = 0; i < 2; i++) {
187 if (!exec[i])
188 continue;
189
190 for (j = 0; j < exec[i]->bo_count; j++) {
Cihangir Akturk1d5494e2017-08-03 14:58:40 +0300191 drm_gem_object_get(&exec[i]->bo[j]->base);
Varad Gautamca26d282016-02-17 19:08:21 +0530192 kernel_state->bo[j + prev_idx] = &exec[i]->bo[j]->base;
193 }
194
195 list_for_each_entry(bo, &exec[i]->unref_list, unref_head) {
Cihangir Akturk1d5494e2017-08-03 14:58:40 +0300196 drm_gem_object_get(&bo->base.base);
Varad Gautamca26d282016-02-17 19:08:21 +0530197 kernel_state->bo[j + prev_idx] = &bo->base.base;
198 j++;
199 }
200 prev_idx = j + 1;
Eric Anholt21461362015-10-30 10:09:02 -0700201 }
202
Varad Gautamca26d282016-02-17 19:08:21 +0530203 if (exec[0])
204 state->start_bin = exec[0]->ct0ca;
205 if (exec[1])
206 state->start_render = exec[1]->ct1ca;
Eric Anholt21461362015-10-30 10:09:02 -0700207
208 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
209
210 state->ct0ca = V3D_READ(V3D_CTNCA(0));
211 state->ct0ea = V3D_READ(V3D_CTNEA(0));
212
213 state->ct1ca = V3D_READ(V3D_CTNCA(1));
214 state->ct1ea = V3D_READ(V3D_CTNEA(1));
215
216 state->ct0cs = V3D_READ(V3D_CTNCS(0));
217 state->ct1cs = V3D_READ(V3D_CTNCS(1));
218
219 state->ct0ra0 = V3D_READ(V3D_CT00RA0);
220 state->ct1ra0 = V3D_READ(V3D_CT01RA0);
221
222 state->bpca = V3D_READ(V3D_BPCA);
223 state->bpcs = V3D_READ(V3D_BPCS);
224 state->bpoa = V3D_READ(V3D_BPOA);
225 state->bpos = V3D_READ(V3D_BPOS);
226
227 state->vpmbase = V3D_READ(V3D_VPMBASE);
228
229 state->dbge = V3D_READ(V3D_DBGE);
230 state->fdbgo = V3D_READ(V3D_FDBGO);
231 state->fdbgb = V3D_READ(V3D_FDBGB);
232 state->fdbgr = V3D_READ(V3D_FDBGR);
233 state->fdbgs = V3D_READ(V3D_FDBGS);
234 state->errstat = V3D_READ(V3D_ERRSTAT);
235
236 spin_lock_irqsave(&vc4->job_lock, irqflags);
237 if (vc4->hang_state) {
238 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
239 vc4_free_hang_state(dev, kernel_state);
240 } else {
241 vc4->hang_state = kernel_state;
242 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
243 }
244}
245
Eric Anholtd5b1a782015-11-30 12:13:37 -0800246static void
247vc4_reset(struct drm_device *dev)
248{
249 struct vc4_dev *vc4 = to_vc4_dev(dev);
250
251 DRM_INFO("Resetting GPU.\n");
Eric Anholt36cb6252016-02-08 12:59:02 -0800252
253 mutex_lock(&vc4->power_lock);
254 if (vc4->power_refcount) {
255 /* Power the device off and back on the by dropping the
256 * reference on runtime PM.
257 */
258 pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev);
259 pm_runtime_get_sync(&vc4->v3d->pdev->dev);
260 }
261 mutex_unlock(&vc4->power_lock);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800262
263 vc4_irq_reset(dev);
264
265 /* Rearm the hangcheck -- another job might have been waiting
266 * for our hung one to get kicked off, and vc4_irq_reset()
267 * would have started it.
268 */
269 vc4_queue_hangcheck(dev);
270}
271
272static void
273vc4_reset_work(struct work_struct *work)
274{
275 struct vc4_dev *vc4 =
276 container_of(work, struct vc4_dev, hangcheck.reset_work);
277
Eric Anholt21461362015-10-30 10:09:02 -0700278 vc4_save_hang_state(vc4->dev);
279
Eric Anholtd5b1a782015-11-30 12:13:37 -0800280 vc4_reset(vc4->dev);
281}
282
283static void
284vc4_hangcheck_elapsed(unsigned long data)
285{
286 struct drm_device *dev = (struct drm_device *)data;
287 struct vc4_dev *vc4 = to_vc4_dev(dev);
288 uint32_t ct0ca, ct1ca;
Eric Anholtc4ce60d2016-02-08 11:19:14 -0800289 unsigned long irqflags;
Varad Gautamca26d282016-02-17 19:08:21 +0530290 struct vc4_exec_info *bin_exec, *render_exec;
Eric Anholtc4ce60d2016-02-08 11:19:14 -0800291
292 spin_lock_irqsave(&vc4->job_lock, irqflags);
Varad Gautamca26d282016-02-17 19:08:21 +0530293
294 bin_exec = vc4_first_bin_job(vc4);
295 render_exec = vc4_first_render_job(vc4);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800296
297 /* If idle, we can stop watching for hangs. */
Varad Gautamca26d282016-02-17 19:08:21 +0530298 if (!bin_exec && !render_exec) {
Eric Anholtc4ce60d2016-02-08 11:19:14 -0800299 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800300 return;
Eric Anholtc4ce60d2016-02-08 11:19:14 -0800301 }
Eric Anholtd5b1a782015-11-30 12:13:37 -0800302
303 ct0ca = V3D_READ(V3D_CTNCA(0));
304 ct1ca = V3D_READ(V3D_CTNCA(1));
305
306 /* If we've made any progress in execution, rearm the timer
307 * and wait.
308 */
Varad Gautamca26d282016-02-17 19:08:21 +0530309 if ((bin_exec && ct0ca != bin_exec->last_ct0ca) ||
310 (render_exec && ct1ca != render_exec->last_ct1ca)) {
311 if (bin_exec)
312 bin_exec->last_ct0ca = ct0ca;
313 if (render_exec)
314 render_exec->last_ct1ca = ct1ca;
Eric Anholtc4ce60d2016-02-08 11:19:14 -0800315 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800316 vc4_queue_hangcheck(dev);
317 return;
318 }
319
Eric Anholtc4ce60d2016-02-08 11:19:14 -0800320 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
321
Eric Anholtd5b1a782015-11-30 12:13:37 -0800322 /* We've gone too long with no progress, reset. This has to
323 * be done from a work struct, since resetting can sleep and
324 * this timer hook isn't allowed to.
325 */
326 schedule_work(&vc4->hangcheck.reset_work);
327}
328
329static void
330submit_cl(struct drm_device *dev, uint32_t thread, uint32_t start, uint32_t end)
331{
332 struct vc4_dev *vc4 = to_vc4_dev(dev);
333
334 /* Set the current and end address of the control list.
335 * Writing the end register is what starts the job.
336 */
337 V3D_WRITE(V3D_CTNCA(thread), start);
338 V3D_WRITE(V3D_CTNEA(thread), end);
339}
340
341int
342vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns,
343 bool interruptible)
344{
345 struct vc4_dev *vc4 = to_vc4_dev(dev);
346 int ret = 0;
347 unsigned long timeout_expire;
348 DEFINE_WAIT(wait);
349
350 if (vc4->finished_seqno >= seqno)
351 return 0;
352
353 if (timeout_ns == 0)
354 return -ETIME;
355
356 timeout_expire = jiffies + nsecs_to_jiffies(timeout_ns);
357
358 trace_vc4_wait_for_seqno_begin(dev, seqno, timeout_ns);
359 for (;;) {
360 prepare_to_wait(&vc4->job_wait_queue, &wait,
361 interruptible ? TASK_INTERRUPTIBLE :
362 TASK_UNINTERRUPTIBLE);
363
364 if (interruptible && signal_pending(current)) {
365 ret = -ERESTARTSYS;
366 break;
367 }
368
369 if (vc4->finished_seqno >= seqno)
370 break;
371
372 if (timeout_ns != ~0ull) {
373 if (time_after_eq(jiffies, timeout_expire)) {
374 ret = -ETIME;
375 break;
376 }
377 schedule_timeout(timeout_expire - jiffies);
378 } else {
379 schedule();
380 }
381 }
382
383 finish_wait(&vc4->job_wait_queue, &wait);
384 trace_vc4_wait_for_seqno_end(dev, seqno);
385
Eric Anholt13cf8902016-01-25 14:32:41 -0800386 return ret;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800387}
388
389static void
390vc4_flush_caches(struct drm_device *dev)
391{
392 struct vc4_dev *vc4 = to_vc4_dev(dev);
393
394 /* Flush the GPU L2 caches. These caches sit on top of system
395 * L3 (the 128kb or so shared with the CPU), and are
396 * non-allocating in the L3.
397 */
398 V3D_WRITE(V3D_L2CACTL,
399 V3D_L2CACTL_L2CCLR);
400
401 V3D_WRITE(V3D_SLCACTL,
402 VC4_SET_FIELD(0xf, V3D_SLCACTL_T1CC) |
403 VC4_SET_FIELD(0xf, V3D_SLCACTL_T0CC) |
404 VC4_SET_FIELD(0xf, V3D_SLCACTL_UCC) |
405 VC4_SET_FIELD(0xf, V3D_SLCACTL_ICC));
406}
407
408/* Sets the registers for the next job to be actually be executed in
409 * the hardware.
410 *
411 * The job_lock should be held during this.
412 */
413void
Varad Gautamca26d282016-02-17 19:08:21 +0530414vc4_submit_next_bin_job(struct drm_device *dev)
Eric Anholtd5b1a782015-11-30 12:13:37 -0800415{
416 struct vc4_dev *vc4 = to_vc4_dev(dev);
Varad Gautamca26d282016-02-17 19:08:21 +0530417 struct vc4_exec_info *exec;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800418
Varad Gautamca26d282016-02-17 19:08:21 +0530419again:
420 exec = vc4_first_bin_job(vc4);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800421 if (!exec)
422 return;
423
424 vc4_flush_caches(dev);
425
Varad Gautamca26d282016-02-17 19:08:21 +0530426 /* Either put the job in the binner if it uses the binner, or
427 * immediately move it to the to-be-rendered queue.
428 */
429 if (exec->ct0ca != exec->ct0ea) {
Eric Anholtd5b1a782015-11-30 12:13:37 -0800430 submit_cl(dev, 0, exec->ct0ca, exec->ct0ea);
Varad Gautamca26d282016-02-17 19:08:21 +0530431 } else {
432 vc4_move_job_to_render(dev, exec);
433 goto again;
434 }
435}
436
437void
438vc4_submit_next_render_job(struct drm_device *dev)
439{
440 struct vc4_dev *vc4 = to_vc4_dev(dev);
441 struct vc4_exec_info *exec = vc4_first_render_job(vc4);
442
443 if (!exec)
444 return;
445
Eric Anholtd5b1a782015-11-30 12:13:37 -0800446 submit_cl(dev, 1, exec->ct1ca, exec->ct1ea);
447}
448
Varad Gautamca26d282016-02-17 19:08:21 +0530449void
450vc4_move_job_to_render(struct drm_device *dev, struct vc4_exec_info *exec)
451{
452 struct vc4_dev *vc4 = to_vc4_dev(dev);
453 bool was_empty = list_empty(&vc4->render_job_list);
454
455 list_move_tail(&exec->head, &vc4->render_job_list);
456 if (was_empty)
457 vc4_submit_next_render_job(dev);
458}
459
Eric Anholtd5b1a782015-11-30 12:13:37 -0800460static void
461vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno)
462{
463 struct vc4_bo *bo;
464 unsigned i;
465
466 for (i = 0; i < exec->bo_count; i++) {
467 bo = to_vc4_bo(&exec->bo[i]->base);
468 bo->seqno = seqno;
Eric Anholtcdec4d32017-04-12 12:12:02 -0700469
470 reservation_object_add_shared_fence(bo->resv, exec->fence);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800471 }
472
473 list_for_each_entry(bo, &exec->unref_list, unref_head) {
474 bo->seqno = seqno;
475 }
Eric Anholt7edabee2016-09-27 09:03:13 -0700476
477 for (i = 0; i < exec->rcl_write_bo_count; i++) {
478 bo = to_vc4_bo(&exec->rcl_write_bo[i]->base);
479 bo->write_seqno = seqno;
Eric Anholtcdec4d32017-04-12 12:12:02 -0700480
481 reservation_object_add_excl_fence(bo->resv, exec->fence);
Eric Anholt7edabee2016-09-27 09:03:13 -0700482 }
Eric Anholtd5b1a782015-11-30 12:13:37 -0800483}
484
Eric Anholtcdec4d32017-04-12 12:12:02 -0700485static void
486vc4_unlock_bo_reservations(struct drm_device *dev,
487 struct vc4_exec_info *exec,
488 struct ww_acquire_ctx *acquire_ctx)
489{
490 int i;
491
492 for (i = 0; i < exec->bo_count; i++) {
493 struct vc4_bo *bo = to_vc4_bo(&exec->bo[i]->base);
494
495 ww_mutex_unlock(&bo->resv->lock);
496 }
497
498 ww_acquire_fini(acquire_ctx);
499}
500
501/* Takes the reservation lock on all the BOs being referenced, so that
502 * at queue submit time we can update the reservations.
503 *
504 * We don't lock the RCL the tile alloc/state BOs, or overflow memory
505 * (all of which are on exec->unref_list). They're entirely private
506 * to vc4, so we don't attach dma-buf fences to them.
507 */
508static int
509vc4_lock_bo_reservations(struct drm_device *dev,
510 struct vc4_exec_info *exec,
511 struct ww_acquire_ctx *acquire_ctx)
512{
513 int contended_lock = -1;
514 int i, ret;
515 struct vc4_bo *bo;
516
517 ww_acquire_init(acquire_ctx, &reservation_ww_class);
518
519retry:
520 if (contended_lock != -1) {
521 bo = to_vc4_bo(&exec->bo[contended_lock]->base);
522 ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
523 acquire_ctx);
524 if (ret) {
525 ww_acquire_done(acquire_ctx);
526 return ret;
527 }
528 }
529
530 for (i = 0; i < exec->bo_count; i++) {
531 if (i == contended_lock)
532 continue;
533
534 bo = to_vc4_bo(&exec->bo[i]->base);
535
536 ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
537 if (ret) {
538 int j;
539
540 for (j = 0; j < i; j++) {
541 bo = to_vc4_bo(&exec->bo[j]->base);
542 ww_mutex_unlock(&bo->resv->lock);
543 }
544
545 if (contended_lock != -1 && contended_lock >= i) {
546 bo = to_vc4_bo(&exec->bo[contended_lock]->base);
547
548 ww_mutex_unlock(&bo->resv->lock);
549 }
550
551 if (ret == -EDEADLK) {
552 contended_lock = i;
553 goto retry;
554 }
555
556 ww_acquire_done(acquire_ctx);
557 return ret;
558 }
559 }
560
561 ww_acquire_done(acquire_ctx);
562
563 /* Reserve space for our shared (read-only) fence references,
564 * before we commit the CL to the hardware.
565 */
566 for (i = 0; i < exec->bo_count; i++) {
567 bo = to_vc4_bo(&exec->bo[i]->base);
568
569 ret = reservation_object_reserve_shared(bo->resv);
570 if (ret) {
571 vc4_unlock_bo_reservations(dev, exec, acquire_ctx);
572 return ret;
573 }
574 }
575
576 return 0;
577}
578
Eric Anholtd5b1a782015-11-30 12:13:37 -0800579/* Queues a struct vc4_exec_info for execution. If no job is
580 * currently executing, then submits it.
581 *
582 * Unlike most GPUs, our hardware only handles one command list at a
583 * time. To queue multiple jobs at once, we'd need to edit the
584 * previous command list to have a jump to the new one at the end, and
585 * then bump the end address. That's a change for a later date,
586 * though.
587 */
Eric Anholtcdec4d32017-04-12 12:12:02 -0700588static int
589vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec,
590 struct ww_acquire_ctx *acquire_ctx)
Eric Anholtd5b1a782015-11-30 12:13:37 -0800591{
592 struct vc4_dev *vc4 = to_vc4_dev(dev);
593 uint64_t seqno;
594 unsigned long irqflags;
Eric Anholtcdec4d32017-04-12 12:12:02 -0700595 struct vc4_fence *fence;
596
597 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
598 if (!fence)
599 return -ENOMEM;
600 fence->dev = dev;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800601
602 spin_lock_irqsave(&vc4->job_lock, irqflags);
603
604 seqno = ++vc4->emit_seqno;
605 exec->seqno = seqno;
Eric Anholtcdec4d32017-04-12 12:12:02 -0700606
607 dma_fence_init(&fence->base, &vc4_fence_ops, &vc4->job_lock,
608 vc4->dma_fence_context, exec->seqno);
609 fence->seqno = exec->seqno;
610 exec->fence = &fence->base;
611
Eric Anholtd5b1a782015-11-30 12:13:37 -0800612 vc4_update_bo_seqnos(exec, seqno);
613
Eric Anholtcdec4d32017-04-12 12:12:02 -0700614 vc4_unlock_bo_reservations(dev, exec, acquire_ctx);
615
Varad Gautamca26d282016-02-17 19:08:21 +0530616 list_add_tail(&exec->head, &vc4->bin_job_list);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800617
618 /* If no job was executing, kick ours off. Otherwise, it'll
Varad Gautamca26d282016-02-17 19:08:21 +0530619 * get started when the previous job's flush done interrupt
Eric Anholtd5b1a782015-11-30 12:13:37 -0800620 * occurs.
621 */
Varad Gautamca26d282016-02-17 19:08:21 +0530622 if (vc4_first_bin_job(vc4) == exec) {
623 vc4_submit_next_bin_job(dev);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800624 vc4_queue_hangcheck(dev);
625 }
626
627 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
Eric Anholtcdec4d32017-04-12 12:12:02 -0700628
629 return 0;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800630}
631
632/**
Eric Anholt72f793f2017-02-27 12:11:41 -0800633 * vc4_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects
634 * referenced by the job.
635 * @dev: DRM device
636 * @file_priv: DRM file for this fd
637 * @exec: V3D job being set up
638 *
639 * The command validator needs to reference BOs by their index within
640 * the submitted job's BO list. This does the validation of the job's
641 * BO list and reference counting for the lifetime of the job.
642 *
643 * Note that this function doesn't need to unreference the BOs on
644 * failure, because that will happen at vc4_complete_exec() time.
Eric Anholtd5b1a782015-11-30 12:13:37 -0800645 */
646static int
647vc4_cl_lookup_bos(struct drm_device *dev,
648 struct drm_file *file_priv,
649 struct vc4_exec_info *exec)
650{
651 struct drm_vc4_submit_cl *args = exec->args;
652 uint32_t *handles;
653 int ret = 0;
654 int i;
655
656 exec->bo_count = args->bo_handle_count;
657
658 if (!exec->bo_count) {
659 /* See comment on bo_index for why we have to check
660 * this.
661 */
Eric Anholtfb959922017-07-25 09:27:32 -0700662 DRM_DEBUG("Rendering requires BOs to validate\n");
Eric Anholtd5b1a782015-11-30 12:13:37 -0800663 return -EINVAL;
664 }
665
Michal Hocko20981052017-05-17 14:23:12 +0200666 exec->bo = kvmalloc_array(exec->bo_count,
667 sizeof(struct drm_gem_cma_object *),
668 GFP_KERNEL | __GFP_ZERO);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800669 if (!exec->bo) {
670 DRM_ERROR("Failed to allocate validated BO pointers\n");
671 return -ENOMEM;
672 }
673
Michal Hocko20981052017-05-17 14:23:12 +0200674 handles = kvmalloc_array(exec->bo_count, sizeof(uint32_t), GFP_KERNEL);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800675 if (!handles) {
Dan Carpenterb2cdeb12016-10-13 11:54:31 +0300676 ret = -ENOMEM;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800677 DRM_ERROR("Failed to allocate incoming GEM handles\n");
678 goto fail;
679 }
680
Eric Anholt95d7cbc2017-07-25 11:27:16 -0700681 if (copy_from_user(handles, u64_to_user_ptr(args->bo_handles),
Dan Carpenterb2cdeb12016-10-13 11:54:31 +0300682 exec->bo_count * sizeof(uint32_t))) {
683 ret = -EFAULT;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800684 DRM_ERROR("Failed to copy in GEM handles\n");
685 goto fail;
686 }
687
688 spin_lock(&file_priv->table_lock);
689 for (i = 0; i < exec->bo_count; i++) {
690 struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
691 handles[i]);
692 if (!bo) {
Eric Anholtfb959922017-07-25 09:27:32 -0700693 DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
Eric Anholtd5b1a782015-11-30 12:13:37 -0800694 i, handles[i]);
695 ret = -EINVAL;
696 spin_unlock(&file_priv->table_lock);
697 goto fail;
698 }
Cihangir Akturk1d5494e2017-08-03 14:58:40 +0300699 drm_gem_object_get(bo);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800700 exec->bo[i] = (struct drm_gem_cma_object *)bo;
701 }
702 spin_unlock(&file_priv->table_lock);
703
704fail:
Michal Hocko20981052017-05-17 14:23:12 +0200705 kvfree(handles);
Eric Anholt552416c2016-07-26 13:47:15 -0700706 return ret;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800707}
708
709static int
710vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
711{
712 struct drm_vc4_submit_cl *args = exec->args;
713 void *temp = NULL;
714 void *bin;
715 int ret = 0;
716 uint32_t bin_offset = 0;
717 uint32_t shader_rec_offset = roundup(bin_offset + args->bin_cl_size,
718 16);
719 uint32_t uniforms_offset = shader_rec_offset + args->shader_rec_size;
720 uint32_t exec_size = uniforms_offset + args->uniforms_size;
721 uint32_t temp_size = exec_size + (sizeof(struct vc4_shader_state) *
722 args->shader_rec_count);
723 struct vc4_bo *bo;
724
Eric Anholt0f2ff822017-01-17 21:42:53 +1100725 if (shader_rec_offset < args->bin_cl_size ||
726 uniforms_offset < shader_rec_offset ||
Eric Anholtd5b1a782015-11-30 12:13:37 -0800727 exec_size < uniforms_offset ||
728 args->shader_rec_count >= (UINT_MAX /
729 sizeof(struct vc4_shader_state)) ||
730 temp_size < exec_size) {
Eric Anholtfb959922017-07-25 09:27:32 -0700731 DRM_DEBUG("overflow in exec arguments\n");
Eric Anholt6b8ac632017-01-17 21:58:06 +1100732 ret = -EINVAL;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800733 goto fail;
734 }
735
736 /* Allocate space where we'll store the copied in user command lists
737 * and shader records.
738 *
739 * We don't just copy directly into the BOs because we need to
740 * read the contents back for validation, and I think the
741 * bo->vaddr is uncached access.
742 */
Michal Hocko20981052017-05-17 14:23:12 +0200743 temp = kvmalloc_array(temp_size, 1, GFP_KERNEL);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800744 if (!temp) {
745 DRM_ERROR("Failed to allocate storage for copying "
746 "in bin/render CLs.\n");
747 ret = -ENOMEM;
748 goto fail;
749 }
750 bin = temp + bin_offset;
751 exec->shader_rec_u = temp + shader_rec_offset;
752 exec->uniforms_u = temp + uniforms_offset;
753 exec->shader_state = temp + exec_size;
754 exec->shader_state_size = args->shader_rec_count;
755
Dan Carpenter65c47772015-12-17 15:36:28 +0300756 if (copy_from_user(bin,
Eric Anholt95d7cbc2017-07-25 11:27:16 -0700757 u64_to_user_ptr(args->bin_cl),
Dan Carpenter65c47772015-12-17 15:36:28 +0300758 args->bin_cl_size)) {
759 ret = -EFAULT;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800760 goto fail;
761 }
762
Dan Carpenter65c47772015-12-17 15:36:28 +0300763 if (copy_from_user(exec->shader_rec_u,
Eric Anholt95d7cbc2017-07-25 11:27:16 -0700764 u64_to_user_ptr(args->shader_rec),
Dan Carpenter65c47772015-12-17 15:36:28 +0300765 args->shader_rec_size)) {
766 ret = -EFAULT;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800767 goto fail;
768 }
769
Dan Carpenter65c47772015-12-17 15:36:28 +0300770 if (copy_from_user(exec->uniforms_u,
Eric Anholt95d7cbc2017-07-25 11:27:16 -0700771 u64_to_user_ptr(args->uniforms),
Dan Carpenter65c47772015-12-17 15:36:28 +0300772 args->uniforms_size)) {
773 ret = -EFAULT;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800774 goto fail;
775 }
776
Eric Anholtf3099462017-07-25 11:27:17 -0700777 bo = vc4_bo_create(dev, exec_size, true, VC4_BO_TYPE_BCL);
Eric Anholt2c68f1f2016-01-25 14:13:12 -0800778 if (IS_ERR(bo)) {
Eric Anholtd5b1a782015-11-30 12:13:37 -0800779 DRM_ERROR("Couldn't allocate BO for binning\n");
Eric Anholt2c68f1f2016-01-25 14:13:12 -0800780 ret = PTR_ERR(bo);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800781 goto fail;
782 }
783 exec->exec_bo = &bo->base;
784
785 list_add_tail(&to_vc4_bo(&exec->exec_bo->base)->unref_head,
786 &exec->unref_list);
787
788 exec->ct0ca = exec->exec_bo->paddr + bin_offset;
789
790 exec->bin_u = bin;
791
792 exec->shader_rec_v = exec->exec_bo->vaddr + shader_rec_offset;
793 exec->shader_rec_p = exec->exec_bo->paddr + shader_rec_offset;
794 exec->shader_rec_size = args->shader_rec_size;
795
796 exec->uniforms_v = exec->exec_bo->vaddr + uniforms_offset;
797 exec->uniforms_p = exec->exec_bo->paddr + uniforms_offset;
798 exec->uniforms_size = args->uniforms_size;
799
800 ret = vc4_validate_bin_cl(dev,
801 exec->exec_bo->vaddr + bin_offset,
802 bin,
803 exec);
804 if (ret)
805 goto fail;
806
807 ret = vc4_validate_shader_recs(dev, exec);
Eric Anholt7edabee2016-09-27 09:03:13 -0700808 if (ret)
809 goto fail;
810
811 /* Block waiting on any previous rendering into the CS's VBO,
812 * IB, or textures, so that pixels are actually written by the
813 * time we try to read them.
814 */
815 ret = vc4_wait_for_seqno(dev, exec->bin_dep_seqno, ~0ull, true);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800816
817fail:
Michal Hocko20981052017-05-17 14:23:12 +0200818 kvfree(temp);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800819 return ret;
820}
821
822static void
823vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
824{
Eric Anholt001bdb52016-02-05 17:41:49 -0800825 struct vc4_dev *vc4 = to_vc4_dev(dev);
Eric Anholt553c9422017-03-27 16:10:25 -0700826 unsigned long irqflags;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800827 unsigned i;
828
Eric Anholtcdec4d32017-04-12 12:12:02 -0700829 /* If we got force-completed because of GPU reset rather than
830 * through our IRQ handler, signal the fence now.
831 */
832 if (exec->fence)
833 dma_fence_signal(exec->fence);
834
Eric Anholtd5b1a782015-11-30 12:13:37 -0800835 if (exec->bo) {
836 for (i = 0; i < exec->bo_count; i++)
Cihangir Akturk1d5494e2017-08-03 14:58:40 +0300837 drm_gem_object_put_unlocked(&exec->bo[i]->base);
Michal Hocko20981052017-05-17 14:23:12 +0200838 kvfree(exec->bo);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800839 }
840
841 while (!list_empty(&exec->unref_list)) {
842 struct vc4_bo *bo = list_first_entry(&exec->unref_list,
843 struct vc4_bo, unref_head);
844 list_del(&bo->unref_head);
Cihangir Akturk1d5494e2017-08-03 14:58:40 +0300845 drm_gem_object_put_unlocked(&bo->base.base);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800846 }
Eric Anholtd5b1a782015-11-30 12:13:37 -0800847
Eric Anholt553c9422017-03-27 16:10:25 -0700848 /* Free up the allocation of any bin slots we used. */
849 spin_lock_irqsave(&vc4->job_lock, irqflags);
850 vc4->bin_alloc_used &= ~exec->bin_slots;
851 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
852
Eric Anholt36cb6252016-02-08 12:59:02 -0800853 mutex_lock(&vc4->power_lock);
Eric Anholt3a622342016-11-04 15:58:38 -0700854 if (--vc4->power_refcount == 0) {
855 pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
856 pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
857 }
Eric Anholt36cb6252016-02-08 12:59:02 -0800858 mutex_unlock(&vc4->power_lock);
Eric Anholt001bdb52016-02-05 17:41:49 -0800859
Eric Anholtd5b1a782015-11-30 12:13:37 -0800860 kfree(exec);
861}
862
863void
864vc4_job_handle_completed(struct vc4_dev *vc4)
865{
866 unsigned long irqflags;
Eric Anholtb501bac2015-11-30 12:34:01 -0800867 struct vc4_seqno_cb *cb, *cb_temp;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800868
869 spin_lock_irqsave(&vc4->job_lock, irqflags);
870 while (!list_empty(&vc4->job_done_list)) {
871 struct vc4_exec_info *exec =
872 list_first_entry(&vc4->job_done_list,
873 struct vc4_exec_info, head);
874 list_del(&exec->head);
875
876 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
877 vc4_complete_exec(vc4->dev, exec);
878 spin_lock_irqsave(&vc4->job_lock, irqflags);
879 }
Eric Anholtb501bac2015-11-30 12:34:01 -0800880
881 list_for_each_entry_safe(cb, cb_temp, &vc4->seqno_cb_list, work.entry) {
882 if (cb->seqno <= vc4->finished_seqno) {
883 list_del_init(&cb->work.entry);
884 schedule_work(&cb->work);
885 }
886 }
887
Eric Anholtd5b1a782015-11-30 12:13:37 -0800888 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
889}
890
Eric Anholtb501bac2015-11-30 12:34:01 -0800891static void vc4_seqno_cb_work(struct work_struct *work)
892{
893 struct vc4_seqno_cb *cb = container_of(work, struct vc4_seqno_cb, work);
894
895 cb->func(cb);
896}
897
898int vc4_queue_seqno_cb(struct drm_device *dev,
899 struct vc4_seqno_cb *cb, uint64_t seqno,
900 void (*func)(struct vc4_seqno_cb *cb))
901{
902 struct vc4_dev *vc4 = to_vc4_dev(dev);
903 int ret = 0;
904 unsigned long irqflags;
905
906 cb->func = func;
907 INIT_WORK(&cb->work, vc4_seqno_cb_work);
908
909 spin_lock_irqsave(&vc4->job_lock, irqflags);
910 if (seqno > vc4->finished_seqno) {
911 cb->seqno = seqno;
912 list_add_tail(&cb->work.entry, &vc4->seqno_cb_list);
913 } else {
914 schedule_work(&cb->work);
915 }
916 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
917
918 return ret;
919}
920
Eric Anholtd5b1a782015-11-30 12:13:37 -0800921/* Scheduled when any job has been completed, this walks the list of
922 * jobs that had completed and unrefs their BOs and frees their exec
923 * structs.
924 */
925static void
926vc4_job_done_work(struct work_struct *work)
927{
928 struct vc4_dev *vc4 =
929 container_of(work, struct vc4_dev, job_done_work);
930
931 vc4_job_handle_completed(vc4);
932}
933
934static int
935vc4_wait_for_seqno_ioctl_helper(struct drm_device *dev,
936 uint64_t seqno,
937 uint64_t *timeout_ns)
938{
939 unsigned long start = jiffies;
940 int ret = vc4_wait_for_seqno(dev, seqno, *timeout_ns, true);
941
942 if ((ret == -EINTR || ret == -ERESTARTSYS) && *timeout_ns != ~0ull) {
943 uint64_t delta = jiffies_to_nsecs(jiffies - start);
944
945 if (*timeout_ns >= delta)
946 *timeout_ns -= delta;
947 }
948
949 return ret;
950}
951
952int
953vc4_wait_seqno_ioctl(struct drm_device *dev, void *data,
954 struct drm_file *file_priv)
955{
956 struct drm_vc4_wait_seqno *args = data;
957
958 return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno,
959 &args->timeout_ns);
960}
961
962int
963vc4_wait_bo_ioctl(struct drm_device *dev, void *data,
964 struct drm_file *file_priv)
965{
966 int ret;
967 struct drm_vc4_wait_bo *args = data;
968 struct drm_gem_object *gem_obj;
969 struct vc4_bo *bo;
970
Eric Anholte0015232016-01-25 13:05:00 -0800971 if (args->pad != 0)
972 return -EINVAL;
973
Chris Wilsona8ad0bd2016-05-09 11:04:54 +0100974 gem_obj = drm_gem_object_lookup(file_priv, args->handle);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800975 if (!gem_obj) {
Eric Anholtfb959922017-07-25 09:27:32 -0700976 DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800977 return -EINVAL;
978 }
979 bo = to_vc4_bo(gem_obj);
980
981 ret = vc4_wait_for_seqno_ioctl_helper(dev, bo->seqno,
982 &args->timeout_ns);
983
Cihangir Akturk1d5494e2017-08-03 14:58:40 +0300984 drm_gem_object_put_unlocked(gem_obj);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800985 return ret;
986}
987
988/**
Eric Anholt72f793f2017-02-27 12:11:41 -0800989 * vc4_submit_cl_ioctl() - Submits a job (frame) to the VC4.
990 * @dev: DRM device
991 * @data: ioctl argument
992 * @file_priv: DRM file for this fd
Eric Anholtd5b1a782015-11-30 12:13:37 -0800993 *
Eric Anholt72f793f2017-02-27 12:11:41 -0800994 * This is the main entrypoint for userspace to submit a 3D frame to
995 * the GPU. Userspace provides the binner command list (if
996 * applicable), and the kernel sets up the render command list to draw
997 * to the framebuffer described in the ioctl, using the command lists
998 * that the 3D engine's binner will produce.
Eric Anholtd5b1a782015-11-30 12:13:37 -0800999 */
1000int
1001vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
1002 struct drm_file *file_priv)
1003{
1004 struct vc4_dev *vc4 = to_vc4_dev(dev);
1005 struct drm_vc4_submit_cl *args = data;
1006 struct vc4_exec_info *exec;
Eric Anholtcdec4d32017-04-12 12:12:02 -07001007 struct ww_acquire_ctx acquire_ctx;
Eric Anholt36cb6252016-02-08 12:59:02 -08001008 int ret = 0;
Eric Anholtd5b1a782015-11-30 12:13:37 -08001009
Eric Anholt3be8edd2017-07-25 09:27:33 -07001010 if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR |
1011 VC4_SUBMIT_CL_FIXED_RCL_ORDER |
1012 VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X |
1013 VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y)) != 0) {
Eric Anholtfb959922017-07-25 09:27:32 -07001014 DRM_DEBUG("Unknown flags: 0x%02x\n", args->flags);
Eric Anholtd5b1a782015-11-30 12:13:37 -08001015 return -EINVAL;
1016 }
1017
1018 exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
1019 if (!exec) {
1020 DRM_ERROR("malloc failure on exec struct\n");
1021 return -ENOMEM;
1022 }
1023
Eric Anholt36cb6252016-02-08 12:59:02 -08001024 mutex_lock(&vc4->power_lock);
Eric Anholt925d05e2017-04-17 09:26:03 -07001025 if (vc4->power_refcount++ == 0) {
Eric Anholt36cb6252016-02-08 12:59:02 -08001026 ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
Eric Anholt925d05e2017-04-17 09:26:03 -07001027 if (ret < 0) {
1028 mutex_unlock(&vc4->power_lock);
1029 vc4->power_refcount--;
1030 kfree(exec);
1031 return ret;
1032 }
Eric Anholt001bdb52016-02-05 17:41:49 -08001033 }
Eric Anholt925d05e2017-04-17 09:26:03 -07001034 mutex_unlock(&vc4->power_lock);
Eric Anholt001bdb52016-02-05 17:41:49 -08001035
Eric Anholtd5b1a782015-11-30 12:13:37 -08001036 exec->args = args;
1037 INIT_LIST_HEAD(&exec->unref_list);
1038
1039 ret = vc4_cl_lookup_bos(dev, file_priv, exec);
1040 if (ret)
1041 goto fail;
1042
1043 if (exec->args->bin_cl_size != 0) {
1044 ret = vc4_get_bcl(dev, exec);
1045 if (ret)
1046 goto fail;
1047 } else {
1048 exec->ct0ca = 0;
1049 exec->ct0ea = 0;
1050 }
1051
1052 ret = vc4_get_rcl(dev, exec);
1053 if (ret)
1054 goto fail;
1055
Eric Anholtcdec4d32017-04-12 12:12:02 -07001056 ret = vc4_lock_bo_reservations(dev, exec, &acquire_ctx);
1057 if (ret)
1058 goto fail;
1059
Eric Anholtd5b1a782015-11-30 12:13:37 -08001060 /* Clear this out of the struct we'll be putting in the queue,
1061 * since it's part of our stack.
1062 */
1063 exec->args = NULL;
1064
Eric Anholtcdec4d32017-04-12 12:12:02 -07001065 ret = vc4_queue_submit(dev, exec, &acquire_ctx);
1066 if (ret)
1067 goto fail;
Eric Anholtd5b1a782015-11-30 12:13:37 -08001068
1069 /* Return the seqno for our job. */
1070 args->seqno = vc4->emit_seqno;
1071
1072 return 0;
1073
1074fail:
1075 vc4_complete_exec(vc4->dev, exec);
1076
1077 return ret;
1078}
1079
1080void
1081vc4_gem_init(struct drm_device *dev)
1082{
1083 struct vc4_dev *vc4 = to_vc4_dev(dev);
1084
Eric Anholtcdec4d32017-04-12 12:12:02 -07001085 vc4->dma_fence_context = dma_fence_context_alloc(1);
1086
Varad Gautamca26d282016-02-17 19:08:21 +05301087 INIT_LIST_HEAD(&vc4->bin_job_list);
1088 INIT_LIST_HEAD(&vc4->render_job_list);
Eric Anholtd5b1a782015-11-30 12:13:37 -08001089 INIT_LIST_HEAD(&vc4->job_done_list);
Eric Anholtb501bac2015-11-30 12:34:01 -08001090 INIT_LIST_HEAD(&vc4->seqno_cb_list);
Eric Anholtd5b1a782015-11-30 12:13:37 -08001091 spin_lock_init(&vc4->job_lock);
1092
1093 INIT_WORK(&vc4->hangcheck.reset_work, vc4_reset_work);
1094 setup_timer(&vc4->hangcheck.timer,
1095 vc4_hangcheck_elapsed,
1096 (unsigned long)dev);
1097
1098 INIT_WORK(&vc4->job_done_work, vc4_job_done_work);
Eric Anholt36cb6252016-02-08 12:59:02 -08001099
1100 mutex_init(&vc4->power_lock);
Eric Anholtd5b1a782015-11-30 12:13:37 -08001101}
1102
1103void
1104vc4_gem_destroy(struct drm_device *dev)
1105{
1106 struct vc4_dev *vc4 = to_vc4_dev(dev);
1107
1108 /* Waiting for exec to finish would need to be done before
1109 * unregistering V3D.
1110 */
1111 WARN_ON(vc4->emit_seqno != vc4->finished_seqno);
1112
1113 /* V3D should already have disabled its interrupt and cleared
1114 * the overflow allocation registers. Now free the object.
1115 */
Eric Anholt553c9422017-03-27 16:10:25 -07001116 if (vc4->bin_bo) {
1117 drm_gem_object_put_unlocked(&vc4->bin_bo->base.base);
1118 vc4->bin_bo = NULL;
Eric Anholtd5b1a782015-11-30 12:13:37 -08001119 }
1120
Eric Anholt21461362015-10-30 10:09:02 -07001121 if (vc4->hang_state)
1122 vc4_free_hang_state(dev, vc4->hang_state);
Eric Anholtd5b1a782015-11-30 12:13:37 -08001123}