aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2016-03-15 18:26:28 -0400
committerRob Clark <robdclark@gmail.com>2016-05-08 10:22:15 -0400
commitb6295f9a38fc3f7d59ec0caa45aa803461c6cea5 (patch)
tree81f8e68dfaf8d900d86cd971e293d6a824a178d0
parentba00c3f2f0c84456ffe9d548823ff4fb8e4e7ed4 (diff)
drm/msm: 'struct fence' conversion
Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c4
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c42
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h5
-rw-r--r--drivers/gpu/drm/msm/msm_fence.c71
-rw-r--r--drivers/gpu/drm/msm/msm_fence.h4
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c124
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h16
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c22
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c27
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c2
10 files changed, 233 insertions, 84 deletions
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 9aab871f4def..95aed377b933 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -168,7 +168,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
168 OUT_PKT2(ring); 168 OUT_PKT2(ring);
169 169
170 OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); 170 OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
171 OUT_RING(ring, submit->fence); 171 OUT_RING(ring, submit->fence->seqno);
172 172
173 if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) { 173 if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) {
174 /* Flush HLSQ lazy updates to make sure there is nothing 174 /* Flush HLSQ lazy updates to make sure there is nothing
@@ -185,7 +185,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
185 OUT_PKT3(ring, CP_EVENT_WRITE, 3); 185 OUT_PKT3(ring, CP_EVENT_WRITE, 3);
186 OUT_RING(ring, CACHE_FLUSH_TS); 186 OUT_RING(ring, CACHE_FLUSH_TS);
187 OUT_RING(ring, rbmemptr(adreno_gpu, fence)); 187 OUT_RING(ring, rbmemptr(adreno_gpu, fence));
188 OUT_RING(ring, submit->fence); 188 OUT_RING(ring, submit->fence->seqno);
189 189
190 /* we could maybe be clever and only CP_COND_EXEC the interrupt: */ 190 /* we could maybe be clever and only CP_COND_EXEC the interrupt: */
191 OUT_PKT3(ring, CP_INTERRUPT, 1); 191 OUT_PKT3(ring, CP_INTERRUPT, 1);
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 6ac7192d0ad6..e3892c263f27 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -107,27 +107,6 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
107 } 107 }
108} 108}
109 109
110static void wait_fences(struct msm_commit *c, bool async)
111{
112 int nplanes = c->dev->mode_config.num_total_plane;
113 ktime_t timeout = ktime_add_ms(ktime_get(), 1000);
114 int i;
115
116 for (i = 0; i < nplanes; i++) {
117 struct drm_plane *plane = c->state->planes[i];
118 struct drm_plane_state *new_state = c->state->plane_states[i];
119
120 if (!plane)
121 continue;
122
123 if ((plane->state->fb != new_state->fb) && new_state->fb) {
124 struct drm_gem_object *obj =
125 msm_framebuffer_bo(new_state->fb, 0);
126 msm_gem_cpu_sync(obj, MSM_PREP_READ, &timeout);
127 }
128 }
129}
130
131/* The (potentially) asynchronous part of the commit. At this point 110/* The (potentially) asynchronous part of the commit. At this point
132 * nothing can fail short of armageddon. 111 * nothing can fail short of armageddon.
133 */ 112 */
@@ -138,7 +117,7 @@ static void complete_commit(struct msm_commit *c, bool async)
138 struct msm_drm_private *priv = dev->dev_private; 117 struct msm_drm_private *priv = dev->dev_private;
139 struct msm_kms *kms = priv->kms; 118 struct msm_kms *kms = priv->kms;
140 119
141 wait_fences(c, async); 120 drm_atomic_helper_wait_for_fences(dev, state);
142 121
143 kms->funcs->prepare_commit(kms, state); 122 kms->funcs->prepare_commit(kms, state);
144 123
@@ -213,6 +192,7 @@ int msm_atomic_commit(struct drm_device *dev,
213 struct drm_atomic_state *state, bool nonblock) 192 struct drm_atomic_state *state, bool nonblock)
214{ 193{
215 struct msm_drm_private *priv = dev->dev_private; 194 struct msm_drm_private *priv = dev->dev_private;
195 int nplanes = dev->mode_config.num_total_plane;
216 int ncrtcs = dev->mode_config.num_crtc; 196 int ncrtcs = dev->mode_config.num_crtc;
217 struct msm_commit *c; 197 struct msm_commit *c;
218 int i, ret; 198 int i, ret;
@@ -238,6 +218,24 @@ int msm_atomic_commit(struct drm_device *dev,
238 } 218 }
239 219
240 /* 220 /*
221 * Figure out what fence to wait for:
222 */
223 for (i = 0; i < nplanes; i++) {
224 struct drm_plane *plane = state->planes[i];
225 struct drm_plane_state *new_state = state->plane_states[i];
226
227 if (!plane)
228 continue;
229
230 if ((plane->state->fb != new_state->fb) && new_state->fb) {
231 struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0);
232 struct msm_gem_object *msm_obj = to_msm_bo(obj);
233
234 new_state->fence = reservation_object_get_excl_rcu(msm_obj->resv);
235 }
236 }
237
238 /*
241 * Wait for pending updates on any of the same crtc's and then 239 * Wait for pending updates on any of the same crtc's and then
242 * mark our set of crtc's as busy: 240 * mark our set of crtc's as busy:
243 */ 241 */
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 7124c7f262ec..4114a40e4a09 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -190,10 +190,11 @@ int msm_gem_prime_pin(struct drm_gem_object *obj);
190void msm_gem_prime_unpin(struct drm_gem_object *obj); 190void msm_gem_prime_unpin(struct drm_gem_object *obj);
191void *msm_gem_vaddr_locked(struct drm_gem_object *obj); 191void *msm_gem_vaddr_locked(struct drm_gem_object *obj);
192void *msm_gem_vaddr(struct drm_gem_object *obj); 192void *msm_gem_vaddr(struct drm_gem_object *obj);
193int msm_gem_sync_object(struct drm_gem_object *obj,
194 struct msm_fence_context *fctx, bool exclusive);
193void msm_gem_move_to_active(struct drm_gem_object *obj, 195void msm_gem_move_to_active(struct drm_gem_object *obj,
194 struct msm_gpu *gpu, bool write, uint32_t fence); 196 struct msm_gpu *gpu, bool exclusive, struct fence *fence);
195void msm_gem_move_to_inactive(struct drm_gem_object *obj); 197void msm_gem_move_to_inactive(struct drm_gem_object *obj);
196int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
197int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); 198int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
198int msm_gem_cpu_fini(struct drm_gem_object *obj); 199int msm_gem_cpu_fini(struct drm_gem_object *obj);
199void msm_gem_free_object(struct drm_gem_object *obj); 200void msm_gem_free_object(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index 088610ca80ca..a9b9b1c95a2e 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -32,7 +32,9 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name)
32 32
33 fctx->dev = dev; 33 fctx->dev = dev;
34 fctx->name = name; 34 fctx->name = name;
35 fctx->context = fence_context_alloc(1);
35 init_waitqueue_head(&fctx->event); 36 init_waitqueue_head(&fctx->event);
37 spin_lock_init(&fctx->spinlock);
36 38
37 return fctx; 39 return fctx;
38} 40}
@@ -47,6 +49,7 @@ static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fenc
47 return (int32_t)(fctx->completed_fence - fence) >= 0; 49 return (int32_t)(fctx->completed_fence - fence) >= 0;
48} 50}
49 51
52/* legacy path for WAIT_FENCE ioctl: */
50int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence, 53int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
51 ktime_t *timeout, bool interruptible) 54 ktime_t *timeout, bool interruptible)
52{ 55{
@@ -88,9 +91,73 @@ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
88/* called from workqueue */ 91/* called from workqueue */
89void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) 92void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
90{ 93{
91 mutex_lock(&fctx->dev->struct_mutex); 94 spin_lock(&fctx->spinlock);
92 fctx->completed_fence = max(fence, fctx->completed_fence); 95 fctx->completed_fence = max(fence, fctx->completed_fence);
93 mutex_unlock(&fctx->dev->struct_mutex); 96 spin_unlock(&fctx->spinlock);
94 97
95 wake_up_all(&fctx->event); 98 wake_up_all(&fctx->event);
96} 99}
100
101struct msm_fence {
102 struct msm_fence_context *fctx;
103 struct fence base;
104};
105
106static inline struct msm_fence *to_msm_fence(struct fence *fence)
107{
108 return container_of(fence, struct msm_fence, base);
109}
110
111static const char *msm_fence_get_driver_name(struct fence *fence)
112{
113 return "msm";
114}
115
116static const char *msm_fence_get_timeline_name(struct fence *fence)
117{
118 struct msm_fence *f = to_msm_fence(fence);
119 return f->fctx->name;
120}
121
122static bool msm_fence_enable_signaling(struct fence *fence)
123{
124 return true;
125}
126
127static bool msm_fence_signaled(struct fence *fence)
128{
129 struct msm_fence *f = to_msm_fence(fence);
130 return fence_completed(f->fctx, f->base.seqno);
131}
132
133static void msm_fence_release(struct fence *fence)
134{
135 struct msm_fence *f = to_msm_fence(fence);
136 kfree_rcu(f, base.rcu);
137}
138
139static const struct fence_ops msm_fence_ops = {
140 .get_driver_name = msm_fence_get_driver_name,
141 .get_timeline_name = msm_fence_get_timeline_name,
142 .enable_signaling = msm_fence_enable_signaling,
143 .signaled = msm_fence_signaled,
144 .wait = fence_default_wait,
145 .release = msm_fence_release,
146};
147
148struct fence *
149msm_fence_alloc(struct msm_fence_context *fctx)
150{
151 struct msm_fence *f;
152
153 f = kzalloc(sizeof(*f), GFP_KERNEL);
154 if (!f)
155 return ERR_PTR(-ENOMEM);
156
157 f->fctx = fctx;
158
159 fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
160 fctx->context, ++fctx->last_fence);
161
162 return &f->base;
163}
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
index 2820781d974a..ceb5b3d314b4 100644
--- a/drivers/gpu/drm/msm/msm_fence.h
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -23,10 +23,12 @@
23struct msm_fence_context { 23struct msm_fence_context {
24 struct drm_device *dev; 24 struct drm_device *dev;
25 const char *name; 25 const char *name;
26 unsigned context;
26 /* last_fence == completed_fence --> no pending work */ 27 /* last_fence == completed_fence --> no pending work */
27 uint32_t last_fence; /* last assigned fence */ 28 uint32_t last_fence; /* last assigned fence */
28 uint32_t completed_fence; /* last completed fence */ 29 uint32_t completed_fence; /* last completed fence */
29 wait_queue_head_t event; 30 wait_queue_head_t event;
31 spinlock_t spinlock;
30}; 32};
31 33
32struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev, 34struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
@@ -39,4 +41,6 @@ int msm_queue_fence_cb(struct msm_fence_context *fctx,
39 struct msm_fence_cb *cb, uint32_t fence); 41 struct msm_fence_cb *cb, uint32_t fence);
40void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence); 42void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
41 43
44struct fence * msm_fence_alloc(struct msm_fence_context *fctx);
45
42#endif 46#endif
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 9080ed13998a..9bbe1c5e7151 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -411,15 +411,62 @@ void *msm_gem_vaddr(struct drm_gem_object *obj)
411 return ret; 411 return ret;
412} 412}
413 413
414/* must be called before _move_to_active().. */
415int msm_gem_sync_object(struct drm_gem_object *obj,
416 struct msm_fence_context *fctx, bool exclusive)
417{
418 struct msm_gem_object *msm_obj = to_msm_bo(obj);
419 struct reservation_object_list *fobj;
420 struct fence *fence;
421 int i, ret;
422
423 if (!exclusive) {
424 /* NOTE: _reserve_shared() must happen before _add_shared_fence(),
425 * which makes this a slightly strange place to call it. OTOH this
426 * is a convenient can-fail point to hook it in. (And similar to
427 * how etnaviv and nouveau handle this.)
428 */
429 ret = reservation_object_reserve_shared(msm_obj->resv);
430 if (ret)
431 return ret;
432 }
433
434 fobj = reservation_object_get_list(msm_obj->resv);
435 if (!fobj || (fobj->shared_count == 0)) {
436 fence = reservation_object_get_excl(msm_obj->resv);
437 /* don't need to wait on our own fences, since ring is fifo */
438 if (fence && (fence->context != fctx->context)) {
439 ret = fence_wait(fence, true);
440 if (ret)
441 return ret;
442 }
443 }
444
445 if (!exclusive || !fobj)
446 return 0;
447
448 for (i = 0; i < fobj->shared_count; i++) {
449 fence = rcu_dereference_protected(fobj->shared[i],
450 reservation_object_held(msm_obj->resv));
451 if (fence->context != fctx->context) {
452 ret = fence_wait(fence, true);
453 if (ret)
454 return ret;
455 }
456 }
457
458 return 0;
459}
460
414void msm_gem_move_to_active(struct drm_gem_object *obj, 461void msm_gem_move_to_active(struct drm_gem_object *obj,
415 struct msm_gpu *gpu, bool write, uint32_t fence) 462 struct msm_gpu *gpu, bool exclusive, struct fence *fence)
416{ 463{
417 struct msm_gem_object *msm_obj = to_msm_bo(obj); 464 struct msm_gem_object *msm_obj = to_msm_bo(obj);
418 msm_obj->gpu = gpu; 465 msm_obj->gpu = gpu;
419 if (write) 466 if (exclusive)
420 msm_obj->write_fence = fence; 467 reservation_object_add_excl_fence(msm_obj->resv, fence);
421 else 468 else
422 msm_obj->read_fence = fence; 469 reservation_object_add_shared_fence(msm_obj->resv, fence);
423 list_del_init(&msm_obj->mm_list); 470 list_del_init(&msm_obj->mm_list);
424 list_add_tail(&msm_obj->mm_list, &gpu->active_list); 471 list_add_tail(&msm_obj->mm_list, &gpu->active_list);
425} 472}
@@ -433,39 +480,30 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
433 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 480 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
434 481
435 msm_obj->gpu = NULL; 482 msm_obj->gpu = NULL;
436 msm_obj->read_fence = 0;
437 msm_obj->write_fence = 0;
438 list_del_init(&msm_obj->mm_list); 483 list_del_init(&msm_obj->mm_list);
439 list_add_tail(&msm_obj->mm_list, &priv->inactive_list); 484 list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
440} 485}
441 486
442int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) 487int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
443{ 488{
444 struct drm_device *dev = obj->dev;
445 struct msm_drm_private *priv = dev->dev_private;
446 struct msm_gem_object *msm_obj = to_msm_bo(obj); 489 struct msm_gem_object *msm_obj = to_msm_bo(obj);
447 int ret = 0; 490 bool write = !!(op & MSM_PREP_WRITE);
448
449 if (is_active(msm_obj)) {
450 uint32_t fence = msm_gem_fence(msm_obj, op);
451 491
452 if (op & MSM_PREP_NOSYNC) 492 if (op & MSM_PREP_NOSYNC) {
453 timeout = NULL; 493 if (!reservation_object_test_signaled_rcu(msm_obj->resv, write))
494 return -EBUSY;
495 } else {
496 int ret;
454 497
455 if (priv->gpu) 498 ret = reservation_object_wait_timeout_rcu(msm_obj->resv, write,
456 ret = msm_wait_fence(priv->gpu->fctx, fence, timeout, true); 499 true, timeout_to_jiffies(timeout));
500 if (ret <= 0)
501 return ret == 0 ? -ETIMEDOUT : ret;
457 } 502 }
458 503
459 return ret;
460}
461
462int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
463{
464 int ret = msm_gem_cpu_sync(obj, op, timeout);
465
466 /* TODO cache maintenance */ 504 /* TODO cache maintenance */
467 505
468 return ret; 506 return 0;
469} 507}
470 508
471int msm_gem_cpu_fini(struct drm_gem_object *obj) 509int msm_gem_cpu_fini(struct drm_gem_object *obj)
@@ -475,18 +513,46 @@ int msm_gem_cpu_fini(struct drm_gem_object *obj)
475} 513}
476 514
477#ifdef CONFIG_DEBUG_FS 515#ifdef CONFIG_DEBUG_FS
516static void describe_fence(struct fence *fence, const char *type,
517 struct seq_file *m)
518{
519 if (!fence_is_signaled(fence))
520 seq_printf(m, "\t%9s: %s %s seq %u\n", type,
521 fence->ops->get_driver_name(fence),
522 fence->ops->get_timeline_name(fence),
523 fence->seqno);
524}
525
478void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) 526void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
479{ 527{
480 struct drm_device *dev = obj->dev;
481 struct msm_gem_object *msm_obj = to_msm_bo(obj); 528 struct msm_gem_object *msm_obj = to_msm_bo(obj);
529 struct reservation_object *robj = msm_obj->resv;
530 struct reservation_object_list *fobj;
531 struct fence *fence;
482 uint64_t off = drm_vma_node_start(&obj->vma_node); 532 uint64_t off = drm_vma_node_start(&obj->vma_node);
483 533
484 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 534 WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
485 seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %zu\n", 535
536 seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu\n",
486 msm_obj->flags, is_active(msm_obj) ? 'A' : 'I', 537 msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
487 msm_obj->read_fence, msm_obj->write_fence,
488 obj->name, obj->refcount.refcount.counter, 538 obj->name, obj->refcount.refcount.counter,
489 off, msm_obj->vaddr, obj->size); 539 off, msm_obj->vaddr, obj->size);
540
541 rcu_read_lock();
542 fobj = rcu_dereference(robj->fence);
543 if (fobj) {
544 unsigned int i, shared_count = fobj->shared_count;
545
546 for (i = 0; i < shared_count; i++) {
547 fence = rcu_dereference(fobj->shared[i]);
548 describe_fence(fence, "Shared", m);
549 }
550 }
551
552 fence = rcu_dereference(robj->fence_excl);
553 if (fence)
554 describe_fence(fence, "Exclusive", m);
555 rcu_read_unlock();
490} 556}
491 557
492void msm_gem_describe_objects(struct list_head *list, struct seq_file *m) 558void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index b8904517117d..2771d155587a 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -39,7 +39,6 @@ struct msm_gem_object {
39 */ 39 */
40 struct list_head mm_list; 40 struct list_head mm_list;
41 struct msm_gpu *gpu; /* non-null if active */ 41 struct msm_gpu *gpu; /* non-null if active */
42 uint32_t read_fence, write_fence;
43 42
44 /* Transiently in the process of submit ioctl, objects associated 43 /* Transiently in the process of submit ioctl, objects associated
45 * with the submit are on submit->bo_list.. this only lasts for 44 * with the submit are on submit->bo_list.. this only lasts for
@@ -73,19 +72,6 @@ static inline bool is_active(struct msm_gem_object *msm_obj)
73 return msm_obj->gpu != NULL; 72 return msm_obj->gpu != NULL;
74} 73}
75 74
76static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,
77 uint32_t op)
78{
79 uint32_t fence = 0;
80
81 if (op & MSM_PREP_READ)
82 fence = msm_obj->write_fence;
83 if (op & MSM_PREP_WRITE)
84 fence = max(fence, msm_obj->read_fence);
85
86 return fence;
87}
88
89#define MAX_CMDS 4 75#define MAX_CMDS 4
90 76
91/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc, 77/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
@@ -99,7 +85,7 @@ struct msm_gem_submit {
99 struct list_head node; /* node in gpu submit_list */ 85 struct list_head node; /* node in gpu submit_list */
100 struct list_head bo_list; 86 struct list_head bo_list;
101 struct ww_acquire_ctx ticket; 87 struct ww_acquire_ctx ticket;
102 uint32_t fence; 88 struct fence *fence;
103 bool valid; /* true if no cmdstream patching needed */ 89 bool valid; /* true if no cmdstream patching needed */
104 unsigned int nr_cmds; 90 unsigned int nr_cmds;
105 unsigned int nr_bos; 91 unsigned int nr_bos;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index b231544b3f52..2661a7cb23c8 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -184,6 +184,22 @@ fail:
184 return ret; 184 return ret;
185} 185}
186 186
187static int submit_fence_sync(struct msm_gem_submit *submit)
188{
189 int i, ret = 0;
190
191 for (i = 0; i < submit->nr_bos; i++) {
192 struct msm_gem_object *msm_obj = submit->bos[i].obj;
193 bool write = submit->bos[i].flags & MSM_SUBMIT_BO_WRITE;
194
195 ret = msm_gem_sync_object(&msm_obj->base, submit->gpu->fctx, write);
196 if (ret)
197 break;
198 }
199
200 return ret;
201}
202
187static int submit_pin_objects(struct msm_gem_submit *submit) 203static int submit_pin_objects(struct msm_gem_submit *submit)
188{ 204{
189 int i, ret = 0; 205 int i, ret = 0;
@@ -358,6 +374,10 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
358 if (ret) 374 if (ret)
359 goto out; 375 goto out;
360 376
377 ret = submit_fence_sync(submit);
378 if (ret)
379 goto out;
380
361 ret = submit_pin_objects(submit); 381 ret = submit_pin_objects(submit);
362 if (ret) 382 if (ret)
363 goto out; 383 goto out;
@@ -424,7 +444,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
424 444
425 ret = msm_gpu_submit(gpu, submit, ctx); 445 ret = msm_gpu_submit(gpu, submit, ctx);
426 446
427 args->fence = submit->fence; 447 args->fence = submit->fence->seqno;
428 448
429out: 449out:
430 submit_cleanup(submit, !!ret); 450 submit_cleanup(submit, !!ret);
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 8f0b29548cfc..f94d01099e19 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -266,22 +266,24 @@ static void inactive_start(struct msm_gpu *gpu)
266 * Hangcheck detection for locked gpu: 266 * Hangcheck detection for locked gpu:
267 */ 267 */
268 268
269static void retire_submits(struct msm_gpu *gpu, uint32_t fence); 269static void retire_submits(struct msm_gpu *gpu);
270 270
271static void recover_worker(struct work_struct *work) 271static void recover_worker(struct work_struct *work)
272{ 272{
273 struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work); 273 struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work);
274 struct drm_device *dev = gpu->dev; 274 struct drm_device *dev = gpu->dev;
275 uint32_t fence = gpu->funcs->last_fence(gpu);
275 276
276 dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name); 277 dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
277 278
279 msm_update_fence(gpu->fctx, fence + 1);
280
278 mutex_lock(&dev->struct_mutex); 281 mutex_lock(&dev->struct_mutex);
279 if (msm_gpu_active(gpu)) { 282 if (msm_gpu_active(gpu)) {
280 struct msm_gem_submit *submit; 283 struct msm_gem_submit *submit;
281 uint32_t fence = gpu->funcs->last_fence(gpu);
282 284
283 /* retire completed submits, plus the one that hung: */ 285 /* retire completed submits, plus the one that hung: */
284 retire_submits(gpu, fence + 1); 286 retire_submits(gpu);
285 287
286 inactive_cancel(gpu); 288 inactive_cancel(gpu);
287 gpu->funcs->recover(gpu); 289 gpu->funcs->recover(gpu);
@@ -444,11 +446,12 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
444 drm_gem_object_unreference(&msm_obj->base); 446 drm_gem_object_unreference(&msm_obj->base);
445 } 447 }
446 448
449 fence_put(submit->fence);
447 list_del(&submit->node); 450 list_del(&submit->node);
448 kfree(submit); 451 kfree(submit);
449} 452}
450 453
451static void retire_submits(struct msm_gpu *gpu, uint32_t fence) 454static void retire_submits(struct msm_gpu *gpu)
452{ 455{
453 struct drm_device *dev = gpu->dev; 456 struct drm_device *dev = gpu->dev;
454 457
@@ -460,7 +463,7 @@ static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
460 submit = list_first_entry(&gpu->submit_list, 463 submit = list_first_entry(&gpu->submit_list,
461 struct msm_gem_submit, node); 464 struct msm_gem_submit, node);
462 465
463 if (submit->fence <= fence) { 466 if (fence_is_signaled(submit->fence)) {
464 retire_submit(gpu, submit); 467 retire_submit(gpu, submit);
465 } else { 468 } else {
466 break; 469 break;
@@ -477,7 +480,7 @@ static void retire_worker(struct work_struct *work)
477 msm_update_fence(gpu->fctx, fence); 480 msm_update_fence(gpu->fctx, fence);
478 481
479 mutex_lock(&dev->struct_mutex); 482 mutex_lock(&dev->struct_mutex);
480 retire_submits(gpu, fence); 483 retire_submits(gpu);
481 mutex_unlock(&dev->struct_mutex); 484 mutex_unlock(&dev->struct_mutex);
482 485
483 if (!msm_gpu_active(gpu)) 486 if (!msm_gpu_active(gpu))
@@ -502,7 +505,12 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
502 505
503 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 506 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
504 507
505 submit->fence = ++gpu->fctx->last_fence; 508 submit->fence = msm_fence_alloc(gpu->fctx);
509 if (IS_ERR(submit->fence)) {
510 ret = PTR_ERR(submit->fence);
511 submit->fence = NULL;
512 return ret;
513 }
506 514
507 inactive_cancel(gpu); 515 inactive_cancel(gpu);
508 516
@@ -526,11 +534,10 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
526 msm_gem_get_iova_locked(&msm_obj->base, 534 msm_gem_get_iova_locked(&msm_obj->base,
527 submit->gpu->id, &iova); 535 submit->gpu->id, &iova);
528 536
529 if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
530 msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
531
532 if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) 537 if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
533 msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence); 538 msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
539 else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
540 msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
534 } 541 }
535 542
536 ret = gpu->funcs->submit(gpu, submit, ctx); 543 ret = gpu->funcs->submit(gpu, submit, ctx);
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 9a78c48817c6..b48f73ac6389 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -296,7 +296,7 @@ void msm_rd_dump_submit(struct msm_gem_submit *submit)
296 296
297 n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u", 297 n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u",
298 TASK_COMM_LEN, current->comm, task_pid_nr(current), 298 TASK_COMM_LEN, current->comm, task_pid_nr(current),
299 submit->fence); 299 submit->fence->seqno);
300 300
301 rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4)); 301 rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
302 302