summaryrefslogtreecommitdiff
path: root/tegra/pushbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'tegra/pushbuf.c')
-rw-r--r--tegra/pushbuf.c111
1 files changed, 99 insertions, 12 deletions
diff --git a/tegra/pushbuf.c b/tegra/pushbuf.c
index 7be12a76..54a0f831 100644
--- a/tegra/pushbuf.c
+++ b/tegra/pushbuf.c
@@ -48,9 +48,14 @@ int drm_tegra_pushbuf_queue(struct drm_tegra_pushbuf_private *pushbuf)
/* add buffer object as command buffers for this job */
memset(&cmdbuf, 0, sizeof(cmdbuf));
- cmdbuf.words = pushbuf->base.ptr - pushbuf->start;
- cmdbuf.handle = pushbuf->bo->handle;
+ cmdbuf.index = pushbuf->index;
cmdbuf.offset = 0;
+ cmdbuf.words = pushbuf->base.ptr - pushbuf->start;
+
+ if (pushbuf->num_fences) {
+ cmdbuf.fences = (uintptr_t)pushbuf->fences;
+ cmdbuf.num_fences = pushbuf->num_fences;
+ }
err = drm_tegra_job_add_cmdbuf(pushbuf->job, &cmdbuf);
if (err < 0)
@@ -82,7 +87,7 @@ int drm_tegra_pushbuf_new(struct drm_tegra_pushbuf **pushbufp,
*pushbufp = &pushbuf->base;
- DRMLISTADD(&pushbuf->list, &job->pushbufs);
+ DRMLISTADDTAIL(&pushbuf->list, &job->pushbufs);
job->pushbuf = pushbuf;
return 0;
@@ -117,6 +122,7 @@ int drm_tegra_pushbuf_prepare(struct drm_tegra_pushbuf *pushbuf,
{
struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf);
struct drm_tegra_channel *channel = priv->job->channel;
+ struct drm_tegra_buffer buffer;
struct drm_tegra_bo *bo;
void *ptr;
int err;
@@ -148,12 +154,19 @@ int drm_tegra_pushbuf_prepare(struct drm_tegra_pushbuf *pushbuf,
return err;
}
- DRMLISTADD(&bo->list, &priv->bos);
+ DRMLISTADDTAIL(&bo->list, &priv->bos);
priv->start = priv->base.ptr = ptr;
- priv->end = priv->start + bo->size;
+ priv->end = priv->start + bo->size / 4;
priv->bo = bo;
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.handle = bo->handle;
+
+ err = drm_tegra_job_add_buffer(priv->job, &buffer, &priv->index);
+ if (err < 0)
+ return err;
+
return 0;
}
@@ -163,13 +176,22 @@ int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf,
unsigned long shift)
{
struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf);
+ struct drm_tegra_buffer buffer;
struct drm_tegra_reloc reloc;
+ unsigned int index;
int err;
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.handle = target->handle;
+
+ err = drm_tegra_job_add_buffer(priv->job, &buffer, &index);
+ if (err < 0)
+ return err;
+
memset(&reloc, 0, sizeof(reloc));
- reloc.cmdbuf.handle = priv->bo->handle;
+ reloc.cmdbuf.index = priv->index;
reloc.cmdbuf.offset = drm_tegra_pushbuf_get_offset(pushbuf);
- reloc.target.handle = target->handle;
+ reloc.target.index = index;
reloc.target.offset = offset;
reloc.shift = shift;
@@ -182,17 +204,82 @@ int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf,
return 0;
}
-int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf,
- enum drm_tegra_syncpt_cond cond)
+static int drm_tegra_pushbuf_add_fence(struct drm_tegra_pushbuf *pushbuf,
+ const struct drm_tegra_fence *fence)
{
struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf);
+ struct drm_tegra_fence *fences;
+ size_t size;
+
+ size = (priv->num_fences + 1) * sizeof(*fence);
+
+ fences = realloc(priv->fences, size);
+ if (!fences)
+ return -ENOMEM;
+
+ priv->fences = fences;
+
+ priv->fences[priv->num_fences++] = *fence;
+
+ return 0;
+}
+
+int drm_tegra_pushbuf_wait_fd(struct drm_tegra_pushbuf *pushbuf,
+ int fd)
+{
+ struct drm_tegra_fence fence;
+ int err;
+
+ memset(&fence, 0, sizeof(fence));
+ fence.handle = fd;
+ fence.flags = DRM_TEGRA_FENCE_FD | DRM_TEGRA_FENCE_WAIT;
- if (cond >= DRM_TEGRA_SYNCPT_COND_MAX)
+ err = drm_tegra_pushbuf_add_fence(pushbuf, &fence);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+int drm_tegra_pushbuf_wait_syncobj(struct drm_tegra_pushbuf *pushbuf,
+ uint32_t syncobj)
+{
+ struct drm_tegra_fence fence;
+ int err;
+
+ memset(&fence, 0, sizeof(fence));
+ fence.handle = syncobj;
+ fence.flags = DRM_TEGRA_FENCE_WAIT;
+
+ err = drm_tegra_pushbuf_add_fence(pushbuf, &fence);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf,
+ unsigned int index, unsigned int value,
+ enum drm_tegra_sync_cond cond)
+{
+ struct drm_tegra_fence fence;
+ int err;
+
+ if (cond >= DRM_TEGRA_SYNC_COND_MAX)
return -EINVAL;
*pushbuf->ptr++ = HOST1X_OPCODE_NONINCR(0x0, 0x1);
- *pushbuf->ptr++ = cond << 8 | priv->job->syncpt;
- priv->job->increments++;
+ *pushbuf->ptr++ = cond;
+
+ memset(&fence, 0, sizeof(fence));
+ fence.flags = DRM_TEGRA_FENCE_EMIT;
+ fence.offset = drm_tegra_pushbuf_get_offset(pushbuf) - 4;
+ fence.index = index;
+ fence.value = value;
+
+ err = drm_tegra_pushbuf_add_fence(pushbuf, &fence);
+ if (err < 0)
+ return err;
return 0;
}