mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
ARM: tegra: add sysfs support for tegra cpuquiet driver
Change-Id: I215c5de8e98d139a93113978e1e27adb5a6b252c Signed-off-by: Sai Charan Gurrappadi <sgurrappadi@nvidia.com> Reviewed-on: http://git-master/r/111283 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
This commit is contained in:
committed by
Huang, Tao
parent
4bb5a83520
commit
a9b2c1b41b
@@ -1 +1 @@
|
||||
obj-$(CONFIG_CPUQUIET_FRAMEWORK) += cpuquiet.o driver.o sysfs.o governor.o governors/
|
||||
obj-$(CONFIG_CPUQUIET_FRAMEWORK) += cpuquiet.o driver.o sysfs.o cpuquiet_attribute.o governor.o governors/
|
||||
|
||||
133
drivers/cpuquiet/cpuquiet_attribute.c
Normal file
133
drivers/cpuquiet/cpuquiet_attribute.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 <linux/cpuquiet.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -55,30 +55,15 @@ static DEFINE_PER_CPU(unsigned int, cpu_load);
|
||||
|
||||
static struct timer_list load_timer;
|
||||
static bool load_timer_active;
|
||||
struct balanced_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct balanced_attribute *attr, char *buf);
|
||||
ssize_t (*store)(struct balanced_attribute *attr, const char *buf,
|
||||
size_t count);
|
||||
unsigned long *param;
|
||||
};
|
||||
|
||||
#define BALANCED_ATTRIBUTE(_name, _mode) \
|
||||
static struct balanced_attribute _name ## _attr = { \
|
||||
.attr = {.name = __stringify(_name), .mode = _mode }, \
|
||||
.show = show_attribute, \
|
||||
.store = store_attribute, \
|
||||
.param = &_name, \
|
||||
}
|
||||
|
||||
/* configurable parameters */
|
||||
static unsigned long balance_level = 60;
|
||||
static unsigned long idle_bottom_freq;
|
||||
static unsigned long idle_top_freq;
|
||||
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 long load_sample_rate = 20; // msec
|
||||
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;
|
||||
@@ -339,53 +324,22 @@ static struct notifier_block balanced_cpufreq_nb = {
|
||||
.notifier_call = balanced_cpufreq_transition,
|
||||
};
|
||||
|
||||
static ssize_t show_attribute(struct balanced_attribute *battr, char *buf)
|
||||
static void delay_callback(struct cpuquiet_attribute *attr)
|
||||
{
|
||||
return sprintf(buf, "%lu\n", *(battr->param));
|
||||
}
|
||||
|
||||
static ssize_t store_attribute(struct balanced_attribute *battr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int err;
|
||||
unsigned long val;
|
||||
|
||||
err = strict_strtoul(buf, 0, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
*(battr->param) = val;
|
||||
|
||||
return count;
|
||||
if (attr) {
|
||||
val = (*((unsigned long *)(attr->param)));
|
||||
(*((unsigned long *)(attr->param))) = msecs_to_jiffies(val);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t balanced_sysfs_store(struct kobject *kobj,
|
||||
struct attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct balanced_attribute *battr =
|
||||
container_of(attr, struct balanced_attribute, attr);
|
||||
|
||||
if (battr->store)
|
||||
return battr->store(battr, buf, count);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t balanced_sysfs_show(struct kobject *kobj,
|
||||
struct attribute *attr, char *buf)
|
||||
{
|
||||
struct balanced_attribute *battr =
|
||||
container_of(attr, struct balanced_attribute, attr);
|
||||
|
||||
return battr->show(battr, buf);
|
||||
}
|
||||
|
||||
BALANCED_ATTRIBUTE(balance_level, 0644);
|
||||
BALANCED_ATTRIBUTE(idle_bottom_freq, 0644);
|
||||
BALANCED_ATTRIBUTE(idle_top_freq, 0644);
|
||||
BALANCED_ATTRIBUTE(up_delay, 0644);
|
||||
BALANCED_ATTRIBUTE(down_delay, 0644);
|
||||
BALANCED_ATTRIBUTE(load_sample_rate, 0644);
|
||||
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(up_delay, 0644, ulong, delay_callback);
|
||||
CPQ_ATTRIBUTE(down_delay, 0644, ulong, delay_callback);
|
||||
|
||||
static struct attribute *balanced_attributes[] = {
|
||||
&balance_level_attr.attr,
|
||||
@@ -397,8 +351,8 @@ static struct attribute *balanced_attributes[] = {
|
||||
};
|
||||
|
||||
static const struct sysfs_ops balanced_sysfs_ops = {
|
||||
.show = balanced_sysfs_show,
|
||||
.store = balanced_sysfs_store,
|
||||
.show = cpuquiet_auto_sysfs_show,
|
||||
.store = cpuquiet_auto_sysfs_store,
|
||||
};
|
||||
|
||||
static struct kobj_type ktype_balanced = {
|
||||
@@ -427,7 +381,6 @@ static int balanced_sysfs(void)
|
||||
|
||||
static void balanced_stop(void)
|
||||
{
|
||||
|
||||
/*
|
||||
first unregister the notifiers. This ensures the governor state
|
||||
can't be modified by a cpufreq transition
|
||||
@@ -465,8 +418,7 @@ static int balanced_start(void)
|
||||
down_delay = msecs_to_jiffies(500);
|
||||
|
||||
table = cpufreq_frequency_get_table(0);
|
||||
for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++)
|
||||
;
|
||||
for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++);
|
||||
|
||||
idle_top_freq = table[(count / 2) - 1].frequency;
|
||||
idle_bottom_freq = table[(count / 2) - 2].frequency;
|
||||
|
||||
@@ -50,4 +50,56 @@ extern void cpuquiet_remove_group(struct attribute_group *attrs);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user