GPU Frequency Scaling on Qualcomm Adreno Using the Linux devfreq Framework
Using Qualcomm’s Adreno GPU as a case study, the article explains how the Linux devfreq framework enables GPU frequency scaling by creating a kgsl devfreq device and an msm‑adreno‑tz governor, detailing their initialization, event handling, target‑frequency computation, and the kernel callbacks that apply the new rates.
The AI era has arrived, and with the growing demand for compute power, GPUs have become indispensable in the AI world. Mobile high‑rendering, high‑frame‑rate applications also place increasing demands on mobile GPUs. This article uses Qualcomm's Adreno GPU as an example to introduce GPU frequency scaling.
Before diving in, it is recommended to read the article "Linux devfreq framework analysis" to understand the role of devfreq devices and the unified implementation format of governors within the devfreq framework. GPU frequency scaling is built on the devfreq framework by creating a GPU‑specific devfreq device (kgsl) and a governor (msm‑adreno‑tz), following the same basic flow as the devfreq framework.
a. Initialize the governor and register it to the framework via devfreq_add_governor . Initialize the devfreq device and register it via devfreq_add_device , then match the device with the governor.
b. When the governor's event_handler receives the corresponding event, it calls the governor’s implemented get_target_freq to compute the target frequency and returns it to the framework.
c. The framework then invokes the devfreq device’s callback devfreq->profile->target() to set the target frequency.
The msm‑adreno‑tz governor is introduced next. Its crucial role is to receive events and calculate the target frequency for the devfreq device, so it must implement two key functions: event_handler and get_target_freq .
The tz_handler receives the DEVFREQ_GOV_START event and calls tz_get_target_freq . Inside tz_get_target_freq , the current GPU frequency is obtained via devfreq_update_stats and mapped to a freq_level using devfreq_get_freq_level . The current GPU load is retrieved with compute_work_load , and the target freq_level is calculated by __secure_tz_update_entry3 . Finally, the target freq_level is mapped back to an actual frequency, which becomes the target frequency.
The corresponding devfreq device is kgsl . Its callback for setting the target frequency is kgsl_devfreq_target . This function first checks whether the computed target frequency satisfies the conditions for updating the GPU frequency, then invokes kgsl_pwrctrl_pwrlevel_change , which uses _isense_clk_set_rate to apply the new frequency.
Tips: The GPU frequency and its freq_level table can be inspected from user space at /sys/class/kgsl/kgsl-3d0/freq_table_mhz .
References
1. "Linux devfreq framework analysis" (link)
2. https://android.googlesource.com/kernel/msm
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.