From 88cbdb61738e15ccae3679a9d8cc9fbc126c5509 Mon Sep 17 00:00:00 2001 From: "Huang, Tao" Date: Fri, 20 May 2016 17:05:24 +0800 Subject: [PATCH] rk: remove cpuquiet Change-Id: I1fde79829ebff9f74609c3c4aeb759c7db822b01 Signed-off-by: Huang, Tao --- drivers/cpuquiet/Kconfig | 90 --- drivers/cpuquiet/Makefile | 4 - drivers/cpuquiet/cpuquiet.c | 32 - drivers/cpuquiet/cpuquiet.h | 36 -- drivers/cpuquiet/cpuquiet_attribute.c | 133 ----- drivers/cpuquiet/driver.c | 215 ------- drivers/cpuquiet/governor.c | 116 ---- drivers/cpuquiet/governors/Makefile | 5 - drivers/cpuquiet/governors/balanced.c | 563 ------------------ drivers/cpuquiet/governors/runnable_threads.c | 379 ------------ drivers/cpuquiet/governors/userspace.c | 62 -- drivers/cpuquiet/rockchip-cpuquiet.c | 551 ----------------- drivers/cpuquiet/sysfs.c | 291 --------- include/linux/cpuquiet.h | 109 ---- 14 files changed, 2586 deletions(-) delete mode 100644 drivers/cpuquiet/Kconfig delete mode 100644 drivers/cpuquiet/Makefile delete mode 100644 drivers/cpuquiet/cpuquiet.c delete mode 100644 drivers/cpuquiet/cpuquiet.h delete mode 100644 drivers/cpuquiet/cpuquiet_attribute.c delete mode 100644 drivers/cpuquiet/driver.c delete mode 100644 drivers/cpuquiet/governor.c delete mode 100644 drivers/cpuquiet/governors/Makefile delete mode 100644 drivers/cpuquiet/governors/balanced.c delete mode 100644 drivers/cpuquiet/governors/runnable_threads.c delete mode 100644 drivers/cpuquiet/governors/userspace.c delete mode 100644 drivers/cpuquiet/rockchip-cpuquiet.c delete mode 100644 drivers/cpuquiet/sysfs.c delete mode 100644 include/linux/cpuquiet.h diff --git a/drivers/cpuquiet/Kconfig b/drivers/cpuquiet/Kconfig deleted file mode 100644 index a1e6c59886be..000000000000 --- a/drivers/cpuquiet/Kconfig +++ /dev/null @@ -1,90 +0,0 @@ -menu "CPUQUIET Framework" - -config CPUQUIET_FRAMEWORK - bool "Cpuquiet framework" - help - Cpuquiet implements pluggable policies for forcing cpu cores into a - quiescent state. Appropriate policies will save power without hurting - performance. - - -if CPUQUIET_FRAMEWORK - -config CPUQUIET_STATS - bool "per CPU statistics" - default n - help - Enable up/down count and total time plugged statistics per CPU. These - depend on correct driver input for reliability - - If in doubt say N. - -config CPUQUIET_GOVERNOR_USERSPACE - bool "userspace" - default y - help - Manual control of the number of CPUs online. - This governor allows userspace to control the number of online CPUs. - - If in doubt say Y. - -config CPUQUIET_GOVERNOR_BALANCED - bool "balanced" - default y - depends on CPU_FREQ - help - Scale the number of CPUs online depending on the CPU load. - This governor will scale the number of CPUs online depending on the - CPU load and the number of runnable threads. - - If in doubt say Y. - -config CPUQUIET_GOVERNOR_RUNNABLE - bool "runnable threads" - default y - help - Scale the number of CPUs online depending on the number of runnable - threads. This governor will scale the number of CPUs online depending - on the number of runnable threads. - - If in doubt say Y. - -choice - prompt "Default CPUQuiet governor" - default CPUQUIET_DEFAULT_GOV_USERSPACE - help - This option sets which CPUQuiet governor shall be loaded at - startup. If in doubt, select 'userspace'. - -config CPUQUIET_DEFAULT_GOV_USERSPACE - bool "userspace" - select CPUQUIET_GOVERNOR_USERSPACE - help - Use the CPUQuiet governor 'userspace' as default. - -config CPUQUIET_DEFAULT_GOV_BALANCED - bool "balanced" - select CPUQUIET_GOVERNOR_BALANCED - depends on CPU_FREQ - help - Use the CPUQuiet governor 'balanced' as default. - -config CPUQUIET_DEFAULT_GOV_RUNNABLE - bool "runnable threads" - select CPUQUIET_GOVERNOR_RUNNABLE - help - Use the CPUQuiet governor 'runnable threads' as default. - -endchoice - -config ROCKCHIP_CPUQUIET - bool "CPUQuiet driver for Rockchip CPUs" - depends on ARCH_ROCKCHIP - default y - help - This enables the CPUQuiet driver for Rockchip CPUs. - - If in doubt, say N. - -endif -endmenu diff --git a/drivers/cpuquiet/Makefile b/drivers/cpuquiet/Makefile deleted file mode 100644 index 68641dc458b4..000000000000 --- a/drivers/cpuquiet/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -GCOV_PROFILE := y - -obj-$(CONFIG_CPUQUIET_FRAMEWORK) += cpuquiet.o driver.o sysfs.o cpuquiet_attribute.o governor.o governors/ -obj-$(CONFIG_ROCKCHIP_CPUQUIET) += rockchip-cpuquiet.o diff --git a/drivers/cpuquiet/cpuquiet.c b/drivers/cpuquiet/cpuquiet.c deleted file mode 100644 index a0f36c32bb05..000000000000 --- a/drivers/cpuquiet/cpuquiet.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include "cpuquiet.h" - -DEFINE_MUTEX(cpuquiet_lock); - -static int __init cpuquiet_init(void) -{ - return cpuquiet_add_interface(cpu_subsys.dev_root); -} - -core_initcall(cpuquiet_init); diff --git a/drivers/cpuquiet/cpuquiet.h b/drivers/cpuquiet/cpuquiet.h deleted file mode 100644 index bf5af94cdd7d..000000000000 --- a/drivers/cpuquiet/cpuquiet.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef __DRIVER_CPUQUIET_H -#define __DRIVER_CPUQUIET_H - -#include - -extern struct mutex cpuquiet_lock; -extern struct cpuquiet_governor *cpuquiet_curr_governor; -extern struct list_head cpuquiet_governors; -int cpuquiet_add_interface(struct device *dev); -struct cpuquiet_governor *cpuquiet_find_governor(const char *str); -int cpuquiet_switch_governor(struct cpuquiet_governor *gov); -struct cpuquiet_governor *cpuquiet_get_first_governor(void); -struct cpuquiet_driver *cpuquiet_get_driver(void); -void cpuquiet_add_dev(struct device *dev, unsigned int cpu); -void cpuquiet_remove_dev(unsigned int cpu); -int cpuquiet_cpu_kobject_init(struct kobject *kobj, struct kobj_type *type, - char *name, int cpu); -#endif diff --git a/drivers/cpuquiet/cpuquiet_attribute.c b/drivers/cpuquiet/cpuquiet_attribute.c deleted file mode 100644 index 9f1aa430149d..000000000000 --- a/drivers/cpuquiet/cpuquiet_attribute.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - -ssize_t show_int_attribute(struct cpuquiet_attribute *cattr, char *buf) -{ - return sprintf(buf, "%d\n", *((int *)cattr->param)); -} - -ssize_t store_int_attribute(struct cpuquiet_attribute *cattr, - const char *buf, size_t count) -{ - int err, val; - - err = kstrtoint(buf, 0, &val); - if (err < 0) - return err; - - *((int *)(cattr->param)) = val; - - if (cattr->store_callback) - cattr->store_callback(cattr); - - return count; -} - -ssize_t show_bool_attribute(struct cpuquiet_attribute *cattr, char *buf) -{ - return sprintf(buf, "%d\n", *((bool *)cattr->param)); -} - -ssize_t store_bool_attribute(struct cpuquiet_attribute *cattr, - const char *buf, size_t count) -{ - int err, val; - - err = kstrtoint(buf, 0, &val); - if (err < 0) - return err; - - if (val < 0 || val > 1) - return -EINVAL; - - *((bool *)(cattr->param)) = val; - - if (cattr->store_callback) - cattr->store_callback(cattr); - - return count; -} - -ssize_t show_uint_attribute(struct cpuquiet_attribute *cattr, char *buf) -{ - return sprintf(buf, "%u\n", *((unsigned int *)cattr->param)); -} - -ssize_t store_uint_attribute(struct cpuquiet_attribute *cattr, - const char *buf, size_t count) -{ - int err; - unsigned int val; - - err = kstrtouint(buf, 0, &val); - if (err < 0) - return err; - - *((unsigned int *)(cattr->param)) = val; - - if (cattr->store_callback) - cattr->store_callback(cattr); - - return count; -} - -ssize_t store_ulong_attribute(struct cpuquiet_attribute *cattr, - const char *buf, size_t count) -{ - int err; - unsigned long val; - - err = kstrtoul(buf, 0, &val); - if (err < 0) - return err; - - *((unsigned long *)(cattr->param)) = val; - - if (cattr->store_callback) - cattr->store_callback(cattr); - - return count; -} - -ssize_t show_ulong_attribute(struct cpuquiet_attribute *cattr, - char *buf) -{ - return sprintf(buf, "%lu\n", *((unsigned long *)cattr->param)); -} - -ssize_t cpuquiet_auto_sysfs_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t count) -{ - struct cpuquiet_attribute *cattr = - container_of(attr, struct cpuquiet_attribute, attr); - - if (cattr->store) - return cattr->store(cattr, buf, count); - - return -EINVAL; -} - -ssize_t cpuquiet_auto_sysfs_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct cpuquiet_attribute *cattr = - container_of(attr, struct cpuquiet_attribute, attr); - - return cattr->show(cattr, buf); -} diff --git a/drivers/cpuquiet/driver.c b/drivers/cpuquiet/driver.c deleted file mode 100644 index 097d2e36b79d..000000000000 --- a/drivers/cpuquiet/driver.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2012-2013 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "cpuquiet.h" - -static struct cpuquiet_driver *cpuquiet_curr_driver; - -#ifdef CONFIG_CPUQUIET_STATS -struct cpuquiet_cpu_stat { - cputime64_t time_up_total; - u64 last_update; - unsigned int up_down_count; - struct kobject cpu_kobject; -}; - -struct cpuquiet_cpu_stat *stats; - -struct cpu_attribute { - struct attribute attr; - enum { up_down_count, time_up_total } type; -}; - -#define CPU_ATTRIBUTE(_name) \ - static struct cpu_attribute _name ## _attr = { \ - .attr = {.name = __stringify(_name), .mode = 0444 }, \ - .type = _name, \ -} - -CPU_ATTRIBUTE(up_down_count); -CPU_ATTRIBUTE(time_up_total); - -static struct attribute *cpu_attributes[] = { - &up_down_count_attr.attr, - &time_up_total_attr.attr, - NULL, -}; - -static void stats_update(struct cpuquiet_cpu_stat *stat, bool up) -{ - u64 cur_jiffies = get_jiffies_64(); - bool was_up = stat->up_down_count & 0x1; - - if (was_up) - stat->time_up_total += cur_jiffies - stat->last_update; - - if (was_up != up) - stat->up_down_count++; - - stat->last_update = cur_jiffies; -} - -static ssize_t stats_sysfs_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct cpu_attribute *cattr = - container_of(attr, struct cpu_attribute, attr); - struct cpuquiet_cpu_stat *stat = - container_of(kobj, struct cpuquiet_cpu_stat, cpu_kobject); - ssize_t len = 0; - bool was_up = stat->up_down_count & 0x1; - - stats_update(stat, was_up); - - switch (cattr->type) { - case up_down_count: - len = sprintf(buf, "%u\n", stat->up_down_count); - break; - case time_up_total: - len = sprintf(buf, "%llu\n", stat->time_up_total); - break; - } - - return len; -} - -static const struct sysfs_ops stats_sysfs_ops = { - .show = stats_sysfs_show, -}; - -static struct kobj_type ktype_cpu_stats = { - .sysfs_ops = &stats_sysfs_ops, - .default_attrs = cpu_attributes, -}; -#endif - -int cpuquiet_quiesence_cpu(unsigned int cpunumber, bool sync) -{ - int err = -EPERM; - - if (cpuquiet_curr_driver && cpuquiet_curr_driver->quiesence_cpu) - err = cpuquiet_curr_driver->quiesence_cpu(cpunumber, sync); - -#ifdef CONFIG_CPUQUIET_STATS - if (!err) - stats_update(stats + cpunumber, 0); -#endif - - return err; -} -EXPORT_SYMBOL(cpuquiet_quiesence_cpu); - -int cpuquiet_wake_cpu(unsigned int cpunumber, bool sync) -{ - int err = -EPERM; - - if (cpuquiet_curr_driver && cpuquiet_curr_driver->wake_cpu) - err = cpuquiet_curr_driver->wake_cpu(cpunumber, sync); - -#ifdef CONFIG_CPUQUIET_STATS - if (!err) - stats_update(stats + cpunumber, 1); -#endif - - return err; -} -EXPORT_SYMBOL(cpuquiet_wake_cpu); - -int cpuquiet_register_driver(struct cpuquiet_driver *drv) -{ - int err = -EBUSY; - unsigned int cpu; - struct device *dev; - - if (!drv) - return -EINVAL; - -#ifdef CONFIG_CPUQUIET_STATS - stats = kzalloc(nr_cpu_ids * sizeof(*stats), GFP_KERNEL); - if (!stats) - return -ENOMEM; -#endif - - for_each_possible_cpu(cpu) { -#ifdef CONFIG_CPUQUIET_STATS - u64 cur_jiffies = get_jiffies_64(); - stats[cpu].last_update = cur_jiffies; - if (cpu_online(cpu)) - stats[cpu].up_down_count = 1; -#endif - dev = get_cpu_device(cpu); - if (dev) { - cpuquiet_add_dev(dev, cpu); -#ifdef CONFIG_CPUQUIET_STATS - cpuquiet_cpu_kobject_init(&stats[cpu].cpu_kobject, - &ktype_cpu_stats, "stats", cpu); -#endif - } - } - - mutex_lock(&cpuquiet_lock); - if (!cpuquiet_curr_driver) { - err = 0; - cpuquiet_curr_driver = drv; - cpuquiet_switch_governor(cpuquiet_get_first_governor()); - } - mutex_unlock(&cpuquiet_lock); - - return err; -} -EXPORT_SYMBOL(cpuquiet_register_driver); - -struct cpuquiet_driver *cpuquiet_get_driver(void) -{ - return cpuquiet_curr_driver; -} - -void cpuquiet_unregister_driver(struct cpuquiet_driver *drv) -{ - unsigned int cpu; - - if (drv != cpuquiet_curr_driver) { - WARN(1, "invalid cpuquiet_unregister_driver(%s)\n", - drv->name); - return; - } - - mutex_lock(&cpuquiet_lock); - - /* Stop current governor first */ - cpuquiet_switch_governor(NULL); - cpuquiet_curr_driver = NULL; - - for_each_possible_cpu(cpu) { -#ifdef CONFIG_CPUQUIET_STATS - kobject_put(&stats[cpu].cpu_kobject); -#endif - cpuquiet_remove_dev(cpu); - } - - mutex_unlock(&cpuquiet_lock); -} -EXPORT_SYMBOL(cpuquiet_unregister_driver); diff --git a/drivers/cpuquiet/governor.c b/drivers/cpuquiet/governor.c deleted file mode 100644 index 176ba3bd705f..000000000000 --- a/drivers/cpuquiet/governor.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include - -#include "cpuquiet.h" - -LIST_HEAD(cpuquiet_governors); -struct cpuquiet_governor *cpuquiet_curr_governor; - -struct cpuquiet_governor *cpuquiet_get_first_governor(void) -{ - if (!list_empty(&cpuquiet_governors)) - return list_entry(cpuquiet_governors.next, - struct cpuquiet_governor, - governor_list); - else - return NULL; -} - -struct cpuquiet_governor *cpuquiet_find_governor(const char *str) -{ - struct cpuquiet_governor *gov; - - list_for_each_entry(gov, &cpuquiet_governors, governor_list) - if (!strnicmp(str, gov->name, CPUQUIET_NAME_LEN)) - return gov; - - return NULL; -} - -int cpuquiet_switch_governor(struct cpuquiet_governor *gov) -{ - int err = 0; - - if (cpuquiet_curr_governor) { - if (cpuquiet_curr_governor->stop) - cpuquiet_curr_governor->stop(); - module_put(cpuquiet_curr_governor->owner); - } - - cpuquiet_curr_governor = gov; - - if (gov) { - if (!try_module_get(cpuquiet_curr_governor->owner)) - return -EINVAL; - if (gov->start) - err = gov->start(); - if (!err) - cpuquiet_curr_governor = gov; - } - - return err; -} - -int cpuquiet_register_governor(struct cpuquiet_governor *gov) -{ - int ret = -EEXIST; - - if (!gov) - return -EINVAL; - - mutex_lock(&cpuquiet_lock); - if (cpuquiet_find_governor(gov->name) == NULL) { - ret = 0; - list_add_tail(&gov->governor_list, &cpuquiet_governors); - if (!cpuquiet_curr_governor && cpuquiet_get_driver()) - cpuquiet_switch_governor(gov); - } - mutex_unlock(&cpuquiet_lock); - - return ret; -} - -void cpuquiet_unregister_governor(struct cpuquiet_governor *gov) -{ - if (!gov) - return; - - mutex_lock(&cpuquiet_lock); - if (cpuquiet_curr_governor == gov) - cpuquiet_switch_governor(NULL); - list_del(&gov->governor_list); - mutex_unlock(&cpuquiet_lock); -} - -void cpuquiet_device_busy(void) -{ - if (cpuquiet_curr_governor && - cpuquiet_curr_governor->device_busy_notification) - cpuquiet_curr_governor->device_busy_notification(); -} - -void cpuquiet_device_free(void) -{ - if (cpuquiet_curr_governor && - cpuquiet_curr_governor->device_free_notification) - cpuquiet_curr_governor->device_free_notification(); -} diff --git a/drivers/cpuquiet/governors/Makefile b/drivers/cpuquiet/governors/Makefile deleted file mode 100644 index 49f9a948869f..000000000000 --- a/drivers/cpuquiet/governors/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -GCOV_PROFILE := y - -obj-$(CONFIG_CPUQUIET_GOVERNOR_USERSPACE) += userspace.o -obj-$(CONFIG_CPUQUIET_GOVERNOR_BALANCED) += balanced.o -obj-$(CONFIG_CPUQUIET_GOVERNOR_RUNNABLE) += runnable_threads.o diff --git a/drivers/cpuquiet/governors/balanced.c b/drivers/cpuquiet/governors/balanced.c deleted file mode 100644 index c5f3f9934b62..000000000000 --- a/drivers/cpuquiet/governors/balanced.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CPUNAMELEN 8 - -typedef enum { - CPU_SPEED_BALANCED, - CPU_SPEED_BIASED, - CPU_SPEED_SKEWED, -} CPU_SPEED_BALANCE; - -typedef enum { - IDLE, - DOWN, - UP, -} BALANCED_STATE; - -struct idle_info { - u64 idle_last; - u64 last_timestamp; - u64 idle_current; - u64 timestamp; -}; - -static DEFINE_PER_CPU(struct idle_info, idleinfo); -static DEFINE_PER_CPU(unsigned int, cpu_load); - -static struct timer_list load_timer; -static bool load_timer_active; - -/* configurable parameters */ -static unsigned int balance_level = 60; -static unsigned int idle_bottom_freq; -static unsigned int idle_top_freq; -static unsigned long up_delay; -static unsigned long down_delay; -static unsigned long last_change_time; -static unsigned int load_sample_rate = 20; /* msec */ -static struct workqueue_struct *balanced_wq; -static struct delayed_work balanced_work; -static BALANCED_STATE balanced_state; -static struct kobject *balanced_kobject; - -static void calculate_load_timer(unsigned long data) -{ - int i; - u64 idle_time, elapsed_time; - - if (!load_timer_active) - return; - - for_each_online_cpu(i) { - struct idle_info *iinfo = &per_cpu(idleinfo, i); - unsigned int *load = &per_cpu(cpu_load, i); - - iinfo->idle_last = iinfo->idle_current; - iinfo->last_timestamp = iinfo->timestamp; - iinfo->idle_current = - get_cpu_idle_time_us(i, &iinfo->timestamp); - elapsed_time = iinfo->timestamp - iinfo->last_timestamp; - - idle_time = iinfo->idle_current - iinfo->idle_last; - idle_time *= 100; - do_div(idle_time, elapsed_time); - *load = 100 - idle_time; - } - mod_timer(&load_timer, jiffies + msecs_to_jiffies(load_sample_rate)); -} - -static void start_load_timer(void) -{ - int i; - - if (load_timer_active) - return; - - load_timer_active = true; - - for_each_online_cpu(i) { - struct idle_info *iinfo = &per_cpu(idleinfo, i); - - iinfo->idle_current = - get_cpu_idle_time_us(i, &iinfo->timestamp); - } - mod_timer(&load_timer, jiffies + msecs_to_jiffies(100)); -} - -static void stop_load_timer(void) -{ - if (!load_timer_active) - return; - - load_timer_active = false; - del_timer(&load_timer); -} - -static unsigned int get_slowest_cpu_n(void) -{ - unsigned int cpu = nr_cpu_ids; - unsigned long minload = ULONG_MAX; - int i; - - for_each_online_cpu(i) { - unsigned int *load = &per_cpu(cpu_load, i); - - if ((i > 0) && (minload > *load)) { - cpu = i; - minload = *load; - } - } - - return cpu; -} - -static unsigned int cpu_highest_speed(void) -{ - unsigned int maxload = 0; - int i; - - for_each_online_cpu(i) { - unsigned int *load = &per_cpu(cpu_load, i); - - maxload = max(maxload, *load); - } - - return maxload; -} - -static unsigned int count_slow_cpus(unsigned int limit) -{ - unsigned int cnt = 0; - int i; - - for_each_online_cpu(i) { - unsigned int *load = &per_cpu(cpu_load, i); - - if (*load <= limit) - cnt++; - } - - return cnt; -} - -#define NR_FSHIFT 2 - -static unsigned int rt_profile_sel; -static unsigned int core_bias; //Dummy variable exposed to userspace - -static unsigned int rt_profile_default[] = { -/* 1, 2, 3, 4 - on-line cpus target */ - 5, 9, 10, UINT_MAX -}; - -static unsigned int rt_profile_1[] = { -/* 1, 2, 3, 4 - on-line cpus target */ - 8, 9, 10, UINT_MAX -}; - -static unsigned int rt_profile_2[] = { -/* 1, 2, 3, 4 - on-line cpus target */ - 5, 13, 14, UINT_MAX -}; - -static unsigned int rt_profile_disable[] = { -/* 1, 2, 3, 4 - on-line cpus target */ - 0, 0, 0, UINT_MAX -}; - -static unsigned int *rt_profiles[] = { - rt_profile_default, - rt_profile_1, - rt_profile_2, - rt_profile_disable -}; - -static unsigned int nr_run_hysteresis = 2; /* 0.5 thread */ -static unsigned int nr_run_last; - -struct runnables_avg_sample { - u64 previous_integral; - unsigned int avg; - bool integral_sampled; - u64 prev_timestamp; -}; - -static DEFINE_PER_CPU(struct runnables_avg_sample, avg_nr_sample); - -static unsigned int get_avg_nr_runnables(void) -{ - unsigned int i, sum = 0; - struct runnables_avg_sample *sample; - u64 integral, old_integral, delta_integral, delta_time, cur_time; - - for_each_online_cpu(i) { - sample = &per_cpu(avg_nr_sample, i); - integral = nr_running_integral(i); - old_integral = sample->previous_integral; - sample->previous_integral = integral; - cur_time = ktime_to_ns(ktime_get()); - delta_time = cur_time - sample->prev_timestamp; - sample->prev_timestamp = cur_time; - - if (!sample->integral_sampled) { - sample->integral_sampled = true; - /* First sample to initialize prev_integral, skip - * avg calculation - */ - continue; - } - - if (integral < old_integral) { - /* Overflow */ - delta_integral = (ULLONG_MAX - old_integral) + integral; - } else { - delta_integral = integral - old_integral; - } - - /* Calculate average for the previous sample window */ - do_div(delta_integral, delta_time); - sample->avg = delta_integral; - sum += sample->avg; - } - - return sum; -} - -static CPU_SPEED_BALANCE balanced_speed_balance(void) -{ - unsigned long highest_speed = cpu_highest_speed(); - unsigned long balanced_speed = highest_speed * balance_level / 100; - unsigned long skewed_speed = balanced_speed / 2; - unsigned int nr_cpus = num_online_cpus(); - unsigned int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS) ? : 4; - unsigned int avg_nr_run = get_avg_nr_runnables(); - unsigned int nr_run; - unsigned int *current_profile = rt_profiles[rt_profile_sel]; - - /* balanced: freq targets for all CPUs are above 50% of highest speed - biased: freq target for at least one CPU is below 50% threshold - skewed: freq targets for at least 2 CPUs are below 25% threshold */ - for (nr_run = 1; nr_run < ARRAY_SIZE(rt_profile_default); nr_run++) { - unsigned int nr_threshold = current_profile[nr_run - 1]; - if (nr_run_last <= nr_run) - nr_threshold += nr_run_hysteresis; - if (avg_nr_run <= (nr_threshold << (FSHIFT - NR_FSHIFT))) - break; - } - nr_run_last = nr_run; - - if (count_slow_cpus(skewed_speed) >= 2 || nr_cpus > max_cpus || - nr_run < nr_cpus) - return CPU_SPEED_SKEWED; - - if (count_slow_cpus(balanced_speed) >= 1 || nr_cpus == max_cpus || - nr_run <= nr_cpus) - return CPU_SPEED_BIASED; - - return CPU_SPEED_BALANCED; -} - -static void balanced_work_func(struct work_struct *work) -{ - bool up = false; - unsigned int cpu = nr_cpu_ids; - unsigned long now = jiffies; - - CPU_SPEED_BALANCE balance; - - switch (balanced_state) { - case IDLE: - break; - case DOWN: - cpu = get_slowest_cpu_n(); - if (cpu < nr_cpu_ids) { - up = false; - queue_delayed_work(balanced_wq, - &balanced_work, up_delay); - } else - stop_load_timer(); - break; - case UP: - balance = balanced_speed_balance(); - switch (balance) { - - /* cpu speed is up and balanced - one more on-line */ - case CPU_SPEED_BALANCED: - cpu = cpumask_next_zero(0, cpu_online_mask); - if (cpu < nr_cpu_ids) - up = true; - break; - /* cpu speed is up, but skewed - remove one core */ - case CPU_SPEED_SKEWED: - cpu = get_slowest_cpu_n(); - if (cpu < nr_cpu_ids) - up = false; - break; - /* cpu speed is up, but under-utilized - do nothing */ - case CPU_SPEED_BIASED: - default: - break; - } - queue_delayed_work( - balanced_wq, &balanced_work, up_delay); - break; - default: - pr_err("%s: invalid cpuquiet balanced governor state %d\n", - __func__, balanced_state); - } - - if (!up && ((now - last_change_time) < down_delay)) - cpu = nr_cpu_ids; - - if (cpu < nr_cpu_ids) { - last_change_time = now; - if (up) - cpuquiet_wake_cpu(cpu, false); - else - cpuquiet_quiesence_cpu(cpu, false); - } -} - -static int balanced_cpufreq_transition(struct notifier_block *nb, - unsigned long state, void *data) -{ - struct cpufreq_freqs *freqs = data; - unsigned long cpu_freq; - - if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) { - cpu_freq = freqs->new; - - switch (balanced_state) { - case IDLE: - if (cpu_freq >= idle_top_freq) { - balanced_state = UP; - queue_delayed_work( - balanced_wq, &balanced_work, up_delay); - start_load_timer(); - } else if (cpu_freq <= idle_bottom_freq) { - balanced_state = DOWN; - queue_delayed_work( - balanced_wq, &balanced_work, - down_delay); - start_load_timer(); - } - break; - case DOWN: - if (cpu_freq >= idle_top_freq) { - balanced_state = UP; - queue_delayed_work( - balanced_wq, &balanced_work, up_delay); - start_load_timer(); - } - break; - case UP: - if (cpu_freq <= idle_bottom_freq) { - balanced_state = DOWN; - queue_delayed_work(balanced_wq, - &balanced_work, up_delay); - start_load_timer(); - } - break; - default: - pr_err("%s: invalid cpuquiet balanced governor " - "state %d\n", __func__, balanced_state); - } - } - - return NOTIFY_OK; -} - -static struct notifier_block balanced_cpufreq_nb = { - .notifier_call = balanced_cpufreq_transition, -}; - -static void delay_callback(struct cpuquiet_attribute *attr) -{ - unsigned long val; - - if (attr) { - val = (*((unsigned long *)(attr->param))); - (*((unsigned long *)(attr->param))) = msecs_to_jiffies(val); - } -} - -static void core_bias_callback (struct cpuquiet_attribute *attr) -{ - unsigned long val; - if (attr) { - val = (*((unsigned int*)(attr->param))); - if (val < ARRAY_SIZE(rt_profiles)) { - rt_profile_sel = val; - } - else { //Revert the change due to invalid range - core_bias = rt_profile_sel; - } - } -} - -CPQ_BASIC_ATTRIBUTE(balance_level, 0644, uint); -CPQ_BASIC_ATTRIBUTE(idle_bottom_freq, 0644, uint); -CPQ_BASIC_ATTRIBUTE(idle_top_freq, 0644, uint); -CPQ_BASIC_ATTRIBUTE(load_sample_rate, 0644, uint); -CPQ_ATTRIBUTE(core_bias, 0644, uint, core_bias_callback); -CPQ_ATTRIBUTE(up_delay, 0644, ulong, delay_callback); -CPQ_ATTRIBUTE(down_delay, 0644, ulong, delay_callback); - -static struct attribute *balanced_attributes[] = { - &balance_level_attr.attr, - &idle_bottom_freq_attr.attr, - &idle_top_freq_attr.attr, - &up_delay_attr.attr, - &down_delay_attr.attr, - &load_sample_rate_attr.attr, - &core_bias_attr.attr, - NULL, -}; - -static const struct sysfs_ops balanced_sysfs_ops = { - .show = cpuquiet_auto_sysfs_show, - .store = cpuquiet_auto_sysfs_store, -}; - -static struct kobj_type ktype_balanced = { - .sysfs_ops = &balanced_sysfs_ops, - .default_attrs = balanced_attributes, -}; - -static int balanced_sysfs(void) -{ - int err; - - balanced_kobject = kzalloc(sizeof(*balanced_kobject), - GFP_KERNEL); - - if (!balanced_kobject) - return -ENOMEM; - - err = cpuquiet_kobject_init(balanced_kobject, &ktype_balanced, - "balanced"); - - if (err) - kfree(balanced_kobject); - - return err; -} - -static void balanced_stop(void) -{ - /* - first unregister the notifiers. This ensures the governor state - can't be modified by a cpufreq transition - */ - cpufreq_unregister_notifier(&balanced_cpufreq_nb, - CPUFREQ_TRANSITION_NOTIFIER); - - /* now we can force the governor to be idle */ - balanced_state = IDLE; - cancel_delayed_work_sync(&balanced_work); - destroy_workqueue(balanced_wq); - del_timer(&load_timer); - - kobject_put(balanced_kobject); -} - -static int balanced_start(void) -{ - int err, count; - struct cpufreq_frequency_table *table; - struct cpufreq_freqs initial_freq; - - err = balanced_sysfs(); - if (err) - return err; - - balanced_wq = alloc_workqueue("cpuquiet-balanced", - WQ_UNBOUND | WQ_FREEZABLE, 1); - if (!balanced_wq) - return -ENOMEM; - - INIT_DELAYED_WORK(&balanced_work, balanced_work_func); - - up_delay = msecs_to_jiffies(100); - down_delay = msecs_to_jiffies(2000); - - table = cpufreq_frequency_get_table(0); - if (!table) - return -EINVAL; - - for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++); - - if (count < 4) - return -EINVAL; - - idle_top_freq = table[(count / 2) - 1].frequency; - idle_bottom_freq = table[(count / 2) - 2].frequency; - - cpufreq_register_notifier(&balanced_cpufreq_nb, - CPUFREQ_TRANSITION_NOTIFIER); - - init_timer(&load_timer); - load_timer.function = calculate_load_timer; - - /*FIXME: Kick start the state machine by faking a freq notification*/ - initial_freq.new = cpufreq_get(0); - if (initial_freq.new != 0) - balanced_cpufreq_transition(NULL, CPUFREQ_RESUMECHANGE, - &initial_freq); - return 0; -} - -struct cpuquiet_governor balanced_governor = { - .name = "balanced", - .start = balanced_start, - .stop = balanced_stop, - .owner = THIS_MODULE, -}; - -static int __init init_balanced(void) -{ - return cpuquiet_register_governor(&balanced_governor); -} - -static void __exit exit_balanced(void) -{ - cpuquiet_unregister_governor(&balanced_governor); -} - -MODULE_LICENSE("GPL"); -#ifdef CONFIG_CPUQUIET_DEFAULT_GOV_BALANCED -fs_initcall(init_balanced); -#else -module_init(init_balanced); -#endif -module_exit(exit_balanced); - diff --git a/drivers/cpuquiet/governors/runnable_threads.c b/drivers/cpuquiet/governors/runnable_threads.c deleted file mode 100644 index f9d6d560cb35..000000000000 --- a/drivers/cpuquiet/governors/runnable_threads.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2012-2014 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef enum { - DISABLED, - IDLE, - RUNNING, -} RUNNABLES_STATE; - -static struct work_struct runnables_work; -static struct kobject *runnables_kobject; -static struct timer_list runnables_timer; - -static RUNNABLES_STATE runnables_state; -/* configurable parameters */ -static unsigned int sample_rate = 20; /* msec */ - -#define NR_FSHIFT_EXP 3 -#define NR_FSHIFT (1 << NR_FSHIFT_EXP) -/* avg run threads * 8 (e.g., 11 = 1.375 threads) */ -static unsigned int default_thresholds[] = { - 10, 18, 20, UINT_MAX -}; - -static unsigned int nr_run_last; -static unsigned int nr_run_hysteresis = 2; /* 1 / 2 thread */ -static unsigned int default_threshold_level = 4; /* 1 / 4 thread */ -static unsigned int nr_run_thresholds[NR_CPUS]; - -DEFINE_MUTEX(runnables_lock); - -struct runnables_avg_sample { - u64 previous_integral; - unsigned int avg; - bool integral_sampled; - u64 prev_timestamp; -}; - -static DEFINE_PER_CPU(struct runnables_avg_sample, avg_nr_sample); - -/* EXP = alpha in the exponential moving average. - * Alpha = e ^ (-sample_rate / window_size) * FIXED_1 - * Calculated for sample_rate of 20ms, window size of 100ms - */ -#define EXP 1677 - -static unsigned int get_avg_nr_runnables(void) -{ - unsigned int i, sum = 0; - static unsigned int avg; - struct runnables_avg_sample *sample; - u64 integral, old_integral, delta_integral, delta_time, cur_time; - - for_each_online_cpu(i) { - sample = &per_cpu(avg_nr_sample, i); - integral = nr_running_integral(i); - old_integral = sample->previous_integral; - sample->previous_integral = integral; - cur_time = ktime_to_ns(ktime_get()); - delta_time = cur_time - sample->prev_timestamp; - sample->prev_timestamp = cur_time; - - if (!sample->integral_sampled) { - sample->integral_sampled = true; - /* First sample to initialize prev_integral, skip - * avg calculation - */ - continue; - } - - if (integral < old_integral) { - /* Overflow */ - delta_integral = (ULLONG_MAX - old_integral) + integral; - } else { - delta_integral = integral - old_integral; - } - - /* Calculate average for the previous sample window */ - do_div(delta_integral, delta_time); - sample->avg = delta_integral; - sum += sample->avg; - } - - /* Exponential moving average - * Avgn = Avgn-1 * alpha + new_avg * (1 - alpha) - */ - avg *= EXP; - avg += sum * (FIXED_1 - EXP); - avg >>= FSHIFT; - - return avg; -} - -static int get_action(unsigned int nr_run) -{ - unsigned int nr_cpus = num_online_cpus(); - int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS) ? : 4; - int min_cpus = pm_qos_request(PM_QOS_MIN_ONLINE_CPUS); - - if ((nr_cpus > max_cpus || nr_run < nr_cpus) && nr_cpus >= min_cpus) - return -1; - - if (nr_cpus < min_cpus || nr_run > nr_cpus) - return 1; - - return 0; -} - -static void runnables_avg_sampler(unsigned long data) -{ - unsigned int nr_run, avg_nr_run; - int action; - - rmb(); - if (runnables_state != RUNNING) - return; - - avg_nr_run = get_avg_nr_runnables(); - mod_timer(&runnables_timer, jiffies + msecs_to_jiffies(sample_rate)); - - for (nr_run = 1; nr_run < ARRAY_SIZE(nr_run_thresholds); nr_run++) { - unsigned int nr_threshold = nr_run_thresholds[nr_run - 1]; - if (nr_run_last <= nr_run) - nr_threshold += NR_FSHIFT / nr_run_hysteresis; - if (avg_nr_run <= (nr_threshold << (FSHIFT - NR_FSHIFT_EXP))) - break; - } - - nr_run_last = nr_run; - - action = get_action(nr_run); - if (action != 0) { - wmb(); - schedule_work(&runnables_work); - } -} - -static unsigned int get_lightest_loaded_cpu_n(void) -{ - unsigned long min_avg_runnables = ULONG_MAX; - unsigned int cpu = nr_cpu_ids; - int i; - - for_each_online_cpu(i) { - struct runnables_avg_sample *s = &per_cpu(avg_nr_sample, i); - unsigned int nr_runnables = s->avg; - if (i > 0 && min_avg_runnables > nr_runnables) { - cpu = i; - min_avg_runnables = nr_runnables; - } - } - - return cpu; -} - -static void runnables_work_func(struct work_struct *work) -{ - unsigned int cpu = nr_cpu_ids; - int action; - - if (runnables_state != RUNNING) - return; - - action = get_action(nr_run_last); - if (action > 0) { - cpu = cpumask_next_zero(0, cpu_online_mask); - if (cpu < nr_cpu_ids) - cpuquiet_wake_cpu(cpu, false); - } else if (action < 0) { - cpu = get_lightest_loaded_cpu_n(); - if (cpu < nr_cpu_ids) - cpuquiet_quiesence_cpu(cpu, false); - } -} - -#define MAX_BYTES 100 - -static ssize_t show_thresholds(struct cpuquiet_attribute *attr, char *buf) -{ - char buffer[MAX_BYTES]; - unsigned int i; - int size = 0; - buffer[0] = 0; - for_each_possible_cpu(i) { - if (i == ARRAY_SIZE(nr_run_thresholds) - 1) - break; - if (size >= sizeof(buffer)) - break; - size += snprintf(buffer + size, sizeof(buffer) - size, - "%u->%u core threshold: %u\n", - i + 1, i + 2, nr_run_thresholds[i]); - } - return snprintf(buf, sizeof(buffer), "%s", buffer); -} - -static ssize_t store_thresholds(struct cpuquiet_attribute *attr, - const char *buf, size_t count) -{ - int ret, i = 0; - char *val, *str, input[MAX_BYTES]; - unsigned int thresholds[NR_CPUS]; - - if (!count || count >= MAX_BYTES) - return -EINVAL; - strncpy(input, buf, count); - input[count] = '\0'; - str = input; - memcpy(thresholds, nr_run_thresholds, sizeof(nr_run_thresholds)); - while ((val = strsep(&str, " ")) != NULL) { - if (*val == '\0') - continue; - if (i == ARRAY_SIZE(nr_run_thresholds) - 1) - break; - ret = kstrtouint(val, 10, &thresholds[i]); - if (ret) - return -EINVAL; - i++; - } - - memcpy(nr_run_thresholds, thresholds, sizeof(thresholds)); - return count; -} - -CPQ_BASIC_ATTRIBUTE(sample_rate, 0644, uint); -CPQ_BASIC_ATTRIBUTE(nr_run_hysteresis, 0644, uint); -CPQ_ATTRIBUTE_CUSTOM(nr_run_thresholds, 0644, - show_thresholds, store_thresholds); - -static struct attribute *runnables_attributes[] = { - &sample_rate_attr.attr, - &nr_run_hysteresis_attr.attr, - &nr_run_thresholds_attr.attr, - NULL, -}; - -static const struct sysfs_ops runnables_sysfs_ops = { - .show = cpuquiet_auto_sysfs_show, - .store = cpuquiet_auto_sysfs_store, -}; - -static struct kobj_type ktype_runnables = { - .sysfs_ops = &runnables_sysfs_ops, - .default_attrs = runnables_attributes, -}; - -static int runnables_sysfs(void) -{ - int err; - - runnables_kobject = kzalloc(sizeof(*runnables_kobject), - GFP_KERNEL); - - if (!runnables_kobject) - return -ENOMEM; - - err = cpuquiet_kobject_init(runnables_kobject, &ktype_runnables, - "runnable_threads"); - - if (err) - kfree(runnables_kobject); - - return err; -} - -static void runnables_device_busy(void) -{ - mutex_lock(&runnables_lock); - if (runnables_state == RUNNING) { - runnables_state = IDLE; - del_timer_sync(&runnables_timer); - } - mutex_unlock(&runnables_lock); -} - -static void runnables_device_free(void) -{ - mutex_lock(&runnables_lock); - if (runnables_state == IDLE) { - runnables_state = RUNNING; - mod_timer(&runnables_timer, jiffies + 1); - } - mutex_unlock(&runnables_lock); -} - -static void runnables_stop(void) -{ - mutex_lock(&runnables_lock); - - runnables_state = DISABLED; - del_timer_sync(&runnables_timer); - kobject_put(runnables_kobject); - kfree(runnables_kobject); - - mutex_unlock(&runnables_lock); -} - -static int runnables_start(void) -{ - int err, i; - - err = runnables_sysfs(); - if (err) - return err; - - INIT_WORK(&runnables_work, runnables_work_func); - - init_timer(&runnables_timer); - runnables_timer.function = runnables_avg_sampler; - - for(i = 0; i < ARRAY_SIZE(nr_run_thresholds); ++i) { - if (i == (ARRAY_SIZE(nr_run_thresholds) - 1)) - nr_run_thresholds[i] = UINT_MAX; - else if (i < ARRAY_SIZE(default_thresholds)) - nr_run_thresholds[i] = default_thresholds[i]; - else - nr_run_thresholds[i] = i + 1 + - NR_FSHIFT / default_threshold_level; - } - - mutex_lock(&runnables_lock); - runnables_state = RUNNING; - mutex_unlock(&runnables_lock); - - runnables_avg_sampler(0); - - return 0; -} - -struct cpuquiet_governor runnables_governor = { - .name = "runnable", - .start = runnables_start, - .device_free_notification = runnables_device_free, - .device_busy_notification = runnables_device_busy, - .stop = runnables_stop, - .owner = THIS_MODULE, -}; - -static int __init init_runnables(void) -{ - return cpuquiet_register_governor(&runnables_governor); -} - -static void __exit exit_runnables(void) -{ - cpuquiet_unregister_governor(&runnables_governor); -} - -MODULE_LICENSE("GPL"); -#ifdef CONFIG_CPUQUIET_DEFAULT_GOV_RUNNABLE -fs_initcall(init_runnables); -#else -module_init(init_runnables); -#endif -module_exit(exit_runnables); diff --git a/drivers/cpuquiet/governors/userspace.c b/drivers/cpuquiet/governors/userspace.c deleted file mode 100644 index 12a3d86228ed..000000000000 --- a/drivers/cpuquiet/governors/userspace.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include - -static DEFINE_MUTEX(userspace_mutex); - -static int governor_set(unsigned int cpu, bool active) -{ - int err; - - mutex_lock(&userspace_mutex); - if (active) - err = cpuquiet_wake_cpu(cpu, true); - else - err = cpuquiet_quiesence_cpu(cpu, true); - mutex_unlock(&userspace_mutex); - - return err; -} - -struct cpuquiet_governor userspace_governor = { - .name = "userspace", - .store_active = governor_set, - .owner = THIS_MODULE, -}; - -static int __init init_usermode(void) -{ - return cpuquiet_register_governor(&userspace_governor); -} - -static void __exit exit_usermode(void) -{ - cpuquiet_unregister_governor(&userspace_governor); -} - -MODULE_LICENSE("GPL"); -#ifdef CONFIG_CPUQUIET_DEFAULT_GOV_USERSPACE -fs_initcall(init_usermode); -#else -module_init(init_usermode); -#endif -module_exit(exit_usermode); diff --git a/drivers/cpuquiet/rockchip-cpuquiet.c b/drivers/cpuquiet/rockchip-cpuquiet.c deleted file mode 100644 index 76845b629d91..000000000000 --- a/drivers/cpuquiet/rockchip-cpuquiet.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Cpuquiet driver for Rockchip SoCs - * - * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define INITIAL_STATE CPQ_DISABLED -#define HOTPLUG_DELAY_MS 100 - -static DEFINE_MUTEX(rockchip_cpuquiet_lock); -static DEFINE_MUTEX(rockchip_cpq_lock_stats); - -static struct workqueue_struct *cpuquiet_wq; -static struct work_struct cpuquiet_work; - -static wait_queue_head_t wait_enable; -static wait_queue_head_t wait_cpu; - -static bool enable; -static unsigned long hotplug_timeout_jiffies; - -static struct cpumask cpumask_online_requests; -static struct cpumask cpumask_offline_requests; - -enum { - CPQ_DISABLED = 0, - CPQ_ENABLED, - CPQ_IDLE, -}; - -static int cpq_target_state; - -static int cpq_state; - -static struct { - cputime64_t time_up_total; - u64 last_update; - unsigned int up_down_count; -} hp_stats[CONFIG_NR_CPUS]; - -static void hp_init_stats(void) -{ - int i; - u64 cur_jiffies = get_jiffies_64(); - - mutex_lock(&rockchip_cpq_lock_stats); - - for (i = 0; i < nr_cpu_ids; i++) { - hp_stats[i].time_up_total = 0; - hp_stats[i].last_update = cur_jiffies; - - hp_stats[i].up_down_count = 0; - if (cpu_online(i)) - hp_stats[i].up_down_count = 1; - } - - mutex_unlock(&rockchip_cpq_lock_stats); -} - -/* must be called with rockchip_cpq_lock_stats held */ -static void __hp_stats_update(unsigned int cpu, bool up) -{ - u64 cur_jiffies = get_jiffies_64(); - bool was_up; - - was_up = hp_stats[cpu].up_down_count & 0x1; - - if (was_up) - hp_stats[cpu].time_up_total = - hp_stats[cpu].time_up_total + - (cur_jiffies - hp_stats[cpu].last_update); - - if (was_up != up) { - hp_stats[cpu].up_down_count++; - if ((hp_stats[cpu].up_down_count & 0x1) != up) { - /* FIXME: sysfs user space CPU control breaks stats */ - pr_err("hotplug stats out of sync with CPU%d", cpu); - hp_stats[cpu].up_down_count ^= 0x1; - } - } - hp_stats[cpu].last_update = cur_jiffies; -} - -static void hp_stats_update(unsigned int cpu, bool up) -{ - mutex_lock(&rockchip_cpq_lock_stats); - - __hp_stats_update(cpu, up); - - mutex_unlock(&rockchip_cpq_lock_stats); -} - -static int update_core_config(unsigned int cpunumber, bool up) -{ - int ret = 0; - - mutex_lock(&rockchip_cpuquiet_lock); - - if (cpq_state == CPQ_DISABLED || cpunumber >= nr_cpu_ids) { - mutex_unlock(&rockchip_cpuquiet_lock); - return -EINVAL; - } - - if (up) { - cpumask_set_cpu(cpunumber, &cpumask_online_requests); - cpumask_clear_cpu(cpunumber, &cpumask_offline_requests); - queue_work(cpuquiet_wq, &cpuquiet_work); - } else { - cpumask_set_cpu(cpunumber, &cpumask_offline_requests); - cpumask_clear_cpu(cpunumber, &cpumask_online_requests); - queue_work(cpuquiet_wq, &cpuquiet_work); - } - - mutex_unlock(&rockchip_cpuquiet_lock); - - return ret; -} - -static int rockchip_quiesence_cpu(unsigned int cpunumber, bool sync) -{ - int err = 0; - - err = update_core_config(cpunumber, false); - if (err || !sync) - return err; - - err = wait_event_interruptible_timeout(wait_cpu, - !cpu_online(cpunumber), - hotplug_timeout_jiffies); - - if (err < 0) - return err; - - if (err > 0) - return 0; - else - return -ETIMEDOUT; -} - -static int rockchip_wake_cpu(unsigned int cpunumber, bool sync) -{ - int err = 0; - - err = update_core_config(cpunumber, true); - if (err || !sync) - return err; - - err = wait_event_interruptible_timeout(wait_cpu, cpu_online(cpunumber), - hotplug_timeout_jiffies); - - if (err < 0) - return err; - - if (err > 0) - return 0; - else - return -ETIMEDOUT; -} - -static struct cpuquiet_driver rockchip_cpuquiet_driver = { - .name = "rockchip", - .quiesence_cpu = rockchip_quiesence_cpu, - .wake_cpu = rockchip_wake_cpu, -}; - -/* must be called from worker function */ -static void __cpuinit __apply_core_config(void) -{ - int count = -1; - unsigned int cpu; - int nr_cpus; - struct cpumask online, offline, cpu_online; - int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS); - int min_cpus = pm_qos_request(PM_QOS_MIN_ONLINE_CPUS); - - if (min_cpus > num_possible_cpus()) - min_cpus = 0; - if (max_cpus <= 0) - max_cpus = num_present_cpus(); - - mutex_lock(&rockchip_cpuquiet_lock); - - online = cpumask_online_requests; - offline = cpumask_offline_requests; - - mutex_unlock(&rockchip_cpuquiet_lock); - - /* always keep CPU0 online */ - cpumask_set_cpu(0, &online); - cpu_online = *cpu_online_mask; - - if (max_cpus < min_cpus) - max_cpus = min_cpus; - - nr_cpus = cpumask_weight(&online); - if (nr_cpus < min_cpus) { - cpu = 0; - count = min_cpus - nr_cpus; - for (; count > 0; count--) { - cpu = cpumask_next_zero(cpu, &online); - cpumask_set_cpu(cpu, &online); - cpumask_clear_cpu(cpu, &offline); - } - } else if (nr_cpus > max_cpus) { - count = nr_cpus - max_cpus; - cpu = 0; - for (; count > 0; count--) { - /* CPU0 should always be online */ - cpu = cpumask_next(cpu, &online); - cpumask_set_cpu(cpu, &offline); - cpumask_clear_cpu(cpu, &online); - } - } - - cpumask_andnot(&online, &online, &cpu_online); - for_each_cpu(cpu, &online) { - cpu_up(cpu); - hp_stats_update(cpu, true); - } - - cpumask_and(&offline, &offline, &cpu_online); - for_each_cpu(cpu, &offline) { - cpu_down(cpu); - hp_stats_update(cpu, false); - } - wake_up_interruptible(&wait_cpu); -} - -static void __cpuinit rockchip_cpuquiet_work_func(struct work_struct *work) -{ - int action; - - mutex_lock(&rockchip_cpuquiet_lock); - - action = cpq_target_state; - - if (action == CPQ_ENABLED) { - hp_init_stats(); - cpuquiet_device_free(); - pr_info("cpuquiet enabled\n"); - cpq_state = CPQ_ENABLED; - cpq_target_state = CPQ_IDLE; - wake_up_interruptible(&wait_enable); - } - - if (cpq_state == CPQ_DISABLED) { - mutex_unlock(&rockchip_cpuquiet_lock); - return; - } - - if (action == CPQ_DISABLED) { - cpq_state = CPQ_DISABLED; - mutex_unlock(&rockchip_cpuquiet_lock); - cpuquiet_device_busy(); - pr_info("cpuquiet disabled\n"); - wake_up_interruptible(&wait_enable); - return; - } - - mutex_unlock(&rockchip_cpuquiet_lock); - __apply_core_config(); -} - -static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p) -{ - mutex_lock(&rockchip_cpuquiet_lock); - - if (cpq_state != CPQ_DISABLED) - queue_work(cpuquiet_wq, &cpuquiet_work); - - mutex_unlock(&rockchip_cpuquiet_lock); - - return NOTIFY_OK; -} - -static int max_cpus_notify(struct notifier_block *nb, unsigned long n, void *p) -{ - mutex_lock(&rockchip_cpuquiet_lock); - - if (cpq_state != CPQ_DISABLED) - queue_work(cpuquiet_wq, &cpuquiet_work); - - mutex_unlock(&rockchip_cpuquiet_lock); - - return NOTIFY_OK; -} - -/* Must be called with rockchip_cpuquiet_lock held */ -static void __idle_stop_governor(void) -{ - if (cpq_state == CPQ_DISABLED) - return; - - if (num_online_cpus() == 1) - cpuquiet_device_busy(); - else - cpuquiet_device_free(); -} - -static int __cpuinit cpu_online_notify(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - switch (action) { - case CPU_POST_DEAD: - if (num_online_cpus() == 1) { - mutex_lock(&rockchip_cpuquiet_lock); - __idle_stop_governor(); - mutex_unlock(&rockchip_cpuquiet_lock); - } - break; - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - mutex_lock(&rockchip_cpuquiet_lock); - __idle_stop_governor(); - mutex_unlock(&rockchip_cpuquiet_lock); - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block cpu_online_notifier __cpuinitdata = { - .notifier_call = cpu_online_notify, -}; - -static struct notifier_block min_cpus_notifier = { - .notifier_call = min_cpus_notify, -}; - -static struct notifier_block max_cpus_notifier = { - .notifier_call = max_cpus_notify, -}; - -static void delay_callback(struct cpuquiet_attribute *attr) -{ - unsigned long val; - - if (attr) { - val = (*((unsigned long *)(attr->param))); - (*((unsigned long *)(attr->param))) = msecs_to_jiffies(val); - } -} - -static void enable_callback(struct cpuquiet_attribute *attr) -{ - int target_state = enable ? CPQ_ENABLED : CPQ_DISABLED; - - mutex_lock(&rockchip_cpuquiet_lock); - - if (cpq_state != target_state) { - cpq_target_state = target_state; - queue_work(cpuquiet_wq, &cpuquiet_work); - } - - mutex_unlock(&rockchip_cpuquiet_lock); - - wait_event_interruptible(wait_enable, cpq_state == target_state); -} - -CPQ_ATTRIBUTE(hotplug_timeout_jiffies, 0644, ulong, delay_callback); -CPQ_ATTRIBUTE(enable, 0644, bool, enable_callback); - -static struct attribute *rockchip_cpuquiet_attributes[] = { - &enable_attr.attr, - &hotplug_timeout_jiffies_attr.attr, - NULL, -}; - -static const struct sysfs_ops rockchip_cpuquiet_sysfs_ops = { - .show = cpuquiet_auto_sysfs_show, - .store = cpuquiet_auto_sysfs_store, -}; - -static struct kobj_type ktype_sysfs = { - .sysfs_ops = &rockchip_cpuquiet_sysfs_ops, - .default_attrs = rockchip_cpuquiet_attributes, -}; - -static int rockchip_cpuquiet_sysfs_init(void) -{ - int err; - - struct kobject *kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); - - if (!kobj) - return -ENOMEM; - - err = cpuquiet_kobject_init(kobj, &ktype_sysfs, "rockchip_cpuquiet"); - - if (err) - kfree(kobj); - - return err; -} - -#ifdef CONFIG_DEBUG_FS -static int hp_stats_show(struct seq_file *s, void *data) -{ - int i; - u64 cur_jiffies = get_jiffies_64(); - - mutex_lock(&rockchip_cpuquiet_lock); - - mutex_lock(&rockchip_cpq_lock_stats); - - if (cpq_state != CPQ_DISABLED) { - for (i = 0; i < nr_cpu_ids; i++) { - bool was_up; - - was_up = (hp_stats[i].up_down_count & 0x1); - __hp_stats_update(i, was_up); - } - } - mutex_unlock(&rockchip_cpq_lock_stats); - - mutex_unlock(&rockchip_cpuquiet_lock); - - seq_printf(s, "%-15s ", "cpu:"); - for (i = 0; i < nr_cpu_ids; i++) - seq_printf(s, "G%-9d ", i); - - seq_printf(s, "%-15s ", "transitions:"); - for (i = 0; i < nr_cpu_ids; i++) - seq_printf(s, "%-10u ", hp_stats[i].up_down_count); - seq_puts(s, "\n"); - - seq_printf(s, "%-15s ", "time plugged:"); - for (i = 0; i < nr_cpu_ids; i++) { - seq_printf(s, "%-10llu ", - cputime64_to_clock_t(hp_stats[i].time_up_total)); - } - seq_puts(s, "\n"); - - seq_printf(s, "%-15s %llu\n", "time-stamp:", - cputime64_to_clock_t(cur_jiffies)); - - return 0; -} - -static int hp_stats_open(struct inode *inode, struct file *file) -{ - return single_open(file, hp_stats_show, inode->i_private); -} - -static const struct file_operations hp_stats_fops = { - .open = hp_stats_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init rockchip_cpuquiet_debug_init(void) -{ - struct dentry *dir; - - dir = debugfs_create_dir("rockchip_cpuquiet", NULL); - if (!dir) - return -ENOMEM; - - if (!debugfs_create_file("stats", S_IRUGO, dir, NULL, &hp_stats_fops)) - goto err_out; - - return 0; - -err_out: - debugfs_remove_recursive(dir); - return -ENOMEM; -} - -late_initcall(rockchip_cpuquiet_debug_init); -#endif /* CONFIG_DEBUG_FS */ - -static int __init rockchip_cpuquiet_init(void) -{ - int err; - - init_waitqueue_head(&wait_enable); - init_waitqueue_head(&wait_cpu); - - /* - * Not bound to the issuer CPU (=> high-priority), has rescue worker - * task, single-threaded, freezable. - */ - cpuquiet_wq = alloc_workqueue( - "cpuquiet", WQ_NON_REENTRANT | WQ_FREEZABLE, 1); - - if (!cpuquiet_wq) - return -ENOMEM; - - INIT_WORK(&cpuquiet_work, rockchip_cpuquiet_work_func); - hotplug_timeout_jiffies = msecs_to_jiffies(HOTPLUG_DELAY_MS); - cpumask_clear(&cpumask_online_requests); - cpumask_clear(&cpumask_offline_requests); - - cpq_state = INITIAL_STATE; - enable = cpq_state == CPQ_DISABLED ? false : true; - hp_init_stats(); - - pr_info("cpuquiet initialized: %s\n", - (cpq_state == CPQ_DISABLED) ? "disabled" : "enabled"); - - if (pm_qos_add_notifier(PM_QOS_MIN_ONLINE_CPUS, &min_cpus_notifier)) - pr_err("Failed to register min cpus PM QoS notifier\n"); - if (pm_qos_add_notifier(PM_QOS_MAX_ONLINE_CPUS, &max_cpus_notifier)) - pr_err("Failed to register max cpus PM QoS notifier\n"); - - register_hotcpu_notifier(&cpu_online_notifier); - - err = cpuquiet_register_driver(&rockchip_cpuquiet_driver); - if (err) { - destroy_workqueue(cpuquiet_wq); - return err; - } - - err = rockchip_cpuquiet_sysfs_init(); - if (err) { - cpuquiet_unregister_driver(&rockchip_cpuquiet_driver); - destroy_workqueue(cpuquiet_wq); - } - - return err; -} -device_initcall(rockchip_cpuquiet_init); diff --git a/drivers/cpuquiet/sysfs.c b/drivers/cpuquiet/sysfs.c deleted file mode 100644 index 3c1422680bbe..000000000000 --- a/drivers/cpuquiet/sysfs.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2012-2013 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include - -#include "cpuquiet.h" - -struct cpuquiet_dev { - unsigned int cpu; - struct kobject kobj; -}; - -struct cpuquiet_sysfs_attr { - struct attribute attr; - ssize_t (*show)(char *); - ssize_t (*store)(const char *, size_t count); -}; - -static struct kobject *cpuquiet_global_kobject; -struct cpuquiet_dev *cpuquiet_cpu_devices[CONFIG_NR_CPUS]; - -static ssize_t show_current_governor(char *buf) -{ - ssize_t ret; - - mutex_lock(&cpuquiet_lock); - - if (cpuquiet_curr_governor) - ret = sprintf(buf, "%s\n", cpuquiet_curr_governor->name); - else - ret = sprintf(buf, "none\n"); - - mutex_unlock(&cpuquiet_lock); - - return ret; - -} - -static ssize_t store_current_governor(const char *buf, size_t count) -{ - char name[CPUQUIET_NAME_LEN]; - struct cpuquiet_governor *gov; - int len = count, ret = -EINVAL; - - if (!len || len >= sizeof(name)) - return -EINVAL; - - memcpy(name, buf, count); - name[len] = '\0'; - if (name[len - 1] == '\n') - name[--len] = '\0'; - - mutex_lock(&cpuquiet_lock); - gov = cpuquiet_find_governor(name); - - if (gov) - ret = cpuquiet_switch_governor(gov); - mutex_unlock(&cpuquiet_lock); - - if (ret) - return ret; - else - return count; -} - -static ssize_t available_governors_show(char *buf) -{ - ssize_t ret = 0, len; - struct cpuquiet_governor *gov; - - mutex_lock(&cpuquiet_lock); - if (!list_empty(&cpuquiet_governors)) { - list_for_each_entry(gov, &cpuquiet_governors, governor_list) { - len = sprintf(buf, "%s ", gov->name); - buf += len; - ret += len; - } - buf--; - *buf = '\n'; - } else - ret = sprintf(buf, "none\n"); - - mutex_unlock(&cpuquiet_lock); - - return ret; -} - -struct cpuquiet_sysfs_attr attr_current_governor = __ATTR(current_governor, - 0644, show_current_governor, store_current_governor); -struct cpuquiet_sysfs_attr attr_governors = __ATTR_RO(available_governors); - - -static struct attribute *cpuquiet_default_attrs[] = { - &attr_current_governor.attr, - &attr_governors.attr, - NULL -}; - -static ssize_t cpuquiet_sysfs_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct cpuquiet_sysfs_attr *cattr = - container_of(attr, struct cpuquiet_sysfs_attr, attr); - - return cattr->show(buf); -} - -static ssize_t cpuquiet_sysfs_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t count) -{ - struct cpuquiet_sysfs_attr *cattr = - container_of(attr, struct cpuquiet_sysfs_attr, attr); - - if (cattr->store) - return cattr->store(buf, count); - - return -EINVAL; -} - -static const struct sysfs_ops cpuquiet_sysfs_ops = { - .show = cpuquiet_sysfs_show, - .store = cpuquiet_sysfs_store, -}; - -static struct kobj_type ktype_cpuquiet_sysfs = { - .sysfs_ops = &cpuquiet_sysfs_ops, - .default_attrs = cpuquiet_default_attrs, -}; - -int cpuquiet_add_group(struct attribute_group *attrs) -{ - return sysfs_create_group(cpuquiet_global_kobject, attrs); -} - -void cpuquiet_remove_group(struct attribute_group *attrs) -{ - sysfs_remove_group(cpuquiet_global_kobject, attrs); -} - -int cpuquiet_kobject_init(struct kobject *kobj, struct kobj_type *type, - char *name) -{ - int err; - - err = kobject_init_and_add(kobj, type, cpuquiet_global_kobject, name); - if (!err) - kobject_uevent(kobj, KOBJ_ADD); - - return err; -} - -int cpuquiet_cpu_kobject_init(struct kobject *kobj, struct kobj_type *type, - char *name, int cpu) -{ - int err; - - err = kobject_init_and_add(kobj, type, &cpuquiet_cpu_devices[cpu]->kobj, - name); - if (!err) - kobject_uevent(kobj, KOBJ_ADD); - - return err; -} - -int cpuquiet_add_interface(struct device *dev) -{ - int err; - - cpuquiet_global_kobject = kzalloc(sizeof(*cpuquiet_global_kobject), - GFP_KERNEL); - if (!cpuquiet_global_kobject) - return -ENOMEM; - - err = kobject_init_and_add(cpuquiet_global_kobject, - &ktype_cpuquiet_sysfs, &dev->kobj, "cpuquiet"); - if (!err) - kobject_uevent(cpuquiet_global_kobject, KOBJ_ADD); - - return err; -} - - -struct cpuquiet_attr { - struct attribute attr; - ssize_t (*show)(unsigned int, char *); - ssize_t (*store)(unsigned int, const char *, size_t count); -}; - - -static ssize_t cpuquiet_state_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct cpuquiet_attr *cattr = container_of(attr, - struct cpuquiet_attr, attr); - struct cpuquiet_dev *dev = container_of(kobj, - struct cpuquiet_dev, kobj); - - return cattr->show(dev->cpu, buf); -} - -static ssize_t cpuquiet_state_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t count) -{ - struct cpuquiet_attr *cattr = container_of(attr, - struct cpuquiet_attr, attr); - struct cpuquiet_dev *dev = container_of(kobj, - struct cpuquiet_dev, kobj); - - if (cattr->store) - return cattr->store(dev->cpu, buf, count); - - return -EINVAL; -} - -static ssize_t show_active(unsigned int cpu, char *buf) -{ - return sprintf(buf, "%u\n", cpu_online(cpu)); -} - -static ssize_t store_active(unsigned int cpu, const char *value, size_t count) -{ - unsigned int active; - int ret; - - if (!cpuquiet_curr_governor->store_active) - return -EINVAL; - - ret = sscanf(value, "%u", &active); - if (ret != 1) - return -EINVAL; - - cpuquiet_curr_governor->store_active(cpu, active); - - return count; -} - -struct cpuquiet_attr attr_active = __ATTR(active, 0644, show_active, - store_active); - -static struct attribute *cpuquiet_default_cpu_attrs[] = { - &attr_active.attr, - NULL -}; - -static const struct sysfs_ops cpuquiet_cpu_sysfs_ops = { - .show = cpuquiet_state_show, - .store = cpuquiet_state_store, -}; - -static struct kobj_type ktype_cpuquiet = { - .sysfs_ops = &cpuquiet_cpu_sysfs_ops, - .default_attrs = cpuquiet_default_cpu_attrs, -}; - -void cpuquiet_add_dev(struct device *device, unsigned int cpu) -{ - struct cpuquiet_dev *dev; - int err; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - dev->cpu = cpu; - cpuquiet_cpu_devices[cpu] = dev; - err = kobject_init_and_add(&dev->kobj, &ktype_cpuquiet, - &device->kobj, "cpuquiet"); - if (!err) - kobject_uevent(&dev->kobj, KOBJ_ADD); -} - -void cpuquiet_remove_dev(unsigned int cpu) -{ - if (cpu < CONFIG_NR_CPUS && cpuquiet_cpu_devices[cpu]) - kobject_put(&cpuquiet_cpu_devices[cpu]->kobj); -} diff --git a/include/linux/cpuquiet.h b/include/linux/cpuquiet.h deleted file mode 100644 index 02e0267a4636..000000000000 --- a/include/linux/cpuquiet.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef _LINUX_CPUONLINE_H -#define _LINUX_CPUONLINE_H - -#include -#include - -#define CPUQUIET_NAME_LEN 16 - -struct cpuquiet_governor { - char name[CPUQUIET_NAME_LEN]; - struct list_head governor_list; - int (*start) (void); - void (*stop) (void); - int (*store_active) (unsigned int cpu, bool active); - void (*device_free_notification) (void); - void (*device_busy_notification) (void); - struct module *owner; -}; - -struct cpuquiet_driver { - char name[CPUQUIET_NAME_LEN]; - int (*quiesence_cpu) (unsigned int cpunumber, bool sync); - int (*wake_cpu) (unsigned int cpunumber, bool sync); -}; - -extern int cpuquiet_register_governor(struct cpuquiet_governor *gov); -extern void cpuquiet_unregister_governor(struct cpuquiet_governor *gov); -extern int cpuquiet_quiesence_cpu(unsigned int cpunumber, bool sync); -extern int cpuquiet_wake_cpu(unsigned int cpunumber, bool sync); -extern int cpuquiet_register_driver(struct cpuquiet_driver *drv); -extern void cpuquiet_unregister_driver(struct cpuquiet_driver *drv); -extern int cpuquiet_add_group(struct attribute_group *attrs); -extern void cpuquiet_remove_group(struct attribute_group *attrs); -extern void cpuquiet_device_busy(void); -extern void cpuquiet_device_free(void); -int cpuquiet_kobject_init(struct kobject *kobj, struct kobj_type *type, - char *name); -extern unsigned int nr_cluster_ids; - -/* Sysfs support */ -struct cpuquiet_attribute { - struct attribute attr; - ssize_t (*show)(struct cpuquiet_attribute *attr, char *buf); - ssize_t (*store)(struct cpuquiet_attribute *attr, const char *buf, - size_t count); - /* Optional. Called after store is called */ - void (*store_callback)(struct cpuquiet_attribute *attr); - void *param; -}; - -#define CPQ_ATTRIBUTE(_name, _mode, _type, _callback) \ - static struct cpuquiet_attribute _name ## _attr = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = show_ ## _type ## _attribute, \ - .store = store_ ## _type ## _attribute, \ - .store_callback = _callback, \ - .param = &_name, \ -} - -#define CPQ_BASIC_ATTRIBUTE(_name, _mode, _type) \ - CPQ_ATTRIBUTE(_name, _mode, _type, NULL) - -#define CPQ_ATTRIBUTE_CUSTOM(_name, _mode, _show, _store) \ - static struct cpuquiet_attribute _name ## _attr = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ - .store_callback = NULL, \ - .param = &_name, \ -} - - -extern ssize_t show_int_attribute(struct cpuquiet_attribute *cattr, char *buf); -extern ssize_t store_int_attribute(struct cpuquiet_attribute *cattr, - const char *buf, size_t count); -extern ssize_t show_bool_attribute(struct cpuquiet_attribute *cattr, char *buf); -extern ssize_t store_bool_attribute(struct cpuquiet_attribute *cattr, - const char *buf, size_t count); -extern ssize_t store_uint_attribute(struct cpuquiet_attribute *cattr, - const char *buf, size_t count); -extern ssize_t show_uint_attribute(struct cpuquiet_attribute *cattr, char *buf); -extern ssize_t store_ulong_attribute(struct cpuquiet_attribute *cattr, - const char *buf, size_t count); -extern ssize_t show_ulong_attribute(struct cpuquiet_attribute *cattr, - char *buf); -extern ssize_t cpuquiet_auto_sysfs_show(struct kobject *kobj, - struct attribute *attr, char *buf); -extern ssize_t cpuquiet_auto_sysfs_store(struct kobject *kobj, - struct attribute *attr, const char *buf, - size_t count); -#endif -- 2.34.1