0%

Linux设备休眠-概念

前言

<LINUX电源管理介绍-1>和<LINUX电源管理介绍-2>分别进行了Linux PM的框架介绍以及Autosleep流程分析。本文着重以设备驱动角度介绍电源管理子系统对系统休眠的处理流程。

数据结构

在介绍流程前,先看一下设备驱动中有关睡眠的数据结构,dev_pm_ops:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
struct device_driver {
//......
const struct dev_pm_ops *pm;
//......
};
struct dev_pm_ops {
int (*prepare)(struct device *dev);
void (*complete)(struct device *dev);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*suspend_late)(struct device *dev);
int (*resume_early)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw_early)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore_early)(struct device *dev);
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
int (*thaw_noirq)(struct device *dev);
int (*poweroff_noirq)(struct device *dev);
int (*restore_noirq)(struct device *dev);
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
};

睡眠类型

根据Linux睡眠子系统执行的回调函数不同,Linux的休眠可以分为如下几个类型:

  • suspend,包括如下两种,执行的设备驱动回调函数主要有:
    • suspend to idle (Standby)
    • suspend to mem
1
2
3
4
5
6
7
8
int (*prepare)(struct device *dev);
void (*complete)(struct device *dev);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*resume_early)(struct device *dev);
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
  • hibernation,即suspend to disk(挂起到硬盘),执行的设备驱动回调函数比较多,包括:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int (*prepare)(struct device *dev);
void (*complete)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw_early)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore_early)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
int (*thaw_noirq)(struct device *dev);
int (*poweroff_noirq)(struct device *dev);
int (*restore_noirq)(struct device *dev);
  • runtime suspend,使用到的设备驱动回调函数有:
1
2
3
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);

根据执行设备睡眠的触发点不同,Linux执行睡眠的流程又分为两类:

  • 系统休眠
    • 即上节提到的Suspend和Hibernation
    • 此时系统会执行所有设备的Suspend或Hibernation回调,并进入系统对应的休眠状态
  • 设备运行时休眠
    • 仅针对特定设备。当设备需要被占用时(例如,将要进行数据传输时),设备驱动调用系统函数通知系统,系统再调用设备的runtime_resume回调让该设备退出低功耗状态(或本身设备就在工作状态,便不做操作)。
    • 而当设备没有数据传输等工作时,通知Linux电源管理子系统,系统再调用runtime_suspend/idle回调让设备进入低功耗状态

      结论

      本节介绍了Linux系统设备休眠的相关回调函数,并介绍了Linux系统设备休眠的分类。之后将会分别对Suspend、Hibernation流程、Runtime Suspend流程进行分析。