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