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

Commit 4855bd18 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

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

parents a2b01374 db107eec
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;
}