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

Commit 0d6c8dbc authored by Jordan Crouse's avatar Jordan Crouse Committed by Tarun Karra
Browse files

msm: kgsl: Turn cmdbatch->synclist into an RCU list



cmdbatch->synclist is read often for debug purposes so we can easily
turn it into an RCU list and get rid of a lot of the locking. As a
bonus this fixes a warning that was occurring because the the sync
retire function was being called from the dma-fence subsystem with
interrupts turned off.

Change-Id: Ic0dedbad25e9539279e693b1587801935f30a66e
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent eb8ec7b9
Loading
Loading
Loading
Loading
+4 −10
Original line number Diff line number Diff line
@@ -148,15 +148,10 @@ static void cmdbatch_print(struct seq_file *s, struct kgsl_cmdbatch *cmdbatch)
{
	struct kgsl_cmdbatch_sync_event *sync_event;

	/*
	 * print fences first, since they block this cmdbatch.
	 * We may have cmdbatch timer running, which also uses
	 * same lock, take a lock with software interrupt disabled (bh)
	 * to avoid spin lock recursion.
	 */
	spin_lock_bh(&cmdbatch->lock);
	/* print fences first, since they block this cmdbatch */

	list_for_each_entry(sync_event, &cmdbatch->synclist, node) {
	rcu_read_lock();
	list_for_each_entry_rcu(sync_event, &cmdbatch->synclist, node) {
		/*
		 * Timestamp is 0 for KGSL_CONTEXT_SYNC, but print it anyways
		 * so that it is clear if the fence was a separate submit
@@ -166,8 +161,7 @@ static void cmdbatch_print(struct seq_file *s, struct kgsl_cmdbatch *cmdbatch)
		sync_event_print(s, sync_event);
		seq_puts(s, "\n");
	}

	spin_unlock_bh(&cmdbatch->lock);
	rcu_read_unlock();

	/* if this flag is set, there won't be an IB */
	if (cmdbatch->flags & KGSL_CONTEXT_SYNC)
+2 −7
Original line number Diff line number Diff line
@@ -363,15 +363,10 @@ static struct kgsl_cmdbatch *_get_cmdbatch(struct adreno_context *drawctxt)
			pending = true;
	}

	/*
	 * We may have cmdbatch timer running, which also uses same lock,
	 * take a lock with software interrupt disabled (bh) to avoid
	 * spin lock recursion.
	 */
	spin_lock_bh(&cmdbatch->lock);
	rcu_read_lock();
	if (!list_empty(&cmdbatch->synclist))
		pending = true;
	spin_unlock_bh(&cmdbatch->lock);
	rcu_read_unlock();

	/*
	 * If changes are pending and the canary timer hasn't been
+2 −8
Original line number Diff line number Diff line
@@ -77,13 +77,7 @@ void adreno_drawctxt_dump(struct kgsl_device *device,
			goto stats;
		}

		/*
		 * We may have cmdbatch timer running, which also uses same
		 * lock, take a lock with software interrupt disabled (bh)
		 * to avoid spin lock recursion.
		 */
		spin_lock_bh(&cmdbatch->lock);

		rcu_read_lock();
		if (!list_empty(&cmdbatch->synclist)) {
			dev_err(device->dev,
				"  context[%d] (ts=%d) Active sync points:\n",
@@ -91,7 +85,7 @@ void adreno_drawctxt_dump(struct kgsl_device *device,

			kgsl_dump_syncpoints(device, cmdbatch);
		}
		spin_unlock_bh(&cmdbatch->lock);
		rcu_read_unlock();
	}

stats:
+14 −22
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ void kgsl_dump_syncpoints(struct kgsl_device *device,
	struct kgsl_cmdbatch_sync_event *event;

	/* Print all the pending sync objects */
	list_for_each_entry(event, &cmdbatch->synclist, node) {
	list_for_each_entry_rcu(event, &cmdbatch->synclist, node) {

		switch (event->type) {
		case KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP: {
@@ -121,14 +121,14 @@ static void _kgsl_cmdbatch_timer(unsigned long data)
	kgsl_context_dump(cmdbatch->context);
	clear_bit(CMDBATCH_FLAG_FENCE_LOG, &cmdbatch->priv);

	spin_lock(&cmdbatch->lock);
	/* Print all the fences */
	list_for_each_entry(event, &cmdbatch->synclist, node) {
	rcu_read_lock();
	list_for_each_entry_rcu(event, &cmdbatch->synclist, node) {
		if (KGSL_CMD_SYNCPOINT_TYPE_FENCE == event->type &&
			event->handle && event->handle->fence)
			kgsl_sync_fence_log(event->handle->fence);
	}
	spin_unlock(&cmdbatch->lock);
	rcu_read_unlock();
	dev_err(device->dev, "--gpu syncpoint deadlock print end--\n");
}

@@ -187,12 +187,7 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device,
	int sched = 0;
	int removed = 0;

	/*
	 * We may have cmdbatch timer running, which also uses same lock,
	 * take a lock with software interrupt disabled (bh) to avoid
	 * spin lock recursion.
	 */
	spin_lock_bh(&event->cmdbatch->lock);
	spin_lock(&event->cmdbatch->lock);

	/*
	 * sync events that are contained by a cmdbatch which has been
@@ -201,14 +196,14 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device,

	list_for_each_entry_safe(e, tmp, &event->cmdbatch->synclist, node) {
		if (e == event) {
			list_del_init(&event->node);
			list_del_rcu(&event->node);
			removed = 1;
			break;
		}
	}

	sched = list_empty(&event->cmdbatch->synclist) ? 1 : 0;
	spin_unlock_bh(&event->cmdbatch->lock);
	spin_unlock(&event->cmdbatch->lock);

	/* If the list is empty delete the canary timer */
	if (sched)
@@ -276,12 +271,9 @@ void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch)
	/* Zap the canary timer */
	del_timer_sync(&cmdbatch->timer);

	/* non-bh because we just destroyed timer */
	spin_lock(&cmdbatch->lock);

	/* Empty the synclist before canceling events */
	list_splice_init(&cmdbatch->synclist, &cancel_synclist);
	spin_unlock(&cmdbatch->lock);
	list_splice_init_rcu(&cmdbatch->synclist, &cancel_synclist,
		synchronize_rcu);

	/*
	 * Finish canceling events outside the cmdbatch spinlock and
@@ -394,7 +386,7 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device,

	/* non-bh because, we haven't started cmdbatch timer yet */
	spin_lock(&cmdbatch->lock);
	list_add(&event->node, &cmdbatch->synclist);
	list_add_rcu(&event->node, &cmdbatch->synclist);
	spin_unlock(&cmdbatch->lock);

	/*
@@ -417,7 +409,7 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device,

		/* Remove event from the synclist */
		spin_lock(&cmdbatch->lock);
		list_del(&event->node);
		list_del_rcu(&event->node);
		spin_unlock(&cmdbatch->lock);
		kgsl_cmdbatch_sync_event_put(event);

@@ -511,7 +503,7 @@ static int kgsl_cmdbatch_add_sync_timestamp(struct kgsl_device *device,

	/* non-bh because, we haven't started cmdbatch timer yet */
	spin_lock(&cmdbatch->lock);
	list_add(&event->node, &cmdbatch->synclist);
	list_add_rcu(&event->node, &cmdbatch->synclist);
	spin_unlock(&cmdbatch->lock);

	ret = kgsl_add_event(device, &context->events, sync->timestamp,
@@ -519,7 +511,7 @@ static int kgsl_cmdbatch_add_sync_timestamp(struct kgsl_device *device,

	if (ret) {
		spin_lock(&cmdbatch->lock);
		list_del(&event->node);
		list_del_rcu(&event->node);
		spin_unlock(&cmdbatch->lock);

		kgsl_cmdbatch_put(cmdbatch);
@@ -720,7 +712,7 @@ struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device,

	kref_init(&cmdbatch->refcount);
	INIT_LIST_HEAD(&cmdbatch->cmdlist);
	INIT_LIST_HEAD(&cmdbatch->synclist);
	INIT_LIST_HEAD_RCU(&cmdbatch->synclist);
	INIT_LIST_HEAD(&cmdbatch->memlist);
	spin_lock_init(&cmdbatch->lock);