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
nexedi
linux
Commits
ba420e28
Commit
ba420e28
authored
Jan 14, 2005
by
Dave Jones
Browse files
Options
Browse Files
Download
Plain Diff
Merge delerium.kernelslacker.org:/mnt/data/src/bk/bk-linus
into delerium.kernelslacker.org:/mnt/data/src/bk/cpufreq
parents
812ab7f3
c24a8e84
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
635 additions
and
868 deletions
+635
-868
Documentation/cpu-freq/index.txt
Documentation/cpu-freq/index.txt
+4
-4
MAINTAINERS
MAINTAINERS
+1
-1
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+31
-3
arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
+1
-10
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+1
-1
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+1
-1
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+11
-8
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+18
-11
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+4
-5
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+91
-61
arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h
arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h
+25
-0
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig
+15
-26
drivers/cpufreq/Makefile
drivers/cpufreq/Makefile
+2
-1
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq.c
+16
-4
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_ondemand.c
+66
-14
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/cpufreq_stats.c
+334
-0
drivers/cpufreq/cpufreq_userspace.c
drivers/cpufreq/cpufreq_userspace.c
+4
-396
drivers/cpufreq/freq_table.c
drivers/cpufreq/freq_table.c
+5
-0
drivers/cpufreq/proc_intf.c
drivers/cpufreq/proc_intf.c
+0
-263
include/linux/cpufreq.h
include/linux/cpufreq.h
+5
-59
No files found.
Documentation/cpu-freq/index.txt
View file @
ba420e28
...
@@ -35,10 +35,10 @@ Mailing List
...
@@ -35,10 +35,10 @@ Mailing List
------------
------------
There is a CPU frequency changing CVS commit and general list where
There is a CPU frequency changing CVS commit and general list where
you can report bugs, problems or submit patches. To post a message,
you can report bugs, problems or submit patches. To post a message,
send an email to cpufreq@
www
.linux.org.uk, to subscribe go to
send an email to cpufreq@
lists
.linux.org.uk, to subscribe go to
http://
www
.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
http://
lists
.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
mailing list are available to subscribers at
mailing list are available to subscribers at
http://
www
.linux.org.uk/mailman/private/cpufreq/.
http://
lists
.linux.org.uk/mailman/private/cpufreq/.
Links
Links
...
@@ -50,7 +50,7 @@ how to access the CVS repository:
...
@@ -50,7 +50,7 @@ how to access the CVS repository:
* http://cvs.arm.linux.org.uk/
* http://cvs.arm.linux.org.uk/
the CPUFreq Mailing list:
the CPUFreq Mailing list:
* http://
www
.linux.org.uk/mailman/listinfo/cpufreq
* http://
lists
.linux.org.uk/mailman/listinfo/cpufreq
Clock and voltage scaling for the SA-1100:
Clock and voltage scaling for the SA-1100:
* http://www.lart.tudelft.nl/projects/scaling
* http://www.lart.tudelft.nl/projects/scaling
MAINTAINERS
View file @
ba420e28
...
@@ -575,7 +575,7 @@ S: Maintained
...
@@ -575,7 +575,7 @@ S: Maintained
CPU FREQUENCY DRIVERS
CPU FREQUENCY DRIVERS
P: Dave Jones
P: Dave Jones
M: davej@codemonkey.org.uk
M: davej@codemonkey.org.uk
L: cpufreq@
www
.linux.org.uk
L: cpufreq@
lists
.linux.org.uk
W: http://www.codemonkey.org.uk/projects/cpufreq/
W: http://www.codemonkey.org.uk/projects/cpufreq/
S: Maintained
S: Maintained
...
...
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
View file @
ba420e28
...
@@ -38,6 +38,8 @@
...
@@ -38,6 +38,8 @@
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <acpi/processor.h>
#include <acpi/processor.h>
#include "speedstep-est-common.h"
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
MODULE_AUTHOR
(
"Paul Diefenbaugh, Dominik Brodowski"
);
MODULE_AUTHOR
(
"Paul Diefenbaugh, Dominik Brodowski"
);
...
@@ -48,10 +50,12 @@ MODULE_LICENSE("GPL");
...
@@ -48,10 +50,12 @@ MODULE_LICENSE("GPL");
struct
cpufreq_acpi_io
{
struct
cpufreq_acpi_io
{
struct
acpi_processor_performance
acpi_data
;
struct
acpi_processor_performance
acpi_data
;
struct
cpufreq_frequency_table
*
freq_table
;
struct
cpufreq_frequency_table
*
freq_table
;
unsigned
int
resume
;
};
};
static
struct
cpufreq_acpi_io
*
acpi_io_data
[
NR_CPUS
];
static
struct
cpufreq_acpi_io
*
acpi_io_data
[
NR_CPUS
];
static
struct
cpufreq_driver
acpi_cpufreq_driver
;
static
int
static
int
acpi_processor_write_port
(
acpi_processor_write_port
(
...
@@ -119,9 +123,14 @@ acpi_processor_set_performance (
...
@@ -119,9 +123,14 @@ acpi_processor_set_performance (
}
}
if
(
state
==
data
->
acpi_data
.
state
)
{
if
(
state
==
data
->
acpi_data
.
state
)
{
dprintk
(
"Already at target state (P%d)
\n
"
,
state
);
if
(
unlikely
(
data
->
resume
))
{
retval
=
0
;
dprintk
(
"Called after resume, resetting to P%d
\n
"
,
state
);
goto
migrate_end
;
data
->
resume
=
0
;
}
else
{
dprintk
(
"Already at target state (P%d)
\n
"
,
state
);
retval
=
0
;
goto
migrate_end
;
}
}
}
dprintk
(
"Transitioning from P%d to P%d
\n
"
,
dprintk
(
"Transitioning from P%d to P%d
\n
"
,
...
@@ -368,6 +377,10 @@ acpi_cpufreq_cpu_init (
...
@@ -368,6 +377,10 @@ acpi_cpufreq_cpu_init (
if
(
result
)
if
(
result
)
goto
err_free
;
goto
err_free
;
if
(
is_const_loops_cpu
(
cpu
))
{
acpi_cpufreq_driver
.
flags
|=
CPUFREQ_CONST_LOOPS
;
}
/* capability check */
/* capability check */
if
(
data
->
acpi_data
.
state_count
<=
1
)
{
if
(
data
->
acpi_data
.
state_count
<=
1
)
{
dprintk
(
"No P-States
\n
"
);
dprintk
(
"No P-States
\n
"
);
...
@@ -462,6 +475,20 @@ acpi_cpufreq_cpu_exit (
...
@@ -462,6 +475,20 @@ acpi_cpufreq_cpu_exit (
return
(
0
);
return
(
0
);
}
}
static
int
acpi_cpufreq_resume
(
struct
cpufreq_policy
*
policy
)
{
struct
cpufreq_acpi_io
*
data
=
acpi_io_data
[
policy
->
cpu
];
dprintk
(
"acpi_cpufreq_resume
\n
"
);
data
->
resume
=
1
;
return
(
0
);
}
static
struct
freq_attr
*
acpi_cpufreq_attr
[]
=
{
static
struct
freq_attr
*
acpi_cpufreq_attr
[]
=
{
&
cpufreq_freq_attr_scaling_available_freqs
,
&
cpufreq_freq_attr_scaling_available_freqs
,
...
@@ -473,6 +500,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
...
@@ -473,6 +500,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.
target
=
acpi_cpufreq_target
,
.
target
=
acpi_cpufreq_target
,
.
init
=
acpi_cpufreq_cpu_init
,
.
init
=
acpi_cpufreq_cpu_init
,
.
exit
=
acpi_cpufreq_cpu_exit
,
.
exit
=
acpi_cpufreq_cpu_exit
,
.
resume
=
acpi_cpufreq_resume
,
.
name
=
"acpi-cpufreq"
,
.
name
=
"acpi-cpufreq"
,
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
attr
=
acpi_cpufreq_attr
,
.
attr
=
acpi_cpufreq_attr
,
...
...
arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
View file @
ba420e28
...
@@ -55,16 +55,7 @@ MODULE_PARM_DESC(fid, "CPU multiplier to use (11.5 = 115)");
...
@@ -55,16 +55,7 @@ MODULE_PARM_DESC(fid, "CPU multiplier to use (11.5 = 115)");
MODULE_PARM_DESC
(
min_fsb
,
MODULE_PARM_DESC
(
min_fsb
,
"Minimum FSB to use, if not defined: current FSB - 50"
);
"Minimum FSB to use, if not defined: current FSB - 50"
);
/* DEBUG
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "cpufreq-nforce2", msg)
* Define it if you want verbose debug output, e.g. for bug reporting
*/
//#define NFORCE2_DEBUG
#ifdef NFORCE2_DEBUG
#define dprintk(msg...) printk(msg)
#else
#define dprintk(msg...) do { } while(0)
#endif
/*
/*
* nforce2_calc_fsb - calculate FSB
* nforce2_calc_fsb - calculate FSB
...
...
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
View file @
ba420e28
...
@@ -209,7 +209,7 @@ static unsigned int gx_get_cpuspeed(unsigned int cpu)
...
@@ -209,7 +209,7 @@ static unsigned int gx_get_cpuspeed(unsigned int cpu)
if
((
gx_params
->
pci_suscfg
&
SUSMOD
)
==
0
)
if
((
gx_params
->
pci_suscfg
&
SUSMOD
)
==
0
)
return
stock_freq
;
return
stock_freq
;
return
(
stock_freq
*
gx_params
->
o
n
_duration
)
return
(
stock_freq
*
gx_params
->
o
ff
_duration
)
/
(
gx_params
->
on_duration
+
gx_params
->
off_duration
);
/
(
gx_params
->
on_duration
+
gx_params
->
off_duration
);
}
}
...
...
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
View file @
ba420e28
...
@@ -171,7 +171,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
...
@@ -171,7 +171,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
return
speedstep_get_processor_frequency
(
SPEEDSTEP_PROCESSOR_PM
);
return
speedstep_get_processor_frequency
(
SPEEDSTEP_PROCESSOR_PM
);
}
}
if
((
c
->
x86
==
0x06
)
&&
(
c
->
x86_model
==
0x
13
))
{
if
((
c
->
x86
==
0x06
)
&&
(
c
->
x86_model
==
0x
0D
))
{
/* Pentium M (Dothan) */
/* Pentium M (Dothan) */
printk
(
KERN_WARNING
PFX
"Warning: Pentium M detected. "
printk
(
KERN_WARNING
PFX
"Warning: Pentium M detected. "
"The speedstep_centrino module offers voltage scaling"
"The speedstep_centrino module offers voltage scaling"
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
View file @
ba420e28
...
@@ -635,6 +635,17 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
...
@@ -635,6 +635,17 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
static
int
powernow_cpu_exit
(
struct
cpufreq_policy
*
policy
)
{
static
int
powernow_cpu_exit
(
struct
cpufreq_policy
*
policy
)
{
cpufreq_frequency_table_put_attr
(
policy
->
cpu
);
cpufreq_frequency_table_put_attr
(
policy
->
cpu
);
#ifdef CONFIG_X86_POWERNOW_K7_ACPI
if
(
acpi_processor_perf
)
{
acpi_processor_unregister_performance
(
acpi_processor_perf
,
0
);
kfree
(
acpi_processor_perf
);
}
#endif
if
(
powernow_table
)
kfree
(
powernow_table
);
return
0
;
return
0
;
}
}
...
@@ -664,15 +675,7 @@ static int __init powernow_init (void)
...
@@ -664,15 +675,7 @@ static int __init powernow_init (void)
static
void
__exit
powernow_exit
(
void
)
static
void
__exit
powernow_exit
(
void
)
{
{
#ifdef CONFIG_X86_POWERNOW_K7_ACPI
if
(
acpi_processor_perf
)
{
acpi_processor_unregister_performance
(
acpi_processor_perf
,
0
);
kfree
(
acpi_processor_perf
);
}
#endif
cpufreq_unregister_driver
(
&
powernow_driver
);
cpufreq_unregister_driver
(
&
powernow_driver
);
if
(
powernow_table
)
kfree
(
powernow_table
);
}
}
module_param
(
acpi_force
,
int
,
0444
);
module_param
(
acpi_force
,
int
,
0444
);
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
View file @
ba420e28
...
@@ -18,6 +18,9 @@
...
@@ -18,6 +18,9 @@
* Processor information obtained from Chapter 9 (Power and Thermal Management)
* Processor information obtained from Chapter 9 (Power and Thermal Management)
* of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
* of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
* Opteron Processors" available for download from www.amd.com
* Opteron Processors" available for download from www.amd.com
*
* Tables for specific CPUs can be infrerred from
* http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
*/
*/
#include <linux/kernel.h>
#include <linux/kernel.h>
...
@@ -65,7 +68,12 @@ static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid)
...
@@ -65,7 +68,12 @@ static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid)
return
1550
-
vid
*
25
;
return
1550
-
vid
*
25
;
}
}
/* Return the vco fid for an input fid */
/* Return the vco fid for an input fid
*
* Each "low" fid has corresponding "high" fid, and you can get to "low" fids
* only from corresponding high fids. This returns "high" fid corresponding to
* "low" one.
*/
static
u32
convert_fid_to_vco_fid
(
u32
fid
)
static
u32
convert_fid_to_vco_fid
(
u32
fid
)
{
{
if
(
fid
<
HI_FID_TABLE_BOTTOM
)
{
if
(
fid
<
HI_FID_TABLE_BOTTOM
)
{
...
@@ -278,7 +286,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
...
@@ -278,7 +286,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
return
1
;
return
1
;
}
}
while
(
rvosteps
>
0
)
{
while
(
(
rvosteps
>
0
)
&&
((
data
->
rvo
+
data
->
currvid
)
>
reqvid
)
)
{
if
(
data
->
currvid
==
0
)
{
if
(
data
->
currvid
==
0
)
{
rvosteps
=
0
;
rvosteps
=
0
;
}
else
{
}
else
{
...
@@ -307,10 +315,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
...
@@ -307,10 +315,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
/* Phase 2 - core frequency transition */
/* Phase 2 - core frequency transition */
static
int
core_frequency_transition
(
struct
powernow_k8_data
*
data
,
u32
reqfid
)
static
int
core_frequency_transition
(
struct
powernow_k8_data
*
data
,
u32
reqfid
)
{
{
u32
vcoreqfid
;
u32
vcoreqfid
,
vcocurrfid
,
vcofiddiff
,
savevid
=
data
->
currvid
;
u32
vcocurrfid
;
u32
vcofiddiff
;
u32
savevid
=
data
->
currvid
;
if
((
reqfid
<
HI_FID_TABLE_BOTTOM
)
&&
(
data
->
currfid
<
HI_FID_TABLE_BOTTOM
))
{
if
((
reqfid
<
HI_FID_TABLE_BOTTOM
)
&&
(
data
->
currfid
<
HI_FID_TABLE_BOTTOM
))
{
printk
(
KERN_ERR
PFX
"ph2: illegal lo-lo transition 0x%x 0x%x
\n
"
,
printk
(
KERN_ERR
PFX
"ph2: illegal lo-lo transition 0x%x 0x%x
\n
"
,
...
@@ -498,7 +503,7 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8
...
@@ -498,7 +503,7 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8
||
(
pst
[
j
].
fid
&
1
)
||
(
pst
[
j
].
fid
&
1
)
||
(
j
&&
(
pst
[
j
].
fid
<
HI_FID_TABLE_BOTTOM
)))
{
||
(
j
&&
(
pst
[
j
].
fid
<
HI_FID_TABLE_BOTTOM
)))
{
/* Only first fid is allowed to be in "low" range */
/* Only first fid is allowed to be in "low" range */
printk
(
KERN_ERR
PFX
"
fid %d invali
d : 0x%x
\n
"
,
j
,
pst
[
j
].
fid
);
printk
(
KERN_ERR
PFX
"
two low fids - %
d : 0x%x
\n
"
,
j
,
pst
[
j
].
fid
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
pst
[
j
].
fid
<
lastfid
)
if
(
pst
[
j
].
fid
<
lastfid
)
...
@@ -618,7 +623,7 @@ static int find_psb_table(struct powernow_k8_data *data)
...
@@ -618,7 +623,7 @@ static int find_psb_table(struct powernow_k8_data *data)
return
-
ENODEV
;
return
-
ENODEV
;
}
}
data
->
vstable
=
psb
->
v
oltagestabilizationtim
e
;
data
->
vstable
=
psb
->
v
stabl
e
;
dprintk
(
"voltage stabilization time: %d(*20us)
\n
"
,
data
->
vstable
);
dprintk
(
"voltage stabilization time: %d(*20us)
\n
"
,
data
->
vstable
);
dprintk
(
"flags2: 0x%x
\n
"
,
psb
->
flags2
);
dprintk
(
"flags2: 0x%x
\n
"
,
psb
->
flags2
);
...
@@ -632,8 +637,8 @@ static int find_psb_table(struct powernow_k8_data *data)
...
@@ -632,8 +637,8 @@ static int find_psb_table(struct powernow_k8_data *data)
dprintk
(
"isochronous relief time: %d
\n
"
,
data
->
irt
);
dprintk
(
"isochronous relief time: %d
\n
"
,
data
->
irt
);
dprintk
(
"maximum voltage step: %d - 0x%x
\n
"
,
mvs
,
data
->
vidmvs
);
dprintk
(
"maximum voltage step: %d - 0x%x
\n
"
,
mvs
,
data
->
vidmvs
);
dprintk
(
"numpst: 0x%x
\n
"
,
psb
->
num
pst
);
dprintk
(
"numpst: 0x%x
\n
"
,
psb
->
num
_tables
);
cpst
=
psb
->
num
pst
;
cpst
=
psb
->
num
_tables
;
if
((
psb
->
cpuid
==
0x00000fc0
)
||
(
psb
->
cpuid
==
0x00000fe0
)
){
if
((
psb
->
cpuid
==
0x00000fc0
)
||
(
psb
->
cpuid
==
0x00000fe0
)
){
thiscpuid
=
cpuid_eax
(
CPUID_PROCESSOR_SIGNATURE
);
thiscpuid
=
cpuid_eax
(
CPUID_PROCESSOR_SIGNATURE
);
if
((
thiscpuid
==
0x00000fc0
)
||
(
thiscpuid
==
0x00000fe0
)
)
{
if
((
thiscpuid
==
0x00000fc0
)
||
(
thiscpuid
==
0x00000fe0
)
)
{
...
@@ -651,7 +656,7 @@ static int find_psb_table(struct powernow_k8_data *data)
...
@@ -651,7 +656,7 @@ static int find_psb_table(struct powernow_k8_data *data)
dprintk
(
"maxvid: 0x%x
\n
"
,
psb
->
maxvid
);
dprintk
(
"maxvid: 0x%x
\n
"
,
psb
->
maxvid
);
maxvid
=
psb
->
maxvid
;
maxvid
=
psb
->
maxvid
;
data
->
numps
=
psb
->
numps
tates
;
data
->
numps
=
psb
->
numps
;
dprintk
(
"numpstates: 0x%x
\n
"
,
data
->
numps
);
dprintk
(
"numpstates: 0x%x
\n
"
,
data
->
numps
);
return
fill_powernow_table
(
data
,
(
struct
pst_s
*
)(
psb
+
1
),
maxvid
);
return
fill_powernow_table
(
data
,
(
struct
pst_s
*
)(
psb
+
1
),
maxvid
);
}
}
...
@@ -1010,6 +1015,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
...
@@ -1010,6 +1015,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
/* min/max the cpu is capable of */
/* min/max the cpu is capable of */
if
(
cpufreq_frequency_table_cpuinfo
(
pol
,
data
->
powernow_table
))
{
if
(
cpufreq_frequency_table_cpuinfo
(
pol
,
data
->
powernow_table
))
{
printk
(
KERN_ERR
PFX
"invalid powernow_table
\n
"
);
printk
(
KERN_ERR
PFX
"invalid powernow_table
\n
"
);
powernow_k8_cpu_exit_acpi
(
data
);
kfree
(
data
->
powernow_table
);
kfree
(
data
->
powernow_table
);
kfree
(
data
);
kfree
(
data
);
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -1027,6 +1033,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
...
@@ -1027,6 +1033,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
err_out:
err_out:
set_cpus_allowed
(
current
,
oldmask
);
set_cpus_allowed
(
current
,
oldmask
);
schedule
();
schedule
();
powernow_k8_cpu_exit_acpi
(
data
);
kfree
(
data
);
kfree
(
data
);
return
-
ENODEV
;
return
-
ENODEV
;
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
View file @
ba420e28
...
@@ -21,8 +21,7 @@ struct powernow_k8_data {
...
@@ -21,8 +21,7 @@ struct powernow_k8_data {
u32
plllock
;
/* pll lock time, units 1 us */
u32
plllock
;
/* pll lock time, units 1 us */
/* keep track of the current fid / vid */
/* keep track of the current fid / vid */
u32
currvid
;
u32
currvid
,
currfid
;
u32
currfid
;
/* the powernow_table includes all frequency and vid/fid pairings:
/* the powernow_table includes all frequency and vid/fid pairings:
* fid are the lower 8 bits of the index, vid are the upper 8 bits.
* fid are the lower 8 bits of the index, vid are the upper 8 bits.
...
@@ -152,14 +151,14 @@ struct psb_s {
...
@@ -152,14 +151,14 @@ struct psb_s {
u8
signature
[
10
];
u8
signature
[
10
];
u8
tableversion
;
u8
tableversion
;
u8
flags1
;
u8
flags1
;
u16
v
oltagestabilizationtim
e
;
u16
v
stabl
e
;
u8
flags2
;
u8
flags2
;
u8
num
pst
;
u8
num
_tables
;
u32
cpuid
;
u32
cpuid
;
u8
plllocktime
;
u8
plllocktime
;
u8
maxfid
;
u8
maxfid
;
u8
maxvid
;
u8
maxvid
;
u8
numps
tates
;
u8
numps
;
};
};
/* Pairs of fid/vid values are appended to the version 1.4 PSB table. */
/* Pairs of fid/vid values are appended to the version 1.4 PSB table. */
...
...
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
View file @
ba420e28
...
@@ -22,6 +22,8 @@
...
@@ -22,6 +22,8 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/cpufreq.h>
#include <linux/config.h>
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/compiler.h>
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
#include <linux/acpi.h>
#include <linux/acpi.h>
...
@@ -32,6 +34,8 @@
...
@@ -32,6 +34,8 @@
#include <asm/processor.h>
#include <asm/processor.h>
#include <asm/cpufeature.h>
#include <asm/cpufeature.h>
#include "speedstep-est-common.h"
#define PFX "speedstep-centrino: "
#define PFX "speedstep-centrino: "
#define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>"
#define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>"
...
@@ -71,8 +75,10 @@ struct cpu_model
...
@@ -71,8 +75,10 @@ struct cpu_model
static
int
centrino_verify_cpu_id
(
const
struct
cpuinfo_x86
*
c
,
const
struct
cpu_id
*
x
);
static
int
centrino_verify_cpu_id
(
const
struct
cpuinfo_x86
*
c
,
const
struct
cpu_id
*
x
);
/* Operating points for current CPU */
/* Operating points for current CPU */
static
struct
cpu_model
*
centrino_model
;
static
struct
cpu_model
*
centrino_model
[
NR_CPUS
];
static
const
struct
cpu_id
*
centrino_cpu
;
static
const
struct
cpu_id
*
centrino_cpu
[
NR_CPUS
];
static
struct
cpufreq_driver
centrino_driver
;
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
...
@@ -239,7 +245,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
...
@@ -239,7 +245,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
if
(
model
->
cpu_id
==
NULL
)
{
if
(
model
->
cpu_id
==
NULL
)
{
/* No match at all */
/* No match at all */
printk
(
KERN_INFO
PFX
"no support for CPU model
\"
%s
\"
: "
d
printk
(
KERN_INFO
PFX
"no support for CPU model
\"
%s
\"
: "
"send /proc/cpuinfo to "
MAINTAINER
"
\n
"
,
"send /proc/cpuinfo to "
MAINTAINER
"
\n
"
,
cpu
->
x86_model_id
);
cpu
->
x86_model_id
);
return
-
ENOENT
;
return
-
ENOENT
;
...
@@ -247,15 +253,15 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
...
@@ -247,15 +253,15 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
if
(
model
->
op_points
==
NULL
)
{
if
(
model
->
op_points
==
NULL
)
{
/* Matched a non-match */
/* Matched a non-match */
printk
(
KERN_INFO
PFX
"no table support for CPU model
\"
%s
\"
:
\n
"
,
d
printk
(
KERN_INFO
PFX
"no table support for CPU model
\"
%s
\"
:
\n
"
,
cpu
->
x86_model_id
);
cpu
->
x86_model_id
);
#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
printk
(
KERN_INFO
PFX
"try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled
\n
"
);
d
printk
(
KERN_INFO
PFX
"try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled
\n
"
);
#endif
#endif
return
-
ENOENT
;
return
-
ENOENT
;
}
}
centrino_model
=
model
;
centrino_model
[
policy
->
cpu
]
=
model
;
dprintk
(
"found
\"
%s
\"
: max frequency: %dkHz
\n
"
,
dprintk
(
"found
\"
%s
\"
: max frequency: %dkHz
\n
"
,
model
->
model_name
,
model
->
max_freq
);
model
->
model_name
,
model
->
max_freq
);
...
@@ -277,7 +283,7 @@ static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_
...
@@ -277,7 +283,7 @@ static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_
}
}
/* To be called only after centrino_model is initialized */
/* To be called only after centrino_model is initialized */
static
unsigned
extract_clock
(
unsigned
msr
)
static
unsigned
extract_clock
(
unsigned
msr
,
unsigned
int
cpu
,
int
failsafe
)
{
{
int
i
;
int
i
;
...
@@ -286,28 +292,32 @@ static unsigned extract_clock(unsigned msr)
...
@@ -286,28 +292,32 @@ static unsigned extract_clock(unsigned msr)
* for centrino, as some DSDTs are buggy.
* for centrino, as some DSDTs are buggy.
* Ideally, this can be done using the acpi_data structure.
* Ideally, this can be done using the acpi_data structure.
*/
*/
if
((
centrino_cpu
==
&
cpu_ids
[
CPU_BANIAS
])
||
if
((
centrino_cpu
[
cpu
]
==
&
cpu_ids
[
CPU_BANIAS
])
||
(
centrino_cpu
==
&
cpu_ids
[
CPU_DOTHAN_A1
])
||
(
centrino_cpu
[
cpu
]
==
&
cpu_ids
[
CPU_DOTHAN_A1
])
||
(
centrino_cpu
==
&
cpu_ids
[
CPU_DOTHAN_B0
]))
{
(
centrino_cpu
[
cpu
]
==
&
cpu_ids
[
CPU_DOTHAN_B0
]))
{
msr
=
(
msr
>>
8
)
&
0xff
;
msr
=
(
msr
>>
8
)
&
0xff
;
return
msr
*
100000
;
return
msr
*
100000
;
}
}
if
((
!
centrino_model
)
||
(
!
centrino_model
->
op_points
))
if
((
!
centrino_model
[
cpu
])
||
(
!
centrino_model
[
cpu
]
->
op_points
))
return
0
;
return
0
;
msr
&=
0xffff
;
msr
&=
0xffff
;
for
(
i
=
0
;
centrino_model
->
op_points
[
i
].
frequency
!=
CPUFREQ_TABLE_END
;
i
++
)
{
for
(
i
=
0
;
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
!=
CPUFREQ_TABLE_END
;
i
++
)
{
if
(
msr
==
centrino_model
->
op_points
[
i
].
index
)
if
(
msr
==
centrino_model
[
cpu
]
->
op_points
[
i
].
index
)
return
centrino_model
->
op_points
[
i
].
frequency
;
return
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
;
}
}
return
0
;
if
(
failsafe
)
return
centrino_model
[
cpu
]
->
op_points
[
i
-
1
].
frequency
;
else
return
0
;
}
}
/* Return the current CPU frequency in kHz */
/* Return the current CPU frequency in kHz */
static
unsigned
int
get_cur_freq
(
unsigned
int
cpu
)
static
unsigned
int
get_cur_freq
(
unsigned
int
cpu
)
{
{
unsigned
l
,
h
;
unsigned
l
,
h
;
unsigned
clock_freq
;
cpumask_t
saved_mask
;
cpumask_t
saved_mask
;
saved_mask
=
current
->
cpus_allowed
;
saved_mask
=
current
->
cpus_allowed
;
...
@@ -316,8 +326,21 @@ static unsigned int get_cur_freq(unsigned int cpu)
...
@@ -316,8 +326,21 @@ static unsigned int get_cur_freq(unsigned int cpu)
return
0
;
return
0
;
rdmsr
(
MSR_IA32_PERF_STATUS
,
l
,
h
);
rdmsr
(
MSR_IA32_PERF_STATUS
,
l
,
h
);
clock_freq
=
extract_clock
(
l
,
cpu
,
0
);
if
(
unlikely
(
clock_freq
==
0
))
{
/*
* On some CPUs, we can see transient MSR values (which are
* not present in _PSS), while CPU is doing some automatic
* P-state transition (like TM2). Get the last freq set
* in PERF_CTL.
*/
rdmsr
(
MSR_IA32_PERF_CTL
,
l
,
h
);
clock_freq
=
extract_clock
(
l
,
cpu
,
1
);
}
set_cpus_allowed
(
current
,
saved_mask
);
set_cpus_allowed
(
current
,
saved_mask
);
return
extract_clock
(
l
)
;
return
clock_freq
;
}
}
...
@@ -339,6 +362,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
...
@@ -339,6 +362,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
struct
acpi_object_list
arg_list
=
{
1
,
&
arg0
};
struct
acpi_object_list
arg_list
=
{
1
,
&
arg0
};
unsigned
long
cur_freq
;
unsigned
long
cur_freq
;
int
result
=
0
,
i
;
int
result
=
0
,
i
;
unsigned
int
cpu
=
policy
->
cpu
;
/* _PDC settings */
/* _PDC settings */
arg0
.
buffer
.
length
=
12
;
arg0
.
buffer
.
length
=
12
;
...
@@ -350,8 +374,8 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
...
@@ -350,8 +374,8 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
p
.
pdc
=
&
arg_list
;
p
.
pdc
=
&
arg_list
;
/* register with ACPI core */
/* register with ACPI core */
if
(
acpi_processor_register_performance
(
&
p
,
policy
->
cpu
))
{
if
(
acpi_processor_register_performance
(
&
p
,
cpu
))
{
printk
(
KERN_INFO
PFX
"obtaining ACPI data failed
\n
"
);
d
printk
(
KERN_INFO
PFX
"obtaining ACPI data failed
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
...
@@ -392,49 +416,49 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
...
@@ -392,49 +416,49 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
}
}
}
}
centrino_model
=
kmalloc
(
sizeof
(
struct
cpu_model
),
GFP_KERNEL
);
centrino_model
[
cpu
]
=
kmalloc
(
sizeof
(
struct
cpu_model
),
GFP_KERNEL
);
if
(
!
centrino_model
)
{
if
(
!
centrino_model
[
cpu
]
)
{
result
=
-
ENOMEM
;
result
=
-
ENOMEM
;
goto
err_unreg
;
goto
err_unreg
;
}
}
memset
(
centrino_model
,
0
,
sizeof
(
struct
cpu_model
));
memset
(
centrino_model
[
cpu
]
,
0
,
sizeof
(
struct
cpu_model
));
centrino_model
->
model_name
=
NULL
;
centrino_model
[
cpu
]
->
model_name
=
NULL
;
centrino_model
->
max_freq
=
p
.
states
[
0
].
core_frequency
*
1000
;
centrino_model
[
cpu
]
->
max_freq
=
p
.
states
[
0
].
core_frequency
*
1000
;
centrino_model
->
op_points
=
kmalloc
(
sizeof
(
struct
cpufreq_frequency_table
)
*
centrino_model
[
cpu
]
->
op_points
=
kmalloc
(
sizeof
(
struct
cpufreq_frequency_table
)
*
(
p
.
state_count
+
1
),
GFP_KERNEL
);
(
p
.
state_count
+
1
),
GFP_KERNEL
);
if
(
!
centrino_model
->
op_points
)
{
if
(
!
centrino_model
[
cpu
]
->
op_points
)
{
result
=
-
ENOMEM
;
result
=
-
ENOMEM
;
goto
err_kfree
;
goto
err_kfree
;
}
}
for
(
i
=
0
;
i
<
p
.
state_count
;
i
++
)
{
for
(
i
=
0
;
i
<
p
.
state_count
;
i
++
)
{
centrino_model
->
op_points
[
i
].
index
=
p
.
states
[
i
].
control
;
centrino_model
[
cpu
]
->
op_points
[
i
].
index
=
p
.
states
[
i
].
control
;
centrino_model
->
op_points
[
i
].
frequency
=
p
.
states
[
i
].
core_frequency
*
1000
;
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
=
p
.
states
[
i
].
core_frequency
*
1000
;
dprintk
(
"adding state %i with frequency %u and control value %04x
\n
"
,
dprintk
(
"adding state %i with frequency %u and control value %04x
\n
"
,
i
,
centrino_model
->
op_points
[
i
].
frequency
,
centrino_model
->
op_points
[
i
].
index
);
i
,
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
,
centrino_model
[
cpu
]
->
op_points
[
i
].
index
);
}
}
centrino_model
->
op_points
[
p
.
state_count
].
frequency
=
CPUFREQ_TABLE_END
;
centrino_model
[
cpu
]
->
op_points
[
p
.
state_count
].
frequency
=
CPUFREQ_TABLE_END
;
cur_freq
=
get_cur_freq
(
policy
->
cpu
);
cur_freq
=
get_cur_freq
(
cpu
);
for
(
i
=
0
;
i
<
p
.
state_count
;
i
++
)
{
for
(
i
=
0
;
i
<
p
.
state_count
;
i
++
)
{
if
(
!
p
.
states
[
i
].
core_frequency
)
{
if
(
!
p
.
states
[
i
].
core_frequency
)
{
dprintk
(
"skipping state %u
\n
"
,
i
);
dprintk
(
"skipping state %u
\n
"
,
i
);
centrino_model
->
op_points
[
i
].
frequency
=
CPUFREQ_ENTRY_INVALID
;
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
=
CPUFREQ_ENTRY_INVALID
;
continue
;
continue
;
}
}
if
(
extract_clock
(
centrino_model
->
op_points
[
i
].
index
)
!=
if
(
extract_clock
(
centrino_model
[
cpu
]
->
op_points
[
i
].
index
,
cpu
,
0
)
!=
(
centrino_model
->
op_points
[
i
].
frequency
))
{
(
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
))
{
dprintk
(
"Invalid encoded frequency (%u vs. %u)
\n
"
,
dprintk
(
"Invalid encoded frequency (%u vs. %u)
\n
"
,
extract_clock
(
centrino_model
->
op_points
[
i
].
index
),
extract_clock
(
centrino_model
[
cpu
]
->
op_points
[
i
].
index
,
cpu
,
0
),
centrino_model
->
op_points
[
i
].
frequency
);
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
);
result
=
-
EINVAL
;
result
=
-
EINVAL
;
goto
err_kfree_all
;
goto
err_kfree_all
;
}
}
if
(
cur_freq
==
centrino_model
->
op_points
[
i
].
frequency
)
if
(
cur_freq
==
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
)
p
.
state
=
i
;
p
.
state
=
i
;
}
}
...
@@ -444,12 +468,12 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
...
@@ -444,12 +468,12 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
return
0
;
return
0
;
err_kfree_all:
err_kfree_all:
kfree
(
centrino_model
->
op_points
);
kfree
(
centrino_model
[
cpu
]
->
op_points
);
err_kfree:
err_kfree:
kfree
(
centrino_model
);
kfree
(
centrino_model
[
cpu
]
);
err_unreg:
err_unreg:
acpi_processor_unregister_performance
(
&
p
,
policy
->
cpu
);
acpi_processor_unregister_performance
(
&
p
,
cpu
);
printk
(
KERN_INFO
PFX
"invalid ACPI data
\n
"
);
d
printk
(
KERN_INFO
PFX
"invalid ACPI data
\n
"
);
return
(
result
);
return
(
result
);
}
}
#else
#else
...
@@ -473,14 +497,18 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
...
@@ -473,14 +497,18 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
break
;
break
;
if
(
i
!=
N_IDS
)
if
(
i
!=
N_IDS
)
centrino_cpu
=
&
cpu_ids
[
i
];
centrino_cpu
[
policy
->
cpu
]
=
&
cpu_ids
[
i
];
if
(
is_const_loops_cpu
(
policy
->
cpu
))
{
centrino_driver
.
flags
|=
CPUFREQ_CONST_LOOPS
;
}
if
(
centrino_cpu_init_acpi
(
policy
))
{
if
(
centrino_cpu_init_acpi
(
policy
))
{
if
(
policy
->
cpu
!=
0
)
if
(
policy
->
cpu
!=
0
)
return
-
ENODEV
;
return
-
ENODEV
;
if
(
!
centrino_cpu
)
{
if
(
!
centrino_cpu
[
policy
->
cpu
]
)
{
printk
(
KERN_INFO
PFX
"found unsupported CPU with "
d
printk
(
KERN_INFO
PFX
"found unsupported CPU with "
"Enhanced SpeedStep: send /proc/cpuinfo to "
"Enhanced SpeedStep: send /proc/cpuinfo to "
MAINTAINER
"
\n
"
);
MAINTAINER
"
\n
"
);
return
-
ENODEV
;
return
-
ENODEV
;
...
@@ -516,32 +544,34 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
...
@@ -516,32 +544,34 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
dprintk
(
"centrino_cpu_init: cur=%dkHz
\n
"
,
policy
->
cur
);
dprintk
(
"centrino_cpu_init: cur=%dkHz
\n
"
,
policy
->
cur
);
ret
=
cpufreq_frequency_table_cpuinfo
(
policy
,
centrino_model
->
op_points
);
ret
=
cpufreq_frequency_table_cpuinfo
(
policy
,
centrino_model
[
policy
->
cpu
]
->
op_points
);
if
(
ret
)
if
(
ret
)
return
(
ret
);
return
(
ret
);
cpufreq_frequency_table_get_attr
(
centrino_model
->
op_points
,
policy
->
cpu
);
cpufreq_frequency_table_get_attr
(
centrino_model
[
policy
->
cpu
]
->
op_points
,
policy
->
cpu
);
return
0
;
return
0
;
}
}
static
int
centrino_cpu_exit
(
struct
cpufreq_policy
*
policy
)
static
int
centrino_cpu_exit
(
struct
cpufreq_policy
*
policy
)
{
{
if
(
!
centrino_model
)
unsigned
int
cpu
=
policy
->
cpu
;
if
(
!
centrino_model
[
cpu
])
return
-
ENODEV
;
return
-
ENODEV
;
cpufreq_frequency_table_put_attr
(
policy
->
cpu
);
cpufreq_frequency_table_put_attr
(
cpu
);
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
if
(
!
centrino_model
->
model_name
)
{
if
(
!
centrino_model
[
cpu
]
->
model_name
)
{
dprintk
(
"unregistering and freeing ACPI data
\n
"
);
dprintk
(
"unregistering and freeing ACPI data
\n
"
);
acpi_processor_unregister_performance
(
&
p
,
policy
->
cpu
);
acpi_processor_unregister_performance
(
&
p
,
cpu
);
kfree
(
centrino_model
->
op_points
);
kfree
(
centrino_model
[
cpu
]
->
op_points
);
kfree
(
centrino_model
);
kfree
(
centrino_model
[
cpu
]
);
}
}
#endif
#endif
centrino_model
=
NULL
;
centrino_model
[
cpu
]
=
NULL
;
return
0
;
return
0
;
}
}
...
@@ -555,7 +585,7 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
...
@@ -555,7 +585,7 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
*/
*/
static
int
centrino_verify
(
struct
cpufreq_policy
*
policy
)
static
int
centrino_verify
(
struct
cpufreq_policy
*
policy
)
{
{
return
cpufreq_frequency_table_verify
(
policy
,
centrino_model
->
op_points
);
return
cpufreq_frequency_table_verify
(
policy
,
centrino_model
[
policy
->
cpu
]
->
op_points
);
}
}
/**
/**
...
@@ -571,12 +601,12 @@ static int centrino_target (struct cpufreq_policy *policy,
...
@@ -571,12 +601,12 @@ static int centrino_target (struct cpufreq_policy *policy,
unsigned
int
relation
)
unsigned
int
relation
)
{
{
unsigned
int
newstate
=
0
;
unsigned
int
newstate
=
0
;
unsigned
int
msr
,
oldmsr
,
h
;
unsigned
int
msr
,
oldmsr
,
h
,
cpu
=
policy
->
cpu
;
struct
cpufreq_freqs
freqs
;
struct
cpufreq_freqs
freqs
;
cpumask_t
saved_mask
;
cpumask_t
saved_mask
;
int
retval
;
int
retval
;
if
(
centrino_model
==
NULL
)
if
(
centrino_model
[
cpu
]
==
NULL
)
return
-
ENODEV
;
return
-
ENODEV
;
/*
/*
...
@@ -585,18 +615,18 @@ static int centrino_target (struct cpufreq_policy *policy,
...
@@ -585,18 +615,18 @@ static int centrino_target (struct cpufreq_policy *policy,
*/
*/
saved_mask
=
current
->
cpus_allowed
;
saved_mask
=
current
->
cpus_allowed
;
set_cpus_allowed
(
current
,
policy
->
cpus
);
set_cpus_allowed
(
current
,
policy
->
cpus
);
if
(
smp_processor_id
()
!=
policy
->
cpu
)
{
if
(
!
cpu_isset
(
smp_processor_id
(),
policy
->
cpus
)
)
{
dprintk
(
"couldn't limit to CPUs in this domain
\n
"
);
dprintk
(
"couldn't limit to CPUs in this domain
\n
"
);
return
(
-
EAGAIN
);
return
(
-
EAGAIN
);
}
}
if
(
cpufreq_frequency_table_target
(
policy
,
centrino_model
->
op_points
,
target_freq
,
if
(
cpufreq_frequency_table_target
(
policy
,
centrino_model
[
cpu
]
->
op_points
,
target_freq
,
relation
,
&
newstate
))
{
relation
,
&
newstate
))
{
retval
=
-
EINVAL
;
retval
=
-
EINVAL
;
goto
migrate_end
;
goto
migrate_end
;
}
}
msr
=
centrino_model
->
op_points
[
newstate
].
index
;
msr
=
centrino_model
[
cpu
]
->
op_points
[
newstate
].
index
;
rdmsr
(
MSR_IA32_PERF_CTL
,
oldmsr
,
h
);
rdmsr
(
MSR_IA32_PERF_CTL
,
oldmsr
,
h
);
if
(
msr
==
(
oldmsr
&
0xffff
))
{
if
(
msr
==
(
oldmsr
&
0xffff
))
{
...
@@ -605,9 +635,9 @@ static int centrino_target (struct cpufreq_policy *policy,
...
@@ -605,9 +635,9 @@ static int centrino_target (struct cpufreq_policy *policy,
goto
migrate_end
;
goto
migrate_end
;
}
}
freqs
.
cpu
=
policy
->
cpu
;
freqs
.
cpu
=
cpu
;
freqs
.
old
=
extract_clock
(
oldmsr
);
freqs
.
old
=
extract_clock
(
oldmsr
,
cpu
,
0
);
freqs
.
new
=
extract_clock
(
msr
);
freqs
.
new
=
extract_clock
(
msr
,
cpu
,
0
);
dprintk
(
"target=%dkHz old=%d new=%d msr=%04x
\n
"
,
dprintk
(
"target=%dkHz old=%d new=%d msr=%04x
\n
"
,
target_freq
,
freqs
.
old
,
freqs
.
new
,
msr
);
target_freq
,
freqs
.
old
,
freqs
.
new
,
msr
);
...
...
arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h
0 → 100644
View file @
ba420e28
/*
* Routines common for drivers handling Enhanced Speedstep Technology
* Copyright (C) 2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
*
* Licensed under the terms of the GNU GPL License version 2 -- see
* COPYING for details.
*/
static
inline
int
is_const_loops_cpu
(
unsigned
int
cpu
)
{
struct
cpuinfo_x86
*
c
=
cpu_data
+
cpu
;
if
(
c
->
x86_vendor
!=
X86_VENDOR_INTEL
||
!
cpu_has
(
c
,
X86_FEATURE_EST
))
return
0
;
/*
* on P-4s, the TSC runs with constant frequency independent of cpu freq
* when we use EST
*/
if
(
c
->
x86
==
0xf
)
return
1
;
return
0
;
}
drivers/cpufreq/Kconfig
View file @
ba420e28
...
@@ -27,17 +27,21 @@ config CPU_FREQ_DEBUG
...
@@ -27,17 +27,21 @@ config CPU_FREQ_DEBUG
2 to activate CPUfreq drivers debugging, and
2 to activate CPUfreq drivers debugging, and
4 to activate CPUfreq governor debugging
4 to activate CPUfreq governor debugging
config CPU_FREQ_PROC_INTF
config CPU_FREQ_STAT
tristate "/proc/cpufreq interface (deprecated)"
tristate "CPU frequency translation statistics"
depends on CPU_FREQ && PROC_FS
depends on CPU_FREQ && CPU_FREQ_TABLE
help
default y
This enables the /proc/cpufreq interface for controlling
help
CPUFreq. Please note that it is recommended to use the sysfs
This driver exports CPU frequency statistics information through sysfs
interface instead (which is built automatically).
file system
For details, take a look at <file:Documentation/cpu-freq/>.
config CPU_FREQ_STAT_DETAILS
bool "CPU frequency translation statistics details"
If in doubt, say N.
depends on CPU_FREQ && CPU_FREQ_STAT
default n
help
This will show detail CPU frequency translation table in sysfs file
system
choice
choice
prompt "Default CPUFreq governor"
prompt "Default CPUFreq governor"
...
@@ -98,21 +102,6 @@ config CPU_FREQ_GOV_USERSPACE
...
@@ -98,21 +102,6 @@ config CPU_FREQ_GOV_USERSPACE
If in doubt, say Y.
If in doubt, say Y.
config CPU_FREQ_24_API
bool "/proc/sys/cpu/ interface (2.4. / OLD)"
depends on CPU_FREQ_GOV_USERSPACE
depends on SYSCTL
help
This enables the /proc/sys/cpu/ sysctl interface for controlling
the CPUFreq,"userspace" governor. This is the same interface
as known from the 2.4.-kernel patches for CPUFreq, and offers
the same functionality as long as "userspace" is the
selected governor for the specified CPU.
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
config CPU_FREQ_GOV_ONDEMAND
config CPU_FREQ_GOV_ONDEMAND
tristate "'ondemand' cpufreq policy governor"
tristate "'ondemand' cpufreq policy governor"
depends on CPU_FREQ
depends on CPU_FREQ
...
...
drivers/cpufreq/Makefile
View file @
ba420e28
# CPUfreq core
# CPUfreq core
obj-$(CONFIG_CPU_FREQ)
+=
cpufreq.o
obj-$(CONFIG_CPU_FREQ)
+=
cpufreq.o
# CPUfreq stats
obj-$(CONFIG_CPU_FREQ_STAT)
+=
cpufreq_stats.o
# CPUfreq governors
# CPUfreq governors
obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE)
+=
cpufreq_performance.o
obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE)
+=
cpufreq_performance.o
...
@@ -9,5 +11,4 @@ obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
...
@@ -9,5 +11,4 @@ obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
# CPUfreq cross-arch helpers
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE)
+=
freq_table.o
obj-$(CONFIG_CPU_FREQ_TABLE)
+=
freq_table.o
obj-$(CONFIG_CPU_FREQ_PROC_INTF)
+=
proc_intf.o
drivers/cpufreq/cpufreq.c
View file @
ba420e28
...
@@ -63,7 +63,7 @@ static DECLARE_RWSEM (cpufreq_notifier_rwsem);
...
@@ -63,7 +63,7 @@ static DECLARE_RWSEM (cpufreq_notifier_rwsem);
static
LIST_HEAD
(
cpufreq_governor_list
);
static
LIST_HEAD
(
cpufreq_governor_list
);
static
DECLARE_MUTEX
(
cpufreq_governor_sem
);
static
DECLARE_MUTEX
(
cpufreq_governor_sem
);
st
atic
st
ruct
cpufreq_policy
*
cpufreq_cpu_get
(
unsigned
int
cpu
)
struct
cpufreq_policy
*
cpufreq_cpu_get
(
unsigned
int
cpu
)
{
{
struct
cpufreq_policy
*
data
;
struct
cpufreq_policy
*
data
;
unsigned
long
flags
;
unsigned
long
flags
;
...
@@ -102,12 +102,14 @@ static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
...
@@ -102,12 +102,14 @@ static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
err_out:
err_out:
return
NULL
;
return
NULL
;
}
}
EXPORT_SYMBOL_GPL
(
cpufreq_cpu_get
);
static
void
cpufreq_cpu_put
(
struct
cpufreq_policy
*
data
)
void
cpufreq_cpu_put
(
struct
cpufreq_policy
*
data
)
{
{
kobject_put
(
&
data
->
kobj
);
kobject_put
(
&
data
->
kobj
);
module_put
(
cpufreq_driver
->
owner
);
module_put
(
cpufreq_driver
->
owner
);
}
}
EXPORT_SYMBOL_GPL
(
cpufreq_cpu_put
);
/*********************************************************************
/*********************************************************************
...
@@ -285,7 +287,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
...
@@ -285,7 +287,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/**
/**
* cpufreq_parse_governor - parse a governor string
* cpufreq_parse_governor - parse a governor string
*/
*/
int
cpufreq_parse_governor
(
char
*
str_governor
,
unsigned
int
*
policy
,
static
int
cpufreq_parse_governor
(
char
*
str_governor
,
unsigned
int
*
policy
,
struct
cpufreq_governor
**
governor
)
struct
cpufreq_governor
**
governor
)
{
{
if
(
!
cpufreq_driver
)
if
(
!
cpufreq_driver
)
...
@@ -763,8 +765,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
...
@@ -763,8 +765,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
spin_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
spin_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
#endif
#endif
down
(
&
data
->
lock
);
if
(
cpufreq_driver
->
target
)
if
(
cpufreq_driver
->
target
)
__cpufreq_governor
(
data
,
CPUFREQ_GOV_STOP
);
__cpufreq_governor
(
data
,
CPUFREQ_GOV_STOP
);
cpufreq_driver
->
target
=
NULL
;
up
(
&
data
->
lock
);
kobject_unregister
(
&
data
->
kobj
);
kobject_unregister
(
&
data
->
kobj
);
...
@@ -893,6 +898,13 @@ static int cpufreq_resume(struct sys_device * sysdev)
...
@@ -893,6 +898,13 @@ static int cpufreq_resume(struct sys_device * sysdev)
return
0
;
return
0
;
}
}
if
(
cpufreq_driver
->
resume
)
{
ret
=
cpufreq_driver
->
resume
(
cpu_policy
);
printk
(
KERN_ERR
"cpufreq: resume failed in ->resume step on CPU %u
\n
"
,
cpu_policy
->
cpu
);
cpufreq_cpu_put
(
cpu_policy
);
return
(
ret
);
}
if
(
!
(
cpufreq_driver
->
flags
&
CPUFREQ_CONST_LOOPS
))
{
if
(
!
(
cpufreq_driver
->
flags
&
CPUFREQ_CONST_LOOPS
))
{
unsigned
int
cur_freq
=
0
;
unsigned
int
cur_freq
=
0
;
...
@@ -1018,7 +1030,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
...
@@ -1018,7 +1030,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
lock_cpu_hotplug
();
lock_cpu_hotplug
();
dprintk
(
"target for CPU %u: %u kHz, relation %u
\n
"
,
policy
->
cpu
,
dprintk
(
"target for CPU %u: %u kHz, relation %u
\n
"
,
policy
->
cpu
,
target_freq
,
relation
);
target_freq
,
relation
);
if
(
cpu_online
(
policy
->
cpu
))
if
(
cpu_online
(
policy
->
cpu
)
&&
cpufreq_driver
->
target
)
retval
=
cpufreq_driver
->
target
(
policy
,
target_freq
,
relation
);
retval
=
cpufreq_driver
->
target
(
policy
,
target_freq
,
relation
);
unlock_cpu_hotplug
();
unlock_cpu_hotplug
();
return
retval
;
return
retval
;
...
...
drivers/cpufreq/cpufreq_ondemand.c
View file @
ba420e28
...
@@ -229,10 +229,14 @@ static void dbs_check_cpu(int cpu)
...
@@ -229,10 +229,14 @@ static void dbs_check_cpu(int cpu)
static
int
down_skip
[
NR_CPUS
];
static
int
down_skip
[
NR_CPUS
];
struct
cpu_dbs_info_s
*
this_dbs_info
;
struct
cpu_dbs_info_s
*
this_dbs_info
;
struct
cpufreq_policy
*
policy
;
unsigned
int
j
;
this_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
cpu
);
this_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
cpu
);
if
(
!
this_dbs_info
->
enable
)
if
(
!
this_dbs_info
->
enable
)
return
;
return
;
policy
=
this_dbs_info
->
cur_policy
;
/*
/*
* The default safe range is 20% to 80%
* The default safe range is 20% to 80%
* Every sampling_rate, we check
* Every sampling_rate, we check
...
@@ -246,12 +250,33 @@ static void dbs_check_cpu(int cpu)
...
@@ -246,12 +250,33 @@ static void dbs_check_cpu(int cpu)
* Frequency reduction happens at minimum steps of
* Frequency reduction happens at minimum steps of
* 5% of max_frequency
* 5% of max_frequency
*/
*/
/* Check for frequency increase */
/* Check for frequency increase */
total_idle_ticks
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
total_idle_ticks
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
idle_ticks
=
total_idle_ticks
-
idle_ticks
=
total_idle_ticks
-
this_dbs_info
->
prev_cpu_idle_up
;
this_dbs_info
->
prev_cpu_idle_up
;
this_dbs_info
->
prev_cpu_idle_up
=
total_idle_ticks
;
this_dbs_info
->
prev_cpu_idle_up
=
total_idle_ticks
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
unsigned
int
tmp_idle_ticks
;
struct
cpu_dbs_info_s
*
j_dbs_info
;
if
(
j
==
cpu
)
continue
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
/* Check for frequency increase */
total_idle_ticks
=
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
iowait
;
tmp_idle_ticks
=
total_idle_ticks
-
j_dbs_info
->
prev_cpu_idle_up
;
j_dbs_info
->
prev_cpu_idle_up
=
total_idle_ticks
;
if
(
tmp_idle_ticks
<
idle_ticks
)
idle_ticks
=
tmp_idle_ticks
;
}
/* Scale idle ticks by 100 and compare with up and down ticks */
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks
*=
100
;
idle_ticks
*=
100
;
...
@@ -259,8 +284,7 @@ static void dbs_check_cpu(int cpu)
...
@@ -259,8 +284,7 @@ static void dbs_check_cpu(int cpu)
sampling_rate_in_HZ
(
dbs_tuners_ins
.
sampling_rate
);
sampling_rate_in_HZ
(
dbs_tuners_ins
.
sampling_rate
);
if
(
idle_ticks
<
up_idle_ticks
)
{
if
(
idle_ticks
<
up_idle_ticks
)
{
__cpufreq_driver_target
(
this_dbs_info
->
cur_policy
,
__cpufreq_driver_target
(
policy
,
policy
->
max
,
this_dbs_info
->
cur_policy
->
max
,
CPUFREQ_RELATION_H
);
CPUFREQ_RELATION_H
);
down_skip
[
cpu
]
=
0
;
down_skip
[
cpu
]
=
0
;
this_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
this_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
...
@@ -272,12 +296,34 @@ static void dbs_check_cpu(int cpu)
...
@@ -272,12 +296,34 @@ static void dbs_check_cpu(int cpu)
if
(
down_skip
[
cpu
]
<
dbs_tuners_ins
.
sampling_down_factor
)
if
(
down_skip
[
cpu
]
<
dbs_tuners_ins
.
sampling_down_factor
)
return
;
return
;
total_idle_ticks
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
idle_ticks
=
total_idle_ticks
-
idle_ticks
=
total_idle_ticks
-
this_dbs_info
->
prev_cpu_idle_down
;
this_dbs_info
->
prev_cpu_idle_down
;
this_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
unsigned
int
tmp_idle_ticks
;
struct
cpu_dbs_info_s
*
j_dbs_info
;
if
(
j
==
cpu
)
continue
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
/* Check for frequency increase */
total_idle_ticks
=
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
iowait
;
tmp_idle_ticks
=
total_idle_ticks
-
j_dbs_info
->
prev_cpu_idle_down
;
j_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
if
(
tmp_idle_ticks
<
idle_ticks
)
idle_ticks
=
tmp_idle_ticks
;
}
/* Scale idle ticks by 100 and compare with up and down ticks */
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks
*=
100
;
idle_ticks
*=
100
;
down_skip
[
cpu
]
=
0
;
down_skip
[
cpu
]
=
0
;
this_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
freq_down_sampling_rate
=
dbs_tuners_ins
.
sampling_rate
*
freq_down_sampling_rate
=
dbs_tuners_ins
.
sampling_rate
*
dbs_tuners_ins
.
sampling_down_factor
;
dbs_tuners_ins
.
sampling_down_factor
;
...
@@ -285,14 +331,14 @@ static void dbs_check_cpu(int cpu)
...
@@ -285,14 +331,14 @@ static void dbs_check_cpu(int cpu)
sampling_rate_in_HZ
(
freq_down_sampling_rate
);
sampling_rate_in_HZ
(
freq_down_sampling_rate
);
if
(
idle_ticks
>
down_idle_ticks
)
{
if
(
idle_ticks
>
down_idle_ticks
)
{
freq_down_step
=
(
5
*
this_dbs_info
->
cur_
policy
->
max
)
/
100
;
freq_down_step
=
(
5
*
policy
->
max
)
/
100
;
/* max freq cannot be less than 100. But who knows.... */
/* max freq cannot be less than 100. But who knows.... */
if
(
unlikely
(
freq_down_step
==
0
))
if
(
unlikely
(
freq_down_step
==
0
))
freq_down_step
=
5
;
freq_down_step
=
5
;
__cpufreq_driver_target
(
this_dbs_info
->
cur_
policy
,
__cpufreq_driver_target
(
policy
,
this_dbs_info
->
cur_
policy
->
cur
-
freq_down_step
,
policy
->
cur
-
freq_down_step
,
CPUFREQ_RELATION_H
);
CPUFREQ_RELATION_H
);
return
;
return
;
}
}
...
@@ -313,7 +359,8 @@ static void do_dbs_timer(void *data)
...
@@ -313,7 +359,8 @@ static void do_dbs_timer(void *data)
static
inline
void
dbs_timer_init
(
void
)
static
inline
void
dbs_timer_init
(
void
)
{
{
INIT_WORK
(
&
dbs_work
,
do_dbs_timer
,
NULL
);
INIT_WORK
(
&
dbs_work
,
do_dbs_timer
,
NULL
);
schedule_work
(
&
dbs_work
);
schedule_delayed_work
(
&
dbs_work
,
sampling_rate_in_HZ
(
dbs_tuners_ins
.
sampling_rate
));
return
;
return
;
}
}
...
@@ -328,6 +375,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
...
@@ -328,6 +375,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
{
{
unsigned
int
cpu
=
policy
->
cpu
;
unsigned
int
cpu
=
policy
->
cpu
;
struct
cpu_dbs_info_s
*
this_dbs_info
;
struct
cpu_dbs_info_s
*
this_dbs_info
;
unsigned
int
j
;
this_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
cpu
);
this_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
cpu
);
...
@@ -344,14 +392,18 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
...
@@ -344,14 +392,18 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
break
;
break
;
down
(
&
dbs_sem
);
down
(
&
dbs_sem
);
this_dbs_info
->
cur_policy
=
policy
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
struct
cpu_dbs_info_s
*
j_dbs_info
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
j_dbs_info
->
cur_policy
=
policy
;
this_dbs_info
->
prev_cpu_idle_up
=
j_dbs_info
->
prev_cpu_idle_up
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
kstat_cpu
(
j
).
cpustat
.
iowait
;
this_dbs_info
->
prev_cpu_idle_down
=
j_dbs_info
->
prev_cpu_idle_down
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
kstat_cpu
(
j
).
cpustat
.
iowait
;
}
this_dbs_info
->
enable
=
1
;
this_dbs_info
->
enable
=
1
;
sysfs_create_group
(
&
policy
->
kobj
,
&
dbs_attr_group
);
sysfs_create_group
(
&
policy
->
kobj
,
&
dbs_attr_group
);
dbs_enable
++
;
dbs_enable
++
;
...
...
drivers/cpufreq/cpufreq_stats.c
0 → 100644
View file @
ba420e28
/*
* drivers/cpufreq/cpufreq_stats.c
*
* Copyright (C) 2003-2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
* (C) 2004 Zou Nan hai <nanhai.zou@intel.com>.
*
* 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 <linux/config.h>
#include <linux/kernel.h>
#include <linux/sysdev.h>
#include <linux/cpu.h>
#include <linux/sysfs.h>
#include <linux/cpufreq.h>
#include <linux/jiffies.h>
#include <linux/percpu.h>
#include <linux/kobject.h>
#include <linux/spinlock.h>
static
spinlock_t
cpufreq_stats_lock
;
#define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
static struct freq_attr _attr_##_name = {\
.attr = {.name = __stringify(_name), .owner = THIS_MODULE, \
.mode = _mode, }, \
.show = _show,\
};
static
unsigned
long
delta_time
(
unsigned
long
old
,
unsigned
long
new
)
{
return
(
old
>
new
)
?
(
old
-
new
)
:
(
new
+
~
old
+
1
);
}
struct
cpufreq_stats
{
unsigned
int
cpu
;
unsigned
int
total_trans
;
unsigned
long
long
last_time
;
unsigned
int
max_state
;
unsigned
int
state_num
;
unsigned
int
last_index
;
unsigned
long
long
*
time_in_state
;
unsigned
int
*
freq_table
;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
unsigned
int
*
trans_table
;
#endif
};
static
struct
cpufreq_stats
*
cpufreq_stats_table
[
NR_CPUS
];
struct
cpufreq_stats_attribute
{
struct
attribute
attr
;
ssize_t
(
*
show
)
(
struct
cpufreq_stats
*
,
char
*
);
};
static
int
cpufreq_stats_update
(
unsigned
int
cpu
)
{
struct
cpufreq_stats
*
stat
;
spin_lock
(
&
cpufreq_stats_lock
);
stat
=
cpufreq_stats_table
[
cpu
];
if
(
stat
->
time_in_state
)
stat
->
time_in_state
[
stat
->
last_index
]
+=
delta_time
(
stat
->
last_time
,
jiffies
);
stat
->
last_time
=
jiffies
;
spin_unlock
(
&
cpufreq_stats_lock
);
return
0
;
}
static
ssize_t
show_total_trans
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
struct
cpufreq_stats
*
stat
=
cpufreq_stats_table
[
policy
->
cpu
];
if
(
!
stat
)
return
0
;
return
sprintf
(
buf
,
"%d
\n
"
,
cpufreq_stats_table
[
stat
->
cpu
]
->
total_trans
);
}
static
ssize_t
show_time_in_state
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
ssize_t
len
=
0
;
int
i
;
struct
cpufreq_stats
*
stat
=
cpufreq_stats_table
[
policy
->
cpu
];
if
(
!
stat
)
return
0
;
cpufreq_stats_update
(
stat
->
cpu
);
for
(
i
=
0
;
i
<
stat
->
state_num
;
i
++
)
{
len
+=
sprintf
(
buf
+
len
,
"%u %llu
\n
"
,
stat
->
freq_table
[
i
],
stat
->
time_in_state
[
i
]);
}
return
len
;
}
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
static
ssize_t
show_trans_table
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
ssize_t
len
=
0
;
int
i
,
j
;
struct
cpufreq_stats
*
stat
=
cpufreq_stats_table
[
policy
->
cpu
];
if
(
!
stat
)
return
0
;
cpufreq_stats_update
(
stat
->
cpu
);
for
(
i
=
0
;
i
<
stat
->
state_num
;
i
++
)
{
if
(
len
>=
PAGE_SIZE
)
break
;
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"%9u:
\t
"
,
stat
->
freq_table
[
i
]);
for
(
j
=
0
;
j
<
stat
->
state_num
;
j
++
)
{
if
(
len
>=
PAGE_SIZE
)
break
;
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"%u
\t
"
,
stat
->
trans_table
[
i
*
stat
->
max_state
+
j
]);
}
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"
\n
"
);
}
return
len
;
}
CPUFREQ_STATDEVICE_ATTR
(
trans_table
,
0444
,
show_trans_table
);
#endif
CPUFREQ_STATDEVICE_ATTR
(
total_trans
,
0444
,
show_total_trans
);
CPUFREQ_STATDEVICE_ATTR
(
time_in_state
,
0444
,
show_time_in_state
);
static
struct
attribute
*
default_attrs
[]
=
{
&
_attr_total_trans
.
attr
,
&
_attr_time_in_state
.
attr
,
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
&
_attr_trans_table
.
attr
,
#endif
NULL
};
static
struct
attribute_group
stats_attr_group
=
{
.
attrs
=
default_attrs
,
.
name
=
"stats"
};
static
int
freq_table_get_index
(
struct
cpufreq_stats
*
stat
,
unsigned
int
freq
)
{
int
index
;
for
(
index
=
0
;
index
<
stat
->
max_state
;
index
++
)
if
(
stat
->
freq_table
[
index
]
==
freq
)
return
index
;
return
-
1
;
}
static
void
cpufreq_stats_free_table
(
unsigned
int
cpu
)
{
struct
cpufreq_stats
*
stat
=
cpufreq_stats_table
[
cpu
];
struct
cpufreq_policy
*
policy
=
cpufreq_cpu_get
(
cpu
);
if
(
policy
&&
policy
->
cpu
==
cpu
)
sysfs_remove_group
(
&
policy
->
kobj
,
&
stats_attr_group
);
if
(
stat
)
{
kfree
(
stat
->
time_in_state
);
kfree
(
stat
);
}
cpufreq_stats_table
[
cpu
]
=
NULL
;
if
(
policy
)
cpufreq_cpu_put
(
policy
);
}
static
int
cpufreq_stats_create_table
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_frequency_table
*
table
)
{
unsigned
int
i
,
j
,
count
=
0
,
ret
=
0
;
struct
cpufreq_stats
*
stat
;
struct
cpufreq_policy
*
data
;
unsigned
int
alloc_size
;
unsigned
int
cpu
=
policy
->
cpu
;
if
(
cpufreq_stats_table
[
cpu
])
return
-
EBUSY
;
if
((
stat
=
kmalloc
(
sizeof
(
struct
cpufreq_stats
),
GFP_KERNEL
))
==
NULL
)
return
-
ENOMEM
;
memset
(
stat
,
0
,
sizeof
(
struct
cpufreq_stats
));
data
=
cpufreq_cpu_get
(
cpu
);
if
((
ret
=
sysfs_create_group
(
&
data
->
kobj
,
&
stats_attr_group
)))
goto
error_out
;
stat
->
cpu
=
cpu
;
cpufreq_stats_table
[
cpu
]
=
stat
;
for
(
i
=
0
;
table
[
i
].
frequency
!=
CPUFREQ_TABLE_END
;
i
++
)
{
unsigned
int
freq
=
table
[
i
].
frequency
;
if
(
freq
==
CPUFREQ_ENTRY_INVALID
)
continue
;
count
++
;
}
alloc_size
=
count
*
sizeof
(
int
)
+
count
*
sizeof
(
long
long
);
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
alloc_size
+=
count
*
count
*
sizeof
(
int
);
#endif
stat
->
max_state
=
count
;
stat
->
time_in_state
=
kmalloc
(
alloc_size
,
GFP_KERNEL
);
if
(
!
stat
->
time_in_state
)
{
ret
=
-
ENOMEM
;
goto
error_out
;
}
memset
(
stat
->
time_in_state
,
0
,
alloc_size
);
stat
->
freq_table
=
(
unsigned
int
*
)(
stat
->
time_in_state
+
count
);
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
stat
->
trans_table
=
stat
->
freq_table
+
count
;
#endif
j
=
0
;
for
(
i
=
0
;
table
[
i
].
frequency
!=
CPUFREQ_TABLE_END
;
i
++
)
{
unsigned
int
freq
=
table
[
i
].
frequency
;
if
(
freq
==
CPUFREQ_ENTRY_INVALID
)
continue
;
if
(
freq_table_get_index
(
stat
,
freq
)
==
-
1
)
stat
->
freq_table
[
j
++
]
=
freq
;
}
stat
->
state_num
=
j
;
spin_lock
(
&
cpufreq_stats_lock
);
stat
->
last_time
=
jiffies
;
stat
->
last_index
=
freq_table_get_index
(
stat
,
policy
->
cur
);
spin_unlock
(
&
cpufreq_stats_lock
);
cpufreq_cpu_put
(
data
);
return
0
;
error_out:
cpufreq_cpu_put
(
data
);
kfree
(
stat
);
cpufreq_stats_table
[
cpu
]
=
NULL
;
return
ret
;
}
static
int
cpufreq_stat_notifier_policy
(
struct
notifier_block
*
nb
,
unsigned
long
val
,
void
*
data
)
{
int
ret
;
struct
cpufreq_policy
*
policy
=
data
;
struct
cpufreq_frequency_table
*
table
;
unsigned
int
cpu
=
policy
->
cpu
;
if
(
val
!=
CPUFREQ_NOTIFY
)
return
0
;
table
=
cpufreq_frequency_get_table
(
cpu
);
if
(
!
table
)
return
0
;
if
((
ret
=
cpufreq_stats_create_table
(
policy
,
table
)))
return
ret
;
return
0
;
}
static
int
cpufreq_stat_notifier_trans
(
struct
notifier_block
*
nb
,
unsigned
long
val
,
void
*
data
)
{
struct
cpufreq_freqs
*
freq
=
data
;
struct
cpufreq_stats
*
stat
;
int
old_index
,
new_index
;
if
(
val
!=
CPUFREQ_POSTCHANGE
)
return
0
;
stat
=
cpufreq_stats_table
[
freq
->
cpu
];
if
(
!
stat
)
return
0
;
old_index
=
freq_table_get_index
(
stat
,
freq
->
old
);
new_index
=
freq_table_get_index
(
stat
,
freq
->
new
);
cpufreq_stats_update
(
freq
->
cpu
);
if
(
old_index
==
new_index
)
return
0
;
spin_lock
(
&
cpufreq_stats_lock
);
stat
->
last_index
=
new_index
;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
stat
->
trans_table
[
old_index
*
stat
->
max_state
+
new_index
]
++
;
#endif
stat
->
total_trans
++
;
spin_unlock
(
&
cpufreq_stats_lock
);
return
0
;
}
static
struct
notifier_block
notifier_policy_block
=
{
.
notifier_call
=
cpufreq_stat_notifier_policy
};
static
struct
notifier_block
notifier_trans_block
=
{
.
notifier_call
=
cpufreq_stat_notifier_trans
};
static
int
__init
cpufreq_stats_init
(
void
)
{
int
ret
;
unsigned
int
cpu
;
spin_lock_init
(
&
cpufreq_stats_lock
);
if
((
ret
=
cpufreq_register_notifier
(
&
notifier_policy_block
,
CPUFREQ_POLICY_NOTIFIER
)))
return
ret
;
if
((
ret
=
cpufreq_register_notifier
(
&
notifier_trans_block
,
CPUFREQ_TRANSITION_NOTIFIER
)))
{
cpufreq_unregister_notifier
(
&
notifier_policy_block
,
CPUFREQ_POLICY_NOTIFIER
);
return
ret
;
}
for_each_cpu
(
cpu
)
cpufreq_update_policy
(
cpu
);
return
0
;
}
static
void
__exit
cpufreq_stats_exit
(
void
)
{
unsigned
int
cpu
;
cpufreq_unregister_notifier
(
&
notifier_policy_block
,
CPUFREQ_POLICY_NOTIFIER
);
cpufreq_unregister_notifier
(
&
notifier_trans_block
,
CPUFREQ_TRANSITION_NOTIFIER
);
for_each_cpu
(
cpu
)
cpufreq_stats_free_table
(
cpu
);
}
MODULE_AUTHOR
(
"Zou Nan hai <nanhai.zou@intel.com>"
);
MODULE_DESCRIPTION
(
"'cpufreq_stats' - A driver to export cpufreq stats through sysfs filesystem"
);
MODULE_LICENSE
(
"GPL"
);
module_init
(
cpufreq_stats_init
);
module_exit
(
cpufreq_stats_exit
);
drivers/cpufreq/cpufreq_userspace.c
View file @
ba420e28
...
@@ -17,51 +17,13 @@
...
@@ -17,51 +17,13 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/ctype.h>
#include <linux/cpufreq.h>
#include <linux/cpufreq.h>
#include <linux/sysctl.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <linux/sysfs.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \
.ctl_name = CPU_NR_FREQ_MAX, \
.data = &cpu_max_freq[cpunr], \
.procname = "speed-max", \
.maxlen = sizeof(cpu_max_freq[cpunr]),\
.mode = 0444, \
.proc_handler = proc_dointvec, }
#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \
.ctl_name = CPU_NR_FREQ_MIN, \
.data = &cpu_min_freq[cpunr], \
.procname = "speed-min", \
.maxlen = sizeof(cpu_min_freq[cpunr]),\
.mode = 0444, \
.proc_handler = proc_dointvec, }
#define CTL_CPU_VARS_SPEED(cpunr) { \
.ctl_name = CPU_NR_FREQ, \
.procname = "speed", \
.mode = 0644, \
.proc_handler = cpufreq_procctl, \
.strategy = cpufreq_sysctl, \
.extra1 = (void*) (cpunr), }
#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\
CTL_CPU_VARS_SPEED_MAX(cpunr), \
CTL_CPU_VARS_SPEED_MIN(cpunr), \
CTL_CPU_VARS_SPEED(cpunr), \
{ .ctl_name = 0, }, }
/* the ctl_table entry for each CPU */
#define CPU_ENUM(s) { \
.ctl_name = (CPU_NR + s), \
.procname = #s, \
.mode = 0555, \
.child = ctl_cpu_vars_##s }
/**
/**
* A few values needed by the userspace governor
* A few values needed by the userspace governor
...
@@ -96,17 +58,17 @@ static struct notifier_block userspace_cpufreq_notifier_block = {
...
@@ -96,17 +58,17 @@ static struct notifier_block userspace_cpufreq_notifier_block = {
/**
/**
*
_
cpufreq_set - set the CPU frequency
* cpufreq_set - set the CPU frequency
* @freq: target frequency in kHz
* @freq: target frequency in kHz
* @cpu: CPU for which the frequency is to be set
* @cpu: CPU for which the frequency is to be set
*
*
* Sets the CPU frequency to freq.
* Sets the CPU frequency to freq.
*/
*/
static
int
_
cpufreq_set
(
unsigned
int
freq
,
unsigned
int
cpu
)
static
int
cpufreq_set
(
unsigned
int
freq
,
unsigned
int
cpu
)
{
{
int
ret
=
-
EINVAL
;
int
ret
=
-
EINVAL
;
dprintk
(
"
_
cpufreq_set for cpu %u, freq %u kHz
\n
"
,
cpu
,
freq
);
dprintk
(
"cpufreq_set for cpu %u, freq %u kHz
\n
"
,
cpu
,
freq
);
down
(
&
userspace_sem
);
down
(
&
userspace_sem
);
if
(
!
cpu_is_managed
[
cpu
])
if
(
!
cpu_is_managed
[
cpu
])
...
@@ -135,358 +97,6 @@ static int _cpufreq_set(unsigned int freq, unsigned int cpu)
...
@@ -135,358 +97,6 @@ static int _cpufreq_set(unsigned int freq, unsigned int cpu)
}
}
#ifdef CONFIG_CPU_FREQ_24_API
#warning The /proc/sys/cpu/ and sysctl interface to cpufreq will be removed from the 2.6. kernel series soon after 2005-01-01
static
unsigned
int
warning_print
=
0
;
int
__deprecated
cpufreq_set
(
unsigned
int
freq
,
unsigned
int
cpu
)
{
return
_cpufreq_set
(
freq
,
cpu
);
}
EXPORT_SYMBOL_GPL
(
cpufreq_set
);
/**
* cpufreq_setmax - set the CPU to the maximum frequency
* @cpu - affected cpu;
*
* Sets the CPU frequency to the maximum frequency supported by
* this CPU.
*/
int
__deprecated
cpufreq_setmax
(
unsigned
int
cpu
)
{
if
(
!
cpu_is_managed
[
cpu
]
||
!
cpu_online
(
cpu
))
return
-
EINVAL
;
return
_cpufreq_set
(
cpu_max_freq
[
cpu
],
cpu
);
}
EXPORT_SYMBOL_GPL
(
cpufreq_setmax
);
/*********************** cpufreq_sysctl interface ********************/
static
int
cpufreq_procctl
(
ctl_table
*
ctl
,
int
write
,
struct
file
*
filp
,
void
__user
*
buffer
,
size_t
*
lenp
,
loff_t
*
ppos
)
{
char
buf
[
16
],
*
p
;
int
cpu
=
(
long
)
ctl
->
extra1
;
unsigned
int
len
,
left
=
*
lenp
;
if
(
!
left
||
(
*
ppos
&&
!
write
)
||
!
cpu_online
(
cpu
))
{
*
lenp
=
0
;
return
0
;
}
if
(
!
warning_print
)
{
warning_print
++
;
printk
(
KERN_INFO
"Access to /proc/sys/cpu/ is deprecated and "
"will be removed from (new) 2.6. kernels soon "
"after 2005-01-01
\n
"
);
}
if
(
write
)
{
unsigned
int
freq
;
len
=
left
;
if
(
left
>
sizeof
(
buf
))
left
=
sizeof
(
buf
);
if
(
copy_from_user
(
buf
,
buffer
,
left
))
return
-
EFAULT
;
buf
[
sizeof
(
buf
)
-
1
]
=
'\0'
;
freq
=
simple_strtoul
(
buf
,
&
p
,
0
);
_cpufreq_set
(
freq
,
cpu
);
}
else
{
len
=
sprintf
(
buf
,
"%d
\n
"
,
cpufreq_get
(
cpu
));
if
(
len
>
left
)
len
=
left
;
if
(
copy_to_user
(
buffer
,
buf
,
len
))
return
-
EFAULT
;
}
*
lenp
=
len
;
*
ppos
+=
len
;
return
0
;
}
static
int
cpufreq_sysctl
(
ctl_table
*
table
,
int
__user
*
name
,
int
nlen
,
void
__user
*
oldval
,
size_t
__user
*
oldlenp
,
void
__user
*
newval
,
size_t
newlen
,
void
**
context
)
{
int
cpu
=
(
long
)
table
->
extra1
;
if
(
!
cpu_online
(
cpu
))
return
-
EINVAL
;
if
(
!
warning_print
)
{
warning_print
++
;
printk
(
KERN_INFO
"Access to /proc/sys/cpu/ is deprecated and "
"will be removed from (new) 2.6. kernels soon "
"after 2005-01-01
\n
"
);
}
if
(
oldval
&&
oldlenp
)
{
size_t
oldlen
;
if
(
get_user
(
oldlen
,
oldlenp
))
return
-
EFAULT
;
if
(
oldlen
!=
sizeof
(
unsigned
int
))
return
-
EINVAL
;
if
(
put_user
(
cpufreq_get
(
cpu
),
(
unsigned
int
__user
*
)
oldval
)
||
put_user
(
sizeof
(
unsigned
int
),
oldlenp
))
return
-
EFAULT
;
}
if
(
newval
&&
newlen
)
{
unsigned
int
freq
;
if
(
newlen
!=
sizeof
(
unsigned
int
))
return
-
EINVAL
;
if
(
get_user
(
freq
,
(
unsigned
int
__user
*
)
newval
))
return
-
EFAULT
;
_cpufreq_set
(
freq
,
cpu
);
}
return
1
;
}
/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */
/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
CTL_TABLE_CPU_VARS
(
0
);
#if NR_CPUS > 1
CTL_TABLE_CPU_VARS
(
1
);
#endif
#if NR_CPUS > 2
CTL_TABLE_CPU_VARS
(
2
);
#endif
#if NR_CPUS > 3
CTL_TABLE_CPU_VARS
(
3
);
#endif
#if NR_CPUS > 4
CTL_TABLE_CPU_VARS
(
4
);
#endif
#if NR_CPUS > 5
CTL_TABLE_CPU_VARS
(
5
);
#endif
#if NR_CPUS > 6
CTL_TABLE_CPU_VARS
(
6
);
#endif
#if NR_CPUS > 7
CTL_TABLE_CPU_VARS
(
7
);
#endif
#if NR_CPUS > 8
CTL_TABLE_CPU_VARS
(
8
);
#endif
#if NR_CPUS > 9
CTL_TABLE_CPU_VARS
(
9
);
#endif
#if NR_CPUS > 10
CTL_TABLE_CPU_VARS
(
10
);
#endif
#if NR_CPUS > 11
CTL_TABLE_CPU_VARS
(
11
);
#endif
#if NR_CPUS > 12
CTL_TABLE_CPU_VARS
(
12
);
#endif
#if NR_CPUS > 13
CTL_TABLE_CPU_VARS
(
13
);
#endif
#if NR_CPUS > 14
CTL_TABLE_CPU_VARS
(
14
);
#endif
#if NR_CPUS > 15
CTL_TABLE_CPU_VARS
(
15
);
#endif
#if NR_CPUS > 16
CTL_TABLE_CPU_VARS
(
16
);
#endif
#if NR_CPUS > 17
CTL_TABLE_CPU_VARS
(
17
);
#endif
#if NR_CPUS > 18
CTL_TABLE_CPU_VARS
(
18
);
#endif
#if NR_CPUS > 19
CTL_TABLE_CPU_VARS
(
19
);
#endif
#if NR_CPUS > 20
CTL_TABLE_CPU_VARS
(
20
);
#endif
#if NR_CPUS > 21
CTL_TABLE_CPU_VARS
(
21
);
#endif
#if NR_CPUS > 22
CTL_TABLE_CPU_VARS
(
22
);
#endif
#if NR_CPUS > 23
CTL_TABLE_CPU_VARS
(
23
);
#endif
#if NR_CPUS > 24
CTL_TABLE_CPU_VARS
(
24
);
#endif
#if NR_CPUS > 25
CTL_TABLE_CPU_VARS
(
25
);
#endif
#if NR_CPUS > 26
CTL_TABLE_CPU_VARS
(
26
);
#endif
#if NR_CPUS > 27
CTL_TABLE_CPU_VARS
(
27
);
#endif
#if NR_CPUS > 28
CTL_TABLE_CPU_VARS
(
28
);
#endif
#if NR_CPUS > 29
CTL_TABLE_CPU_VARS
(
29
);
#endif
#if NR_CPUS > 30
CTL_TABLE_CPU_VARS
(
30
);
#endif
#if NR_CPUS > 31
CTL_TABLE_CPU_VARS
(
31
);
#endif
#if NR_CPUS > 32
#error please extend CPU enumeration
#endif
/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
static
ctl_table
ctl_cpu_table
[
NR_CPUS
+
1
]
=
{
CPU_ENUM
(
0
),
#if NR_CPUS > 1
CPU_ENUM
(
1
),
#endif
#if NR_CPUS > 2
CPU_ENUM
(
2
),
#endif
#if NR_CPUS > 3
CPU_ENUM
(
3
),
#endif
#if NR_CPUS > 4
CPU_ENUM
(
4
),
#endif
#if NR_CPUS > 5
CPU_ENUM
(
5
),
#endif
#if NR_CPUS > 6
CPU_ENUM
(
6
),
#endif
#if NR_CPUS > 7
CPU_ENUM
(
7
),
#endif
#if NR_CPUS > 8
CPU_ENUM
(
8
),
#endif
#if NR_CPUS > 9
CPU_ENUM
(
9
),
#endif
#if NR_CPUS > 10
CPU_ENUM
(
10
),
#endif
#if NR_CPUS > 11
CPU_ENUM
(
11
),
#endif
#if NR_CPUS > 12
CPU_ENUM
(
12
),
#endif
#if NR_CPUS > 13
CPU_ENUM
(
13
),
#endif
#if NR_CPUS > 14
CPU_ENUM
(
14
),
#endif
#if NR_CPUS > 15
CPU_ENUM
(
15
),
#endif
#if NR_CPUS > 16
CPU_ENUM
(
16
),
#endif
#if NR_CPUS > 17
CPU_ENUM
(
17
),
#endif
#if NR_CPUS > 18
CPU_ENUM
(
18
),
#endif
#if NR_CPUS > 19
CPU_ENUM
(
19
),
#endif
#if NR_CPUS > 20
CPU_ENUM
(
20
),
#endif
#if NR_CPUS > 21
CPU_ENUM
(
21
),
#endif
#if NR_CPUS > 22
CPU_ENUM
(
22
),
#endif
#if NR_CPUS > 23
CPU_ENUM
(
23
),
#endif
#if NR_CPUS > 24
CPU_ENUM
(
24
),
#endif
#if NR_CPUS > 25
CPU_ENUM
(
25
),
#endif
#if NR_CPUS > 26
CPU_ENUM
(
26
),
#endif
#if NR_CPUS > 27
CPU_ENUM
(
27
),
#endif
#if NR_CPUS > 28
CPU_ENUM
(
28
),
#endif
#if NR_CPUS > 29
CPU_ENUM
(
29
),
#endif
#if NR_CPUS > 30
CPU_ENUM
(
30
),
#endif
#if NR_CPUS > 31
CPU_ENUM
(
31
),
#endif
#if NR_CPUS > 32
#error please extend CPU enumeration
#endif
{
.
ctl_name
=
0
,
}
};
static
ctl_table
ctl_cpu
[
2
]
=
{
{
.
ctl_name
=
CTL_CPU
,
.
procname
=
"cpu"
,
.
mode
=
0555
,
.
child
=
ctl_cpu_table
,
},
{
.
ctl_name
=
0
,
}
};
static
struct
ctl_table_header
*
cpufreq_sysctl_table
;
static
inline
void
cpufreq_sysctl_init
(
void
)
{
cpufreq_sysctl_table
=
register_sysctl_table
(
ctl_cpu
,
0
);
}
static
inline
void
cpufreq_sysctl_exit
(
void
)
{
unregister_sysctl_table
(
cpufreq_sysctl_table
);
}
#else
#define cpufreq_sysctl_init() do {} while(0)
#define cpufreq_sysctl_exit() do {} while(0)
#endif
/* CONFIG_CPU_FREQ_24API */
/************************** sysfs interface ************************/
/************************** sysfs interface ************************/
static
ssize_t
show_speed
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
static
ssize_t
show_speed
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
{
...
@@ -503,7 +113,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
...
@@ -503,7 +113,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
if
(
ret
!=
1
)
if
(
ret
!=
1
)
return
-
EINVAL
;
return
-
EINVAL
;
_
cpufreq_set
(
freq
,
policy
->
cpu
);
cpufreq_set
(
freq
,
policy
->
cpu
);
return
count
;
return
count
;
}
}
...
@@ -577,7 +187,6 @@ EXPORT_SYMBOL(cpufreq_gov_userspace);
...
@@ -577,7 +187,6 @@ EXPORT_SYMBOL(cpufreq_gov_userspace);
static
int
__init
cpufreq_gov_userspace_init
(
void
)
static
int
__init
cpufreq_gov_userspace_init
(
void
)
{
{
cpufreq_sysctl_init
();
cpufreq_register_notifier
(
&
userspace_cpufreq_notifier_block
,
CPUFREQ_TRANSITION_NOTIFIER
);
cpufreq_register_notifier
(
&
userspace_cpufreq_notifier_block
,
CPUFREQ_TRANSITION_NOTIFIER
);
return
cpufreq_register_governor
(
&
cpufreq_gov_userspace
);
return
cpufreq_register_governor
(
&
cpufreq_gov_userspace
);
}
}
...
@@ -587,7 +196,6 @@ static void __exit cpufreq_gov_userspace_exit(void)
...
@@ -587,7 +196,6 @@ static void __exit cpufreq_gov_userspace_exit(void)
{
{
cpufreq_unregister_governor
(
&
cpufreq_gov_userspace
);
cpufreq_unregister_governor
(
&
cpufreq_gov_userspace
);
cpufreq_unregister_notifier
(
&
userspace_cpufreq_notifier_block
,
CPUFREQ_TRANSITION_NOTIFIER
);
cpufreq_unregister_notifier
(
&
userspace_cpufreq_notifier_block
,
CPUFREQ_TRANSITION_NOTIFIER
);
cpufreq_sysctl_exit
();
}
}
...
...
drivers/cpufreq/freq_table.c
View file @
ba420e28
...
@@ -214,6 +214,11 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu)
...
@@ -214,6 +214,11 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu)
}
}
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_put_attr
);
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_put_attr
);
struct
cpufreq_frequency_table
*
cpufreq_frequency_get_table
(
unsigned
int
cpu
)
{
return
show_table
[
cpu
];
}
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_get_table
);
MODULE_AUTHOR
(
"Dominik Brodowski <linux@brodo.de>"
);
MODULE_AUTHOR
(
"Dominik Brodowski <linux@brodo.de>"
);
MODULE_DESCRIPTION
(
"CPUfreq frequency table helpers"
);
MODULE_DESCRIPTION
(
"CPUfreq frequency table helpers"
);
...
...
drivers/cpufreq/proc_intf.c
View file @
ba420e28
/*
* linux/drivers/cpufreq/proc_intf.c
*
* Copyright (C) 2002 - 2003 Dominik Brodowski
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/ctype.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#warning This module will be removed from the 2.6. kernel series soon after 2005-01-01
#define CPUFREQ_ALL_CPUS ((NR_CPUS))
static
unsigned
int
warning_print
=
0
;
/**
* 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
str_governor
[
16
];
struct
cpufreq_policy
current_policy
;
unsigned
int
result
=
-
EFAULT
;
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:%15s"
,
&
cpu
,
&
min
,
&
max
,
str_governor
)
==
4
)
{
policy
->
min
=
min
;
policy
->
max
=
max
;
policy
->
cpu
=
cpu
;
result
=
0
;
goto
scan_policy
;
}
if
(
sscanf
(
input_string
,
"%d%%%d%%%d%%%15s"
,
&
cpu
,
&
min
,
&
max
,
str_governor
)
==
4
)
{
if
(
!
cpufreq_get_policy
(
&
current_policy
,
cpu
))
{
policy
->
min
=
(
min
*
current_policy
.
cpuinfo
.
max_freq
)
/
100
;
policy
->
max
=
(
max
*
current_policy
.
cpuinfo
.
max_freq
)
/
100
;
policy
->
cpu
=
cpu
;
result
=
0
;
goto
scan_policy
;
}
}
if
(
sscanf
(
input_string
,
"%d:%d:%15s"
,
&
min
,
&
max
,
str_governor
)
==
3
)
{
policy
->
min
=
min
;
policy
->
max
=
max
;
result
=
0
;
goto
scan_policy
;
}
if
(
sscanf
(
input_string
,
"%d%%%d%%%15s"
,
&
min
,
&
max
,
str_governor
)
==
3
)
{
if
(
!
cpufreq_get_policy
(
&
current_policy
,
cpu
))
{
policy
->
min
=
(
min
*
current_policy
.
cpuinfo
.
max_freq
)
/
100
;
policy
->
max
=
(
max
*
current_policy
.
cpuinfo
.
max_freq
)
/
100
;
result
=
0
;
goto
scan_policy
;
}
}
return
-
EINVAL
;
scan_policy:
result
=
cpufreq_parse_governor
(
str_governor
,
&
policy
->
policy
,
&
policy
->
governor
);
return
result
;
}
/**
* 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
;
if
(
!
warning_print
)
{
warning_print
++
;
printk
(
KERN_INFO
"Access to /proc/cpufreq is deprecated and "
"will be removed from (new) 2.6. kernels soon "
"after 2005-01-01
\n
"
);
}
p
+=
sprintf
(
p
,
" minimum CPU frequency - maximum CPU frequency - policy
\n
"
);
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
if
(
!
cpu_online
(
i
))
continue
;
if
(
cpufreq_get_policy
(
&
policy
,
i
))
continue
;
if
(
!
policy
.
cpuinfo
.
max_freq
)
continue
;
min_pctg
=
(
policy
.
min
*
100
)
/
policy
.
cpuinfo
.
max_freq
;
max_pctg
=
(
policy
.
max
*
100
)
/
policy
.
cpuinfo
.
max_freq
;
p
+=
sprintf
(
p
,
"CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - "
,
i
,
policy
.
min
,
min_pctg
,
policy
.
max
,
max_pctg
);
if
(
policy
.
policy
)
{
switch
(
policy
.
policy
)
{
case
CPUFREQ_POLICY_POWERSAVE
:
p
+=
sprintf
(
p
,
"powersave
\n
"
);
break
;
case
CPUFREQ_POLICY_PERFORMANCE
:
p
+=
sprintf
(
p
,
"performance
\n
"
);
break
;
default:
p
+=
sprintf
(
p
,
"INVALID
\n
"
);
break
;
}
}
else
p
+=
scnprintf
(
p
,
CPUFREQ_NAME_LEN
,
"%s
\n
"
,
policy
.
governor
->
name
);
}
end:
len
=
(
p
-
page
);
if
(
len
<=
off
+
count
)
*
eof
=
1
;
*
start
=
page
+
off
;
len
-=
off
;
if
(
len
>
count
)
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
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
int
result
=
0
;
char
proc_string
[
42
]
=
{
'\0'
};
struct
cpufreq_policy
policy
;
unsigned
int
i
=
0
;
if
((
count
>
sizeof
(
proc_string
)
-
1
))
return
-
EINVAL
;
if
(
copy_from_user
(
proc_string
,
buffer
,
count
))
return
-
EFAULT
;
if
(
!
warning_print
)
{
warning_print
++
;
printk
(
KERN_INFO
"Access to /proc/cpufreq is deprecated and "
"will be removed from (new) 2.6. kernels soon "
"after 2005-01-01
\n
"
);
}
proc_string
[
count
]
=
'\0'
;
result
=
cpufreq_parse_policy
(
proc_string
,
&
policy
);
if
(
result
)
return
-
EFAULT
;
if
(
policy
.
cpu
==
CPUFREQ_ALL_CPUS
)
{
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
policy
.
cpu
=
i
;
if
(
cpu_online
(
i
))
cpufreq_set_policy
(
&
policy
);
}
}
else
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
int
__init
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
__exit
cpufreq_proc_exit
(
void
)
{
remove_proc_entry
(
"cpufreq"
,
&
proc_root
);
return
;
}
MODULE_AUTHOR
(
"Dominik Brodowski <linux@brodo.de>"
);
MODULE_DESCRIPTION
(
"CPUfreq /proc/cpufreq interface"
);
MODULE_LICENSE
(
"GPL"
);
module_init
(
cpufreq_proc_init
);
module_exit
(
cpufreq_proc_exit
);
include/linux/cpufreq.h
View file @
ba420e28
...
@@ -252,65 +252,6 @@ int cpufreq_update_policy(unsigned int cpu);
...
@@ -252,65 +252,6 @@ int cpufreq_update_policy(unsigned int cpu);
/* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
/* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
unsigned
int
cpufreq_get
(
unsigned
int
cpu
);
unsigned
int
cpufreq_get
(
unsigned
int
cpu
);
/* the proc_intf.c needs this */
int
cpufreq_parse_governor
(
char
*
str_governor
,
unsigned
int
*
policy
,
struct
cpufreq_governor
**
governor
);
/*********************************************************************
* CPUFREQ USERSPACE GOVERNOR *
*********************************************************************/
#ifdef CONFIG_CPU_FREQ_24_API
int
__deprecated
cpufreq_setmax
(
unsigned
int
cpu
);
int
__deprecated
cpufreq_set
(
unsigned
int
kHz
,
unsigned
int
cpu
);
/* /proc/sys/cpu */
enum
{
CPU_NR
=
1
,
/* compatibilty reasons */
CPU_NR_0
=
1
,
CPU_NR_1
=
2
,
CPU_NR_2
=
3
,
CPU_NR_3
=
4
,
CPU_NR_4
=
5
,
CPU_NR_5
=
6
,
CPU_NR_6
=
7
,
CPU_NR_7
=
8
,
CPU_NR_8
=
9
,
CPU_NR_9
=
10
,
CPU_NR_10
=
11
,
CPU_NR_11
=
12
,
CPU_NR_12
=
13
,
CPU_NR_13
=
14
,
CPU_NR_14
=
15
,
CPU_NR_15
=
16
,
CPU_NR_16
=
17
,
CPU_NR_17
=
18
,
CPU_NR_18
=
19
,
CPU_NR_19
=
20
,
CPU_NR_20
=
21
,
CPU_NR_21
=
22
,
CPU_NR_22
=
23
,
CPU_NR_23
=
24
,
CPU_NR_24
=
25
,
CPU_NR_25
=
26
,
CPU_NR_26
=
27
,
CPU_NR_27
=
28
,
CPU_NR_28
=
29
,
CPU_NR_29
=
30
,
CPU_NR_30
=
31
,
CPU_NR_31
=
32
,
};
/* /proc/sys/cpu/{0,1,...,(NR_CPUS-1)} */
enum
{
CPU_NR_FREQ_MAX
=
1
,
CPU_NR_FREQ_MIN
=
2
,
CPU_NR_FREQ
=
3
,
};
#endif
/* CONFIG_CPU_FREQ_24_API */
/*********************************************************************
/*********************************************************************
* CPUFREQ DEFAULT GOVERNOR *
* CPUFREQ DEFAULT GOVERNOR *
...
@@ -351,6 +292,11 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
...
@@ -351,6 +292,11 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned
int
relation
,
unsigned
int
relation
,
unsigned
int
*
index
);
unsigned
int
*
index
);
/* the following 3 funtions are for cpufreq core use only */
struct
cpufreq_frequency_table
*
cpufreq_frequency_get_table
(
unsigned
int
cpu
);
struct
cpufreq_policy
*
cpufreq_cpu_get
(
unsigned
int
cpu
);
void
cpufreq_cpu_put
(
struct
cpufreq_policy
*
data
);
/* the following are really really optional */
/* the following are really really optional */
extern
struct
freq_attr
cpufreq_freq_attr_scaling_available_freqs
;
extern
struct
freq_attr
cpufreq_freq_attr_scaling_available_freqs
;
...
...
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