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

Commit db107eec authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Immediately signal a timeline if the timestamp has retired



When creating a new fence immediately signal the timeline if the target
timestamp has already expired and don't create a new GPU event.  This
cuts down on the number of events being fired for already expired
timestamps and removes the brief delay for the event to go out and
immediately come back.

Change-Id: Ic0dedbadc0512977f662bda5fdb4c4d3db7bd51f
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 9b4d473e
Loading
Loading
Loading
Loading
+50 −19
Original line number Diff line number Diff line
@@ -100,6 +100,37 @@ static void kgsl_fence_event_cb(struct kgsl_device *device,
	kfree(ev);
}

static int _add_fence_event(struct kgsl_device *device,
	struct kgsl_context *context, unsigned int timestamp)
{
	struct kgsl_fence_event_priv *event;
	int ret;

	event = kmalloc(sizeof(*event), GFP_KERNEL);
	if (event == NULL)
		return -ENOMEM;

	/*
	 * Increase the refcount for the context to keep it through the
	 * callback
	 */

	_kgsl_context_get(context);

	event->context = context;
	event->timestamp = timestamp;

	ret = kgsl_add_event(device, &context->events, timestamp,
		kgsl_fence_event_cb, event);

	if (ret) {
		kgsl_context_put(context);
		kfree(event);
	}

	return ret;
}

/**
 * kgsl_add_fence_event - Create a new fence event
 * @device - KGSL device to create the event on
@@ -117,23 +148,19 @@ int kgsl_add_fence_event(struct kgsl_device *device,
	u32 context_id, u32 timestamp, void __user *data, int len,
	struct kgsl_device_private *owner)
{
	struct kgsl_fence_event_priv *event;
	struct kgsl_timestamp_event_fence priv;
	struct kgsl_context *context;
	struct sync_pt *pt;
	struct sync_fence *fence = NULL;
	int ret = -EINVAL;
	char fence_name[sizeof(fence->name)] = {};
	unsigned int cur;

	priv.fence_fd = -1;

	if (len != sizeof(priv))
		return -EINVAL;

	event = kzalloc(sizeof(*event), GFP_KERNEL);
	if (event == NULL)
		return -ENOMEM;

	mutex_lock(&device->mutex);

	context = kgsl_context_get_owner(owner, context_id);
@@ -141,9 +168,6 @@ int kgsl_add_fence_event(struct kgsl_device *device,
	if (context == NULL)
		goto unlock;

	event->context = context;
	event->timestamp = timestamp;

	pt = kgsl_sync_pt_create(context->timeline, timestamp);
	if (pt == NULL) {
		KGSL_DRV_ERR(device, "kgsl_sync_pt_create failed\n");
@@ -174,6 +198,24 @@ int kgsl_add_fence_event(struct kgsl_device *device,
	}
	sync_fence_install(fence, priv.fence_fd);

	/*
	 * If the timestamp hasn't expired yet create an event to trigger it.
	 * Otherwise, just signal the fence - there is no reason to go through
	 * the effort of creating a fence we don't need.
	 */

	kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED, &cur);

	if (timestamp_cmp(cur, timestamp) >= 0)
		kgsl_sync_timeline_signal(context->timeline, cur);
	else {
		ret = _add_fence_event(device, context, timestamp);
		if (ret)
			goto unlock;
	}

	kgsl_context_put(context);

	/* Unlock the mutex before copying to user */
	mutex_unlock(&device->mutex);

@@ -182,16 +224,6 @@ int kgsl_add_fence_event(struct kgsl_device *device,
		goto out;
	}

	/*
	 * Hold the context ref-count for the event - it will get released in
	 * the callback
	 */
	ret = kgsl_add_event(device, &context->events, timestamp,
		kgsl_fence_event_cb, event);

	if (ret)
		goto out;

	return 0;

unlock:
@@ -205,7 +237,6 @@ out:
		sync_fence_put(fence);

	kgsl_context_put(context);
	kfree(event);
	return ret;
}