Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
4f3bff70
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
4f3bff70
编写于
4月 05, 2009
作者:
L
Len Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'thermal' into release
上级
2ddb9f17
03a971a2
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
525 addition
and
509 deletion
+525
-509
drivers/acpi/fan.c
drivers/acpi/fan.c
+12
-8
drivers/acpi/processor_thermal.c
drivers/acpi/processor_thermal.c
+11
-9
drivers/acpi/thermal.c
drivers/acpi/thermal.c
+99
-440
drivers/acpi/video.c
drivers/acpi/video.c
+13
-9
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/intel_menlow.c
+10
-19
drivers/thermal/thermal_sys.c
drivers/thermal/thermal_sys.c
+341
-15
include/linux/thermal.h
include/linux/thermal.h
+39
-9
未找到文件。
drivers/acpi/fan.c
浏览文件 @
4f3bff70
...
...
@@ -68,31 +68,35 @@ static struct acpi_driver acpi_fan_driver = {
};
/* thermal cooling device callbacks */
static
int
fan_get_max_state
(
struct
thermal_cooling_device
*
cdev
,
char
*
buf
)
static
int
fan_get_max_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
*
state
)
{
/* ACPI fan device only support two states: ON/OFF */
return
sprintf
(
buf
,
"1
\n
"
);
*
state
=
1
;
return
0
;
}
static
int
fan_get_cur_state
(
struct
thermal_cooling_device
*
cdev
,
char
*
buf
)
static
int
fan_get_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
*
state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
int
state
;
int
result
;
int
acpi_state
;
if
(
!
device
)
return
-
EINVAL
;
result
=
acpi_bus_get_power
(
device
->
handle
,
&
state
);
result
=
acpi_bus_get_power
(
device
->
handle
,
&
acpi_
state
);
if
(
result
)
return
result
;
return
sprintf
(
buf
,
"%s
\n
"
,
state
==
ACPI_STATE_D3
?
"0"
:
(
state
==
ACPI_STATE_D0
?
"1"
:
"unknown"
));
*
state
=
(
acpi_state
==
ACPI_STATE_D3
?
0
:
(
acpi_state
==
ACPI_STATE_D0
?
1
:
-
1
));
return
0
;
}
static
int
fan_set_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
int
state
)
fan_set_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
int
result
;
...
...
drivers/acpi/processor_thermal.c
浏览文件 @
4f3bff70
...
...
@@ -373,7 +373,8 @@ static int acpi_processor_max_state(struct acpi_processor *pr)
return
max_state
;
}
static
int
processor_get_max_state
(
struct
thermal_cooling_device
*
cdev
,
char
*
buf
)
processor_get_max_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
*
state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
struct
acpi_processor
*
pr
=
acpi_driver_data
(
device
);
...
...
@@ -381,28 +382,29 @@ processor_get_max_state(struct thermal_cooling_device *cdev, char *buf)
if
(
!
device
||
!
pr
)
return
-
EINVAL
;
return
sprintf
(
buf
,
"%d
\n
"
,
acpi_processor_max_state
(
pr
));
*
state
=
acpi_processor_max_state
(
pr
);
return
0
;
}
static
int
processor_get_cur_state
(
struct
thermal_cooling_device
*
cdev
,
char
*
buf
)
processor_get_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
*
cur_state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
struct
acpi_processor
*
pr
=
acpi_driver_data
(
device
);
int
cur_state
;
if
(
!
device
||
!
pr
)
return
-
EINVAL
;
cur_state
=
cpufreq_get_cur_state
(
pr
->
id
);
*
cur_state
=
cpufreq_get_cur_state
(
pr
->
id
);
if
(
pr
->
flags
.
throttling
)
cur_state
+=
pr
->
throttling
.
state
;
return
sprintf
(
buf
,
"%d
\n
"
,
cur_state
);
*
cur_state
+=
pr
->
throttling
.
state
;
return
0
;
}
static
int
processor_set_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
int
state
)
processor_set_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
struct
acpi_processor
*
pr
=
acpi_driver_data
(
device
);
...
...
drivers/acpi/thermal.c
浏览文件 @
4f3bff70
...
...
@@ -37,11 +37,11 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/kmod.h>
#include <linux/seq_file.h>
#include <linux/reboot.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/thermal.h>
#include <acpi/acpi_bus.h>
...
...
@@ -190,7 +190,6 @@ struct acpi_thermal {
struct
acpi_thermal_state
state
;
struct
acpi_thermal_trips
trips
;
struct
acpi_handle_list
devices
;
struct
timer_list
timer
;
struct
thermal_zone_device
*
thermal_zone
;
int
tz_enabled
;
struct
mutex
lock
;
...
...
@@ -290,6 +289,11 @@ static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
tz
->
polling_frequency
=
seconds
*
10
;
/* Convert value to deci-seconds */
tz
->
thermal_zone
->
polling_delay
=
seconds
*
1000
;
if
(
tz
->
tz_enabled
)
thermal_zone_device_update
(
tz
->
thermal_zone
);
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Polling frequency set to %lu seconds
\n
"
,
tz
->
polling_frequency
/
10
));
...
...
@@ -569,392 +573,18 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
return
acpi_thermal_trips_update
(
tz
,
ACPI_TRIPS_INIT
);
}
static
int
acpi_thermal_critical
(
struct
acpi_thermal
*
tz
)
{
if
(
!
tz
||
!
tz
->
trips
.
critical
.
flags
.
valid
)
return
-
EINVAL
;
if
(
tz
->
temperature
>=
tz
->
trips
.
critical
.
temperature
)
{
printk
(
KERN_WARNING
PREFIX
"Critical trip point
\n
"
);
tz
->
trips
.
critical
.
flags
.
enabled
=
1
;
}
else
if
(
tz
->
trips
.
critical
.
flags
.
enabled
)
tz
->
trips
.
critical
.
flags
.
enabled
=
0
;
acpi_bus_generate_proc_event
(
tz
->
device
,
ACPI_THERMAL_NOTIFY_CRITICAL
,
tz
->
trips
.
critical
.
flags
.
enabled
);
acpi_bus_generate_netlink_event
(
tz
->
device
->
pnp
.
device_class
,
dev_name
(
&
tz
->
device
->
dev
),
ACPI_THERMAL_NOTIFY_CRITICAL
,
tz
->
trips
.
critical
.
flags
.
enabled
);
/* take no action if nocrt is set */
if
(
!
nocrt
)
{
printk
(
KERN_EMERG
"Critical temperature reached (%ld C), shutting down.
\n
"
,
KELVIN_TO_CELSIUS
(
tz
->
temperature
));
orderly_poweroff
(
true
);
}
return
0
;
}
static
int
acpi_thermal_hot
(
struct
acpi_thermal
*
tz
)
{
if
(
!
tz
||
!
tz
->
trips
.
hot
.
flags
.
valid
)
return
-
EINVAL
;
if
(
tz
->
temperature
>=
tz
->
trips
.
hot
.
temperature
)
{
printk
(
KERN_WARNING
PREFIX
"Hot trip point
\n
"
);
tz
->
trips
.
hot
.
flags
.
enabled
=
1
;
}
else
if
(
tz
->
trips
.
hot
.
flags
.
enabled
)
tz
->
trips
.
hot
.
flags
.
enabled
=
0
;
acpi_bus_generate_proc_event
(
tz
->
device
,
ACPI_THERMAL_NOTIFY_HOT
,
tz
->
trips
.
hot
.
flags
.
enabled
);
acpi_bus_generate_netlink_event
(
tz
->
device
->
pnp
.
device_class
,
dev_name
(
&
tz
->
device
->
dev
),
ACPI_THERMAL_NOTIFY_HOT
,
tz
->
trips
.
hot
.
flags
.
enabled
);
/* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */
return
0
;
}
static
void
acpi_thermal_passive
(
struct
acpi_thermal
*
tz
)
{
int
result
=
1
;
struct
acpi_thermal_passive
*
passive
=
NULL
;
int
trend
=
0
;
int
i
=
0
;
if
(
!
tz
||
!
tz
->
trips
.
passive
.
flags
.
valid
)
return
;
passive
=
&
(
tz
->
trips
.
passive
);
/*
* Above Trip?
* -----------
* Calculate the thermal trend (using the passive cooling equation)
* and modify the performance limit for all passive cooling devices
* accordingly. Note that we assume symmetry.
*/
if
(
tz
->
temperature
>=
passive
->
temperature
)
{
trend
=
(
passive
->
tc1
*
(
tz
->
temperature
-
tz
->
last_temperature
))
+
(
passive
->
tc2
*
(
tz
->
temperature
-
passive
->
temperature
));
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))
\n
"
,
trend
,
passive
->
tc1
,
tz
->
temperature
,
tz
->
last_temperature
,
passive
->
tc2
,
tz
->
temperature
,
passive
->
temperature
));
passive
->
flags
.
enabled
=
1
;
/* Heating up? */
if
(
trend
>
0
)
for
(
i
=
0
;
i
<
passive
->
devices
.
count
;
i
++
)
acpi_processor_set_thermal_limit
(
passive
->
devices
.
handles
[
i
],
ACPI_PROCESSOR_LIMIT_INCREMENT
);
/* Cooling off? */
else
if
(
trend
<
0
)
{
for
(
i
=
0
;
i
<
passive
->
devices
.
count
;
i
++
)
/*
* assume that we are on highest
* freq/lowest thrott and can leave
* passive mode, even in error case
*/
if
(
!
acpi_processor_set_thermal_limit
(
passive
->
devices
.
handles
[
i
],
ACPI_PROCESSOR_LIMIT_DECREMENT
))
result
=
0
;
/*
* Leave cooling mode, even if the temp might
* higher than trip point This is because some
* machines might have long thermal polling
* frequencies (tsp) defined. We will fall back
* into passive mode in next cycle (probably quicker)
*/
if
(
result
)
{
passive
->
flags
.
enabled
=
0
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Disabling passive cooling, still above threshold,"
" but we are cooling down
\n
"
));
}
}
return
;
}
/*
* Below Trip?
* -----------
* Implement passive cooling hysteresis to slowly increase performance
* and avoid thrashing around the passive trip point. Note that we
* assume symmetry.
*/
if
(
!
passive
->
flags
.
enabled
)
return
;
for
(
i
=
0
;
i
<
passive
->
devices
.
count
;
i
++
)
if
(
!
acpi_processor_set_thermal_limit
(
passive
->
devices
.
handles
[
i
],
ACPI_PROCESSOR_LIMIT_DECREMENT
))
result
=
0
;
if
(
result
)
{
passive
->
flags
.
enabled
=
0
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Disabling passive cooling (zone is cool)
\n
"
));
}
}
static
void
acpi_thermal_active
(
struct
acpi_thermal
*
tz
)
{
int
result
=
0
;
struct
acpi_thermal_active
*
active
=
NULL
;
int
i
=
0
;
int
j
=
0
;
unsigned
long
maxtemp
=
0
;
if
(
!
tz
)
return
;
for
(
i
=
0
;
i
<
ACPI_THERMAL_MAX_ACTIVE
;
i
++
)
{
active
=
&
(
tz
->
trips
.
active
[
i
]);
if
(
!
active
||
!
active
->
flags
.
valid
)
break
;
if
(
tz
->
temperature
>=
active
->
temperature
)
{
/*
* Above Threshold?
* ----------------
* If not already enabled, turn ON all cooling devices
* associated with this active threshold.
*/
if
(
active
->
temperature
>
maxtemp
)
tz
->
state
.
active_index
=
i
;
maxtemp
=
active
->
temperature
;
if
(
active
->
flags
.
enabled
)
continue
;
for
(
j
=
0
;
j
<
active
->
devices
.
count
;
j
++
)
{
result
=
acpi_bus_set_power
(
active
->
devices
.
handles
[
j
],
ACPI_STATE_D0
);
if
(
result
)
{
printk
(
KERN_WARNING
PREFIX
"Unable to turn cooling device [%p] 'on'
\n
"
,
active
->
devices
.
handles
[
j
]);
continue
;
}
active
->
flags
.
enabled
=
1
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Cooling device [%p] now 'on'
\n
"
,
active
->
devices
.
handles
[
j
]));
}
continue
;
}
if
(
!
active
->
flags
.
enabled
)
continue
;
/*
* Below Threshold?
* ----------------
* Turn OFF all cooling devices associated with this
* threshold.
*/
for
(
j
=
0
;
j
<
active
->
devices
.
count
;
j
++
)
{
result
=
acpi_bus_set_power
(
active
->
devices
.
handles
[
j
],
ACPI_STATE_D3
);
if
(
result
)
{
printk
(
KERN_WARNING
PREFIX
"Unable to turn cooling device [%p] 'off'
\n
"
,
active
->
devices
.
handles
[
j
]);
continue
;
}
active
->
flags
.
enabled
=
0
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Cooling device [%p] now 'off'
\n
"
,
active
->
devices
.
handles
[
j
]));
}
}
}
static
void
acpi_thermal_check
(
void
*
context
);
static
void
acpi_thermal_run
(
unsigned
long
data
)
{
struct
acpi_thermal
*
tz
=
(
struct
acpi_thermal
*
)
data
;
if
(
!
tz
->
zombie
)
acpi_os_execute
(
OSL_GPE_HANDLER
,
acpi_thermal_check
,
(
void
*
)
data
);
}
static
void
acpi_thermal_active_off
(
void
*
data
)
{
int
result
=
0
;
struct
acpi_thermal
*
tz
=
data
;
int
i
=
0
;
int
j
=
0
;
struct
acpi_thermal_active
*
active
=
NULL
;
if
(
!
tz
)
{
printk
(
KERN_ERR
PREFIX
"Invalid (NULL) context
\n
"
);
return
;
}
result
=
acpi_thermal_get_temperature
(
tz
);
if
(
result
)
return
;
for
(
i
=
0
;
i
<
ACPI_THERMAL_MAX_ACTIVE
;
i
++
)
{
active
=
&
(
tz
->
trips
.
active
[
i
]);
if
(
!
active
||
!
active
->
flags
.
valid
)
break
;
if
(
tz
->
temperature
>=
active
->
temperature
)
{
/*
* If the thermal temperature is greater than the
* active threshod, unnecessary to turn off the
* the active cooling device.
*/
continue
;
}
/*
* Below Threshold?
* ----------------
* Turn OFF all cooling devices associated with this
* threshold.
*/
for
(
j
=
0
;
j
<
active
->
devices
.
count
;
j
++
)
result
=
acpi_bus_set_power
(
active
->
devices
.
handles
[
j
],
ACPI_STATE_D3
);
}
}
static
void
acpi_thermal_check
(
void
*
data
)
{
int
result
=
0
;
struct
acpi_thermal
*
tz
=
data
;
unsigned
long
sleep_time
=
0
;
unsigned
long
timeout_jiffies
=
0
;
int
i
=
0
;
struct
acpi_thermal_state
state
;
if
(
!
tz
)
{
printk
(
KERN_ERR
PREFIX
"Invalid (NULL) context
\n
"
);
return
;
}
/* Check if someone else is already running */
if
(
!
mutex_trylock
(
&
tz
->
lock
))
return
;
state
=
tz
->
state
;
result
=
acpi_thermal_get_temperature
(
tz
);
if
(
result
)
goto
unlock
;
if
(
!
tz
->
tz_enabled
)
goto
unlock
;
memset
(
&
tz
->
state
,
0
,
sizeof
(
tz
->
state
));
/*
* Check Trip Points
* -----------------
* Compare the current temperature to the trip point values to see
* if we've entered one of the thermal policy states. Note that
* this function determines when a state is entered, but the
* individual policy decides when it is exited (e.g. hysteresis).
*/
if
(
tz
->
trips
.
critical
.
flags
.
valid
)
state
.
critical
|=
(
tz
->
temperature
>=
tz
->
trips
.
critical
.
temperature
);
if
(
tz
->
trips
.
hot
.
flags
.
valid
)
state
.
hot
|=
(
tz
->
temperature
>=
tz
->
trips
.
hot
.
temperature
);
if
(
tz
->
trips
.
passive
.
flags
.
valid
)
state
.
passive
|=
(
tz
->
temperature
>=
tz
->
trips
.
passive
.
temperature
);
for
(
i
=
0
;
i
<
ACPI_THERMAL_MAX_ACTIVE
;
i
++
)
if
(
tz
->
trips
.
active
[
i
].
flags
.
valid
)
state
.
active
|=
(
tz
->
temperature
>=
tz
->
trips
.
active
[
i
].
temperature
);
/*
* Invoke Policy
* -------------
* Separated from the above check to allow individual policy to
* determine when to exit a given state.
*/
if
(
state
.
critical
)
acpi_thermal_critical
(
tz
);
if
(
state
.
hot
)
acpi_thermal_hot
(
tz
);
if
(
state
.
passive
)
acpi_thermal_passive
(
tz
);
if
(
state
.
active
)
acpi_thermal_active
(
tz
);
/*
* Calculate State
* ---------------
* Again, separated from the above two to allow independent policy
* decisions.
*/
tz
->
state
.
critical
=
tz
->
trips
.
critical
.
flags
.
enabled
;
tz
->
state
.
hot
=
tz
->
trips
.
hot
.
flags
.
enabled
;
tz
->
state
.
passive
=
tz
->
trips
.
passive
.
flags
.
enabled
;
tz
->
state
.
active
=
0
;
for
(
i
=
0
;
i
<
ACPI_THERMAL_MAX_ACTIVE
;
i
++
)
tz
->
state
.
active
|=
tz
->
trips
.
active
[
i
].
flags
.
enabled
;
/*
* Calculate Sleep Time
* --------------------
* If we're in the passive state, use _TSP's value. Otherwise
* use the default polling frequency (e.g. _TZP). If no polling
* frequency is specified then we'll wait forever (at least until
* a thermal event occurs). Note that _TSP and _TZD values are
* given in 1/10th seconds (we must covert to milliseconds).
*/
if
(
tz
->
state
.
passive
)
{
sleep_time
=
tz
->
trips
.
passive
.
tsp
*
100
;
timeout_jiffies
=
jiffies
+
(
HZ
*
sleep_time
)
/
1000
;
}
else
if
(
tz
->
polling_frequency
>
0
)
{
sleep_time
=
tz
->
polling_frequency
*
100
;
timeout_jiffies
=
round_jiffies
(
jiffies
+
(
HZ
*
sleep_time
)
/
1000
);
}
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"%s: temperature[%lu] sleep[%lu]
\n
"
,
tz
->
name
,
tz
->
temperature
,
sleep_time
));
/*
* Schedule Next Poll
* ------------------
*/
if
(
!
sleep_time
)
{
if
(
timer_pending
(
&
(
tz
->
timer
)))
del_timer
(
&
(
tz
->
timer
));
}
else
{
if
(
timer_pending
(
&
(
tz
->
timer
)))
mod_timer
(
&
(
tz
->
timer
),
timeout_jiffies
);
else
{
tz
->
timer
.
data
=
(
unsigned
long
)
tz
;
tz
->
timer
.
function
=
acpi_thermal_run
;
tz
->
timer
.
expires
=
timeout_jiffies
;
add_timer
(
&
(
tz
->
timer
));
}
}
unlock:
mutex_unlock
(
&
tz
->
lock
);
thermal_zone_device_update
(
tz
->
thermal_zone
);
}
/* sys I/F for generic thermal sysfs support */
#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)
static
int
thermal_get_temp
(
struct
thermal_zone_device
*
thermal
,
char
*
buf
)
static
int
thermal_get_temp
(
struct
thermal_zone_device
*
thermal
,
unsigned
long
*
temp
)
{
struct
acpi_thermal
*
tz
=
thermal
->
devdata
;
int
result
;
...
...
@@ -966,25 +596,28 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
if
(
result
)
return
result
;
return
sprintf
(
buf
,
"%ld
\n
"
,
KELVIN_TO_MILLICELSIUS
(
tz
->
temperature
));
*
temp
=
KELVIN_TO_MILLICELSIUS
(
tz
->
temperature
);
return
0
;
}
static
const
char
enabled
[]
=
"kernel"
;
static
const
char
disabled
[]
=
"user"
;
static
int
thermal_get_mode
(
struct
thermal_zone_device
*
thermal
,
char
*
buf
)
enum
thermal_device_mode
*
mode
)
{
struct
acpi_thermal
*
tz
=
thermal
->
devdata
;
if
(
!
tz
)
return
-
EINVAL
;
return
sprintf
(
buf
,
"%s
\n
"
,
tz
->
tz_enabled
?
enabled
:
disabled
);
*
mode
=
tz
->
tz_enabled
?
THERMAL_DEVICE_ENABLED
:
THERMAL_DEVICE_DISABLED
;
return
0
;
}
static
int
thermal_set_mode
(
struct
thermal_zone_device
*
thermal
,
const
char
*
buf
)
enum
thermal_device_mode
mode
)
{
struct
acpi_thermal
*
tz
=
thermal
->
devdata
;
int
enable
;
...
...
@@ -995,9 +628,9 @@ static int thermal_set_mode(struct thermal_zone_device *thermal,
/*
* enable/disable thermal management from ACPI thermal driver
*/
if
(
!
strncmp
(
buf
,
enabled
,
sizeof
enabled
-
1
)
)
if
(
mode
==
THERMAL_DEVICE_ENABLED
)
enable
=
1
;
else
if
(
!
strncmp
(
buf
,
disabled
,
sizeof
disabled
-
1
)
)
else
if
(
mode
==
THERMAL_DEVICE_DISABLED
)
enable
=
0
;
else
return
-
EINVAL
;
...
...
@@ -1013,7 +646,7 @@ static int thermal_set_mode(struct thermal_zone_device *thermal,
}
static
int
thermal_get_trip_type
(
struct
thermal_zone_device
*
thermal
,
int
trip
,
char
*
buf
)
int
trip
,
enum
thermal_trip_type
*
type
)
{
struct
acpi_thermal
*
tz
=
thermal
->
devdata
;
int
i
;
...
...
@@ -1022,27 +655,35 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
return
-
EINVAL
;
if
(
tz
->
trips
.
critical
.
flags
.
valid
)
{
if
(
!
trip
)
return
sprintf
(
buf
,
"critical
\n
"
);
if
(
!
trip
)
{
*
type
=
THERMAL_TRIP_CRITICAL
;
return
0
;
}
trip
--
;
}
if
(
tz
->
trips
.
hot
.
flags
.
valid
)
{
if
(
!
trip
)
return
sprintf
(
buf
,
"hot
\n
"
);
if
(
!
trip
)
{
*
type
=
THERMAL_TRIP_HOT
;
return
0
;
}
trip
--
;
}
if
(
tz
->
trips
.
passive
.
flags
.
valid
)
{
if
(
!
trip
)
return
sprintf
(
buf
,
"passive
\n
"
);
if
(
!
trip
)
{
*
type
=
THERMAL_TRIP_PASSIVE
;
return
0
;
}
trip
--
;
}
for
(
i
=
0
;
i
<
ACPI_THERMAL_MAX_ACTIVE
&&
tz
->
trips
.
active
[
i
].
flags
.
valid
;
i
++
)
{
if
(
!
trip
)
return
sprintf
(
buf
,
"active%d
\n
"
,
i
);
if
(
!
trip
)
{
*
type
=
THERMAL_TRIP_ACTIVE
;
return
0
;
}
trip
--
;
}
...
...
@@ -1050,7 +691,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
}
static
int
thermal_get_trip_temp
(
struct
thermal_zone_device
*
thermal
,
int
trip
,
char
*
buf
)
int
trip
,
unsigned
long
*
temp
)
{
struct
acpi_thermal
*
tz
=
thermal
->
devdata
;
int
i
;
...
...
@@ -1059,31 +700,39 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
return
-
EINVAL
;
if
(
tz
->
trips
.
critical
.
flags
.
valid
)
{
if
(
!
trip
)
return
sprintf
(
buf
,
"%ld
\n
"
,
KELVIN_TO_MILLICELSIUS
(
tz
->
trips
.
critical
.
temperature
));
if
(
!
trip
)
{
*
temp
=
KELVIN_TO_MILLICELSIUS
(
tz
->
trips
.
critical
.
temperature
);
return
0
;
}
trip
--
;
}
if
(
tz
->
trips
.
hot
.
flags
.
valid
)
{
if
(
!
trip
)
return
sprintf
(
buf
,
"%ld
\n
"
,
KELVIN_TO_MILLICELSIUS
(
tz
->
trips
.
hot
.
temperature
));
if
(
!
trip
)
{
*
temp
=
KELVIN_TO_MILLICELSIUS
(
tz
->
trips
.
hot
.
temperature
);
return
0
;
}
trip
--
;
}
if
(
tz
->
trips
.
passive
.
flags
.
valid
)
{
if
(
!
trip
)
return
sprintf
(
buf
,
"%ld
\n
"
,
KELVIN_TO_MILLICELSIUS
(
tz
->
trips
.
passive
.
temperature
));
if
(
!
trip
)
{
*
temp
=
KELVIN_TO_MILLICELSIUS
(
tz
->
trips
.
passive
.
temperature
);
return
0
;
}
trip
--
;
}
for
(
i
=
0
;
i
<
ACPI_THERMAL_MAX_ACTIVE
&&
tz
->
trips
.
active
[
i
].
flags
.
valid
;
i
++
)
{
if
(
!
trip
)
return
sprintf
(
buf
,
"%ld
\n
"
,
KELVIN_TO_MILLICELSIUS
(
tz
->
trips
.
active
[
i
].
temperature
));
if
(
!
trip
)
{
*
temp
=
KELVIN_TO_MILLICELSIUS
(
tz
->
trips
.
active
[
i
].
temperature
);
return
0
;
}
trip
--
;
}
...
...
@@ -1102,6 +751,29 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
return
-
EINVAL
;
}
static
int
thermal_notify
(
struct
thermal_zone_device
*
thermal
,
int
trip
,
enum
thermal_trip_type
trip_type
)
{
u8
type
=
0
;
struct
acpi_thermal
*
tz
=
thermal
->
devdata
;
if
(
trip_type
==
THERMAL_TRIP_CRITICAL
)
type
=
ACPI_THERMAL_NOTIFY_CRITICAL
;
else
if
(
trip_type
==
THERMAL_TRIP_HOT
)
type
=
ACPI_THERMAL_NOTIFY_HOT
;
else
return
0
;
acpi_bus_generate_proc_event
(
tz
->
device
,
type
,
1
);
acpi_bus_generate_netlink_event
(
tz
->
device
->
pnp
.
device_class
,
dev_name
(
&
tz
->
device
->
dev
),
type
,
1
);
if
(
trip_type
==
THERMAL_TRIP_CRITICAL
&&
nocrt
)
return
1
;
return
0
;
}
typedef
int
(
*
cb
)(
struct
thermal_zone_device
*
,
int
,
struct
thermal_cooling_device
*
);
static
int
acpi_thermal_cooling_device_cb
(
struct
thermal_zone_device
*
thermal
,
...
...
@@ -1194,6 +866,7 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
.
get_trip_type
=
thermal_get_trip_type
,
.
get_trip_temp
=
thermal_get_trip_temp
,
.
get_crit_temp
=
thermal_get_crit_temp
,
.
notify
=
thermal_notify
,
};
static
int
acpi_thermal_register_thermal_zone
(
struct
acpi_thermal
*
tz
)
...
...
@@ -1214,8 +887,21 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
for
(
i
=
0
;
i
<
ACPI_THERMAL_MAX_ACTIVE
&&
tz
->
trips
.
active
[
i
].
flags
.
valid
;
i
++
,
trips
++
);
tz
->
thermal_zone
=
thermal_zone_device_register
(
"acpitz"
,
trips
,
tz
,
&
acpi_thermal_zone_ops
);
if
(
tz
->
trips
.
passive
.
flags
.
valid
)
tz
->
thermal_zone
=
thermal_zone_device_register
(
"acpitz"
,
trips
,
tz
,
&
acpi_thermal_zone_ops
,
tz
->
trips
.
passive
.
tc1
,
tz
->
trips
.
passive
.
tc2
,
tz
->
trips
.
passive
.
tsp
*
100
,
tz
->
polling_frequency
*
100
);
else
tz
->
thermal_zone
=
thermal_zone_device_register
(
"acpitz"
,
trips
,
tz
,
&
acpi_thermal_zone_ops
,
0
,
0
,
0
,
tz
->
polling_frequency
);
if
(
IS_ERR
(
tz
->
thermal_zone
))
return
-
ENODEV
;
...
...
@@ -1447,13 +1133,13 @@ static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
if
(
!
tz
)
goto
end
;
if
(
!
tz
->
polling_frequenc
y
)
{
if
(
!
tz
->
thermal_zone
->
polling_dela
y
)
{
seq_puts
(
seq
,
"<polling disabled>
\n
"
);
goto
end
;
}
seq_printf
(
seq
,
"polling frequency: %
lu
seconds
\n
"
,
(
tz
->
polling_frequency
/
1
0
));
seq_printf
(
seq
,
"polling frequency: %
d
seconds
\n
"
,
(
tz
->
thermal_zone
->
polling_delay
/
100
0
));
end:
return
0
;
...
...
@@ -1683,12 +1369,6 @@ static int acpi_thermal_add(struct acpi_device *device)
if
(
result
)
goto
unregister_thermal_zone
;
init_timer
(
&
tz
->
timer
);
acpi_thermal_active_off
(
tz
);
acpi_thermal_check
(
tz
);
status
=
acpi_install_notify_handler
(
device
->
handle
,
ACPI_DEVICE_NOTIFY
,
acpi_thermal_notify
,
tz
);
...
...
@@ -1717,36 +1397,15 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
acpi_status
status
=
AE_OK
;
struct
acpi_thermal
*
tz
=
NULL
;
if
(
!
device
||
!
acpi_driver_data
(
device
))
return
-
EINVAL
;
tz
=
acpi_driver_data
(
device
);
/* avoid timer adding new defer task */
tz
->
zombie
=
1
;
/* wait for running timer (on other CPUs) finish */
del_timer_sync
(
&
(
tz
->
timer
));
/* synchronize deferred task */
acpi_os_wait_events_complete
(
NULL
);
/* deferred task may reinsert timer */
del_timer_sync
(
&
(
tz
->
timer
));
status
=
acpi_remove_notify_handler
(
device
->
handle
,
ACPI_DEVICE_NOTIFY
,
acpi_thermal_notify
);
/* Terminate policy */
if
(
tz
->
trips
.
passive
.
flags
.
valid
&&
tz
->
trips
.
passive
.
flags
.
enabled
)
{
tz
->
trips
.
passive
.
flags
.
enabled
=
0
;
acpi_thermal_passive
(
tz
);
}
if
(
tz
->
trips
.
active
[
0
].
flags
.
valid
&&
tz
->
trips
.
active
[
0
].
flags
.
enabled
)
{
tz
->
trips
.
active
[
0
].
flags
.
enabled
=
0
;
acpi_thermal_active
(
tz
);
}
acpi_thermal_remove_fs
(
device
);
acpi_thermal_unregister_thermal_zone
(
tz
);
mutex_destroy
(
&
tz
->
lock
);
...
...
drivers/acpi/video.c
浏览文件 @
4f3bff70
...
...
@@ -358,32 +358,36 @@ static struct output_properties acpi_output_properties = {
/* thermal cooling device callbacks */
static
int
video_get_max_state
(
struct
thermal_cooling_device
*
cdev
,
char
*
buf
)
static
int
video_get_max_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
*
state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
struct
acpi_video_device
*
video
=
acpi_driver_data
(
device
);
return
sprintf
(
buf
,
"%d
\n
"
,
video
->
brightness
->
count
-
3
);
*
state
=
video
->
brightness
->
count
-
3
;
return
0
;
}
static
int
video_get_cur_state
(
struct
thermal_cooling_device
*
cdev
,
char
*
buf
)
static
int
video_get_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
*
state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
struct
acpi_video_device
*
video
=
acpi_driver_data
(
device
);
unsigned
long
long
level
;
int
state
;
int
offset
;
acpi_video_device_lcd_get_level_current
(
video
,
&
level
);
for
(
state
=
2
;
state
<
video
->
brightness
->
count
;
state
++
)
if
(
level
==
video
->
brightness
->
levels
[
state
])
return
sprintf
(
buf
,
"%d
\n
"
,
video
->
brightness
->
count
-
state
-
1
);
for
(
offset
=
2
;
offset
<
video
->
brightness
->
count
;
offset
++
)
if
(
level
==
video
->
brightness
->
levels
[
offset
])
{
*
state
=
video
->
brightness
->
count
-
offset
-
1
;
return
0
;
}
return
-
EINVAL
;
}
static
int
video_set_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
int
state
)
video_set_cur_state
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
struct
acpi_video_device
*
video
=
acpi_driver_data
(
device
);
...
...
drivers/platform/x86/intel_menlow.c
浏览文件 @
4f3bff70
...
...
@@ -57,8 +57,8 @@ MODULE_LICENSE("GPL");
* In that case max_cstate would be n-1
* GTHS returning '0' would mean that no bandwidth control states are supported
*/
static
int
memory_get_
int_
max_bandwidth
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
*
max_state
)
static
int
memory_get_max_bandwidth
(
struct
thermal_cooling_device
*
cdev
,
unsigned
long
*
max_state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
acpi_handle
handle
=
device
->
handle
;
...
...
@@ -83,22 +83,12 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev,
return
0
;
}
static
int
memory_get_max_bandwidth
(
struct
thermal_cooling_device
*
cdev
,
char
*
buf
)
{
unsigned
long
value
;
if
(
memory_get_int_max_bandwidth
(
cdev
,
&
value
))
return
-
EINVAL
;
return
sprintf
(
buf
,
"%ld
\n
"
,
value
);
}
static
int
memory_get_cur_bandwidth
(
struct
thermal_cooling_device
*
cdev
,
char
*
buf
)
unsigned
long
*
value
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
acpi_handle
handle
=
device
->
handle
;
unsigned
long
long
value
;
unsigned
long
long
result
;
struct
acpi_object_list
arg_list
;
union
acpi_object
arg
;
acpi_status
status
=
AE_OK
;
...
...
@@ -108,15 +98,16 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
arg
.
type
=
ACPI_TYPE_INTEGER
;
arg
.
integer
.
value
=
MEMORY_ARG_CUR_BANDWIDTH
;
status
=
acpi_evaluate_integer
(
handle
,
MEMORY_GET_BANDWIDTH
,
&
arg_list
,
&
value
);
&
arg_list
,
&
result
);
if
(
ACPI_FAILURE
(
status
))
return
-
EFAULT
;
return
sprintf
(
buf
,
"%llu
\n
"
,
value
);
*
value
=
result
;
return
0
;
}
static
int
memory_set_cur_bandwidth
(
struct
thermal_cooling_device
*
cdev
,
unsigned
int
state
)
unsigned
long
state
)
{
struct
acpi_device
*
device
=
cdev
->
devdata
;
acpi_handle
handle
=
device
->
handle
;
...
...
@@ -126,7 +117,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
unsigned
long
long
temp
;
unsigned
long
max_state
;
if
(
memory_get_
int_
max_bandwidth
(
cdev
,
&
max_state
))
if
(
memory_get_max_bandwidth
(
cdev
,
&
max_state
))
return
-
EFAULT
;
if
(
state
>
max_state
)
...
...
@@ -142,7 +133,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
&
temp
);
printk
(
KERN_INFO
"Bandwidth value was %d: status is %d
\n
"
,
state
,
status
);
"Bandwidth value was %
l
d: status is %d
\n
"
,
state
,
status
);
if
(
ACPI_FAILURE
(
status
))
return
-
EFAULT
;
...
...
drivers/thermal/thermal_sys.c
浏览文件 @
4f3bff70
...
...
@@ -30,6 +30,7 @@
#include <linux/idr.h>
#include <linux/thermal.h>
#include <linux/spinlock.h>
#include <linux/reboot.h>
MODULE_AUTHOR
(
"Zhang Rui"
);
MODULE_DESCRIPTION
(
"Generic thermal management sysfs support"
);
...
...
@@ -104,22 +105,36 @@ static ssize_t
temp_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
thermal_zone_device
*
tz
=
to_thermal_zone
(
dev
);
long
temperature
;
int
ret
;
if
(
!
tz
->
ops
->
get_temp
)
return
-
EPERM
;
return
tz
->
ops
->
get_temp
(
tz
,
buf
);
ret
=
tz
->
ops
->
get_temp
(
tz
,
&
temperature
);
if
(
ret
)
return
ret
;
return
sprintf
(
buf
,
"%ld
\n
"
,
temperature
);
}
static
ssize_t
mode_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
thermal_zone_device
*
tz
=
to_thermal_zone
(
dev
);
enum
thermal_device_mode
mode
;
int
result
;
if
(
!
tz
->
ops
->
get_mode
)
return
-
EPERM
;
return
tz
->
ops
->
get_mode
(
tz
,
buf
);
result
=
tz
->
ops
->
get_mode
(
tz
,
&
mode
);
if
(
result
)
return
result
;
return
sprintf
(
buf
,
"%s
\n
"
,
mode
==
THERMAL_DEVICE_ENABLED
?
"enabled"
:
"disabled"
);
}
static
ssize_t
...
...
@@ -132,7 +147,13 @@ mode_store(struct device *dev, struct device_attribute *attr,
if
(
!
tz
->
ops
->
set_mode
)
return
-
EPERM
;
result
=
tz
->
ops
->
set_mode
(
tz
,
buf
);
if
(
!
strncmp
(
buf
,
"enabled"
,
sizeof
(
"enabled"
)))
result
=
tz
->
ops
->
set_mode
(
tz
,
THERMAL_DEVICE_ENABLED
);
else
if
(
!
strncmp
(
buf
,
"disabled"
,
sizeof
(
"disabled"
)))
result
=
tz
->
ops
->
set_mode
(
tz
,
THERMAL_DEVICE_DISABLED
);
else
result
=
-
EINVAL
;
if
(
result
)
return
result
;
...
...
@@ -144,7 +165,8 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
char
*
buf
)
{
struct
thermal_zone_device
*
tz
=
to_thermal_zone
(
dev
);
int
trip
;
enum
thermal_trip_type
type
;
int
trip
,
result
;
if
(
!
tz
->
ops
->
get_trip_type
)
return
-
EPERM
;
...
...
@@ -152,7 +174,22 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
if
(
!
sscanf
(
attr
->
attr
.
name
,
"trip_point_%d_type"
,
&
trip
))
return
-
EINVAL
;
return
tz
->
ops
->
get_trip_type
(
tz
,
trip
,
buf
);
result
=
tz
->
ops
->
get_trip_type
(
tz
,
trip
,
&
type
);
if
(
result
)
return
result
;
switch
(
type
)
{
case
THERMAL_TRIP_CRITICAL
:
return
sprintf
(
buf
,
"critical"
);
case
THERMAL_TRIP_HOT
:
return
sprintf
(
buf
,
"hot"
);
case
THERMAL_TRIP_PASSIVE
:
return
sprintf
(
buf
,
"passive"
);
case
THERMAL_TRIP_ACTIVE
:
return
sprintf
(
buf
,
"active"
);
default:
return
sprintf
(
buf
,
"unknown"
);
}
}
static
ssize_t
...
...
@@ -160,7 +197,8 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
char
*
buf
)
{
struct
thermal_zone_device
*
tz
=
to_thermal_zone
(
dev
);
int
trip
;
int
trip
,
ret
;
long
temperature
;
if
(
!
tz
->
ops
->
get_trip_temp
)
return
-
EPERM
;
...
...
@@ -168,12 +206,77 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
if
(
!
sscanf
(
attr
->
attr
.
name
,
"trip_point_%d_temp"
,
&
trip
))
return
-
EINVAL
;
return
tz
->
ops
->
get_trip_temp
(
tz
,
trip
,
buf
);
ret
=
tz
->
ops
->
get_trip_temp
(
tz
,
trip
,
&
temperature
);
if
(
ret
)
return
ret
;
return
sprintf
(
buf
,
"%ld
\n
"
,
temperature
);
}
static
ssize_t
passive_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
thermal_zone_device
*
tz
=
to_thermal_zone
(
dev
);
struct
thermal_cooling_device
*
cdev
=
NULL
;
int
state
;
if
(
!
sscanf
(
buf
,
"%d
\n
"
,
&
state
))
return
-
EINVAL
;
if
(
state
&&
!
tz
->
forced_passive
)
{
mutex_lock
(
&
thermal_list_lock
);
list_for_each_entry
(
cdev
,
&
thermal_cdev_list
,
node
)
{
if
(
!
strncmp
(
"Processor"
,
cdev
->
type
,
sizeof
(
"Processor"
)))
thermal_zone_bind_cooling_device
(
tz
,
THERMAL_TRIPS_NONE
,
cdev
);
}
mutex_unlock
(
&
thermal_list_lock
);
}
else
if
(
!
state
&&
tz
->
forced_passive
)
{
mutex_lock
(
&
thermal_list_lock
);
list_for_each_entry
(
cdev
,
&
thermal_cdev_list
,
node
)
{
if
(
!
strncmp
(
"Processor"
,
cdev
->
type
,
sizeof
(
"Processor"
)))
thermal_zone_unbind_cooling_device
(
tz
,
THERMAL_TRIPS_NONE
,
cdev
);
}
mutex_unlock
(
&
thermal_list_lock
);
}
tz
->
tc1
=
1
;
tz
->
tc2
=
1
;
if
(
!
tz
->
passive_delay
)
tz
->
passive_delay
=
1000
;
if
(
!
tz
->
polling_delay
)
tz
->
polling_delay
=
10000
;
tz
->
forced_passive
=
state
;
thermal_zone_device_update
(
tz
);
return
count
;
}
static
ssize_t
passive_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
thermal_zone_device
*
tz
=
to_thermal_zone
(
dev
);
return
sprintf
(
buf
,
"%d
\n
"
,
tz
->
forced_passive
);
}
static
DEVICE_ATTR
(
type
,
0444
,
type_show
,
NULL
);
static
DEVICE_ATTR
(
temp
,
0444
,
temp_show
,
NULL
);
static
DEVICE_ATTR
(
mode
,
0644
,
mode_show
,
mode_store
);
static
DEVICE_ATTR
(
passive
,
S_IRUGO
|
S_IWUSR
,
passive_show
,
\
passive_store
);
static
struct
device_attribute
trip_point_attrs
[]
=
{
__ATTR
(
trip_point_0_type
,
0444
,
trip_point_type_show
,
NULL
),
...
...
@@ -236,8 +339,13 @@ thermal_cooling_device_max_state_show(struct device *dev,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
thermal_cooling_device
*
cdev
=
to_cooling_device
(
dev
);
unsigned
long
state
;
int
ret
;
return
cdev
->
ops
->
get_max_state
(
cdev
,
buf
);
ret
=
cdev
->
ops
->
get_max_state
(
cdev
,
&
state
);
if
(
ret
)
return
ret
;
return
sprintf
(
buf
,
"%ld
\n
"
,
state
);
}
static
ssize_t
...
...
@@ -245,8 +353,13 @@ thermal_cooling_device_cur_state_show(struct device *dev,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
thermal_cooling_device
*
cdev
=
to_cooling_device
(
dev
);
unsigned
long
state
;
int
ret
;
return
cdev
->
ops
->
get_cur_state
(
cdev
,
buf
);
ret
=
cdev
->
ops
->
get_cur_state
(
cdev
,
&
state
);
if
(
ret
)
return
ret
;
return
sprintf
(
buf
,
"%ld
\n
"
,
state
);
}
static
ssize_t
...
...
@@ -255,10 +368,10 @@ thermal_cooling_device_cur_state_store(struct device *dev,
const
char
*
buf
,
size_t
count
)
{
struct
thermal_cooling_device
*
cdev
=
to_cooling_device
(
dev
);
int
state
;
unsigned
long
state
;
int
result
;
if
(
!
sscanf
(
buf
,
"%d
\n
"
,
&
state
))
if
(
!
sscanf
(
buf
,
"%
l
d
\n
"
,
&
state
))
return
-
EINVAL
;
if
(
state
<
0
)
...
...
@@ -312,13 +425,20 @@ static DEVICE_ATTR(name, 0444, name_show, NULL);
static
ssize_t
temp_input_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
long
temperature
;
int
ret
;
struct
thermal_hwmon_attr
*
hwmon_attr
=
container_of
(
attr
,
struct
thermal_hwmon_attr
,
attr
);
struct
thermal_zone_device
*
tz
=
container_of
(
hwmon_attr
,
struct
thermal_zone_device
,
temp_input
);
return
tz
->
ops
->
get_temp
(
tz
,
buf
);
ret
=
tz
->
ops
->
get_temp
(
tz
,
&
temperature
);
if
(
ret
)
return
ret
;
return
sprintf
(
buf
,
"%ld
\n
"
,
temperature
);
}
static
ssize_t
...
...
@@ -330,8 +450,14 @@ temp_crit_show(struct device *dev, struct device_attribute *attr,
struct
thermal_zone_device
*
tz
=
container_of
(
hwmon_attr
,
struct
thermal_zone_device
,
temp_crit
);
long
temperature
;
int
ret
;
ret
=
tz
->
ops
->
get_trip_temp
(
tz
,
0
,
&
temperature
);
if
(
ret
)
return
ret
;
return
tz
->
ops
->
get_trip_temp
(
tz
,
0
,
buf
);
return
sprintf
(
buf
,
"%ld
\n
"
,
temperature
);
}
...
...
@@ -452,6 +578,97 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
}
#endif
static
void
thermal_zone_device_set_polling
(
struct
thermal_zone_device
*
tz
,
int
delay
)
{
cancel_delayed_work
(
&
(
tz
->
poll_queue
));
if
(
!
delay
)
return
;
if
(
delay
>
1000
)
schedule_delayed_work
(
&
(
tz
->
poll_queue
),
round_jiffies
(
msecs_to_jiffies
(
delay
)));
else
schedule_delayed_work
(
&
(
tz
->
poll_queue
),
msecs_to_jiffies
(
delay
));
}
static
void
thermal_zone_device_passive
(
struct
thermal_zone_device
*
tz
,
int
temp
,
int
trip_temp
,
int
trip
)
{
int
trend
=
0
;
struct
thermal_cooling_device_instance
*
instance
;
struct
thermal_cooling_device
*
cdev
;
long
state
,
max_state
;
/*
* Above Trip?
* -----------
* Calculate the thermal trend (using the passive cooling equation)
* and modify the performance limit for all passive cooling devices
* accordingly. Note that we assume symmetry.
*/
if
(
temp
>=
trip_temp
)
{
tz
->
passive
=
true
;
trend
=
(
tz
->
tc1
*
(
temp
-
tz
->
last_temperature
))
+
(
tz
->
tc2
*
(
temp
-
trip_temp
));
/* Heating up? */
if
(
trend
>
0
)
{
list_for_each_entry
(
instance
,
&
tz
->
cooling_devices
,
node
)
{
if
(
instance
->
trip
!=
trip
)
continue
;
cdev
=
instance
->
cdev
;
cdev
->
ops
->
get_cur_state
(
cdev
,
&
state
);
cdev
->
ops
->
get_max_state
(
cdev
,
&
max_state
);
if
(
state
++
<
max_state
)
cdev
->
ops
->
set_cur_state
(
cdev
,
state
);
}
}
else
if
(
trend
<
0
)
{
/* Cooling off? */
list_for_each_entry
(
instance
,
&
tz
->
cooling_devices
,
node
)
{
if
(
instance
->
trip
!=
trip
)
continue
;
cdev
=
instance
->
cdev
;
cdev
->
ops
->
get_cur_state
(
cdev
,
&
state
);
cdev
->
ops
->
get_max_state
(
cdev
,
&
max_state
);
if
(
state
>
0
)
cdev
->
ops
->
set_cur_state
(
cdev
,
--
state
);
}
}
return
;
}
/*
* Below Trip?
* -----------
* Implement passive cooling hysteresis to slowly increase performance
* and avoid thrashing around the passive trip point. Note that we
* assume symmetry.
*/
list_for_each_entry
(
instance
,
&
tz
->
cooling_devices
,
node
)
{
if
(
instance
->
trip
!=
trip
)
continue
;
cdev
=
instance
->
cdev
;
cdev
->
ops
->
get_cur_state
(
cdev
,
&
state
);
cdev
->
ops
->
get_max_state
(
cdev
,
&
max_state
);
if
(
state
>
0
)
cdev
->
ops
->
set_cur_state
(
cdev
,
--
state
);
if
(
state
==
0
)
tz
->
passive
=
false
;
}
}
static
void
thermal_zone_device_check
(
struct
work_struct
*
work
)
{
struct
thermal_zone_device
*
tz
=
container_of
(
work
,
struct
thermal_zone_device
,
poll_queue
.
work
);
thermal_zone_device_update
(
tz
);
}
/**
* thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
...
...
@@ -721,26 +938,114 @@ void thermal_cooling_device_unregister(struct
EXPORT_SYMBOL
(
thermal_cooling_device_unregister
);
/**
* thermal_zone_device_update - force an update of a thermal zone's state
* @ttz: the thermal zone to update
*/
void
thermal_zone_device_update
(
struct
thermal_zone_device
*
tz
)
{
int
count
,
ret
=
0
;
long
temp
,
trip_temp
;
enum
thermal_trip_type
trip_type
;
struct
thermal_cooling_device_instance
*
instance
;
struct
thermal_cooling_device
*
cdev
;
mutex_lock
(
&
tz
->
lock
);
tz
->
ops
->
get_temp
(
tz
,
&
temp
);
for
(
count
=
0
;
count
<
tz
->
trips
;
count
++
)
{
tz
->
ops
->
get_trip_type
(
tz
,
count
,
&
trip_type
);
tz
->
ops
->
get_trip_temp
(
tz
,
count
,
&
trip_temp
);
switch
(
trip_type
)
{
case
THERMAL_TRIP_CRITICAL
:
if
(
temp
>
trip_temp
)
{
if
(
tz
->
ops
->
notify
)
ret
=
tz
->
ops
->
notify
(
tz
,
count
,
trip_type
);
if
(
!
ret
)
{
printk
(
KERN_EMERG
"Critical temperature reached (%ld C), shutting down.
\n
"
,
temp
/
1000
);
orderly_poweroff
(
true
);
}
}
break
;
case
THERMAL_TRIP_HOT
:
if
(
temp
>
trip_temp
)
if
(
tz
->
ops
->
notify
)
tz
->
ops
->
notify
(
tz
,
count
,
trip_type
);
break
;
case
THERMAL_TRIP_ACTIVE
:
list_for_each_entry
(
instance
,
&
tz
->
cooling_devices
,
node
)
{
if
(
instance
->
trip
!=
count
)
continue
;
cdev
=
instance
->
cdev
;
if
(
temp
>
trip_temp
)
cdev
->
ops
->
set_cur_state
(
cdev
,
1
);
else
cdev
->
ops
->
set_cur_state
(
cdev
,
0
);
}
break
;
case
THERMAL_TRIP_PASSIVE
:
if
(
temp
>
trip_temp
||
tz
->
passive
)
thermal_zone_device_passive
(
tz
,
temp
,
trip_temp
,
count
);
break
;
}
}
if
(
tz
->
forced_passive
)
thermal_zone_device_passive
(
tz
,
temp
,
tz
->
forced_passive
,
THERMAL_TRIPS_NONE
);
tz
->
last_temperature
=
temp
;
if
(
tz
->
passive
)
thermal_zone_device_set_polling
(
tz
,
tz
->
passive_delay
);
else
if
(
tz
->
polling_delay
)
thermal_zone_device_set_polling
(
tz
,
tz
->
polling_delay
);
mutex_unlock
(
&
tz
->
lock
);
}
EXPORT_SYMBOL
(
thermal_zone_device_update
);
/**
* thermal_zone_device_register - register a new thermal zone device
* @type: the thermal zone device type
* @trips: the number of trip points the thermal zone support
* @devdata: private device data
* @ops: standard thermal zone device callbacks
* @tc1: thermal coefficient 1 for passive calculations
* @tc2: thermal coefficient 2 for passive calculations
* @passive_delay: number of milliseconds to wait between polls when
* performing passive cooling
* @polling_delay: number of milliseconds to wait between polls when checking
* whether trip points have been crossed (0 for interrupt
* driven systems)
*
* thermal_zone_device_unregister() must be called when the device is no
* longer needed.
* longer needed. The passive cooling formula uses tc1 and tc2 as described in
* section 11.1.5.1 of the ACPI specification 3.0.
*/
struct
thermal_zone_device
*
thermal_zone_device_register
(
char
*
type
,
int
trips
,
void
*
devdata
,
struct
thermal_zone_device_ops
*
ops
)
*
ops
,
int
tc1
,
int
tc2
,
int
passive_delay
,
int
polling_delay
)
{
struct
thermal_zone_device
*
tz
;
struct
thermal_cooling_device
*
pos
;
enum
thermal_trip_type
trip_type
;
int
result
;
int
count
;
int
passive
=
0
;
if
(
strlen
(
type
)
>=
THERMAL_NAME_LENGTH
)
return
ERR_PTR
(
-
EINVAL
);
...
...
@@ -769,6 +1074,11 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
tz
->
device
.
class
=
&
thermal_class
;
tz
->
devdata
=
devdata
;
tz
->
trips
=
trips
;
tz
->
tc1
=
tc1
;
tz
->
tc2
=
tc2
;
tz
->
passive_delay
=
passive_delay
;
tz
->
polling_delay
=
polling_delay
;
dev_set_name
(
&
tz
->
device
,
"thermal_zone%d"
,
tz
->
id
);
result
=
device_register
(
&
tz
->
device
);
if
(
result
)
{
...
...
@@ -798,8 +1108,18 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
TRIP_POINT_ATTR_ADD
(
&
tz
->
device
,
count
,
result
);
if
(
result
)
goto
unregister
;
tz
->
ops
->
get_trip_type
(
tz
,
count
,
&
trip_type
);
if
(
trip_type
==
THERMAL_TRIP_PASSIVE
)
passive
=
1
;
}
if
(
!
passive
)
result
=
device_create_file
(
&
tz
->
device
,
&
dev_attr_passive
);
if
(
result
)
goto
unregister
;
result
=
thermal_add_hwmon_sysfs
(
tz
);
if
(
result
)
goto
unregister
;
...
...
@@ -814,6 +1134,10 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
}
mutex_unlock
(
&
thermal_list_lock
);
INIT_DELAYED_WORK
(
&
(
tz
->
poll_queue
),
thermal_zone_device_check
);
thermal_zone_device_update
(
tz
);
if
(
!
result
)
return
tz
;
...
...
@@ -853,6 +1177,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
tz
->
ops
->
unbind
(
tz
,
cdev
);
mutex_unlock
(
&
thermal_list_lock
);
thermal_zone_device_set_polling
(
tz
,
0
);
if
(
tz
->
type
[
0
])
device_remove_file
(
&
tz
->
device
,
&
dev_attr_type
);
device_remove_file
(
&
tz
->
device
,
&
dev_attr_temp
);
...
...
include/linux/thermal.h
浏览文件 @
4f3bff70
...
...
@@ -27,27 +27,46 @@
#include <linux/idr.h>
#include <linux/device.h>
#include <linux/workqueue.h>
struct
thermal_zone_device
;
struct
thermal_cooling_device
;
enum
thermal_device_mode
{
THERMAL_DEVICE_DISABLED
=
0
,
THERMAL_DEVICE_ENABLED
,
};
enum
thermal_trip_type
{
THERMAL_TRIP_ACTIVE
=
0
,
THERMAL_TRIP_PASSIVE
,
THERMAL_TRIP_HOT
,
THERMAL_TRIP_CRITICAL
,
};
struct
thermal_zone_device_ops
{
int
(
*
bind
)
(
struct
thermal_zone_device
*
,
struct
thermal_cooling_device
*
);
int
(
*
unbind
)
(
struct
thermal_zone_device
*
,
struct
thermal_cooling_device
*
);
int
(
*
get_temp
)
(
struct
thermal_zone_device
*
,
char
*
);
int
(
*
get_mode
)
(
struct
thermal_zone_device
*
,
char
*
);
int
(
*
set_mode
)
(
struct
thermal_zone_device
*
,
const
char
*
);
int
(
*
get_trip_type
)
(
struct
thermal_zone_device
*
,
int
,
char
*
);
int
(
*
get_trip_temp
)
(
struct
thermal_zone_device
*
,
int
,
char
*
);
int
(
*
get_temp
)
(
struct
thermal_zone_device
*
,
unsigned
long
*
);
int
(
*
get_mode
)
(
struct
thermal_zone_device
*
,
enum
thermal_device_mode
*
);
int
(
*
set_mode
)
(
struct
thermal_zone_device
*
,
enum
thermal_device_mode
);
int
(
*
get_trip_type
)
(
struct
thermal_zone_device
*
,
int
,
enum
thermal_trip_type
*
);
int
(
*
get_trip_temp
)
(
struct
thermal_zone_device
*
,
int
,
unsigned
long
*
);
int
(
*
get_crit_temp
)
(
struct
thermal_zone_device
*
,
unsigned
long
*
);
int
(
*
notify
)
(
struct
thermal_zone_device
*
,
int
,
enum
thermal_trip_type
);
};
struct
thermal_cooling_device_ops
{
int
(
*
get_max_state
)
(
struct
thermal_cooling_device
*
,
char
*
);
int
(
*
get_cur_state
)
(
struct
thermal_cooling_device
*
,
char
*
);
int
(
*
set_cur_state
)
(
struct
thermal_cooling_device
*
,
unsigned
int
);
int
(
*
get_max_state
)
(
struct
thermal_cooling_device
*
,
unsigned
long
*
);
int
(
*
get_cur_state
)
(
struct
thermal_cooling_device
*
,
unsigned
long
*
);
int
(
*
set_cur_state
)
(
struct
thermal_cooling_device
*
,
unsigned
long
);
};
#define THERMAL_TRIPS_NONE -1
...
...
@@ -88,11 +107,19 @@ struct thermal_zone_device {
struct
device
device
;
void
*
devdata
;
int
trips
;
int
tc1
;
int
tc2
;
int
passive_delay
;
int
polling_delay
;
int
last_temperature
;
bool
passive
;
unsigned
int
forced_passive
;
struct
thermal_zone_device_ops
*
ops
;
struct
list_head
cooling_devices
;
struct
idr
idr
;
struct
mutex
lock
;
/* protect cooling devices list */
struct
list_head
node
;
struct
delayed_work
poll_queue
;
#if defined(CONFIG_THERMAL_HWMON)
struct
list_head
hwmon_node
;
struct
thermal_hwmon_device
*
hwmon
;
...
...
@@ -104,13 +131,16 @@ struct thermal_zone_device {
struct
thermal_zone_device
*
thermal_zone_device_register
(
char
*
,
int
,
void
*
,
struct
thermal_zone_device_ops
*
);
*
,
int
tc1
,
int
tc2
,
int
passive_freq
,
int
polling_freq
);
void
thermal_zone_device_unregister
(
struct
thermal_zone_device
*
);
int
thermal_zone_bind_cooling_device
(
struct
thermal_zone_device
*
,
int
,
struct
thermal_cooling_device
*
);
int
thermal_zone_unbind_cooling_device
(
struct
thermal_zone_device
*
,
int
,
struct
thermal_cooling_device
*
);
void
thermal_zone_device_update
(
struct
thermal_zone_device
*
);
struct
thermal_cooling_device
*
thermal_cooling_device_register
(
char
*
,
void
*
,
struct
thermal_cooling_device_ops
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录