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

Commit 97035715 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: Account for throttled clock cycles in DCVS"

parents 1468823d 2c3467e9
Loading
Loading
Loading
Loading
+82 −7
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ MODULE_PARM_DESC(nopreempt, "Disable GPU preemption");
#define KGSL_LOG_LEVEL_DEFAULT 3

static void adreno_input_work(struct work_struct *work);
static unsigned int counter_delta(struct adreno_device *adreno_dev,
	unsigned int reg, unsigned int *counter);

static struct devfreq_msm_adreno_tz_data adreno_tz_data = {
	.bus = {
@@ -1379,6 +1381,77 @@ static bool regulators_left_on(struct kgsl_device *device)
	return false;
}

static void _setup_throttling_counters(struct adreno_device *adreno_dev)
{
	int i, ret;

	if (!adreno_is_a540(adreno_dev))
		return;

	if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM))
		return;

	for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) {
		/* reset throttled cycles ivalue */
		adreno_dev->busy_data.throttle_cycles[i] = 0;

		if (adreno_dev->gpmu_throttle_counters[i] != 0)
			continue;
		ret = adreno_perfcounter_get(adreno_dev,
			KGSL_PERFCOUNTER_GROUP_GPMU_PWR,
			ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i,
			&adreno_dev->gpmu_throttle_counters[i],
			NULL,
			PERFCOUNTER_FLAG_KERNEL);
		WARN_ONCE(ret,  "Unable to get clock throttling counter %x\n",
			ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i);
	}
}

/* FW driven idle 10% throttle */
#define IDLE_10PCT 0
/* number of cycles when clock is throttled by 50% (CRC) */
#define CRC_50PCT  1
/* number of cycles when clock is throttled by more than 50% (CRC) */
#define CRC_MORE50PCT 2
/* number of cycles when clock is throttle by less than 50% (CRC) */
#define CRC_LESS50PCT 3

static uint64_t _read_throttling_counters(struct adreno_device *adreno_dev)
{
	int i;
	uint32_t th[ADRENO_GPMU_THROTTLE_COUNTERS];
	struct adreno_busy_data *busy = &adreno_dev->busy_data;

	if (!adreno_is_a540(adreno_dev))
		return 0;

	if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM))
		return 0;

	for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) {
		if (!adreno_dev->gpmu_throttle_counters[i])
			return 0;

		th[i] = counter_delta(adreno_dev,
			adreno_dev->gpmu_throttle_counters[i],
			&busy->throttle_cycles[i]);
	}
	return th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 +
		(th[CRC_MORE50PCT] - th[IDLE_10PCT]) * 3;

}

static void _update_threshold_count(struct adreno_device *adreno_dev,
	uint64_t adj)
{
	if (adreno_is_a530(adreno_dev))
		kgsl_regread(&adreno_dev->dev, adreno_dev->lm_threshold_count,
		&adreno_dev->lm_threshold_cross);
	else if (adreno_is_a540(adreno_dev))
		adreno_dev->lm_threshold_cross = adj;
}

/**
 * _adreno_start - Power up the GPU and prepare to accept commands
 * @adreno_dev: Pointer to an adreno_device structure
@@ -1390,7 +1463,7 @@ static int _adreno_start(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = &adreno_dev->dev;
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	int status = -EINVAL;
	int status = -EINVAL, ret;
	unsigned int state = device->state;
	bool regulator_left_on;
	unsigned int pmqos_wakeup_vote = device->pwrctrl.pm_qos_wakeup_latency;
@@ -1454,7 +1527,7 @@ static int _adreno_start(struct adreno_device *adreno_dev)
		gpudev->enable_64bit(adreno_dev);

	if (adreno_dev->perfctr_pwr_lo == 0) {
		int ret = adreno_perfcounter_get(adreno_dev,
		ret = adreno_perfcounter_get(adreno_dev,
			KGSL_PERFCOUNTER_GROUP_PWR, 1,
			&adreno_dev->perfctr_pwr_lo, NULL,
			PERFCOUNTER_FLAG_KERNEL);
@@ -1467,7 +1540,6 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	}

	if (device->pwrctrl.bus_control) {
		int ret;

		/* VBIF waiting for RAM */
		if (adreno_dev->starved_ram_lo == 0) {
@@ -1504,9 +1576,8 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	adreno_dev->busy_data.vbif_ram_cycles = 0;
	adreno_dev->busy_data.vbif_starved_ram = 0;

	if (ADRENO_FEATURE(adreno_dev, ADRENO_LM)
	if (adreno_is_a530(adreno_dev) && ADRENO_FEATURE(adreno_dev, ADRENO_LM)
		&& adreno_dev->lm_threshold_count == 0) {
		int ret;

		ret = adreno_perfcounter_get(adreno_dev,
			KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 27,
@@ -1517,6 +1588,8 @@ static int _adreno_start(struct adreno_device *adreno_dev)
			adreno_dev->lm_threshold_count = 0;
	}

	_setup_throttling_counters(adreno_dev);

	/* Restore performance counter registers with saved values */
	adreno_perfcounter_restore(adreno_dev);

@@ -2602,6 +2675,7 @@ static void adreno_power_stats(struct kgsl_device *device,
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct adreno_busy_data *busy = &adreno_dev->busy_data;
	uint64_t adj;

	memset(stats, 0, sizeof(*stats));

@@ -2612,6 +2686,8 @@ static void adreno_power_stats(struct kgsl_device *device,
		gpu_busy = counter_delta(adreno_dev, adreno_dev->perfctr_pwr_lo,
			&busy->gpu_busy);

		adj = _read_throttling_counters(adreno_dev);
		gpu_busy += adj;
		stats->busy_time = adreno_ticks_to_us(gpu_busy,
			kgsl_pwrctrl_active_freq(pwr));
	}
@@ -2633,8 +2709,7 @@ static void adreno_power_stats(struct kgsl_device *device,
		stats->ram_wait = starved_ram;
	}
	if (adreno_dev->lm_threshold_count)
		kgsl_regread(&adreno_dev->dev, adreno_dev->lm_threshold_count,
			&adreno_dev->lm_threshold_cross);
		_update_threshold_count(adreno_dev, adj);
}

static unsigned int adreno_gpuid(struct kgsl_device *device,
+8 −0
Original line number Diff line number Diff line
@@ -186,12 +186,18 @@ enum adreno_gpurev {
#define ADRENO_PPD_CTRL     1
#define ADRENO_LM_CTRL      2

/* number of throttle counters for DCVS adjustment */
#define ADRENO_GPMU_THROTTLE_COUNTERS 4
/* base for throttle counters */
#define ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG 43

struct adreno_gpudev;

struct adreno_busy_data {
	unsigned int gpu_busy;
	unsigned int vbif_ram_cycles;
	unsigned int vbif_starved_ram;
	unsigned int throttle_cycles[ADRENO_GPMU_THROTTLE_COUNTERS];
};

/**
@@ -310,6 +316,7 @@ struct adreno_gpu_core {
 * @lm_threshold_cross: number of current peaks exceeding threshold
 * @speed_bin: Indicate which power level set to use
 * @csdev: Pointer to a coresight device (if applicable)
 * @gpmu_throttle_counters - counteers for number of throttled clocks
 */
struct adreno_device {
	struct kgsl_device dev;    /* Must be first field in this struct */
@@ -369,6 +376,7 @@ struct adreno_device {
	unsigned int quirks;

	struct coresight_device *csdev;
	uint32_t gpmu_throttle_counters[ADRENO_GPMU_THROTTLE_COUNTERS];
};

/**
+8 −1
Original line number Diff line number Diff line
@@ -671,8 +671,15 @@ static void _power_counter_enable_gpmu(struct adreno_device *adreno_dev,
	struct kgsl_device *device = &adreno_dev->dev;
	struct adreno_perfcount_register *reg;

	if (adreno_is_a530(adreno_dev)) {
		if (countable > 43)
			return;
	} else if (adreno_is_a540(adreno_dev)) {
		if (countable > 47)
			return;
	} else
		/* return on platforms that have no GPMU */
		return;

	reg = &counters->groups[group].regs[counter];