static DECLARE_MUTEX (cpufreq_notifier_sem);
-/**
- * The cpufreq default policy. Can be set by a "cpufreq=..." command
- * line option.
- */
-static struct cpufreq_policy default_policy = {
- .cpu = CPUFREQ_ALL_CPUS,
- .min = 0,
- .max = 0,
- .policy = 0,
-};
-
-
#ifdef CONFIG_CPU_FREQ_24_API
/**
* A few values needed by the 2.4.-compatible API
}
+/**
+ * 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);
+}
+
+
/**
* cpufreq_per_cpu_attr_ro - read-only cpufreq per-CPU file
*/
cpufreq_per_cpu_attr_rw(scaling_max_freq, max);
static DEVICE_ATTR(scaling_governor, (S_IRUGO | S_IWUSR), show_scaling_governor, store_scaling_governor);
+static DEVICE_ATTR(scaling_driver, S_IRUGO, show_scaling_driver, NULL);
/**
{
unsigned int cpu = to_cpu_nr(dev);
int ret = 0;
+ struct cpufreq_policy policy;
down(&cpufreq_driver_sem);
if (!cpufreq_driver) {
return -EINVAL;
}
+ /* call driver. From then on the cpufreq must be able
+ * to accept all calls to ->verify and ->setpolicy for this CPU
+ */
+ cpufreq_driver->policy[cpu].cpu = cpu;
+ if (cpufreq_driver->init) {
+ ret = cpufreq_driver->init(&cpufreq_driver->policy[cpu]);
+ if (ret) {
+ up(&cpufreq_driver_sem);
+ return -ENODEV;
+ }
+ }
+
+ /* set default policy on this CPU */
+ policy.policy = cpufreq_driver->policy[cpu].policy;
+ policy.min = cpufreq_driver->policy[cpu].min;
+ policy.max = cpufreq_driver->policy[cpu].max;
+ policy.cpu = cpu;
+
+ up(&cpufreq_driver_sem);
+ ret = cpufreq_set_policy(&policy);
+ if (ret)
+ return -EINVAL;
+ down(&cpufreq_driver_sem);
+
+ /* 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
+
/* prepare interface data */
cpufreq_driver->policy[cpu].intf.dev = dev;
cpufreq_driver->policy[cpu].intf.intf = &cpufreq_interface;
device_create_file (dev, &dev_attr_scaling_min_freq);
device_create_file (dev, &dev_attr_scaling_max_freq);
device_create_file (dev, &dev_attr_scaling_governor);
+ device_create_file (dev, &dev_attr_scaling_driver);
up(&cpufreq_driver_sem);
return ret;
static int cpufreq_remove_dev (struct intf_data *intf)
{
struct device * dev = intf->dev;
+ unsigned int cpu = to_cpu_nr(dev);
+
+ if (cpufreq_driver->exit)
+ cpufreq_driver->exit(&cpufreq_driver->policy[cpu]);
device_remove_file (dev, &dev_attr_cpuinfo_min_freq);
device_remove_file (dev, &dev_attr_cpuinfo_max_freq);
device_remove_file (dev, &dev_attr_scaling_min_freq);
device_remove_file (dev, &dev_attr_scaling_max_freq);
device_remove_file (dev, &dev_attr_scaling_governor);
+ device_remove_file (dev, &dev_attr_scaling_governor);
return 0;
}
}
-/*
- * cpufreq command line parameter. Must be hard values (kHz)
- * cpufreq=1000000:2000000:PERFORMANCE
- * to set the default CPUFreq policy.
- */
-static int __init cpufreq_setup(char *str)
-{
- cpufreq_parse_policy(str, &default_policy);
- default_policy.cpu = CPUFREQ_ALL_CPUS;
- return 1;
-}
-__setup("cpufreq=", cpufreq_setup);
-
-
/**
* cpufreq_proc_read - read /proc/cpufreq
*
*********************************************************************/
/**
- * cpufreq_register - register a CPU Frequency driver
- * @driver_data: A struct cpufreq_driver containing the values submitted by the CPU Frequency driver.
+ * cpufreq_register_driver - register a CPU Frequency driver
+ * @driver_data: A struct cpufreq_driver containing the values#
+ * submitted by the CPU Frequency driver.
*
* Registers a CPU Frequency driver to this core code. This code
* returns zero on success, -EBUSY when another driver got here first
* (and isn't unregistered in the meantime).
*
*/
-int cpufreq_register(struct cpufreq_driver *driver_data)
+int cpufreq_register_driver(struct cpufreq_driver *driver_data)
{
- unsigned int ret;
- unsigned int i;
- struct cpufreq_policy policy;
+ int ret = 0;
if (cpufreq_driver)
return -EBUSY;
return -EINVAL;
down(&cpufreq_driver_sem);
- cpufreq_driver = driver_data;
-
- /* check for a default policy - if it exists, use it on _all_ CPUs*/
- for (i=0; i<NR_CPUS; i++)
- {
- if (default_policy.policy)
- cpufreq_driver->policy[i].policy = default_policy.policy;
- if (default_policy.min)
- cpufreq_driver->policy[i].min = default_policy.min;
- if (default_policy.max)
- cpufreq_driver->policy[i].max = default_policy.max;
- }
- /* set default policy on all CPUs. Must be called per-CPU and not
- * with CPUFREQ_ALL_CPUs as there might be no common policy for all
- * CPUs (UltraSPARC etc.)
- */
- for (i=0; i<NR_CPUS; i++)
- {
- policy.policy = cpufreq_driver->policy[i].policy;
- policy.min = cpufreq_driver->policy[i].min;
- policy.max = cpufreq_driver->policy[i].max;
- policy.cpu = i;
- up(&cpufreq_driver_sem);
- ret = cpufreq_set_policy(&policy);
- down(&cpufreq_driver_sem);
- if (ret) {
- cpufreq_driver = NULL;
+ cpufreq_driver = driver_data;
+
+ if (!cpufreq_driver->policy) {
+ /* then we need per-CPU init */
+ if (!cpufreq_driver->init) {
up(&cpufreq_driver_sem);
- return ret;
+ return -EINVAL;
+ }
+ cpufreq_driver->policy = kmalloc(NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
+ if (!cpufreq_driver->policy) {
+ up(&cpufreq_driver_sem);
+ return -ENOMEM;
}
}
-
+
up(&cpufreq_driver_sem);
cpufreq_proc_init();
#ifdef CONFIG_CPU_FREQ_24_API
- down(&cpufreq_driver_sem);
- for (i=0; i<NR_CPUS; i++)
- {
- cpu_min_freq[i] = driver_data->policy[i].cpuinfo.min_freq;
- cpu_max_freq[i] = driver_data->policy[i].cpuinfo.max_freq;
- cpu_cur_freq[i] = driver_data->cpu_cur_freq[i];
- }
- up(&cpufreq_driver_sem);
-
cpufreq_sysctl_init();
#endif
return ret;
}
-EXPORT_SYMBOL_GPL(cpufreq_register);
+EXPORT_SYMBOL_GPL(cpufreq_register_driver);
/**
- * cpufreq_unregister - unregister the current CPUFreq driver
+ * cpufreq_unregister_driver - unregister the current CPUFreq driver
*
* Unregister the current CPUFreq driver. Only call this if you have
* the right to do so, i.e. if you have succeeded in initialising before!
* Returns zero if successful, and -EINVAL if the cpufreq_driver is
* currently not initialised.
*/
-int cpufreq_unregister(void)
+int cpufreq_unregister_driver(struct cpufreq_driver *driver)
{
down(&cpufreq_driver_sem);
- if (!cpufreq_driver) {
+ if (!cpufreq_driver ||
+ ((driver != cpufreq_driver) && (driver != NULL))) { /* compat */
up(&cpufreq_driver_sem);
return -EINVAL;
}
- interface_unregister(&cpufreq_interface);
- cpufreq_driver = NULL;
-
- up(&cpufreq_driver_sem);
-
cpufreq_proc_exit();
#ifdef CONFIG_CPU_FREQ_24_API
cpufreq_sysctl_exit();
#endif
+ /* remove this workaround as soon as interface_add_data works */
+ {
+ unsigned int i;
+ for (i=0; i<NR_CPUS; i++) {
+ if (cpu_online(i))
+ cpufreq_remove_dev(&cpufreq_driver->policy[i].intf);
+ }
+ }
+
+ interface_unregister(&cpufreq_interface);
+
+ if (driver)
+ kfree(cpufreq_driver->policy);
+ cpufreq_driver = NULL;
+
+ up(&cpufreq_driver_sem);
+
return 0;
}
-EXPORT_SYMBOL_GPL(cpufreq_unregister);
+EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
#ifdef CONFIG_PM