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

Commit 2c336fc3 authored by Shubhraprakash Das's avatar Shubhraprakash Das
Browse files

msm: kgsl: Use GPU to select perfcounters



Use the GPU to set the select register of perfcounter instead
of using the CPU to set the select register. This removes the
synchronization between CPU and GPU where CPU needs to wait for
GPU to idle before setting the perfcounter select register.
Additionally with SP/TP power collapse feature the SP/TP will
automatically power on when GPU is used to set perfcounter
registers hence this feature does not need to be turned off/on when
SP/TP perfcounters are set.

Change-Id: I3f12792ddd44f055e7d3bb803e7bfd3ca49a4158
Signed-off-by: default avatarShubhraprakash Das <sadas@codeaurora.org>
parent 55ca3fcf
Loading
Loading
Loading
Loading
+0 −43
Original line number Diff line number Diff line
@@ -532,44 +532,6 @@ static inline void refcount_group(struct adreno_perfcount_group *group,
		*hi = group->regs[reg].offset_hi;
}


/**
 * adreno_idle_unsafe() - wait for the GPU hardware to go idle
 *
 * This doesn't check for dispatcher mutex owner. Hence this function
 * should be called only if we are sure that we dont own dispatcher mutex
 * in this thread.
 *
 * @device: Pointer to the KGSL device structure for the GPU
 *
 * Wait up to ADRENO_IDLE_TIMEOUT milliseconds for the GPU hardware to go quiet.
 */

static int adreno_idle_unsafe(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	int ret;

	/*
	 * Make sure the device mutex is held so the dispatcher can't send any
	 * more commands to the hardware
	 */

	BUG_ON(!mutex_is_locked(&device->mutex));

	/* Check if we are already idle before idling dispatcher */
	if (adreno_isidle(device))
		return 0;
	/*
	 * Wait for dispatcher to finish completing commands
	 * already submitted
	 */
	ret = adreno_dispatcher_idle_unsafe(adreno_dev);
	if (ret)
		return ret;

	return adreno_spin_idle(device);
}
/**
 * adreno_perfcounter_get: Try to put a countable in an available counter
 * @adreno_dev: Adreno device to configure
@@ -652,11 +614,6 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev,
	if (empty == -1)
		return -EBUSY;

	ret = adreno_idle_unsafe(&adreno_dev->dev);

	if (ret)
		return ret;

	/* enable the new counter */
	ret = gpudev->perfcounter_enable(adreno_dev, groupid, empty, countable);
	if (ret)
+0 −1
Original line number Diff line number Diff line
@@ -737,7 +737,6 @@ void adreno_dispatcher_start(struct kgsl_device *device);
int adreno_dispatcher_init(struct adreno_device *adreno_dev);
void adreno_dispatcher_close(struct adreno_device *adreno_dev);
int adreno_dispatcher_idle(struct adreno_device *adreno_dev);
int adreno_dispatcher_idle_unsafe(struct adreno_device *adreno_dev);
void adreno_dispatcher_irq_fault(struct kgsl_device *device);
void adreno_dispatcher_stop(struct adreno_device *adreno_dev);

+37 −4
Original line number Diff line number Diff line
@@ -1015,6 +1015,7 @@ int a3xx_perfcounter_enable(struct adreno_device *adreno_dev,
	struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev);
	struct adreno_perfcount_register *reg;
	int i;
	int ret = 0;

	/* Special cases */
	if (group == KGSL_PERFCOUNTER_GROUP_PWR)
@@ -1064,10 +1065,42 @@ int a3xx_perfcounter_enable(struct adreno_device *adreno_dev,
	}
	reg = &(counters->groups[group].regs[counter]);

	if (test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv)) {
		struct kgsl_device *device = &adreno_dev->dev;
		unsigned int cmds[4];
		int ret;

		cmds[0] = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
		cmds[1] = 0;
		cmds[2] = cp_type0_packet(reg->select, 1);
		cmds[3] = countable;
		ret = adreno_ringbuffer_issuecmds(device, NULL, 0, cmds,
				4);
		if (ret)
			goto done;
		/* wait for the above commands submitted to complete */
		ret = adreno_spin_idle(device);
		if (ret) {
			/*
			 * counter turn on failed and the commands probably
			 * hung GPU, reset GPU after which counter should be
			 * turned on already via the CPU path
			 */
			ret = adreno_reset(device);
			BUG_ON(ret);
		} else {
			unsigned int ts_processed;
			adreno_rb_readtimestamp(device, adreno_dev->cur_rb,
				KGSL_TIMESTAMP_RETIRED, &ts_processed);
			BUG_ON(ts_processed != adreno_dev->cur_rb->timestamp);
		}
	} else {
		/* Select the desired perfcounter */
		kgsl_regwrite(&adreno_dev->dev, reg->select, countable);
	}
done:
	if (!ret)
		counters->groups[group].regs[counter].value = 0;

	return 0;
}

+1 −24
Original line number Diff line number Diff line
@@ -2032,6 +2032,7 @@ int adreno_dispatcher_idle(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = &adreno_dev->dev;
	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
	int ret;

	BUG_ON(!mutex_is_locked(&device->mutex));
	if (!test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
@@ -2045,30 +2046,6 @@ int adreno_dispatcher_idle(struct adreno_device *adreno_dev)
		dispatcher->mutex.owner == current)
		BUG_ON(1);

	return adreno_dispatcher_idle_unsafe(adreno_dev);
}

/*
 * adreno_dispatcher_idle_unsafe() - Wait for dispatcher to idle
 *
 *
 * @adreno_dev: Adreno device whose dispatcher needs to idle
 *
 * Signal dispatcher to stop sending more commands and complete
 * the commands that have already been submitted.
 * This function should not be called when dispatcher mutex is held
 * since it doesnt check for dispatcher mutex owner.
 */
int adreno_dispatcher_idle_unsafe(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = &adreno_dev->dev;
	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
	int ret;

	BUG_ON(!mutex_is_locked(&device->mutex));
	if (!test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
		return 0;

	adreno_get_gpu_halt(adreno_dev);

	mutex_unlock(&device->mutex);
+1 −1
Original line number Diff line number Diff line
@@ -900,7 +900,7 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
	return 0;
}

unsigned int
int
adreno_ringbuffer_issuecmds(struct kgsl_device *device,
						struct adreno_context *drawctxt,
						unsigned int flags,
Loading