Linux内核睡眠唤醒状态

2021-06-14  本文已影响0人  小田BSP

一、系统睡眠状态

Linux内核支持四种系统睡眠状态即:mem、standby、freeze and disk

可通过文件/sys/power/state进行读写访问,区别如下:

Label ACPI State 说明 State 功耗 唤醒
freeze Suspend-To-Idle 冻结用户空间,将所有I/O设备进入低功耗状态,处理器进入空闲状态 S0 最高 最快
standby Power-On Suspend 冻结用户空间,将所有I/O设备进入低功耗状态,关闭非引导CPU,暂停系统 S1 较高 较快
mem Suspend-to-RAM(STR) 将系统和设备状态保存到内存(处在自刷新模式,已保留其内容),所有设备进入低功耗模式 S2 较低 较慢
disk Suspend-to-disk(STD) 类似STR,将内存内容写入到磁盘, S3 最低 最慢

二、睡眠状态说明

RockPI 4A单板Debian系统Linux 4.4内核中,查看电源状态,仅支持freeze和mem两种。

root@linaro-alip:/sys/power# cat state
freeze mem

原因:

1、Platform驱动只实现了mem类型的suspend

2、只有在hibernation可用时,才支持STD

1、psci初始化流程

/**
 * suspend_valid_only_mem - Generic memory-only valid callback.
 *
 * Platform drivers that implement mem suspend only and only need to check for
 * that in their .valid() callback can use this instead of rolling their own
 * .valid() callback.
 */
int suspend_valid_only_mem(suspend_state_t state)
{
    return state == PM_SUSPEND_MEM;
}

static const struct platform_suspend_ops psci_suspend_ops = {
    .valid          = suspend_valid_only_mem, ## 判读有效状态,仅支持mem状态
    ...
};

static void __init psci_init_system_suspend(void)
{
    int ret;
    ...
    if (ret != PSCI_RET_NOT_SUPPORTED)
        suspend_set_ops(&psci_suspend_ops);  ### 设置global suspend method table
}

suspend_set_ops()函数赋值数组pm_states实现如下:

/**
 * suspend_set_ops - Set the global suspend method table.
 * @ops: Suspend operations to use.
 */
void suspend_set_ops(const struct platform_suspend_ops *ops)
{
    suspend_state_t i;
    int j = 0;

    lock_system_sleep();

    suspend_ops = ops;
    for (i = PM_SUSPEND_MEM; i >= PM_SUSPEND_STANDBY; i--)
        ## 1、此处判断valid状态,只有mem满足
        if (valid_state(i)) {
            pm_states[i] = pm_labels[j++];
        } else if (!relative_states) {  ## 2、standby状态,置NULL
            pm_states[i] = NULL;
            j++;
        }

    
    pm_states[PM_SUSPEND_FREEZE] = pm_labels[j]; ## 3、freeze状态

    unlock_system_sleep();
}

2、power state显示

/sys/power/state文件显示的内容,通过state_show()函数实现,该函数最终显示数组pm_states的内容。

static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
              char *buf)
{
    char *s = buf;
#ifdef CONFIG_SUSPEND
    suspend_state_t i;

    for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
        if (pm_states[i])
            s += sprintf(s,"%s ", pm_states[i]);

#endif
    if (hibernation_available())  ### hibernation_available()为true,才支持STD
        s += sprintf(s, "disk ");
    if (s != buf)
        /* convert the last space to a newline */
        *(s-1) = '\n';
    return (s - buf);
}

参考:

Documentation/power/states.txt

上一篇下一篇

猜你喜欢

热点阅读