Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
2dc36ecf
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
2dc36ecf
编写于
8月 07, 2015
作者:
R
Rafael J. Wysocki
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'pm-cpufreq' into pm-opp
上级
19445b25
144c8e17
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
638 addition
and
404 deletion
+638
-404
arch/powerpc/include/asm/opal-api.h
arch/powerpc/include/asm/opal-api.h
+12
-0
drivers/acpi/processor_perflib.c
drivers/acpi/processor_perflib.c
+1
-3
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/acpi-cpufreq.c
+51
-42
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq.c
+145
-177
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_conservative.c
+7
-18
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/cpufreq_governor.c
+146
-50
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_governor.h
+22
-18
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_ondemand.c
+32
-35
drivers/cpufreq/e_powersaver.c
drivers/cpufreq/e_powersaver.c
+1
-1
drivers/cpufreq/ia64-acpi-cpufreq.c
drivers/cpufreq/ia64-acpi-cpufreq.c
+10
-10
drivers/cpufreq/integrator-cpufreq.c
drivers/cpufreq/integrator-cpufreq.c
+8
-10
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/intel_pstate.c
+9
-6
drivers/cpufreq/powernow-k7.c
drivers/cpufreq/powernow-k7.c
+2
-2
drivers/cpufreq/powernow-k8.c
drivers/cpufreq/powernow-k8.c
+2
-3
drivers/cpufreq/powernv-cpufreq.c
drivers/cpufreq/powernv-cpufreq.c
+183
-15
drivers/xen/xen-acpi-processor.c
drivers/xen/xen-acpi-processor.c
+6
-10
include/acpi/processor.h
include/acpi/processor.h
+1
-4
未找到文件。
arch/powerpc/include/asm/opal-api.h
浏览文件 @
2dc36ecf
...
@@ -361,6 +361,7 @@ enum opal_msg_type {
...
@@ -361,6 +361,7 @@ enum opal_msg_type {
OPAL_MSG_HMI_EVT
,
OPAL_MSG_HMI_EVT
,
OPAL_MSG_DPO
,
OPAL_MSG_DPO
,
OPAL_MSG_PRD
,
OPAL_MSG_PRD
,
OPAL_MSG_OCC
,
OPAL_MSG_TYPE_MAX
,
OPAL_MSG_TYPE_MAX
,
};
};
...
@@ -700,6 +701,17 @@ struct opal_prd_msg_header {
...
@@ -700,6 +701,17 @@ struct opal_prd_msg_header {
struct
opal_prd_msg
;
struct
opal_prd_msg
;
#define OCC_RESET 0
#define OCC_LOAD 1
#define OCC_THROTTLE 2
#define OCC_MAX_THROTTLE_STATUS 5
struct
opal_occ_msg
{
__be64
type
;
__be64
chip
;
__be64
throttle_status
;
};
/*
/*
* SG entries
* SG entries
*
*
...
...
drivers/acpi/processor_perflib.c
浏览文件 @
2dc36ecf
...
@@ -784,9 +784,7 @@ acpi_processor_register_performance(struct acpi_processor_performance
...
@@ -784,9 +784,7 @@ acpi_processor_register_performance(struct acpi_processor_performance
EXPORT_SYMBOL
(
acpi_processor_register_performance
);
EXPORT_SYMBOL
(
acpi_processor_register_performance
);
void
void
acpi_processor_unregister_performance
(
unsigned
int
cpu
)
acpi_processor_unregister_performance
(
struct
acpi_processor_performance
*
performance
,
unsigned
int
cpu
)
{
{
struct
acpi_processor
*
pr
;
struct
acpi_processor
*
pr
;
...
...
drivers/cpufreq/acpi-cpufreq.c
浏览文件 @
2dc36ecf
...
@@ -65,18 +65,21 @@ enum {
...
@@ -65,18 +65,21 @@ enum {
#define MSR_K7_HWCR_CPB_DIS (1ULL << 25)
#define MSR_K7_HWCR_CPB_DIS (1ULL << 25)
struct
acpi_cpufreq_data
{
struct
acpi_cpufreq_data
{
struct
acpi_processor_performance
*
acpi_data
;
struct
cpufreq_frequency_table
*
freq_table
;
struct
cpufreq_frequency_table
*
freq_table
;
unsigned
int
resume
;
unsigned
int
resume
;
unsigned
int
cpu_feature
;
unsigned
int
cpu_feature
;
unsigned
int
acpi_perf_cpu
;
cpumask_var_t
freqdomain_cpus
;
cpumask_var_t
freqdomain_cpus
;
};
};
static
DEFINE_PER_CPU
(
struct
acpi_cpufreq_data
*
,
acfreq_data
);
/* acpi_perf_data is a pointer to percpu data. */
/* acpi_perf_data is a pointer to percpu data. */
static
struct
acpi_processor_performance
__percpu
*
acpi_perf_data
;
static
struct
acpi_processor_performance
__percpu
*
acpi_perf_data
;
static
inline
struct
acpi_processor_performance
*
to_perf_data
(
struct
acpi_cpufreq_data
*
data
)
{
return
per_cpu_ptr
(
acpi_perf_data
,
data
->
acpi_perf_cpu
);
}
static
struct
cpufreq_driver
acpi_cpufreq_driver
;
static
struct
cpufreq_driver
acpi_cpufreq_driver
;
static
unsigned
int
acpi_pstate_strict
;
static
unsigned
int
acpi_pstate_strict
;
...
@@ -144,7 +147,7 @@ static int _store_boost(int val)
...
@@ -144,7 +147,7 @@ static int _store_boost(int val)
static
ssize_t
show_freqdomain_cpus
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
static
ssize_t
show_freqdomain_cpus
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
{
struct
acpi_cpufreq_data
*
data
=
p
er_cpu
(
acfreq_data
,
policy
->
cpu
)
;
struct
acpi_cpufreq_data
*
data
=
p
olicy
->
driver_data
;
return
cpufreq_show_cpus
(
data
->
freqdomain_cpus
,
buf
);
return
cpufreq_show_cpus
(
data
->
freqdomain_cpus
,
buf
);
}
}
...
@@ -202,7 +205,7 @@ static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
...
@@ -202,7 +205,7 @@ static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
struct
acpi_processor_performance
*
perf
;
struct
acpi_processor_performance
*
perf
;
int
i
;
int
i
;
perf
=
data
->
acpi_data
;
perf
=
to_perf_data
(
data
)
;
for
(
i
=
0
;
i
<
perf
->
state_count
;
i
++
)
{
for
(
i
=
0
;
i
<
perf
->
state_count
;
i
++
)
{
if
(
value
==
perf
->
states
[
i
].
status
)
if
(
value
==
perf
->
states
[
i
].
status
)
...
@@ -221,7 +224,7 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
...
@@ -221,7 +224,7 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
else
else
msr
&=
INTEL_MSR_RANGE
;
msr
&=
INTEL_MSR_RANGE
;
perf
=
data
->
acpi_data
;
perf
=
to_perf_data
(
data
)
;
cpufreq_for_each_entry
(
pos
,
data
->
freq_table
)
cpufreq_for_each_entry
(
pos
,
data
->
freq_table
)
if
(
msr
==
perf
->
states
[
pos
->
driver_data
].
status
)
if
(
msr
==
perf
->
states
[
pos
->
driver_data
].
status
)
...
@@ -327,7 +330,8 @@ static void drv_write(struct drv_cmd *cmd)
...
@@ -327,7 +330,8 @@ static void drv_write(struct drv_cmd *cmd)
put_cpu
();
put_cpu
();
}
}
static
u32
get_cur_val
(
const
struct
cpumask
*
mask
)
static
u32
get_cur_val
(
const
struct
cpumask
*
mask
,
struct
acpi_cpufreq_data
*
data
)
{
{
struct
acpi_processor_performance
*
perf
;
struct
acpi_processor_performance
*
perf
;
struct
drv_cmd
cmd
;
struct
drv_cmd
cmd
;
...
@@ -335,7 +339,7 @@ static u32 get_cur_val(const struct cpumask *mask)
...
@@ -335,7 +339,7 @@ static u32 get_cur_val(const struct cpumask *mask)
if
(
unlikely
(
cpumask_empty
(
mask
)))
if
(
unlikely
(
cpumask_empty
(
mask
)))
return
0
;
return
0
;
switch
(
per_cpu
(
acfreq_data
,
cpumask_first
(
mask
))
->
cpu_feature
)
{
switch
(
data
->
cpu_feature
)
{
case
SYSTEM_INTEL_MSR_CAPABLE
:
case
SYSTEM_INTEL_MSR_CAPABLE
:
cmd
.
type
=
SYSTEM_INTEL_MSR_CAPABLE
;
cmd
.
type
=
SYSTEM_INTEL_MSR_CAPABLE
;
cmd
.
addr
.
msr
.
reg
=
MSR_IA32_PERF_CTL
;
cmd
.
addr
.
msr
.
reg
=
MSR_IA32_PERF_CTL
;
...
@@ -346,7 +350,7 @@ static u32 get_cur_val(const struct cpumask *mask)
...
@@ -346,7 +350,7 @@ static u32 get_cur_val(const struct cpumask *mask)
break
;
break
;
case
SYSTEM_IO_CAPABLE
:
case
SYSTEM_IO_CAPABLE
:
cmd
.
type
=
SYSTEM_IO_CAPABLE
;
cmd
.
type
=
SYSTEM_IO_CAPABLE
;
perf
=
per_cpu
(
acfreq_data
,
cpumask_first
(
mask
))
->
acpi_data
;
perf
=
to_perf_data
(
data
)
;
cmd
.
addr
.
io
.
port
=
perf
->
control_register
.
address
;
cmd
.
addr
.
io
.
port
=
perf
->
control_register
.
address
;
cmd
.
addr
.
io
.
bit_width
=
perf
->
control_register
.
bit_width
;
cmd
.
addr
.
io
.
bit_width
=
perf
->
control_register
.
bit_width
;
break
;
break
;
...
@@ -364,19 +368,24 @@ static u32 get_cur_val(const struct cpumask *mask)
...
@@ -364,19 +368,24 @@ static u32 get_cur_val(const struct cpumask *mask)
static
unsigned
int
get_cur_freq_on_cpu
(
unsigned
int
cpu
)
static
unsigned
int
get_cur_freq_on_cpu
(
unsigned
int
cpu
)
{
{
struct
acpi_cpufreq_data
*
data
=
per_cpu
(
acfreq_data
,
cpu
);
struct
acpi_cpufreq_data
*
data
;
struct
cpufreq_policy
*
policy
;
unsigned
int
freq
;
unsigned
int
freq
;
unsigned
int
cached_freq
;
unsigned
int
cached_freq
;
pr_debug
(
"get_cur_freq_on_cpu (%d)
\n
"
,
cpu
);
pr_debug
(
"get_cur_freq_on_cpu (%d)
\n
"
,
cpu
);
if
(
unlikely
(
data
==
NULL
||
policy
=
cpufreq_cpu_get
(
cpu
);
data
->
acpi_data
==
NULL
||
data
->
freq_table
==
NULL
))
{
if
(
unlikely
(
!
policy
))
return
0
;
return
0
;
}
cached_freq
=
data
->
freq_table
[
data
->
acpi_data
->
state
].
frequency
;
data
=
policy
->
driver_data
;
freq
=
extract_freq
(
get_cur_val
(
cpumask_of
(
cpu
)),
data
);
cpufreq_cpu_put
(
policy
);
if
(
unlikely
(
!
data
||
!
data
->
freq_table
))
return
0
;
cached_freq
=
data
->
freq_table
[
to_perf_data
(
data
)
->
state
].
frequency
;
freq
=
extract_freq
(
get_cur_val
(
cpumask_of
(
cpu
),
data
),
data
);
if
(
freq
!=
cached_freq
)
{
if
(
freq
!=
cached_freq
)
{
/*
/*
* The dreaded BIOS frequency change behind our back.
* The dreaded BIOS frequency change behind our back.
...
@@ -397,7 +406,7 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,
...
@@ -397,7 +406,7 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,
unsigned
int
i
;
unsigned
int
i
;
for
(
i
=
0
;
i
<
100
;
i
++
)
{
for
(
i
=
0
;
i
<
100
;
i
++
)
{
cur_freq
=
extract_freq
(
get_cur_val
(
mask
),
data
);
cur_freq
=
extract_freq
(
get_cur_val
(
mask
,
data
),
data
);
if
(
cur_freq
==
freq
)
if
(
cur_freq
==
freq
)
return
1
;
return
1
;
udelay
(
10
);
udelay
(
10
);
...
@@ -408,18 +417,17 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,
...
@@ -408,18 +417,17 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,
static
int
acpi_cpufreq_target
(
struct
cpufreq_policy
*
policy
,
static
int
acpi_cpufreq_target
(
struct
cpufreq_policy
*
policy
,
unsigned
int
index
)
unsigned
int
index
)
{
{
struct
acpi_cpufreq_data
*
data
=
p
er_cpu
(
acfreq_data
,
policy
->
cpu
)
;
struct
acpi_cpufreq_data
*
data
=
p
olicy
->
driver_data
;
struct
acpi_processor_performance
*
perf
;
struct
acpi_processor_performance
*
perf
;
struct
drv_cmd
cmd
;
struct
drv_cmd
cmd
;
unsigned
int
next_perf_state
=
0
;
/* Index into perf table */
unsigned
int
next_perf_state
=
0
;
/* Index into perf table */
int
result
=
0
;
int
result
=
0
;
if
(
unlikely
(
data
==
NULL
||
if
(
unlikely
(
data
==
NULL
||
data
->
freq_table
==
NULL
))
{
data
->
acpi_data
==
NULL
||
data
->
freq_table
==
NULL
))
{
return
-
ENODEV
;
return
-
ENODEV
;
}
}
perf
=
data
->
acpi_data
;
perf
=
to_perf_data
(
data
)
;
next_perf_state
=
data
->
freq_table
[
index
].
driver_data
;
next_perf_state
=
data
->
freq_table
[
index
].
driver_data
;
if
(
perf
->
state
==
next_perf_state
)
{
if
(
perf
->
state
==
next_perf_state
)
{
if
(
unlikely
(
data
->
resume
))
{
if
(
unlikely
(
data
->
resume
))
{
...
@@ -482,8 +490,9 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
...
@@ -482,8 +490,9 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
static
unsigned
long
static
unsigned
long
acpi_cpufreq_guess_freq
(
struct
acpi_cpufreq_data
*
data
,
unsigned
int
cpu
)
acpi_cpufreq_guess_freq
(
struct
acpi_cpufreq_data
*
data
,
unsigned
int
cpu
)
{
{
struct
acpi_processor_performance
*
perf
=
data
->
acpi_data
;
struct
acpi_processor_performance
*
perf
;
perf
=
to_perf_data
(
data
);
if
(
cpu_khz
)
{
if
(
cpu_khz
)
{
/* search the closest match to cpu_khz */
/* search the closest match to cpu_khz */
unsigned
int
i
;
unsigned
int
i
;
...
@@ -672,17 +681,17 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
...
@@ -672,17 +681,17 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
goto
err_free
;
goto
err_free
;
}
}
data
->
acpi_data
=
per_cpu_ptr
(
acpi_perf_data
,
cpu
);
perf
=
per_cpu_ptr
(
acpi_perf_data
,
cpu
);
per_cpu
(
acfreq_data
,
cpu
)
=
data
;
data
->
acpi_perf_cpu
=
cpu
;
policy
->
driver_data
=
data
;
if
(
cpu_has
(
c
,
X86_FEATURE_CONSTANT_TSC
))
if
(
cpu_has
(
c
,
X86_FEATURE_CONSTANT_TSC
))
acpi_cpufreq_driver
.
flags
|=
CPUFREQ_CONST_LOOPS
;
acpi_cpufreq_driver
.
flags
|=
CPUFREQ_CONST_LOOPS
;
result
=
acpi_processor_register_performance
(
data
->
acpi_data
,
cpu
);
result
=
acpi_processor_register_performance
(
perf
,
cpu
);
if
(
result
)
if
(
result
)
goto
err_free_mask
;
goto
err_free_mask
;
perf
=
data
->
acpi_data
;
policy
->
shared_type
=
perf
->
shared_type
;
policy
->
shared_type
=
perf
->
shared_type
;
/*
/*
...
@@ -838,26 +847,25 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
...
@@ -838,26 +847,25 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
err_freqfree:
err_freqfree:
kfree
(
data
->
freq_table
);
kfree
(
data
->
freq_table
);
err_unreg:
err_unreg:
acpi_processor_unregister_performance
(
perf
,
cpu
);
acpi_processor_unregister_performance
(
cpu
);
err_free_mask:
err_free_mask:
free_cpumask_var
(
data
->
freqdomain_cpus
);
free_cpumask_var
(
data
->
freqdomain_cpus
);
err_free:
err_free:
kfree
(
data
);
kfree
(
data
);
p
er_cpu
(
acfreq_data
,
cpu
)
=
NULL
;
p
olicy
->
driver_data
=
NULL
;
return
result
;
return
result
;
}
}
static
int
acpi_cpufreq_cpu_exit
(
struct
cpufreq_policy
*
policy
)
static
int
acpi_cpufreq_cpu_exit
(
struct
cpufreq_policy
*
policy
)
{
{
struct
acpi_cpufreq_data
*
data
=
p
er_cpu
(
acfreq_data
,
policy
->
cpu
)
;
struct
acpi_cpufreq_data
*
data
=
p
olicy
->
driver_data
;
pr_debug
(
"acpi_cpufreq_cpu_exit
\n
"
);
pr_debug
(
"acpi_cpufreq_cpu_exit
\n
"
);
if
(
data
)
{
if
(
data
)
{
per_cpu
(
acfreq_data
,
policy
->
cpu
)
=
NULL
;
policy
->
driver_data
=
NULL
;
acpi_processor_unregister_performance
(
data
->
acpi_data
,
acpi_processor_unregister_performance
(
data
->
acpi_perf_cpu
);
policy
->
cpu
);
free_cpumask_var
(
data
->
freqdomain_cpus
);
free_cpumask_var
(
data
->
freqdomain_cpus
);
kfree
(
data
->
freq_table
);
kfree
(
data
->
freq_table
);
kfree
(
data
);
kfree
(
data
);
...
@@ -868,7 +876,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
...
@@ -868,7 +876,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
static
int
acpi_cpufreq_resume
(
struct
cpufreq_policy
*
policy
)
static
int
acpi_cpufreq_resume
(
struct
cpufreq_policy
*
policy
)
{
{
struct
acpi_cpufreq_data
*
data
=
p
er_cpu
(
acfreq_data
,
policy
->
cpu
)
;
struct
acpi_cpufreq_data
*
data
=
p
olicy
->
driver_data
;
pr_debug
(
"acpi_cpufreq_resume
\n
"
);
pr_debug
(
"acpi_cpufreq_resume
\n
"
);
...
@@ -880,7 +888,9 @@ static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
...
@@ -880,7 +888,9 @@ static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
static
struct
freq_attr
*
acpi_cpufreq_attr
[]
=
{
static
struct
freq_attr
*
acpi_cpufreq_attr
[]
=
{
&
cpufreq_freq_attr_scaling_available_freqs
,
&
cpufreq_freq_attr_scaling_available_freqs
,
&
freqdomain_cpus
,
&
freqdomain_cpus
,
NULL
,
/* this is a placeholder for cpb, do not remove */
#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
&
cpb
,
#endif
NULL
,
NULL
,
};
};
...
@@ -953,17 +963,16 @@ static int __init acpi_cpufreq_init(void)
...
@@ -953,17 +963,16 @@ static int __init acpi_cpufreq_init(void)
* only if configured. This is considered legacy code, which
* only if configured. This is considered legacy code, which
* will probably be removed at some point in the future.
* will probably be removed at some point in the future.
*/
*/
if
(
check_amd_hwpstate_cpu
(
0
))
{
if
(
!
check_amd_hwpstate_cpu
(
0
))
{
struct
freq_attr
**
iter
;
struct
freq_attr
**
attr
;
pr_debug
(
"adding sysfs entry for cpb
\n
"
);
for
(
iter
=
acpi_cpufreq_attr
;
*
iter
!=
NULL
;
iter
++
)
pr_debug
(
"CPB unsupported, do not expose it
\n
"
);
;
/* make sure there is a terminator behind it */
for
(
attr
=
acpi_cpufreq_attr
;
*
attr
;
attr
++
)
if
(
iter
[
1
]
==
NULL
)
if
(
*
attr
==
&
cpb
)
{
*
iter
=
&
cpb
;
*
attr
=
NULL
;
break
;
}
}
}
#endif
#endif
acpi_cpufreq_boost_init
();
acpi_cpufreq_boost_init
();
...
...
drivers/cpufreq/cpufreq.c
浏览文件 @
2dc36ecf
...
@@ -112,12 +112,6 @@ static inline bool has_target(void)
...
@@ -112,12 +112,6 @@ static inline bool has_target(void)
return
cpufreq_driver
->
target_index
||
cpufreq_driver
->
target
;
return
cpufreq_driver
->
target_index
||
cpufreq_driver
->
target
;
}
}
/*
* rwsem to guarantee that cpufreq driver module doesn't unload during critical
* sections
*/
static
DECLARE_RWSEM
(
cpufreq_rwsem
);
/* internal prototypes */
/* internal prototypes */
static
int
__cpufreq_governor
(
struct
cpufreq_policy
*
policy
,
static
int
__cpufreq_governor
(
struct
cpufreq_policy
*
policy
,
unsigned
int
event
);
unsigned
int
event
);
...
@@ -277,10 +271,6 @@ EXPORT_SYMBOL_GPL(cpufreq_generic_get);
...
@@ -277,10 +271,6 @@ EXPORT_SYMBOL_GPL(cpufreq_generic_get);
* If corresponding call cpufreq_cpu_put() isn't made, the policy wouldn't be
* If corresponding call cpufreq_cpu_put() isn't made, the policy wouldn't be
* freed as that depends on the kobj count.
* freed as that depends on the kobj count.
*
*
* It also takes a read-lock of 'cpufreq_rwsem' and doesn't put it back if a
* valid policy is found. This is done to make sure the driver doesn't get
* unregistered while the policy is being used.
*
* Return: A valid policy on success, otherwise NULL on failure.
* Return: A valid policy on success, otherwise NULL on failure.
*/
*/
struct
cpufreq_policy
*
cpufreq_cpu_get
(
unsigned
int
cpu
)
struct
cpufreq_policy
*
cpufreq_cpu_get
(
unsigned
int
cpu
)
...
@@ -291,9 +281,6 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
...
@@ -291,9 +281,6 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
if
(
WARN_ON
(
cpu
>=
nr_cpu_ids
))
if
(
WARN_ON
(
cpu
>=
nr_cpu_ids
))
return
NULL
;
return
NULL
;
if
(
!
down_read_trylock
(
&
cpufreq_rwsem
))
return
NULL
;
/* get the cpufreq driver */
/* get the cpufreq driver */
read_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
read_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
...
@@ -306,9 +293,6 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
...
@@ -306,9 +293,6 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
read_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
read_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
if
(
!
policy
)
up_read
(
&
cpufreq_rwsem
);
return
policy
;
return
policy
;
}
}
EXPORT_SYMBOL_GPL
(
cpufreq_cpu_get
);
EXPORT_SYMBOL_GPL
(
cpufreq_cpu_get
);
...
@@ -320,13 +304,10 @@ EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
...
@@ -320,13 +304,10 @@ EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
*
*
* This decrements the kobject reference count incremented earlier by calling
* This decrements the kobject reference count incremented earlier by calling
* cpufreq_cpu_get().
* cpufreq_cpu_get().
*
* It also drops the read-lock of 'cpufreq_rwsem' taken at cpufreq_cpu_get().
*/
*/
void
cpufreq_cpu_put
(
struct
cpufreq_policy
*
policy
)
void
cpufreq_cpu_put
(
struct
cpufreq_policy
*
policy
)
{
{
kobject_put
(
&
policy
->
kobj
);
kobject_put
(
&
policy
->
kobj
);
up_read
(
&
cpufreq_rwsem
);
}
}
EXPORT_SYMBOL_GPL
(
cpufreq_cpu_put
);
EXPORT_SYMBOL_GPL
(
cpufreq_cpu_put
);
...
@@ -851,9 +832,6 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
...
@@ -851,9 +832,6 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
struct
freq_attr
*
fattr
=
to_attr
(
attr
);
struct
freq_attr
*
fattr
=
to_attr
(
attr
);
ssize_t
ret
;
ssize_t
ret
;
if
(
!
down_read_trylock
(
&
cpufreq_rwsem
))
return
-
EINVAL
;
down_read
(
&
policy
->
rwsem
);
down_read
(
&
policy
->
rwsem
);
if
(
fattr
->
show
)
if
(
fattr
->
show
)
...
@@ -862,7 +840,6 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
...
@@ -862,7 +840,6 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
ret
=
-
EIO
;
ret
=
-
EIO
;
up_read
(
&
policy
->
rwsem
);
up_read
(
&
policy
->
rwsem
);
up_read
(
&
cpufreq_rwsem
);
return
ret
;
return
ret
;
}
}
...
@@ -879,9 +856,6 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
...
@@ -879,9 +856,6 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
if
(
!
cpu_online
(
policy
->
cpu
))
if
(
!
cpu_online
(
policy
->
cpu
))
goto
unlock
;
goto
unlock
;
if
(
!
down_read_trylock
(
&
cpufreq_rwsem
))
goto
unlock
;
down_write
(
&
policy
->
rwsem
);
down_write
(
&
policy
->
rwsem
);
/* Updating inactive policies is invalid, so avoid doing that. */
/* Updating inactive policies is invalid, so avoid doing that. */
...
@@ -897,8 +871,6 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
...
@@ -897,8 +871,6 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
unlock_policy_rwsem:
unlock_policy_rwsem:
up_write
(
&
policy
->
rwsem
);
up_write
(
&
policy
->
rwsem
);
up_read
(
&
cpufreq_rwsem
);
unlock:
unlock:
put_online_cpus
();
put_online_cpus
();
...
@@ -1027,8 +999,7 @@ static void cpufreq_remove_dev_symlink(struct cpufreq_policy *policy)
...
@@ -1027,8 +999,7 @@ static void cpufreq_remove_dev_symlink(struct cpufreq_policy *policy)
}
}
}
}
static
int
cpufreq_add_dev_interface
(
struct
cpufreq_policy
*
policy
,
static
int
cpufreq_add_dev_interface
(
struct
cpufreq_policy
*
policy
)
struct
device
*
dev
)
{
{
struct
freq_attr
**
drv_attr
;
struct
freq_attr
**
drv_attr
;
int
ret
=
0
;
int
ret
=
0
;
...
@@ -1060,11 +1031,10 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
...
@@ -1060,11 +1031,10 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
return
cpufreq_add_dev_symlink
(
policy
);
return
cpufreq_add_dev_symlink
(
policy
);
}
}
static
void
cpufreq_init_policy
(
struct
cpufreq_policy
*
policy
)
static
int
cpufreq_init_policy
(
struct
cpufreq_policy
*
policy
)
{
{
struct
cpufreq_governor
*
gov
=
NULL
;
struct
cpufreq_governor
*
gov
=
NULL
;
struct
cpufreq_policy
new_policy
;
struct
cpufreq_policy
new_policy
;
int
ret
=
0
;
memcpy
(
&
new_policy
,
policy
,
sizeof
(
*
policy
));
memcpy
(
&
new_policy
,
policy
,
sizeof
(
*
policy
));
...
@@ -1083,16 +1053,10 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
...
@@ -1083,16 +1053,10 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
cpufreq_parse_governor
(
gov
->
name
,
&
new_policy
.
policy
,
NULL
);
cpufreq_parse_governor
(
gov
->
name
,
&
new_policy
.
policy
,
NULL
);
/* set default policy */
/* set default policy */
ret
=
cpufreq_set_policy
(
policy
,
&
new_policy
);
return
cpufreq_set_policy
(
policy
,
&
new_policy
);
if
(
ret
)
{
pr_debug
(
"setting policy failed
\n
"
);
if
(
cpufreq_driver
->
exit
)
cpufreq_driver
->
exit
(
policy
);
}
}
}
static
int
cpufreq_add_policy_cpu
(
struct
cpufreq_policy
*
policy
,
static
int
cpufreq_add_policy_cpu
(
struct
cpufreq_policy
*
policy
,
unsigned
int
cpu
)
unsigned
int
cpu
,
struct
device
*
dev
)
{
{
int
ret
=
0
;
int
ret
=
0
;
...
@@ -1126,33 +1090,15 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
...
@@ -1126,33 +1090,15 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
return
0
;
return
0
;
}
}
static
struct
cpufreq_policy
*
cpufreq_policy_restore
(
unsigned
int
cpu
)
static
struct
cpufreq_policy
*
cpufreq_policy_alloc
(
unsigned
int
cpu
)
{
struct
cpufreq_policy
*
policy
;
unsigned
long
flags
;
read_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
policy
=
per_cpu
(
cpufreq_cpu_data
,
cpu
);
read_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
if
(
likely
(
policy
))
{
/* Policy should be inactive here */
WARN_ON
(
!
policy_is_inactive
(
policy
));
down_write
(
&
policy
->
rwsem
);
policy
->
cpu
=
cpu
;
policy
->
governor
=
NULL
;
up_write
(
&
policy
->
rwsem
);
}
return
policy
;
}
static
struct
cpufreq_policy
*
cpufreq_policy_alloc
(
struct
device
*
dev
)
{
{
struct
device
*
dev
=
get_cpu_device
(
cpu
);
struct
cpufreq_policy
*
policy
;
struct
cpufreq_policy
*
policy
;
int
ret
;
int
ret
;
if
(
WARN_ON
(
!
dev
))
return
NULL
;
policy
=
kzalloc
(
sizeof
(
*
policy
),
GFP_KERNEL
);
policy
=
kzalloc
(
sizeof
(
*
policy
),
GFP_KERNEL
);
if
(
!
policy
)
if
(
!
policy
)
return
NULL
;
return
NULL
;
...
@@ -1180,10 +1126,10 @@ static struct cpufreq_policy *cpufreq_policy_alloc(struct device *dev)
...
@@ -1180,10 +1126,10 @@ static struct cpufreq_policy *cpufreq_policy_alloc(struct device *dev)
init_completion
(
&
policy
->
kobj_unregister
);
init_completion
(
&
policy
->
kobj_unregister
);
INIT_WORK
(
&
policy
->
update
,
handle_update
);
INIT_WORK
(
&
policy
->
update
,
handle_update
);
policy
->
cpu
=
dev
->
id
;
policy
->
cpu
=
cpu
;
/* Set this once on allocation */
/* Set this once on allocation */
policy
->
kobj_cpu
=
dev
->
id
;
policy
->
kobj_cpu
=
cpu
;
return
policy
;
return
policy
;
...
@@ -1245,59 +1191,34 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy, bool notify)
...
@@ -1245,59 +1191,34 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy, bool notify)
kfree
(
policy
);
kfree
(
policy
);
}
}
/**
static
int
cpufreq_online
(
unsigned
int
cpu
)
* cpufreq_add_dev - add a CPU device
*
* Adds the cpufreq interface for a CPU device.
*
* The Oracle says: try running cpufreq registration/unregistration concurrently
* with with cpu hotplugging and all hell will break loose. Tried to clean this
* mess up, but more thorough testing is needed. - Mathieu
*/
static
int
cpufreq_add_dev
(
struct
device
*
dev
,
struct
subsys_interface
*
sif
)
{
{
unsigned
int
j
,
cpu
=
dev
->
id
;
int
ret
=
-
ENOMEM
;
struct
cpufreq_policy
*
policy
;
struct
cpufreq_policy
*
policy
;
bool
new_policy
;
unsigned
long
flags
;
unsigned
long
flags
;
bool
recover_policy
=
!
sif
;
unsigned
int
j
;
int
ret
;
pr_debug
(
"adding CPU %u
\n
"
,
cpu
);
if
(
cpu_is_offline
(
cpu
))
{
/*
* Only possible if we are here from the subsys_interface add
* callback. A hotplug notifier will follow and we will handle
* it as CPU online then. For now, just create the sysfs link,
* unless there is no policy or the link is already present.
*/
policy
=
per_cpu
(
cpufreq_cpu_data
,
cpu
);
return
policy
&&
!
cpumask_test_and_set_cpu
(
cpu
,
policy
->
real_cpus
)
?
add_cpu_dev_symlink
(
policy
,
cpu
)
:
0
;
}
if
(
!
down_read_trylock
(
&
cpufreq_rwsem
))
pr_debug
(
"%s: bringing CPU%u online
\n
"
,
__func__
,
cpu
);
return
0
;
/* Check if this CPU already has a policy to manage it */
/* Check if this CPU already has a policy to manage it */
policy
=
per_cpu
(
cpufreq_cpu_data
,
cpu
);
policy
=
per_cpu
(
cpufreq_cpu_data
,
cpu
);
if
(
policy
&&
!
policy_is_inactive
(
policy
)
)
{
if
(
policy
)
{
WARN_ON
(
!
cpumask_test_cpu
(
cpu
,
policy
->
related_cpus
));
WARN_ON
(
!
cpumask_test_cpu
(
cpu
,
policy
->
related_cpus
));
ret
=
cpufreq_add_policy_cpu
(
policy
,
cpu
,
dev
);
if
(
!
policy_is_inactive
(
policy
))
up_read
(
&
cpufreq_rwsem
);
return
cpufreq_add_policy_cpu
(
policy
,
cpu
);
return
ret
;
}
/*
/* This is the only online CPU for the policy. Start over. */
* Restore the saved policy when doing light-weight init and fall back
new_policy
=
false
;
* to the full init if that fails.
down_write
(
&
policy
->
rwsem
);
*/
policy
->
cpu
=
cpu
;
policy
=
recover_policy
?
cpufreq_policy_restore
(
cpu
)
:
NULL
;
policy
->
governor
=
NULL
;
if
(
!
policy
)
{
up_write
(
&
policy
->
rwsem
);
recover_policy
=
false
;
}
else
{
policy
=
cpufreq_policy_alloc
(
dev
);
new_policy
=
true
;
policy
=
cpufreq_policy_alloc
(
cpu
);
if
(
!
policy
)
if
(
!
policy
)
goto
nomem_out
;
return
-
ENOMEM
;
}
}
cpumask_copy
(
policy
->
cpus
,
cpumask_of
(
cpu
));
cpumask_copy
(
policy
->
cpus
,
cpumask_of
(
cpu
));
...
@@ -1308,17 +1229,17 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
...
@@ -1308,17 +1229,17 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
ret
=
cpufreq_driver
->
init
(
policy
);
ret
=
cpufreq_driver
->
init
(
policy
);
if
(
ret
)
{
if
(
ret
)
{
pr_debug
(
"initialization failed
\n
"
);
pr_debug
(
"initialization failed
\n
"
);
goto
err_set_policy_cpu
;
goto
out_free_policy
;
}
}
down_write
(
&
policy
->
rwsem
);
down_write
(
&
policy
->
rwsem
);
/* related cpus should atleast have policy->cpus */
if
(
new_policy
)
{
cpumask_or
(
policy
->
related_cpus
,
policy
->
related_cpus
,
policy
->
cpus
);
/* related_cpus should at least include policy->cpus. */
cpumask_or
(
policy
->
related_cpus
,
policy
->
related_cpus
,
policy
->
cpus
);
/* Remember which CPUs have been present at the policy creation time. */
/* Remember CPUs present at the policy creation time. */
if
(
!
recover_policy
)
cpumask_and
(
policy
->
real_cpus
,
policy
->
cpus
,
cpu_present_mask
);
cpumask_and
(
policy
->
real_cpus
,
policy
->
cpus
,
cpu_present_mask
);
}
/*
/*
* affected cpus must always be the one, which are online. We aren't
* affected cpus must always be the one, which are online. We aren't
...
@@ -1326,7 +1247,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
...
@@ -1326,7 +1247,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
*/
*/
cpumask_and
(
policy
->
cpus
,
policy
->
cpus
,
cpu_online_mask
);
cpumask_and
(
policy
->
cpus
,
policy
->
cpus
,
cpu_online_mask
);
if
(
!
recover
_policy
)
{
if
(
new
_policy
)
{
policy
->
user_policy
.
min
=
policy
->
min
;
policy
->
user_policy
.
min
=
policy
->
min
;
policy
->
user_policy
.
max
=
policy
->
max
;
policy
->
user_policy
.
max
=
policy
->
max
;
...
@@ -1340,7 +1261,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
...
@@ -1340,7 +1261,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
policy
->
cur
=
cpufreq_driver
->
get
(
policy
->
cpu
);
policy
->
cur
=
cpufreq_driver
->
get
(
policy
->
cpu
);
if
(
!
policy
->
cur
)
{
if
(
!
policy
->
cur
)
{
pr_err
(
"%s: ->get() failed
\n
"
,
__func__
);
pr_err
(
"%s: ->get() failed
\n
"
,
__func__
);
goto
err_get_freq
;
goto
out_exit_policy
;
}
}
}
}
...
@@ -1387,10 +1308,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
...
@@ -1387,10 +1308,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
blocking_notifier_call_chain
(
&
cpufreq_policy_notifier_list
,
blocking_notifier_call_chain
(
&
cpufreq_policy_notifier_list
,
CPUFREQ_START
,
policy
);
CPUFREQ_START
,
policy
);
if
(
!
recover
_policy
)
{
if
(
new
_policy
)
{
ret
=
cpufreq_add_dev_interface
(
policy
,
dev
);
ret
=
cpufreq_add_dev_interface
(
policy
);
if
(
ret
)
if
(
ret
)
goto
err_out_unregister
;
goto
out_exit_policy
;
blocking_notifier_call_chain
(
&
cpufreq_policy_notifier_list
,
blocking_notifier_call_chain
(
&
cpufreq_policy_notifier_list
,
CPUFREQ_CREATE_POLICY
,
policy
);
CPUFREQ_CREATE_POLICY
,
policy
);
...
@@ -1399,9 +1320,16 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
...
@@ -1399,9 +1320,16 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
}
}
cpufreq_init_policy
(
policy
);
ret
=
cpufreq_init_policy
(
policy
);
if
(
ret
)
{
pr_err
(
"%s: Failed to initialize policy for cpu: %d (%d)
\n
"
,
__func__
,
cpu
,
ret
);
/* cpufreq_policy_free() will notify based on this */
new_policy
=
false
;
goto
out_exit_policy
;
}
if
(
!
recover
_policy
)
{
if
(
new
_policy
)
{
policy
->
user_policy
.
policy
=
policy
->
policy
;
policy
->
user_policy
.
policy
=
policy
->
policy
;
policy
->
user_policy
.
governor
=
policy
->
governor
;
policy
->
user_policy
.
governor
=
policy
->
governor
;
}
}
...
@@ -1409,8 +1337,6 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
...
@@ -1409,8 +1337,6 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
kobject_uevent
(
&
policy
->
kobj
,
KOBJ_ADD
);
kobject_uevent
(
&
policy
->
kobj
,
KOBJ_ADD
);
up_read
(
&
cpufreq_rwsem
);
/* Callback for handling stuff after policy is ready */
/* Callback for handling stuff after policy is ready */
if
(
cpufreq_driver
->
ready
)
if
(
cpufreq_driver
->
ready
)
cpufreq_driver
->
ready
(
policy
);
cpufreq_driver
->
ready
(
policy
);
...
@@ -1419,24 +1345,47 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
...
@@ -1419,24 +1345,47 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
return
0
;
return
0
;
err_out_unregister:
out_exit_policy:
err_get_freq:
up_write
(
&
policy
->
rwsem
);
up_write
(
&
policy
->
rwsem
);
if
(
cpufreq_driver
->
exit
)
if
(
cpufreq_driver
->
exit
)
cpufreq_driver
->
exit
(
policy
);
cpufreq_driver
->
exit
(
policy
);
err_set_policy_cpu:
out_free_policy:
cpufreq_policy_free
(
policy
,
recover_policy
);
cpufreq_policy_free
(
policy
,
!
new_policy
);
nomem_out:
return
ret
;
up_read
(
&
cpufreq_rwsem
);
}
/**
* cpufreq_add_dev - the cpufreq interface for a CPU device.
* @dev: CPU device.
* @sif: Subsystem interface structure pointer (not used)
*/
static
int
cpufreq_add_dev
(
struct
device
*
dev
,
struct
subsys_interface
*
sif
)
{
unsigned
cpu
=
dev
->
id
;
int
ret
;
dev_dbg
(
dev
,
"%s: adding CPU%u
\n
"
,
__func__
,
cpu
);
if
(
cpu_online
(
cpu
))
{
ret
=
cpufreq_online
(
cpu
);
}
else
{
/*
* A hotplug notifier will follow and we will handle it as CPU
* online then. For now, just create the sysfs link, unless
* there is no policy or the link is already present.
*/
struct
cpufreq_policy
*
policy
=
per_cpu
(
cpufreq_cpu_data
,
cpu
);
ret
=
policy
&&
!
cpumask_test_and_set_cpu
(
cpu
,
policy
->
real_cpus
)
?
add_cpu_dev_symlink
(
policy
,
cpu
)
:
0
;
}
return
ret
;
return
ret
;
}
}
static
int
__cpufreq_remove_dev_prepare
(
struct
device
*
dev
)
static
void
cpufreq_offline_prepare
(
unsigned
int
cpu
)
{
{
unsigned
int
cpu
=
dev
->
id
;
int
ret
=
0
;
struct
cpufreq_policy
*
policy
;
struct
cpufreq_policy
*
policy
;
pr_debug
(
"%s: unregistering CPU %u
\n
"
,
__func__
,
cpu
);
pr_debug
(
"%s: unregistering CPU %u
\n
"
,
__func__
,
cpu
);
...
@@ -1444,11 +1393,11 @@ static int __cpufreq_remove_dev_prepare(struct device *dev)
...
@@ -1444,11 +1393,11 @@ static int __cpufreq_remove_dev_prepare(struct device *dev)
policy
=
cpufreq_cpu_get_raw
(
cpu
);
policy
=
cpufreq_cpu_get_raw
(
cpu
);
if
(
!
policy
)
{
if
(
!
policy
)
{
pr_debug
(
"%s: No cpu_data found
\n
"
,
__func__
);
pr_debug
(
"%s: No cpu_data found
\n
"
,
__func__
);
return
-
EINVAL
;
return
;
}
}
if
(
has_target
())
{
if
(
has_target
())
{
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_STOP
);
int
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_STOP
);
if
(
ret
)
if
(
ret
)
pr_err
(
"%s: Failed to stop governor
\n
"
,
__func__
);
pr_err
(
"%s: Failed to stop governor
\n
"
,
__func__
);
}
}
...
@@ -1469,7 +1418,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev)
...
@@ -1469,7 +1418,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev)
/* Start governor again for active policy */
/* Start governor again for active policy */
if
(
!
policy_is_inactive
(
policy
))
{
if
(
!
policy_is_inactive
(
policy
))
{
if
(
has_target
())
{
if
(
has_target
())
{
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_START
);
int
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_START
);
if
(
!
ret
)
if
(
!
ret
)
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_LIMITS
);
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_LIMITS
);
...
@@ -1479,28 +1428,24 @@ static int __cpufreq_remove_dev_prepare(struct device *dev)
...
@@ -1479,28 +1428,24 @@ static int __cpufreq_remove_dev_prepare(struct device *dev)
}
else
if
(
cpufreq_driver
->
stop_cpu
)
{
}
else
if
(
cpufreq_driver
->
stop_cpu
)
{
cpufreq_driver
->
stop_cpu
(
policy
);
cpufreq_driver
->
stop_cpu
(
policy
);
}
}
return
ret
;
}
}
static
int
__cpufreq_remove_dev_finish
(
struct
device
*
dev
)
static
void
cpufreq_offline_finish
(
unsigned
int
cpu
)
{
{
unsigned
int
cpu
=
dev
->
id
;
int
ret
;
struct
cpufreq_policy
*
policy
=
per_cpu
(
cpufreq_cpu_data
,
cpu
);
struct
cpufreq_policy
*
policy
=
per_cpu
(
cpufreq_cpu_data
,
cpu
);
if
(
!
policy
)
{
if
(
!
policy
)
{
pr_debug
(
"%s: No cpu_data found
\n
"
,
__func__
);
pr_debug
(
"%s: No cpu_data found
\n
"
,
__func__
);
return
-
EINVAL
;
return
;
}
}
/* Only proceed for inactive policies */
/* Only proceed for inactive policies */
if
(
!
policy_is_inactive
(
policy
))
if
(
!
policy_is_inactive
(
policy
))
return
0
;
return
;
/* If cpu is last user of policy, free policy */
/* If cpu is last user of policy, free policy */
if
(
has_target
())
{
if
(
has_target
())
{
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_POLICY_EXIT
);
int
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_POLICY_EXIT
);
if
(
ret
)
if
(
ret
)
pr_err
(
"%s: Failed to exit governor
\n
"
,
__func__
);
pr_err
(
"%s: Failed to exit governor
\n
"
,
__func__
);
}
}
...
@@ -1512,8 +1457,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev)
...
@@ -1512,8 +1457,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev)
*/
*/
if
(
cpufreq_driver
->
exit
)
if
(
cpufreq_driver
->
exit
)
cpufreq_driver
->
exit
(
policy
);
cpufreq_driver
->
exit
(
policy
);
return
0
;
}
}
/**
/**
...
@@ -1530,8 +1473,8 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
...
@@ -1530,8 +1473,8 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
return
0
;
return
0
;
if
(
cpu_online
(
cpu
))
{
if
(
cpu_online
(
cpu
))
{
__cpufreq_remove_dev_prepare
(
dev
);
cpufreq_offline_prepare
(
cpu
);
__cpufreq_remove_dev_finish
(
dev
);
cpufreq_offline_finish
(
cpu
);
}
}
cpumask_clear_cpu
(
cpu
,
policy
->
real_cpus
);
cpumask_clear_cpu
(
cpu
,
policy
->
real_cpus
);
...
@@ -2247,7 +2190,11 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
...
@@ -2247,7 +2190,11 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
memcpy
(
&
new_policy
->
cpuinfo
,
&
policy
->
cpuinfo
,
sizeof
(
policy
->
cpuinfo
));
memcpy
(
&
new_policy
->
cpuinfo
,
&
policy
->
cpuinfo
,
sizeof
(
policy
->
cpuinfo
));
if
(
new_policy
->
min
>
policy
->
max
||
new_policy
->
max
<
policy
->
min
)
/*
* This check works well when we store new min/max freq attributes,
* because new_policy is a copy of policy with one field updated.
*/
if
(
new_policy
->
min
>
new_policy
->
max
)
return
-
EINVAL
;
return
-
EINVAL
;
/* verify the cpu speed can be set within this limit */
/* verify the cpu speed can be set within this limit */
...
@@ -2296,16 +2243,31 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
...
@@ -2296,16 +2243,31 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
old_gov
=
policy
->
governor
;
old_gov
=
policy
->
governor
;
/* end old governor */
/* end old governor */
if
(
old_gov
)
{
if
(
old_gov
)
{
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_STOP
);
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_STOP
);
if
(
ret
)
{
/* This can happen due to race with other operations */
pr_debug
(
"%s: Failed to Stop Governor: %s (%d)
\n
"
,
__func__
,
old_gov
->
name
,
ret
);
return
ret
;
}
up_write
(
&
policy
->
rwsem
);
up_write
(
&
policy
->
rwsem
);
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_POLICY_EXIT
);
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_POLICY_EXIT
);
down_write
(
&
policy
->
rwsem
);
down_write
(
&
policy
->
rwsem
);
if
(
ret
)
{
pr_err
(
"%s: Failed to Exit Governor: %s (%d)
\n
"
,
__func__
,
old_gov
->
name
,
ret
);
return
ret
;
}
}
}
/* start new governor */
/* start new governor */
policy
->
governor
=
new_policy
->
governor
;
policy
->
governor
=
new_policy
->
governor
;
if
(
!
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_POLICY_INIT
))
{
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_POLICY_INIT
);
if
(
!
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_START
))
if
(
!
ret
)
{
ret
=
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_START
);
if
(
!
ret
)
goto
out
;
goto
out
;
up_write
(
&
policy
->
rwsem
);
up_write
(
&
policy
->
rwsem
);
...
@@ -2317,11 +2279,13 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
...
@@ -2317,11 +2279,13 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
pr_debug
(
"starting governor %s failed
\n
"
,
policy
->
governor
->
name
);
pr_debug
(
"starting governor %s failed
\n
"
,
policy
->
governor
->
name
);
if
(
old_gov
)
{
if
(
old_gov
)
{
policy
->
governor
=
old_gov
;
policy
->
governor
=
old_gov
;
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_POLICY_INIT
);
if
(
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_POLICY_INIT
))
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_START
);
policy
->
governor
=
NULL
;
else
__cpufreq_governor
(
policy
,
CPUFREQ_GOV_START
);
}
}
return
-
EINVAL
;
return
ret
;
out:
out:
pr_debug
(
"governor: change or update limits
\n
"
);
pr_debug
(
"governor: change or update limits
\n
"
);
...
@@ -2387,27 +2351,23 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
...
@@ -2387,27 +2351,23 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
unsigned
long
action
,
void
*
hcpu
)
unsigned
long
action
,
void
*
hcpu
)
{
{
unsigned
int
cpu
=
(
unsigned
long
)
hcpu
;
unsigned
int
cpu
=
(
unsigned
long
)
hcpu
;
struct
device
*
dev
;
dev
=
get_cpu_device
(
cpu
);
switch
(
action
&
~
CPU_TASKS_FROZEN
)
{
if
(
dev
)
{
case
CPU_ONLINE
:
switch
(
action
&
~
CPU_TASKS_FROZEN
)
{
cpufreq_online
(
cpu
);
case
CPU_ONLINE
:
break
;
cpufreq_add_dev
(
dev
,
NULL
);
break
;
case
CPU_DOWN_PREPARE
:
case
CPU_DOWN_PREPARE
:
__cpufreq_remove_dev_prepare
(
dev
);
cpufreq_offline_prepare
(
cpu
);
break
;
break
;
case
CPU_POST_DEAD
:
case
CPU_POST_DEAD
:
__cpufreq_remove_dev_finish
(
dev
);
cpufreq_offline_finish
(
cpu
);
break
;
break
;
case
CPU_DOWN_FAILED
:
case
CPU_DOWN_FAILED
:
cpufreq_add_dev
(
dev
,
NULL
);
cpufreq_online
(
cpu
);
break
;
break
;
}
}
}
return
NOTIFY_OK
;
return
NOTIFY_OK
;
}
}
...
@@ -2515,10 +2475,14 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
...
@@ -2515,10 +2475,14 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
pr_debug
(
"trying to register driver %s
\n
"
,
driver_data
->
name
);
pr_debug
(
"trying to register driver %s
\n
"
,
driver_data
->
name
);
/* Protect against concurrent CPU online/offline. */
get_online_cpus
();
write_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
write_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
if
(
cpufreq_driver
)
{
if
(
cpufreq_driver
)
{
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
return
-
EEXIST
;
ret
=
-
EEXIST
;
goto
out
;
}
}
cpufreq_driver
=
driver_data
;
cpufreq_driver
=
driver_data
;
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
...
@@ -2557,7 +2521,10 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
...
@@ -2557,7 +2521,10 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
register_hotcpu_notifier
(
&
cpufreq_cpu_notifier
);
register_hotcpu_notifier
(
&
cpufreq_cpu_notifier
);
pr_debug
(
"driver %s up and running
\n
"
,
driver_data
->
name
);
pr_debug
(
"driver %s up and running
\n
"
,
driver_data
->
name
);
return
0
;
out:
put_online_cpus
();
return
ret
;
err_if_unreg:
err_if_unreg:
subsys_interface_unregister
(
&
cpufreq_interface
);
subsys_interface_unregister
(
&
cpufreq_interface
);
err_boost_unreg:
err_boost_unreg:
...
@@ -2567,7 +2534,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
...
@@ -2567,7 +2534,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
write_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
write_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
cpufreq_driver
=
NULL
;
cpufreq_driver
=
NULL
;
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
return
re
t
;
goto
ou
t
;
}
}
EXPORT_SYMBOL_GPL
(
cpufreq_register_driver
);
EXPORT_SYMBOL_GPL
(
cpufreq_register_driver
);
...
@@ -2588,19 +2555,20 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
...
@@ -2588,19 +2555,20 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
pr_debug
(
"unregistering driver %s
\n
"
,
driver
->
name
);
pr_debug
(
"unregistering driver %s
\n
"
,
driver
->
name
);
/* Protect against concurrent cpu hotplug */
get_online_cpus
();
subsys_interface_unregister
(
&
cpufreq_interface
);
subsys_interface_unregister
(
&
cpufreq_interface
);
if
(
cpufreq_boost_supported
())
if
(
cpufreq_boost_supported
())
cpufreq_sysfs_remove_file
(
&
boost
.
attr
);
cpufreq_sysfs_remove_file
(
&
boost
.
attr
);
unregister_hotcpu_notifier
(
&
cpufreq_cpu_notifier
);
unregister_hotcpu_notifier
(
&
cpufreq_cpu_notifier
);
down_write
(
&
cpufreq_rwsem
);
write_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
write_lock_irqsave
(
&
cpufreq_driver_lock
,
flags
);
cpufreq_driver
=
NULL
;
cpufreq_driver
=
NULL
;
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
write_unlock_irqrestore
(
&
cpufreq_driver_lock
,
flags
);
up_write
(
&
cpufreq_rwsem
);
put_online_cpus
(
);
return
0
;
return
0
;
}
}
...
...
drivers/cpufreq/cpufreq_conservative.c
浏览文件 @
2dc36ecf
...
@@ -47,7 +47,7 @@ static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
...
@@ -47,7 +47,7 @@ static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
static
void
cs_check_cpu
(
int
cpu
,
unsigned
int
load
)
static
void
cs_check_cpu
(
int
cpu
,
unsigned
int
load
)
{
{
struct
cs_cpu_dbs_info_s
*
dbs_info
=
&
per_cpu
(
cs_cpu_dbs_info
,
cpu
);
struct
cs_cpu_dbs_info_s
*
dbs_info
=
&
per_cpu
(
cs_cpu_dbs_info
,
cpu
);
struct
cpufreq_policy
*
policy
=
dbs_info
->
cdbs
.
cur_
policy
;
struct
cpufreq_policy
*
policy
=
dbs_info
->
cdbs
.
shared
->
policy
;
struct
dbs_data
*
dbs_data
=
policy
->
governor_data
;
struct
dbs_data
*
dbs_data
=
policy
->
governor_data
;
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
...
@@ -102,26 +102,15 @@ static void cs_check_cpu(int cpu, unsigned int load)
...
@@ -102,26 +102,15 @@ static void cs_check_cpu(int cpu, unsigned int load)
}
}
}
}
static
void
cs_dbs_timer
(
struct
work_struct
*
work
)
static
unsigned
int
cs_dbs_timer
(
struct
cpu_dbs_info
*
cdbs
,
struct
dbs_data
*
dbs_data
,
bool
modify_all
)
{
{
struct
cs_cpu_dbs_info_s
*
dbs_info
=
container_of
(
work
,
struct
cs_cpu_dbs_info_s
,
cdbs
.
work
.
work
);
unsigned
int
cpu
=
dbs_info
->
cdbs
.
cur_policy
->
cpu
;
struct
cs_cpu_dbs_info_s
*
core_dbs_info
=
&
per_cpu
(
cs_cpu_dbs_info
,
cpu
);
struct
dbs_data
*
dbs_data
=
dbs_info
->
cdbs
.
cur_policy
->
governor_data
;
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
int
delay
=
delay_for_sampling_rate
(
cs_tuners
->
sampling_rate
);
bool
modify_all
=
true
;
mutex_lock
(
&
core_dbs_info
->
cdbs
.
timer_mutex
);
if
(
modify_all
)
if
(
!
need_load_eval
(
&
core_dbs_info
->
cdbs
,
cs_tuners
->
sampling_rate
))
dbs_check_cpu
(
dbs_data
,
cdbs
->
shared
->
policy
->
cpu
);
modify_all
=
false
;
else
dbs_check_cpu
(
dbs_data
,
cpu
);
gov_queue_work
(
dbs_data
,
dbs_info
->
cdbs
.
cur_policy
,
delay
,
modify_all
);
return
delay_for_sampling_rate
(
cs_tuners
->
sampling_rate
);
mutex_unlock
(
&
core_dbs_info
->
cdbs
.
timer_mutex
);
}
}
static
int
dbs_cpufreq_notifier
(
struct
notifier_block
*
nb
,
unsigned
long
val
,
static
int
dbs_cpufreq_notifier
(
struct
notifier_block
*
nb
,
unsigned
long
val
,
...
@@ -135,7 +124,7 @@ static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
...
@@ -135,7 +124,7 @@ static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
if
(
!
dbs_info
->
enable
)
if
(
!
dbs_info
->
enable
)
return
0
;
return
0
;
policy
=
dbs_info
->
cdbs
.
cur_
policy
;
policy
=
dbs_info
->
cdbs
.
shared
->
policy
;
/*
/*
* we only care if our internally tracked freq moves outside the 'valid'
* we only care if our internally tracked freq moves outside the 'valid'
...
...
drivers/cpufreq/cpufreq_governor.c
浏览文件 @
2dc36ecf
...
@@ -32,10 +32,10 @@ static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data)
...
@@ -32,10 +32,10 @@ static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data)
void
dbs_check_cpu
(
struct
dbs_data
*
dbs_data
,
int
cpu
)
void
dbs_check_cpu
(
struct
dbs_data
*
dbs_data
,
int
cpu
)
{
{
struct
cpu_dbs_
common_
info
*
cdbs
=
dbs_data
->
cdata
->
get_cpu_cdbs
(
cpu
);
struct
cpu_dbs_info
*
cdbs
=
dbs_data
->
cdata
->
get_cpu_cdbs
(
cpu
);
struct
od_dbs_tuners
*
od_tuners
=
dbs_data
->
tuners
;
struct
od_dbs_tuners
*
od_tuners
=
dbs_data
->
tuners
;
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
struct
cpufreq_policy
*
policy
;
struct
cpufreq_policy
*
policy
=
cdbs
->
shared
->
policy
;
unsigned
int
sampling_rate
;
unsigned
int
sampling_rate
;
unsigned
int
max_load
=
0
;
unsigned
int
max_load
=
0
;
unsigned
int
ignore_nice
;
unsigned
int
ignore_nice
;
...
@@ -60,11 +60,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
...
@@ -60,11 +60,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
ignore_nice
=
cs_tuners
->
ignore_nice_load
;
ignore_nice
=
cs_tuners
->
ignore_nice_load
;
}
}
policy
=
cdbs
->
cur_policy
;
/* Get Absolute Load */
/* Get Absolute Load */
for_each_cpu
(
j
,
policy
->
cpus
)
{
for_each_cpu
(
j
,
policy
->
cpus
)
{
struct
cpu_dbs_
common_
info
*
j_cdbs
;
struct
cpu_dbs_info
*
j_cdbs
;
u64
cur_wall_time
,
cur_idle_time
;
u64
cur_wall_time
,
cur_idle_time
;
unsigned
int
idle_time
,
wall_time
;
unsigned
int
idle_time
,
wall_time
;
unsigned
int
load
;
unsigned
int
load
;
...
@@ -163,9 +161,9 @@ EXPORT_SYMBOL_GPL(dbs_check_cpu);
...
@@ -163,9 +161,9 @@ EXPORT_SYMBOL_GPL(dbs_check_cpu);
static
inline
void
__gov_queue_work
(
int
cpu
,
struct
dbs_data
*
dbs_data
,
static
inline
void
__gov_queue_work
(
int
cpu
,
struct
dbs_data
*
dbs_data
,
unsigned
int
delay
)
unsigned
int
delay
)
{
{
struct
cpu_dbs_
common_
info
*
cdbs
=
dbs_data
->
cdata
->
get_cpu_cdbs
(
cpu
);
struct
cpu_dbs_info
*
cdbs
=
dbs_data
->
cdata
->
get_cpu_cdbs
(
cpu
);
mod_delayed_work_on
(
cpu
,
system_wq
,
&
cdbs
->
work
,
delay
);
mod_delayed_work_on
(
cpu
,
system_wq
,
&
cdbs
->
d
work
,
delay
);
}
}
void
gov_queue_work
(
struct
dbs_data
*
dbs_data
,
struct
cpufreq_policy
*
policy
,
void
gov_queue_work
(
struct
dbs_data
*
dbs_data
,
struct
cpufreq_policy
*
policy
,
...
@@ -199,33 +197,63 @@ EXPORT_SYMBOL_GPL(gov_queue_work);
...
@@ -199,33 +197,63 @@ EXPORT_SYMBOL_GPL(gov_queue_work);
static
inline
void
gov_cancel_work
(
struct
dbs_data
*
dbs_data
,
static
inline
void
gov_cancel_work
(
struct
dbs_data
*
dbs_data
,
struct
cpufreq_policy
*
policy
)
struct
cpufreq_policy
*
policy
)
{
{
struct
cpu_dbs_
common_
info
*
cdbs
;
struct
cpu_dbs_info
*
cdbs
;
int
i
;
int
i
;
for_each_cpu
(
i
,
policy
->
cpus
)
{
for_each_cpu
(
i
,
policy
->
cpus
)
{
cdbs
=
dbs_data
->
cdata
->
get_cpu_cdbs
(
i
);
cdbs
=
dbs_data
->
cdata
->
get_cpu_cdbs
(
i
);
cancel_delayed_work_sync
(
&
cdbs
->
work
);
cancel_delayed_work_sync
(
&
cdbs
->
d
work
);
}
}
}
}
/* Will return if we need to evaluate cpu load again or not */
/* Will return if we need to evaluate cpu load again or not */
bool
need_load_eval
(
struct
cpu_dbs_common_info
*
cdbs
,
static
bool
need_load_eval
(
struct
cpu_common_dbs_info
*
shared
,
unsigned
int
sampling_rate
)
unsigned
int
sampling_rate
)
{
{
if
(
policy_is_shared
(
cdbs
->
cur_
policy
))
{
if
(
policy_is_shared
(
shared
->
policy
))
{
ktime_t
time_now
=
ktime_get
();
ktime_t
time_now
=
ktime_get
();
s64
delta_us
=
ktime_us_delta
(
time_now
,
cdbs
->
time_stamp
);
s64
delta_us
=
ktime_us_delta
(
time_now
,
shared
->
time_stamp
);
/* Do nothing if we recently have sampled */
/* Do nothing if we recently have sampled */
if
(
delta_us
<
(
s64
)(
sampling_rate
/
2
))
if
(
delta_us
<
(
s64
)(
sampling_rate
/
2
))
return
false
;
return
false
;
else
else
cdbs
->
time_stamp
=
time_now
;
shared
->
time_stamp
=
time_now
;
}
}
return
true
;
return
true
;
}
}
EXPORT_SYMBOL_GPL
(
need_load_eval
);
static
void
dbs_timer
(
struct
work_struct
*
work
)
{
struct
cpu_dbs_info
*
cdbs
=
container_of
(
work
,
struct
cpu_dbs_info
,
dwork
.
work
);
struct
cpu_common_dbs_info
*
shared
=
cdbs
->
shared
;
struct
cpufreq_policy
*
policy
=
shared
->
policy
;
struct
dbs_data
*
dbs_data
=
policy
->
governor_data
;
unsigned
int
sampling_rate
,
delay
;
bool
modify_all
=
true
;
mutex_lock
(
&
shared
->
timer_mutex
);
if
(
dbs_data
->
cdata
->
governor
==
GOV_CONSERVATIVE
)
{
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
sampling_rate
=
cs_tuners
->
sampling_rate
;
}
else
{
struct
od_dbs_tuners
*
od_tuners
=
dbs_data
->
tuners
;
sampling_rate
=
od_tuners
->
sampling_rate
;
}
if
(
!
need_load_eval
(
cdbs
->
shared
,
sampling_rate
))
modify_all
=
false
;
delay
=
dbs_data
->
cdata
->
gov_dbs_timer
(
cdbs
,
dbs_data
,
modify_all
);
gov_queue_work
(
dbs_data
,
policy
,
delay
,
modify_all
);
mutex_unlock
(
&
shared
->
timer_mutex
);
}
static
void
set_sampling_rate
(
struct
dbs_data
*
dbs_data
,
static
void
set_sampling_rate
(
struct
dbs_data
*
dbs_data
,
unsigned
int
sampling_rate
)
unsigned
int
sampling_rate
)
...
@@ -239,6 +267,37 @@ static void set_sampling_rate(struct dbs_data *dbs_data,
...
@@ -239,6 +267,37 @@ static void set_sampling_rate(struct dbs_data *dbs_data,
}
}
}
}
static
int
alloc_common_dbs_info
(
struct
cpufreq_policy
*
policy
,
struct
common_dbs_data
*
cdata
)
{
struct
cpu_common_dbs_info
*
shared
;
int
j
;
/* Allocate memory for the common information for policy->cpus */
shared
=
kzalloc
(
sizeof
(
*
shared
),
GFP_KERNEL
);
if
(
!
shared
)
return
-
ENOMEM
;
/* Set shared for all CPUs, online+offline */
for_each_cpu
(
j
,
policy
->
related_cpus
)
cdata
->
get_cpu_cdbs
(
j
)
->
shared
=
shared
;
return
0
;
}
static
void
free_common_dbs_info
(
struct
cpufreq_policy
*
policy
,
struct
common_dbs_data
*
cdata
)
{
struct
cpu_dbs_info
*
cdbs
=
cdata
->
get_cpu_cdbs
(
policy
->
cpu
);
struct
cpu_common_dbs_info
*
shared
=
cdbs
->
shared
;
int
j
;
for_each_cpu
(
j
,
policy
->
cpus
)
cdata
->
get_cpu_cdbs
(
j
)
->
shared
=
NULL
;
kfree
(
shared
);
}
static
int
cpufreq_governor_init
(
struct
cpufreq_policy
*
policy
,
static
int
cpufreq_governor_init
(
struct
cpufreq_policy
*
policy
,
struct
dbs_data
*
dbs_data
,
struct
dbs_data
*
dbs_data
,
struct
common_dbs_data
*
cdata
)
struct
common_dbs_data
*
cdata
)
...
@@ -246,9 +305,18 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy,
...
@@ -246,9 +305,18 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy,
unsigned
int
latency
;
unsigned
int
latency
;
int
ret
;
int
ret
;
/* State should be equivalent to EXIT */
if
(
policy
->
governor_data
)
return
-
EBUSY
;
if
(
dbs_data
)
{
if
(
dbs_data
)
{
if
(
WARN_ON
(
have_governor_per_policy
()))
if
(
WARN_ON
(
have_governor_per_policy
()))
return
-
EINVAL
;
return
-
EINVAL
;
ret
=
alloc_common_dbs_info
(
policy
,
cdata
);
if
(
ret
)
return
ret
;
dbs_data
->
usage_count
++
;
dbs_data
->
usage_count
++
;
policy
->
governor_data
=
dbs_data
;
policy
->
governor_data
=
dbs_data
;
return
0
;
return
0
;
...
@@ -258,12 +326,16 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy,
...
@@ -258,12 +326,16 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy,
if
(
!
dbs_data
)
if
(
!
dbs_data
)
return
-
ENOMEM
;
return
-
ENOMEM
;
ret
=
alloc_common_dbs_info
(
policy
,
cdata
);
if
(
ret
)
goto
free_dbs_data
;
dbs_data
->
cdata
=
cdata
;
dbs_data
->
cdata
=
cdata
;
dbs_data
->
usage_count
=
1
;
dbs_data
->
usage_count
=
1
;
ret
=
cdata
->
init
(
dbs_data
,
!
policy
->
governor
->
initialized
);
ret
=
cdata
->
init
(
dbs_data
,
!
policy
->
governor
->
initialized
);
if
(
ret
)
if
(
ret
)
goto
free_
dbs_data
;
goto
free_
common_dbs_info
;
/* policy latency is in ns. Convert it to us first */
/* policy latency is in ns. Convert it to us first */
latency
=
policy
->
cpuinfo
.
transition_latency
/
1000
;
latency
=
policy
->
cpuinfo
.
transition_latency
/
1000
;
...
@@ -300,15 +372,22 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy,
...
@@ -300,15 +372,22 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy,
}
}
cdata_exit:
cdata_exit:
cdata
->
exit
(
dbs_data
,
!
policy
->
governor
->
initialized
);
cdata
->
exit
(
dbs_data
,
!
policy
->
governor
->
initialized
);
free_common_dbs_info:
free_common_dbs_info
(
policy
,
cdata
);
free_dbs_data:
free_dbs_data:
kfree
(
dbs_data
);
kfree
(
dbs_data
);
return
ret
;
return
ret
;
}
}
static
void
cpufreq_governor_exit
(
struct
cpufreq_policy
*
policy
,
static
int
cpufreq_governor_exit
(
struct
cpufreq_policy
*
policy
,
struct
dbs_data
*
dbs_data
)
struct
dbs_data
*
dbs_data
)
{
{
struct
common_dbs_data
*
cdata
=
dbs_data
->
cdata
;
struct
common_dbs_data
*
cdata
=
dbs_data
->
cdata
;
struct
cpu_dbs_info
*
cdbs
=
cdata
->
get_cpu_cdbs
(
policy
->
cpu
);
/* State should be equivalent to INIT */
if
(
!
cdbs
->
shared
||
cdbs
->
shared
->
policy
)
return
-
EBUSY
;
policy
->
governor_data
=
NULL
;
policy
->
governor_data
=
NULL
;
if
(
!--
dbs_data
->
usage_count
)
{
if
(
!--
dbs_data
->
usage_count
)
{
...
@@ -323,6 +402,9 @@ static void cpufreq_governor_exit(struct cpufreq_policy *policy,
...
@@ -323,6 +402,9 @@ static void cpufreq_governor_exit(struct cpufreq_policy *policy,
cdata
->
exit
(
dbs_data
,
policy
->
governor
->
initialized
==
1
);
cdata
->
exit
(
dbs_data
,
policy
->
governor
->
initialized
==
1
);
kfree
(
dbs_data
);
kfree
(
dbs_data
);
}
}
free_common_dbs_info
(
policy
,
cdata
);
return
0
;
}
}
static
int
cpufreq_governor_start
(
struct
cpufreq_policy
*
policy
,
static
int
cpufreq_governor_start
(
struct
cpufreq_policy
*
policy
,
...
@@ -330,12 +412,17 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
...
@@ -330,12 +412,17 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
{
{
struct
common_dbs_data
*
cdata
=
dbs_data
->
cdata
;
struct
common_dbs_data
*
cdata
=
dbs_data
->
cdata
;
unsigned
int
sampling_rate
,
ignore_nice
,
j
,
cpu
=
policy
->
cpu
;
unsigned
int
sampling_rate
,
ignore_nice
,
j
,
cpu
=
policy
->
cpu
;
struct
cpu_dbs_common_info
*
cpu_cdbs
=
cdata
->
get_cpu_cdbs
(
cpu
);
struct
cpu_dbs_info
*
cdbs
=
cdata
->
get_cpu_cdbs
(
cpu
);
struct
cpu_common_dbs_info
*
shared
=
cdbs
->
shared
;
int
io_busy
=
0
;
int
io_busy
=
0
;
if
(
!
policy
->
cur
)
if
(
!
policy
->
cur
)
return
-
EINVAL
;
return
-
EINVAL
;
/* State should be equivalent to INIT */
if
(
!
shared
||
shared
->
policy
)
return
-
EBUSY
;
if
(
cdata
->
governor
==
GOV_CONSERVATIVE
)
{
if
(
cdata
->
governor
==
GOV_CONSERVATIVE
)
{
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
struct
cs_dbs_tuners
*
cs_tuners
=
dbs_data
->
tuners
;
...
@@ -349,12 +436,14 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
...
@@ -349,12 +436,14 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
io_busy
=
od_tuners
->
io_is_busy
;
io_busy
=
od_tuners
->
io_is_busy
;
}
}
shared
->
policy
=
policy
;
shared
->
time_stamp
=
ktime_get
();
mutex_init
(
&
shared
->
timer_mutex
);
for_each_cpu
(
j
,
policy
->
cpus
)
{
for_each_cpu
(
j
,
policy
->
cpus
)
{
struct
cpu_dbs_
common_
info
*
j_cdbs
=
cdata
->
get_cpu_cdbs
(
j
);
struct
cpu_dbs_info
*
j_cdbs
=
cdata
->
get_cpu_cdbs
(
j
);
unsigned
int
prev_load
;
unsigned
int
prev_load
;
j_cdbs
->
cpu
=
j
;
j_cdbs
->
cur_policy
=
policy
;
j_cdbs
->
prev_cpu_idle
=
j_cdbs
->
prev_cpu_idle
=
get_cpu_idle_time
(
j
,
&
j_cdbs
->
prev_cpu_wall
,
io_busy
);
get_cpu_idle_time
(
j
,
&
j_cdbs
->
prev_cpu_wall
,
io_busy
);
...
@@ -366,8 +455,7 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
...
@@ -366,8 +455,7 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
if
(
ignore_nice
)
if
(
ignore_nice
)
j_cdbs
->
prev_cpu_nice
=
kcpustat_cpu
(
j
).
cpustat
[
CPUTIME_NICE
];
j_cdbs
->
prev_cpu_nice
=
kcpustat_cpu
(
j
).
cpustat
[
CPUTIME_NICE
];
mutex_init
(
&
j_cdbs
->
timer_mutex
);
INIT_DEFERRABLE_WORK
(
&
j_cdbs
->
dwork
,
dbs_timer
);
INIT_DEFERRABLE_WORK
(
&
j_cdbs
->
work
,
cdata
->
gov_dbs_timer
);
}
}
if
(
cdata
->
governor
==
GOV_CONSERVATIVE
)
{
if
(
cdata
->
governor
==
GOV_CONSERVATIVE
)
{
...
@@ -386,20 +474,24 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
...
@@ -386,20 +474,24 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
od_ops
->
powersave_bias_init_cpu
(
cpu
);
od_ops
->
powersave_bias_init_cpu
(
cpu
);
}
}
/* Initiate timer time stamp */
cpu_cdbs
->
time_stamp
=
ktime_get
();
gov_queue_work
(
dbs_data
,
policy
,
delay_for_sampling_rate
(
sampling_rate
),
gov_queue_work
(
dbs_data
,
policy
,
delay_for_sampling_rate
(
sampling_rate
),
true
);
true
);
return
0
;
return
0
;
}
}
static
void
cpufreq_governor_stop
(
struct
cpufreq_policy
*
policy
,
static
int
cpufreq_governor_stop
(
struct
cpufreq_policy
*
policy
,
struct
dbs_data
*
dbs_data
)
struct
dbs_data
*
dbs_data
)
{
{
struct
common_dbs_data
*
cdata
=
dbs_data
->
cdata
;
struct
common_dbs_data
*
cdata
=
dbs_data
->
cdata
;
unsigned
int
cpu
=
policy
->
cpu
;
unsigned
int
cpu
=
policy
->
cpu
;
struct
cpu_dbs_common_info
*
cpu_cdbs
=
cdata
->
get_cpu_cdbs
(
cpu
);
struct
cpu_dbs_info
*
cdbs
=
cdata
->
get_cpu_cdbs
(
cpu
);
struct
cpu_common_dbs_info
*
shared
=
cdbs
->
shared
;
/* State should be equivalent to START */
if
(
!
shared
||
!
shared
->
policy
)
return
-
EBUSY
;
gov_cancel_work
(
dbs_data
,
policy
);
if
(
cdata
->
governor
==
GOV_CONSERVATIVE
)
{
if
(
cdata
->
governor
==
GOV_CONSERVATIVE
)
{
struct
cs_cpu_dbs_info_s
*
cs_dbs_info
=
struct
cs_cpu_dbs_info_s
*
cs_dbs_info
=
...
@@ -408,38 +500,40 @@ static void cpufreq_governor_stop(struct cpufreq_policy *policy,
...
@@ -408,38 +500,40 @@ static void cpufreq_governor_stop(struct cpufreq_policy *policy,
cs_dbs_info
->
enable
=
0
;
cs_dbs_info
->
enable
=
0
;
}
}
gov_cancel_work
(
dbs_data
,
policy
);
shared
->
policy
=
NULL
;
mutex_destroy
(
&
shared
->
timer_mutex
);
mutex_destroy
(
&
cpu_cdbs
->
timer_mutex
);
return
0
;
cpu_cdbs
->
cur_policy
=
NULL
;
}
}
static
void
cpufreq_governor_limits
(
struct
cpufreq_policy
*
policy
,
static
int
cpufreq_governor_limits
(
struct
cpufreq_policy
*
policy
,
struct
dbs_data
*
dbs_data
)
struct
dbs_data
*
dbs_data
)
{
{
struct
common_dbs_data
*
cdata
=
dbs_data
->
cdata
;
struct
common_dbs_data
*
cdata
=
dbs_data
->
cdata
;
unsigned
int
cpu
=
policy
->
cpu
;
unsigned
int
cpu
=
policy
->
cpu
;
struct
cpu_dbs_
common_info
*
cpu_
cdbs
=
cdata
->
get_cpu_cdbs
(
cpu
);
struct
cpu_dbs_
info
*
cdbs
=
cdata
->
get_cpu_cdbs
(
cpu
);
if
(
!
cpu_cdbs
->
cur_policy
)
/* State should be equivalent to START */
return
;
if
(
!
cdbs
->
shared
||
!
cdbs
->
shared
->
policy
)
return
-
EBUSY
;
mutex_lock
(
&
c
pu_cdbs
->
timer_mutex
);
mutex_lock
(
&
c
dbs
->
shared
->
timer_mutex
);
if
(
policy
->
max
<
c
pu_cdbs
->
cur_
policy
->
cur
)
if
(
policy
->
max
<
c
dbs
->
shared
->
policy
->
cur
)
__cpufreq_driver_target
(
c
pu_cdbs
->
cur_
policy
,
policy
->
max
,
__cpufreq_driver_target
(
c
dbs
->
shared
->
policy
,
policy
->
max
,
CPUFREQ_RELATION_H
);
CPUFREQ_RELATION_H
);
else
if
(
policy
->
min
>
c
pu_cdbs
->
cur_
policy
->
cur
)
else
if
(
policy
->
min
>
c
dbs
->
shared
->
policy
->
cur
)
__cpufreq_driver_target
(
c
pu_cdbs
->
cur_
policy
,
policy
->
min
,
__cpufreq_driver_target
(
c
dbs
->
shared
->
policy
,
policy
->
min
,
CPUFREQ_RELATION_L
);
CPUFREQ_RELATION_L
);
dbs_check_cpu
(
dbs_data
,
cpu
);
dbs_check_cpu
(
dbs_data
,
cpu
);
mutex_unlock
(
&
cpu_cdbs
->
timer_mutex
);
mutex_unlock
(
&
cdbs
->
shared
->
timer_mutex
);
return
0
;
}
}
int
cpufreq_governor_dbs
(
struct
cpufreq_policy
*
policy
,
int
cpufreq_governor_dbs
(
struct
cpufreq_policy
*
policy
,
struct
common_dbs_data
*
cdata
,
unsigned
int
event
)
struct
common_dbs_data
*
cdata
,
unsigned
int
event
)
{
{
struct
dbs_data
*
dbs_data
;
struct
dbs_data
*
dbs_data
;
int
ret
=
0
;
int
ret
;
/* Lock governor to block concurrent initialization of governor */
/* Lock governor to block concurrent initialization of governor */
mutex_lock
(
&
cdata
->
mutex
);
mutex_lock
(
&
cdata
->
mutex
);
...
@@ -449,7 +543,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
...
@@ -449,7 +543,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
else
else
dbs_data
=
cdata
->
gdbs_data
;
dbs_data
=
cdata
->
gdbs_data
;
if
(
WARN_ON
(
!
dbs_data
&&
(
event
!=
CPUFREQ_GOV_POLICY_INIT
)
))
{
if
(
!
dbs_data
&&
(
event
!=
CPUFREQ_GOV_POLICY_INIT
))
{
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
goto
unlock
;
goto
unlock
;
}
}
...
@@ -459,17 +553,19 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
...
@@ -459,17 +553,19 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
ret
=
cpufreq_governor_init
(
policy
,
dbs_data
,
cdata
);
ret
=
cpufreq_governor_init
(
policy
,
dbs_data
,
cdata
);
break
;
break
;
case
CPUFREQ_GOV_POLICY_EXIT
:
case
CPUFREQ_GOV_POLICY_EXIT
:
cpufreq_governor_exit
(
policy
,
dbs_data
);
ret
=
cpufreq_governor_exit
(
policy
,
dbs_data
);
break
;
break
;
case
CPUFREQ_GOV_START
:
case
CPUFREQ_GOV_START
:
ret
=
cpufreq_governor_start
(
policy
,
dbs_data
);
ret
=
cpufreq_governor_start
(
policy
,
dbs_data
);
break
;
break
;
case
CPUFREQ_GOV_STOP
:
case
CPUFREQ_GOV_STOP
:
cpufreq_governor_stop
(
policy
,
dbs_data
);
ret
=
cpufreq_governor_stop
(
policy
,
dbs_data
);
break
;
break
;
case
CPUFREQ_GOV_LIMITS
:
case
CPUFREQ_GOV_LIMITS
:
cpufreq_governor_limits
(
policy
,
dbs_data
);
ret
=
cpufreq_governor_limits
(
policy
,
dbs_data
);
break
;
break
;
default:
ret
=
-
EINVAL
;
}
}
unlock:
unlock:
...
...
drivers/cpufreq/cpufreq_governor.h
浏览文件 @
2dc36ecf
...
@@ -109,7 +109,7 @@ store_one(_gov, file_name)
...
@@ -109,7 +109,7 @@ store_one(_gov, file_name)
/* create helper routines */
/* create helper routines */
#define define_get_cpu_dbs_routines(_dbs_info) \
#define define_get_cpu_dbs_routines(_dbs_info) \
static struct cpu_dbs_
common_info *get_cpu_cdbs(int cpu)
\
static struct cpu_dbs_
info *get_cpu_cdbs(int cpu)
\
{ \
{ \
return &per_cpu(_dbs_info, cpu).cdbs; \
return &per_cpu(_dbs_info, cpu).cdbs; \
} \
} \
...
@@ -128,9 +128,20 @@ static void *get_cpu_dbs_info_s(int cpu) \
...
@@ -128,9 +128,20 @@ static void *get_cpu_dbs_info_s(int cpu) \
* cs_*: Conservative governor
* cs_*: Conservative governor
*/
*/
/* Common to all CPUs of a policy */
struct
cpu_common_dbs_info
{
struct
cpufreq_policy
*
policy
;
/*
* percpu mutex that serializes governor limit change with dbs_timer
* invocation. We do not want dbs_timer to run when user is changing
* the governor or limits.
*/
struct
mutex
timer_mutex
;
ktime_t
time_stamp
;
};
/* Per cpu structures */
/* Per cpu structures */
struct
cpu_dbs_common_info
{
struct
cpu_dbs_info
{
int
cpu
;
u64
prev_cpu_idle
;
u64
prev_cpu_idle
;
u64
prev_cpu_wall
;
u64
prev_cpu_wall
;
u64
prev_cpu_nice
;
u64
prev_cpu_nice
;
...
@@ -141,19 +152,12 @@ struct cpu_dbs_common_info {
...
@@ -141,19 +152,12 @@ struct cpu_dbs_common_info {
* wake-up from idle.
* wake-up from idle.
*/
*/
unsigned
int
prev_load
;
unsigned
int
prev_load
;
struct
cpufreq_policy
*
cur_policy
;
struct
delayed_work
dwork
;
struct
delayed_work
work
;
struct
cpu_common_dbs_info
*
shared
;
/*
* percpu mutex that serializes governor limit change with gov_dbs_timer
* invocation. We do not want gov_dbs_timer to run when user is changing
* the governor or limits.
*/
struct
mutex
timer_mutex
;
ktime_t
time_stamp
;
};
};
struct
od_cpu_dbs_info_s
{
struct
od_cpu_dbs_info_s
{
struct
cpu_dbs_
common_
info
cdbs
;
struct
cpu_dbs_info
cdbs
;
struct
cpufreq_frequency_table
*
freq_table
;
struct
cpufreq_frequency_table
*
freq_table
;
unsigned
int
freq_lo
;
unsigned
int
freq_lo
;
unsigned
int
freq_lo_jiffies
;
unsigned
int
freq_lo_jiffies
;
...
@@ -163,7 +167,7 @@ struct od_cpu_dbs_info_s {
...
@@ -163,7 +167,7 @@ struct od_cpu_dbs_info_s {
};
};
struct
cs_cpu_dbs_info_s
{
struct
cs_cpu_dbs_info_s
{
struct
cpu_dbs_
common_
info
cdbs
;
struct
cpu_dbs_info
cdbs
;
unsigned
int
down_skip
;
unsigned
int
down_skip
;
unsigned
int
requested_freq
;
unsigned
int
requested_freq
;
unsigned
int
enable
:
1
;
unsigned
int
enable
:
1
;
...
@@ -204,9 +208,11 @@ struct common_dbs_data {
...
@@ -204,9 +208,11 @@ struct common_dbs_data {
*/
*/
struct
dbs_data
*
gdbs_data
;
struct
dbs_data
*
gdbs_data
;
struct
cpu_dbs_
common_
info
*
(
*
get_cpu_cdbs
)(
int
cpu
);
struct
cpu_dbs_info
*
(
*
get_cpu_cdbs
)(
int
cpu
);
void
*
(
*
get_cpu_dbs_info_s
)(
int
cpu
);
void
*
(
*
get_cpu_dbs_info_s
)(
int
cpu
);
void
(
*
gov_dbs_timer
)(
struct
work_struct
*
work
);
unsigned
int
(
*
gov_dbs_timer
)(
struct
cpu_dbs_info
*
cdbs
,
struct
dbs_data
*
dbs_data
,
bool
modify_all
);
void
(
*
gov_check_cpu
)(
int
cpu
,
unsigned
int
load
);
void
(
*
gov_check_cpu
)(
int
cpu
,
unsigned
int
load
);
int
(
*
init
)(
struct
dbs_data
*
dbs_data
,
bool
notify
);
int
(
*
init
)(
struct
dbs_data
*
dbs_data
,
bool
notify
);
void
(
*
exit
)(
struct
dbs_data
*
dbs_data
,
bool
notify
);
void
(
*
exit
)(
struct
dbs_data
*
dbs_data
,
bool
notify
);
...
@@ -265,8 +271,6 @@ static ssize_t show_sampling_rate_min_gov_pol \
...
@@ -265,8 +271,6 @@ static ssize_t show_sampling_rate_min_gov_pol \
extern
struct
mutex
cpufreq_governor_lock
;
extern
struct
mutex
cpufreq_governor_lock
;
void
dbs_check_cpu
(
struct
dbs_data
*
dbs_data
,
int
cpu
);
void
dbs_check_cpu
(
struct
dbs_data
*
dbs_data
,
int
cpu
);
bool
need_load_eval
(
struct
cpu_dbs_common_info
*
cdbs
,
unsigned
int
sampling_rate
);
int
cpufreq_governor_dbs
(
struct
cpufreq_policy
*
policy
,
int
cpufreq_governor_dbs
(
struct
cpufreq_policy
*
policy
,
struct
common_dbs_data
*
cdata
,
unsigned
int
event
);
struct
common_dbs_data
*
cdata
,
unsigned
int
event
);
void
gov_queue_work
(
struct
dbs_data
*
dbs_data
,
struct
cpufreq_policy
*
policy
,
void
gov_queue_work
(
struct
dbs_data
*
dbs_data
,
struct
cpufreq_policy
*
policy
,
...
...
drivers/cpufreq/cpufreq_ondemand.c
浏览文件 @
2dc36ecf
...
@@ -155,7 +155,7 @@ static void dbs_freq_increase(struct cpufreq_policy *policy, unsigned int freq)
...
@@ -155,7 +155,7 @@ static void dbs_freq_increase(struct cpufreq_policy *policy, unsigned int freq)
static
void
od_check_cpu
(
int
cpu
,
unsigned
int
load
)
static
void
od_check_cpu
(
int
cpu
,
unsigned
int
load
)
{
{
struct
od_cpu_dbs_info_s
*
dbs_info
=
&
per_cpu
(
od_cpu_dbs_info
,
cpu
);
struct
od_cpu_dbs_info_s
*
dbs_info
=
&
per_cpu
(
od_cpu_dbs_info
,
cpu
);
struct
cpufreq_policy
*
policy
=
dbs_info
->
cdbs
.
cur_
policy
;
struct
cpufreq_policy
*
policy
=
dbs_info
->
cdbs
.
shared
->
policy
;
struct
dbs_data
*
dbs_data
=
policy
->
governor_data
;
struct
dbs_data
*
dbs_data
=
policy
->
governor_data
;
struct
od_dbs_tuners
*
od_tuners
=
dbs_data
->
tuners
;
struct
od_dbs_tuners
*
od_tuners
=
dbs_data
->
tuners
;
...
@@ -191,46 +191,40 @@ static void od_check_cpu(int cpu, unsigned int load)
...
@@ -191,46 +191,40 @@ static void od_check_cpu(int cpu, unsigned int load)
}
}
}
}
static
void
od_dbs_timer
(
struct
work_struct
*
work
)
static
unsigned
int
od_dbs_timer
(
struct
cpu_dbs_info
*
cdbs
,
struct
dbs_data
*
dbs_data
,
bool
modify_all
)
{
{
struct
od_cpu_dbs_info_s
*
dbs_info
=
struct
cpufreq_policy
*
policy
=
cdbs
->
shared
->
policy
;
container_of
(
work
,
struct
od_cpu_dbs_info_s
,
cdbs
.
work
.
work
);
unsigned
int
cpu
=
policy
->
cpu
;
unsigned
int
cpu
=
dbs_info
->
cdbs
.
cur_policy
->
cpu
;
struct
od_cpu_dbs_info_s
*
dbs_info
=
&
per_cpu
(
od_cpu_dbs_info
,
struct
od_cpu_dbs_info_s
*
core_dbs_info
=
&
per_cpu
(
od_cpu_dbs_info
,
cpu
);
cpu
);
struct
dbs_data
*
dbs_data
=
dbs_info
->
cdbs
.
cur_policy
->
governor_data
;
struct
od_dbs_tuners
*
od_tuners
=
dbs_data
->
tuners
;
struct
od_dbs_tuners
*
od_tuners
=
dbs_data
->
tuners
;
int
delay
=
0
,
sample_type
=
core_dbs_info
->
sample_type
;
int
delay
=
0
,
sample_type
=
dbs_info
->
sample_type
;
bool
modify_all
=
true
;
mutex_lock
(
&
core_dbs_info
->
cdbs
.
timer_mutex
);
if
(
!
modify_all
)
if
(
!
need_load_eval
(
&
core_dbs_info
->
cdbs
,
od_tuners
->
sampling_rate
))
{
modify_all
=
false
;
goto
max_delay
;
goto
max_delay
;
}
/* Common NORMAL_SAMPLE setup */
/* Common NORMAL_SAMPLE setup */
core_
dbs_info
->
sample_type
=
OD_NORMAL_SAMPLE
;
dbs_info
->
sample_type
=
OD_NORMAL_SAMPLE
;
if
(
sample_type
==
OD_SUB_SAMPLE
)
{
if
(
sample_type
==
OD_SUB_SAMPLE
)
{
delay
=
core_
dbs_info
->
freq_lo_jiffies
;
delay
=
dbs_info
->
freq_lo_jiffies
;
__cpufreq_driver_target
(
core_dbs_info
->
cdbs
.
cur_policy
,
__cpufreq_driver_target
(
policy
,
dbs_info
->
freq_lo
,
core_dbs_info
->
freq_lo
,
CPUFREQ_RELATION_H
);
CPUFREQ_RELATION_H
);
}
else
{
}
else
{
dbs_check_cpu
(
dbs_data
,
cpu
);
dbs_check_cpu
(
dbs_data
,
cpu
);
if
(
core_
dbs_info
->
freq_lo
)
{
if
(
dbs_info
->
freq_lo
)
{
/* Setup timer for SUB_SAMPLE */
/* Setup timer for SUB_SAMPLE */
core_
dbs_info
->
sample_type
=
OD_SUB_SAMPLE
;
dbs_info
->
sample_type
=
OD_SUB_SAMPLE
;
delay
=
core_
dbs_info
->
freq_hi_jiffies
;
delay
=
dbs_info
->
freq_hi_jiffies
;
}
}
}
}
max_delay:
max_delay:
if
(
!
delay
)
if
(
!
delay
)
delay
=
delay_for_sampling_rate
(
od_tuners
->
sampling_rate
delay
=
delay_for_sampling_rate
(
od_tuners
->
sampling_rate
*
core_
dbs_info
->
rate_mult
);
*
dbs_info
->
rate_mult
);
gov_queue_work
(
dbs_data
,
dbs_info
->
cdbs
.
cur_policy
,
delay
,
modify_all
);
return
delay
;
mutex_unlock
(
&
core_dbs_info
->
cdbs
.
timer_mutex
);
}
}
/************************** sysfs interface ************************/
/************************** sysfs interface ************************/
...
@@ -273,27 +267,27 @@ static void update_sampling_rate(struct dbs_data *dbs_data,
...
@@ -273,27 +267,27 @@ static void update_sampling_rate(struct dbs_data *dbs_data,
dbs_info
=
&
per_cpu
(
od_cpu_dbs_info
,
cpu
);
dbs_info
=
&
per_cpu
(
od_cpu_dbs_info
,
cpu
);
cpufreq_cpu_put
(
policy
);
cpufreq_cpu_put
(
policy
);
mutex_lock
(
&
dbs_info
->
cdbs
.
timer_mutex
);
mutex_lock
(
&
dbs_info
->
cdbs
.
shared
->
timer_mutex
);
if
(
!
delayed_work_pending
(
&
dbs_info
->
cdbs
.
work
))
{
if
(
!
delayed_work_pending
(
&
dbs_info
->
cdbs
.
d
work
))
{
mutex_unlock
(
&
dbs_info
->
cdbs
.
timer_mutex
);
mutex_unlock
(
&
dbs_info
->
cdbs
.
shared
->
timer_mutex
);
continue
;
continue
;
}
}
next_sampling
=
jiffies
+
usecs_to_jiffies
(
new_rate
);
next_sampling
=
jiffies
+
usecs_to_jiffies
(
new_rate
);
appointed_at
=
dbs_info
->
cdbs
.
work
.
timer
.
expires
;
appointed_at
=
dbs_info
->
cdbs
.
d
work
.
timer
.
expires
;
if
(
time_before
(
next_sampling
,
appointed_at
))
{
if
(
time_before
(
next_sampling
,
appointed_at
))
{
mutex_unlock
(
&
dbs_info
->
cdbs
.
timer_mutex
);
mutex_unlock
(
&
dbs_info
->
cdbs
.
shared
->
timer_mutex
);
cancel_delayed_work_sync
(
&
dbs_info
->
cdbs
.
work
);
cancel_delayed_work_sync
(
&
dbs_info
->
cdbs
.
d
work
);
mutex_lock
(
&
dbs_info
->
cdbs
.
timer_mutex
);
mutex_lock
(
&
dbs_info
->
cdbs
.
shared
->
timer_mutex
);
gov_queue_work
(
dbs_data
,
dbs_info
->
cdbs
.
cur_
policy
,
gov_queue_work
(
dbs_data
,
policy
,
usecs_to_jiffies
(
new_rate
),
true
);
usecs_to_jiffies
(
new_rate
),
true
);
}
}
mutex_unlock
(
&
dbs_info
->
cdbs
.
timer_mutex
);
mutex_unlock
(
&
dbs_info
->
cdbs
.
shared
->
timer_mutex
);
}
}
}
}
...
@@ -556,13 +550,16 @@ static void od_set_powersave_bias(unsigned int powersave_bias)
...
@@ -556,13 +550,16 @@ static void od_set_powersave_bias(unsigned int powersave_bias)
get_online_cpus
();
get_online_cpus
();
for_each_online_cpu
(
cpu
)
{
for_each_online_cpu
(
cpu
)
{
struct
cpu_common_dbs_info
*
shared
;
if
(
cpumask_test_cpu
(
cpu
,
&
done
))
if
(
cpumask_test_cpu
(
cpu
,
&
done
))
continue
;
continue
;
policy
=
per_cpu
(
od_cpu_dbs_info
,
cpu
).
cdbs
.
cur_policy
;
shared
=
per_cpu
(
od_cpu_dbs_info
,
cpu
).
cdbs
.
shared
;
if
(
!
policy
)
if
(
!
shared
)
continue
;
continue
;
policy
=
shared
->
policy
;
cpumask_or
(
&
done
,
&
done
,
policy
->
cpus
);
cpumask_or
(
&
done
,
&
done
,
policy
->
cpus
);
if
(
policy
->
governor
!=
&
cpufreq_gov_ondemand
)
if
(
policy
->
governor
!=
&
cpufreq_gov_ondemand
)
...
...
drivers/cpufreq/e_powersaver.c
浏览文件 @
2dc36ecf
...
@@ -78,7 +78,7 @@ static int eps_acpi_init(void)
...
@@ -78,7 +78,7 @@ static int eps_acpi_init(void)
static
int
eps_acpi_exit
(
struct
cpufreq_policy
*
policy
)
static
int
eps_acpi_exit
(
struct
cpufreq_policy
*
policy
)
{
{
if
(
eps_acpi_cpu_perf
)
{
if
(
eps_acpi_cpu_perf
)
{
acpi_processor_unregister_performance
(
eps_acpi_cpu_perf
,
0
);
acpi_processor_unregister_performance
(
0
);
free_cpumask_var
(
eps_acpi_cpu_perf
->
shared_cpu_map
);
free_cpumask_var
(
eps_acpi_cpu_perf
->
shared_cpu_map
);
kfree
(
eps_acpi_cpu_perf
);
kfree
(
eps_acpi_cpu_perf
);
eps_acpi_cpu_perf
=
NULL
;
eps_acpi_cpu_perf
=
NULL
;
...
...
drivers/cpufreq/ia64-acpi-cpufreq.c
浏览文件 @
2dc36ecf
...
@@ -29,7 +29,6 @@ MODULE_LICENSE("GPL");
...
@@ -29,7 +29,6 @@ MODULE_LICENSE("GPL");
struct
cpufreq_acpi_io
{
struct
cpufreq_acpi_io
{
struct
acpi_processor_performance
acpi_data
;
struct
acpi_processor_performance
acpi_data
;
struct
cpufreq_frequency_table
*
freq_table
;
unsigned
int
resume
;
unsigned
int
resume
;
};
};
...
@@ -221,6 +220,7 @@ acpi_cpufreq_cpu_init (
...
@@ -221,6 +220,7 @@ acpi_cpufreq_cpu_init (
unsigned
int
cpu
=
policy
->
cpu
;
unsigned
int
cpu
=
policy
->
cpu
;
struct
cpufreq_acpi_io
*
data
;
struct
cpufreq_acpi_io
*
data
;
unsigned
int
result
=
0
;
unsigned
int
result
=
0
;
struct
cpufreq_frequency_table
*
freq_table
;
pr_debug
(
"acpi_cpufreq_cpu_init
\n
"
);
pr_debug
(
"acpi_cpufreq_cpu_init
\n
"
);
...
@@ -254,10 +254,10 @@ acpi_cpufreq_cpu_init (
...
@@ -254,10 +254,10 @@ acpi_cpufreq_cpu_init (
}
}
/* alloc freq_table */
/* alloc freq_table */
data
->
freq_table
=
kzalloc
(
sizeof
(
*
data
->
freq_table
)
*
freq_table
=
kzalloc
(
sizeof
(
*
freq_table
)
*
(
data
->
acpi_data
.
state_count
+
1
),
(
data
->
acpi_data
.
state_count
+
1
),
GFP_KERNEL
);
GFP_KERNEL
);
if
(
!
data
->
freq_table
)
{
if
(
!
freq_table
)
{
result
=
-
ENOMEM
;
result
=
-
ENOMEM
;
goto
err_unreg
;
goto
err_unreg
;
}
}
...
@@ -276,14 +276,14 @@ acpi_cpufreq_cpu_init (
...
@@ -276,14 +276,14 @@ acpi_cpufreq_cpu_init (
for
(
i
=
0
;
i
<=
data
->
acpi_data
.
state_count
;
i
++
)
for
(
i
=
0
;
i
<=
data
->
acpi_data
.
state_count
;
i
++
)
{
{
if
(
i
<
data
->
acpi_data
.
state_count
)
{
if
(
i
<
data
->
acpi_data
.
state_count
)
{
data
->
freq_table
[
i
].
frequency
=
freq_table
[
i
].
frequency
=
data
->
acpi_data
.
states
[
i
].
core_frequency
*
1000
;
data
->
acpi_data
.
states
[
i
].
core_frequency
*
1000
;
}
else
{
}
else
{
data
->
freq_table
[
i
].
frequency
=
CPUFREQ_TABLE_END
;
freq_table
[
i
].
frequency
=
CPUFREQ_TABLE_END
;
}
}
}
}
result
=
cpufreq_table_validate_and_show
(
policy
,
data
->
freq_table
);
result
=
cpufreq_table_validate_and_show
(
policy
,
freq_table
);
if
(
result
)
{
if
(
result
)
{
goto
err_freqfree
;
goto
err_freqfree
;
}
}
...
@@ -311,9 +311,9 @@ acpi_cpufreq_cpu_init (
...
@@ -311,9 +311,9 @@ acpi_cpufreq_cpu_init (
return
(
result
);
return
(
result
);
err_freqfree:
err_freqfree:
kfree
(
data
->
freq_table
);
kfree
(
freq_table
);
err_unreg:
err_unreg:
acpi_processor_unregister_performance
(
&
data
->
acpi_data
,
cpu
);
acpi_processor_unregister_performance
(
cpu
);
err_free:
err_free:
kfree
(
data
);
kfree
(
data
);
acpi_io_data
[
cpu
]
=
NULL
;
acpi_io_data
[
cpu
]
=
NULL
;
...
@@ -332,8 +332,8 @@ acpi_cpufreq_cpu_exit (
...
@@ -332,8 +332,8 @@ acpi_cpufreq_cpu_exit (
if
(
data
)
{
if
(
data
)
{
acpi_io_data
[
policy
->
cpu
]
=
NULL
;
acpi_io_data
[
policy
->
cpu
]
=
NULL
;
acpi_processor_unregister_performance
(
&
data
->
acpi_data
,
acpi_processor_unregister_performance
(
policy
->
cpu
);
policy
->
cpu
);
kfree
(
policy
->
freq_table
);
kfree
(
data
);
kfree
(
data
);
}
}
...
...
drivers/cpufreq/integrator-cpufreq.c
浏览文件 @
2dc36ecf
...
@@ -98,11 +98,10 @@ static int integrator_set_target(struct cpufreq_policy *policy,
...
@@ -98,11 +98,10 @@ static int integrator_set_target(struct cpufreq_policy *policy,
/* get current setting */
/* get current setting */
cm_osc
=
__raw_readl
(
cm_base
+
INTEGRATOR_HDR_OSC_OFFSET
);
cm_osc
=
__raw_readl
(
cm_base
+
INTEGRATOR_HDR_OSC_OFFSET
);
if
(
machine_is_integrator
())
{
if
(
machine_is_integrator
())
vco
.
s
=
(
cm_osc
>>
8
)
&
7
;
vco
.
s
=
(
cm_osc
>>
8
)
&
7
;
}
else
if
(
machine_is_cintegrator
())
{
else
if
(
machine_is_cintegrator
())
vco
.
s
=
1
;
vco
.
s
=
1
;
}
vco
.
v
=
cm_osc
&
255
;
vco
.
v
=
cm_osc
&
255
;
vco
.
r
=
22
;
vco
.
r
=
22
;
freqs
.
old
=
icst_hz
(
&
cclk_params
,
vco
)
/
1000
;
freqs
.
old
=
icst_hz
(
&
cclk_params
,
vco
)
/
1000
;
...
@@ -163,11 +162,10 @@ static unsigned int integrator_get(unsigned int cpu)
...
@@ -163,11 +162,10 @@ static unsigned int integrator_get(unsigned int cpu)
/* detect memory etc. */
/* detect memory etc. */
cm_osc
=
__raw_readl
(
cm_base
+
INTEGRATOR_HDR_OSC_OFFSET
);
cm_osc
=
__raw_readl
(
cm_base
+
INTEGRATOR_HDR_OSC_OFFSET
);
if
(
machine_is_integrator
())
{
if
(
machine_is_integrator
())
vco
.
s
=
(
cm_osc
>>
8
)
&
7
;
vco
.
s
=
(
cm_osc
>>
8
)
&
7
;
}
else
{
else
vco
.
s
=
1
;
vco
.
s
=
1
;
}
vco
.
v
=
cm_osc
&
255
;
vco
.
v
=
cm_osc
&
255
;
vco
.
r
=
22
;
vco
.
r
=
22
;
...
@@ -203,7 +201,7 @@ static int __init integrator_cpufreq_probe(struct platform_device *pdev)
...
@@ -203,7 +201,7 @@ static int __init integrator_cpufreq_probe(struct platform_device *pdev)
struct
resource
*
res
;
struct
resource
*
res
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
if
(
!
res
)
return
-
ENODEV
;
return
-
ENODEV
;
cm_base
=
devm_ioremap
(
&
pdev
->
dev
,
res
->
start
,
resource_size
(
res
));
cm_base
=
devm_ioremap
(
&
pdev
->
dev
,
res
->
start
,
resource_size
(
res
));
...
@@ -234,6 +232,6 @@ static struct platform_driver integrator_cpufreq_driver = {
...
@@ -234,6 +232,6 @@ static struct platform_driver integrator_cpufreq_driver = {
module_platform_driver_probe
(
integrator_cpufreq_driver
,
module_platform_driver_probe
(
integrator_cpufreq_driver
,
integrator_cpufreq_probe
);
integrator_cpufreq_probe
);
MODULE_AUTHOR
(
"Russell M. King"
);
MODULE_AUTHOR
(
"Russell M. King"
);
MODULE_DESCRIPTION
(
"cpufreq driver for ARM Integrator CPUs"
);
MODULE_DESCRIPTION
(
"cpufreq driver for ARM Integrator CPUs"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
drivers/cpufreq/intel_pstate.c
浏览文件 @
2dc36ecf
...
@@ -484,12 +484,11 @@ static void __init intel_pstate_sysfs_expose_params(void)
...
@@ -484,12 +484,11 @@ static void __init intel_pstate_sysfs_expose_params(void)
}
}
/************************** sysfs end ************************/
/************************** sysfs end ************************/
static
void
intel_pstate_hwp_enable
(
void
)
static
void
intel_pstate_hwp_enable
(
struct
cpudata
*
cpudata
)
{
{
hwp_active
++
;
pr_info
(
"intel_pstate: HWP enabled
\n
"
);
pr_info
(
"intel_pstate: HWP enabled
\n
"
);
wrmsrl
(
MSR_PM_ENABLE
,
0x1
);
wrmsrl
_on_cpu
(
cpudata
->
cpu
,
MSR_PM_ENABLE
,
0x1
);
}
}
static
int
byt_get_min_pstate
(
void
)
static
int
byt_get_min_pstate
(
void
)
...
@@ -522,7 +521,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
...
@@ -522,7 +521,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
int32_t
vid_fp
;
int32_t
vid_fp
;
u32
vid
;
u32
vid
;
val
=
pstate
<<
8
;
val
=
(
u64
)
pstate
<<
8
;
if
(
limits
.
no_turbo
&&
!
limits
.
turbo_disabled
)
if
(
limits
.
no_turbo
&&
!
limits
.
turbo_disabled
)
val
|=
(
u64
)
1
<<
32
;
val
|=
(
u64
)
1
<<
32
;
...
@@ -611,7 +610,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate)
...
@@ -611,7 +610,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate)
{
{
u64
val
;
u64
val
;
val
=
pstate
<<
8
;
val
=
(
u64
)
pstate
<<
8
;
if
(
limits
.
no_turbo
&&
!
limits
.
turbo_disabled
)
if
(
limits
.
no_turbo
&&
!
limits
.
turbo_disabled
)
val
|=
(
u64
)
1
<<
32
;
val
|=
(
u64
)
1
<<
32
;
...
@@ -933,6 +932,10 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
...
@@ -933,6 +932,10 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
cpu
=
all_cpu_data
[
cpunum
];
cpu
=
all_cpu_data
[
cpunum
];
cpu
->
cpu
=
cpunum
;
cpu
->
cpu
=
cpunum
;
if
(
hwp_active
)
intel_pstate_hwp_enable
(
cpu
);
intel_pstate_get_cpu_pstates
(
cpu
);
intel_pstate_get_cpu_pstates
(
cpu
);
init_timer_deferrable
(
&
cpu
->
timer
);
init_timer_deferrable
(
&
cpu
->
timer
);
...
@@ -1246,7 +1249,7 @@ static int __init intel_pstate_init(void)
...
@@ -1246,7 +1249,7 @@ static int __init intel_pstate_init(void)
return
-
ENOMEM
;
return
-
ENOMEM
;
if
(
static_cpu_has_safe
(
X86_FEATURE_HWP
)
&&
!
no_hwp
)
if
(
static_cpu_has_safe
(
X86_FEATURE_HWP
)
&&
!
no_hwp
)
intel_pstate_hwp_enable
()
;
hwp_active
++
;
if
(
!
hwp_active
&&
hwp_only
)
if
(
!
hwp_active
&&
hwp_only
)
goto
out
;
goto
out
;
...
...
drivers/cpufreq/powernow-k7.c
浏览文件 @
2dc36ecf
...
@@ -421,7 +421,7 @@ static int powernow_acpi_init(void)
...
@@ -421,7 +421,7 @@ static int powernow_acpi_init(void)
return
0
;
return
0
;
err2:
err2:
acpi_processor_unregister_performance
(
acpi_processor_perf
,
0
);
acpi_processor_unregister_performance
(
0
);
err1:
err1:
free_cpumask_var
(
acpi_processor_perf
->
shared_cpu_map
);
free_cpumask_var
(
acpi_processor_perf
->
shared_cpu_map
);
err05:
err05:
...
@@ -661,7 +661,7 @@ static int powernow_cpu_exit(struct cpufreq_policy *policy)
...
@@ -661,7 +661,7 @@ static int powernow_cpu_exit(struct cpufreq_policy *policy)
{
{
#ifdef CONFIG_X86_POWERNOW_K7_ACPI
#ifdef CONFIG_X86_POWERNOW_K7_ACPI
if
(
acpi_processor_perf
)
{
if
(
acpi_processor_perf
)
{
acpi_processor_unregister_performance
(
acpi_processor_perf
,
0
);
acpi_processor_unregister_performance
(
0
);
free_cpumask_var
(
acpi_processor_perf
->
shared_cpu_map
);
free_cpumask_var
(
acpi_processor_perf
->
shared_cpu_map
);
kfree
(
acpi_processor_perf
);
kfree
(
acpi_processor_perf
);
}
}
...
...
drivers/cpufreq/powernow-k8.c
浏览文件 @
2dc36ecf
...
@@ -795,7 +795,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
...
@@ -795,7 +795,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
kfree
(
powernow_table
);
kfree
(
powernow_table
);
err_out:
err_out:
acpi_processor_unregister_performance
(
&
data
->
acpi_data
,
data
->
cpu
);
acpi_processor_unregister_performance
(
data
->
cpu
);
/* data->acpi_data.state_count informs us at ->exit()
/* data->acpi_data.state_count informs us at ->exit()
* whether ACPI was used */
* whether ACPI was used */
...
@@ -863,8 +863,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data,
...
@@ -863,8 +863,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data,
static
void
powernow_k8_cpu_exit_acpi
(
struct
powernow_k8_data
*
data
)
static
void
powernow_k8_cpu_exit_acpi
(
struct
powernow_k8_data
*
data
)
{
{
if
(
data
->
acpi_data
.
state_count
)
if
(
data
->
acpi_data
.
state_count
)
acpi_processor_unregister_performance
(
&
data
->
acpi_data
,
acpi_processor_unregister_performance
(
data
->
cpu
);
data
->
cpu
);
free_cpumask_var
(
data
->
acpi_data
.
shared_cpu_map
);
free_cpumask_var
(
data
->
acpi_data
.
shared_cpu_map
);
}
}
...
...
drivers/cpufreq/powernv-cpufreq.c
浏览文件 @
2dc36ecf
...
@@ -27,20 +27,31 @@
...
@@ -27,20 +27,31 @@
#include <linux/smp.h>
#include <linux/smp.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/reboot.h>
#include <linux/reboot.h>
#include <linux/slab.h>
#include <asm/cputhreads.h>
#include <asm/cputhreads.h>
#include <asm/firmware.h>
#include <asm/firmware.h>
#include <asm/reg.h>
#include <asm/reg.h>
#include <asm/smp.h>
/* Required for cpu_sibling_mask() in UP configs */
#include <asm/smp.h>
/* Required for cpu_sibling_mask() in UP configs */
#include <asm/opal.h>
#define POWERNV_MAX_PSTATES 256
#define POWERNV_MAX_PSTATES 256
#define PMSR_PSAFE_ENABLE (1UL << 30)
#define PMSR_PSAFE_ENABLE (1UL << 30)
#define PMSR_SPR_EM_DISABLE (1UL << 31)
#define PMSR_SPR_EM_DISABLE (1UL << 31)
#define PMSR_MAX(x) ((x >> 32) & 0xFF)
#define PMSR_MAX(x) ((x >> 32) & 0xFF)
#define PMSR_LP(x) ((x >> 48) & 0xFF)
static
struct
cpufreq_frequency_table
powernv_freqs
[
POWERNV_MAX_PSTATES
+
1
];
static
struct
cpufreq_frequency_table
powernv_freqs
[
POWERNV_MAX_PSTATES
+
1
];
static
bool
rebooting
,
throttled
;
static
bool
rebooting
,
throttled
,
occ_reset
;
static
struct
chip
{
unsigned
int
id
;
bool
throttled
;
cpumask_t
mask
;
struct
work_struct
throttle
;
bool
restore
;
}
*
chips
;
static
int
nr_chips
;
/*
/*
* Note: The set of pstates consists of contiguous integers, the
* Note: The set of pstates consists of contiguous integers, the
...
@@ -298,28 +309,35 @@ static inline unsigned int get_nominal_index(void)
...
@@ -298,28 +309,35 @@ static inline unsigned int get_nominal_index(void)
return
powernv_pstate_info
.
max
-
powernv_pstate_info
.
nominal
;
return
powernv_pstate_info
.
max
-
powernv_pstate_info
.
nominal
;
}
}
static
void
powernv_cpufreq_throttle_check
(
unsigned
int
cpu
)
static
void
powernv_cpufreq_throttle_check
(
void
*
data
)
{
{
unsigned
int
cpu
=
smp_processor_id
();
unsigned
long
pmsr
;
unsigned
long
pmsr
;
int
pmsr_pmax
,
pmsr_lp
;
int
pmsr_pmax
,
i
;
pmsr
=
get_pmspr
(
SPRN_PMSR
);
pmsr
=
get_pmspr
(
SPRN_PMSR
);
for
(
i
=
0
;
i
<
nr_chips
;
i
++
)
if
(
chips
[
i
].
id
==
cpu_to_chip_id
(
cpu
))
break
;
/* Check for Pmax Capping */
/* Check for Pmax Capping */
pmsr_pmax
=
(
s8
)
PMSR_MAX
(
pmsr
);
pmsr_pmax
=
(
s8
)
PMSR_MAX
(
pmsr
);
if
(
pmsr_pmax
!=
powernv_pstate_info
.
max
)
{
if
(
pmsr_pmax
!=
powernv_pstate_info
.
max
)
{
throttled
=
true
;
if
(
chips
[
i
].
throttled
)
pr_info
(
"CPU %d Pmax is reduced to %d
\n
"
,
cpu
,
pmsr_pmax
);
goto
next
;
pr_info
(
"Max allowed Pstate is capped
\n
"
);
chips
[
i
].
throttled
=
true
;
pr_info
(
"CPU %d on Chip %u has Pmax reduced to %d
\n
"
,
cpu
,
chips
[
i
].
id
,
pmsr_pmax
);
}
else
if
(
chips
[
i
].
throttled
)
{
chips
[
i
].
throttled
=
false
;
pr_info
(
"CPU %d on Chip %u has Pmax restored to %d
\n
"
,
cpu
,
chips
[
i
].
id
,
pmsr_pmax
);
}
}
/*
/* Check if Psafe_mode_active is set in PMSR. */
* Check for Psafe by reading LocalPstate
next:
* or check if Psafe_mode_active is set in PMSR.
if
(
pmsr
&
PMSR_PSAFE_ENABLE
)
{
*/
pmsr_lp
=
(
s8
)
PMSR_LP
(
pmsr
);
if
((
pmsr_lp
<
powernv_pstate_info
.
min
)
||
(
pmsr
&
PMSR_PSAFE_ENABLE
))
{
throttled
=
true
;
throttled
=
true
;
pr_info
(
"Pstate set to safe frequency
\n
"
);
pr_info
(
"Pstate set to safe frequency
\n
"
);
}
}
...
@@ -350,7 +368,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
...
@@ -350,7 +368,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
return
0
;
return
0
;
if
(
!
throttled
)
if
(
!
throttled
)
powernv_cpufreq_throttle_check
(
smp_processor_id
()
);
powernv_cpufreq_throttle_check
(
NULL
);
freq_data
.
pstate_id
=
powernv_freqs
[
new_index
].
driver_data
;
freq_data
.
pstate_id
=
powernv_freqs
[
new_index
].
driver_data
;
...
@@ -395,6 +413,118 @@ static struct notifier_block powernv_cpufreq_reboot_nb = {
...
@@ -395,6 +413,118 @@ static struct notifier_block powernv_cpufreq_reboot_nb = {
.
notifier_call
=
powernv_cpufreq_reboot_notifier
,
.
notifier_call
=
powernv_cpufreq_reboot_notifier
,
};
};
void
powernv_cpufreq_work_fn
(
struct
work_struct
*
work
)
{
struct
chip
*
chip
=
container_of
(
work
,
struct
chip
,
throttle
);
unsigned
int
cpu
;
cpumask_var_t
mask
;
smp_call_function_any
(
&
chip
->
mask
,
powernv_cpufreq_throttle_check
,
NULL
,
0
);
if
(
!
chip
->
restore
)
return
;
chip
->
restore
=
false
;
cpumask_copy
(
mask
,
&
chip
->
mask
);
for_each_cpu_and
(
cpu
,
mask
,
cpu_online_mask
)
{
int
index
,
tcpu
;
struct
cpufreq_policy
policy
;
cpufreq_get_policy
(
&
policy
,
cpu
);
cpufreq_frequency_table_target
(
&
policy
,
policy
.
freq_table
,
policy
.
cur
,
CPUFREQ_RELATION_C
,
&
index
);
powernv_cpufreq_target_index
(
&
policy
,
index
);
for_each_cpu
(
tcpu
,
policy
.
cpus
)
cpumask_clear_cpu
(
tcpu
,
mask
);
}
}
static
char
throttle_reason
[][
30
]
=
{
"No throttling"
,
"Power Cap"
,
"Processor Over Temperature"
,
"Power Supply Failure"
,
"Over Current"
,
"OCC Reset"
};
static
int
powernv_cpufreq_occ_msg
(
struct
notifier_block
*
nb
,
unsigned
long
msg_type
,
void
*
_msg
)
{
struct
opal_msg
*
msg
=
_msg
;
struct
opal_occ_msg
omsg
;
int
i
;
if
(
msg_type
!=
OPAL_MSG_OCC
)
return
0
;
omsg
.
type
=
be64_to_cpu
(
msg
->
params
[
0
]);
switch
(
omsg
.
type
)
{
case
OCC_RESET
:
occ_reset
=
true
;
/*
* powernv_cpufreq_throttle_check() is called in
* target() callback which can detect the throttle state
* for governors like ondemand.
* But static governors will not call target() often thus
* report throttling here.
*/
if
(
!
throttled
)
{
throttled
=
true
;
pr_crit
(
"CPU Frequency is throttled
\n
"
);
}
pr_info
(
"OCC: Reset
\n
"
);
break
;
case
OCC_LOAD
:
pr_info
(
"OCC: Loaded
\n
"
);
break
;
case
OCC_THROTTLE
:
omsg
.
chip
=
be64_to_cpu
(
msg
->
params
[
1
]);
omsg
.
throttle_status
=
be64_to_cpu
(
msg
->
params
[
2
]);
if
(
occ_reset
)
{
occ_reset
=
false
;
throttled
=
false
;
pr_info
(
"OCC: Active
\n
"
);
for
(
i
=
0
;
i
<
nr_chips
;
i
++
)
{
chips
[
i
].
restore
=
true
;
schedule_work
(
&
chips
[
i
].
throttle
);
}
return
0
;
}
if
(
omsg
.
throttle_status
&&
omsg
.
throttle_status
<=
OCC_MAX_THROTTLE_STATUS
)
pr_info
(
"OCC: Chip %u Pmax reduced due to %s
\n
"
,
(
unsigned
int
)
omsg
.
chip
,
throttle_reason
[
omsg
.
throttle_status
]);
else
if
(
!
omsg
.
throttle_status
)
pr_info
(
"OCC: Chip %u %s
\n
"
,
(
unsigned
int
)
omsg
.
chip
,
throttle_reason
[
omsg
.
throttle_status
]);
else
return
0
;
for
(
i
=
0
;
i
<
nr_chips
;
i
++
)
if
(
chips
[
i
].
id
==
omsg
.
chip
)
{
if
(
!
omsg
.
throttle_status
)
chips
[
i
].
restore
=
true
;
schedule_work
(
&
chips
[
i
].
throttle
);
}
}
return
0
;
}
static
struct
notifier_block
powernv_cpufreq_opal_nb
=
{
.
notifier_call
=
powernv_cpufreq_occ_msg
,
.
next
=
NULL
,
.
priority
=
0
,
};
static
void
powernv_cpufreq_stop_cpu
(
struct
cpufreq_policy
*
policy
)
static
void
powernv_cpufreq_stop_cpu
(
struct
cpufreq_policy
*
policy
)
{
{
struct
powernv_smp_call_data
freq_data
;
struct
powernv_smp_call_data
freq_data
;
...
@@ -414,6 +544,36 @@ static struct cpufreq_driver powernv_cpufreq_driver = {
...
@@ -414,6 +544,36 @@ static struct cpufreq_driver powernv_cpufreq_driver = {
.
attr
=
powernv_cpu_freq_attr
,
.
attr
=
powernv_cpu_freq_attr
,
};
};
static
int
init_chip_info
(
void
)
{
unsigned
int
chip
[
256
];
unsigned
int
cpu
,
i
;
unsigned
int
prev_chip_id
=
UINT_MAX
;
for_each_possible_cpu
(
cpu
)
{
unsigned
int
id
=
cpu_to_chip_id
(
cpu
);
if
(
prev_chip_id
!=
id
)
{
prev_chip_id
=
id
;
chip
[
nr_chips
++
]
=
id
;
}
}
chips
=
kmalloc_array
(
nr_chips
,
sizeof
(
struct
chip
),
GFP_KERNEL
);
if
(
!
chips
)
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
nr_chips
;
i
++
)
{
chips
[
i
].
id
=
chip
[
i
];
chips
[
i
].
throttled
=
false
;
cpumask_copy
(
&
chips
[
i
].
mask
,
cpumask_of_node
(
chip
[
i
]));
INIT_WORK
(
&
chips
[
i
].
throttle
,
powernv_cpufreq_work_fn
);
chips
[
i
].
restore
=
false
;
}
return
0
;
}
static
int
__init
powernv_cpufreq_init
(
void
)
static
int
__init
powernv_cpufreq_init
(
void
)
{
{
int
rc
=
0
;
int
rc
=
0
;
...
@@ -429,7 +589,13 @@ static int __init powernv_cpufreq_init(void)
...
@@ -429,7 +589,13 @@ static int __init powernv_cpufreq_init(void)
return
rc
;
return
rc
;
}
}
/* Populate chip info */
rc
=
init_chip_info
();
if
(
rc
)
return
rc
;
register_reboot_notifier
(
&
powernv_cpufreq_reboot_nb
);
register_reboot_notifier
(
&
powernv_cpufreq_reboot_nb
);
opal_message_notifier_register
(
OPAL_MSG_OCC
,
&
powernv_cpufreq_opal_nb
);
return
cpufreq_register_driver
(
&
powernv_cpufreq_driver
);
return
cpufreq_register_driver
(
&
powernv_cpufreq_driver
);
}
}
module_init
(
powernv_cpufreq_init
);
module_init
(
powernv_cpufreq_init
);
...
@@ -437,6 +603,8 @@ module_init(powernv_cpufreq_init);
...
@@ -437,6 +603,8 @@ module_init(powernv_cpufreq_init);
static
void
__exit
powernv_cpufreq_exit
(
void
)
static
void
__exit
powernv_cpufreq_exit
(
void
)
{
{
unregister_reboot_notifier
(
&
powernv_cpufreq_reboot_nb
);
unregister_reboot_notifier
(
&
powernv_cpufreq_reboot_nb
);
opal_message_notifier_unregister
(
OPAL_MSG_OCC
,
&
powernv_cpufreq_opal_nb
);
cpufreq_unregister_driver
(
&
powernv_cpufreq_driver
);
cpufreq_unregister_driver
(
&
powernv_cpufreq_driver
);
}
}
module_exit
(
powernv_cpufreq_exit
);
module_exit
(
powernv_cpufreq_exit
);
...
...
drivers/xen/xen-acpi-processor.c
浏览文件 @
2dc36ecf
...
@@ -560,11 +560,9 @@ static int __init xen_acpi_processor_init(void)
...
@@ -560,11 +560,9 @@ static int __init xen_acpi_processor_init(void)
return
0
;
return
0
;
err_unregister:
err_unregister:
for_each_possible_cpu
(
i
)
{
for_each_possible_cpu
(
i
)
struct
acpi_processor_performance
*
perf
;
acpi_processor_unregister_performance
(
i
);
perf
=
per_cpu_ptr
(
acpi_perf_data
,
i
);
acpi_processor_unregister_performance
(
perf
,
i
);
}
err_out:
err_out:
/* Freeing a NULL pointer is OK: alloc_percpu zeroes. */
/* Freeing a NULL pointer is OK: alloc_percpu zeroes. */
free_acpi_perf_data
();
free_acpi_perf_data
();
...
@@ -579,11 +577,9 @@ static void __exit xen_acpi_processor_exit(void)
...
@@ -579,11 +577,9 @@ static void __exit xen_acpi_processor_exit(void)
kfree
(
acpi_ids_done
);
kfree
(
acpi_ids_done
);
kfree
(
acpi_id_present
);
kfree
(
acpi_id_present
);
kfree
(
acpi_id_cst_present
);
kfree
(
acpi_id_cst_present
);
for_each_possible_cpu
(
i
)
{
for_each_possible_cpu
(
i
)
struct
acpi_processor_performance
*
perf
;
acpi_processor_unregister_performance
(
i
);
perf
=
per_cpu_ptr
(
acpi_perf_data
,
i
);
acpi_processor_unregister_performance
(
perf
,
i
);
}
free_acpi_perf_data
();
free_acpi_perf_data
();
}
}
...
...
include/acpi/processor.h
浏览文件 @
2dc36ecf
...
@@ -228,10 +228,7 @@ extern int acpi_processor_preregister_performance(struct
...
@@ -228,10 +228,7 @@ extern int acpi_processor_preregister_performance(struct
extern
int
acpi_processor_register_performance
(
struct
acpi_processor_performance
extern
int
acpi_processor_register_performance
(
struct
acpi_processor_performance
*
performance
,
unsigned
int
cpu
);
*
performance
,
unsigned
int
cpu
);
extern
void
acpi_processor_unregister_performance
(
struct
extern
void
acpi_processor_unregister_performance
(
unsigned
int
cpu
);
acpi_processor_performance
*
performance
,
unsigned
int
cpu
);
/* note: this locks both the calling module and the processor module
/* note: this locks both the calling module and the processor module
if a _PPC object exists, rmmod is disallowed then */
if a _PPC object exists, rmmod is disallowed then */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录