Commit bf6811f3 authored by Rob Clark's avatar Rob Clark

drm/msm: handle read vs write fences

The userspace API already had everything needed to handle read vs write
synchronization.  This patch actually bothers to hook it up properly, so
that we don't need to (for example) stall on userspace read access to a
buffer that gpu is also still reading.
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 86a7e122
......@@ -153,7 +153,7 @@ void *msm_gem_vaddr(struct drm_gem_object *obj);
int msm_gem_queue_inactive_work(struct drm_gem_object *obj,
struct work_struct *work);
void msm_gem_move_to_active(struct drm_gem_object *obj,
struct msm_gpu *gpu, uint32_t fence);
struct msm_gpu *gpu, bool write, uint32_t fence);
void msm_gem_move_to_inactive(struct drm_gem_object *obj);
int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
struct timespec *timeout);
......
......@@ -393,11 +393,14 @@ int msm_gem_queue_inactive_work(struct drm_gem_object *obj,
}
void msm_gem_move_to_active(struct drm_gem_object *obj,
struct msm_gpu *gpu, uint32_t fence)
struct msm_gpu *gpu, bool write, uint32_t fence)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
msm_obj->gpu = gpu;
msm_obj->fence = fence;
if (write)
msm_obj->write_fence = fence;
else
msm_obj->read_fence = fence;
list_del_init(&msm_obj->mm_list);
list_add_tail(&msm_obj->mm_list, &gpu->active_list);
}
......@@ -411,7 +414,8 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
msm_obj->gpu = NULL;
msm_obj->fence = 0;
msm_obj->read_fence = 0;
msm_obj->write_fence = 0;
list_del_init(&msm_obj->mm_list);
list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
......@@ -433,8 +437,14 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
struct msm_gem_object *msm_obj = to_msm_bo(obj);
int ret = 0;
if (is_active(msm_obj) && !(op & MSM_PREP_NOSYNC))
ret = msm_wait_fence_interruptable(dev, msm_obj->fence, timeout);
if (is_active(msm_obj) && !(op & MSM_PREP_NOSYNC)) {
uint32_t fence = 0;
if (op & MSM_PREP_READ)
fence = msm_obj->write_fence;
if (op & MSM_PREP_WRITE)
fence = max(fence, msm_obj->read_fence);
ret = msm_wait_fence_interruptable(dev, fence, timeout);
}
/* TODO cache maintenance */
......@@ -455,9 +465,10 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
uint64_t off = drm_vma_node_start(&obj->vma_node);
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
seq_printf(m, "%08x: %c(%d) %2d (%2d) %08llx %p %d\n",
seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %d\n",
msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
msm_obj->fence, obj->name, obj->refcount.refcount.counter,
msm_obj->read_fence, msm_obj->write_fence,
obj->name, obj->refcount.refcount.counter,
off, msm_obj->vaddr, obj->size);
}
......
......@@ -36,7 +36,7 @@ struct msm_gem_object {
*/
struct list_head mm_list;
struct msm_gpu *gpu; /* non-null if active */
uint32_t fence;
uint32_t read_fence, write_fence;
/* Transiently in the process of submit ioctl, objects associated
* with the submit are on submit->bo_list.. this only lasts for
......
......@@ -265,7 +265,8 @@ static void retire_worker(struct work_struct *work)
obj = list_first_entry(&gpu->active_list,
struct msm_gem_object, mm_list);
if (obj->fence <= fence) {
if ((obj->read_fence <= fence) &&
(obj->write_fence <= fence)) {
/* move to inactive: */
msm_gem_move_to_inactive(&obj->base);
msm_gem_put_iova(&obj->base, gpu->id);
......@@ -321,7 +322,11 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
submit->gpu->id, &iova);
}
msm_gem_move_to_active(&msm_obj->base, gpu, submit->fence);
if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
}
hangcheck_timer_reset(gpu);
mutex_unlock(&dev->struct_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment