Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Sat, 28 Sep 2002 05:27:20 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Sat, 28 Sep 2002 05:27:20 -0400 Received: from natwar.webmailer.de ([192.67.198.70]:28554 "EHLO post.webmailer.de") by vger.kernel.org with ESMTP id ; Sat, 28 Sep 2002 05:26:55 -0400 Date: Sat, 28 Sep 2002 11:22:29 +0200 From: Dominik Brodowski To: torvalds@transmeta.com, linux-kernel@vger.kernel.org Cc: hpa@zytor.com, cpufreq@www.linux.org.uk Subject: [2.5.39] (1/5) CPUfreq core Message-ID: <20020928112229.B1217@brodo.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.16i Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 24506 Lines: 875 CPUFreq core for 2.5.39 include/linux/cpufreq.h CPUFreq header kernel/Makefile add cpufreq.c if necessary kernel/cpufreq.c CPUFreq core diff -ruN linux-2539original/include/linux/cpufreq.h linux/include/linux/cpufreq.h --- linux-2539original/include/linux/cpufreq.h Thu Jan 1 01:00:00 1970 +++ linux/include/linux/cpufreq.h Sat Sep 28 09:30:00 2002 @@ -0,0 +1,158 @@ +/* + * linux/include/linux/cpufreq.h + * + * Copyright (C) 2001 Russell King + * (C) 2002 Dominik Brodowski + * + * + * $Id: cpufreq.h,v 1.26 2002/09/21 09:05:29 db Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _LINUX_CPUFREQ_H +#define _LINUX_CPUFREQ_H + +#include +#include +#include + + +/********************************************************************* + * CPUFREQ NOTIFIER INTERFACE * + *********************************************************************/ + +int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); +int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); + +#define CPUFREQ_TRANSITION_NOTIFIER (0) +#define CPUFREQ_POLICY_NOTIFIER (1) + +#define CPUFREQ_ALL_CPUS ((NR_CPUS)) + + +/********************** cpufreq policy notifiers *********************/ + +#define CPUFREQ_POLICY_POWERSAVE (1) +#define CPUFREQ_POLICY_PERFORMANCE (2) + +/* values here are CPU kHz so that hardware which doesn't run with some + * frequencies can complain without having to guess what per cent / per + * mille means. */ +struct cpufreq_policy { + unsigned int cpu; /* cpu nr or CPUFREQ_ALL_CPUS */ + unsigned int min; /* in kHz */ + unsigned int max; /* in kHz */ + unsigned int policy; /* see above */ + unsigned int max_cpu_freq; /* for information */ +}; + +#define CPUFREQ_ADJUST (0) +#define CPUFREQ_INCOMPATIBLE (1) +#define CPUFREQ_NOTIFY (2) + + +/******************** cpufreq transition notifiers *******************/ + +#define CPUFREQ_PRECHANGE (0) +#define CPUFREQ_POSTCHANGE (1) + +struct cpufreq_freqs { + unsigned int cpu; /* cpu nr or CPUFREQ_ALL_CPUS */ + unsigned int old; + unsigned int new; +}; + + +/** + * cpufreq_scale - "old * mult / div" calculation for large values (32-bit-arch safe) + * @old: old value + * @div: divisor + * @mult: multiplier + * + * Needed for loops_per_jiffy and similar calculations. We do it + * this way to avoid math overflow on 32-bit machines. This will + * become architecture dependent once high-resolution-timer is + * merged (or any other thing that introduces sc_math.h). + * + * new = old * mult / div + */ +static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mult) +{ + unsigned long val, carry; + + mult /= 100; + div /= 100; + val = (old / div) * mult; + carry = old % div; + carry = carry * mult / div; + + return carry + val; +}; + + +/********************************************************************* + * DYNAMIC CPUFREQ INTERFACE * + *********************************************************************/ +#ifdef CONFIG_CPU_FREQ_DYNAMIC +/* TBD */ +#endif /* CONFIG_CPU_FREQ_DYNAMIC */ + + +/********************************************************************* + * CPUFREQ DRIVER INTERFACE * + *********************************************************************/ + +typedef void (*cpufreq_policy_t) (struct cpufreq_policy *policy); + +struct cpufreq_driver { + /* needed by all drivers */ + cpufreq_policy_t verify; + cpufreq_policy_t setpolicy; + struct cpufreq_policy *policy; +#ifdef CONFIG_CPU_FREQ_DYNAMIC + /* TBD */ +#endif + /* 2.4. compatible API */ +#ifdef CONFIG_CPU_FREQ_24_API + unsigned int cpu_min_freq; + unsigned int cpu_cur_freq[NR_CPUS]; +#endif +}; + +int cpufreq_register(struct cpufreq_driver *driver_data); +int cpufreq_unregister(void); + +void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state); + + +static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned int min, unsigned int max) +{ + if (policy->min < min) + policy->min = min; + if (policy->max < min) + policy->max = min; + if (policy->min > max) + policy->min = max; + if (policy->max > max) + policy->max = max; + if (policy->min > policy->max) + policy->min = policy->max; + return; +} + +/********************************************************************* + * CPUFREQ 2.6. INTERFACE * + *********************************************************************/ +int cpufreq_set_policy(struct cpufreq_policy *policy); +int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); + +#ifdef CONFIG_CPU_FREQ_26_API +#ifdef CONFIG_PM +int cpufreq_restore(void); +#endif +#endif + + +#endif /* _LINUX_CPUFREQ_H */ diff -ruN linux-2539original/kernel/Makefile linux/kernel/Makefile --- linux-2539original/kernel/Makefile Tue Sep 17 09:00:00 2002 +++ linux/kernel/Makefile Sat Sep 28 09:30:00 2002 @@ -3,7 +3,7 @@ # export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \ - printk.o platform.o suspend.o dma.o module.o + printk.o platform.o suspend.o dma.o module.o cpufreq.o obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o time.o softirq.o resource.o \ @@ -16,6 +16,7 @@ obj-$(CONFIG_MODULES) += ksyms.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PM) += pm.o +obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o diff -ruN linux-2539original/kernel/cpufreq.c linux/kernel/cpufreq.c --- linux-2539original/kernel/cpufreq.c Thu Jan 1 01:00:00 1970 +++ linux/kernel/cpufreq.c Sat Sep 28 09:30:00 2002 @@ -0,0 +1,678 @@ +/* + * linux/kernel/cpufreq.c + * + * Copyright (C) 2001 Russell King + * (C) 2002 Dominik Brodowski + * + * $Id: cpufreq.c,v 1.43 2002/09/21 09:05:29 db Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_CPU_FREQ_26_API +#include +#endif + + + +/** + * The "cpufreq driver" - the arch- or hardware-dependend low + * level driver of CPUFreq support, and its locking mutex. + * cpu_max_freq is in kHz. + */ +static struct cpufreq_driver *cpufreq_driver; +static DECLARE_MUTEX (cpufreq_driver_sem); + + +/** + * Two notifier lists: the "policy" list is involved in the + * validation process for a new CPU frequency policy; the + * "transition" list for kernel code that needs to handle + * changes to devices when the CPU clock speed changes. + * The mutex locks both lists. If both cpufreq_driver_sem + * and cpufreq_notifier_sem need to be hold, get cpufreq_driver_sem + * first. + */ +static struct notifier_block *cpufreq_policy_notifier_list; +static struct notifier_block *cpufreq_transition_notifier_list; +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, +}; + + + +/********************************************************************* + * 2.6. API * + *********************************************************************/ + +/** + * cpufreq_parse_policy - parse a policy string + * @input_string: the string to parse. + * @policy: the policy written inside input_string + * + * This function parses a "policy string" - something the user echo'es into + * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy. + * If there are invalid/missing entries, they are replaced with current + * cpufreq policy. + */ +static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy) +{ + unsigned int min = 0; + unsigned int max = 0; + unsigned int cpu = 0; + char policy_string[42] = {'\0'}; + struct cpufreq_policy current_policy; + unsigned int result = -EFAULT; + unsigned int i = 0; + + if (!policy) + return -EINVAL; + + policy->min = 0; + policy->max = 0; + policy->policy = 0; + policy->cpu = CPUFREQ_ALL_CPUS; + + if (sscanf(input_string, "%d:%d:%d:%s", &cpu, &min, &max, policy_string) == 4) + { + policy->min = min; + policy->max = max; + policy->cpu = cpu; + result = 0; + goto scan_policy; + } + if (sscanf(input_string, "%d%%%d%%%d%%%s", &cpu, &min, &max, policy_string) == 4) + { + if (!cpufreq_get_policy(¤t_policy, cpu)) { + policy->min = (min * current_policy.max_cpu_freq) / 100; + policy->max = (max * current_policy.max_cpu_freq) / 100; + policy->cpu = cpu; + result = 0; + goto scan_policy; + } + } + + if (sscanf(input_string, "%d:%d:%s", &min, &max, policy_string) == 3) + { + policy->min = min; + policy->max = max; + result = 0; + goto scan_policy; + } + + if (sscanf(input_string, "%d%%%d%%%s", &min, &max, policy_string) == 3) + { + if (!cpufreq_get_policy(¤t_policy, cpu)) { + policy->min = (min * current_policy.max_cpu_freq) / 100; + policy->max = (max * current_policy.max_cpu_freq) / 100; + result = 0; + goto scan_policy; + } + } + + return -EINVAL; + +scan_policy: + + for (i=0;ipolicy = CPUFREQ_POLICY_POWERSAVE; + } + else if (!strncmp(policy_string, "performance",6) || + !strncmp(policy_string, "high",4) || + !strncmp(policy_string, "full",4)) + { + result = 0; + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + } + else if (!cpufreq_get_policy(¤t_policy, policy->cpu)) + { + policy->policy = current_policy.policy; + } + else + { + policy->policy = 0; + } + + return result; +} + + +/* + * 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); + + +#ifdef CONFIG_CPU_FREQ_26_API +#ifdef CONFIG_PROC_FS + +/** + * cpufreq_proc_read - read /proc/cpufreq + * + * This function prints out the current cpufreq policy. + */ +static int cpufreq_proc_read ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *data) +{ + char *p = page; + int len = 0; + struct cpufreq_policy policy; + unsigned int min_pctg = 0; + unsigned int max_pctg = 0; + unsigned int i = 0; + + if (off != 0) + goto end; + + p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n"); + for (i=0;icount) + len = count; + if (len<0) + len = 0; + + return len; +} + + +/** + * cpufreq_proc_write - handles writing into /proc/cpufreq + * + * This function calls the parsing script and then sets the policy + * accordingly. + */ +static int cpufreq_proc_write ( + struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int result = 0; + char proc_string[42] = {'\0'}; + struct cpufreq_policy policy; + + + if ((count > sizeof(proc_string) - 1)) + return -EINVAL; + + if (copy_from_user(proc_string, buffer, count)) + return -EFAULT; + + proc_string[count] = '\0'; + + result = cpufreq_parse_policy(proc_string, &policy); + if (result) + return -EFAULT; + + cpufreq_set_policy(&policy); + + return count; +} + + +/** + * cpufreq_proc_init - add "cpufreq" to the /proc root directory + * + * This function adds "cpufreq" to the /proc root directory. + */ +static unsigned int cpufreq_proc_init (void) +{ + struct proc_dir_entry *entry = NULL; + + /* are these acceptable values? */ + entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR, + &proc_root); + + if (!entry) { + printk(KERN_ERR "unable to create /proc/cpufreq entry\n"); + return -EIO; + } else { + entry->read_proc = cpufreq_proc_read; + entry->write_proc = cpufreq_proc_write; + } + + return 0; +} + + +/** + * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory. + * + * This function removes "cpufreq" from the /proc root directory. + */ +static void cpufreq_proc_exit (void) +{ + remove_proc_entry("cpufreq", &proc_root); + return; +} +#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_CPU_FREQ_26_API */ + + + +/********************************************************************* + * NOTIFIER LISTS INTERFACE * + *********************************************************************/ + +/** + * cpufreq_register_notifier - register a driver with cpufreq + * @nb: notifier function to register + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER + * + * Add a driver to one of two lists: either a list of drivers that + * are notified about clock rate changes (once before and once after + * the transition), or a list of drivers that are notified about + * changes in cpufreq policy. + * + * This function may sleep, and has the same return conditions as + * notifier_chain_register. + */ +int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) +{ + int ret; + + down(&cpufreq_notifier_sem); + switch (list) { + case CPUFREQ_TRANSITION_NOTIFIER: + ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb); + break; + case CPUFREQ_POLICY_NOTIFIER: + ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb); + break; + default: + ret = -EINVAL; + } + up(&cpufreq_notifier_sem); + + return ret; +} +EXPORT_SYMBOL(cpufreq_register_notifier); + + +/** + * cpufreq_unregister_notifier - unregister a driver with cpufreq + * @nb: notifier block to be unregistered + * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER + * + * Remove a driver from the CPU frequency notifier list. + * + * This function may sleep, and has the same return conditions as + * notifier_chain_unregister. + */ +int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) +{ + int ret; + + down(&cpufreq_notifier_sem); + switch (list) { + case CPUFREQ_TRANSITION_NOTIFIER: + ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb); + break; + case CPUFREQ_POLICY_NOTIFIER: + ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb); + break; + default: + ret = -EINVAL; + } + up(&cpufreq_notifier_sem); + + return ret; +} +EXPORT_SYMBOL(cpufreq_unregister_notifier); + + + +/********************************************************************* + * POLICY INTERFACE * + *********************************************************************/ + +/** + * cpufreq_get_policy - get the current cpufreq_policy + * @policy: struct cpufreq_policy into which the current cpufreq_policy is written + * + * Reads the current cpufreq policy. + */ +int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) +{ + down(&cpufreq_driver_sem); + if (!cpufreq_driver || !policy || + (cpu >= NR_CPUS) || (!cpu_online(cpu))) { + up(&cpufreq_driver_sem); + return -EINVAL; + } + + policy->min = cpufreq_driver->policy[cpu].min; + policy->max = cpufreq_driver->policy[cpu].max; + policy->policy = cpufreq_driver->policy[cpu].policy; + policy->max_cpu_freq = cpufreq_driver->policy[0].max_cpu_freq; + policy->cpu = cpu; + + up(&cpufreq_driver_sem); + + return 0; +} + + +/** + * cpufreq_set_policy - set a new CPUFreq policy + * @policy: policy to be set. + * + * Sets a new CPU frequency and voltage scaling policy. + */ +int cpufreq_set_policy(struct cpufreq_policy *policy) +{ + unsigned int i; + + down(&cpufreq_driver_sem); + if (!cpufreq_driver || !cpufreq_driver->verify || + !cpufreq_driver->setpolicy || !policy || + (policy->cpu > NR_CPUS)) { + up(&cpufreq_driver_sem); + return -EINVAL; + } + + down(&cpufreq_notifier_sem); + + policy->max_cpu_freq = cpufreq_driver->policy[0].max_cpu_freq; + + /* verify the cpu speed can be set within this limit */ + cpufreq_driver->verify(policy); + + /* adjust if neccessary - all reasons */ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, + policy); + + /* adjust if neccessary - hardware incompatibility*/ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE, + policy); + + /* verify the cpu speed can be set within this limit, + which might be different to the first one */ + cpufreq_driver->verify(policy); + + /* notification of the new policy */ + notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, + policy); + + up(&cpufreq_notifier_sem); + + if (policy->cpu == CPUFREQ_ALL_CPUS) { + for (i=0;ipolicy[i].min = policy->min; + cpufreq_driver->policy[i].max = policy->max; + cpufreq_driver->policy[i].policy = policy->policy; + } + } else { + cpufreq_driver->policy[policy->cpu].min = policy->min; + cpufreq_driver->policy[policy->cpu].max = policy->max; + cpufreq_driver->policy[policy->cpu].policy = policy->policy; + } + + cpufreq_driver->setpolicy(policy); + + up(&cpufreq_driver_sem); + + return 0; +} +EXPORT_SYMBOL(cpufreq_set_policy); + + + +/********************************************************************* + * DYNAMIC CPUFREQ SWITCHING * + *********************************************************************/ +#ifdef CONFIG_CPU_FREQ_DYNAMIC +/* TBD */ +#endif /* CONFIG_CPU_FREQ_DYNAMIC */ + + + +/********************************************************************* + * EXTERNALLY AFFECTING FREQUENCY CHANGES * + *********************************************************************/ + +/** + * adjust_jiffies - adjust the system "loops_per_jiffy" + * + * This function alters the system "loops_per_jiffy" for the clock + * speed change. Note that loops_per_jiffy is only updated if all + * CPUs are affected - else there is a need for per-CPU loops_per_jiffy + * values which are provided by various architectures. + */ +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) +{ + if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || + (val == CPUFREQ_POSTCHANGE && ci->old > ci->new)) + if (ci->cpu == CPUFREQ_ALL_CPUS) + loops_per_jiffy = cpufreq_scale(loops_per_jiffy, ci->old, ci->new); +} + + +/** + * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition + * + * This function calls the transition notifiers and the "adjust_jiffies" function. It is called + * twice on all CPU frequency changes that have external effects. + */ +void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) +{ + down(&cpufreq_notifier_sem); + switch (state) { + case CPUFREQ_PRECHANGE: + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); + adjust_jiffies(CPUFREQ_PRECHANGE, freqs); + break; + case CPUFREQ_POSTCHANGE: + adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); + break; + } + up(&cpufreq_notifier_sem); +} +EXPORT_SYMBOL_GPL(cpufreq_notify_transition); + + + +/********************************************************************* + * REGISTER / UNREGISTER CPUFREQ DRIVER * + *********************************************************************/ + +/** + * cpufreq_register - 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) +{ + unsigned int ret; + + if (cpufreq_driver) + return -EBUSY; + + if (!driver_data || !driver_data->verify || + !driver_data->setpolicy) + return -EINVAL; + + down(&cpufreq_driver_sem); + cpufreq_driver = driver_data; + + if (!default_policy.policy) + default_policy.policy = driver_data->policy[0].policy; + if (!default_policy.min) + default_policy.min = driver_data->policy[0].min; + if (!default_policy.max) + default_policy.max = driver_data->policy[0].max; + default_policy.cpu = CPUFREQ_ALL_CPUS; + + up(&cpufreq_driver_sem); + + ret = cpufreq_set_policy(&default_policy); + +#ifdef CONFIG_CPU_FREQ_26_API + cpufreq_proc_init(); +#endif + + if (ret) { + down(&cpufreq_driver_sem); + cpufreq_driver = NULL; + up(&cpufreq_driver_sem); + } + + return ret; +} +EXPORT_SYMBOL_GPL(cpufreq_register); + + +/** + * cpufreq_unregister - 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) +{ + down(&cpufreq_driver_sem); + + if (!cpufreq_driver) { + up(&cpufreq_driver_sem); + return -EINVAL; + } + + cpufreq_driver = NULL; + + up(&cpufreq_driver_sem); + +#ifdef CONFIG_CPU_FREQ_26_API + cpufreq_proc_exit(); +#endif + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_unregister); + + +#ifdef CONFIG_PM +/** + * cpufreq_restore - restore the CPU clock frequency after resume + * + * Restore the CPU clock frequency so that our idea of the current + * frequency reflects the actual hardware. + */ +int cpufreq_restore(void) +{ + struct cpufreq_policy policy; + unsigned int i; + + if (in_interrupt()) + panic("cpufreq_restore() called from interrupt context!"); + + for (i=0;ipolicy[i].min; + policy.max = cpufreq_driver->policy[i].max; + policy.policy = cpufreq_driver->policy[i].policy; + policy.cpu = i; + up(&cpufreq_driver_sem); + +#ifdef CONFIG_CPU_FREQ_26_API + cpufreq_set_policy(&policy); +#endif + } + + return 0; +} +EXPORT_SYMBOL_GPL(cpufreq_restore); +#else +#define cpufreq_restore() +#endif /* CONFIG_PM */ + - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/