Loading drivers/gpu/msm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ msm_kgsl-y = \ kgsl_pwrscale.o \ kgsl_sharedmem.o \ kgsl_snapshot.o \ kgsl_timeline.o \ kgsl_trace.o \ kgsl_util.o Loading drivers/gpu/msm/adreno_debugfs.c +12 −2 Original line number Diff line number Diff line Loading @@ -139,10 +139,20 @@ static void sync_event_print(struct seq_file *s, } case KGSL_CMD_SYNCPOINT_TYPE_FENCE: { int i; struct event_fence_info *info = sync_event->priv; for (i = 0; i < sync_event->info.num_fences; i++) for (i = 0; info && i < info->num_fences; i++) seq_printf(s, "sync: %s", sync_event->info.fences[i].name); info->fences[i].name); break; } case KGSL_CMD_SYNCPOINT_TYPE_TIMELINE: { int j; struct event_timeline_info *info = sync_event->priv; for (j = 0; info && info[j].timeline; j++) seq_printf(s, "timeline: %d seqno: %d", info[j].timeline, info[j].seqno); break; } default: Loading drivers/gpu/msm/adreno_dispatch.c +87 −40 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include "adreno.h" #include "adreno_trace.h" #include "kgsl_gmu_core.h" #include "kgsl_timeline.h" #define DRAWQUEUE_NEXT(_i, _s) (((_i) + 1) % (_s)) Loading Loading @@ -286,6 +287,8 @@ static void _retire_timestamp(struct kgsl_drawobj *drawobj) KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), drawobj->timestamp); drawctxt->submitted_timestamp = drawobj->timestamp; /* Retire pending GPU events for the object */ kgsl_process_event_group(device, &context->events); Loading Loading @@ -357,12 +360,14 @@ static inline void _pop_drawobj(struct adreno_context *drawctxt) drawctxt->queued--; } static int _retire_markerobj(struct kgsl_drawobj_cmd *cmdobj, static int dispatch_retire_markerobj(struct kgsl_drawobj *drawobj, struct adreno_context *drawctxt) { struct kgsl_drawobj_cmd *cmdobj = CMDOBJ(drawobj); if (_marker_expired(cmdobj)) { _pop_drawobj(drawctxt); _retire_timestamp(DRAWOBJ(cmdobj)); _retire_timestamp(drawobj); return 0; } Loading @@ -378,12 +383,14 @@ static int _retire_markerobj(struct kgsl_drawobj_cmd *cmdobj, return test_bit(CMDOBJ_SKIP, &cmdobj->priv) ? 1 : -EAGAIN; } static int _retire_syncobj(struct kgsl_drawobj_sync *syncobj, static int dispatch_retire_syncobj(struct kgsl_drawobj *drawobj, struct adreno_context *drawctxt) { struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj); if (!kgsl_drawobj_events_pending(syncobj)) { _pop_drawobj(drawctxt); kgsl_drawobj_destroy(DRAWOBJ(syncobj)); kgsl_drawobj_destroy(drawobj); return 0; } Loading @@ -399,6 +406,22 @@ static int _retire_syncobj(struct kgsl_drawobj_sync *syncobj, return -EAGAIN; } static int drawqueue_retire_timelineobj(struct kgsl_drawobj *drawobj, struct adreno_context *drawctxt) { struct kgsl_drawobj_timeline *timelineobj = TIMELINEOBJ(drawobj); int i; for (i = 0; i < timelineobj->count; i++) kgsl_timeline_signal(timelineobj->timelines[i].timeline, timelineobj->timelines[i].seqno); _pop_drawobj(drawctxt); _retire_timestamp(drawobj); return 0; } /* * Retires all expired marker and sync objs from the context * queue and returns one of the below Loading @@ -412,35 +435,40 @@ static struct kgsl_drawobj *_process_drawqueue_get_next_drawobj( { 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)) { int ret = 0; drawobj = drawctxt->drawqueue[i]; if (drawobj == NULL) if (!drawobj) return NULL; if (drawobj->type == CMDOBJ_TYPE) switch (drawobj->type) { case CMDOBJ_TYPE: return drawobj; else if (drawobj->type == MARKEROBJ_TYPE) { ret = _retire_markerobj(CMDOBJ(drawobj), drawctxt); case MARKEROBJ_TYPE: ret = dispatch_retire_markerobj(drawobj, drawctxt); /* Special case where marker needs to be sent to GPU */ if (ret == 1) 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); break; case SYNCOBJ_TYPE: ret = dispatch_retire_syncobj(drawobj, drawctxt); break; case TIMELINEOBJ_TYPE: ret = drawqueue_retire_timelineobj(drawobj, drawctxt); break; default: ret = -EINVAL; break; } continue; if (ret) return ERR_PTR(ret); } return NULL; Loading Loading @@ -1184,11 +1212,27 @@ static void _queue_drawobj(struct adreno_context *drawctxt, trace_adreno_cmdbatch_queued(drawobj, drawctxt->queued); } static int _queue_markerobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj_cmd *markerobj, static int drawctxt_queue_auxobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj, u32 *timestamp, u32 user_ts) { int ret; ret = get_timestamp(drawctxt, drawobj, timestamp, user_ts); if (ret) return ret; drawctxt->queued_timestamp = *timestamp; _queue_drawobj(drawctxt, drawobj); return 0; } static int drawctxt_queue_markerobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj, uint32_t *timestamp, unsigned int user_ts) { struct kgsl_drawobj *drawobj = DRAWOBJ(markerobj); struct kgsl_drawobj_cmd *markerobj = CMDOBJ(drawobj); int ret; ret = get_timestamp(drawctxt, drawobj, timestamp, user_ts); Loading Loading @@ -1221,11 +1265,11 @@ static int _queue_markerobj(struct adreno_device *adreno_dev, return 0; } static int _queue_cmdobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj_cmd *cmdobj, static int drawctxt_queue_cmdobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj, uint32_t *timestamp, unsigned int user_ts) { struct kgsl_drawobj *drawobj = DRAWOBJ(cmdobj); struct kgsl_drawobj_cmd *cmdobj = CMDOBJ(drawobj); unsigned int j; int ret; Loading Loading @@ -1259,11 +1303,9 @@ static int _queue_cmdobj(struct adreno_device *adreno_dev, return 0; } static void _queue_syncobj(struct adreno_context *drawctxt, struct kgsl_drawobj_sync *syncobj, uint32_t *timestamp) static void drawctxt_queue_syncobj(struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj, uint32_t *timestamp) { struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj); *timestamp = 0; drawobj->timestamp = 0; Loading Loading @@ -1337,29 +1379,34 @@ int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv, switch (drawobj[i]->type) { case MARKEROBJ_TYPE: ret = _queue_markerobj(adreno_dev, drawctxt, CMDOBJ(drawobj[i]), timestamp, user_ts); if (ret == 1) { ret = drawctxt_queue_markerobj(adreno_dev, drawctxt, drawobj[i], timestamp, user_ts); if (ret) spin_unlock(&drawctxt->lock); if (ret == 1) goto done; } else if (ret) { spin_unlock(&drawctxt->lock); else if (ret) return ret; } break; case CMDOBJ_TYPE: ret = _queue_cmdobj(adreno_dev, drawctxt, CMDOBJ(drawobj[i]), timestamp, user_ts); ret = drawctxt_queue_cmdobj(adreno_dev, drawctxt, drawobj[i], timestamp, user_ts); if (ret) { spin_unlock(&drawctxt->lock); return ret; } break; case SYNCOBJ_TYPE: _queue_syncobj(drawctxt, SYNCOBJ(drawobj[i]), timestamp); drawctxt_queue_syncobj(drawctxt, drawobj[i], timestamp); break; case TIMELINEOBJ_TYPE: ret = drawctxt_queue_auxobj(adreno_dev, drawctxt, drawobj[i], timestamp, user_ts); if (ret) { spin_unlock(&drawctxt->lock); return ret; } break; default: spin_unlock(&drawctxt->lock); Loading drivers/gpu/msm/kgsl.c +138 −0 Original line number Diff line number Diff line Loading @@ -1858,6 +1858,141 @@ long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv, return result; } long kgsl_ioctl_gpu_aux_command(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_gpu_aux_command *param = data; struct kgsl_device *device = dev_priv->device; struct kgsl_context *context; struct kgsl_drawobj **drawobjs; struct kgsl_drawobj_sync *tsobj; void __user *cmdlist; u32 queued, count; int i, index = 0; long ret; /* Aux commands don't make sense without commands */ if (!param->numcmds) return -EINVAL; if (!(param->flags & (KGSL_GPU_AUX_COMMAND_TIMELINE))) return -EINVAL; /* Make sure we don't overflow count */ if (param->numcmds == UINT_MAX) return -EINVAL; context = kgsl_context_get_owner(dev_priv, param->context_id); if (!context) return -EINVAL; /* * We have one drawobj for the timestamp sync plus one for all of the * commands */ count = param->numcmds + 1; if (param->flags & KGSL_GPU_AUX_COMMAND_SYNC) count++; drawobjs = kvcalloc(count, sizeof(*drawobjs), GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); if (!drawobjs) { kgsl_context_put(context); return -ENOMEM; } trace_kgsl_aux_command(context->id, param->numcmds, param->flags, param->timestamp); if (param->flags & KGSL_GPU_AUX_COMMAND_SYNC) { struct kgsl_drawobj_sync *syncobj = kgsl_drawobj_sync_create(device, context); if (IS_ERR(syncobj)) { ret = PTR_ERR(syncobj); goto err; } drawobjs[index++] = DRAWOBJ(syncobj); ret = kgsl_drawobj_sync_add_synclist(device, syncobj, u64_to_user_ptr(param->synclist), param->syncsize, param->numsyncs); if (ret) goto err; } kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_QUEUED, &queued); /* * Make an implicit sync object for the last queued timestamp on this * context */ tsobj = kgsl_drawobj_create_timestamp_syncobj(device, context, queued); if (IS_ERR(tsobj)) { ret = PTR_ERR(tsobj); goto err; } drawobjs[index++] = DRAWOBJ(tsobj); cmdlist = u64_to_user_ptr(param->cmdlist); /* Create a draw object for each command */ for (i = 0; i < param->numcmds; i++) { struct kgsl_gpu_aux_command_generic generic; if (copy_struct_from_user(&generic, sizeof(generic), cmdlist, param->cmdsize)) { ret = -EFAULT; goto err; } if (generic.type == KGSL_GPU_AUX_COMMAND_TIMELINE) { struct kgsl_drawobj_timeline *timelineobj; timelineobj = kgsl_drawobj_timeline_create(device, context); if (IS_ERR(timelineobj)) { ret = PTR_ERR(timelineobj); goto err; } ret = kgsl_drawobj_add_timeline(dev_priv, timelineobj, cmdlist, param->cmdsize); if (ret) goto err; drawobjs[index++] = DRAWOBJ(timelineobj); } else { ret = -EINVAL; goto err; } cmdlist += param->cmdsize; } ret = device->ftbl->queue_cmds(dev_priv, context, drawobjs, index, ¶m->timestamp); err: kgsl_context_put(context); if (ret && ret != -EPROTO) { for (i = 0; i < count; i++) kgsl_drawobj_destroy(drawobjs[i]); } kvfree(drawobjs); return ret; } long kgsl_ioctl_cmdstream_readtimestamp_ctxtid(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) Loading Loading @@ -4147,6 +4282,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device) rwlock_init(&device->context_lock); spin_lock_init(&device->submit_lock); /* Use XA_FLAGS_ALLOC1 to disallow 0 as an option */ xa_init_flags(&device->timelines, XA_FLAGS_ALLOC1); kgsl_device_debugfs_init(device); dma_set_coherent_mask(&pdev->dev, KGSL_DMA_BIT_MASK); Loading drivers/gpu/msm/kgsl.h +14 −0 Original line number Diff line number Diff line Loading @@ -425,6 +425,20 @@ long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_gpu_aux_command(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_create(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_wait(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_query(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_fence_get(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_signal(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_destroy(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); void kgsl_mem_entry_destroy(struct kref *kref); Loading Loading
drivers/gpu/msm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ msm_kgsl-y = \ kgsl_pwrscale.o \ kgsl_sharedmem.o \ kgsl_snapshot.o \ kgsl_timeline.o \ kgsl_trace.o \ kgsl_util.o Loading
drivers/gpu/msm/adreno_debugfs.c +12 −2 Original line number Diff line number Diff line Loading @@ -139,10 +139,20 @@ static void sync_event_print(struct seq_file *s, } case KGSL_CMD_SYNCPOINT_TYPE_FENCE: { int i; struct event_fence_info *info = sync_event->priv; for (i = 0; i < sync_event->info.num_fences; i++) for (i = 0; info && i < info->num_fences; i++) seq_printf(s, "sync: %s", sync_event->info.fences[i].name); info->fences[i].name); break; } case KGSL_CMD_SYNCPOINT_TYPE_TIMELINE: { int j; struct event_timeline_info *info = sync_event->priv; for (j = 0; info && info[j].timeline; j++) seq_printf(s, "timeline: %d seqno: %d", info[j].timeline, info[j].seqno); break; } default: Loading
drivers/gpu/msm/adreno_dispatch.c +87 −40 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include "adreno.h" #include "adreno_trace.h" #include "kgsl_gmu_core.h" #include "kgsl_timeline.h" #define DRAWQUEUE_NEXT(_i, _s) (((_i) + 1) % (_s)) Loading Loading @@ -286,6 +287,8 @@ static void _retire_timestamp(struct kgsl_drawobj *drawobj) KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), drawobj->timestamp); drawctxt->submitted_timestamp = drawobj->timestamp; /* Retire pending GPU events for the object */ kgsl_process_event_group(device, &context->events); Loading Loading @@ -357,12 +360,14 @@ static inline void _pop_drawobj(struct adreno_context *drawctxt) drawctxt->queued--; } static int _retire_markerobj(struct kgsl_drawobj_cmd *cmdobj, static int dispatch_retire_markerobj(struct kgsl_drawobj *drawobj, struct adreno_context *drawctxt) { struct kgsl_drawobj_cmd *cmdobj = CMDOBJ(drawobj); if (_marker_expired(cmdobj)) { _pop_drawobj(drawctxt); _retire_timestamp(DRAWOBJ(cmdobj)); _retire_timestamp(drawobj); return 0; } Loading @@ -378,12 +383,14 @@ static int _retire_markerobj(struct kgsl_drawobj_cmd *cmdobj, return test_bit(CMDOBJ_SKIP, &cmdobj->priv) ? 1 : -EAGAIN; } static int _retire_syncobj(struct kgsl_drawobj_sync *syncobj, static int dispatch_retire_syncobj(struct kgsl_drawobj *drawobj, struct adreno_context *drawctxt) { struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj); if (!kgsl_drawobj_events_pending(syncobj)) { _pop_drawobj(drawctxt); kgsl_drawobj_destroy(DRAWOBJ(syncobj)); kgsl_drawobj_destroy(drawobj); return 0; } Loading @@ -399,6 +406,22 @@ static int _retire_syncobj(struct kgsl_drawobj_sync *syncobj, return -EAGAIN; } static int drawqueue_retire_timelineobj(struct kgsl_drawobj *drawobj, struct adreno_context *drawctxt) { struct kgsl_drawobj_timeline *timelineobj = TIMELINEOBJ(drawobj); int i; for (i = 0; i < timelineobj->count; i++) kgsl_timeline_signal(timelineobj->timelines[i].timeline, timelineobj->timelines[i].seqno); _pop_drawobj(drawctxt); _retire_timestamp(drawobj); return 0; } /* * Retires all expired marker and sync objs from the context * queue and returns one of the below Loading @@ -412,35 +435,40 @@ static struct kgsl_drawobj *_process_drawqueue_get_next_drawobj( { 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)) { int ret = 0; drawobj = drawctxt->drawqueue[i]; if (drawobj == NULL) if (!drawobj) return NULL; if (drawobj->type == CMDOBJ_TYPE) switch (drawobj->type) { case CMDOBJ_TYPE: return drawobj; else if (drawobj->type == MARKEROBJ_TYPE) { ret = _retire_markerobj(CMDOBJ(drawobj), drawctxt); case MARKEROBJ_TYPE: ret = dispatch_retire_markerobj(drawobj, drawctxt); /* Special case where marker needs to be sent to GPU */ if (ret == 1) 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); break; case SYNCOBJ_TYPE: ret = dispatch_retire_syncobj(drawobj, drawctxt); break; case TIMELINEOBJ_TYPE: ret = drawqueue_retire_timelineobj(drawobj, drawctxt); break; default: ret = -EINVAL; break; } continue; if (ret) return ERR_PTR(ret); } return NULL; Loading Loading @@ -1184,11 +1212,27 @@ static void _queue_drawobj(struct adreno_context *drawctxt, trace_adreno_cmdbatch_queued(drawobj, drawctxt->queued); } static int _queue_markerobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj_cmd *markerobj, static int drawctxt_queue_auxobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj, u32 *timestamp, u32 user_ts) { int ret; ret = get_timestamp(drawctxt, drawobj, timestamp, user_ts); if (ret) return ret; drawctxt->queued_timestamp = *timestamp; _queue_drawobj(drawctxt, drawobj); return 0; } static int drawctxt_queue_markerobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj, uint32_t *timestamp, unsigned int user_ts) { struct kgsl_drawobj *drawobj = DRAWOBJ(markerobj); struct kgsl_drawobj_cmd *markerobj = CMDOBJ(drawobj); int ret; ret = get_timestamp(drawctxt, drawobj, timestamp, user_ts); Loading Loading @@ -1221,11 +1265,11 @@ static int _queue_markerobj(struct adreno_device *adreno_dev, return 0; } static int _queue_cmdobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj_cmd *cmdobj, static int drawctxt_queue_cmdobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj, uint32_t *timestamp, unsigned int user_ts) { struct kgsl_drawobj *drawobj = DRAWOBJ(cmdobj); struct kgsl_drawobj_cmd *cmdobj = CMDOBJ(drawobj); unsigned int j; int ret; Loading Loading @@ -1259,11 +1303,9 @@ static int _queue_cmdobj(struct adreno_device *adreno_dev, return 0; } static void _queue_syncobj(struct adreno_context *drawctxt, struct kgsl_drawobj_sync *syncobj, uint32_t *timestamp) static void drawctxt_queue_syncobj(struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj, uint32_t *timestamp) { struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj); *timestamp = 0; drawobj->timestamp = 0; Loading Loading @@ -1337,29 +1379,34 @@ int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv, switch (drawobj[i]->type) { case MARKEROBJ_TYPE: ret = _queue_markerobj(adreno_dev, drawctxt, CMDOBJ(drawobj[i]), timestamp, user_ts); if (ret == 1) { ret = drawctxt_queue_markerobj(adreno_dev, drawctxt, drawobj[i], timestamp, user_ts); if (ret) spin_unlock(&drawctxt->lock); if (ret == 1) goto done; } else if (ret) { spin_unlock(&drawctxt->lock); else if (ret) return ret; } break; case CMDOBJ_TYPE: ret = _queue_cmdobj(adreno_dev, drawctxt, CMDOBJ(drawobj[i]), timestamp, user_ts); ret = drawctxt_queue_cmdobj(adreno_dev, drawctxt, drawobj[i], timestamp, user_ts); if (ret) { spin_unlock(&drawctxt->lock); return ret; } break; case SYNCOBJ_TYPE: _queue_syncobj(drawctxt, SYNCOBJ(drawobj[i]), timestamp); drawctxt_queue_syncobj(drawctxt, drawobj[i], timestamp); break; case TIMELINEOBJ_TYPE: ret = drawctxt_queue_auxobj(adreno_dev, drawctxt, drawobj[i], timestamp, user_ts); if (ret) { spin_unlock(&drawctxt->lock); return ret; } break; default: spin_unlock(&drawctxt->lock); Loading
drivers/gpu/msm/kgsl.c +138 −0 Original line number Diff line number Diff line Loading @@ -1858,6 +1858,141 @@ long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv, return result; } long kgsl_ioctl_gpu_aux_command(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_gpu_aux_command *param = data; struct kgsl_device *device = dev_priv->device; struct kgsl_context *context; struct kgsl_drawobj **drawobjs; struct kgsl_drawobj_sync *tsobj; void __user *cmdlist; u32 queued, count; int i, index = 0; long ret; /* Aux commands don't make sense without commands */ if (!param->numcmds) return -EINVAL; if (!(param->flags & (KGSL_GPU_AUX_COMMAND_TIMELINE))) return -EINVAL; /* Make sure we don't overflow count */ if (param->numcmds == UINT_MAX) return -EINVAL; context = kgsl_context_get_owner(dev_priv, param->context_id); if (!context) return -EINVAL; /* * We have one drawobj for the timestamp sync plus one for all of the * commands */ count = param->numcmds + 1; if (param->flags & KGSL_GPU_AUX_COMMAND_SYNC) count++; drawobjs = kvcalloc(count, sizeof(*drawobjs), GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); if (!drawobjs) { kgsl_context_put(context); return -ENOMEM; } trace_kgsl_aux_command(context->id, param->numcmds, param->flags, param->timestamp); if (param->flags & KGSL_GPU_AUX_COMMAND_SYNC) { struct kgsl_drawobj_sync *syncobj = kgsl_drawobj_sync_create(device, context); if (IS_ERR(syncobj)) { ret = PTR_ERR(syncobj); goto err; } drawobjs[index++] = DRAWOBJ(syncobj); ret = kgsl_drawobj_sync_add_synclist(device, syncobj, u64_to_user_ptr(param->synclist), param->syncsize, param->numsyncs); if (ret) goto err; } kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_QUEUED, &queued); /* * Make an implicit sync object for the last queued timestamp on this * context */ tsobj = kgsl_drawobj_create_timestamp_syncobj(device, context, queued); if (IS_ERR(tsobj)) { ret = PTR_ERR(tsobj); goto err; } drawobjs[index++] = DRAWOBJ(tsobj); cmdlist = u64_to_user_ptr(param->cmdlist); /* Create a draw object for each command */ for (i = 0; i < param->numcmds; i++) { struct kgsl_gpu_aux_command_generic generic; if (copy_struct_from_user(&generic, sizeof(generic), cmdlist, param->cmdsize)) { ret = -EFAULT; goto err; } if (generic.type == KGSL_GPU_AUX_COMMAND_TIMELINE) { struct kgsl_drawobj_timeline *timelineobj; timelineobj = kgsl_drawobj_timeline_create(device, context); if (IS_ERR(timelineobj)) { ret = PTR_ERR(timelineobj); goto err; } ret = kgsl_drawobj_add_timeline(dev_priv, timelineobj, cmdlist, param->cmdsize); if (ret) goto err; drawobjs[index++] = DRAWOBJ(timelineobj); } else { ret = -EINVAL; goto err; } cmdlist += param->cmdsize; } ret = device->ftbl->queue_cmds(dev_priv, context, drawobjs, index, ¶m->timestamp); err: kgsl_context_put(context); if (ret && ret != -EPROTO) { for (i = 0; i < count; i++) kgsl_drawobj_destroy(drawobjs[i]); } kvfree(drawobjs); return ret; } long kgsl_ioctl_cmdstream_readtimestamp_ctxtid(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) Loading Loading @@ -4147,6 +4282,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device) rwlock_init(&device->context_lock); spin_lock_init(&device->submit_lock); /* Use XA_FLAGS_ALLOC1 to disallow 0 as an option */ xa_init_flags(&device->timelines, XA_FLAGS_ALLOC1); kgsl_device_debugfs_init(device); dma_set_coherent_mask(&pdev->dev, KGSL_DMA_BIT_MASK); Loading
drivers/gpu/msm/kgsl.h +14 −0 Original line number Diff line number Diff line Loading @@ -425,6 +425,20 @@ long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_gpu_aux_command(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_create(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_wait(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_query(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_fence_get(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_signal(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); long kgsl_ioctl_timeline_destroy(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); void kgsl_mem_entry_destroy(struct kref *kref); Loading