这是系列文章中第二篇,我们将分析完整的 Linux runtime suspend 操作流程,以 Vivante GPU 为例,展示开发者如何通过内核程序实现和调试 runtime PM 机制。
一、内核中的 Runtime PM 工作流程概览
当调用者执行:
pm_runtime_put(dev);
时,内核开始启动 suspend 流程,简化路径如下:
pm_runtime_put()\_ __pm_runtime_resume()/suspend()\_ queue_work(pm_wq, pm_runtime_work())\_ rpm_suspend()\_ call runtime_suspend(dev)
一切工作通过 workqueue 静态分配执行,最终会调用驱动引擎里的:
const struct dev_pm_ops xxx_pm_ops = {.runtime_suspend = xxx_runtime_suspend,.runtime_resume = xxx_runtime_resume,
};
设备与驱动在 probe 时相关联,这些操作是 runtime PM 作用的基础。
二、GPU 驱动中如何实现 runtime_suspend()
以 NXP 官方 BSP中 drivers/gpu/imx/gpu2d/gpu2d.c
为例,其 runtime_suspend 代码类似如下:
static int gpu2d_runtime_suspend(struct device *dev)
{struct gpu2d_data *gpu = dev_get_drvdata(dev);clk_disable_unprepare(gpu->clk_axi);clk_disable_unprepare(gpu->clk_ahb);return 0;
}static int gpu2d_runtime_resume(struct device *dev)
{struct gpu2d_data *gpu = dev_get_drvdata(dev);clk_prepare_enable(gpu->clk_axi);clk_prepare_enable(gpu->clk_ahb);return 0;
}static const struct dev_pm_ops gpu2d_pm_ops = {.runtime_suspend = gpu2d_runtime_suspend,.runtime_resume = gpu2d_runtime_resume,
};static struct platform_driver gpu2d_driver = {.driver = {.name = "imx-gpu2d",.pm = &gpu2d_pm_ops,},.probe = gpu2d_probe,.remove = gpu2d_remove,
};
这段代码表明:
- GPU2D 设备需要两条时钟线:AHB + AXI
- runtime_suspend() 释放时钟,用于节能
- resume() 重新启动 clock ,确保正常运行
实现非常简洁,同时需要确保 clock 名称和 device tree 配置一致。
三、如何验证 runtime_suspend 被调用
1.使用 dev_info()
在 suspend/resume 函数中加上:
dev_info(dev, "runtime suspend enter\n");
dev_info(dev, "runtime resume enter\n");
然后通过 dmesg
观看调用时机记录
2.开启 ftrace 跟踪:
echo 1 > /sys/kernel/debug/tracing/tracing_on
echo dev_pm_* > /sys/kernel/debug/tracing/set_ftrace_filter
echo function > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/trace
四、如何解析 GPU 不能 suspend 的原因?
惊悚一:runtime_status = active
- 表示尚有使用者依赖,通常是 usage 不为 0
- 通过:
cat runtime_usage
如果 > 0,表示有场景使用了 pm_runtime_get()
后未 release
惊悚二:未启用 power domain
- 查看 device tree 中是否定义
power-domains = <&gpu_pd>
等 - 查看 /sys/devices/…/power/下是否有
autosuspend_delay_ms
惊悚三:无 .runtime_suspend()
- 查验 driver 中是否没有 pm_ops 的注册
- 添加 dev_dbg/dev_info 打印确认
五、最终建议:为什么开发时必须支持 runtime suspend?
- 所有裱系统和开源 Linux BSP 都应使用 runtime PM 节能
- suspend/resume 是后续 DVFS/power domain 控制的基础
- 能够保证屏幕灯消灯后,GPU 和 VPU 都被展示为 suspend ,是面试常问答的背景矩阵
六、小结
本文我们从全局角度解析了 Linux runtime PM 机制的内核流程,以 GPU 驱动为例完整说明了 suspend/resume 函数如何实现,如何调试和怎样分析失效原因。
这是所有 Linux BSP 开发者的基本功夫。