Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
aec1d96c
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
aec1d96c
编写于
10月 01, 2014
作者:
H
Heiko Stuebner
浏览文件
操作
浏览文件
下载
差异文件
Merge tag 'tags/restart-handler-for-v3.18' into v3.18-next/cpuclk
Immutable branch with restart handler patches for v3.18
上级
fc69ed70
6cd6d94d
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
165 addition
and
42 deletion
+165
-42
arch/arm/kernel/process.c
arch/arm/kernel/process.c
+5
-7
arch/arm64/kernel/process.c
arch/arm64/kernel/process.c
+2
-1
drivers/power/reset/restart-poweroff.c
drivers/power/reset/restart-poweroff.c
+2
-1
drivers/watchdog/alim7101_wdt.c
drivers/watchdog/alim7101_wdt.c
+32
-10
drivers/watchdog/moxart_wdt.c
drivers/watchdog/moxart_wdt.c
+20
-12
drivers/watchdog/sunxi_wdt.c
drivers/watchdog/sunxi_wdt.c
+20
-11
include/linux/reboot.h
include/linux/reboot.h
+3
-0
kernel/reboot.c
kernel/reboot.c
+81
-0
未找到文件。
arch/arm/kernel/process.c
浏览文件 @
aec1d96c
...
...
@@ -114,18 +114,13 @@ void soft_restart(unsigned long addr)
BUG
();
}
static
void
null_restart
(
enum
reboot_mode
reboot_mode
,
const
char
*
cmd
)
{
}
/*
* Function pointers to optional machine specific functions
*/
void
(
*
pm_power_off
)(
void
);
EXPORT_SYMBOL
(
pm_power_off
);
void
(
*
arm_pm_restart
)(
enum
reboot_mode
reboot_mode
,
const
char
*
cmd
)
=
null_restart
;
EXPORT_SYMBOL_GPL
(
arm_pm_restart
);
void
(
*
arm_pm_restart
)(
enum
reboot_mode
reboot_mode
,
const
char
*
cmd
);
/*
* This is our default idle handler.
...
...
@@ -230,7 +225,10 @@ void machine_restart(char *cmd)
local_irq_disable
();
smp_send_stop
();
arm_pm_restart
(
reboot_mode
,
cmd
);
if
(
arm_pm_restart
)
arm_pm_restart
(
reboot_mode
,
cmd
);
else
do_kernel_restart
(
cmd
);
/* Give a grace period for failure to restart of 1s */
mdelay
(
1000
);
...
...
arch/arm64/kernel/process.c
浏览文件 @
aec1d96c
...
...
@@ -98,7 +98,6 @@ void (*pm_power_off)(void);
EXPORT_SYMBOL_GPL
(
pm_power_off
);
void
(
*
arm_pm_restart
)(
enum
reboot_mode
reboot_mode
,
const
char
*
cmd
);
EXPORT_SYMBOL_GPL
(
arm_pm_restart
);
/*
* This is our default idle handler.
...
...
@@ -180,6 +179,8 @@ void machine_restart(char *cmd)
/* Now call the architecture specific reboot code. */
if
(
arm_pm_restart
)
arm_pm_restart
(
reboot_mode
,
cmd
);
else
do_kernel_restart
(
cmd
);
/*
* Whoops - the architecture was unable to reboot.
...
...
drivers/power/reset/restart-poweroff.c
浏览文件 @
aec1d96c
...
...
@@ -20,7 +20,8 @@
static
void
restart_poweroff_do_poweroff
(
void
)
{
arm_pm_restart
(
REBOOT_HARD
,
NULL
);
reboot_mode
=
REBOOT_HARD
;
machine_restart
(
NULL
);
}
static
int
restart_poweroff_probe
(
struct
platform_device
*
pdev
)
...
...
drivers/watchdog/alim7101_wdt.c
浏览文件 @
aec1d96c
...
...
@@ -301,6 +301,28 @@ static struct miscdevice wdt_miscdev = {
.
fops
=
&
wdt_fops
,
};
static
int
wdt_restart_handle
(
struct
notifier_block
*
this
,
unsigned
long
mode
,
void
*
cmd
)
{
/*
* Cobalt devices have no way of rebooting themselves other
* than getting the watchdog to pull reset, so we restart the
* watchdog on reboot with no heartbeat.
*/
wdt_change
(
WDT_ENABLE
);
/* loop until the watchdog fires */
while
(
true
)
;
return
NOTIFY_DONE
;
}
static
struct
notifier_block
wdt_restart_handler
=
{
.
notifier_call
=
wdt_restart_handle
,
.
priority
=
128
,
};
/*
* Notifier for system down
*/
...
...
@@ -311,15 +333,6 @@ static int wdt_notify_sys(struct notifier_block *this,
if
(
code
==
SYS_DOWN
||
code
==
SYS_HALT
)
wdt_turnoff
();
if
(
code
==
SYS_RESTART
)
{
/*
* Cobalt devices have no way of rebooting themselves other
* than getting the watchdog to pull reset, so we restart the
* watchdog on reboot with no heartbeat
*/
wdt_change
(
WDT_ENABLE
);
pr_info
(
"Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second
\n
"
);
}
return
NOTIFY_DONE
;
}
...
...
@@ -338,6 +351,7 @@ static void __exit alim7101_wdt_unload(void)
/* Deregister */
misc_deregister
(
&
wdt_miscdev
);
unregister_reboot_notifier
(
&
wdt_notifier
);
unregister_restart_handler
(
&
wdt_restart_handler
);
pci_dev_put
(
alim7101_pmu
);
}
...
...
@@ -390,11 +404,17 @@ static int __init alim7101_wdt_init(void)
goto
err_out
;
}
rc
=
register_restart_handler
(
&
wdt_restart_handler
);
if
(
rc
)
{
pr_err
(
"cannot register restart handler (err=%d)
\n
"
,
rc
);
goto
err_out_reboot
;
}
rc
=
misc_register
(
&
wdt_miscdev
);
if
(
rc
)
{
pr_err
(
"cannot register miscdev on minor=%d (err=%d)
\n
"
,
wdt_miscdev
.
minor
,
rc
);
goto
err_out_re
boo
t
;
goto
err_out_re
star
t
;
}
if
(
nowayout
)
...
...
@@ -404,6 +424,8 @@ static int __init alim7101_wdt_init(void)
timeout
,
nowayout
);
return
0
;
err_out_restart:
unregister_restart_handler
(
&
wdt_restart_handler
);
err_out_reboot:
unregister_reboot_notifier
(
&
wdt_notifier
);
err_out:
...
...
drivers/watchdog/moxart_wdt.c
浏览文件 @
aec1d96c
...
...
@@ -15,12 +15,12 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/watchdog.h>
#include <linux/moduleparam.h>
#include <asm/system_misc.h>
#define REG_COUNT 0x4
#define REG_MODE 0x8
#define REG_ENABLE 0xC
...
...
@@ -29,17 +29,22 @@ struct moxart_wdt_dev {
struct
watchdog_device
dev
;
void
__iomem
*
base
;
unsigned
int
clock_frequency
;
struct
notifier_block
restart_handler
;
};
static
struct
moxart_wdt_dev
*
moxart_restart_ctx
;
static
int
heartbeat
;
static
void
moxart_wdt_restart
(
enum
reboot_mode
reboot_mode
,
const
char
*
cmd
)
static
int
moxart_restart_handle
(
struct
notifier_block
*
this
,
unsigned
long
mode
,
void
*
cmd
)
{
writel
(
1
,
moxart_restart_ctx
->
base
+
REG_COUNT
);
writel
(
0x5ab9
,
moxart_restart_ctx
->
base
+
REG_MODE
);
writel
(
0x03
,
moxart_restart_ctx
->
base
+
REG_ENABLE
);
struct
moxart_wdt_dev
*
moxart_wdt
=
container_of
(
this
,
struct
moxart_wdt_dev
,
restart_handler
);
writel
(
1
,
moxart_wdt
->
base
+
REG_COUNT
);
writel
(
0x5ab9
,
moxart_wdt
->
base
+
REG_MODE
);
writel
(
0x03
,
moxart_wdt
->
base
+
REG_ENABLE
);
return
NOTIFY_DONE
;
}
static
int
moxart_wdt_stop
(
struct
watchdog_device
*
wdt_dev
)
...
...
@@ -136,8 +141,12 @@ static int moxart_wdt_probe(struct platform_device *pdev)
if
(
err
)
return
err
;
moxart_restart_ctx
=
moxart_wdt
;
arm_pm_restart
=
moxart_wdt_restart
;
moxart_wdt
->
restart_handler
.
notifier_call
=
moxart_restart_handle
;
moxart_wdt
->
restart_handler
.
priority
=
128
;
err
=
register_restart_handler
(
&
moxart_wdt
->
restart_handler
);
if
(
err
)
dev_err
(
dev
,
"cannot register restart notifier (err=%d)
\n
"
,
err
);
dev_dbg
(
dev
,
"Watchdog enabled (heartbeat=%d sec, nowayout=%d)
\n
"
,
moxart_wdt
->
dev
.
timeout
,
nowayout
);
...
...
@@ -149,9 +158,8 @@ static int moxart_wdt_remove(struct platform_device *pdev)
{
struct
moxart_wdt_dev
*
moxart_wdt
=
platform_get_drvdata
(
pdev
);
arm_pm_restart
=
NULL
;
unregister_restart_handler
(
&
moxart_wdt
->
restart_handler
)
;
moxart_wdt_stop
(
&
moxart_wdt
->
dev
);
watchdog_unregister_device
(
&
moxart_wdt
->
dev
);
return
0
;
}
...
...
drivers/watchdog/sunxi_wdt.c
浏览文件 @
aec1d96c
...
...
@@ -21,14 +21,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/types.h>
#include <linux/watchdog.h>
#include <asm/system_misc.h>
#define WDT_MAX_TIMEOUT 16
#define WDT_MIN_TIMEOUT 1
#define WDT_MODE_TIMEOUT(n) ((n) << 3)
...
...
@@ -50,6 +49,7 @@ static unsigned int timeout = WDT_MAX_TIMEOUT;
struct
sunxi_wdt_dev
{
struct
watchdog_device
wdt_dev
;
void
__iomem
*
wdt_base
;
struct
notifier_block
restart_handler
;
};
/*
...
...
@@ -74,24 +74,29 @@ static const int wdt_timeout_map[] = {
[
16
]
=
0xB
,
/* 16s */
};
static
void
__iomem
*
reboot_wdt_base
;
static
void
sun4i_wdt_restart
(
enum
reboot_mode
mode
,
const
char
*
cmd
)
static
int
sunxi_restart_handle
(
struct
notifier_block
*
this
,
unsigned
long
mode
,
void
*
cmd
)
{
struct
sunxi_wdt_dev
*
sunxi_wdt
=
container_of
(
this
,
struct
sunxi_wdt_dev
,
restart_handler
);
void
__iomem
*
wdt_base
=
sunxi_wdt
->
wdt_base
;
/* Enable timer and set reset bit in the watchdog */
writel
(
WDT_MODE_EN
|
WDT_MODE_RST_EN
,
reboot_
wdt_base
+
WDT_MODE
);
writel
(
WDT_MODE_EN
|
WDT_MODE_RST_EN
,
wdt_base
+
WDT_MODE
);
/*
* Restart the watchdog. The default (and lowest) interval
* value for the watchdog is 0.5s.
*/
writel
(
WDT_CTRL_RELOAD
,
reboot_
wdt_base
+
WDT_CTRL
);
writel
(
WDT_CTRL_RELOAD
,
wdt_base
+
WDT_CTRL
);
while
(
1
)
{
mdelay
(
5
);
writel
(
WDT_MODE_EN
|
WDT_MODE_RST_EN
,
reboot_wdt_base
+
WDT_MODE
);
writel
(
WDT_MODE_EN
|
WDT_MODE_RST_EN
,
wdt_base
+
WDT_MODE
);
}
return
NOTIFY_DONE
;
}
static
int
sunxi_wdt_ping
(
struct
watchdog_device
*
wdt_dev
)
...
...
@@ -205,8 +210,12 @@ static int sunxi_wdt_probe(struct platform_device *pdev)
if
(
unlikely
(
err
))
return
err
;
reboot_wdt_base
=
sunxi_wdt
->
wdt_base
;
arm_pm_restart
=
sun4i_wdt_restart
;
sunxi_wdt
->
restart_handler
.
notifier_call
=
sunxi_restart_handle
;
sunxi_wdt
->
restart_handler
.
priority
=
128
;
err
=
register_restart_handler
(
&
sunxi_wdt
->
restart_handler
);
if
(
err
)
dev_err
(
&
pdev
->
dev
,
"cannot register restart handler (err=%d)
\n
"
,
err
);
dev_info
(
&
pdev
->
dev
,
"Watchdog enabled (timeout=%d sec, nowayout=%d)"
,
sunxi_wdt
->
wdt_dev
.
timeout
,
nowayout
);
...
...
@@ -218,7 +227,7 @@ static int sunxi_wdt_remove(struct platform_device *pdev)
{
struct
sunxi_wdt_dev
*
sunxi_wdt
=
platform_get_drvdata
(
pdev
);
arm_pm_restart
=
NULL
;
unregister_restart_handler
(
&
sunxi_wdt
->
restart_handler
)
;
watchdog_unregister_device
(
&
sunxi_wdt
->
wdt_dev
);
watchdog_set_drvdata
(
&
sunxi_wdt
->
wdt_dev
,
NULL
);
...
...
include/linux/reboot.h
浏览文件 @
aec1d96c
...
...
@@ -38,6 +38,9 @@ extern int reboot_force;
extern
int
register_reboot_notifier
(
struct
notifier_block
*
);
extern
int
unregister_reboot_notifier
(
struct
notifier_block
*
);
extern
int
register_restart_handler
(
struct
notifier_block
*
);
extern
int
unregister_restart_handler
(
struct
notifier_block
*
);
extern
void
do_kernel_restart
(
char
*
cmd
);
/*
* Architecture-specific implementations of sys_reboot commands.
...
...
kernel/reboot.c
浏览文件 @
aec1d96c
...
...
@@ -104,6 +104,87 @@ int unregister_reboot_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL
(
unregister_reboot_notifier
);
/*
* Notifier list for kernel code which wants to be called
* to restart the system.
*/
static
ATOMIC_NOTIFIER_HEAD
(
restart_handler_list
);
/**
* register_restart_handler - Register function to be called to reset
* the system
* @nb: Info about handler function to be called
* @nb->priority: Handler priority. Handlers should follow the
* following guidelines for setting priorities.
* 0: Restart handler of last resort,
* with limited restart capabilities
* 128: Default restart handler; use if no other
* restart handler is expected to be available,
* and/or if restart functionality is
* sufficient to restart the entire system
* 255: Highest priority restart handler, will
* preempt all other restart handlers
*
* Registers a function with code to be called to restart the
* system.
*
* Registered functions will be called from machine_restart as last
* step of the restart sequence (if the architecture specific
* machine_restart function calls do_kernel_restart - see below
* for details).
* Registered functions are expected to restart the system immediately.
* If more than one function is registered, the restart handler priority
* selects which function will be called first.
*
* Restart handlers are expected to be registered from non-architecture
* code, typically from drivers. A typical use case would be a system
* where restart functionality is provided through a watchdog. Multiple
* restart handlers may exist; for example, one restart handler might
* restart the entire system, while another only restarts the CPU.
* In such cases, the restart handler which only restarts part of the
* hardware is expected to register with low priority to ensure that
* it only runs if no other means to restart the system is available.
*
* Currently always returns zero, as atomic_notifier_chain_register()
* always returns zero.
*/
int
register_restart_handler
(
struct
notifier_block
*
nb
)
{
return
atomic_notifier_chain_register
(
&
restart_handler_list
,
nb
);
}
EXPORT_SYMBOL
(
register_restart_handler
);
/**
* unregister_restart_handler - Unregister previously registered
* restart handler
* @nb: Hook to be unregistered
*
* Unregisters a previously registered restart handler function.
*
* Returns zero on success, or %-ENOENT on failure.
*/
int
unregister_restart_handler
(
struct
notifier_block
*
nb
)
{
return
atomic_notifier_chain_unregister
(
&
restart_handler_list
,
nb
);
}
EXPORT_SYMBOL
(
unregister_restart_handler
);
/**
* do_kernel_restart - Execute kernel restart handler call chain
*
* Calls functions registered with register_restart_handler.
*
* Expected to be called from machine_restart as last step of the restart
* sequence.
*
* Restarts the system immediately if a restart handler function has been
* registered. Otherwise does nothing.
*/
void
do_kernel_restart
(
char
*
cmd
)
{
atomic_notifier_call_chain
(
&
restart_handler_list
,
reboot_mode
,
cmd
);
}
void
migrate_to_reboot_cpu
(
void
)
{
/* The boot cpu is always logical cpu 0 */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录