Loading drivers/gpu/msm/adreno_dispatch.c +125 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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 Loading @@ -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); Loading Loading @@ -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) Loading @@ -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; } Loading Loading @@ -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 Loading @@ -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; Loading Loading @@ -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; Loading drivers/gpu/msm/adreno_drawctxt.c +2 −1 Original line number Diff line number Diff line Loading @@ -351,7 +351,8 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, KGSL_CONTEXT_IFH_NOP | KGSL_CONTEXT_SECURE | KGSL_CONTEXT_PREEMPT_STYLE_MASK | KGSL_CONTEXT_NO_SNAPSHOT); KGSL_CONTEXT_NO_SNAPSHOT | KGSL_CONTEXT_SPARSE); /* Check for errors before trying to initialize */ Loading drivers/gpu/msm/kgsl.c +150 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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)) { Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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, ¶m->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) { Loading Loading @@ -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); Loading Loading @@ -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; Loading drivers/gpu/msm/kgsl.h +3 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ static inline void KGSL_STATS_ADD(uint64_t size, atomic_long_t *stat, #define KGSL_MAX_NUMIBS 100000 #define KGSL_MAX_SYNCPOINTS 32 #define KGSL_MAX_SPARSE 1000 struct kgsl_device; struct kgsl_context; Loading Loading @@ -432,6 +433,8 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_sparse_unbind(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_gpu_sparse_command(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); void kgsl_mem_entry_destroy(struct kref *kref); Loading drivers/gpu/msm/kgsl_compat.c +2 −0 Original line number Diff line number Diff line Loading @@ -382,6 +382,8 @@ static const struct kgsl_ioctl kgsl_compat_ioctl_funcs[] = { kgsl_ioctl_sparse_virt_free), KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_BIND, kgsl_ioctl_sparse_bind), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPU_SPARSE_COMMAND, kgsl_ioctl_gpu_sparse_command), }; long kgsl_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) Loading Loading
drivers/gpu/msm/adreno_dispatch.c +125 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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 Loading @@ -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); Loading Loading @@ -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) Loading @@ -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; } Loading Loading @@ -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 Loading @@ -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; Loading Loading @@ -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; Loading
drivers/gpu/msm/adreno_drawctxt.c +2 −1 Original line number Diff line number Diff line Loading @@ -351,7 +351,8 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, KGSL_CONTEXT_IFH_NOP | KGSL_CONTEXT_SECURE | KGSL_CONTEXT_PREEMPT_STYLE_MASK | KGSL_CONTEXT_NO_SNAPSHOT); KGSL_CONTEXT_NO_SNAPSHOT | KGSL_CONTEXT_SPARSE); /* Check for errors before trying to initialize */ Loading
drivers/gpu/msm/kgsl.c +150 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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)) { Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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, ¶m->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) { Loading Loading @@ -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); Loading Loading @@ -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; Loading
drivers/gpu/msm/kgsl.h +3 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ static inline void KGSL_STATS_ADD(uint64_t size, atomic_long_t *stat, #define KGSL_MAX_NUMIBS 100000 #define KGSL_MAX_SYNCPOINTS 32 #define KGSL_MAX_SPARSE 1000 struct kgsl_device; struct kgsl_context; Loading Loading @@ -432,6 +433,8 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_sparse_unbind(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_gpu_sparse_command(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); void kgsl_mem_entry_destroy(struct kref *kref); Loading
drivers/gpu/msm/kgsl_compat.c +2 −0 Original line number Diff line number Diff line Loading @@ -382,6 +382,8 @@ static const struct kgsl_ioctl kgsl_compat_ioctl_funcs[] = { kgsl_ioctl_sparse_virt_free), KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_BIND, kgsl_ioctl_sparse_bind), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPU_SPARSE_COMMAND, kgsl_ioctl_gpu_sparse_command), }; long kgsl_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) Loading