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
------------
There is a CPU frequency changing CVS commit and general list where
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
http://
www
.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
send an email to cpufreq@
lists
.linux.org.uk, to subscribe go to
http://
lists
.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
mailing list are available to subscribers at
http://
www
.linux.org.uk/mailman/private/cpufreq/.
http://
lists
.linux.org.uk/mailman/private/cpufreq/.
Links
...
...
@@ -50,7 +50,7 @@ how to access the CVS repository:
* http://cvs.arm.linux.org.uk/
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:
* http://www.lart.tudelft.nl/projects/scaling
MAINTAINERS
View file @
ba420e28
...
...
@@ -575,7 +575,7 @@ S: Maintained
CPU FREQUENCY DRIVERS
P: Dave Jones
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/
S: Maintained
...
...
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
View file @
ba420e28
...
...
@@ -38,6 +38,8 @@
#include <linux/acpi.h>
#include <acpi/processor.h>
#include "speedstep-est-common.h"
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
MODULE_AUTHOR
(
"Paul Diefenbaugh, Dominik Brodowski"
);
...
...
@@ -48,10 +50,12 @@ MODULE_LICENSE("GPL");
struct
cpufreq_acpi_io
{
struct
acpi_processor_performance
acpi_data
;
struct
cpufreq_frequency_table
*
freq_table
;
unsigned
int
resume
;
};
static
struct
cpufreq_acpi_io
*
acpi_io_data
[
NR_CPUS
];
static
struct
cpufreq_driver
acpi_cpufreq_driver
;
static
int
acpi_processor_write_port
(
...
...
@@ -119,9 +123,14 @@ acpi_processor_set_performance (
}
if
(
state
==
data
->
acpi_data
.
state
)
{
dprintk
(
"Already at target state (P%d)
\n
"
,
state
);
retval
=
0
;
goto
migrate_end
;
if
(
unlikely
(
data
->
resume
))
{
dprintk
(
"Called after resume, resetting to P%d
\n
"
,
state
);
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
"
,
...
...
@@ -368,6 +377,10 @@ acpi_cpufreq_cpu_init (
if
(
result
)
goto
err_free
;
if
(
is_const_loops_cpu
(
cpu
))
{
acpi_cpufreq_driver
.
flags
|=
CPUFREQ_CONST_LOOPS
;
}
/* capability check */
if
(
data
->
acpi_data
.
state_count
<=
1
)
{
dprintk
(
"No P-States
\n
"
);
...
...
@@ -462,6 +475,20 @@ acpi_cpufreq_cpu_exit (
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
[]
=
{
&
cpufreq_freq_attr_scaling_available_freqs
,
...
...
@@ -473,6 +500,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.
target
=
acpi_cpufreq_target
,
.
init
=
acpi_cpufreq_cpu_init
,
.
exit
=
acpi_cpufreq_cpu_exit
,
.
resume
=
acpi_cpufreq_resume
,
.
name
=
"acpi-cpufreq"
,
.
owner
=
THIS_MODULE
,
.
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)");
MODULE_PARM_DESC
(
min_fsb
,
"Minimum FSB to use, if not defined: current FSB - 50"
);
/* DEBUG
* 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
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "cpufreq-nforce2", msg)
/*
* 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)
if
((
gx_params
->
pci_suscfg
&
SUSMOD
)
==
0
)
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
);
}
...
...
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)
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) */
printk
(
KERN_WARNING
PFX
"Warning: Pentium M detected. "
"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)
static
int
powernow_cpu_exit
(
struct
cpufreq_policy
*
policy
)
{
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
;
}
...
...
@@ -664,15 +675,7 @@ static int __init powernow_init (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
);
if
(
powernow_table
)
kfree
(
powernow_table
);
}
module_param
(
acpi_force
,
int
,
0444
);
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
View file @
ba420e28
...
...
@@ -18,6 +18,9 @@
* 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
* 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>
...
...
@@ -65,7 +68,12 @@ static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid)
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
)
{
if
(
fid
<
HI_FID_TABLE_BOTTOM
)
{
...
...
@@ -278,7 +286,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
return
1
;
}
while
(
rvosteps
>
0
)
{
while
(
(
rvosteps
>
0
)
&&
((
data
->
rvo
+
data
->
currvid
)
>
reqvid
)
)
{
if
(
data
->
currvid
==
0
)
{
rvosteps
=
0
;
}
else
{
...
...
@@ -307,10 +315,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
/* Phase 2 - core frequency transition */
static
int
core_frequency_transition
(
struct
powernow_k8_data
*
data
,
u32
reqfid
)
{
u32
vcoreqfid
;
u32
vcocurrfid
;
u32
vcofiddiff
;
u32
savevid
=
data
->
currvid
;
u32
vcoreqfid
,
vcocurrfid
,
vcofiddiff
,
savevid
=
data
->
currvid
;
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
"
,
...
...
@@ -498,7 +503,7 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8
||
(
pst
[
j
].
fid
&
1
)
||
(
j
&&
(
pst
[
j
].
fid
<
HI_FID_TABLE_BOTTOM
)))
{
/* 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
;
}
if
(
pst
[
j
].
fid
<
lastfid
)
...
...
@@ -618,7 +623,7 @@ static int find_psb_table(struct powernow_k8_data *data)
return
-
ENODEV
;
}
data
->
vstable
=
psb
->
v
oltagestabilizationtim
e
;
data
->
vstable
=
psb
->
v
stabl
e
;
dprintk
(
"voltage stabilization time: %d(*20us)
\n
"
,
data
->
vstable
);
dprintk
(
"flags2: 0x%x
\n
"
,
psb
->
flags2
);
...
...
@@ -632,8 +637,8 @@ static int find_psb_table(struct powernow_k8_data *data)
dprintk
(
"isochronous relief time: %d
\n
"
,
data
->
irt
);
dprintk
(
"maximum voltage step: %d - 0x%x
\n
"
,
mvs
,
data
->
vidmvs
);
dprintk
(
"numpst: 0x%x
\n
"
,
psb
->
num
pst
);
cpst
=
psb
->
num
pst
;
dprintk
(
"numpst: 0x%x
\n
"
,
psb
->
num
_tables
);
cpst
=
psb
->
num
_tables
;
if
((
psb
->
cpuid
==
0x00000fc0
)
||
(
psb
->
cpuid
==
0x00000fe0
)
){
thiscpuid
=
cpuid_eax
(
CPUID_PROCESSOR_SIGNATURE
);
if
((
thiscpuid
==
0x00000fc0
)
||
(
thiscpuid
==
0x00000fe0
)
)
{
...
...
@@ -651,7 +656,7 @@ static int find_psb_table(struct powernow_k8_data *data)
dprintk
(
"maxvid: 0x%x
\n
"
,
psb
->
maxvid
);
maxvid
=
psb
->
maxvid
;
data
->
numps
=
psb
->
numps
tates
;
data
->
numps
=
psb
->
numps
;
dprintk
(
"numpstates: 0x%x
\n
"
,
data
->
numps
);
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)
/* min/max the cpu is capable of */
if
(
cpufreq_frequency_table_cpuinfo
(
pol
,
data
->
powernow_table
))
{
printk
(
KERN_ERR
PFX
"invalid powernow_table
\n
"
);
powernow_k8_cpu_exit_acpi
(
data
);
kfree
(
data
->
powernow_table
);
kfree
(
data
);
return
-
EINVAL
;
...
...
@@ -1027,6 +1033,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
err_out:
set_cpus_allowed
(
current
,
oldmask
);
schedule
();
powernow_k8_cpu_exit_acpi
(
data
);
kfree
(
data
);
return
-
ENODEV
;
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
View file @
ba420e28
...
...
@@ -21,8 +21,7 @@ struct powernow_k8_data {
u32
plllock
;
/* pll lock time, units 1 us */
/* keep track of the current fid / vid */
u32
currvid
;
u32
currfid
;
u32
currvid
,
currfid
;
/* 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.
...
...
@@ -152,14 +151,14 @@ struct psb_s {
u8
signature
[
10
];
u8
tableversion
;
u8
flags1
;
u16
v
oltagestabilizationtim
e
;
u16
v
stabl
e
;
u8
flags2
;
u8
num
pst
;
u8
num
_tables
;
u32
cpuid
;
u8
plllocktime
;
u8
maxfid
;
u8
maxvid
;
u8
numps
tates
;
u8
numps
;
};
/* 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 @@
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/compiler.h>
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
#include <linux/acpi.h>
...
...
@@ -32,6 +34,8 @@
#include <asm/processor.h>
#include <asm/cpufeature.h>
#include "speedstep-est-common.h"
#define PFX "speedstep-centrino: "
#define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>"
...
...
@@ -71,8 +75,10 @@ struct cpu_model
static
int
centrino_verify_cpu_id
(
const
struct
cpuinfo_x86
*
c
,
const
struct
cpu_id
*
x
);
/* Operating points for current CPU */
static
struct
cpu_model
*
centrino_model
;
static
const
struct
cpu_id
*
centrino_cpu
;
static
struct
cpu_model
*
centrino_model
[
NR_CPUS
];
static
const
struct
cpu_id
*
centrino_cpu
[
NR_CPUS
];
static
struct
cpufreq_driver
centrino_driver
;
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
...
...
@@ -239,7 +245,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
if
(
model
->
cpu_id
==
NULL
)
{
/* 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
"
,
cpu
->
x86_model_id
);
return
-
ENOENT
;
...
...
@@ -247,15 +253,15 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
if
(
model
->
op_points
==
NULL
)
{
/* 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
);
#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
return
-
ENOENT
;
}
centrino_model
=
model
;
centrino_model
[
policy
->
cpu
]
=
model
;
dprintk
(
"found
\"
%s
\"
: max frequency: %dkHz
\n
"
,
model
->
model_name
,
model
->
max_freq
);
...
...
@@ -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 */
static
unsigned
extract_clock
(
unsigned
msr
)
static
unsigned
extract_clock
(
unsigned
msr
,
unsigned
int
cpu
,
int
failsafe
)
{
int
i
;
...
...
@@ -286,28 +292,32 @@ static unsigned extract_clock(unsigned msr)
* for centrino, as some DSDTs are buggy.
* Ideally, this can be done using the acpi_data structure.
*/
if
((
centrino_cpu
==
&
cpu_ids
[
CPU_BANIAS
])
||
(
centrino_cpu
==
&
cpu_ids
[
CPU_DOTHAN_A1
])
||
(
centrino_cpu
==
&
cpu_ids
[
CPU_DOTHAN_B0
]))
{
if
((
centrino_cpu
[
cpu
]
==
&
cpu_ids
[
CPU_BANIAS
])
||
(
centrino_cpu
[
cpu
]
==
&
cpu_ids
[
CPU_DOTHAN_A1
])
||
(
centrino_cpu
[
cpu
]
==
&
cpu_ids
[
CPU_DOTHAN_B0
]))
{
msr
=
(
msr
>>
8
)
&
0xff
;
return
msr
*
100000
;
}
if
((
!
centrino_model
)
||
(
!
centrino_model
->
op_points
))
if
((
!
centrino_model
[
cpu
])
||
(
!
centrino_model
[
cpu
]
->
op_points
))
return
0
;
msr
&=
0xffff
;
for
(
i
=
0
;
centrino_model
->
op_points
[
i
].
frequency
!=
CPUFREQ_TABLE_END
;
i
++
)
{
if
(
msr
==
centrino_model
->
op_points
[
i
].
index
)
return
centrino_model
->
op_points
[
i
].
frequency
;
for
(
i
=
0
;
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
!=
CPUFREQ_TABLE_END
;
i
++
)
{
if
(
msr
==
centrino_model
[
cpu
]
->
op_points
[
i
].
index
)
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 */
static
unsigned
int
get_cur_freq
(
unsigned
int
cpu
)
{
unsigned
l
,
h
;
unsigned
clock_freq
;
cpumask_t
saved_mask
;
saved_mask
=
current
->
cpus_allowed
;
...
...
@@ -316,8 +326,21 @@ static unsigned int get_cur_freq(unsigned int cpu)
return
0
;
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
);
return
extract_clock
(
l
)
;
return
clock_freq
;
}
...
...
@@ -339,6 +362,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
struct
acpi_object_list
arg_list
=
{
1
,
&
arg0
};
unsigned
long
cur_freq
;
int
result
=
0
,
i
;
unsigned
int
cpu
=
policy
->
cpu
;
/* _PDC settings */
arg0
.
buffer
.
length
=
12
;
...
...
@@ -350,8 +374,8 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
p
.
pdc
=
&
arg_list
;
/* register with ACPI core */
if
(
acpi_processor_register_performance
(
&
p
,
policy
->
cpu
))
{
printk
(
KERN_INFO
PFX
"obtaining ACPI data failed
\n
"
);
if
(
acpi_processor_register_performance
(
&
p
,
cpu
))
{
d
printk
(
KERN_INFO
PFX
"obtaining ACPI data failed
\n
"
);
return
-
EIO
;
}
...
...
@@ -392,49 +416,49 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
}
}
centrino_model
=
kmalloc
(
sizeof
(
struct
cpu_model
),
GFP_KERNEL
);
if
(
!
centrino_model
)
{
centrino_model
[
cpu
]
=
kmalloc
(
sizeof
(
struct
cpu_model
),
GFP_KERNEL
);
if
(
!
centrino_model
[
cpu
]
)
{
result
=
-
ENOMEM
;
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
->
max_freq
=
p
.
states
[
0
].
core_frequency
*
1000
;
centrino_model
->
op_points
=
kmalloc
(
sizeof
(
struct
cpufreq_frequency_table
)
*
centrino_model
[
cpu
]
->
model_name
=
NULL
;
centrino_model
[
cpu
]
->
max_freq
=
p
.
states
[
0
].
core_frequency
*
1000
;
centrino_model
[
cpu
]
->
op_points
=
kmalloc
(
sizeof
(
struct
cpufreq_frequency_table
)
*
(
p
.
state_count
+
1
),
GFP_KERNEL
);
if
(
!
centrino_model
->
op_points
)
{
if
(
!
centrino_model
[
cpu
]
->
op_points
)
{
result
=
-
ENOMEM
;
goto
err_kfree
;
}
for
(
i
=
0
;
i
<
p
.
state_count
;
i
++
)
{
centrino_model
->
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
].
index
=
p
.
states
[
i
].
control
;
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
"
,
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
++
)
{
if
(
!
p
.
states
[
i
].
core_frequency
)
{
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
;
}
if
(
extract_clock
(
centrino_model
->
op_points
[
i
].
index
)
!=
(
centrino_model
->
op_points
[
i
].
frequency
))
{
if
(
extract_clock
(
centrino_model
[
cpu
]
->
op_points
[
i
].
index
,
cpu
,
0
)
!=
(
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
))
{
dprintk
(
"Invalid encoded frequency (%u vs. %u)
\n
"
,
extract_clock
(
centrino_model
->
op_points
[
i
].
index
),
centrino_model
->
op_points
[
i
].
frequency
);
extract_clock
(
centrino_model
[
cpu
]
->
op_points
[
i
].
index
,
cpu
,
0
),
centrino_model
[
cpu
]
->
op_points
[
i
].
frequency
);
result
=
-
EINVAL
;
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
;
}
...
...
@@ -444,12 +468,12 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
return
0
;
err_kfree_all:
kfree
(
centrino_model
->
op_points
);
kfree
(
centrino_model
[
cpu
]
->
op_points
);
err_kfree:
kfree
(
centrino_model
);
kfree
(
centrino_model
[
cpu
]
);
err_unreg:
acpi_processor_unregister_performance
(
&
p
,
policy
->
cpu
);
printk
(
KERN_INFO
PFX
"invalid ACPI data
\n
"
);
acpi_processor_unregister_performance
(
&
p
,
cpu
);
d
printk
(
KERN_INFO
PFX
"invalid ACPI data
\n
"
);
return
(
result
);
}
#else
...
...
@@ -473,14 +497,18 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
break
;
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
(
policy
->
cpu
!=
0
)
return
-
ENODEV
;
if
(
!
centrino_cpu
)
{
printk
(
KERN_INFO
PFX
"found unsupported CPU with "
if
(
!
centrino_cpu
[
policy
->
cpu
]
)
{
d
printk
(
KERN_INFO
PFX
"found unsupported CPU with "
"Enhanced SpeedStep: send /proc/cpuinfo to "
MAINTAINER
"
\n
"
);
return
-
ENODEV
;
...
...
@@ -516,32 +544,34 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
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
)
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
;
}
static
int
centrino_cpu_exit
(
struct
cpufreq_policy
*
policy
)
{
if
(
!
centrino_model
)
unsigned
int
cpu
=
policy
->
cpu
;
if
(
!
centrino_model
[
cpu
])
return
-
ENODEV
;
cpufreq_frequency_table_put_attr
(
policy
->
cpu
);
cpufreq_frequency_table_put_attr
(
cpu
);
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
if
(
!
centrino_model
->
model_name
)
{
if
(
!
centrino_model
[
cpu
]
->
model_name
)
{
dprintk
(
"unregistering and freeing ACPI data
\n
"
);
acpi_processor_unregister_performance
(
&
p
,
policy
->
cpu
);
kfree
(
centrino_model
->
op_points
);
kfree
(
centrino_model
);
acpi_processor_unregister_performance
(
&
p
,
cpu
);
kfree
(
centrino_model
[
cpu
]
->
op_points
);
kfree
(
centrino_model
[
cpu
]
);
}
#endif
centrino_model
=
NULL
;
centrino_model
[
cpu
]
=
NULL
;
return
0
;
}
...
...
@@ -555,7 +585,7 @@ static int centrino_cpu_exit(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,
unsigned
int
relation
)
{
unsigned
int
newstate
=
0
;
unsigned
int
msr
,
oldmsr
,
h
;
unsigned
int
msr
,
oldmsr
,
h
,
cpu
=
policy
->
cpu
;
struct
cpufreq_freqs
freqs
;
cpumask_t
saved_mask
;
int
retval
;
if
(
centrino_model
==
NULL
)
if
(
centrino_model
[
cpu
]
==
NULL
)
return
-
ENODEV
;
/*
...
...
@@ -585,18 +615,18 @@ static int centrino_target (struct cpufreq_policy *policy,
*/
saved_mask
=
current
->
cpus_allowed
;
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
"
);
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
))
{
retval
=
-
EINVAL
;
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
);
if
(
msr
==
(
oldmsr
&
0xffff
))
{
...
...
@@ -605,9 +635,9 @@ static int centrino_target (struct cpufreq_policy *policy,
goto
migrate_end
;
}
freqs
.
cpu
=
policy
->
cpu
;
freqs
.
old
=
extract_clock
(
oldmsr
);
freqs
.
new
=
extract_clock
(
msr
);
freqs
.
cpu
=
cpu
;
freqs
.
old
=
extract_clock
(
oldmsr
,
cpu
,
0
);
freqs
.
new
=
extract_clock
(
msr
,
cpu
,
0
);
dprintk
(
"target=%dkHz old=%d new=%d msr=%04x
\n
"
,
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
2 to activate CPUfreq drivers debugging, and
4 to activate CPUfreq governor debugging
config CPU_FREQ_PROC_INTF
tristate "/proc/cpufreq interface (deprecated)"
depends on CPU_FREQ && PROC_FS
help
This enables the /proc/cpufreq interface for controlling
CPUFreq. Please note that it is recommended to use the sysfs
interface instead (which is built automatically).
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
config CPU_FREQ_STAT
tristate "CPU frequency translation statistics"
depends on CPU_FREQ && CPU_FREQ_TABLE
default y
help
This driver exports CPU frequency statistics information through sysfs
file system
config CPU_FREQ_STAT_DETAILS
bool "CPU frequency translation statistics details"
depends on CPU_FREQ && CPU_FREQ_STAT
default n
help
This will show detail CPU frequency translation table in sysfs file
system
choice
prompt "Default CPUFreq governor"
...
...
@@ -98,21 +102,6 @@ config CPU_FREQ_GOV_USERSPACE
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
tristate "'ondemand' cpufreq policy governor"
depends on CPU_FREQ
...
...
drivers/cpufreq/Makefile
View file @
ba420e28
# CPUfreq core
obj-$(CONFIG_CPU_FREQ)
+=
cpufreq.o
# CPUfreq stats
obj-$(CONFIG_CPU_FREQ_STAT)
+=
cpufreq_stats.o
# CPUfreq governors
obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE)
+=
cpufreq_performance.o
...
...
@@ -9,5 +11,4 @@ obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
# CPUfreq cross-arch helpers
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);
static
LIST_HEAD
(
cpufreq_governor_list
);
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
;
unsigned
long
flags
;
...
...
@@ -102,12 +102,14 @@ static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
err_out:
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
);
module_put
(
cpufreq_driver
->
owner
);
}
EXPORT_SYMBOL_GPL
(
cpufreq_cpu_put
);
/*********************************************************************
...
...
@@ -285,7 +287,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/**
* 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
)
{
if
(
!
cpufreq_driver
)
...
...
@@ -763,8 +765,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
spin_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
#endif
down
(
&
data
->
lock
);
if
(
cpufreq_driver
->
target
)
__cpufreq_governor
(
data
,
CPUFREQ_GOV_STOP
);
cpufreq_driver
->
target
=
NULL
;
up
(
&
data
->
lock
);
kobject_unregister
(
&
data
->
kobj
);
...
...
@@ -893,6 +898,13 @@ static int cpufreq_resume(struct sys_device * sysdev)
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
))
{
unsigned
int
cur_freq
=
0
;
...
...
@@ -1018,7 +1030,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
lock_cpu_hotplug
();
dprintk
(
"target for CPU %u: %u kHz, relation %u
\n
"
,
policy
->
cpu
,
target_freq
,
relation
);
if
(
cpu_online
(
policy
->
cpu
))
if
(
cpu_online
(
policy
->
cpu
)
&&
cpufreq_driver
->
target
)
retval
=
cpufreq_driver
->
target
(
policy
,
target_freq
,
relation
);
unlock_cpu_hotplug
();
return
retval
;
...
...
drivers/cpufreq/cpufreq_ondemand.c
View file @
ba420e28
...
...
@@ -229,10 +229,14 @@ static void dbs_check_cpu(int cpu)
static
int
down_skip
[
NR_CPUS
];
struct
cpu_dbs_info_s
*
this_dbs_info
;
struct
cpufreq_policy
*
policy
;
unsigned
int
j
;
this_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
cpu
);
if
(
!
this_dbs_info
->
enable
)
return
;
policy
=
this_dbs_info
->
cur_policy
;
/*
* The default safe range is 20% to 80%
* Every sampling_rate, we check
...
...
@@ -246,12 +250,33 @@ static void dbs_check_cpu(int cpu)
* Frequency reduction happens at minimum steps of
* 5% of max_frequency
*/
/* Check for frequency increase */
total_idle_ticks
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
idle_ticks
=
total_idle_ticks
-
this_dbs_info
->
prev_cpu_idle_up
;
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 */
idle_ticks
*=
100
;
...
...
@@ -259,8 +284,7 @@ static void dbs_check_cpu(int cpu)
sampling_rate_in_HZ
(
dbs_tuners_ins
.
sampling_rate
);
if
(
idle_ticks
<
up_idle_ticks
)
{
__cpufreq_driver_target
(
this_dbs_info
->
cur_policy
,
this_dbs_info
->
cur_policy
->
max
,
__cpufreq_driver_target
(
policy
,
policy
->
max
,
CPUFREQ_RELATION_H
);
down_skip
[
cpu
]
=
0
;
this_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
...
...
@@ -272,12 +296,34 @@ static void dbs_check_cpu(int cpu)
if
(
down_skip
[
cpu
]
<
dbs_tuners_ins
.
sampling_down_factor
)
return
;
total_idle_ticks
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
idle_ticks
=
total_idle_ticks
-
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 */
idle_ticks
*=
100
;
down_skip
[
cpu
]
=
0
;
this_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
freq_down_sampling_rate
=
dbs_tuners_ins
.
sampling_rate
*
dbs_tuners_ins
.
sampling_down_factor
;
...
...
@@ -285,14 +331,14 @@ static void dbs_check_cpu(int cpu)
sampling_rate_in_HZ
(
freq_down_sampling_rate
);
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.... */
if
(
unlikely
(
freq_down_step
==
0
))
freq_down_step
=
5
;
__cpufreq_driver_target
(
this_dbs_info
->
cur_
policy
,
this_dbs_info
->
cur_
policy
->
cur
-
freq_down_step
,
__cpufreq_driver_target
(
policy
,
policy
->
cur
-
freq_down_step
,
CPUFREQ_RELATION_H
);
return
;
}
...
...
@@ -313,7 +359,8 @@ static void do_dbs_timer(void *data)
static
inline
void
dbs_timer_init
(
void
)
{
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
;
}
...
...
@@ -328,6 +375,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
{
unsigned
int
cpu
=
policy
->
cpu
;
struct
cpu_dbs_info_s
*
this_dbs_info
;
unsigned
int
j
;
this_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
cpu
);
...
...
@@ -344,14 +392,18 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
break
;
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
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
this_dbs_info
->
prev_cpu_idle_down
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
j_dbs_info
->
prev_cpu_idle_up
=
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
iowait
;
j_dbs_info
->
prev_cpu_idle_down
=
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
iowait
;
}
this_dbs_info
->
enable
=
1
;
sysfs_create_group
(
&
policy
->
kobj
,
&
dbs_attr_group
);
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 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/ctype.h>
#include <linux/cpufreq.h>
#include <linux/sysctl.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/sysfs.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
...
...
@@ -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
* @cpu: CPU for which the frequency is to be set
*
* 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
;
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
);
if
(
!
cpu_is_managed
[
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 ************************/
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)
if
(
ret
!=
1
)
return
-
EINVAL
;
_
cpufreq_set
(
freq
,
policy
->
cpu
);
cpufreq_set
(
freq
,
policy
->
cpu
);
return
count
;
}
...
...
@@ -577,7 +187,6 @@ EXPORT_SYMBOL(cpufreq_gov_userspace);
static
int
__init
cpufreq_gov_userspace_init
(
void
)
{
cpufreq_sysctl_init
();
cpufreq_register_notifier
(
&
userspace_cpufreq_notifier_block
,
CPUFREQ_TRANSITION_NOTIFIER
);
return
cpufreq_register_governor
(
&
cpufreq_gov_userspace
);
}
...
...
@@ -587,7 +196,6 @@ static void __exit cpufreq_gov_userspace_exit(void)
{
cpufreq_unregister_governor
(
&
cpufreq_gov_userspace
);
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)
}
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_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);
/* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
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 *
...
...
@@ -351,6 +292,11 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned
int
relation
,
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 */
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