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

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

msm: kgsl: Detach all command batches from context while holding lock



The two paths to take down a context both detach command batches from
a context but they do it differently.  Most importantly the
invalidate path takes the lock and drains the entire list while
detach takes and releases the lock as it walks the tree. The latter
is far more dangerous.

Make a helper function and call it from both paths - this should cut
down on issues when both functions are called concurrently.

Change-Id: Ic0dedbad184809118bdbf91c4f52b498ebb8efff
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 50e0173f
Loading
Loading
Loading
Loading
+32 −37
Original line number Diff line number Diff line
@@ -217,6 +217,24 @@ done:
	return ret;
}

static int drawctxt_detach_cmdbatches(struct adreno_context *drawctxt,
		struct kgsl_cmdbatch **list)
{
	int count = 0;

	while (drawctxt->cmdqueue_head != drawctxt->cmdqueue_tail) {
		struct kgsl_cmdbatch *cmdbatch =
			drawctxt->cmdqueue[drawctxt->cmdqueue_head];

		drawctxt->cmdqueue_head = (drawctxt->cmdqueue_head + 1) %
			ADRENO_CONTEXT_CMDQUEUE_SIZE;

		list[count++] = cmdbatch;
	}

	return count;
}

/**
 * adreno_drawctxt_invalidate() - Invalidate an adreno draw context
 * @device: Pointer to the KGSL device structure for the GPU
@@ -229,8 +247,8 @@ void adreno_drawctxt_invalidate(struct kgsl_device *device,
		struct kgsl_context *context)
{
	struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
	struct kgsl_cmdbatch *inv_cmdbatchs[ADRENO_CONTEXT_CMDQUEUE_SIZE];
	int i, cmd_num = 0;
	struct kgsl_cmdbatch *list[ADRENO_CONTEXT_CMDQUEUE_SIZE];
	int i, count;

	trace_adreno_drawctxt_invalidate(drawctxt);

@@ -250,24 +268,15 @@ void adreno_drawctxt_invalidate(struct kgsl_device *device,
			drawctxt->timestamp);

	/* Get rid of commands still waiting in the queue */
	while (drawctxt->cmdqueue_head != drawctxt->cmdqueue_tail) {
		struct kgsl_cmdbatch *cmdbatch =
			drawctxt->cmdqueue[drawctxt->cmdqueue_head];

		drawctxt->cmdqueue_head = (drawctxt->cmdqueue_head + 1) %
			ADRENO_CONTEXT_CMDQUEUE_SIZE;
	count = drawctxt_detach_cmdbatches(drawctxt, list);
	spin_unlock(&drawctxt->lock);

	for (i = 0; i < count; i++) {
		kgsl_cancel_events_timestamp(device, &context->events,
			cmdbatch->timestamp);

		inv_cmdbatchs[cmd_num++] = cmdbatch;
			list[i]->timestamp);
		kgsl_cmdbatch_destroy(list[i]);
	}

	spin_unlock(&drawctxt->lock);

	for (; cmd_num > 0; cmd_num--)
		kgsl_cmdbatch_destroy(inv_cmdbatchs[i]);

	/* Make sure all pending events are processed or cancelled */
	kgsl_flush_event_group(device, &context->events);

@@ -428,7 +437,8 @@ void adreno_drawctxt_detach(struct kgsl_context *context)
	struct adreno_device *adreno_dev;
	struct adreno_context *drawctxt;
	struct adreno_ringbuffer *rb;
	int ret;
	int ret, count, i;
	struct kgsl_cmdbatch *list[ADRENO_CONTEXT_CMDQUEUE_SIZE];

	if (context == NULL)
		return;
@@ -453,34 +463,19 @@ void adreno_drawctxt_detach(struct kgsl_context *context)
	mutex_unlock(&device->mutex);

	spin_lock(&drawctxt->lock);

	while (drawctxt->cmdqueue_head != drawctxt->cmdqueue_tail) {
		struct kgsl_cmdbatch *cmdbatch =
			drawctxt->cmdqueue[drawctxt->cmdqueue_head];

		drawctxt->cmdqueue_head = (drawctxt->cmdqueue_head + 1) %
			ADRENO_CONTEXT_CMDQUEUE_SIZE;

	count = drawctxt_detach_cmdbatches(drawctxt, list);
	spin_unlock(&drawctxt->lock);

	for (i = 0; i < count; i++) {
		/*
		 * If the context is deteached while we are waiting for
		 * the next command in GFT SKIP CMD, print the context
		 * detached status here.
		 */
		adreno_fault_skipcmd_detached(device, drawctxt, cmdbatch);

		/*
		 * Don't hold the drawctxt mutex while the cmdbatch is being
		 * destroyed because the cmdbatch destroy takes the device
		 * mutex and the world falls in on itself
		 */

		kgsl_cmdbatch_destroy(cmdbatch);
		spin_lock(&drawctxt->lock);
		adreno_fault_skipcmd_detached(device, drawctxt, list[i]);
		kgsl_cmdbatch_destroy(list[i]);
	}

	spin_unlock(&drawctxt->lock);
	/*
	 * internal_timestamp is set in adreno_ringbuffer_addcmds,
	 * which holds the device mutex.