Loading drivers/gpu/msm/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,8 @@ msm_kgsl_core-y = \ kgsl_rgmu.o \ kgsl_hfi.o \ kgsl_pool.o \ kgsl_reclaim.o kgsl_reclaim.o \ kgsl_timeline.o msm_kgsl_core-$(CONFIG_QCOM_KGSL_IOMMU) += kgsl_iommu.o msm_kgsl_core-$(CONFIG_DEBUG_FS) += kgsl_debugfs.o Loading drivers/gpu/msm/adreno_debugfs.c +14 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2008-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2002,2008-2021, The Linux Foundation. All rights reserved. */ #include <linux/debugfs.h> Loading Loading @@ -147,11 +147,22 @@ static void sync_event_print(struct seq_file *s, break; } case KGSL_CMD_SYNCPOINT_TYPE_FENCE: { struct event_fence_info *info = sync_event ? sync_event->priv : NULL; int i; 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: { struct event_timeline_info *info = sync_event->priv; int j; 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 −42 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. */ #include <linux/slab.h> 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 @@ -276,6 +277,7 @@ 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 @@ -342,12 +344,14 @@ static void _retire_sparseobj(struct kgsl_drawobj_sparse *sparseobj, _retire_timestamp(DRAWOBJ(sparseobj)); } 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 @@ -363,12 +367,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 @@ -384,6 +390,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 @@ -397,35 +419,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 @@ -696,7 +723,7 @@ static struct kgsl_drawobj_sparse *_get_next_sparseobj( return NULL; if (drawobj->type == SYNCOBJ_TYPE) ret = _retire_syncobj(SYNCOBJ(drawobj), drawctxt); ret = dispatch_retire_syncobj(drawobj, drawctxt); else if (drawobj->type == SPARSEOBJ_TYPE) return SPARSEOBJ(drawobj); else Loading Loading @@ -1247,12 +1274,27 @@ static int _queue_sparseobj(struct adreno_device *adreno_dev, return 0; } 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 _queue_markerobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj_cmd *markerobj, 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 @@ -1285,11 +1327,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 @@ -1323,11 +1365,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 @@ -1401,29 +1441,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; case SPARSEOBJ_TYPE: ret = _queue_sparseobj(adreno_dev, drawctxt, Loading drivers/gpu/msm/kgsl.c +127 −0 Original line number Diff line number Diff line Loading @@ -2107,6 +2107,129 @@ 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; struct kgsl_gpu_aux_command_generic generic; /* We support only one aux command */ if (param->numcmds != 1) return -EINVAL; if (!(param->flags & KGSL_GPU_AUX_COMMAND_TIMELINE)) return -EINVAL; context = kgsl_context_get_owner(dev_priv, param->context_id); if (!context) return -EINVAL; /* * param->numcmds is always one and we have one additional drawobj * for the timestamp sync if KGSL_GPU_AUX_COMMAND_SYNC flag is passed. * On top of that we make an implicit sync object for the last queued * timestamp on this context. */ count = (param->flags & KGSL_GPU_AUX_COMMAND_SYNC) ? 3 : 2; drawobjs = kvcalloc(count, sizeof(*drawobjs), GFP_KERNEL); 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 KGSL_GPU_AUX_COMMAND_TIMELINE */ if (kgsl_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; } drawobjs[index++] = DRAWOBJ(timelineobj); ret = kgsl_drawobj_add_timeline(dev_priv, timelineobj, u64_to_user_ptr(generic.priv), generic.size); if (ret) goto err; } else { ret = -EINVAL; goto err; } 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 @@ -5222,6 +5345,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device) if (status) goto error_close_mmu; idr_init(&device->timelines); spin_lock_init(&device->timelines_lock); /* * The default request type PM_QOS_REQ_ALL_CORES is * applicable to all CPU cores that are online and Loading Loading @@ -5296,6 +5422,7 @@ void kgsl_device_platform_remove(struct kgsl_device *device) pm_qos_remove_request(&device->pwrctrl.l2pc_cpus_qos); idr_destroy(&device->context_idr); idr_destroy(&device->timelines); kgsl_mmu_close(device); 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); long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); Loading Loading
drivers/gpu/msm/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,8 @@ msm_kgsl_core-y = \ kgsl_rgmu.o \ kgsl_hfi.o \ kgsl_pool.o \ kgsl_reclaim.o kgsl_reclaim.o \ kgsl_timeline.o msm_kgsl_core-$(CONFIG_QCOM_KGSL_IOMMU) += kgsl_iommu.o msm_kgsl_core-$(CONFIG_DEBUG_FS) += kgsl_debugfs.o Loading
drivers/gpu/msm/adreno_debugfs.c +14 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2008-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2002,2008-2021, The Linux Foundation. All rights reserved. */ #include <linux/debugfs.h> Loading Loading @@ -147,11 +147,22 @@ static void sync_event_print(struct seq_file *s, break; } case KGSL_CMD_SYNCPOINT_TYPE_FENCE: { struct event_fence_info *info = sync_event ? sync_event->priv : NULL; int i; 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: { struct event_timeline_info *info = sync_event->priv; int j; 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 −42 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. */ #include <linux/slab.h> 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 @@ -276,6 +277,7 @@ 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 @@ -342,12 +344,14 @@ static void _retire_sparseobj(struct kgsl_drawobj_sparse *sparseobj, _retire_timestamp(DRAWOBJ(sparseobj)); } 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 @@ -363,12 +367,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 @@ -384,6 +390,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 @@ -397,35 +419,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 @@ -696,7 +723,7 @@ static struct kgsl_drawobj_sparse *_get_next_sparseobj( return NULL; if (drawobj->type == SYNCOBJ_TYPE) ret = _retire_syncobj(SYNCOBJ(drawobj), drawctxt); ret = dispatch_retire_syncobj(drawobj, drawctxt); else if (drawobj->type == SPARSEOBJ_TYPE) return SPARSEOBJ(drawobj); else Loading Loading @@ -1247,12 +1274,27 @@ static int _queue_sparseobj(struct adreno_device *adreno_dev, return 0; } 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 _queue_markerobj(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj_cmd *markerobj, 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 @@ -1285,11 +1327,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 @@ -1323,11 +1365,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 @@ -1401,29 +1441,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; case SPARSEOBJ_TYPE: ret = _queue_sparseobj(adreno_dev, drawctxt, Loading
drivers/gpu/msm/kgsl.c +127 −0 Original line number Diff line number Diff line Loading @@ -2107,6 +2107,129 @@ 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; struct kgsl_gpu_aux_command_generic generic; /* We support only one aux command */ if (param->numcmds != 1) return -EINVAL; if (!(param->flags & KGSL_GPU_AUX_COMMAND_TIMELINE)) return -EINVAL; context = kgsl_context_get_owner(dev_priv, param->context_id); if (!context) return -EINVAL; /* * param->numcmds is always one and we have one additional drawobj * for the timestamp sync if KGSL_GPU_AUX_COMMAND_SYNC flag is passed. * On top of that we make an implicit sync object for the last queued * timestamp on this context. */ count = (param->flags & KGSL_GPU_AUX_COMMAND_SYNC) ? 3 : 2; drawobjs = kvcalloc(count, sizeof(*drawobjs), GFP_KERNEL); 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 KGSL_GPU_AUX_COMMAND_TIMELINE */ if (kgsl_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; } drawobjs[index++] = DRAWOBJ(timelineobj); ret = kgsl_drawobj_add_timeline(dev_priv, timelineobj, u64_to_user_ptr(generic.priv), generic.size); if (ret) goto err; } else { ret = -EINVAL; goto err; } 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 @@ -5222,6 +5345,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device) if (status) goto error_close_mmu; idr_init(&device->timelines); spin_lock_init(&device->timelines_lock); /* * The default request type PM_QOS_REQ_ALL_CORES is * applicable to all CPU cores that are online and Loading Loading @@ -5296,6 +5422,7 @@ void kgsl_device_platform_remove(struct kgsl_device *device) pm_qos_remove_request(&device->pwrctrl.l2pc_cpus_qos); idr_destroy(&device->context_idr); idr_destroy(&device->timelines); kgsl_mmu_close(device); 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); long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data); Loading