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

Commit 370aca60 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: Use spin_lock_bh to avoid spinlock recursion"

parents 6245a7e5 d1f4e3f3
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -112,10 +112,14 @@ static void print_flags(struct seq_file *s, const struct flag_entry *table,
static void cmdbatch_print(struct seq_file *s, struct kgsl_cmdbatch *cmdbatch)
{
	struct kgsl_cmdbatch_sync_event *sync_event;
	unsigned long flags;

	/* print fences first, since they block this cmdbatch */
	spin_lock_irqsave(&cmdbatch->lock, flags);
	/*
	 * 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);

	list_for_each_entry(sync_event, &cmdbatch->synclist, node) {
		/*
@@ -128,7 +132,7 @@ static void cmdbatch_print(struct seq_file *s, struct kgsl_cmdbatch *cmdbatch)
		seq_puts(s, "\n");
	}

	spin_unlock_irqrestore(&cmdbatch->lock, flags);
	spin_unlock_bh(&cmdbatch->lock);

	/* if this flag is set, there won't be an IB */
	if (cmdbatch->flags & KGSL_CONTEXT_SYNC)
+7 −3
Original line number Diff line number Diff line
@@ -293,7 +293,6 @@ static struct kgsl_cmdbatch *_get_cmdbatch(struct adreno_context *drawctxt)
{
	struct kgsl_cmdbatch *cmdbatch = NULL;
	bool pending = false;
	unsigned long flags;

	if (drawctxt->cmdqueue_head == drawctxt->cmdqueue_tail)
		return NULL;
@@ -323,10 +322,15 @@ static struct kgsl_cmdbatch *_get_cmdbatch(struct adreno_context *drawctxt)
			pending = true;
	}

	spin_lock_irqsave(&cmdbatch->lock, flags);
	/*
	 * 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);
	if (!list_empty(&cmdbatch->synclist))
		pending = true;
	spin_unlock_irqrestore(&cmdbatch->lock, flags);
	spin_unlock_bh(&cmdbatch->lock);

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

		spin_lock(&cmdbatch->lock);
		/*
		 * 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);

		if (!list_empty(&cmdbatch->synclist)) {
			dev_err(device->dev,
@@ -93,7 +98,7 @@ void adreno_drawctxt_dump(struct kgsl_device *device,

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

stats:
+16 −8
Original line number Diff line number Diff line
@@ -1595,6 +1595,7 @@ static void _kgsl_cmdbatch_timer(unsigned long data)
	if (cmdbatch == NULL || cmdbatch->context == NULL)
		return;

	/* We are in timer context, this can be non-bh */
	spin_lock(&cmdbatch->lock);
	if (list_empty(&cmdbatch->synclist))
		goto done;
@@ -1692,9 +1693,13 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device,
	struct kgsl_cmdbatch_sync_event *e, *tmp;
	int sched = 0;
	int removed = 0;
	unsigned long flags;

	spin_lock_irqsave(&event->cmdbatch->lock, flags);
	/*
	 * 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);

	/*
	 * sync events that are contained by a cmdbatch which has been
@@ -1710,7 +1715,7 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device,
	}

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

	/* If the list is empty delete the canary timer */
	if (sched)
@@ -1776,6 +1781,7 @@ 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 */
@@ -1864,7 +1870,6 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device,
{
	struct kgsl_cmd_syncpoint_fence *sync = priv;
	struct kgsl_cmdbatch_sync_event *event;
	unsigned long flags;

	event = kzalloc(sizeof(*event), GFP_KERNEL);

@@ -1892,9 +1897,11 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device,
	 */

	kref_get(&event->refcount);
	spin_lock_irqsave(&cmdbatch->lock, flags);

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

	/*
	 * Increment the reference count for the async callback.
@@ -1915,9 +1922,9 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device,
		kgsl_cmdbatch_sync_event_put(event);

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

		/* Event no longer needed by this function */
@@ -2008,6 +2015,7 @@ static int kgsl_cmdbatch_add_sync_timestamp(struct kgsl_device *device,
	kref_init(&event->refcount);
	kref_get(&event->refcount);

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