Loading drivers/gpu/drm/msm/adreno/adreno_gpu.c +2 −2 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, OUT_PKT2(ring); OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); OUT_RING(ring, submit->fence); OUT_RING(ring, submit->fence->seqno); if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) { /* Flush HLSQ lazy updates to make sure there is nothing Loading @@ -185,7 +185,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, OUT_PKT3(ring, CP_EVENT_WRITE, 3); OUT_RING(ring, CACHE_FLUSH_TS); OUT_RING(ring, rbmemptr(adreno_gpu, fence)); OUT_RING(ring, submit->fence); OUT_RING(ring, submit->fence->seqno); /* we could maybe be clever and only CP_COND_EXEC the interrupt: */ OUT_PKT3(ring, CP_INTERRUPT, 1); Loading drivers/gpu/drm/msm/msm_atomic.c +20 −22 Original line number Diff line number Diff line Loading @@ -107,27 +107,6 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev, } } static void wait_fences(struct msm_commit *c, bool async) { int nplanes = c->dev->mode_config.num_total_plane; ktime_t timeout = ktime_add_ms(ktime_get(), 1000); int i; for (i = 0; i < nplanes; i++) { struct drm_plane *plane = c->state->planes[i]; struct drm_plane_state *new_state = c->state->plane_states[i]; if (!plane) continue; if ((plane->state->fb != new_state->fb) && new_state->fb) { struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0); msm_gem_cpu_sync(obj, MSM_PREP_READ, &timeout); } } } /* The (potentially) asynchronous part of the commit. At this point * nothing can fail short of armageddon. */ Loading @@ -138,7 +117,7 @@ static void complete_commit(struct msm_commit *c, bool async) struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; wait_fences(c, async); drm_atomic_helper_wait_for_fences(dev, state); kms->funcs->prepare_commit(kms, state); Loading Loading @@ -213,6 +192,7 @@ int msm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { struct msm_drm_private *priv = dev->dev_private; int nplanes = dev->mode_config.num_total_plane; int ncrtcs = dev->mode_config.num_crtc; struct msm_commit *c; int i, ret; Loading @@ -237,6 +217,24 @@ int msm_atomic_commit(struct drm_device *dev, c->crtc_mask |= (1 << drm_crtc_index(crtc)); } /* * Figure out what fence to wait for: */ for (i = 0; i < nplanes; i++) { struct drm_plane *plane = state->planes[i]; struct drm_plane_state *new_state = state->plane_states[i]; if (!plane) continue; if ((plane->state->fb != new_state->fb) && new_state->fb) { struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0); struct msm_gem_object *msm_obj = to_msm_bo(obj); new_state->fence = reservation_object_get_excl_rcu(msm_obj->resv); } } /* * Wait for pending updates on any of the same crtc's and then * mark our set of crtc's as busy: Loading drivers/gpu/drm/msm/msm_drv.h +3 −2 Original line number Diff line number Diff line Loading @@ -190,10 +190,11 @@ int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); void *msm_gem_vaddr_locked(struct drm_gem_object *obj); void *msm_gem_vaddr(struct drm_gem_object *obj); int msm_gem_sync_object(struct drm_gem_object *obj, struct msm_fence_context *fctx, bool exclusive); void msm_gem_move_to_active(struct drm_gem_object *obj, struct msm_gpu *gpu, bool write, uint32_t fence); struct msm_gpu *gpu, bool exclusive, struct fence *fence); void msm_gem_move_to_inactive(struct drm_gem_object *obj); int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); int msm_gem_cpu_fini(struct drm_gem_object *obj); void msm_gem_free_object(struct drm_gem_object *obj); Loading drivers/gpu/drm/msm/msm_fence.c +69 −2 Original line number Diff line number Diff line Loading @@ -32,7 +32,9 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name) fctx->dev = dev; fctx->name = name; fctx->context = fence_context_alloc(1); init_waitqueue_head(&fctx->event); spin_lock_init(&fctx->spinlock); return fctx; } Loading @@ -47,6 +49,7 @@ static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fenc return (int32_t)(fctx->completed_fence - fence) >= 0; } /* legacy path for WAIT_FENCE ioctl: */ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence, ktime_t *timeout, bool interruptible) { Loading Loading @@ -88,9 +91,73 @@ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence, /* called from workqueue */ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) { mutex_lock(&fctx->dev->struct_mutex); spin_lock(&fctx->spinlock); fctx->completed_fence = max(fence, fctx->completed_fence); mutex_unlock(&fctx->dev->struct_mutex); spin_unlock(&fctx->spinlock); wake_up_all(&fctx->event); } struct msm_fence { struct msm_fence_context *fctx; struct fence base; }; static inline struct msm_fence *to_msm_fence(struct fence *fence) { return container_of(fence, struct msm_fence, base); } static const char *msm_fence_get_driver_name(struct fence *fence) { return "msm"; } static const char *msm_fence_get_timeline_name(struct fence *fence) { struct msm_fence *f = to_msm_fence(fence); return f->fctx->name; } static bool msm_fence_enable_signaling(struct fence *fence) { return true; } static bool msm_fence_signaled(struct fence *fence) { struct msm_fence *f = to_msm_fence(fence); return fence_completed(f->fctx, f->base.seqno); } static void msm_fence_release(struct fence *fence) { struct msm_fence *f = to_msm_fence(fence); kfree_rcu(f, base.rcu); } static const struct fence_ops msm_fence_ops = { .get_driver_name = msm_fence_get_driver_name, .get_timeline_name = msm_fence_get_timeline_name, .enable_signaling = msm_fence_enable_signaling, .signaled = msm_fence_signaled, .wait = fence_default_wait, .release = msm_fence_release, }; struct fence * msm_fence_alloc(struct msm_fence_context *fctx) { struct msm_fence *f; f = kzalloc(sizeof(*f), GFP_KERNEL); if (!f) return ERR_PTR(-ENOMEM); f->fctx = fctx; fence_init(&f->base, &msm_fence_ops, &fctx->spinlock, fctx->context, ++fctx->last_fence); return &f->base; } drivers/gpu/drm/msm/msm_fence.h +4 −0 Original line number Diff line number Diff line Loading @@ -23,10 +23,12 @@ struct msm_fence_context { struct drm_device *dev; const char *name; unsigned context; /* last_fence == completed_fence --> no pending work */ uint32_t last_fence; /* last assigned fence */ uint32_t completed_fence; /* last completed fence */ wait_queue_head_t event; spinlock_t spinlock; }; struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev, Loading @@ -39,4 +41,6 @@ int msm_queue_fence_cb(struct msm_fence_context *fctx, struct msm_fence_cb *cb, uint32_t fence); void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence); struct fence * msm_fence_alloc(struct msm_fence_context *fctx); #endif Loading
drivers/gpu/drm/msm/adreno/adreno_gpu.c +2 −2 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, OUT_PKT2(ring); OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); OUT_RING(ring, submit->fence); OUT_RING(ring, submit->fence->seqno); if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) { /* Flush HLSQ lazy updates to make sure there is nothing Loading @@ -185,7 +185,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, OUT_PKT3(ring, CP_EVENT_WRITE, 3); OUT_RING(ring, CACHE_FLUSH_TS); OUT_RING(ring, rbmemptr(adreno_gpu, fence)); OUT_RING(ring, submit->fence); OUT_RING(ring, submit->fence->seqno); /* we could maybe be clever and only CP_COND_EXEC the interrupt: */ OUT_PKT3(ring, CP_INTERRUPT, 1); Loading
drivers/gpu/drm/msm/msm_atomic.c +20 −22 Original line number Diff line number Diff line Loading @@ -107,27 +107,6 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev, } } static void wait_fences(struct msm_commit *c, bool async) { int nplanes = c->dev->mode_config.num_total_plane; ktime_t timeout = ktime_add_ms(ktime_get(), 1000); int i; for (i = 0; i < nplanes; i++) { struct drm_plane *plane = c->state->planes[i]; struct drm_plane_state *new_state = c->state->plane_states[i]; if (!plane) continue; if ((plane->state->fb != new_state->fb) && new_state->fb) { struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0); msm_gem_cpu_sync(obj, MSM_PREP_READ, &timeout); } } } /* The (potentially) asynchronous part of the commit. At this point * nothing can fail short of armageddon. */ Loading @@ -138,7 +117,7 @@ static void complete_commit(struct msm_commit *c, bool async) struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; wait_fences(c, async); drm_atomic_helper_wait_for_fences(dev, state); kms->funcs->prepare_commit(kms, state); Loading Loading @@ -213,6 +192,7 @@ int msm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { struct msm_drm_private *priv = dev->dev_private; int nplanes = dev->mode_config.num_total_plane; int ncrtcs = dev->mode_config.num_crtc; struct msm_commit *c; int i, ret; Loading @@ -237,6 +217,24 @@ int msm_atomic_commit(struct drm_device *dev, c->crtc_mask |= (1 << drm_crtc_index(crtc)); } /* * Figure out what fence to wait for: */ for (i = 0; i < nplanes; i++) { struct drm_plane *plane = state->planes[i]; struct drm_plane_state *new_state = state->plane_states[i]; if (!plane) continue; if ((plane->state->fb != new_state->fb) && new_state->fb) { struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0); struct msm_gem_object *msm_obj = to_msm_bo(obj); new_state->fence = reservation_object_get_excl_rcu(msm_obj->resv); } } /* * Wait for pending updates on any of the same crtc's and then * mark our set of crtc's as busy: Loading
drivers/gpu/drm/msm/msm_drv.h +3 −2 Original line number Diff line number Diff line Loading @@ -190,10 +190,11 @@ int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); void *msm_gem_vaddr_locked(struct drm_gem_object *obj); void *msm_gem_vaddr(struct drm_gem_object *obj); int msm_gem_sync_object(struct drm_gem_object *obj, struct msm_fence_context *fctx, bool exclusive); void msm_gem_move_to_active(struct drm_gem_object *obj, struct msm_gpu *gpu, bool write, uint32_t fence); struct msm_gpu *gpu, bool exclusive, struct fence *fence); void msm_gem_move_to_inactive(struct drm_gem_object *obj); int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); int msm_gem_cpu_fini(struct drm_gem_object *obj); void msm_gem_free_object(struct drm_gem_object *obj); Loading
drivers/gpu/drm/msm/msm_fence.c +69 −2 Original line number Diff line number Diff line Loading @@ -32,7 +32,9 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name) fctx->dev = dev; fctx->name = name; fctx->context = fence_context_alloc(1); init_waitqueue_head(&fctx->event); spin_lock_init(&fctx->spinlock); return fctx; } Loading @@ -47,6 +49,7 @@ static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fenc return (int32_t)(fctx->completed_fence - fence) >= 0; } /* legacy path for WAIT_FENCE ioctl: */ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence, ktime_t *timeout, bool interruptible) { Loading Loading @@ -88,9 +91,73 @@ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence, /* called from workqueue */ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) { mutex_lock(&fctx->dev->struct_mutex); spin_lock(&fctx->spinlock); fctx->completed_fence = max(fence, fctx->completed_fence); mutex_unlock(&fctx->dev->struct_mutex); spin_unlock(&fctx->spinlock); wake_up_all(&fctx->event); } struct msm_fence { struct msm_fence_context *fctx; struct fence base; }; static inline struct msm_fence *to_msm_fence(struct fence *fence) { return container_of(fence, struct msm_fence, base); } static const char *msm_fence_get_driver_name(struct fence *fence) { return "msm"; } static const char *msm_fence_get_timeline_name(struct fence *fence) { struct msm_fence *f = to_msm_fence(fence); return f->fctx->name; } static bool msm_fence_enable_signaling(struct fence *fence) { return true; } static bool msm_fence_signaled(struct fence *fence) { struct msm_fence *f = to_msm_fence(fence); return fence_completed(f->fctx, f->base.seqno); } static void msm_fence_release(struct fence *fence) { struct msm_fence *f = to_msm_fence(fence); kfree_rcu(f, base.rcu); } static const struct fence_ops msm_fence_ops = { .get_driver_name = msm_fence_get_driver_name, .get_timeline_name = msm_fence_get_timeline_name, .enable_signaling = msm_fence_enable_signaling, .signaled = msm_fence_signaled, .wait = fence_default_wait, .release = msm_fence_release, }; struct fence * msm_fence_alloc(struct msm_fence_context *fctx) { struct msm_fence *f; f = kzalloc(sizeof(*f), GFP_KERNEL); if (!f) return ERR_PTR(-ENOMEM); f->fctx = fctx; fence_init(&f->base, &msm_fence_ops, &fctx->spinlock, fctx->context, ++fctx->last_fence); return &f->base; }
drivers/gpu/drm/msm/msm_fence.h +4 −0 Original line number Diff line number Diff line Loading @@ -23,10 +23,12 @@ struct msm_fence_context { struct drm_device *dev; const char *name; unsigned context; /* last_fence == completed_fence --> no pending work */ uint32_t last_fence; /* last assigned fence */ uint32_t completed_fence; /* last completed fence */ wait_queue_head_t event; spinlock_t spinlock; }; struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev, Loading @@ -39,4 +41,6 @@ int msm_queue_fence_cb(struct msm_fence_context *fctx, struct msm_fence_cb *cb, uint32_t fence); void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence); struct fence * msm_fence_alloc(struct msm_fence_context *fctx); #endif