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

[CPUFREQ] fix cpufreq core breakage(s)

- update two more cpufreq-related sysfs files to the new interface
  code
- always store the new, user-requested policy in another struct
  cpufreq_policy so that we can safely fall back to the old one in
  case something fails (this equals the behaviour before Pat's patch)
- the kobject which was registered in cpufreq_add_dev was inside a variable
  private to this function -- so the whole cpufreq sysfs interface returned
  -EINVAL.
parent c7650146
...@@ -143,12 +143,17 @@ static ssize_t store_##file_name \ ...@@ -143,12 +143,17 @@ static ssize_t store_##file_name \
(struct cpufreq_policy * policy, const char *buf, size_t count) \ (struct cpufreq_policy * policy, const char *buf, size_t count) \
{ \ { \
unsigned int ret = -EINVAL; \ unsigned int ret = -EINVAL; \
struct cpufreq_policy new_policy; \
\ \
ret = sscanf (buf, "%u", &policy->object); \ ret = cpufreq_get_policy(&new_policy, policy->cpu); \
if (ret) \
return ret; \
\
ret = sscanf (buf, "%u", &new_policy.object); \
if (ret != 1) \ if (ret != 1) \
return -EINVAL; \ return -EINVAL; \
\ \
ret = cpufreq_set_policy(policy); \ ret = cpufreq_set_policy(&new_policy); \
\ \
return ret ? ret : count; \ return ret ? ret : count; \
} }
...@@ -192,19 +197,64 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy, ...@@ -192,19 +197,64 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
{ {
unsigned int ret = -EINVAL; unsigned int ret = -EINVAL;
char str_governor[16]; char str_governor[16];
struct cpufreq_policy new_policy;
ret = cpufreq_get_policy(&new_policy, policy->cpu);
if (ret)
return ret;
ret = sscanf (buf, "%15s", str_governor); ret = sscanf (buf, "%15s", str_governor);
if (ret != 1) if (ret != 1)
return -EINVAL; return -EINVAL;
if (cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor)) if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
return -EINVAL; return -EINVAL;
ret = cpufreq_set_policy(policy); ret = cpufreq_set_policy(&new_policy);
return ret ? ret : count; return ret ? ret : count;
} }
/**
* show_scaling_driver - show the cpufreq driver currently loaded
*/
static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf)
{
char value[CPUFREQ_NAME_LEN];
down(&cpufreq_driver_sem);
if (cpufreq_driver)
strncpy(value, cpufreq_driver->name, CPUFREQ_NAME_LEN);
up(&cpufreq_driver_sem);
return sprintf(buf, "%s\n", value);
}
/**
* show_scaling_available_governors - show the available CPUfreq governors
*/
static ssize_t show_scaling_available_governors(struct cpufreq_policy * policy, char *buf)
{
ssize_t i = 0;
struct cpufreq_governor *t;
i += sprintf(buf, "performance powersave");
down(&cpufreq_driver_sem);
if (!cpufreq_driver || !cpufreq_driver->target)
goto out;
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
goto out;
i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
}
out:
up(&cpufreq_driver_sem);
i += sprintf(&buf[i], "\n");
return i;
}
struct freq_attr { struct freq_attr {
struct attribute attr; struct attribute attr;
...@@ -227,6 +277,8 @@ struct freq_attr _name = { \ ...@@ -227,6 +277,8 @@ struct freq_attr _name = { \
define_one_ro(cpuinfo_min_freq); define_one_ro(cpuinfo_min_freq);
define_one_ro(cpuinfo_max_freq); define_one_ro(cpuinfo_max_freq);
define_one_ro(scaling_available_governors);
define_one_ro(scaling_driver);
define_one_rw(scaling_min_freq); define_one_rw(scaling_min_freq);
define_one_rw(scaling_max_freq); define_one_rw(scaling_max_freq);
define_one_rw(scaling_governor); define_one_rw(scaling_governor);
...@@ -237,6 +289,8 @@ static struct attribute * default_attrs[] = { ...@@ -237,6 +289,8 @@ static struct attribute * default_attrs[] = {
&scaling_min_freq.attr, &scaling_min_freq.attr,
&scaling_max_freq.attr, &scaling_max_freq.attr,
&scaling_governor.attr, &scaling_governor.attr,
&scaling_driver.attr,
&scaling_available_governors.attr,
NULL NULL
}; };
...@@ -270,56 +324,6 @@ static struct kobj_type ktype_cpufreq = { ...@@ -270,56 +324,6 @@ static struct kobj_type ktype_cpufreq = {
}; };
/**
* show_scaling_governor - show the current policy for the specified CPU
*/
static ssize_t show_scaling_driver (struct device *dev, char *buf)
{
char value[CPUFREQ_NAME_LEN];
if (!dev)
return 0;
down(&cpufreq_driver_sem);
if (cpufreq_driver)
strncpy(value, cpufreq_driver->name, CPUFREQ_NAME_LEN);
up(&cpufreq_driver_sem);
return sprintf(buf, "%s\n", value);
}
/**
* show_available_govs - show the available CPUfreq governors
*/
static ssize_t show_available_govs(struct device *dev, char *buf)
{
ssize_t i = 0;
struct cpufreq_governor *t;
if (!dev)
return 0;
i += sprintf(buf, "performance powersave");
down(&cpufreq_driver_sem);
if (!cpufreq_driver || !cpufreq_driver->target)
goto out;
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
goto out;
i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
}
out:
up(&cpufreq_driver_sem);
i += sprintf(&buf[i], "\n");
return i;
}
static DEVICE_ATTR(scaling_driver, S_IRUGO, show_scaling_driver, NULL);
static DEVICE_ATTR(available_scaling_governors, S_IRUGO, show_available_govs, NULL);
/** /**
* cpufreq_add_dev - add a CPU device * cpufreq_add_dev - add a CPU device
* *
...@@ -329,7 +333,8 @@ static int cpufreq_add_dev (struct device * dev) ...@@ -329,7 +333,8 @@ static int cpufreq_add_dev (struct device * dev)
{ {
unsigned int cpu = to_cpu_nr(dev); unsigned int cpu = to_cpu_nr(dev);
int ret = 0; int ret = 0;
struct cpufreq_policy policy; struct cpufreq_policy new_policy;
struct cpufreq_policy *policy;
down(&cpufreq_driver_sem); down(&cpufreq_driver_sem);
if (!cpufreq_driver) { if (!cpufreq_driver) {
...@@ -340,9 +345,10 @@ static int cpufreq_add_dev (struct device * dev) ...@@ -340,9 +345,10 @@ static int cpufreq_add_dev (struct device * dev)
/* call driver. From then on the cpufreq must be able /* call driver. From then on the cpufreq must be able
* to accept all calls to ->verify and ->setpolicy for this CPU * to accept all calls to ->verify and ->setpolicy for this CPU
*/ */
cpufreq_driver->policy[cpu].cpu = cpu; policy = &cpufreq_driver->policy[cpu];
policy->cpu = cpu;
if (cpufreq_driver->init) { if (cpufreq_driver->init) {
ret = cpufreq_driver->init(&cpufreq_driver->policy[cpu]); ret = cpufreq_driver->init(policy);
if (ret) { if (ret) {
up(&cpufreq_driver_sem); up(&cpufreq_driver_sem);
return -ENODEV; return -ENODEV;
...@@ -350,34 +356,27 @@ static int cpufreq_add_dev (struct device * dev) ...@@ -350,34 +356,27 @@ static int cpufreq_add_dev (struct device * dev)
} }
/* set default policy on this CPU */ /* set default policy on this CPU */
memcpy(&policy, memcpy(&new_policy,
&cpufreq_driver->policy[cpu], policy,
sizeof(struct cpufreq_policy)); sizeof(struct cpufreq_policy));
/* 2.4-API init for this CPU */
#ifdef CONFIG_CPU_FREQ_24_API
cpu_min_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.min_freq;
cpu_max_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.max_freq;
cpu_cur_freq[cpu] = cpufreq_driver->cpu_cur_freq[cpu];
#endif
if (cpufreq_driver->target) if (cpufreq_driver->target)
cpufreq_governor(cpu, CPUFREQ_GOV_START); cpufreq_governor(cpu, CPUFREQ_GOV_START);
up(&cpufreq_driver_sem); up(&cpufreq_driver_sem);
ret = cpufreq_set_policy(&policy); ret = cpufreq_set_policy(&new_policy);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
down(&cpufreq_driver_sem); down(&cpufreq_driver_sem);
/* prepare interface data */ /* prepare interface data */
policy.kobj.parent = &dev->kobj; policy->kobj.parent = &dev->kobj;
policy.kobj.ktype = &ktype_cpufreq; policy->kobj.ktype = &ktype_cpufreq;
policy.dev = dev; policy->dev = dev;
strncpy(policy.kobj.name, strncpy(policy->kobj.name,
cpufreq_interface.name, KOBJ_NAME_LEN); cpufreq_interface.name, KOBJ_NAME_LEN);
ret = kobject_register(&policy.kobj); ret = kobject_register(&policy->kobj);
up(&cpufreq_driver_sem); up(&cpufreq_driver_sem);
return ret; return 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