Commit fe3f9d78 authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

[CPUFREQ] allow cpufreq drivers to export sysfs files

This patch lets cpufreq drivers export per-CPU files in the cpufreq and
cpu-specific sysfs directory. As an example, a file
"scaling_available_frequencies" is added to the p4-clockmod.c driver.
parent f913edb4
...@@ -214,6 +214,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) ...@@ -214,6 +214,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
else else
p4clockmod_table[i].frequency = (stock_freq * i)/8; p4clockmod_table[i].frequency = (stock_freq * i)/8;
} }
cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
/* cpuinfo and default policy values */ /* cpuinfo and default policy values */
policy->policy = CPUFREQ_POLICY_PERFORMANCE; policy->policy = CPUFREQ_POLICY_PERFORMANCE;
...@@ -226,9 +227,14 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) ...@@ -226,9 +227,14 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
return cpufreq_p4_setdc(policy->cpu, DC_DISABLE); return cpufreq_p4_setdc(policy->cpu, DC_DISABLE);
} }
static struct freq_attr* p4clockmod_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
};
static struct cpufreq_driver p4clockmod_driver = { static struct cpufreq_driver p4clockmod_driver = {
.verify = cpufreq_p4_verify, .verify = cpufreq_p4_verify,
...@@ -237,6 +243,7 @@ static struct cpufreq_driver p4clockmod_driver = { ...@@ -237,6 +243,7 @@ static struct cpufreq_driver p4clockmod_driver = {
.exit = cpufreq_p4_cpu_exit, .exit = cpufreq_p4_cpu_exit,
.name = "p4-clockmod", .name = "p4-clockmod",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.attr = p4clockmod_attr,
}; };
......
...@@ -147,6 +147,56 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -147,6 +147,56 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
} }
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
static struct cpufreq_frequency_table *show_table[NR_CPUS];
/**
* show_scaling_governor - show the current policy for the specified CPU
*/
static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
{
unsigned int i = 0;
unsigned int cpu = policy->cpu;
ssize_t count = 0;
struct cpufreq_frequency_table *table;
if (!show_table[cpu])
return -ENODEV;
table = show_table[cpu];
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
continue;
count += sprintf(&buf[count], "%d ", table[i].frequency);
}
count += sprintf(&buf[count], "\n");
return count;
}
struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
.attr = { .name = "scaling_available_frequencies", .mode = 0444 },
.show = show_available_freqs,
};
EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
/*
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
*/
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu)
{
show_table[cpu] = table;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
void cpufreq_frequency_table_put_attr(unsigned int cpu)
{
show_table[cpu] = NULL;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>"); MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION ("CPUfreq frequency table helpers"); MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
......
...@@ -152,6 +152,8 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor); ...@@ -152,6 +152,8 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor);
#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */ #define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */
#define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */ #define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */
struct freq_attr;
struct cpufreq_driver { struct cpufreq_driver {
/* needed by all drivers */ /* needed by all drivers */
int (*verify) (struct cpufreq_policy *policy); int (*verify) (struct cpufreq_policy *policy);
...@@ -166,6 +168,7 @@ struct cpufreq_driver { ...@@ -166,6 +168,7 @@ struct cpufreq_driver {
/* optional, for the moment */ /* optional, for the moment */
int (*init) (struct cpufreq_policy *policy); int (*init) (struct cpufreq_policy *policy);
int (*exit) (struct cpufreq_policy *policy); int (*exit) (struct cpufreq_policy *policy);
struct freq_attr **attr;
}; };
int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_register_driver(struct cpufreq_driver *driver_data);
...@@ -298,6 +301,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -298,6 +301,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned int relation, unsigned int relation,
unsigned int *index); unsigned int *index);
/* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);
void cpufreq_frequency_table_put_attr(unsigned int cpu);
#endif /* CONFIG_CPU_FREQ_TABLE */ #endif /* CONFIG_CPU_FREQ_TABLE */
#endif /* _LINUX_CPUFREQ_H */ #endif /* _LINUX_CPUFREQ_H */
...@@ -340,6 +340,7 @@ static int cpufreq_add_dev (struct device * dev) ...@@ -340,6 +340,7 @@ static int cpufreq_add_dev (struct device * dev)
int ret = 0; int ret = 0;
struct cpufreq_policy new_policy; struct cpufreq_policy new_policy;
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
struct freq_attr **drv_attr;
if (!kset_get(&cpufreq_interface.kset)) if (!kset_get(&cpufreq_interface.kset))
return -EINVAL; return -EINVAL;
...@@ -378,7 +379,13 @@ static int cpufreq_add_dev (struct device * dev) ...@@ -378,7 +379,13 @@ static int cpufreq_add_dev (struct device * dev)
ret = kobject_register(&policy->kobj); ret = kobject_register(&policy->kobj);
if (ret) if (ret)
goto out; goto out;
drv_attr = cpufreq_driver->attr;
while ((drv_attr) && (*drv_attr)) {
sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
drv_attr++;
}
/* set default policy */ /* set default policy */
ret = cpufreq_set_policy(&new_policy); ret = cpufreq_set_policy(&new_policy);
if (ret) if (ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment