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

Commit 44ba8f8b authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Return -ENOENT if a context is detached during submit



There are several points during the submission pipeline where we can
bail if the context has been detached. Return -ENOENT in those cases
so the dispatcher can 1) not try to requeue the command or the
context and 2) not log an error (detached commands should be
silently discarded).

Change-Id: Ic0dedbad5d67b24e8bd2804647133d03617ea8dc
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent c049a981
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -2382,9 +2382,9 @@ static int adreno_waittimestamp(struct kgsl_device *device,
		return -ENOTTY;
	}

	/* Return -EINVAL if the context has been detached */
	/* Return -ENOENT if the context has been detached */
	if (kgsl_context_detached(context))
		return -EINVAL;
		return -ENOENT;

	ret = adreno_drawctxt_wait(ADRENO_DEVICE(device), context,
		timestamp, msecs);
+46 −31
Original line number Diff line number Diff line
@@ -439,7 +439,7 @@ static inline int adreno_dispatcher_requeue_cmdbatch(
		spin_unlock(&drawctxt->lock);
		/* get rid of this cmdbatch since the context is bad */
		kgsl_cmdbatch_destroy(cmdbatch);
		return -EINVAL;
		return -ENOENT;
	}

	prev = drawctxt->cmdqueue_head == 0 ?
@@ -568,8 +568,16 @@ static int sendcmd(struct adreno_device *adreno_dev,
	if (ret) {
		dispatcher->inflight--;
		dispatch_q->inflight--;
		KGSL_DRV_WARN(device,
			"Unable to submit command to the ringbuffer %d\n", ret);

		/*
		 * -ENOENT means that the context was detached before the
		 *  command was submitted - don't log a message in that case
		 */

		if (ret != -ENOENT)
			KGSL_DRV_ERR(device,
				"Unable to submit command to the ringbuffer %d\n",
				ret);
		return ret;
	}

@@ -681,15 +689,25 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev,
		ret = sendcmd(adreno_dev, cmdbatch);

		/*
		 * There are various reasons why we can't submit a command (no
		 * memory for the commands, full ringbuffer, etc) but none of
		 * these are actually the current command's fault. Requeue it
		 * in same position in the drawctxt q
		 * On error from sendcmd() try to requeue the command batch
		 * unless we got back -ENOENT which means that the context has
		 * been detached and there will be no more deliveries from here
		 */
		if (ret) {
			if (adreno_dispatcher_requeue_cmdbatch(drawctxt,
				cmdbatch))
				ret = -EINVAL;
		if (ret != 0) {
			/* Destroy the cmdbatch on -ENOENT */
			if (ret == -ENOENT)
				kgsl_cmdbatch_destroy(cmdbatch);
			else {
				/*
				 * If the requeue returns an error, return that
				 * instead of whatever sendcmd() sent us
				 */
				int r = adreno_dispatcher_requeue_cmdbatch(
					drawctxt, cmdbatch);
				if (r)
					ret = r;
			}

			break;
		}

@@ -720,7 +738,7 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev,
 * Issue as many commands as possible (up to inflight) from the pending contexts
 * This function assumes the dispatcher mutex has been locked.
 */
static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)
static void _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)
{
	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
	struct adreno_context *drawctxt, *next;
@@ -729,7 +747,7 @@ static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)

	/* Leave early if the dispatcher isn't in a happy state */
	if (adreno_gpu_fault(adreno_dev) != 0)
			return 0;
		return;

	plist_head_init(&requeue);
	plist_head_init(&busy_list);
@@ -767,19 +785,21 @@ static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)

		ret = dispatcher_context_sendcmds(adreno_dev, drawctxt);

		if (ret != 0) {
		/* Don't bother requeuing on -ENOENT - context is detached */
		if (ret != 0 && ret != -ENOENT) {
			spin_lock(&dispatcher->plist_lock);

			/*
			 * Check to seen if the context had been requeued while
			 * we were processing it (probably by another thread
			 * pushing commands). If it has then do a put to make
			 * sure the reference counting stays accurate.
			 * If the dispatch_q is full then put it on the
			 * busy list so it gets first preference when space
			 * becomes available.
			 * Otherwise put it on the requeue list since it may
			 * have more commands.
			 * pushing commands). If it has then shift it to the
			 * requeue list if it was not able to submit commands
			 * due to the dispatch_q being full. Also, do a put to
			 * make sure the reference counting stays accurate.
			 * If the node is empty then we will put it on the
			 * requeue list and not touch the refcount since we
			 * already hold it from the first time it went on the
			 * list.
			 */

			if (!plist_node_empty(&drawctxt->pending)) {
@@ -820,8 +840,6 @@ static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)
	}

	spin_unlock(&dispatcher->plist_lock);

	return 0;
}

/**
@@ -830,21 +848,18 @@ static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)
 *
 * Lock the dispatcher and call _adreno_dispatcher_issueibcmds
 */
static int adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)
static void adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)
{
	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
	int ret;

	/* If the dispatcher is busy then schedule the work for later */
	if (!mutex_trylock(&dispatcher->mutex)) {
		adreno_dispatcher_schedule(&adreno_dev->dev);
		return 0;
		return;
	}

	ret = _adreno_dispatcher_issuecmds(adreno_dev);
	_adreno_dispatcher_issuecmds(adreno_dev);
	mutex_unlock(&dispatcher->mutex);

	return ret;
}

/**
@@ -984,7 +999,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,

	if (kgsl_context_detached(&drawctxt->base)) {
		spin_unlock(&drawctxt->lock);
		return -EINVAL;
		return -ENOENT;
	}

	/*
@@ -1065,7 +1080,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,
	}
	if (kgsl_context_detached(&drawctxt->base)) {
		spin_unlock(&drawctxt->lock);
		return -EINVAL;
		return -ENOENT;
	}

	ret = get_timestamp(drawctxt, cmdbatch, timestamp);
+6 −10
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ int adreno_drawctxt_wait(struct adreno_device *adreno_dev,
	long ret_temp;

	if (kgsl_context_detached(context))
		return -EINVAL;
		return -ENOENT;

	if (kgsl_context_invalid(context))
		return -EDEADLK;
@@ -177,7 +177,7 @@ int adreno_drawctxt_wait(struct adreno_device *adreno_dev,

	/* Return -EINVAL if the context was detached while we were waiting */
	if (kgsl_context_detached(context))
		ret = -EINVAL;
		ret = -ENOENT;

done:
	trace_adreno_drawctxt_wait_done(-1, context->id, timestamp, ret);
@@ -420,7 +420,7 @@ void adreno_drawctxt_sched(struct kgsl_device *device,
 * @context: Generic KGSL context container for the context
 *
 */
int adreno_drawctxt_detach(struct kgsl_context *context)
void adreno_drawctxt_detach(struct kgsl_context *context)
{
	struct kgsl_device *device;
	struct adreno_device *adreno_dev;
@@ -429,7 +429,7 @@ int adreno_drawctxt_detach(struct kgsl_context *context)
	int ret;

	if (context == NULL)
		return 0;
		return;

	device = context->device;
	adreno_dev = ADRENO_DEVICE(device);
@@ -503,9 +503,7 @@ int adreno_drawctxt_detach(struct kgsl_context *context)
	 * in and there will be no more commands in the RB pipe from this
	 * context which is waht we are waiting for, so ignore -EAGAIN error
	 */
	if (-EAGAIN == ret)
		ret = 0;
	BUG_ON(ret);
	BUG_ON(ret && ret != -EAGAIN);

	kgsl_sharedmem_writel(device, &device->memstore,
			KGSL_MEMSTORE_OFFSET(context->id, soptimestamp),
@@ -522,8 +520,6 @@ int adreno_drawctxt_detach(struct kgsl_context *context)
	/* wake threads waiting to submit commands from this context */
	wake_up_all(&drawctxt->waiting);
	wake_up_all(&drawctxt->wq);

	return ret;
}

void adreno_drawctxt_destroy(struct kgsl_context *context)
@@ -569,7 +565,7 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
	/* Get a refcount to the new instance */
	if (drawctxt) {
		if (!_kgsl_context_get(&drawctxt->base))
			return -EINVAL;
			return -ENOENT;

		new_pt = drawctxt->base.proc_priv->pagetable;
	} else {
+1 −1
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ enum adreno_context_priv {
struct kgsl_context *adreno_drawctxt_create(struct kgsl_device_private *,
			uint32_t *flags);

int adreno_drawctxt_detach(struct kgsl_context *context);
void adreno_drawctxt_detach(struct kgsl_context *context);

void adreno_drawctxt_destroy(struct kgsl_context *context);

+14 −16
Original line number Diff line number Diff line
@@ -540,7 +540,7 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,

	if (drawctxt != NULL && kgsl_context_detached(&drawctxt->base) &&
		!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE))
		return -EINVAL;
		return -ENOENT;

	rb->timestamp++;

@@ -635,8 +635,6 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
	ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
	if (IS_ERR(ringcmds))
		return PTR_ERR(ringcmds);
	if (ringcmds == NULL)
		return -ENOSPC;

	start = ringcmds;

@@ -1131,24 +1129,26 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
					&link[0], (cmds - link),
					cmdbatch->timestamp, time);

	if (!ret) {
		cmdbatch->global_ts = drawctxt->internal_timestamp;

		/* Put the timevalues in the profiling buffer */
		if (cmdbatch_user_profiling) {
			profile_buffer->wall_clock_s = time->utime.tv_sec;
			profile_buffer->wall_clock_ns = time->utime.tv_nsec;
			profile_buffer->gpu_ticks_queued = time->ticks;
		}
	}

	kgsl_cffdump_regpoll(device,
		adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2,
		0x00000000, 0x80000000);
done:
	/* Corresponding unmap to the memdesc map of profile_buffer */
	if (entry)
		kgsl_memdesc_unmap(&entry->memdesc);

	if (!ret)
		cmdbatch->global_ts = drawctxt->internal_timestamp;

	kgsl_cffdump_regpoll(device,
		adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2,
		0x00000000, 0x80000000);
done:
	trace_kgsl_issueibcmds(device, context->id, cmdbatch,
			numibs, cmdbatch->timestamp,
			cmdbatch->flags, ret, drawctxt->type);
@@ -1346,8 +1346,6 @@ int adreno_ringbuffer_submit_preempt_token(struct adreno_ringbuffer *rb,

	if (IS_ERR(ringcmds))
		return PTR_ERR(ringcmds);
	if (ringcmds == NULL)
		return -ENOSPC;

	start = ringcmds;

Loading