OSDN Git Service

msm: kgsl: track GPU active time per frequency
authorGeorge Shen <sqiao@codeaurora.org>
Wed, 4 May 2016 01:23:22 +0000 (18:23 -0700)
committerCarter Cooper <ccooper@codeaurora.org>
Wed, 3 Aug 2016 16:34:03 +0000 (10:34 -0600)
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>
drivers/gpu/msm/adreno.c
drivers/gpu/msm/kgsl_pwrctrl.c
drivers/gpu/msm/kgsl_pwrctrl.h
drivers/gpu/msm/kgsl_pwrscale.c

index a802671..fad5356 100644 (file)
@@ -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);
index 2b9eef8..11b323e 100644 (file)
@@ -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,
index 0029c38..8fd0653 100644 (file)
@@ -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;
index 4f6677d..d90aec4 100644 (file)
@@ -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);