Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5949b262 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Add timeline traces"

parents 04dae11d 70461f8b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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

+12 −2
Original line number Diff line number Diff line
@@ -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:
+87 −40
Original line number Diff line number Diff line
@@ -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))

@@ -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);

@@ -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;
	}

@@ -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;
	}

@@ -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
@@ -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;
@@ -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);
@@ -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;

@@ -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;

@@ -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);
+138 −0
Original line number Diff line number Diff line
@@ -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, &param->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)
@@ -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);
+14 −0
Original line number Diff line number Diff line
@@ -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