diff --git a/translated/tech/20161018 Suspend to Idle.md b/translated/tech/20161018 Suspend to Idle.md index 5d765ba4b8..31ffa5be8e 100644 --- a/translated/tech/20161018 Suspend to Idle.md +++ b/translated/tech/20161018 Suspend to Idle.md @@ -9,9 +9,9 @@ Linux 内核提供了多种睡眠状态,各个状态通过设置系统中的 在冻结过程中,当系统进入空闲状态时会调用一个特殊的 cpu 空闲函数。这个 enter_freeze() 函数可以和调用使 cpu 空闲的 enter() 函数一样简单,也可以复杂得多。该函数复杂的程度由将 SoCs 置为低耗电模式的条件和方法决定。 -### 先决条件 +## 先决条件 -### 平台挂起条件 +### platform_suspend_ops 一般情况,为了支持 S2I,系统必须实现 platform_suspend_ops 并提供最低限度的挂起支持。这意味着至少要完成 platform_suspend_ops 中的 valid() 函数。如果 suspend to idle 和 suspend to ram 都要支持,valid 函数中应使用 suspend_valid_only_men。 @@ -31,7 +31,7 @@ freeze mem_ 一旦系统处于某种睡眠状态,系统必须要接收某个唤醒事件才能恢复系统。这些唤醒事件一般由系统的设备产生。因此一定要确保这些设备驱动使用唤醒中断,并且将自身配置为接收唤醒中断后产生唤醒事件。如果没有正确识别唤醒设备,系统收到中断后会继续保持睡眠状态而不会恢复。 -一旦设备正确实现了唤醒接口的调用,那么该设备就能产生唤醒事件。确保DT正确配置了唤醒源。下面是一个示例唤醒源配置,该文件来自(arch/arm/boot/dst/am335x-evm.dts): +一旦设备正确实现了唤醒接口的调用,就可用来生成唤醒事件。请确保 DT 文件正确配置了唤醒源。下面是一个配置唤醒源示例,该文件来自(arch/arm/boot/dst/am335x-evm.dts): ```     gpio_keys: volume_keys@0 {__ @@ -55,43 +55,44 @@ freeze mem_                };        }; ``` -如上所示,有两个gpio键被配置为了唤醒源,在系统挂起期间按下其中任何一个键都会产生一个唤醒事件。 +如上所示,有两个 gpio 键被配置为唤醒源,在系统挂起期间,其中任何一个键被按下都会产生一个唤醒事件。 -相对与DT文件配置的另一个唤醒源配置就是设备驱动配置自身,如果设备驱动在代码里面配置了唤醒支持,那么就会使用该默认唤醒配置。 +可替代 DT 文件配置的另一个唤醒源配置就是设备驱动,如果设备驱动自身在代码里面配置了唤醒支持,那么就会使用该默认唤醒配置。 -### 补充 +## 实施 -### freeze功能 +### freeze 功能 -如果系统希望能够充分使用suspend to idle,那么应该在cpu空闲驱动代码中定义enter_freeze()函数。enter_freeze()与enter()的使用方式完全不同,因此不能给enter和enter_freeze实现相同的enter()功能。如果没有定义enter_freeze(),虽然系统会挂起,但是不会触发那些只有当enter_freeze()定义了才会触发的函数,比如tick_freeze()和stop_critical_timing()都不会发生。虽然这也会导致中断唤醒系统,但不会导致系统恢复,系统处理完中断后会继续睡眠。在该最低限度情况下,系统会直接调用enter()。 +如果系统希望能够充分使用 suspend to idle,那么应该在 cpu 空闲驱动代码中定义 enter_freeze() 函数。enter_freeze() 与enter() 的函数原型略有不同。因此,不能将 enter() 同时指定给 enter 和 enter_freeze。至少,系统会直接调用 enter()。如果没有定义 enter_freeze(),系统会挂起,但是不会触发那些只有当 enter_freeze() 定义了才会触发的函数,比如 tick_freeze() 和 stop_critical_timing() 都不会发生。这会导致计时器中断唤醒系统,但不会导致系统恢复,因为系统处理完中断后会继续挂起。 -在挂起过程中,越少中断产生越好(最好一个也没有)。 +在挂起过程中,中断越少越好(最好一个也没有)。 -下图显示了能耗和时间的对比。图中的两个尖刺分别是挂起和恢复阶段。挂起前后的能耗尖刺是系统退出空闲态正在进行的记录操作,进程调度,计时器处理等。由于潜在的原因系统进入更深层次休眠状态进行的默认操作需要花很多时间。 +下图显示了能耗和时间的对比。图中的两个尖刺分别是挂起和恢复。挂起前后的能耗尖刺是系统退出空闲态进行记录操作,进程调度,计时器处理等。因延迟的缘故,系统进入更深层次空闲状态需要花费一段时间。 ![blog-picture-one](http://www.linaro.org/wp-content/uploads/2016/10/blog-picture-one-1024x767.png) -Power Usage Time Progression -下面的跟踪时序图显示了4核CPU在系统挂起和恢复操作这段时间内的活动。如图所示,在挂起这段时间没有请求或者中断被处理。 +*能耗使用时序图* + +下图为 ftrace 抓取的 4 核 CPU 在系统挂起和恢复操作之前,之中和之后的活动。可以看到,在挂起期间,没有请求或者中断被处理。 ![blog-picture-2](http://www.linaro.org/wp-content/uploads/2016/10/blog-picture-2-1024x577.png) -Ftrace capture of Suspend/Resume +*Ftrace 抓取的 挂起/恢复 活动图* ### 空闲状态 -你必须确定哪个空闲状态支持冻结,在冻结期间,电源相关代码会决定用哪个空闲状态来实现冻结。这个过程是通过在每个空闲状态中查找谁定义了enter_freeze()来决定的。cpu空闲驱动代码或者SoC挂起相关代码必须实现冻结相关操作,并通过指定冻结功能给所有CPU的可应用空闲状态进行配置。 +你必须确定哪个空闲状态支持冻结。在冻结期间,电源相关代码会决定用哪个空闲状态来实现冻结。这个过程是通过在每个空闲状态中查找谁定义了 enter_freeze() 来决定的。cpu 空闲驱动代码或者 SoC 挂起相关代码必须确定哪种空闲状态实现冻结操作,并通过给每个 CPU 的可应用空闲状态指定冻结功能来进行配置。 -比如Qualcomm会在平台的挂起功能中的初始化代码处定义enter_freeze函数。这个工作是在cpu空闲驱动已经初始化并且所有数据结构已经定义就位的情况下进行的。 +例如, Qualcomm 会在平台挂起代码的挂起初始化函数处定义 enter_freeze 函数。这个工作是在 cpu 空闲驱动已经初始化后进行,以便所有结构已经定义就位。 ### 挂起/恢复相关驱动支持 -你可能会在第一次成功挂起操作后碰到驱动相关的bug。很多驱动开发者没有精力完全测试挂起和恢复相关的代码。由于用户空间已经被冻结,唤醒设备此时已经处于休眠状态并且pm_runtime已经被禁止。你可能会发现挂起操作并没有多少工作可做,因为pm_runtime已经做好了挂起相关的准备。 +你可能会在第一次成功挂起操作后碰到驱动相关的 bug。很多驱动开发者没有精力完全测试挂起和恢复相关的代码。你甚至可能会发现挂起操作并没有多少工作可做,因为 pm_runtime 已经做了你要做的挂起相关的一切工作。由于用户空间已经被冻结,设备此时已经处于休眠状态并且 pm_runtime 已经被禁止。 -### 测试相关 - -测试suspend to idle可以手动进行,也可以用(脚本或程序)自动挂起,使用自动睡眠或者Android中的wakelock来让系统挂起。如果手动测试,下面的操作会直接将系统冻结。 +## 测试相关 +测试 suspend to idle 可以手动进行,也可以使用脚本/进程等实现自动挂起、自动睡眠,或者使用像 Android 中的 wakelock 来让系统挂起。如果手动测试,下面的操作会将系统冻结。 + ``` / # echo freeze > /sys/power/state [  142.580832] PM: Syncing filesystems … done. @@ -115,9 +116,9 @@ _[  142.608073] Suspending console(s) (use no_console_suspend to debug) / # ``` -在上面的例子中,需要注意MMC驱动的操作占了102.883ms中的100ms。有些设备驱动在挂起的时候有很多工作要做,比如将数据刷出到硬盘,或者其他耗时的操作等。 +在上面的例子中,需要注意 MMC 驱动的操作占了 102.883ms 中的 100ms。有些设备驱动在挂起的时候有很多工作要做,比如将数据刷出到硬盘,或者其他耗时的操作等。 -如果系统定义了freeze。那么系统将尝试挂起操作,如果没有freeze功能,那么你会看到下面的提示: +如果系统定义了 freeze,那么系统将尝试挂起操作,如果没有 freeze 功能,那么你会看到下面的提示: ``` / # echo freeze > /sys/power/state  @@ -127,9 +128,10 @@ sh: write error: Invalid argument ### 未来的发展 -目前在ARM平台上的suspend to idle有两方面的工作需要做。第一方面是前面提到的需要准备好platform_suspend_ops相关工作,该工作致力于冻结状态的合法化并将并到4.9版本的内核中。另一方面是关于冻结功能方面的支持。 +目前在 ARM 平台上的 suspend to idle 有两方面的工作需要做。第一方面工作在前面 platform_suspend_ops 小节中提到过,是总允许接受冻结状态以及合并到 4.9 版本内核中的工作。另一方面工作是 freeze_function 支持。 + +如果你希望设备有更好的响应及表现,那么应该继续完善 freeze_function 的实现。然而,由于很多 SoC 会使用 ARM 的 cpu 空闲驱动,这使得 ARM 的 cpu 空闲驱动完善它自己的通用冻结功能的工作更有意义了。而事实上,ARM 正在尝试添加此通用支持。如果 SoC 供应商希望实现他们自己的 cpu 空闲驱动或者需要在进入更深层次的冻结休眠状态时提供额外的支持,那么只有实现自己的冻结功能。 -如果你希望设备有更好的响应及表现那么应该继续完善冻结相关功能的实现。然而很多SoCs会使用ARM的cpu空闲驱动,这使得ARM能够完善自己独特的冻结功能。而事实上,ARM正在尝试添加自己特有的支持。如果SoCs供应商希望实现他们自己的cpu空闲驱动或者需要在进入更深层次的冻结休眠状态时提供额外的支持,那么只有实现自己的冻结功能。 --------------------------------------------------------------------------------