From 82f896e520c9108821755041164a21afad3e9cc2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 2 Jul 2003 23:50:41 +0100 Subject: [CPUFREQ] Fix stupid inverted FID/VID bug. Spotted by Luigi Belli --- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 91a8a25f635a..36181c7a0c64 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -268,8 +268,8 @@ static void change_speed (unsigned int index) change_VID(vid); } else { /* Going up, so change VID first */ - change_VID(fid); - change_FID(vid); + change_VID(vid); + change_FID(fid); } -- cgit v1.2.3 From b7d2869a30ecba2a19eaac29ef50bfd5d5851eea Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 2 Jul 2003 23:52:11 +0100 Subject: [CPUFREQ] update cpufreq docs to reflect newly merged architecture support From Dominik Brodowski --- Documentation/cpu-freq/user-guide.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt index fc206075944d..76934ca5030c 100644 --- a/Documentation/cpu-freq/user-guide.txt +++ b/Documentation/cpu-freq/user-guide.txt @@ -21,6 +21,8 @@ Contents: 1.1 ARM 1.2 x86 1.3 sparc64 +1.4 ppc +1.5 SuperH 2. "Policy" / "Governor"? 2.1 Policy @@ -77,6 +79,20 @@ cpufreq: UltraSPARC-III +1.4 ppc +------- + +Several "PowerBook" and "iBook2" notebooks are supported. + + +1.5 SuperH +---------- + +The following SuperH processors are supported by cpufreq: + +SH-3 +SH-4 + 2. "Policy" / "Governor" ? ========================== -- cgit v1.2.3 From 2c3b4f8952b94576e4958af9e821716545bee9cc Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 9 Jul 2003 18:19:20 +0100 Subject: [CPUFREQ] Misc cleanups. --- drivers/cpufreq/Makefile | 7 +++++-- include/linux/cpufreq.h | 4 ---- kernel/cpufreq.c | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index b05d3948b8e1..85b512348acd 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -1,4 +1,7 @@ -#CPUfreq governors and cross-arch helpers +# CPUfreq governors +obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o + +# CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o -obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o + diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 1bdb797bf9bd..a2fee295ae1a 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -306,8 +306,4 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu); #endif /* CONFIG_CPU_FREQ_TABLE */ - -/* Currently exported only for the proc interface, remove when that goes */ -extern struct cpufreq_driver *cpufreq_driver; - #endif /* _LINUX_CPUFREQ_H */ diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c index 6ae2b821830e..18245832d8c9 100644 --- a/kernel/cpufreq.c +++ b/kernel/cpufreq.c @@ -352,13 +352,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) if (ret) goto out; + /* set up files for this cpu device */ drv_attr = cpufreq_driver->attr; while ((drv_attr) && (*drv_attr)) { sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); drv_attr++; } - /* set up files for this cpu device */ - /* set default policy */ ret = cpufreq_set_policy(&new_policy); -- cgit v1.2.3 From 1c576b19a92e6a4b489c033d77bf2bd512fa7b8e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 9 Jul 2003 18:21:45 +0100 Subject: [CPUFREQ] kobj refcount fixes. Wait with the destruction of cpufreq objects until all references are gone (code partly based on rmk's comparable patch for the PCMCIA subsystem. From Dominik. --- include/linux/cpufreq.h | 2 ++ kernel/cpufreq.c | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index a2fee295ae1a..5a75fc3a69f2 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -20,6 +20,7 @@ #include #include #include +#include #define CPUFREQ_NAME_LEN 16 @@ -71,6 +72,7 @@ struct cpufreq_policy { struct kobject kobj; struct semaphore lock; /* CPU ->setpolicy or ->target may only be called once a time */ + struct completion kobj_unregister; }; #define CPUFREQ_ADJUST (0) diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c index 18245832d8c9..0701eed77ab4 100644 --- a/kernel/cpufreq.c +++ b/kernel/cpufreq.c @@ -23,6 +23,7 @@ #include #include #include +#include /** * The "cpufreq driver" - the arch- or hardware-dependend low @@ -297,6 +298,12 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr, return ret; } +static void cpufreq_sysfs_release(struct kobject * kobj) +{ + struct cpufreq_policy * policy = to_policy(kobj); + complete(&policy->kobj_unregister); +} + static struct sysfs_ops sysfs_ops = { .show = show, .store = store, @@ -305,6 +312,7 @@ static struct sysfs_ops sysfs_ops = { static struct kobj_type ktype_cpufreq = { .sysfs_ops = &sysfs_ops, .default_attrs = default_attrs, + .release = cpufreq_sysfs_release, }; @@ -343,6 +351,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) up(&cpufreq_driver_sem); init_MUTEX(&policy->lock); + init_completion(&policy->kobj_unregister); + /* prepare interface data */ policy->kobj.parent = &sys_dev->kobj; policy->kobj.ktype = &ktype_cpufreq; @@ -361,8 +371,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) /* set default policy */ ret = cpufreq_set_policy(&new_policy); - if (ret) + if (ret) { kobject_unregister(&policy->kobj); + wait_for_completion(&policy->kobj_unregister); + } out: module_put(cpufreq_driver->owner); @@ -400,6 +412,13 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) up(&cpufreq_driver_sem); kobject_put(&cpufreq_driver->policy[cpu].kobj); + + /* we need to make sure that the underlying kobj is actually + * destroyed before we proceed e.g. with cpufreq driver module + * unloading + */ + wait_for_completion(&cpufreq_driver->policy[cpu].kobj_unregister); + return 0; } -- cgit v1.2.3 From 3d48b9e4d663ada8969aaf5a0921c927303ef508 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 9 Jul 2003 18:24:22 +0100 Subject: [CPUFREQ] move cpufreq_restore(), and don't make it dependent on CONFIG_PM From Dominik. --- kernel/cpufreq.c | 58 ++++++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c index 0701eed77ab4..9e76d0bf8044 100644 --- a/kernel/cpufreq.c +++ b/kernel/cpufreq.c @@ -422,7 +422,29 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) return 0; } -static int cpufreq_restore(struct sys_device *); +/** + * 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. + */ +static int cpufreq_restore(struct sys_device * sysdev) +{ + int cpu = sysdev->id; + unsigned int ret = 0; + struct cpufreq_policy policy; + + if (cpu_online(cpu) && cpufreq_cpu_get(cpu)) { + down(&cpufreq_driver_sem); + memcpy(&policy, &cpufreq_driver->policy[cpu], + sizeof(struct cpufreq_policy)); + up(&cpufreq_driver_sem); + ret = cpufreq_set_policy(&policy); + cpufreq_cpu_put(cpu); + } + + return ret; +} static struct sysdev_driver cpufreq_sysdev_driver = { .add = cpufreq_add_dev, @@ -877,37 +899,3 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) return 0; } EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); - - -#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. - */ -static int cpufreq_restore(struct sys_device * sysdev) -{ - int cpu = sysdev->id; - unsigned int ret = 0; - struct cpufreq_policy policy; - - if (cpu_online(cpu) && cpufreq_cpu_get(cpu)) { - down(&cpufreq_driver_sem); - memcpy(&policy, &cpufreq_driver->policy[cpu], - sizeof(struct cpufreq_policy)); - up(&cpufreq_driver_sem); - ret = cpufreq_set_policy(&policy); - cpufreq_cpu_put(cpu); - } - - return ret; -} - -#else -static int cpufreq_restore(struct sys_device * sysdev) -{ - return 0; -} -#endif /* CONFIG_PM */ -- cgit v1.2.3 From 77533ee326ff0ef9ef9e18fd8fdba91d82371c1a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 9 Jul 2003 18:27:21 +0100 Subject: [CPUFREQ] don't care about "rmmod -f". It's expected to break things. More from Dominik --- kernel/cpufreq.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c index 9e76d0bf8044..435f6d2d2fd3 100644 --- a/kernel/cpufreq.c +++ b/kernel/cpufreq.c @@ -627,33 +627,10 @@ EXPORT_SYMBOL_GPL(cpufreq_register_governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor) { - unsigned int i; - if (!governor) return; down(&cpufreq_governor_sem); - - /* - * Unless the user uses rmmod -f, we can be safe. But we never - * know, so check whether if it's currently used. If so, - * stop it and replace it with the default governor. - */ - for (i=0; ipolicy[i].policy == CPUFREQ_POLICY_GOVERNOR) && - (cpufreq_driver->policy[i].governor == governor)) { - cpufreq_governor(i, CPUFREQ_GOV_STOP); - cpufreq_driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE; - cpufreq_governor(i, CPUFREQ_GOV_START); - cpufreq_governor(i, CPUFREQ_GOV_LIMITS); - } - cpufreq_cpu_put(i); - } - - /* now we can safely remove it from the list */ list_del(&governor->governor_list); up(&cpufreq_governor_sem); return; @@ -821,7 +798,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) switch (state) { case CPUFREQ_PRECHANGE: notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); - adjust_jiffies(CPUFREQ_PRECHANGE, freqs); + adjust_jiffies(CPUFREQ_PRECHANGE, freqs); break; case CPUFREQ_POSTCHANGE: adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); -- cgit v1.2.3 From 92175044130735b3c9a0ec3567d758903972f6e2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 9 Jul 2003 18:30:21 +0100 Subject: [CPUFREQ] More misc cleanups. - CPUFREQ_ALL_CPUS is not a valid argument any more, don't mention it in include/linux/cpufreq.h - without a driver->init() function a cpufreq driver isn't even loaded, so remove that check in the per-CPU initialization - whitespace and clarification changes to linux/cpufreq. All from Dominik again.. --- drivers/cpufreq/proc_intf.c | 2 ++ include/linux/cpufreq.h | 67 ++++++++++++++++++++++++--------------------- kernel/cpufreq.c | 8 ++---- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c index dc89b83710b8..d314e526af9c 100644 --- a/drivers/cpufreq/proc_intf.c +++ b/drivers/cpufreq/proc_intf.c @@ -13,6 +13,8 @@ #include +#define CPUFREQ_ALL_CPUS ((NR_CPUS)) + /** * cpufreq_parse_policy - parse a policy string * @input_string: the string to parse. diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 5a75fc3a69f2..dc29d5c4e713 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -32,17 +32,15 @@ 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)) +#define CPUFREQ_TRANSITION_NOTIFIER (0) +#define CPUFREQ_POLICY_NOTIFIER (1) /********************** cpufreq policy notifiers *********************/ -#define CPUFREQ_POLICY_POWERSAVE (1) -#define CPUFREQ_POLICY_PERFORMANCE (2) -#define CPUFREQ_POLICY_GOVERNOR (3) +#define CPUFREQ_POLICY_POWERSAVE (1) +#define CPUFREQ_POLICY_PERFORMANCE (2) +#define CPUFREQ_POLICY_GOVERNOR (3) /* Frequency values here are CPU kHz so that hardware which doesn't run * with some frequencies can complain without having to guess what per @@ -53,31 +51,34 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); struct cpufreq_governor; -#define CPUFREQ_ETERNAL (-1) +#define CPUFREQ_ETERNAL (-1) struct cpufreq_cpuinfo { - unsigned int max_freq; - unsigned int min_freq; - unsigned int transition_latency; + unsigned int max_freq; + unsigned int min_freq; + unsigned int transition_latency; /* in 10^(-9) s */ }; struct cpufreq_policy { - unsigned int cpu; /* cpu nr or CPUFREQ_ALL_CPUS */ - unsigned int min; /* in kHz */ - unsigned int max; /* in kHz */ - unsigned int cur; /* in kHz, only needed if cpufreq + unsigned int cpu; /* cpu nr */ + struct cpufreq_cpuinfo cpuinfo;/* see above */ + + unsigned int min; /* in kHz */ + unsigned int max; /* in kHz */ + unsigned int cur; /* in kHz, only needed if cpufreq * governors are used */ - unsigned int policy; /* see above */ - struct cpufreq_governor *governor; /* see below */ - struct cpufreq_cpuinfo cpuinfo; /* see above */ - struct kobject kobj; + unsigned int policy; /* see above */ + struct cpufreq_governor *governor; /* see below */ + struct semaphore lock; /* CPU ->setpolicy or ->target may only be called once a time */ + + struct kobject kobj; struct completion kobj_unregister; }; -#define CPUFREQ_ADJUST (0) -#define CPUFREQ_INCOMPATIBLE (1) -#define CPUFREQ_NOTIFY (2) +#define CPUFREQ_ADJUST (0) +#define CPUFREQ_INCOMPATIBLE (1) +#define CPUFREQ_NOTIFY (2) /******************** cpufreq transition notifiers *******************/ @@ -86,7 +87,7 @@ struct cpufreq_policy { #define CPUFREQ_POSTCHANGE (1) struct cpufreq_freqs { - unsigned int cpu; /* cpu nr or CPUFREQ_ALL_CPUS */ + unsigned int cpu; /* cpu nr */ unsigned int old; unsigned int new; }; @@ -127,11 +128,11 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu #define CPUFREQ_GOV_LIMITS 3 struct cpufreq_governor { - char name[CPUFREQ_NAME_LEN]; - int (*governor) (struct cpufreq_policy *policy, + char name[CPUFREQ_NAME_LEN]; + int (*governor) (struct cpufreq_policy *policy, unsigned int event); struct list_head governor_list; - struct module *owner; + struct module *owner; }; /* pass a target to the cpufreq driver @@ -156,18 +157,22 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor); struct freq_attr; struct cpufreq_driver { + struct module *owner; + char name[CPUFREQ_NAME_LEN]; + + struct cpufreq_policy *policy; + /* needed by all drivers */ + int (*init) (struct cpufreq_policy *policy); int (*verify) (struct cpufreq_policy *policy); - struct cpufreq_policy *policy; - char name[CPUFREQ_NAME_LEN]; + /* define one out of two */ int (*setpolicy) (struct cpufreq_policy *policy); int (*target) (struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); - struct module *owner; - /* optional, for the moment */ - int (*init) (struct cpufreq_policy *policy); + + /* optional */ int (*exit) (struct cpufreq_policy *policy); struct freq_attr **attr; }; diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c index 435f6d2d2fd3..f4864ce54aae 100644 --- a/kernel/cpufreq.c +++ b/kernel/cpufreq.c @@ -337,11 +337,9 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) */ policy = &cpufreq_driver->policy[cpu]; policy->cpu = cpu; - if (cpufreq_driver->init) { - ret = cpufreq_driver->init(policy); - if (ret) - goto out; - } + ret = cpufreq_driver->init(policy); + if (ret) + goto out; /* set default policy on this CPU */ down(&cpufreq_driver_sem); -- cgit v1.2.3