PD#114881: add debug sysfs for devfreq governor
authorTao Zeng <tao.zeng@amlogic.com>
Thu, 3 Dec 2015 09:56:17 +0000 (17:56 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Thu, 3 Dec 2015 09:56:17 +0000 (17:56 +0800)
Change-Id: I7f7fa3902a0aa24478bc636ecfbe1a19c7ad1df8

t83x/kernel/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c

index 3791457f605d9573a0acee082ad41b0a591d4a2a..db97637c9bc8148b225d766bb5d786be040543f0 100755 (executable)
 #define dev_pm_opp_find_freq_ceil opp_find_freq_ceil
 #endif /* Linux >= 3.13 */
 
+#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
+static struct devfreq_simple_ondemand_data ondemand_data = {
+               .upthreshold = 90,
+               .downdifferential = 5,
+};
+
+#define DEV_FREQ_GOV_DATA              (&ondemand_data)
+
+static ssize_t upthreshold_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", ondemand_data.upthreshold);
+}
+
+static ssize_t upthreshold_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       unsigned int t;
+       int ret;
+
+       ret = sscanf(buf, "%u", &t);
+       if (ret != 1)
+               return -EINVAL;
+
+       if (t >= 100 || t == 0) {
+               dev_err(dev, "invalid input:%s\n", buf);
+               return -EINVAL;
+       }
+       ondemand_data.upthreshold = t;
+       return count;
+
+}
+static DEVICE_ATTR_RW(upthreshold);
+
+static ssize_t downdifferential_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", ondemand_data.downdifferential);
+}
+
+static ssize_t downdifferential_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       unsigned int t;
+       int ret;
+
+       ret = sscanf(buf, "%u", &t);
+       if (ret != 1)
+               return -EINVAL;
+
+       if (t >= 100 || t == 0) {
+               dev_err(dev, "invalid input:%s\n", buf);
+               return -EINVAL;
+       }
+       ondemand_data.downdifferential = t;
+       return count;
+
+}
+static DEVICE_ATTR_RW(downdifferential);
+#else
+#define DEV_FREQ_GOV_DATA              (NULL)
+#endif /* CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND */
+
+static ssize_t utilisation_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct kbase_device *kbdev = dev_get_drvdata(dev->parent);
+       unsigned long total_time = 0, busy_time = 0;
+       unsigned long utilise;
+
+       kbase_pm_get_dvfs_utilisation(kbdev, &total_time, &busy_time);
+
+       if (total_time == 0) {
+               utilise = 0;
+       } else {
+               /* round up */
+               utilise = (busy_time * 100 + (total_time >> 1)) / total_time;
+       }
+       return sprintf(buf, "%ld\n", utilise);
+}
+static DEVICE_ATTR_RO(utilisation);
+
+static struct device_attribute *kbase_dev_attr[] = {
+#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
+       &dev_attr_downdifferential,
+       &dev_attr_upthreshold,
+#endif
+       &dev_attr_utilisation
+};
+
+static int kbase_dev_add_attr(struct device *dev)
+{
+       int i, ret;
+       for (i = 0; i <  ARRAY_SIZE(kbase_dev_attr); i++) {
+               if (!kbase_dev_attr[i])
+                       continue;
+               ret = device_create_file(dev, kbase_dev_attr[i]);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
 
 static int
 kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
@@ -218,12 +322,13 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
                return -EFAULT;
 
        kbdev->devfreq = devfreq_add_device(kbdev->dev, dp,
-                               "simple_ondemand", NULL);
+                               "simple_ondemand", DEV_FREQ_GOV_DATA);
        if (IS_ERR(kbdev->devfreq)) {
                kbase_devfreq_term_freq_table(kbdev);
                return PTR_ERR(kbdev->devfreq);
        }
 
+       kbase_dev_add_attr(&kbdev->devfreq->dev);
        err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq);
        if (err) {
                dev_err(kbdev->dev,