diff options
author | Rob Clark <robdclark@gmail.com> | 2016-03-15 18:26:28 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2016-05-08 10:22:15 -0400 |
commit | b6295f9a38fc3f7d59ec0caa45aa803461c6cea5 (patch) | |
tree | 81f8e68dfaf8d900d86cd971e293d6a824a178d0 | |
parent | ba00c3f2f0c84456ffe9d548823ff4fb8e4e7ed4 (diff) |
drm/msm: 'struct fence' conversion
Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_atomic.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_fence.c | 71 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_fence.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.c | 124 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem_submit.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_rd.c | 2 |
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 | ||
110 | static 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); | |||
190 | void msm_gem_prime_unpin(struct drm_gem_object *obj); | 190 | void msm_gem_prime_unpin(struct drm_gem_object *obj); |
191 | void *msm_gem_vaddr_locked(struct drm_gem_object *obj); | 191 | void *msm_gem_vaddr_locked(struct drm_gem_object *obj); |
192 | void *msm_gem_vaddr(struct drm_gem_object *obj); | 192 | void *msm_gem_vaddr(struct drm_gem_object *obj); |
193 | int msm_gem_sync_object(struct drm_gem_object *obj, | ||
194 | struct msm_fence_context *fctx, bool exclusive); | ||
193 | void msm_gem_move_to_active(struct drm_gem_object *obj, | 195 | void 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); |
195 | void msm_gem_move_to_inactive(struct drm_gem_object *obj); | 197 | void msm_gem_move_to_inactive(struct drm_gem_object *obj); |
196 | int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); | ||
197 | int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); | 198 | int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); |
198 | int msm_gem_cpu_fini(struct drm_gem_object *obj); | 199 | int msm_gem_cpu_fini(struct drm_gem_object *obj); |
199 | void msm_gem_free_object(struct drm_gem_object *obj); | 200 | void 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: */ | ||
50 | int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence, | 53 | int 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 */ |
89 | void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) | 92 | void 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 | |||
101 | struct msm_fence { | ||
102 | struct msm_fence_context *fctx; | ||
103 | struct fence base; | ||
104 | }; | ||
105 | |||
106 | static inline struct msm_fence *to_msm_fence(struct fence *fence) | ||
107 | { | ||
108 | return container_of(fence, struct msm_fence, base); | ||
109 | } | ||
110 | |||
111 | static const char *msm_fence_get_driver_name(struct fence *fence) | ||
112 | { | ||
113 | return "msm"; | ||
114 | } | ||
115 | |||
116 | static 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 | |||
122 | static bool msm_fence_enable_signaling(struct fence *fence) | ||
123 | { | ||
124 | return true; | ||
125 | } | ||
126 | |||
127 | static 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 | |||
133 | static 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 | |||
139 | static 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 | |||
148 | struct fence * | ||
149 | msm_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 @@ | |||
23 | struct msm_fence_context { | 23 | struct 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 | ||
32 | struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev, | 34 | struct 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); |
40 | void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence); | 42 | void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence); |
41 | 43 | ||
44 | struct 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().. */ | ||
415 | int 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 | |||
414 | void msm_gem_move_to_active(struct drm_gem_object *obj, | 461 | void 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 | ||
442 | int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) | 487 | int 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 | |||
462 | int 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 | ||
471 | int msm_gem_cpu_fini(struct drm_gem_object *obj) | 509 | int 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 |
516 | static 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 | |||
478 | void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) | 526 | void 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 | ||
492 | void msm_gem_describe_objects(struct list_head *list, struct seq_file *m) | 558 | void 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 | ||
76 | static 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 | ||
187 | static 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 | |||
187 | static int submit_pin_objects(struct msm_gem_submit *submit) | 203 | static 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 | ||
429 | out: | 449 | out: |
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 | ||
269 | static void retire_submits(struct msm_gpu *gpu, uint32_t fence); | 269 | static void retire_submits(struct msm_gpu *gpu); |
270 | 270 | ||
271 | static void recover_worker(struct work_struct *work) | 271 | static 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 | ||
451 | static void retire_submits(struct msm_gpu *gpu, uint32_t fence) | 454 | static 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 | ||