summaryrefslogtreecommitdiff
path: root/drivers/gpu/msm/kgsl.c
diff options
context:
space:
mode:
authorTarun Karra <tkarra@codeaurora.org>2016-11-14 16:38:27 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2016-12-07 10:33:16 -0800
commitc71cda2d1010e7c936db468b5b4d3bcb2797f1c7 (patch)
treeda6bbd6228913241499e23ce75449c7267a6bc79 /drivers/gpu/msm/kgsl.c
parent368fecd7df5b203a5ce684a0c77726a5690c1147 (diff)
msm: kgsl: Add Bind objects to dispatcher draw queue
kgsl_ioctl_gpu_sparse_command() is added to for user to specify list of binds/unbinds for a memory entry and syncpoints they depend on. If user specifies both create a sync object for syncpoints and bind object for binds/unbinds and add them to dispatcher draw queue. Sync object should be inserted before the bind object in the draw queue. Once the bind object reaches the head of draw queue the corresponding binds/unbinds are performed. kgsl_ioctl_gpu_sparse_command() only accepts commands from context created with flag KGSL_CONTEXT_SPARSE, commands from all other context types will return an error. Change-Id: Ib0a2361f854ae01d0d8090cdd48cfa96308daf93 Signed-off-by: Tarun Karra <tkarra@codeaurora.org>
Diffstat (limited to 'drivers/gpu/msm/kgsl.c')
-rw-r--r--drivers/gpu/msm/kgsl.c152
1 files changed, 150 insertions, 2 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 993f22b26294..bae3884aa277 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1439,6 +1439,17 @@ long kgsl_ioctl_device_waittimestamp_ctxtid(
return result;
}
+static inline bool _check_context_is_sparse(struct kgsl_context *context,
+ uint64_t flags)
+{
+ if ((context->flags & KGSL_CONTEXT_SPARSE) ||
+ (flags & KGSL_DRAWOBJ_SPARSE))
+ return true;
+
+ return false;
+}
+
+
long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
@@ -1463,6 +1474,11 @@ long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
if (context == NULL)
return -EINVAL;
+ if (_check_context_is_sparse(context, param->flags)) {
+ kgsl_context_put(context);
+ return -EINVAL;
+ }
+
cmdobj = kgsl_drawobj_cmd_create(device, context, param->flags,
CMDOBJ_TYPE);
if (IS_ERR(cmdobj)) {
@@ -1558,6 +1574,11 @@ long kgsl_ioctl_submit_commands(struct kgsl_device_private *dev_priv,
if (context == NULL)
return -EINVAL;
+ if (_check_context_is_sparse(context, param->flags)) {
+ kgsl_context_put(context);
+ return -EINVAL;
+ }
+
if (type & SYNCOBJ_TYPE) {
struct kgsl_drawobj_sync *syncobj =
kgsl_drawobj_sync_create(device, context);
@@ -1632,6 +1653,11 @@ long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv,
if (context == NULL)
return -EINVAL;
+ if (_check_context_is_sparse(context, param->flags)) {
+ kgsl_context_put(context);
+ return -EINVAL;
+ }
+
if (type & SYNCOBJ_TYPE) {
struct kgsl_drawobj_sync *syncobj =
kgsl_drawobj_sync_create(device, context);
@@ -3742,6 +3768,128 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
return ret;
}
+long kgsl_ioctl_gpu_sparse_command(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_gpu_sparse_command *param = data;
+ struct kgsl_device *device = dev_priv->device;
+ struct kgsl_context *context;
+ struct kgsl_drawobj *drawobj[2];
+ struct kgsl_drawobj_sparse *sparseobj;
+ long result;
+ unsigned int i = 0;
+
+ /* Make sure sparse and syncpoint count isn't too big */
+ if (param->numsparse > KGSL_MAX_SPARSE ||
+ param->numsyncs > KGSL_MAX_SYNCPOINTS)
+ return -EINVAL;
+
+ /* Make sure there is atleast one sparse or sync */
+ if (param->numsparse == 0 && param->numsyncs == 0)
+ return -EINVAL;
+
+ /* Only Sparse commands are supported in this ioctl */
+ if (!(param->flags & KGSL_DRAWOBJ_SPARSE) || (param->flags &
+ (KGSL_DRAWOBJ_SUBMIT_IB_LIST | KGSL_DRAWOBJ_MARKER
+ | KGSL_DRAWOBJ_SYNC)))
+ return -EINVAL;
+
+ context = kgsl_context_get_owner(dev_priv, param->context_id);
+ if (context == NULL)
+ return -EINVAL;
+
+ /* Restrict bind commands to bind context */
+ if (!(context->flags & KGSL_CONTEXT_SPARSE)) {
+ kgsl_context_put(context);
+ return -EINVAL;
+ }
+
+ if (param->numsyncs) {
+ struct kgsl_drawobj_sync *syncobj = kgsl_drawobj_sync_create(
+ device, context);
+ if (IS_ERR(syncobj)) {
+ result = PTR_ERR(syncobj);
+ goto done;
+ }
+
+ drawobj[i++] = DRAWOBJ(syncobj);
+ result = kgsl_drawobj_sync_add_synclist(device, syncobj,
+ to_user_ptr(param->synclist),
+ param->syncsize, param->numsyncs);
+ if (result)
+ goto done;
+ }
+
+ if (param->numsparse) {
+ sparseobj = kgsl_drawobj_sparse_create(device, context,
+ param->flags);
+ if (IS_ERR(sparseobj)) {
+ result = PTR_ERR(sparseobj);
+ goto done;
+ }
+
+ sparseobj->id = param->id;
+ drawobj[i++] = DRAWOBJ(sparseobj);
+ result = kgsl_drawobj_sparse_add_sparselist(device, sparseobj,
+ param->id, to_user_ptr(param->sparselist),
+ param->sparsesize, param->numsparse);
+ if (result)
+ goto done;
+ }
+
+ result = dev_priv->device->ftbl->queue_cmds(dev_priv, context,
+ drawobj, i, &param->timestamp);
+
+done:
+ /*
+ * -EPROTO is a "success" error - it just tells the user that the
+ * context had previously faulted
+ */
+ if (result && result != -EPROTO)
+ while (i--)
+ kgsl_drawobj_destroy(drawobj[i]);
+
+ kgsl_context_put(context);
+ return result;
+}
+
+void kgsl_sparse_bind(struct kgsl_process_private *private,
+ struct kgsl_drawobj_sparse *sparseobj)
+{
+ struct kgsl_sparseobj_node *sparse_node;
+ struct kgsl_mem_entry *virt_entry = NULL;
+ long ret = 0;
+ char *name;
+
+ virt_entry = kgsl_sharedmem_find_id_flags(private, sparseobj->id,
+ KGSL_MEMFLAGS_SPARSE_VIRT);
+ if (virt_entry == NULL)
+ return;
+
+ list_for_each_entry(sparse_node, &sparseobj->sparselist, node) {
+ if (sparse_node->obj.flags & KGSL_SPARSE_BIND) {
+ ret = sparse_bind_range(private, &sparse_node->obj,
+ virt_entry);
+ name = "bind";
+ } else {
+ ret = sparse_unbind_range(&sparse_node->obj,
+ virt_entry);
+ name = "unbind";
+ }
+
+ if (ret)
+ KGSL_CORE_ERR("kgsl: Unable to '%s' ret %ld virt_id %d, phys_id %d, virt_offset %16.16llX, phys_offset %16.16llX, size %16.16llX, flags %16.16llX\n",
+ name, ret, sparse_node->virt_id,
+ sparse_node->obj.id,
+ sparse_node->obj.virtoffset,
+ sparse_node->obj.physoffset,
+ sparse_node->obj.size, sparse_node->obj.flags);
+ }
+
+ kgsl_mem_entry_put(virt_entry);
+}
+EXPORT_SYMBOL(kgsl_sparse_bind);
+
long kgsl_ioctl_gpuobj_info(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
@@ -4656,7 +4804,7 @@ static void kgsl_core_exit(void)
kgsl_driver.class = NULL;
}
- kgsl_drawobj_exit();
+ kgsl_drawobjs_cache_exit();
kgsl_memfree_exit();
unregister_chrdev_region(kgsl_driver.major, KGSL_DEVICE_MAX);
@@ -4732,7 +4880,7 @@ static int __init kgsl_core_init(void)
kgsl_events_init();
- result = kgsl_drawobj_init();
+ result = kgsl_drawobjs_cache_init();
if (result)
goto err;