Mastering Linux PM QoS: How to Optimize Power Management with Constraints
This article explains the Linux PM QoS framework, detailing its background, system‑ and device‑level constraints, core data structures, key API functions, and a practical example of limiting CPU‑DMA latency for power‑efficient device operation.
Background and Motivation
QoS (Quality of Service) originally describes network performance guarantees; in Linux power management it is treated as a service whose goal is to minimize power consumption while satisfying latency, throughput, and other performance constraints.
PM QoS Overview and Framework
The kernel provides two QoS frameworks: a system‑level class framework (defined in kernel/power/qos.c) and a per‑device framework (defined in drivers/base/power/qos.c). System‑level constraints historically included cpu&dma latency, network latency, network throughput, and memory bandwidth; in kernel‑5.4 they were reduced to only cpu&dma latency with an added cpufreq constraint.
Typical user‑space interfaces are exposed via misc devices such as /dev/cpu_dma_latency, /dev/network_latency, /dev/network_throughput, and /dev/memory_bandwidth.
Core Data Structures
struct pm_qos_request – handle used for add, update, and remove operations.
struct pm_qos_constraints – represents a specific QoS class and its limits.
struct pm_qos_object – contains a misc device that provides user‑space access to the class.
Important fields: node – a plist_node that stores the request value as a priority, automatically sorted in ascending order so the smallest (or largest) value is at the front of the list. pm_qos_class – enumerates the QoS class. target_value and default_value – the desired constraint value and the initial value (usually 0, meaning no limit). type – indicates whether the class uses minimum, maximum, or sum aggregation. notifiers – callback list invoked when the constraint value changes. list – linked list of all requests for the class.
Primary API Functions
void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class, s32 value)– inserts a new request node into the class list and updates the target value.
void pm_qos_update_request(struct pm_qos_request *req, s32 new_value)– changes the value of an existing request.
void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value, unsigned long timeout_us)– same as update but with a timeout for delayed changes. void pm_qos_remove_request(struct pm_qos_request *req) – removes a request from the list. void pm_qos_add_notifier(...) and void pm_qos_remove_notifier(...) – register or unregister callbacks that are invoked when a class’s target value changes.
Usage Example
A camera driver requests a CPU_DMA_LATENCY of 50 µs (path: drivers/media/platform/via-camera.c). This forces the cpuidle governor to stay at C2 level (where exit latency is ≤57 µs) instead of deeper C3 states, ensuring the DMA transfer is not corrupted while still saving power.
References
http://www.wowotech.net/tag/pm_qos
Kernel 5.4 source: https://android.googlesource.com/kernel/common/+/refs/heads/android11-5.4
Kernel 4.19 source: https://android.googlesource.com/kernel/common/+/refs/heads/android-4.19-stable
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
OPPO Kernel Craftsman
Sharing Linux kernel-related cutting-edge technology, technical articles, technical news, and curated tutorials
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
