···168168 OUT_PKT2(ring);169169170170 OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);171171- OUT_RING(ring, submit->fence);171171+ OUT_RING(ring, submit->fence->seqno);172172173173 if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) {174174 /* Flush HLSQ lazy updates to make sure there is nothing···185185 OUT_PKT3(ring, CP_EVENT_WRITE, 3);186186 OUT_RING(ring, CACHE_FLUSH_TS);187187 OUT_RING(ring, rbmemptr(adreno_gpu, fence));188188- OUT_RING(ring, submit->fence);188188+ OUT_RING(ring, submit->fence->seqno);189189190190 /* we could maybe be clever and only CP_COND_EXEC the interrupt: */191191 OUT_PKT3(ring, CP_INTERRUPT, 1);
+20-22
drivers/gpu/drm/msm/msm_atomic.c
···107107 }108108}109109110110-static void wait_fences(struct msm_commit *c, bool async)111111-{112112- int nplanes = c->dev->mode_config.num_total_plane;113113- ktime_t timeout = ktime_add_ms(ktime_get(), 1000);114114- int i;115115-116116- for (i = 0; i < nplanes; i++) {117117- struct drm_plane *plane = c->state->planes[i];118118- struct drm_plane_state *new_state = c->state->plane_states[i];119119-120120- if (!plane)121121- continue;122122-123123- if ((plane->state->fb != new_state->fb) && new_state->fb) {124124- struct drm_gem_object *obj =125125- msm_framebuffer_bo(new_state->fb, 0);126126- msm_gem_cpu_sync(obj, MSM_PREP_READ, &timeout);127127- }128128- }129129-}130130-131110/* The (potentially) asynchronous part of the commit. At this point132111 * nothing can fail short of armageddon.133112 */···117138 struct msm_drm_private *priv = dev->dev_private;118139 struct msm_kms *kms = priv->kms;119140120120- wait_fences(c, async);141141+ drm_atomic_helper_wait_for_fences(dev, state);121142122143 kms->funcs->prepare_commit(kms, state);123144···192213 struct drm_atomic_state *state, bool nonblock)193214{194215 struct msm_drm_private *priv = dev->dev_private;216216+ int nplanes = dev->mode_config.num_total_plane;195217 int ncrtcs = dev->mode_config.num_crtc;196218 struct msm_commit *c;197219 int i, ret;···215235 if (!crtc)216236 continue;217237 c->crtc_mask |= (1 << drm_crtc_index(crtc));238238+ }239239+240240+ /*241241+ * Figure out what fence to wait for:242242+ */243243+ for (i = 0; i < nplanes; i++) {244244+ struct drm_plane *plane = state->planes[i];245245+ struct drm_plane_state *new_state = state->plane_states[i];246246+247247+ if (!plane)248248+ continue;249249+250250+ if ((plane->state->fb != new_state->fb) && new_state->fb) {251251+ struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0);252252+ struct msm_gem_object *msm_obj = to_msm_bo(obj);253253+254254+ new_state->fence = reservation_object_get_excl_rcu(msm_obj->resv);255255+ }218256 }219257220258 /*
···411411 return ret;412412}413413414414+/* must be called before _move_to_active().. */415415+int msm_gem_sync_object(struct drm_gem_object *obj,416416+ struct msm_fence_context *fctx, bool exclusive)417417+{418418+ struct msm_gem_object *msm_obj = to_msm_bo(obj);419419+ struct reservation_object_list *fobj;420420+ struct fence *fence;421421+ int i, ret;422422+423423+ if (!exclusive) {424424+ /* NOTE: _reserve_shared() must happen before _add_shared_fence(),425425+ * which makes this a slightly strange place to call it. OTOH this426426+ * is a convenient can-fail point to hook it in. (And similar to427427+ * how etnaviv and nouveau handle this.)428428+ */429429+ ret = reservation_object_reserve_shared(msm_obj->resv);430430+ if (ret)431431+ return ret;432432+ }433433+434434+ fobj = reservation_object_get_list(msm_obj->resv);435435+ if (!fobj || (fobj->shared_count == 0)) {436436+ fence = reservation_object_get_excl(msm_obj->resv);437437+ /* don't need to wait on our own fences, since ring is fifo */438438+ if (fence && (fence->context != fctx->context)) {439439+ ret = fence_wait(fence, true);440440+ if (ret)441441+ return ret;442442+ }443443+ }444444+445445+ if (!exclusive || !fobj)446446+ return 0;447447+448448+ for (i = 0; i < fobj->shared_count; i++) {449449+ fence = rcu_dereference_protected(fobj->shared[i],450450+ reservation_object_held(msm_obj->resv));451451+ if (fence->context != fctx->context) {452452+ ret = fence_wait(fence, true);453453+ if (ret)454454+ return ret;455455+ }456456+ }457457+458458+ return 0;459459+}460460+414461void msm_gem_move_to_active(struct drm_gem_object *obj,415415- struct msm_gpu *gpu, bool write, uint32_t fence)462462+ struct msm_gpu *gpu, bool exclusive, struct fence *fence)416463{417464 struct msm_gem_object *msm_obj = to_msm_bo(obj);418465 msm_obj->gpu = gpu;419419- if (write)420420- msm_obj->write_fence = fence;466466+ if (exclusive)467467+ reservation_object_add_excl_fence(msm_obj->resv, fence);421468 else422422- msm_obj->read_fence = fence;469469+ reservation_object_add_shared_fence(msm_obj->resv, fence);423470 list_del_init(&msm_obj->mm_list);424471 list_add_tail(&msm_obj->mm_list, &gpu->active_list);425472}···480433 WARN_ON(!mutex_is_locked(&dev->struct_mutex));481434482435 msm_obj->gpu = NULL;483483- msm_obj->read_fence = 0;484484- msm_obj->write_fence = 0;485436 list_del_init(&msm_obj->mm_list);486437 list_add_tail(&msm_obj->mm_list, &priv->inactive_list);487438}488439489489-int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)490490-{491491- struct drm_device *dev = obj->dev;492492- struct msm_drm_private *priv = dev->dev_private;493493- struct msm_gem_object *msm_obj = to_msm_bo(obj);494494- int ret = 0;495495-496496- if (is_active(msm_obj)) {497497- uint32_t fence = msm_gem_fence(msm_obj, op);498498-499499- if (op & MSM_PREP_NOSYNC)500500- timeout = NULL;501501-502502- if (priv->gpu)503503- ret = msm_wait_fence(priv->gpu->fctx, fence, timeout, true);504504- }505505-506506- return ret;507507-}508508-509440int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)510441{511511- int ret = msm_gem_cpu_sync(obj, op, timeout);442442+ struct msm_gem_object *msm_obj = to_msm_bo(obj);443443+ bool write = !!(op & MSM_PREP_WRITE);444444+445445+ if (op & MSM_PREP_NOSYNC) {446446+ if (!reservation_object_test_signaled_rcu(msm_obj->resv, write))447447+ return -EBUSY;448448+ } else {449449+ int ret;450450+451451+ ret = reservation_object_wait_timeout_rcu(msm_obj->resv, write,452452+ true, timeout_to_jiffies(timeout));453453+ if (ret <= 0)454454+ return ret == 0 ? -ETIMEDOUT : ret;455455+ }512456513457 /* TODO cache maintenance */514458515515- return ret;459459+ return 0;516460}517461518462int msm_gem_cpu_fini(struct drm_gem_object *obj)···513475}514476515477#ifdef CONFIG_DEBUG_FS478478+static void describe_fence(struct fence *fence, const char *type,479479+ struct seq_file *m)480480+{481481+ if (!fence_is_signaled(fence))482482+ seq_printf(m, "\t%9s: %s %s seq %u\n", type,483483+ fence->ops->get_driver_name(fence),484484+ fence->ops->get_timeline_name(fence),485485+ fence->seqno);486486+}487487+516488void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)517489{518518- struct drm_device *dev = obj->dev;519490 struct msm_gem_object *msm_obj = to_msm_bo(obj);491491+ struct reservation_object *robj = msm_obj->resv;492492+ struct reservation_object_list *fobj;493493+ struct fence *fence;520494 uint64_t off = drm_vma_node_start(&obj->vma_node);521495522522- WARN_ON(!mutex_is_locked(&dev->struct_mutex));523523- seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %zu\n",496496+ WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));497497+498498+ seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu\n",524499 msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',525525- msm_obj->read_fence, msm_obj->write_fence,526500 obj->name, obj->refcount.refcount.counter,527501 off, msm_obj->vaddr, obj->size);502502+503503+ rcu_read_lock();504504+ fobj = rcu_dereference(robj->fence);505505+ if (fobj) {506506+ unsigned int i, shared_count = fobj->shared_count;507507+508508+ for (i = 0; i < shared_count; i++) {509509+ fence = rcu_dereference(fobj->shared[i]);510510+ describe_fence(fence, "Shared", m);511511+ }512512+ }513513+514514+ fence = rcu_dereference(robj->fence_excl);515515+ if (fence)516516+ describe_fence(fence, "Exclusive", m);517517+ rcu_read_unlock();528518}529519530520void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
+1-15
drivers/gpu/drm/msm/msm_gem.h
···3939 */4040 struct list_head mm_list;4141 struct msm_gpu *gpu; /* non-null if active */4242- uint32_t read_fence, write_fence;43424443 /* Transiently in the process of submit ioctl, objects associated4544 * with the submit are on submit->bo_list.. this only lasts for···7273 return msm_obj->gpu != NULL;7374}74757575-static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,7676- uint32_t op)7777-{7878- uint32_t fence = 0;7979-8080- if (op & MSM_PREP_READ)8181- fence = msm_obj->write_fence;8282- if (op & MSM_PREP_WRITE)8383- fence = max(fence, msm_obj->read_fence);8484-8585- return fence;8686-}8787-8876#define MAX_CMDS 489779078/* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,···8599 struct list_head node; /* node in gpu submit_list */86100 struct list_head bo_list;87101 struct ww_acquire_ctx ticket;8888- uint32_t fence;102102+ struct fence *fence;89103 bool valid; /* true if no cmdstream patching needed */90104 unsigned int nr_cmds;91105 unsigned int nr_bos;
+21-1
drivers/gpu/drm/msm/msm_gem_submit.c
···184184 return ret;185185}186186187187+static int submit_fence_sync(struct msm_gem_submit *submit)188188+{189189+ int i, ret = 0;190190+191191+ for (i = 0; i < submit->nr_bos; i++) {192192+ struct msm_gem_object *msm_obj = submit->bos[i].obj;193193+ bool write = submit->bos[i].flags & MSM_SUBMIT_BO_WRITE;194194+195195+ ret = msm_gem_sync_object(&msm_obj->base, submit->gpu->fctx, write);196196+ if (ret)197197+ break;198198+ }199199+200200+ return ret;201201+}202202+187203static int submit_pin_objects(struct msm_gem_submit *submit)188204{189205 int i, ret = 0;···374358 if (ret)375359 goto out;376360361361+ ret = submit_fence_sync(submit);362362+ if (ret)363363+ goto out;364364+377365 ret = submit_pin_objects(submit);378366 if (ret)379367 goto out;···444424445425 ret = msm_gpu_submit(gpu, submit, ctx);446426447447- args->fence = submit->fence;427427+ args->fence = submit->fence->seqno;448428449429out:450430 submit_cleanup(submit, !!ret);