[COMMON] sched: ems: Separate LBT feature into lbt.c
authorDaeyeong Lee <daeyeong.lee@samsung.com>
Fri, 23 Mar 2018 07:10:55 +0000 (16:10 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:24:53 +0000 (20:24 +0300)
Change-Id: Id4b7b40f06418d4d1c46c3170999942ccb895f5b
Signed-off-by: Daeyeong Lee <daeyeong.lee@samsung.com>
kernel/sched/ems/Makefile
kernel/sched/ems/ehmp.c
kernel/sched/ems/ems.h
kernel/sched/ems/lbt.c [new file with mode: 0644]

index 6c5f5a421c5c5a393f7ff3f69e19fe48f4e4024c..c3abbd9acdf01865b34b14b8e774f0c00e22492b 100644 (file)
@@ -1,4 +1,4 @@
-obj-y += core.o global_boost.o
+obj-y += core.o global_boost.o lbt.o
 obj-$(CONFIG_SCHED_TUNE) += st_addon.o
 obj-$(CONFIG_SCHED_EMS) += ehmp.o
 obj-$(CONFIG_FREQVAR_TUNE) += freqvar_tune.o
index 624f631fd1a7472ef91bf1b00446bf1495b74ea4..c90a09d6b3723f0ce33cfb77c935dcef7e507de0 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "../sched.h"
 #include "../tune.h"
+#include "./ems.h"
 
 /**********************************************************************
  * extern functions                                                   *
@@ -294,347 +295,6 @@ int exynos_need_active_balance(enum cpu_idle_type idle, struct sched_domain *sd,
        return unlikely(sd->nr_balance_failed > sd->cache_nice_tries + 2);
 }
 
-/****************************************************************/
-/*                     Load Balance Trigger                    */
-/****************************************************************/
-#define DISABLE_OU             -1
-#define DEFAULT_OU_RATIO       80
-
-struct lbt_overutil {
-       bool                    top;
-       struct cpumask          cpus;
-       unsigned long           capacity;
-       int                     ratio;
-};
-DEFINE_PER_CPU(struct lbt_overutil *, lbt_overutil);
-
-static inline int get_topology_depth(void)
-{
-       struct sched_domain *sd;
-
-       for_each_domain(0, sd) {
-               if (sd->parent == NULL)
-                       return sd->level;
-       }
-
-       return -1;
-}
-
-static inline int get_last_level(struct lbt_overutil *ou)
-{
-       int level;
-
-       for (level = 0; &ou[level] != NULL; level++) {
-               if (ou[level].top == true)
-                       return level;
-       }
-
-       return -1;
-}
-
-/****************************************************************/
-/*                     External APIs                           */
-/****************************************************************/
-bool lbt_overutilized(int cpu, int level)
-{
-       struct lbt_overutil *ou = per_cpu(lbt_overutil, cpu);
-       bool overutilized;
-
-       if (!ou)
-               return false;
-
-       overutilized = (cpu_util(cpu) > ou[level].capacity) ? true : false;
-
-       if (overutilized)
-               trace_ehmp_lbt_overutilized(cpu, level, cpu_util(cpu),
-                               ou[level].capacity, overutilized);
-
-       return overutilized;
-}
-
-void update_lbt_overutil(int cpu, unsigned long capacity)
-{
-       struct lbt_overutil *ou = per_cpu(lbt_overutil, cpu);
-       int level, last = get_last_level(ou);
-
-       for (level = 0; level <= last; level++) {
-               if (ou[level].ratio == DISABLE_OU)
-                       continue;
-
-               ou[level].capacity = (capacity * ou[level].ratio) / 100;
-       }
-}
-
-/****************************************************************/
-/*                             SYSFS                           */
-/****************************************************************/
-#define lbt_attr_init(_attr, _name, _mode, _show, _store)              \
-       sysfs_attr_init(&_attr.attr);                                   \
-       _attr.attr.name = _name;                                        \
-       _attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(_mode);              \
-       _attr.show      = _show;                                        \
-       _attr.store     = _store;
-
-static struct kobject *lbt_kobj;
-static struct attribute **lbt_attrs;
-static struct kobj_attribute *lbt_kattrs;
-static struct attribute_group lbt_group;
-
-static ssize_t show_overutil_ratio(struct kobject *kobj,
-               struct kobj_attribute *attr, char *buf)
-{
-       struct lbt_overutil *ou = per_cpu(lbt_overutil, 0);
-       int level = attr - lbt_kattrs;
-       int cpu, ret = 0;
-
-       for_each_possible_cpu(cpu) {
-               ou = per_cpu(lbt_overutil, cpu);
-
-               if (ou[level].ratio == DISABLE_OU)
-                       continue;
-
-               ret += sprintf(buf + ret, "cpu%d ratio:%3d capacity:%4lu\n",
-                               cpu, ou[level].ratio, ou[level].capacity);
-       }
-
-       return ret;
-}
-
-static ssize_t store_overutil_ratio(struct kobject *kobj,
-               struct kobj_attribute *attr, const char *buf,
-               size_t count)
-{
-       struct lbt_overutil *ou;
-       unsigned long capacity;
-       int level = attr - lbt_kattrs;
-       int cpu, ratio;
-
-       if (sscanf(buf, "%d %d", &cpu, &ratio) != 2)
-               return -EINVAL;
-
-       /* Check cpu is possible */
-       if (!cpumask_test_cpu(cpu, cpu_possible_mask))
-               return -EINVAL;
-       ou = per_cpu(lbt_overutil, cpu);
-
-       /* If ratio is outrage, disable overutil */
-       if (ratio < 0 || ratio > 100)
-               ratio = DEFAULT_OU_RATIO;
-
-       for_each_cpu(cpu, &ou[level].cpus) {
-               ou = per_cpu(lbt_overutil, cpu);
-               if (ou[level].ratio == DISABLE_OU)
-                       continue;
-
-               ou[level].ratio = ratio;
-               capacity = capacity_orig_of(cpu);
-               update_lbt_overutil(cpu, capacity);
-       }
-
-       return count;
-}
-
-static int alloc_lbt_sysfs(int size)
-{
-       if (size < 0)
-               return -EINVAL;
-
-       lbt_attrs = kzalloc(sizeof(struct attribute *) * (size + 1),
-                       GFP_KERNEL);
-       if (!lbt_attrs)
-               goto fail_alloc;
-
-       lbt_kattrs = kzalloc(sizeof(struct kobj_attribute) * (size),
-                       GFP_KERNEL);
-       if (!lbt_kattrs)
-               goto fail_alloc;
-
-       return 0;
-
-fail_alloc:
-       kfree(lbt_attrs);
-       kfree(lbt_kattrs);
-
-       pr_err("LBT(%s): failed to alloc sysfs attrs\n", __func__);
-       return -ENOMEM;
-}
-
-static int __init lbt_sysfs_init(struct kobject *parent)
-{
-       int depth = get_topology_depth();
-       int i;
-
-       if (alloc_lbt_sysfs(depth + 1))
-               goto out;
-
-       for (i = 0; i <= depth; i++) {
-               char buf[20];
-               char *name;
-
-               sprintf(buf, "overutil_ratio_level%d", i);
-               name = kstrdup(buf, GFP_KERNEL);
-               if (!name)
-                       goto out;
-
-               lbt_attr_init(lbt_kattrs[i], name, 0644,
-                               show_overutil_ratio, store_overutil_ratio);
-               lbt_attrs[i] = &lbt_kattrs[i].attr;
-       }
-
-       lbt_group.attrs = lbt_attrs;
-
-       lbt_kobj = kobject_create_and_add("lbt", parent);
-       if (!lbt_kobj)
-               goto out;
-
-       if (sysfs_create_group(lbt_kobj, &lbt_group))
-               goto out;
-
-       return 0;
-
-out:
-       free_lbt_sysfs();
-
-       pr_err("LBT(%s): failed to create sysfs node\n", __func__);
-       return -EINVAL;
-}
-
-/****************************************************************/
-/*                     Initialization                          */
-/****************************************************************/
-static void free_lbt_overutil(void)
-{
-       int cpu;
-
-       for_each_possible_cpu(cpu) {
-               if (per_cpu(lbt_overutil, cpu))
-                       kfree(per_cpu(lbt_overutil, cpu));
-       }
-}
-
-static int alloc_lbt_overutil(void)
-{
-       int cpu, depth = get_topology_depth();
-
-       for_each_possible_cpu(cpu) {
-               struct lbt_overutil *ou = kzalloc(sizeof(struct lbt_overutil) *
-                               (depth + 1), GFP_KERNEL);
-               if (!ou)
-                       goto fail_alloc;
-
-               per_cpu(lbt_overutil, cpu) = ou;
-       }
-       return 0;
-
-fail_alloc:
-       free_lbt_overutil();
-       return -ENOMEM;
-}
-
-static int set_lbt_overutil(int level, const char *mask, int ratio)
-{
-       struct lbt_overutil *ou;
-       struct cpumask cpus;
-       bool top, overlap = false;
-       int cpu;
-
-       cpulist_parse(mask, &cpus);
-       cpumask_and(&cpus, &cpus, cpu_possible_mask);
-       if (!cpumask_weight(&cpus))
-               return -ENODEV;
-
-       /* If sibling cpus is same with possible cpus, it is top level */
-       top = cpumask_equal(&cpus, cpu_possible_mask);
-
-       /* If this level is overlapped with prev level, disable this level */
-       if (level > 0) {
-               ou = per_cpu(lbt_overutil, cpumask_first(&cpus));
-               overlap = cpumask_equal(&cpus, &ou[level-1].cpus);
-       }
-
-       for_each_cpu(cpu, &cpus) {
-               ou = per_cpu(lbt_overutil, cpu);
-               cpumask_copy(&ou[level].cpus, &cpus);
-               ou[level].ratio = overlap ? DISABLE_OU : ratio;
-               ou[level].top = top;
-       }
-
-       return 0;
-}
-
-static int parse_lbt_overutil(struct device_node *dn)
-{
-       struct device_node *lbt, *ou;
-       int level, depth = get_topology_depth();
-       int ret = 0;
-
-       lbt = of_get_child_by_name(dn, "lbt");
-       if (!lbt)
-               return -ENODEV;
-
-       for (level = 0; level <= depth; level++) {
-               char name[20];
-               const char *mask[NR_CPUS];
-               int ratio[NR_CPUS];
-               int i, proplen;
-
-               snprintf(name, sizeof(name), "overutil-level%d", level);
-               ou = of_get_child_by_name(lbt, name);
-               if (!ou) {
-                       ret = -ENODEV;
-                       goto out;
-               }
-
-               proplen = of_property_count_strings(ou, "cpus");
-               if ((proplen < 0) || (proplen != of_property_count_u32_elems(ou, "ratio"))) {
-                       of_node_put(ou);
-                       ret = -ENODEV;
-                       goto out;
-               }
-
-               of_property_read_string_array(ou, "cpus", mask, proplen);
-               of_property_read_u32_array(ou, "ratio", ratio, proplen);
-               of_node_put(ou);
-
-               for (i = 0; i < proplen; i++) {
-                       ret = set_lbt_overutil(level, mask[i], ratio[i]);
-                       if (ret)
-                               goto out;
-               }
-       }
-
-out:
-       of_node_put(lbt);
-       return ret;
-}
-
-static int __init init_lbt(void)
-{
-       struct device_node *dn;
-       int ret;
-
-       dn = of_find_node_by_path("/cpus/ehmp");
-       if (!dn)
-               return 0;
-
-       ret = alloc_lbt_overutil();
-       if (ret) {
-               pr_err("Failed to allocate lbt_overutil\n");
-               goto out;
-       }
-
-       ret = parse_lbt_overutil(dn);
-       if (ret) {
-               pr_err("Failed to parse lbt_overutil\n");
-               free_lbt_overutil();
-               goto out;
-       }
-
-out:
-       of_node_put(dn);
-       return ret;
-}
-pure_initcall(init_lbt);
 /**********************************************************************
  * Global boost                                                       *
  **********************************************************************/
index e6a75a4bc1a6658811b36e7660d55a73f8feeab0..7288c16d4f491ac36152bbe48f86eb4be2f51a2e 100644 (file)
@@ -29,10 +29,15 @@ static inline int group_balancing(struct task_struct *p) { return -1; }
 #ifdef CONFIG_SCHED_EMS
 extern int
 exynos_wakeup_balance(struct task_struct *p, int sd_flag, int sync);
+extern int __init lbt_sysfs_init(struct kobject *parent);
 #else
 static inline int
 exynos_wakeup_balance(struct task_struct *p, int sd_flag, int sync)
 {
        return -1;
 }
+static inline int __init lbt_sysfs_init(struct kobject *parent)
+{
+       return 0;
+}
 #endif
diff --git a/kernel/sched/ems/lbt.c b/kernel/sched/ems/lbt.c
new file mode 100644 (file)
index 0000000..d9a11b0
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * Load Balance Trigger (LBT) for Exynos Mobile Scheduler (EMS)
+ *
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd
+ * LEE DAEYEONG <daeyeong.lee@samsung.com>
+ */
+
+#include <linux/sched.h>
+#include <linux/cpuidle.h>
+#include <linux/pm_qos.h>
+#include <linux/ems.h>
+#include <linux/sched_energy.h>
+
+#include <trace/events/ems.h>
+
+#include "../sched.h"
+#include "../tune.h"
+#include "./ems.h"
+
+/****************************************************************/
+/*                     Load Balance Trigger                    */
+/****************************************************************/
+#define DISABLE_OU             -1
+#define DEFAULT_OU_RATIO       80
+
+struct lbt_overutil {
+       bool                    top;
+       struct cpumask          cpus;
+       unsigned long           capacity;
+       int                     ratio;
+};
+DEFINE_PER_CPU(struct lbt_overutil *, lbt_overutil);
+
+static inline int get_topology_depth(void)
+{
+       struct sched_domain *sd;
+
+       for_each_domain(0, sd) {
+               if (sd->parent == NULL)
+                       return sd->level;
+       }
+
+       return -1;
+}
+
+static inline int get_last_level(struct lbt_overutil *ou)
+{
+       int level;
+
+       for (level = 0; &ou[level] != NULL; level++) {
+               if (ou[level].top == true)
+                       return level;
+       }
+
+       return -1;
+}
+
+/****************************************************************/
+/*                     External APIs                           */
+/****************************************************************/
+bool lbt_overutilized(int cpu, int level)
+{
+       struct lbt_overutil *ou = per_cpu(lbt_overutil, cpu);
+       bool overutilized;
+
+       if (!ou)
+               return false;
+
+       overutilized = (cpu_util(cpu) > ou[level].capacity) ? true : false;
+
+       if (overutilized)
+               trace_ehmp_lbt_overutilized(cpu, level, cpu_util(cpu),
+                               ou[level].capacity, overutilized);
+
+       return overutilized;
+}
+
+void update_lbt_overutil(int cpu, unsigned long capacity)
+{
+       struct lbt_overutil *ou = per_cpu(lbt_overutil, cpu);
+       int level, last = get_last_level(ou);
+
+       for (level = 0; level <= last; level++) {
+               if (ou[level].ratio == DISABLE_OU)
+                       continue;
+
+               ou[level].capacity = (capacity * ou[level].ratio) / 100;
+       }
+}
+
+/****************************************************************/
+/*                             SYSFS                           */
+/****************************************************************/
+#define lbt_attr_init(_attr, _name, _mode, _show, _store)              \
+       sysfs_attr_init(&_attr.attr);                                   \
+       _attr.attr.name = _name;                                        \
+       _attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(_mode);              \
+       _attr.show      = _show;                                        \
+       _attr.store     = _store;
+
+static struct kobject *lbt_kobj;
+static struct attribute **lbt_attrs;
+static struct kobj_attribute *lbt_kattrs;
+static struct attribute_group lbt_group;
+
+static ssize_t show_overutil_ratio(struct kobject *kobj,
+               struct kobj_attribute *attr, char *buf)
+{
+       struct lbt_overutil *ou = per_cpu(lbt_overutil, 0);
+       int level = attr - lbt_kattrs;
+       int cpu, ret = 0;
+
+       for_each_possible_cpu(cpu) {
+               ou = per_cpu(lbt_overutil, cpu);
+
+               if (ou[level].ratio == DISABLE_OU)
+                       continue;
+
+               ret += sprintf(buf + ret, "cpu%d ratio:%3d capacity:%4lu\n",
+                               cpu, ou[level].ratio, ou[level].capacity);
+       }
+
+       return ret;
+}
+
+static ssize_t store_overutil_ratio(struct kobject *kobj,
+               struct kobj_attribute *attr, const char *buf,
+               size_t count)
+{
+       struct lbt_overutil *ou;
+       unsigned long capacity;
+       int level = attr - lbt_kattrs;
+       int cpu, ratio;
+
+       if (sscanf(buf, "%d %d", &cpu, &ratio) != 2)
+               return -EINVAL;
+
+       /* Check cpu is possible */
+       if (!cpumask_test_cpu(cpu, cpu_possible_mask))
+               return -EINVAL;
+       ou = per_cpu(lbt_overutil, cpu);
+
+       /* If ratio is outrage, disable overutil */
+       if (ratio < 0 || ratio > 100)
+               ratio = DEFAULT_OU_RATIO;
+
+       for_each_cpu(cpu, &ou[level].cpus) {
+               ou = per_cpu(lbt_overutil, cpu);
+               if (ou[level].ratio == DISABLE_OU)
+                       continue;
+
+               ou[level].ratio = ratio;
+               capacity = capacity_orig_of(cpu);
+               update_lbt_overutil(cpu, capacity);
+       }
+
+       return count;
+}
+
+static int alloc_lbt_sysfs(int size)
+{
+       if (size < 0)
+               return -EINVAL;
+
+       lbt_attrs = kzalloc(sizeof(struct attribute *) * (size + 1),
+                       GFP_KERNEL);
+       if (!lbt_attrs)
+               goto fail_alloc;
+
+       lbt_kattrs = kzalloc(sizeof(struct kobj_attribute) * (size),
+                       GFP_KERNEL);
+       if (!lbt_kattrs)
+               goto fail_alloc;
+
+       return 0;
+
+fail_alloc:
+       kfree(lbt_attrs);
+       kfree(lbt_kattrs);
+
+       pr_err("LBT(%s): failed to alloc sysfs attrs\n", __func__);
+       return -ENOMEM;
+}
+
+int __init lbt_sysfs_init(struct kobject *parent)
+{
+       int depth = get_topology_depth();
+       int i;
+
+       if (alloc_lbt_sysfs(depth + 1))
+               goto out;
+
+       for (i = 0; i <= depth; i++) {
+               char buf[20];
+               char *name;
+
+               sprintf(buf, "overutil_ratio_level%d", i);
+               name = kstrdup(buf, GFP_KERNEL);
+               if (!name)
+                       goto out;
+
+               lbt_attr_init(lbt_kattrs[i], name, 0644,
+                               show_overutil_ratio, store_overutil_ratio);
+               lbt_attrs[i] = &lbt_kattrs[i].attr;
+       }
+
+       lbt_group.attrs = lbt_attrs;
+
+       lbt_kobj = kobject_create_and_add("lbt", parent);
+       if (!lbt_kobj)
+               goto out;
+
+       if (sysfs_create_group(lbt_kobj, &lbt_group))
+               goto out;
+
+       return 0;
+
+out:
+       kfree(lbt_attrs);
+       kfree(lbt_kattrs);
+
+       pr_err("LBT(%s): failed to create sysfs node\n", __func__);
+       return -EINVAL;
+}
+
+/****************************************************************/
+/*                     Initialization                          */
+/****************************************************************/
+static void free_lbt_overutil(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               if (per_cpu(lbt_overutil, cpu))
+                       kfree(per_cpu(lbt_overutil, cpu));
+       }
+}
+
+static int alloc_lbt_overutil(void)
+{
+       int cpu, depth = get_topology_depth();
+
+       for_each_possible_cpu(cpu) {
+               struct lbt_overutil *ou = kzalloc(sizeof(struct lbt_overutil) *
+                               (depth + 1), GFP_KERNEL);
+               if (!ou)
+                       goto fail_alloc;
+
+               per_cpu(lbt_overutil, cpu) = ou;
+       }
+       return 0;
+
+fail_alloc:
+       free_lbt_overutil();
+       return -ENOMEM;
+}
+
+static int set_lbt_overutil(int level, const char *mask, int ratio)
+{
+       struct lbt_overutil *ou;
+       struct cpumask cpus;
+       bool top, overlap = false;
+       int cpu;
+
+       cpulist_parse(mask, &cpus);
+       cpumask_and(&cpus, &cpus, cpu_possible_mask);
+       if (!cpumask_weight(&cpus))
+               return -ENODEV;
+
+       /* If sibling cpus is same with possible cpus, it is top level */
+       top = cpumask_equal(&cpus, cpu_possible_mask);
+
+       /* If this level is overlapped with prev level, disable this level */
+       if (level > 0) {
+               ou = per_cpu(lbt_overutil, cpumask_first(&cpus));
+               overlap = cpumask_equal(&cpus, &ou[level-1].cpus);
+       }
+
+       for_each_cpu(cpu, &cpus) {
+               ou = per_cpu(lbt_overutil, cpu);
+               cpumask_copy(&ou[level].cpus, &cpus);
+               ou[level].ratio = overlap ? DISABLE_OU : ratio;
+               ou[level].top = top;
+       }
+
+       return 0;
+}
+
+static int parse_lbt_overutil(struct device_node *dn)
+{
+       struct device_node *lbt, *ou;
+       int level, depth = get_topology_depth();
+       int ret = 0;
+
+       lbt = of_get_child_by_name(dn, "lbt");
+       if (!lbt)
+               return -ENODEV;
+
+       for (level = 0; level <= depth; level++) {
+               char name[20];
+               const char *mask[NR_CPUS];
+               int ratio[NR_CPUS];
+               int i, proplen;
+
+               snprintf(name, sizeof(name), "overutil-level%d", level);
+               ou = of_get_child_by_name(lbt, name);
+               if (!ou) {
+                       ret = -ENODEV;
+                       goto out;
+               }
+
+               proplen = of_property_count_strings(ou, "cpus");
+               if ((proplen < 0) || (proplen != of_property_count_u32_elems(ou, "ratio"))) {
+                       of_node_put(ou);
+                       ret = -ENODEV;
+                       goto out;
+               }
+
+               of_property_read_string_array(ou, "cpus", mask, proplen);
+               of_property_read_u32_array(ou, "ratio", ratio, proplen);
+               of_node_put(ou);
+
+               for (i = 0; i < proplen; i++) {
+                       ret = set_lbt_overutil(level, mask[i], ratio[i]);
+                       if (ret)
+                               goto out;
+               }
+       }
+
+out:
+       of_node_put(lbt);
+       return ret;
+}
+
+static int __init init_lbt(void)
+{
+       struct device_node *dn;
+       int ret;
+
+       dn = of_find_node_by_path("/cpus/ems");
+       if (!dn)
+               return 0;
+
+       ret = alloc_lbt_overutil();
+       if (ret) {
+               pr_err("Failed to allocate lbt_overutil\n");
+               goto out;
+       }
+
+       ret = parse_lbt_overutil(dn);
+       if (ret) {
+               pr_err("Failed to parse lbt_overutil\n");
+               free_lbt_overutil();
+               goto out;
+       }
+
+out:
+       of_node_put(dn);
+       return ret;
+}
+pure_initcall(init_lbt);