summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Shen <sqiao@codeaurora.org>2016-05-03 18:23:22 -0700
committerCarter Cooper <ccooper@codeaurora.org>2016-08-03 10:34:03 -0600
commitb35803e7901f2afafa81ff5dde396856ea5c7426 (patch)
treea3e5f73db2f20a20c20daac46db231b8f12acbd1
parenta8ac335601c4bb8249207877a6d8b486c310ae31 (diff)
msm: kgsl: track GPU active time per frequency
Tracks GPU active time per frequency for GPU workload profiling. The data will be output in /sys/class/kgsl/kgsl-3d0/gpu_clock_stats with one u64 value in microseconds per clock level. For example: cat /sys/class/kgsl/kgsl-3d0/gpu_clock_stats 39392 29292 929292 929292 4040404 CRs-Fixed: 1011462 Change-Id: I5f2caa8b38d99ffd23f03c1dfed1efda273fc2fb Signed-off-by: George Shen <sqiao@codeaurora.org>
-rw-r--r--drivers/gpu/msm/adreno.c2
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c31
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.h2
-rw-r--r--drivers/gpu/msm/kgsl_pwrscale.c3
4 files changed, 38 insertions, 0 deletions
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index a802671acba0..fad5356e2c9e 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1595,6 +1595,8 @@ static int adreno_stop(struct kgsl_device *device)
adreno_ringbuffer_stop(adreno_dev);
+ kgsl_pwrscale_update_stats(device);
+
adreno_irqctrl(adreno_dev, 0);
adreno_ocmem_free(adreno_dev);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 2b9eef8b6351..11b323e9d40c 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -363,6 +363,8 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
if (new_level == old_level)
return;
+ kgsl_pwrscale_update_stats(device);
+
/*
* Set the active and previous powerlevel first in case the clocks are
* off - if we don't do this then the pwrlevel change won't take effect
@@ -934,6 +936,31 @@ static ssize_t kgsl_pwrctrl_gpu_available_frequencies_show(
return num_chars;
}
+static ssize_t kgsl_pwrctrl_gpu_clock_stats_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct kgsl_device *device = kgsl_device_from_dev(dev);
+ struct kgsl_pwrctrl *pwr;
+ int index, num_chars = 0;
+
+ if (device == NULL)
+ return 0;
+ pwr = &device->pwrctrl;
+ mutex_lock(&device->mutex);
+ kgsl_pwrscale_update_stats(device);
+ mutex_unlock(&device->mutex);
+ for (index = 0; index < pwr->num_pwrlevels - 1; index++)
+ num_chars += snprintf(buf + num_chars, PAGE_SIZE - num_chars,
+ "%llu ", pwr->clock_times[index]);
+
+ if (num_chars < PAGE_SIZE)
+ buf[num_chars++] = '\n';
+
+ return num_chars;
+}
+
static ssize_t kgsl_pwrctrl_reset_count_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1201,6 +1228,9 @@ static DEVICE_ATTR(gpubusy, 0444, kgsl_pwrctrl_gpubusy_show,
static DEVICE_ATTR(gpu_available_frequencies, 0444,
kgsl_pwrctrl_gpu_available_frequencies_show,
NULL);
+static DEVICE_ATTR(gpu_clock_stats, 0444,
+ kgsl_pwrctrl_gpu_clock_stats_show,
+ NULL);
static DEVICE_ATTR(max_pwrlevel, 0644,
kgsl_pwrctrl_max_pwrlevel_show,
kgsl_pwrctrl_max_pwrlevel_store);
@@ -1249,6 +1279,7 @@ static const struct device_attribute *pwrctrl_attr_list[] = {
&dev_attr_deep_nap_timer,
&dev_attr_gpubusy,
&dev_attr_gpu_available_frequencies,
+ &dev_attr_gpu_clock_stats,
&dev_attr_max_pwrlevel,
&dev_attr_min_pwrlevel,
&dev_attr_thermal_pwrlevel,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 0029c389484f..8fd06531aa81 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -122,6 +122,7 @@ struct kgsl_regulator {
* @min_pwrlevel - minimum allowable powerlevel per the user
* @num_pwrlevels - number of available power levels
* @interval_timeout - timeout in jiffies to be idle before a power event
+ * @clock_times - Each GPU frequency's accumulated active time in us
* @strtstp_sleepwake - true if the device supports low latency GPU start/stop
* @regulators - array of pointers to kgsl_regulator structs
* @pcl - bus scale identifier
@@ -178,6 +179,7 @@ struct kgsl_pwrctrl {
unsigned int min_pwrlevel;
unsigned int num_pwrlevels;
unsigned long interval_timeout;
+ u64 clock_times[KGSL_MAX_PWRLEVELS];
bool strtstp_sleepwake;
struct kgsl_regulator regulators[KGSL_MAX_REGULATORS];
uint32_t pcl;
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 4f6677d9a1de..d90aec42f30a 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -127,6 +127,7 @@ EXPORT_SYMBOL(kgsl_pwrscale_busy);
*/
void kgsl_pwrscale_update_stats(struct kgsl_device *device)
{
+ struct kgsl_pwrctrl *pwrctrl = &device->pwrctrl;
struct kgsl_pwrscale *psc = &device->pwrscale;
BUG_ON(!mutex_is_locked(&device->mutex));
@@ -150,6 +151,8 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device)
device->pwrscale.accum_stats.busy_time += stats.busy_time;
device->pwrscale.accum_stats.ram_time += stats.ram_time;
device->pwrscale.accum_stats.ram_wait += stats.ram_wait;
+ pwrctrl->clock_times[pwrctrl->active_pwrlevel] +=
+ stats.busy_time;
}
}
EXPORT_SYMBOL(kgsl_pwrscale_update_stats);