summaryrefslogtreecommitdiff
path: root/drivers/gpu/msm/adreno_dispatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/msm/adreno_dispatch.c')
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c127
1 files changed, 125 insertions, 2 deletions
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index cb4108b4e1f9..18c05e930216 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -359,6 +359,13 @@ static inline void _pop_drawobj(struct adreno_context *drawctxt)
drawctxt->queued--;
}
+static void _retire_sparseobj(struct kgsl_drawobj_sparse *sparseobj,
+ struct adreno_context *drawctxt)
+{
+ kgsl_sparse_bind(drawctxt->base.proc_priv, sparseobj);
+ _retire_timestamp(DRAWOBJ(sparseobj));
+}
+
static int _retire_markerobj(struct kgsl_drawobj_cmd *cmdobj,
struct adreno_context *drawctxt)
{
@@ -436,6 +443,8 @@ static struct kgsl_drawobj *_process_drawqueue_get_next_drawobj(
return drawobj;
} else if (drawobj->type == SYNCOBJ_TYPE)
ret = _retire_syncobj(SYNCOBJ(drawobj), drawctxt);
+ else
+ return ERR_PTR(-EINVAL);
if (ret == -EAGAIN)
return ERR_PTR(-EAGAIN);
@@ -670,6 +679,76 @@ static int sendcmd(struct adreno_device *adreno_dev,
return 0;
}
+
+/*
+ * Retires all sync objs from the sparse context
+ * queue and returns one of the below
+ * a) next sparseobj
+ * b) -EAGAIN for syncobj with syncpoints pending
+ * c) -EINVAL for unexpected drawobj
+ * d) NULL for no sparseobj
+ */
+static struct kgsl_drawobj_sparse *_get_next_sparseobj(
+ struct adreno_context *drawctxt)
+{
+ struct kgsl_drawobj *drawobj;
+ unsigned int i = drawctxt->drawqueue_head;
+ int ret = 0;
+
+ if (drawctxt->drawqueue_head == drawctxt->drawqueue_tail)
+ return NULL;
+
+ for (i = drawctxt->drawqueue_head; i != drawctxt->drawqueue_tail;
+ i = DRAWQUEUE_NEXT(i, ADRENO_CONTEXT_DRAWQUEUE_SIZE)) {
+
+ drawobj = drawctxt->drawqueue[i];
+
+ if (drawobj == NULL)
+ return NULL;
+
+ if (drawobj->type == SYNCOBJ_TYPE)
+ ret = _retire_syncobj(SYNCOBJ(drawobj), drawctxt);
+ else if (drawobj->type == SPARSEOBJ_TYPE)
+ return SPARSEOBJ(drawobj);
+ else
+ return ERR_PTR(-EINVAL);
+
+ if (ret == -EAGAIN)
+ return ERR_PTR(-EAGAIN);
+
+ continue;
+ }
+
+ return NULL;
+}
+
+static int _process_drawqueue_sparse(
+ struct adreno_context *drawctxt)
+{
+ struct kgsl_drawobj_sparse *sparseobj;
+ int ret = 0;
+ unsigned int i;
+
+ for (i = 0; i < ADRENO_CONTEXT_DRAWQUEUE_SIZE; i++) {
+
+ spin_lock(&drawctxt->lock);
+ sparseobj = _get_next_sparseobj(drawctxt);
+ if (IS_ERR_OR_NULL(sparseobj)) {
+ if (IS_ERR(sparseobj))
+ ret = PTR_ERR(sparseobj);
+ spin_unlock(&drawctxt->lock);
+ return ret;
+ }
+
+ _pop_drawobj(drawctxt);
+ spin_unlock(&drawctxt->lock);
+
+ _retire_sparseobj(sparseobj, drawctxt);
+ }
+
+ return 0;
+}
+
/**
* dispatcher_context_sendcmds() - Send commands from a context to the GPU
* @adreno_dev: Pointer to the adreno device struct
@@ -689,6 +768,9 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev,
int inflight = _drawqueue_inflight(dispatch_q);
unsigned int timestamp;
+ if (drawctxt->base.flags & KGSL_CONTEXT_SPARSE)
+ return _process_drawqueue_sparse(drawctxt);
+
if (dispatch_q->inflight >= inflight) {
spin_lock(&drawctxt->lock);
_process_drawqueue_get_next_drawobj(drawctxt);
@@ -1124,6 +1206,31 @@ static void _queue_drawobj(struct adreno_context *drawctxt,
trace_adreno_cmdbatch_queued(drawobj, drawctxt->queued);
}
+static int _queue_sparseobj(struct adreno_device *adreno_dev,
+ struct adreno_context *drawctxt, struct kgsl_drawobj_sparse *sparseobj,
+ uint32_t *timestamp, unsigned int user_ts)
+{
+ struct kgsl_drawobj *drawobj = DRAWOBJ(sparseobj);
+ int ret;
+
+ ret = get_timestamp(drawctxt, drawobj, timestamp, user_ts);
+ if (ret)
+ return ret;
+
+ /*
+ * See if we can fastpath this thing - if nothing is
+ * queued bind/unbind without queueing the context
+ */
+ if (!drawctxt->queued)
+ return 1;
+
+ drawctxt->queued_timestamp = *timestamp;
+ _queue_drawobj(drawctxt, drawobj);
+
+ return 0;
+}
+
+
static int _queue_markerobj(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt, struct kgsl_drawobj_cmd *markerobj,
uint32_t *timestamp, unsigned int user_ts)
@@ -1141,7 +1248,6 @@ static int _queue_markerobj(struct adreno_device *adreno_dev,
*/
if (!drawctxt->queued && kgsl_check_timestamp(drawobj->device,
drawobj->context, drawctxt->queued_timestamp)) {
- trace_adreno_cmdbatch_queued(drawobj, drawctxt->queued);
_retire_timestamp(drawobj);
return 1;
}
@@ -1212,7 +1318,7 @@ static void _queue_syncobj(struct adreno_context *drawctxt,
}
/**
- * adreno_dispactcher_queue_drawobj() - Queue a new draw object in the context
+ * adreno_dispactcher_queue_cmds() - Queue a new draw object in the context
* @dev_priv: Pointer to the device private struct
* @context: Pointer to the kgsl draw context
* @drawobj: Pointer to the array of drawobj's being submitted
@@ -1234,6 +1340,9 @@ int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv,
int ret;
unsigned int i, user_ts;
+ if (!count)
+ return -EINVAL;
+
ret = _check_context_state(&drawctxt->base);
if (ret)
return ret;
@@ -1283,6 +1392,20 @@ int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv,
_queue_syncobj(drawctxt, SYNCOBJ(drawobj[i]),
timestamp);
break;
+ case SPARSEOBJ_TYPE:
+ ret = _queue_sparseobj(adreno_dev, drawctxt,
+ SPARSEOBJ(drawobj[i]),
+ timestamp, user_ts);
+ if (ret == 1) {
+ spin_unlock(&drawctxt->lock);
+ _retire_sparseobj(SPARSEOBJ(drawobj[i]),
+ drawctxt);
+ return 0;
+ } else if (ret) {
+ spin_unlock(&drawctxt->lock);
+ return ret;
+ }
+ break;
default:
spin_unlock(&drawctxt->lock);
return -EINVAL;