echo freeze
> /sys/power/state
echo mem
> /sys/power/state
echo disk
> /sys/power/state
有关每个系统低功耗状态的详细信息,请参考系统电源管理休眠状态。
关于Linux 挂起/休眠的sysfs接口的更多细节,如上面提到的/sys/power/state
,请参考https://www.kernel.org/doc/Documentation/power/interface.txt。
英特尔开源技术中心(OTC)中国内核电源团队多年来一直致力于Linux电源管理子系统的质量改进工作。我们处理问题的经验,无论是通过电子邮件在Linux邮件列表或通过https://bugzilla.kernel.org/
显示如下:
因此,编写这个文档是为了帮助用户做一些调试例程,以便他们可以做以下事情:
在本文档中
因此,当用户遇到与挂起/休眠相关的问题时,我们建议用户在第4章中找到描述遇到的问题的适当部分,并直接按照该部分的逐步说明进行操作。
initcall_debug
[ 76.201970] calling 0000:00:02.0+ @ 2298, parent: pci0000:00
[ 76.217006] call 0000:00:02.0+ returned 0 after 14677 usec
负结果意味着回调要么包含一些错误/警告,要么花费不合理的长时间来完成。
no_console_suspend
在内核命令行cmdline中添加no_console_suspend
启动选项可以在挂起/休眠期间禁用控制台的挂起。添加此选项后,调试消息可以到达各种控制台,而系统的其他部分则处于休眠状态。这可能不能在所有控制台都可靠地工作,但是众所周知,它可以在串口和VGA控制台上工作。
ignore_loglevel
在内核命令行cmdline中添加ignore_loglevel
启动选项可以将所有内核消息输出到控制台,无论当前的loglevel是什么,这对于调试非常有用。
对于STI/STR,添加dyndbg="file .c +p"
引导选项,对于HTD,添加file swap.c +p;file snapshot.c +p;file hibernate.c +p
引导选项,用这些选项启用动态调试,这样我们可以在休眠过程中收集更多的信息。
serial console
serial console
输出对于跟踪某些系统挂起问题非常有用,尤其是当VGA控制台宕机或无法记录完整的崩溃日志时。要启用serial console
,请将console=ttyS0,115200
和no_console_suspend
添加到内核的命令行cmdline,然后在另一台机器上使用minicom
或GNU screen
等程序将串行端口设置为115200 8-N-1
以捕获日志。有关更多细节,请参考https://www.kernel.org/doc/Documentation/serial-console.txt
。
RTC跟踪
RTC跟踪是一种特性,用于在挂起/恢复期间以文件+行形式捕获损坏的驱动程序,将其保存到CMOS SRAM中,并在下一次引导期间恢复它。要启用这一点,请确保内核是使用CONFIG_PM_TRACE_RTC=y
构建的,并且通过echo 0 > /sys/power/pm_async
禁用pm异步。更多信息请参考https://www.kernel.org/doc/Documentation/power/s2ram.txt
。
测试结果:从STI/STR/HTD
失败重启后的dmesg输出。请注意,重新启动必须在三分钟内发生,否则保存在SRAM中的数据将被破坏。
pm_async
现在Linux会同时挂起和恢复所有设备,以节省时间。可以使用echo 0 > /sys/power/pm_async
来检查挂起/休眠失败是否由未知的设备依赖问题引起。这也可以用来调优驱动程序挂起/恢复延迟。
测试结果:在禁用异步暂停/恢复后,检查问题是否仍然存在。
pm_test
pm_test
是一种调试方法,系统可以部分地进行STR/HTD
调试,它可以用来缩小导致STI/STR/HTD
故障的代码的范围。请参考https://www.kernel.org/doc/Documentation/power/basic-pm-debugging.txt
获得更多细节。
测试结果可以检查哪些测试模式有问题,哪些测试模式没有问题。dmesg输出的失效模式,如果可能的话。
ACPI唤醒
/proc/acpi/wakeup
列出了所有ACPI设备的唤醒能力,以及对可用物理设备的引用。如下例所示,戳这个文件可以启用/禁用设备的唤醒功能。例如,你可以通过以下步骤禁用/启用“启用”/“禁用”设备:
root@linux-machine# cat /proc/acpi/wakeup
Device S-state Status Sysfs node
...
EHC1 S4 *enabled pci:0000:00:1d.0
...
root@linux-machine# echo EHC1 > /proc/acpi/wakeup
root@linux-machine# cat /proc/acpi/wakeup
Device S-state Status Sysfs node
...
EHC1 S4 *disabled pci:0000:00:1d.0
...
测试结果可以禁用和启用每个设备的唤醒功能可以解决这个问题。
acpidump
acpidump
是一个可以用来转储BIOS提供的ACPI表的工具。这在调试可能由ACPI引起的挂起/休眠问题时非常有用。要获得该工具,只需转到内核源代码的tools/power/acpi/
目录,并运行make
。
rtcwake
rtcwake
是一个工具,可以用来进入系统休眠状态(挂起/休眠),直到指定的唤醒时间。你可以很容易地使用它来执行挂起/休眠压力测试。例如,你可以使用这个简单的脚本轻松运行1000个STR循环:
for i in $(seq 1000); do
rtcwake –m mem –s 30
done
analyze_suspend
analyze_syspend工具为系统开发人员提供了可视化挂起和恢复之间的活动的功能,允许他们识别效率低下和瓶颈。例如,你可以使用以下命令启动:
./analyze_suspend.py -rtcwake 30 -f -m mem
30秒后系统自动恢复并在./suspend-yymmddyy-hhmmss
目录下生成3个文件:
mem_dmesg.txt mem_ftrace.txt mem.html
您可以首先用浏览器打开mem.html
文件,然后深入mem_ftrace.txt
查找数据细节。你可以通过git获得analyze_suspend
工具:
git clone https://github.com/01org/suspendresume.git
更多细节,请访问主页:https://01.org/endresume
。
测试结果:mem_dmesg.txt mem_ftrace.txt mem.html
磁盘模式
这只适用于HTD。尝试echo {shutdown/reboot} > /sys/power/disk
跳过一些平台特定的代码,这些代码在运行echo disk > /sys/power/state
之前可能会有bug。在ACPI平台上,系统实际进入的是S5而不是S4。
测试结果:当/sys/power/disk等于关机或重启时,是否仍然存在问题。
回归是指挂起/休眠可以正常工作,但是在升级内核之后会失败。在这种情况下,找到根本原因并解决问题的最快速和最有效的方法是使用git bisect找出是哪个提交导致了问题,然后将问题报告给提交作者/组件所有者。
驱动损坏可能导致:
suspend
(suspend
命令返回错误代码)。因此,当您遇到与挂起/休眠相关的问题时,通常首先要检查这个问题是否是驱动程序特有的问题。如果在恢复/挂起失败后系统是响应的(可以通过VGA/serial console
、ssh等访问系统),尝试使用启动选项initcall_debug
和no_console_suspend
重现问题。如果有,做以下事情:
modprobe -r foo && echo mem > /sys/power/state & modprobe foo
如果系统不响应,请执行以下操作:
serial console
并使用initcall_debug
和no_console_suspend
引导。serial console
输出是否有驱动程序引起的错误/警告。Kconfig
设置构建驱动程序。modprobe -r foo && echo mem > /sys/power/state & modprobe foo
如果系统在恢复后运行良好,但是一些驱动程序不再工作,请执行以下操作:
modprobe -r foo && echo mem > /sys/power/state & modprobe foo
如果问题是不可重现的,这是一个驱动特有的问题。
对于这些问题,直接向驱动程序/组件所有者提交错误报告,因为这些问题表明有问题的驱动程序/组件破坏了Linux 挂起/休眠。
下面几节将讨论一些典型的驱动程序特有的问题,这些问题可能会导致挂起/休眠中断。
当系统在挂起/休眠期间挂起或恢复后监视器不再显示时,请尝试以下步骤:
CONFIG_DRM_I915=n
。nomodeset modprobe.blacklist=i915
,因为有时i915驱动程序可能会被其他组件探测。serial console
和SSH都不可用,请按PS2键盘上的Num Lock
。如果Num Lock LED
在您按下键时亮起,则使用键盘输入reboot
。虽然监视器没有显示,但是如果系统重新启动成功,那么很可能系统工作正常,这是一个图形问题。对于图形问题,请在https://bugs.freedesktop.org/
中提交一个错误。例如,我们从dmesg输出的下面几行代码中得到提示,将挂起/休眠问题的根本原因隔离到图形驱动程序中:
[ 218.176542] ------------[ cut here ]------------
[ 218.176550] WARNING: CPU: 1 PID: 221 at drivers/gpu/drm/i915/intel_lrc.c:1100 gen8_init_rcs_context+0x15d/0x160()
[ 218.176552] WARN_ON(w->count == 0)
[ 218.176553] Modules linked in:
[ 218.176556] CPU: 1 PID: 221 Comm: kworker/u16:3 Tainted: G W 3.18.0-eywa-dirty #30
[ 218.176558] Hardware name: Intel Corporation Skylake Client platform/Skylake Y LPDDR3 RVP3, BIOS SKLSE2P1.86C.B060.R01.1411140050 11/14/2014
[ 218.176564] Workqueue: events_unbound async_run_entry_fn
[ 218.176567] 0000000000000009 ffff88009a96fad8 ffffffff82431683 0000000000000001
[ 218.176570] ffff88009a96fb28 ffff88009a96fb18 ffffffff8111e001 00000000fffe6b2d
[ 218.176573] ffff88009b42f300 0000000000000005 ffff88009b670000 ffff88009b671ce8
[ 218.176574] Call Trace:
...
[ 218.176657] ---[ end trace f587fddb962240b1 ]---
我们还没有看到音频驱动程序暂停/休眠,但音频驱动程序本身可能需要很长时间才能恢复,如下面的例子所示:
[ 61.273112] calling hdaudioC0D2+ @ 1236, parent: 0000:00:1f.3
[ 64.295757] snd_hda_intel 0000:00:1f.3: azx_get_response timeout, switching to polling mode: last cmd=0x208f8100
[ 65.303916] snd_hda_intel 0000:00:1f.3: No response from codec, disabling MSI: last cmd=0x208f8100
[ 66.312147] snd_hda_intel 0000:00:1f.3: azx_get_response timeout, switching to single_cmd mode: last cmd=0x208f8100
[ 66.312402] azx_single_wait_for_response: 153 callbacks suppressed
[ 66.323406] snd_hda_codec_hdmi hdaudioC0D2: Unable to sync register 0x2f0d00. -5
[ 66.323791] snd_hda_codec_hdmi hdaudioC0D2: HDMI: invalid ELD buf size -1
[ 66.324179] snd_hda_codec_hdmi hdaudioC0D2: HDMI: invalid ELD buf size -1
[ 66.324565] snd_hda_codec_hdmi hdaudioC0D2: HDMI: invalid ELD buf size -1
[ 66.324571] call hdaudioC0D2+ returned 0 after 4932188 usecs
在这种情况下,提交一个音频错误。
通常,USB问题不会挂起系统,但一些USB设备可能会停止工作后,系统恢复。如果一些USB设备(如USB鼠标/键盘/网络)在恢复系统后停止工作,而其他设备(如PS/2键盘)似乎可以正常工作,请检查dmesg/串行日志中的USB警告。如果您发现一个警告,这可能是一个USB问题。例如:
[ 21.203077] xhci-hcd: probe of xhci-hcd.1.auto failed with error -110
在这种情况下,提交USB错误。
MMC失败会导致挂起操作(特别是挂起磁盘)失败。在挂起期间,检查dmesg和serial console
输出中的MMC警告。例如:
[90.373541] mmc1: Timeout waiting for hardware interrupt.
[160.493633] mmc1: error -110 during resume (card was removed?)
如果rootfs不在MMC上,请再次尝试使用modprobe.blacklist = mmc_block
启动选项。如果rootfs在MMC上,请使用具有相同内核/发行版的USB驱动器,然后再次尝试使用modprobe.blacklist = mmc_block
。如果在将MMC驱动程序列入黑名单后问题已经解决,则提交MMC错误。
我们也曾看到若干个由I2C引发的错误,比如:
calling i2c_designware.0+ @ 2867, parent: 0000:00:15.0
------------[ cut here ]------------
WARNING: CPU: 1 PID: 2867 at drivers/clk/clk.c:845 __clk_disable+0x5b/0x60()
[] warn_slowpath_null+0x1a/0x20
[] __clk_disable+0x5b/0x60
[] clk_disable+0x37/0x50
[] dw_i2c_suspend+0x29/0x40
在这种情况下用文件记录I2C错误并提交。
运行cat /sys/power/state
,输出未列举freeze/mem/disk
,从而系统不能进入STI/STR/HTD
状态。
CONFIG_SUSPEND
构建。如果否就设置它。relative_sleep_states=1
引导。如果有就移除它。CONFIG_SUSPEND
构建。如果否就设置它。ACPI: (supports S0 S3 S4 S5)
。如果S3没有列出,它通常意味着平台不支持S3。如果你不确定,保存一个挂起/休眠的缺陷到文件。CONFIG_HIBERNATION
构建。如果否就用CONFIG_HIBERNATION=y
重新构建。ACPI: (supports S0 S3 S4 S5)
。如果S4没有列出,它通常意味着平台不支持S4。如果你不确定,保存一个挂起/休眠的缺陷到文件。[platform] {STI, STR, HTD}: state not available,
,连同dmesg
输出,acpidump
输出和你正在使用的内核配置文件为挂起/休眠缺陷并提交。运行: echo freeze/mem/disk > /sys/power/state
,返回有错误代码。
initcall_debug
和no_console_suspend
。[Platform] {STI, STR, HTD}: failed to suspend
,连同挂起失败后dmesg输出和返回的错误代码。在运行echo freeze/mem/disk > /sys/power/state
之后,屏幕变黑,就像挂起/休眠成功一样,但是系统变得没有响应,无法唤醒到工作状态。这可能在挂起或恢复期间发生。或者,系统进入预期的睡眠状态,但是在恢复时没有响应,只显示黑屏或崩溃日志。例如,风扇开始旋转,任何现有的电源按钮背光改变,但系统永远不会回到工作状态。
[Platform] {STI, STR, HTD}: system hangs during suspend/resume
,以及问题重现后的串口控制台输出/截图,/var/log/kern.log
内容,以及磁盘模式(仅限HTD)、pm_test
、pm_async
和rtc
跟踪的测试结果。屏幕变暗,重新启动,用户什么都不做。
{STI, STR, HTD}: system reboot during suspend/resume
,以及问题重现后的串口控制台输出/截图,/var/log/kern.log
内容,以及磁盘模式(仅限HTD)、pm_test
、pm_async
和rtc
跟踪的测试结果。系统可以挂起并从STI/STR/HTD状态恢复,但是某些组件或驱动程序可能无法工作,或者在恢复后的dmesg中可能出现错误或警告。
[Platform] {STI, STR, HTD}: xxx broken after resume
,以及恢复后dmesg输出。挂起后系统很快就会回到工作状态,而用户不做任何事情。dmesg显示系统已经完成了一个完整的挂起/恢复周期。
当您按下电源键、使用键盘等时,系统不会自动唤醒。
检查这是否是回归。对于STI,检查驱动程序是否有自己的托管中断。如果是,检查enable_irq_wake()
是否为驱动程序使用的中断调用。如果不是,将其添加到驱动程序.probe()
或.suspend()
回调中。例如:
static int bu21013_suspend(struct device *dev)
{
...
if (device_may_wakeup(&client->dev))
enable_irq_wake(bu21013_data->irq);
else
disable_irq(bu21013_data->irq);
...
return 0;
}
如果问题仍然存在,文件保存挂起/休眠缺陷[Platform] {STI, STR, HTD}: XXX cannot wake up the system
,确保包含dmesg、acpidump输出、ACPI唤醒的测试结果以及缺陷报告。
总的/特定的驱动程序挂起/恢复时间比预期/要求的长。
你已经确定了一个特定的驱动程序,需要花太多的时间暂停/恢复,文件错误的驱动程序所有者。
如果总体挂起/恢复延迟很高,请执行以下操作:
initcall_debug
和no_console_suspend
启动选项重新启动。analyze_suspend
重做挂起/恢复。analyze_suspend
的测试结果一起报告给驱动程序/组件所有者。[Platform] HTD: hibernate fails when disk driver is built as module
。initcall_debug
、no_console_suspend
、ignore_loglevel
、动态调试和serial console
重新启动。如果您已经缩小了问题的范围,或者发现问题的根本原因是驱动程序特定的问题:
如果不是驱动程序特定的问题,或者在调试之后您不确定问题是什么,可以在https://bugzilla.kernel.org/enter_bug.cgi?product=Power%20Management,将组件设置为“休眠/挂起”,并包含所需的调试信息和测试结果。