Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
4eabfbb6
Commit
4eabfbb6
authored
Jul 08, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linux-dj.bkbits.net/cpufreq
into home.osdl.org:/home/torvalds/v2.5/linux
parents
85bce232
2342d6cb
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
109 additions
and
104 deletions
+109
-104
Documentation/cpu-freq/user-guide.txt
Documentation/cpu-freq/user-guide.txt
+16
-0
drivers/cpufreq/Makefile
drivers/cpufreq/Makefile
+5
-2
drivers/cpufreq/proc_intf.c
drivers/cpufreq/proc_intf.c
+2
-0
include/linux/cpufreq.h
include/linux/cpufreq.h
+38
-35
kernel/cpufreq.c
kernel/cpufreq.c
+48
-67
No files found.
Documentation/cpu-freq/user-guide.txt
View file @
4eabfbb6
...
...
@@ -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" ?
==========================
...
...
drivers/cpufreq/Makefile
View file @
4eabfbb6
#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
drivers/cpufreq/proc_intf.c
View file @
4eabfbb6
...
...
@@ -13,6 +13,8 @@
#include <asm/uaccess.h>
#define CPUFREQ_ALL_CPUS ((NR_CPUS))
/**
* cpufreq_parse_policy - parse a policy string
* @input_string: the string to parse.
...
...
include/linux/cpufreq.h
View file @
4eabfbb6
...
...
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/completion.h>
#define CPUFREQ_NAME_LEN 16
...
...
@@ -31,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
...
...
@@ -52,30 +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 *******************/
...
...
@@ -84,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
;
};
...
...
@@ -125,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
...
...
@@ -154,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
;
};
...
...
@@ -306,8 +313,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 */
kernel/cpufreq.c
View file @
4eabfbb6
...
...
@@ -23,6 +23,7 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/completion.h>
/**
* 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
,
};
...
...
@@ -329,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
);
...
...
@@ -343,6 +349,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
;
...
...
@@ -352,18 +360,19 @@ 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
);
if
(
ret
)
if
(
ret
)
{
kobject_unregister
(
&
policy
->
kobj
);
wait_for_completion
(
&
policy
->
kobj_unregister
);
}
out:
module_put
(
cpufreq_driver
->
owner
);
...
...
@@ -401,10 +410,39 @@ 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
;
}
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
,
...
...
@@ -587,33 +625,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
;
i
<
NR_CPUS
;
i
++
)
{
if
(
!
cpufreq_cpu_get
(
i
))
continue
;
if
((
cpufreq_driver
->
policy
[
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
;
...
...
@@ -781,7 +796,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
);
...
...
@@ -859,37 +874,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 */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment