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
055f27cd
Commit
055f27cd
authored
Mar 08, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linux-dj.bkbits.net/cpufreq
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
f8546efb
4656c707
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
397 additions
and
319 deletions
+397
-319
Documentation/cpu-freq/core.txt
Documentation/cpu-freq/core.txt
+4
-0
Documentation/cpu-freq/cpu-drivers.txt
Documentation/cpu-freq/cpu-drivers.txt
+3
-0
Documentation/cpu-freq/user-guide.txt
Documentation/cpu-freq/user-guide.txt
+4
-4
arch/i386/kernel/cpu/cpufreq/acpi.c
arch/i386/kernel/cpu/cpufreq/acpi.c
+1
-0
arch/i386/kernel/cpu/cpufreq/elanfreq.c
arch/i386/kernel/cpu/cpufreq/elanfreq.c
+1
-0
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+1
-0
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/longhaul.c
+1
-0
arch/i386/kernel/cpu/cpufreq/longrun.c
arch/i386/kernel/cpu/cpufreq/longrun.c
+1
-0
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+8
-0
arch/i386/kernel/cpu/cpufreq/powernow-k6.c
arch/i386/kernel/cpu/cpufreq/powernow-k6.c
+1
-0
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+1
-0
arch/i386/kernel/cpu/cpufreq/speedstep.c
arch/i386/kernel/cpu/cpufreq/speedstep.c
+13
-2
arch/sparc64/kernel/us3_cpufreq.c
arch/sparc64/kernel/us3_cpufreq.c
+1
-0
drivers/cpufreq/freq_table.c
drivers/cpufreq/freq_table.c
+50
-50
drivers/cpufreq/userspace.c
drivers/cpufreq/userspace.c
+13
-18
include/linux/cpufreq.h
include/linux/cpufreq.h
+25
-14
include/linux/pci_ids.h
include/linux/pci_ids.h
+1
-0
kernel/cpufreq.c
kernel/cpufreq.c
+268
-231
No files found.
Documentation/cpu-freq/core.txt
View file @
055f27cd
...
...
@@ -35,6 +35,10 @@ speed limits (like LCD drivers on ARM architecture). Additionally, the
kernel "constant" loops_per_jiffy is updated on frequency changes
here.
Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
which make sure that the cpufreq processor driver is correctly
registered with the core, and will not be unloaded until
cpufreq_put_cpu is called.
2. CPUFreq notifiers
====================
...
...
Documentation/cpu-freq/cpu-drivers.txt
View file @
055f27cd
...
...
@@ -63,6 +63,9 @@ And optionally
cpufreq_driver.exit - A pointer to a per-CPU cleanup function.
cpufreq_driver.attr - A pointer to a NULL-terminated list of
"struct freq_attr" which allow to
export values to sysfs.
1.2 Per-CPU Initialization
...
...
Documentation/cpu-freq/user-guide.txt
View file @
055f27cd
...
...
@@ -114,9 +114,9 @@ the processor shall run at.
------------------------------
The preferred interface is located in the sysfs filesystem. If you
mounted it at /sys, the cpufreq interface is located in
the
cpu-device directory (e.g. /sys/devices/sys/cpu0/ for the first
CPU).
mounted it at /sys, the cpufreq interface is located in
a subdirectory
"cpufreq" within the cpu-device directory
(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first
CPU).
cpuinfo_min_freq : this file shows the minimum operating
frequency the processor can run at(in kHz)
...
...
@@ -125,7 +125,7 @@ cpuinfo_max_freq : this file shows the maximum operating
scaling_driver : this file shows what cpufreq driver is
used to set the frequency on this CPU
available_scaling
_governors : this file shows the CPUfreq governors
scaling_available
_governors : this file shows the CPUfreq governors
available in this kernel. You can see the
currently activated governor in
...
...
arch/i386/kernel/cpu/cpufreq/acpi.c
View file @
055f27cd
...
...
@@ -619,6 +619,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.
init
=
acpi_cpufreq_cpu_init
,
.
exit
=
acpi_cpufreq_cpu_exit
,
.
name
=
"acpi-cpufreq"
,
.
owner
=
THIS_MODULE
,
};
...
...
arch/i386/kernel/cpu/cpufreq/elanfreq.c
View file @
055f27cd
...
...
@@ -250,6 +250,7 @@ static struct cpufreq_driver elanfreq_driver = {
.
target
=
elanfreq_target
,
.
init
=
elanfreq_cpu_init
,
.
name
=
"elanfreq"
,
.
owner
=
THIS_MODULE
,
};
...
...
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
View file @
055f27cd
...
...
@@ -451,6 +451,7 @@ static struct cpufreq_driver gx_suspmod_driver = {
.
target
=
cpufreq_gx_target
,
.
init
=
cpufreq_gx_cpu_init
,
.
name
=
"gx-suspmod"
,
.
owner
=
THIS_MODULE
,
};
static
int
__init
cpufreq_gx_init
(
void
)
...
...
arch/i386/kernel/cpu/cpufreq/longhaul.c
View file @
055f27cd
...
...
@@ -649,6 +649,7 @@ static struct cpufreq_driver longhaul_driver = {
.
target
=
longhaul_target
,
.
init
=
longhaul_cpu_init
,
.
name
=
"longhaul"
,
.
owner
=
THIS_MODULE
,
};
static
int
__init
longhaul_init
(
void
)
...
...
arch/i386/kernel/cpu/cpufreq/longrun.c
View file @
055f27cd
...
...
@@ -253,6 +253,7 @@ static struct cpufreq_driver longrun_driver = {
.
setpolicy
=
longrun_set_policy
,
.
init
=
longrun_cpu_init
,
.
name
=
"longrun"
,
.
owner
=
THIS_MODULE
,
};
...
...
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
View file @
055f27cd
...
...
@@ -214,6 +214,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
else
p4clockmod_table
[
i
].
frequency
=
(
stock_freq
*
i
)
/
8
;
}
cpufreq_frequency_table_get_attr
(
p4clockmod_table
,
policy
->
cpu
);
/* cpuinfo and default policy values */
policy
->
policy
=
CPUFREQ_POLICY_PERFORMANCE
;
...
...
@@ -226,9 +227,14 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
static
int
cpufreq_p4_cpu_exit
(
struct
cpufreq_policy
*
policy
)
{
cpufreq_frequency_table_put_attr
(
policy
->
cpu
);
return
cpufreq_p4_setdc
(
policy
->
cpu
,
DC_DISABLE
);
}
static
struct
freq_attr
*
p4clockmod_attr
[]
=
{
&
cpufreq_freq_attr_scaling_available_freqs
,
NULL
,
};
static
struct
cpufreq_driver
p4clockmod_driver
=
{
.
verify
=
cpufreq_p4_verify
,
...
...
@@ -236,6 +242,8 @@ static struct cpufreq_driver p4clockmod_driver = {
.
init
=
cpufreq_p4_cpu_init
,
.
exit
=
cpufreq_p4_cpu_exit
,
.
name
=
"p4-clockmod"
,
.
owner
=
THIS_MODULE
,
.
attr
=
p4clockmod_attr
,
};
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k6.c
View file @
055f27cd
...
...
@@ -190,6 +190,7 @@ static struct cpufreq_driver powernow_k6_driver = {
.
init
=
powernow_k6_cpu_init
,
.
exit
=
powernow_k6_cpu_exit
,
.
name
=
"powernow-k6"
,
.
owner
=
THIS_MODULE
,
};
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
View file @
055f27cd
...
...
@@ -377,6 +377,7 @@ static struct cpufreq_driver powernow_driver = {
.
target
=
powernow_target
,
.
init
=
powernow_cpu_init
,
.
name
=
"powernow-k7"
,
.
owner
=
THIS_MODULE
,
};
static
int
__init
powernow_init
(
void
)
...
...
arch/i386/kernel/cpu/cpufreq/speedstep.c
View file @
055f27cd
...
...
@@ -29,7 +29,6 @@
#include <asm/msr.h>
/* speedstep_chipset:
* It is necessary to know which chipset is used. As accesses to
* this device occur at various places in this module, we need a
...
...
@@ -40,7 +39,7 @@ static struct pci_dev *speedstep_chipset_dev;
#define SPEEDSTEP_CHIPSET_ICH2M 0x00000002
#define SPEEDSTEP_CHIPSET_ICH3M 0x00000003
#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004
/* speedstep_processor
*/
...
...
@@ -106,6 +105,7 @@ static int speedstep_get_state (unsigned int *state)
switch
(
speedstep_chipset
)
{
case
SPEEDSTEP_CHIPSET_ICH2M
:
case
SPEEDSTEP_CHIPSET_ICH3M
:
case
SPEEDSTEP_CHIPSET_ICH4M
:
/* get PMBASE */
pci_read_config_dword
(
speedstep_chipset_dev
,
0x40
,
&
pmbase
);
if
(
!
(
pmbase
&
0x01
))
...
...
@@ -166,6 +166,7 @@ static void speedstep_set_state (unsigned int state, int notify)
switch
(
speedstep_chipset
)
{
case
SPEEDSTEP_CHIPSET_ICH2M
:
case
SPEEDSTEP_CHIPSET_ICH3M
:
case
SPEEDSTEP_CHIPSET_ICH4M
:
/* get PMBASE */
pci_read_config_dword
(
speedstep_chipset_dev
,
0x40
,
&
pmbase
);
if
(
!
(
pmbase
&
0x01
))
...
...
@@ -245,6 +246,7 @@ static int speedstep_activate (void)
switch
(
speedstep_chipset
)
{
case
SPEEDSTEP_CHIPSET_ICH2M
:
case
SPEEDSTEP_CHIPSET_ICH3M
:
case
SPEEDSTEP_CHIPSET_ICH4M
:
{
u16
value
=
0
;
...
...
@@ -276,6 +278,14 @@ static int speedstep_activate (void)
*/
static
unsigned
int
speedstep_detect_chipset
(
void
)
{
speedstep_chipset_dev
=
pci_find_subsys
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82801DB_12
,
PCI_ANY_ID
,
PCI_ANY_ID
,
NULL
);
if
(
speedstep_chipset_dev
)
return
SPEEDSTEP_CHIPSET_ICH4M
;
speedstep_chipset_dev
=
pci_find_subsys
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82801CA_12
,
PCI_ANY_ID
,
...
...
@@ -658,6 +668,7 @@ static struct cpufreq_driver speedstep_driver = {
.
verify
=
speedstep_verify
,
.
target
=
speedstep_target
,
.
init
=
speedstep_cpu_init
,
.
owner
=
THIS_MODULE
,
};
...
...
arch/sparc64/kernel/us3_cpufreq.c
View file @
055f27cd
...
...
@@ -276,6 +276,7 @@ static int __init us3freq_init(void)
driver
->
target
=
us3freq_target
;
driver
->
init
=
us3freq_cpu_init
;
driver
->
exit
=
us3freq_cpu_exit
;
driver
->
owner
=
THIS_MODULE
,
strcpy
(
driver
->
name
,
"UltraSPARC-III"
);
cpufreq_us3_driver
=
driver
;
...
...
drivers/cpufreq/freq_table.c
View file @
055f27cd
...
...
@@ -77,56 +77,6 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_verify
);
int
cpufreq_frequency_table_setpolicy
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_frequency_table
*
table
,
unsigned
int
*
index
)
{
struct
cpufreq_frequency_table
optimal
=
{
.
index
=
~
0
,
};
unsigned
int
i
;
switch
(
policy
->
policy
)
{
case
CPUFREQ_POLICY_PERFORMANCE
:
optimal
.
frequency
=
0
;
break
;
case
CPUFREQ_POLICY_POWERSAVE
:
optimal
.
frequency
=
~
0
;
break
;
}
if
(
!
cpu_online
(
policy
->
cpu
))
return
-
EINVAL
;
for
(
i
=
0
;
(
table
[
i
].
frequency
!=
CPUFREQ_TABLE_END
);
i
++
)
{
unsigned
int
freq
=
table
[
i
].
frequency
;
if
(
freq
==
CPUFREQ_ENTRY_INVALID
)
continue
;
if
((
freq
<
policy
->
min
)
||
(
freq
>
policy
->
max
))
continue
;
switch
(
policy
->
policy
)
{
case
CPUFREQ_POLICY_PERFORMANCE
:
if
(
optimal
.
frequency
<=
freq
)
{
optimal
.
frequency
=
freq
;
optimal
.
index
=
i
;
}
break
;
case
CPUFREQ_POLICY_POWERSAVE
:
if
(
optimal
.
frequency
>=
freq
)
{
optimal
.
frequency
=
freq
;
optimal
.
index
=
i
;
}
break
;
}
}
if
(
optimal
.
index
>
i
)
return
-
EINVAL
;
*
index
=
optimal
.
index
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_setpolicy
);
int
cpufreq_frequency_table_target
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_frequency_table
*
table
,
unsigned
int
target_freq
,
...
...
@@ -197,6 +147,56 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
}
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_target
);
static
struct
cpufreq_frequency_table
*
show_table
[
NR_CPUS
];
/**
* show_scaling_governor - show the current policy for the specified CPU
*/
static
ssize_t
show_available_freqs
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
unsigned
int
i
=
0
;
unsigned
int
cpu
=
policy
->
cpu
;
ssize_t
count
=
0
;
struct
cpufreq_frequency_table
*
table
;
if
(
!
show_table
[
cpu
])
return
-
ENODEV
;
table
=
show_table
[
cpu
];
for
(
i
=
0
;
(
table
[
i
].
frequency
!=
CPUFREQ_TABLE_END
);
i
++
)
{
if
(
table
[
i
].
frequency
==
CPUFREQ_ENTRY_INVALID
)
continue
;
count
+=
sprintf
(
&
buf
[
count
],
"%d "
,
table
[
i
].
frequency
);
}
count
+=
sprintf
(
&
buf
[
count
],
"
\n
"
);
return
count
;
}
struct
freq_attr
cpufreq_freq_attr_scaling_available_freqs
=
{
.
attr
=
{
.
name
=
"scaling_available_frequencies"
,
.
mode
=
0444
},
.
show
=
show_available_freqs
,
};
EXPORT_SYMBOL_GPL
(
cpufreq_freq_attr_scaling_available_freqs
);
/*
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
*/
void
cpufreq_frequency_table_get_attr
(
struct
cpufreq_frequency_table
*
table
,
unsigned
int
cpu
)
{
show_table
[
cpu
]
=
table
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_get_attr
);
void
cpufreq_frequency_table_put_attr
(
unsigned
int
cpu
)
{
show_table
[
cpu
]
=
NULL
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_put_attr
);
MODULE_AUTHOR
(
"Dominik Brodowski <linux@brodo.de>"
);
MODULE_DESCRIPTION
(
"CPUfreq frequency table helpers"
);
...
...
drivers/cpufreq/userspace.c
View file @
055f27cd
...
...
@@ -23,6 +23,7 @@
#include <linux/sysctl.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <asm/uaccess.h>
...
...
@@ -112,7 +113,7 @@ int cpufreq_set(unsigned int freq, unsigned int cpu)
if
(
freq
>
cpu_max_freq
[
cpu
])
freq
=
cpu_max_freq
[
cpu
];
ret
=
cpufreq_driver_target
_l
(
&
current_policy
[
cpu
],
freq
,
ret
=
cpufreq_driver_target
(
&
current_policy
[
cpu
],
freq
,
CPUFREQ_RELATION_L
);
err:
...
...
@@ -465,23 +466,14 @@ static inline void cpufreq_sysctl_exit(void)
/************************** sysfs interface ************************/
static
inline
int
to_cpu_nr
(
struct
device
*
dev
)
static
ssize_t
show_speed
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
struct
sys_device
*
cpu_sys_dev
=
container_of
(
dev
,
struct
sys_device
,
dev
);
return
(
cpu_sys_dev
->
id
);
}
static
ssize_t
show_speed
(
struct
device
*
dev
,
char
*
buf
)
{
unsigned
int
cpu
=
to_cpu_nr
(
dev
);
return
sprintf
(
buf
,
"%u
\n
"
,
cpu_cur_freq
[
cpu
]);
return
sprintf
(
buf
,
"%u
\n
"
,
cpu_cur_freq
[
policy
->
cpu
]);
}
static
ssize_t
store_speed
(
struct
device
*
dev
,
const
char
*
buf
,
size_t
count
)
store_speed
(
struct
cpufreq_policy
*
policy
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
cpu
=
to_cpu_nr
(
dev
);
unsigned
int
freq
=
0
;
unsigned
int
ret
;
...
...
@@ -489,13 +481,16 @@ store_speed (struct device *dev, const char *buf, size_t count)
if
(
ret
!=
1
)
return
-
EINVAL
;
cpufreq_set
(
freq
,
cpu
);
cpufreq_set
(
freq
,
policy
->
cpu
);
return
count
;
}
static
DEVICE_ATTR
(
scaling_setspeed
,
(
S_IRUGO
|
S_IWUSR
),
show_speed
,
store_speed
);
static
struct
freq_attr
freq_attr_scaling_setspeed
=
{
.
attr
=
{
.
name
=
"scaling_setspeed"
,
.
mode
=
0644
},
.
show
=
show_speed
,
.
store
=
store_speed
,
};
static
int
cpufreq_governor_userspace
(
struct
cpufreq_policy
*
policy
,
unsigned
int
event
)
...
...
@@ -511,7 +506,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
cpu_min_freq
[
cpu
]
=
policy
->
min
;
cpu_max_freq
[
cpu
]
=
policy
->
max
;
cpu_cur_freq
[
cpu
]
=
policy
->
cur
;
device_create_file
(
policy
->
dev
,
&
dev_attr_scaling_setspeed
);
sysfs_create_file
(
&
policy
->
kobj
,
&
freq_attr_scaling_setspeed
.
attr
);
memcpy
(
&
current_policy
[
cpu
],
policy
,
sizeof
(
struct
cpufreq_policy
));
up
(
&
userspace_sem
);
break
;
...
...
@@ -520,7 +515,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
cpu_is_managed
[
cpu
]
=
0
;
cpu_min_freq
[
cpu
]
=
0
;
cpu_max_freq
[
cpu
]
=
0
;
device_remove_file
(
policy
->
dev
,
&
dev_attr_scaling_setspeed
);
sysfs_remove_file
(
&
policy
->
kobj
,
&
freq_attr_scaling_setspeed
.
attr
);
up
(
&
userspace_sem
);
module_put
(
THIS_MODULE
);
break
;
...
...
include/linux/cpufreq.h
View file @
055f27cd
...
...
@@ -18,7 +18,8 @@
#include <linux/notifier.h>
#include <linux/threads.h>
#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#define CPUFREQ_NAME_LEN 16
...
...
@@ -69,6 +70,8 @@ struct cpufreq_policy {
struct
cpufreq_cpuinfo
cpuinfo
;
/* see above */
struct
device
*
dev
;
struct
kobject
kobj
;
struct
semaphore
lock
;
/* CPU ->setpolicy or ->target may
only be called once a time */
};
#define CPUFREQ_ADJUST (0)
...
...
@@ -131,18 +134,13 @@ struct cpufreq_governor {
};
/* pass a target to the cpufreq driver
* _l : (cpufreq_driver_sem is not held)
*/
inline
int
cpufreq_driver_target
(
struct
cpufreq_policy
*
policy
,
unsigned
int
target_freq
,
unsigned
int
relation
);
inline
int
cpufreq_driver_target_l
(
struct
cpufreq_policy
*
policy
,
unsigned
int
target_freq
,
unsigned
int
relation
);
/* pass an event to the cpufreq governor */
int
cpufreq_governor
_l
(
unsigned
int
cpu
,
unsigned
int
event
);
int
cpufreq_governor
(
unsigned
int
cpu
,
unsigned
int
event
);
int
cpufreq_register_governor
(
struct
cpufreq_governor
*
governor
);
void
cpufreq_unregister_governor
(
struct
cpufreq_governor
*
governor
);
...
...
@@ -154,6 +152,8 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor);
#define CPUFREQ_RELATION_L 0
/* lowest frequency at or above target */
#define CPUFREQ_RELATION_H 1
/* highest frequency below or at target */
struct
freq_attr
;
struct
cpufreq_driver
{
/* needed by all drivers */
int
(
*
verify
)
(
struct
cpufreq_policy
*
policy
);
...
...
@@ -164,16 +164,15 @@ struct cpufreq_driver {
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
);
int
(
*
exit
)
(
struct
cpufreq_policy
*
policy
);
struct
freq_attr
**
attr
;
};
int
cpufreq_register_driver
(
struct
cpufreq_driver
*
driver_data
);
int
cpufreq_unregister_driver
(
struct
cpufreq_driver
*
driver_data
);
/* deprecated */
#define cpufreq_register(x) cpufreq_register_driver(x)
#define cpufreq_unregister() cpufreq_unregister_driver(NULL)
void
cpufreq_notify_transition
(
struct
cpufreq_freqs
*
freqs
,
unsigned
int
state
);
...
...
@@ -194,6 +193,13 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, u
return
;
}
struct
freq_attr
{
struct
attribute
attr
;
ssize_t
(
*
show
)(
struct
cpufreq_policy
*
,
char
*
);
ssize_t
(
*
store
)(
struct
cpufreq_policy
*
,
const
char
*
,
size_t
count
);
};
/*********************************************************************
* CPUFREQ 2.6. INTERFACE *
*********************************************************************/
...
...
@@ -289,16 +295,21 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
int
cpufreq_frequency_table_verify
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_frequency_table
*
table
);
int
cpufreq_frequency_table_setpolicy
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_frequency_table
*
table
,
unsigned
int
*
index
);
int
cpufreq_frequency_table_target
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_frequency_table
*
table
,
unsigned
int
target_freq
,
unsigned
int
relation
,
unsigned
int
*
index
);
/* the following are really really optional */
extern
struct
freq_attr
cpufreq_freq_attr_scaling_available_freqs
;
void
cpufreq_frequency_table_get_attr
(
struct
cpufreq_frequency_table
*
table
,
unsigned
int
cpu
);
void
cpufreq_frequency_table_put_attr
(
unsigned
int
cpu
);
#endif
/* CONFIG_CPU_FREQ_TABLE */
#endif
/* _LINUX_CPUFREQ_H */
include/linux/pci_ids.h
View file @
055f27cd
...
...
@@ -1854,6 +1854,7 @@
#define PCI_DEVICE_ID_INTEL_82801DB_7 0x24c7
#define PCI_DEVICE_ID_INTEL_82801DB_9 0x24cb
#define PCI_DEVICE_ID_INTEL_82801DB_11 PCI_DEVICE_ID_INTEL_82801DB_9
#define PCI_DEVICE_ID_INTEL_82801DB_12 0x24cc
#define PCI_DEVICE_ID_INTEL_82801DB_13 0x24cd
#define PCI_DEVICE_ID_INTEL_82820_HB 0x2500
#define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501
...
...
kernel/cpufreq.c
View file @
055f27cd
...
...
@@ -43,12 +43,40 @@ static DECLARE_MUTEX (cpufreq_driver_sem);
*/
static
struct
notifier_block
*
cpufreq_policy_notifier_list
;
static
struct
notifier_block
*
cpufreq_transition_notifier_list
;
static
DECLARE_
MUTEX
(
cpufreq_notifier_
sem
);
static
DECLARE_
RWSEM
(
cpufreq_notifier_rw
sem
);
LIST_HEAD
(
cpufreq_governor_list
);
static
DECLARE_MUTEX
(
cpufreq_governor_sem
);
static
int
cpufreq_governor
(
unsigned
int
cpu
,
unsigned
int
event
);
static
struct
device_interface
cpufreq_interface
;
static
int
cpufreq_cpu_get
(
unsigned
int
cpu
)
{
if
(
cpu
>=
NR_CPUS
)
return
0
;
if
(
!
kset_get
(
&
cpufreq_interface
.
kset
))
return
0
;
if
(
!
try_module_get
(
cpufreq_driver
->
owner
))
{
kset_put
(
&
cpufreq_interface
.
kset
);
return
0
;
}
if
(
!
kobject_get
(
&
cpufreq_driver
->
policy
[
cpu
].
kobj
))
{
module_put
(
cpufreq_driver
->
owner
);
kset_put
(
&
cpufreq_interface
.
kset
);
return
0
;
}
return
1
;
}
static
void
cpufreq_cpu_put
(
unsigned
int
cpu
)
{
kobject_put
(
&
cpufreq_driver
->
policy
[
cpu
].
kobj
);
module_put
(
cpufreq_driver
->
owner
);
kset_put
(
&
cpufreq_interface
.
kset
);
}
/*********************************************************************
* SYSFS INTERFACE *
...
...
@@ -67,19 +95,19 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpu
return
0
;
}
else
{
struct
cpufreq_governor
*
t
;
down
(
&
cpufreq_
drive
r_sem
);
down
(
&
cpufreq_
governo
r_sem
);
if
(
!
cpufreq_driver
||
!
cpufreq_driver
->
target
)
goto
out
;
list_for_each_entry
(
t
,
&
cpufreq_governor_list
,
governor_list
)
{
if
(
!
strnicmp
(
str_governor
,
t
->
name
,
CPUFREQ_NAME_LEN
))
{
*
governor
=
t
;
*
policy
=
CPUFREQ_POLICY_GOVERNOR
;
up
(
&
cpufreq_
drive
r_sem
);
up
(
&
cpufreq_
governo
r_sem
);
return
0
;
}
}
out:
up
(
&
cpufreq_
drive
r_sem
);
up
(
&
cpufreq_
governo
r_sem
);
}
return
-
EINVAL
;
}
...
...
@@ -120,14 +148,7 @@ static inline int to_cpu_nr (struct device *dev)
static ssize_t show_##file_name \
(struct cpufreq_policy * policy, char *buf) \
{ \
unsigned int value = 0; \
\
down(&cpufreq_driver_sem); \
if (cpufreq_driver) \
value = policy->object; \
up(&cpufreq_driver_sem); \
\
return sprintf (buf, "%u\n", value); \
return sprintf (buf, "%u\n", policy->object); \
}
show_one
(
cpuinfo_min_freq
,
cpuinfo
.
min_freq
);
...
...
@@ -143,12 +164,17 @@ static ssize_t store_##file_name \
(struct cpufreq_policy * policy, const char *buf, size_t count) \
{ \
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 -EINVAL; \
\
ret = sscanf (buf, "%u", &new_policy.object); \
if (ret != 1) \
return -EINVAL; \
\
ret = cpufreq_set_policy(policy); \
ret = cpufreq_set_policy(
&new_
policy); \
\
return ret ? ret : count; \
}
...
...
@@ -161,26 +187,16 @@ store_one(scaling_max_freq,max);
*/
static
ssize_t
show_scaling_governor
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
unsigned
int
value
=
0
;
char
value2
[
CPUFREQ_NAME_LEN
];
down
(
&
cpufreq_driver_sem
);
if
(
cpufreq_driver
)
value
=
policy
->
policy
;
if
(
value
==
CPUFREQ_POLICY_GOVERNOR
)
strncpy
(
value2
,
policy
->
governor
->
name
,
CPUFREQ_NAME_LEN
);
up
(
&
cpufreq_driver_sem
);
switch
(
value
)
{
switch
(
policy
->
policy
)
{
case
CPUFREQ_POLICY_POWERSAVE
:
return
sprintf
(
buf
,
"powersave
\n
"
);
case
CPUFREQ_POLICY_PERFORMANCE
:
return
sprintf
(
buf
,
"performance
\n
"
);
case
CPUFREQ_POLICY_GOVERNOR
:
return
sprintf
(
buf
,
"%s
\n
"
,
value2
);
return
snprintf
(
buf
,
CPUFREQ_NAME_LEN
,
"%s
\n
"
,
policy
->
governor
->
name
);
default:
return
-
EINVAL
;
}
return
-
EINVAL
;
}
...
...
@@ -192,25 +208,55 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
{
unsigned
int
ret
=
-
EINVAL
;
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
);
if
(
ret
!=
1
)
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
;
ret
=
cpufreq_set_policy
(
policy
);
ret
=
cpufreq_set_policy
(
&
new_
policy
);
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
)
{
return
snprintf
(
buf
,
CPUFREQ_NAME_LEN
,
"%s
\n
"
,
cpufreq_driver
->
name
);
}
/**
* 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"
);
if
(
!
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:
i
+=
sprintf
(
&
buf
[
i
],
"
\n
"
);
return
i
;
}
struct
freq_attr
{
struct
attribute
attr
;
ssize_t
(
*
show
)(
struct
cpufreq_policy
*
,
char
*
);
ssize_t
(
*
store
)(
struct
cpufreq_policy
*
,
const
char
*
,
size_t
count
);
};
#define define_one_ro(_name) \
struct freq_attr _name = { \
...
...
@@ -227,6 +273,8 @@ struct freq_attr _name = { \
define_one_ro
(
cpuinfo_min_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_max_freq
);
define_one_rw
(
scaling_governor
);
...
...
@@ -237,10 +285,11 @@ static struct attribute * default_attrs[] = {
&
scaling_min_freq
.
attr
,
&
scaling_max_freq
.
attr
,
&
scaling_governor
.
attr
,
&
scaling_driver
.
attr
,
&
scaling_available_governors
.
attr
,
NULL
};
#define to_policy(k) container_of(k,struct cpufreq_policy,kobj)
#define to_attr(a) container_of(a,struct freq_attr,attr)
...
...
@@ -248,7 +297,12 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
{
struct
cpufreq_policy
*
policy
=
to_policy
(
kobj
);
struct
freq_attr
*
fattr
=
to_attr
(
attr
);
return
fattr
->
show
?
fattr
->
show
(
policy
,
buf
)
:
0
;
ssize_t
ret
;
if
(
!
cpufreq_cpu_get
(
policy
->
cpu
))
return
-
EINVAL
;
ret
=
fattr
->
show
?
fattr
->
show
(
policy
,
buf
)
:
0
;
cpufreq_cpu_put
(
policy
->
cpu
);
return
ret
;
}
static
ssize_t
store
(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
...
...
@@ -256,7 +310,12 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr,
{
struct
cpufreq_policy
*
policy
=
to_policy
(
kobj
);
struct
freq_attr
*
fattr
=
to_attr
(
attr
);
return
fattr
->
store
?
fattr
->
store
(
policy
,
buf
,
count
)
:
0
;
ssize_t
ret
;
if
(
!
cpufreq_cpu_get
(
policy
->
cpu
))
return
-
EINVAL
;
ret
=
fattr
->
store
?
fattr
->
store
(
policy
,
buf
,
count
)
:
0
;
cpufreq_cpu_put
(
policy
->
cpu
);
return
ret
;
}
static
struct
sysfs_ops
sysfs_ops
=
{
...
...
@@ -270,56 +329,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
*
...
...
@@ -329,57 +338,62 @@ static int cpufreq_add_dev (struct device * dev)
{
unsigned
int
cpu
=
to_cpu_nr
(
dev
);
int
ret
=
0
;
struct
cpufreq_policy
policy
;
struct
cpufreq_policy
new_policy
;
struct
cpufreq_policy
*
policy
;
struct
freq_attr
**
drv_attr
;
down
(
&
cpufreq_driver_sem
);
if
(
!
cpufreq_driver
)
{
up
(
&
cpufreq_driver_sem
);
if
(
!
kset_get
(
&
cpufreq_interface
.
kset
))
return
-
EINVAL
;
if
(
!
try_module_get
(
cpufreq_driver
->
owner
))
{
kset_put
(
&
cpufreq_interface
.
kset
);
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
;
policy
=
&
cpufreq_driver
->
policy
[
cpu
];
policy
->
cpu
=
cpu
;
if
(
cpufreq_driver
->
init
)
{
ret
=
cpufreq_driver
->
init
(
&
cpufreq_driver
->
policy
[
cpu
]);
if
(
ret
)
{
up
(
&
cpufreq_driver_sem
);
return
-
ENODEV
;
}
ret
=
cpufreq_driver
->
init
(
policy
);
if
(
ret
)
goto
out
;
}
/* set default policy on this CPU */
memcpy
(
&
policy
,
&
cpufreq_driver
->
policy
[
cpu
],
down
(
&
cpufreq_driver_sem
);
memcpy
(
&
new_policy
,
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
)
cpufreq_governor
(
cpu
,
CPUFREQ_GOV_START
);
up
(
&
cpufreq_driver_sem
);
ret
=
cpufreq_set_policy
(
&
policy
);
if
(
ret
)
return
-
EINVAL
;
down
(
&
cpufreq_driver_sem
);
init_MUTEX
(
&
policy
->
lock
);
/* prepare interface data */
policy
.
kobj
.
parent
=
&
dev
->
kobj
;
policy
.
kobj
.
ktype
=
&
ktype_cpufreq
;
policy
.
dev
=
dev
;
strncpy
(
policy
.
kobj
.
name
,
policy
->
kobj
.
parent
=
&
dev
->
kobj
;
policy
->
kobj
.
ktype
=
&
ktype_cpufreq
;
policy
->
dev
=
dev
;
strncpy
(
policy
->
kobj
.
name
,
cpufreq_interface
.
name
,
KOBJ_NAME_LEN
);
ret
=
kobject_register
(
&
policy
.
kobj
);
ret
=
kobject_register
(
&
policy
->
kobj
);
if
(
ret
)
goto
out
;
drv_attr
=
cpufreq_driver
->
attr
;
while
((
drv_attr
)
&&
(
*
drv_attr
))
{
sysfs_create_file
(
&
policy
->
kobj
,
&
((
*
drv_attr
)
->
attr
));
drv_attr
++
;
}
up
(
&
cpufreq_driver_sem
);
/* set default policy */
ret
=
cpufreq_set_policy
(
&
new_policy
);
if
(
ret
)
kobject_unregister
(
&
policy
->
kobj
);
out:
module_put
(
cpufreq_driver
->
owner
);
kset_put
(
&
cpufreq_interface
.
kset
);
return
ret
;
}
...
...
@@ -387,21 +401,39 @@ static int cpufreq_add_dev (struct device * dev)
/**
* cpufreq_remove_dev - remove a CPU device
*
* Removes the cpufreq interface for a CPU device. Is called with
* cpufreq_driver_sem locked.
* Removes the cpufreq interface for a CPU device.
*/
static
int
cpufreq_remove_dev
(
struct
device
*
dev
)
{
unsigned
int
cpu
=
to_cpu_nr
(
dev
);
if
(
cpufreq_driver
->
target
)
cpufreq_governor
(
cpu
,
CPUFREQ_GOV_STOP
);
if
(
!
kset_get
(
&
cpufreq_interface
.
kset
))
return
-
EINVAL
;
if
(
!
kobject_get
(
&
cpufreq_driver
->
policy
[
cpu
].
kobj
))
{
kset_put
(
&
cpufreq_interface
.
kset
);
return
-
EINVAL
;
}
down
(
&
cpufreq_driver_sem
);
if
((
cpufreq_driver
->
target
)
&&
(
cpufreq_driver
->
policy
[
cpu
].
policy
==
CPUFREQ_POLICY_GOVERNOR
))
{
cpufreq_driver
->
policy
[
cpu
].
governor
->
governor
(
&
cpufreq_driver
->
policy
[
cpu
],
CPUFREQ_GOV_STOP
);
module_put
(
cpufreq_driver
->
policy
[
cpu
].
governor
->
owner
);
}
/* we may call driver->exit here without checking for try_module_exit
* as it's either the driver which wants to unload or we have a CPU
* removal AND driver removal at the same time...
*/
if
(
cpufreq_driver
->
exit
)
cpufreq_driver
->
exit
(
&
cpufreq_driver
->
policy
[
cpu
]);
kobject_unregister
(
&
cpufreq_driver
->
policy
[
cpu
].
kobj
);
up
(
&
cpufreq_driver_sem
);
kobject_put
(
&
cpufreq_driver
->
policy
[
cpu
].
kobj
);
kset_put
(
&
cpufreq_interface
.
kset
);
return
0
;
}
...
...
@@ -427,7 +459,7 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
{
int
ret
;
down
(
&
cpufreq_notifier_
sem
);
down
_write
(
&
cpufreq_notifier_rw
sem
);
switch
(
list
)
{
case
CPUFREQ_TRANSITION_NOTIFIER
:
ret
=
notifier_chain_register
(
&
cpufreq_transition_notifier_list
,
nb
);
...
...
@@ -438,7 +470,7 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
default:
ret
=
-
EINVAL
;
}
up
(
&
cpufreq_notifier_
sem
);
up
_write
(
&
cpufreq_notifier_rw
sem
);
return
ret
;
}
...
...
@@ -459,7 +491,7 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
{
int
ret
;
down
(
&
cpufreq_notifier_
sem
);
down
_write
(
&
cpufreq_notifier_rw
sem
);
switch
(
list
)
{
case
CPUFREQ_TRANSITION_NOTIFIER
:
ret
=
notifier_chain_unregister
(
&
cpufreq_transition_notifier_list
,
nb
);
...
...
@@ -470,7 +502,7 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
default:
ret
=
-
EINVAL
;
}
up
(
&
cpufreq_notifier_
sem
);
up
_write
(
&
cpufreq_notifier_rw
sem
);
return
ret
;
}
...
...
@@ -481,71 +513,72 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier);
* GOVERNORS *
*********************************************************************/
inline
int
cpufreq_driver_target_l
(
struct
cpufreq_policy
*
policy
,
unsigned
int
target_freq
,
unsigned
int
relation
)
{
unsigned
int
ret
;
down
(
&
cpufreq_driver_sem
);
if
(
!
cpufreq_driver
)
ret
=
-
EINVAL
;
else
ret
=
cpufreq_driver
->
target
(
policy
,
target_freq
,
relation
);
up
(
&
cpufreq_driver_sem
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_driver_target_l
);
inline
int
cpufreq_driver_target
(
struct
cpufreq_policy
*
policy
,
unsigned
int
target_freq
,
unsigned
int
relation
)
{
return
cpufreq_driver
->
target
(
policy
,
target_freq
,
relation
);
unsigned
int
ret
;
unsigned
int
cpu
=
policy
->
cpu
;
if
(
!
cpufreq_cpu_get
(
cpu
))
return
-
EINVAL
;
down
(
&
cpufreq_driver
->
policy
[
cpu
].
lock
);
ret
=
cpufreq_driver
->
target
(
policy
,
target_freq
,
relation
);
up
(
&
cpufreq_driver
->
policy
[
cpu
].
lock
);
cpufreq_cpu_put
(
cpu
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_driver_target
);
static
int
cpufreq_governor
(
unsigned
int
cpu
,
unsigned
int
event
)
int
cpufreq_governor
(
unsigned
int
cpu
,
unsigned
int
event
)
{
int
ret
=
0
;
struct
cpufreq_policy
*
policy
=
&
cpufreq_driver
->
policy
[
cpu
];
if
(
!
cpufreq_cpu_get
(
cpu
))
return
-
EINVAL
;
switch
(
policy
->
policy
)
{
case
CPUFREQ_POLICY_POWERSAVE
:
if
((
event
==
CPUFREQ_GOV_LIMITS
)
||
(
event
==
CPUFREQ_GOV_START
))
if
((
event
==
CPUFREQ_GOV_LIMITS
)
||
(
event
==
CPUFREQ_GOV_START
))
{
down
(
&
cpufreq_driver
->
policy
[
cpu
].
lock
);
ret
=
cpufreq_driver
->
target
(
policy
,
policy
->
min
,
CPUFREQ_RELATION_L
);
up
(
&
cpufreq_driver
->
policy
[
cpu
].
lock
);
}
break
;
case
CPUFREQ_POLICY_PERFORMANCE
:
if
((
event
==
CPUFREQ_GOV_LIMITS
)
||
(
event
==
CPUFREQ_GOV_START
))
if
((
event
==
CPUFREQ_GOV_LIMITS
)
||
(
event
==
CPUFREQ_GOV_START
))
{
down
(
&
cpufreq_driver
->
policy
[
cpu
].
lock
);
ret
=
cpufreq_driver
->
target
(
policy
,
policy
->
max
,
CPUFREQ_RELATION_H
);
up
(
&
cpufreq_driver
->
policy
[
cpu
].
lock
);
}
break
;
case
CPUFREQ_POLICY_GOVERNOR
:
ret
=
-
EINVAL
;
if
(
event
==
CPUFREQ_GOV_START
)
if
(
!
try_module_get
(
cpufreq_driver
->
policy
[
cpu
].
governor
->
owner
))
break
;
if
(
!
try_module_get
(
cpufreq_driver
->
policy
[
cpu
].
governor
->
owner
))
break
;
ret
=
cpufreq_driver
->
policy
[
cpu
].
governor
->
governor
(
policy
,
event
);
if
((
event
==
CPUFREQ_GOV_STOP
)
||
(
ret
&&
(
event
==
CPUFREQ_GOV_START
)))
/* we keep one module reference alive for each CPU governed by this CPU */
if
((
event
!=
CPUFREQ_GOV_START
)
||
ret
)
module_put
(
cpufreq_driver
->
policy
[
cpu
].
governor
->
owner
);
if
((
event
==
CPUFREQ_GOV_STOP
)
&&
!
ret
)
module_put
(
cpufreq_driver
->
policy
[
cpu
].
governor
->
owner
);
break
;
default:
ret
=
-
EINVAL
;
}
return
ret
;
}
cpufreq_cpu_put
(
cpu
);
int
cpufreq_governor_l
(
unsigned
int
cpu
,
unsigned
int
event
)
{
int
ret
=
0
;
down
(
&
cpufreq_driver_sem
);
ret
=
cpufreq_governor
(
cpu
,
event
);
up
(
&
cpufreq_driver_sem
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_governor
_l
);
EXPORT_SYMBOL_GPL
(
cpufreq_governor
);
int
cpufreq_register_governor
(
struct
cpufreq_governor
*
governor
)
...
...
@@ -560,16 +593,17 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
if
(
!
strnicmp
(
governor
->
name
,
"performance"
,
CPUFREQ_NAME_LEN
))
return
-
EBUSY
;
down
(
&
cpufreq_
drive
r_sem
);
down
(
&
cpufreq_
governo
r_sem
);
list_for_each_entry
(
t
,
&
cpufreq_governor_list
,
governor_list
)
{
if
(
!
strnicmp
(
governor
->
name
,
t
->
name
,
CPUFREQ_NAME_LEN
))
{
up
(
&
cpufreq_
drive
r_sem
);
up
(
&
cpufreq_
governo
r_sem
);
return
-
EBUSY
;
}
}
list_add
(
&
governor
->
governor_list
,
&
cpufreq_governor_list
);
up
(
&
cpufreq_driver_sem
);
up
(
&
cpufreq_governor_sem
);
return
0
;
}
...
...
@@ -583,7 +617,8 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor)
if
(
!
governor
)
return
;
down
(
&
cpufreq_driver_sem
);
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,
...
...
@@ -591,17 +626,21 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor)
*/
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
if
(
cpufreq_driver
&&
(
cpufreq_driver
->
policy
[
i
].
policy
==
CPUFREQ_POLICY_GOVERNOR
)
&&
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_
drive
r_sem
);
up
(
&
cpufreq_
governo
r_sem
);
return
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_unregister_governor
);
...
...
@@ -620,19 +659,17 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
*/
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
);
if
(
!
policy
||
!
cpufreq_cpu_get
(
cpu
))
return
-
EINVAL
;
}
down
(
&
cpufreq_driver_sem
);
memcpy
(
policy
,
&
cpufreq_driver
->
policy
[
cpu
],
sizeof
(
struct
cpufreq_policy
));
up
(
&
cpufreq_driver_sem
);
cpufreq_cpu_put
(
cpu
);
return
0
;
}
EXPORT_SYMBOL
(
cpufreq_get_policy
);
...
...
@@ -646,27 +683,23 @@ EXPORT_SYMBOL(cpufreq_get_policy);
*/
int
cpufreq_set_policy
(
struct
cpufreq_policy
*
policy
)
{
int
ret
;
int
ret
=
0
;
down
(
&
cpufreq_driver_sem
);
if
(
!
cpufreq_driver
||
!
policy
||
(
policy
->
cpu
>=
NR_CPUS
)
||
(
!
cpu_online
(
policy
->
cpu
)))
{
up
(
&
cpufreq_driver_sem
);
if
(
!
policy
||
!
cpufreq_cpu_get
(
policy
->
cpu
))
return
-
EINVAL
;
}
down
(
&
cpufreq_driver_sem
);
memcpy
(
&
policy
->
cpuinfo
,
&
cpufreq_driver
->
policy
[
policy
->
cpu
].
cpuinfo
,
sizeof
(
struct
cpufreq_cpuinfo
));
up
(
&
cpufreq_driver_sem
);
/* verify the cpu speed can be set within this limit */
ret
=
cpufreq_driver
->
verify
(
policy
);
if
(
ret
)
{
up
(
&
cpufreq_driver_sem
);
return
ret
;
}
if
(
ret
)
goto
error_out
;
down
(
&
cpufreq_notifier_
sem
);
down
_read
(
&
cpufreq_notifier_rw
sem
);
/* adjust if necessary - all reasons */
notifier_call_chain
(
&
cpufreq_policy_notifier_list
,
CPUFREQ_ADJUST
,
...
...
@@ -680,17 +713,18 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
which might be different to the first one */
ret
=
cpufreq_driver
->
verify
(
policy
);
if
(
ret
)
{
up
(
&
cpufreq_notifier_sem
);
up
(
&
cpufreq_driver_sem
);
return
ret
;
up_read
(
&
cpufreq_notifier_rwsem
);
goto
error_out
;
}
/* notification of the new policy */
notifier_call_chain
(
&
cpufreq_policy_notifier_list
,
CPUFREQ_NOTIFY
,
policy
);
up
(
&
cpufreq_notifier_
sem
);
up
_read
(
&
cpufreq_notifier_rw
sem
);
/* from here on we limit it to one limit and/or governor change running at the moment */
down
(
&
cpufreq_driver_sem
);
cpufreq_driver
->
policy
[
policy
->
cpu
].
min
=
policy
->
min
;
cpufreq_driver
->
policy
[
policy
->
cpu
].
max
=
policy
->
max
;
...
...
@@ -718,9 +752,11 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
cpufreq_governor
(
policy
->
cpu
,
CPUFREQ_GOV_LIMITS
);
}
}
up
(
&
cpufreq_driver_sem
);
error_out:
cpufreq_cpu_put
(
policy
->
cpu
);
return
ret
;
}
EXPORT_SYMBOL
(
cpufreq_set_policy
);
...
...
@@ -766,7 +802,7 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
*/
void
cpufreq_notify_transition
(
struct
cpufreq_freqs
*
freqs
,
unsigned
int
state
)
{
down
(
&
cpufreq_notifier_
sem
);
down
_read
(
&
cpufreq_notifier_rw
sem
);
switch
(
state
)
{
case
CPUFREQ_PRECHANGE
:
notifier_call_chain
(
&
cpufreq_transition_notifier_list
,
CPUFREQ_PRECHANGE
,
freqs
);
...
...
@@ -778,7 +814,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
cpufreq_driver
->
policy
[
freqs
->
cpu
].
cur
=
freqs
->
new
;
break
;
}
up
(
&
cpufreq_notifier_
sem
);
up
_read
(
&
cpufreq_notifier_rw
sem
);
}
EXPORT_SYMBOL_GPL
(
cpufreq_notify_transition
);
...
...
@@ -800,38 +836,33 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
*/
int
cpufreq_register_driver
(
struct
cpufreq_driver
*
driver_data
)
{
int
ret
=
0
;
if
(
cpufreq_driver
)
return
-
EBUSY
;
if
(
!
driver_data
||
!
driver_data
->
verify
||
if
(
!
driver_data
||
!
driver_data
->
verify
||
!
driver_data
->
init
||
((
!
driver_data
->
setpolicy
)
&&
(
!
driver_data
->
target
)))
return
-
EINVAL
;
down
(
&
cpufreq_driver_sem
);
if
(
kset_get
(
&
cpufreq_interface
.
kset
))
{
kset_put
(
&
cpufreq_interface
.
kset
);
return
-
EBUSY
;
}
down
(
&
cpufreq_driver_sem
);
if
(
cpufreq_driver
)
{
up
(
&
cpufreq_driver_sem
);
return
-
EBUSY
;
}
cpufreq_driver
=
driver_data
;
up
(
&
cpufreq_driver_sem
);
cpufreq_driver
->
policy
=
kmalloc
(
NR_CPUS
*
sizeof
(
struct
cpufreq_policy
),
GFP_KERNEL
);
if
(
!
cpufreq_driver
->
policy
)
{
/* then we need per-CPU init */
if
(
!
cpufreq_driver
->
init
)
{
up
(
&
cpufreq_driver_sem
);
return
-
EINVAL
;
}
cpufreq_driver
->
policy
=
kmalloc
(
NR_CPUS
*
sizeof
(
struct
cpufreq_policy
),
GFP_KERNEL
);
if
(
!
cpufreq_driver
->
policy
)
{
up
(
&
cpufreq_driver_sem
);
return
-
ENOMEM
;
}
memset
(
cpufreq_driver
->
policy
,
0
,
NR_CPUS
*
sizeof
(
struct
cpufreq_policy
));
cpufreq_driver
=
NULL
;
return
-
ENOMEM
;
}
up
(
&
cpufreq_driver_sem
);
ret
=
interface_register
(
&
cpufreq_interface
);
memset
(
cpufreq_driver
->
policy
,
0
,
NR_CPUS
*
sizeof
(
struct
cpufreq_policy
)
);
return
ret
;
return
interface_register
(
&
cpufreq_interface
)
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_register_driver
);
...
...
@@ -846,20 +877,20 @@ EXPORT_SYMBOL_GPL(cpufreq_register_driver);
*/
int
cpufreq_unregister_driver
(
struct
cpufreq_driver
*
driver
)
{
down
(
&
cpufreq_driver_sem
);
if
(
!
kset_get
(
&
cpufreq_interface
.
kset
))
return
0
;
if
(
!
cpufreq_driver
||
((
driver
!=
cpufreq_driver
)
&&
(
driver
!=
NULL
)))
{
/* compat */
up
(
&
cpufreq_driver_sem
);
if
(
!
cpufreq_driver
||
(
driver
!=
cpufreq_driver
))
{
kset_put
(
&
cpufreq_interface
.
kset
);
return
-
EINVAL
;
}
kset_put
(
&
cpufreq_interface
.
kset
);
interface_unregister
(
&
cpufreq_interface
);
if
(
driver
)
kfree
(
cpufreq_driver
->
policy
);
down
(
&
cpufreq_driver_sem
);
kfree
(
cpufreq_driver
->
policy
);
cpufreq_driver
=
NULL
;
up
(
&
cpufreq_driver_sem
);
return
0
;
...
...
@@ -883,22 +914,28 @@ int cpufreq_restore(void)
if
(
in_interrupt
())
panic
(
"cpufreq_restore() called from interrupt context!"
);
if
(
!
kset_get
(
&
cpufreq_interface
.
kset
))
return
0
;
if
(
!
try_module_get
(
cpufreq_driver
->
owner
))
goto
error_out
;
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
if
(
!
cpu_online
(
i
))
if
(
!
cpu_online
(
i
)
||
!
cpufreq_cpu_get
(
i
)
)
continue
;
down
(
&
cpufreq_driver_sem
);
if
(
!
cpufreq_driver
)
{
up
(
&
cpufreq_driver_sem
);
return
0
;
}
memcpy
(
&
policy
,
&
cpufreq_driver
->
policy
[
i
],
sizeof
(
struct
cpufreq_policy
));
up
(
&
cpufreq_driver_sem
);
ret
+=
cpufreq_set_policy
(
&
policy
);
cpufreq_cpu_put
(
i
);
}
module_put
(
cpufreq_driver
->
owner
);
error_out:
kset_put
(
&
cpufreq_interface
.
kset
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_restore
);
...
...
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