System Control Management Interface (SCMI) Qualcomm Generic Extension Protocol
consists of a small set of generic SET/GET/START/STOP commands, which is
used to turn on/off and configure Qualcomm SoC specific algorithms that run
on the SCP. Each algorithm is identified through an algorithm string and has
an immutable list of param_ids. All supported algorithms (currently just MEMLAT)
have their own dedicated section and are listed after the generic commands.
This series introduces the devfreq SCMI client driver that uses the MEMLAT
algorithm string hosted on the QCOM SCMI Generic Extension Protocol to detect
memory latency workloads and control frequency/level of the various memory
buses (DDR/LLCC/DDR_QOS). DDR/LLCC/DDR_QOS are modelled as devfreq devices
using the remote devfreq governor. This provides basic insight into device
operation via trans_stat and lets userspace further tweak the parameters of
the remote governor.
trans_stat data for DDR/LLCC/DDR_QOS is now available with this series:
From : To
315000000 479000000 545000000 725000000 840000000 959000000 1090000000 1211000000 time(ms)
315000000: 0 3 6 6 6 7 0 30 143956
479000000: 2 0 7 1 1 1 0 3 356
545000000: 7 6 0 5 5 0 0 10 1200
725000000: 3 0 5 0 6 1 0 6 2172
840000000: 8 2 3 2 0 4 0 12 1188
959000000: 3 0 1 2 2 0 0 13 272
1090000000: 0 0 0 0 0 0 0 0 0
1211000000: 35 4 11 5 11 8 0 0 21684
Total transition : 253
MEMLAT: Memory Latency algorithm
The MEMLAT algorithm (0x4d454d4c4154, ASCII "MEMLAT") scales the DDR, LLCC and
DDR_QOS buses in response to memory-latency-bound workloads. It runs on the CPUCP:
every sampling window it reads the per-CPU AMU counters, derives its statistics
(instructions-per-miss, back-end stall, write-back ratio), maps that to a target
level and votes for it directly on the DDR/LLCC/DDR_QOS interconnect. The kernel
never issues a frequency request in that loop. The 6-byte value is treated as a
64-bit algorithm string and split into two uint32 fields on the wire: algo_low
carries its lower 32 bits and algo_high its upper 32 bits.
With a distinct need to have the memory buses scaling done in SCP in response to
memory-latency-bound workloads, none of the existing SCMI solutions could be used
as-is. MPAM does not apply either: it is not enabled on all of the affected parts
(e.g. Hamoa). The role split between SCP and client driver is described next.
MEMLAT client driver pseudo-code:
probe():
SET_COMMON_EV_MAP # AMU events (all groups)
for each memory group (DDR / LLCC / DDR_QOS):
SET_MEM_GROUP # bind group to interconnect
SET_GRP_EV_MAP # per-group AMU events
for each monitor in the group:
SET_MONITOR # topology, cpumask, name
IPM_CEIL / BE_STALL_FLOOR # per-monitor tuneables
MON_FREQ_MAP # cpufreq -> memfreq map
SET_MIN_FREQ / SET_MAX_FREQ # clamps
SAMPLE_MS # sampling period
SET_EFFECTIVE_FREQ_METHOD # cpu-freq derivation method
START_TIMER # CPUCP now scales autonomously
devfreq poll (twice per CPUCP sample period):
GET_CUR_FREQ # read voted freq, per monitor
remove():
STOP_TIMER
SCP pseudo-code:
every sample_ms:
for each CPU:
sample AMU counters (instructions, cycles, cache-misses, stalls)
derive per-CPU IPM, back-end-stall % and write-back ratio
for each configured memory group (DDR / LLCC / DDR_QOS):
for each monitor in the group:
best_freq = 0
for each CPU in the monitor's cpumask:
if CPU is memory-bound (IPM/stall/write-back vs. the
monitor's configured thresholds):
freq = CPU's cpufreq, optionally scaled toward the ceiling
best_freq = max(best_freq, freq)
monitor.target_freq = monitor's cpufreq->memfreq map(best_freq)
group_vote = max(target_freq of every monitor in the group)
if group_vote changed since the last sample:
vote group_vote onto the group's interconnect path
GET_CUR_FREQ returns a monitor's last target_freq
START_TIMER / STOP_TIMER: resume / suspend the loop above
Thanks in advance for taking time to review the series.
Changes in v8:
- Add memlat support for Kaanapali.
- Express the cpufreq/memfreq map in MHz on both sides, matching the
firmware wire format, dropping the kHz conversion and the DDR_QOS
special case [Bjorn].
- Build the on-wire messages directly from the static configuration
instead of deep-copying it into heap mirror structs [Bjorn].
- Anchor each memory bus's OPP table and devfreq device on a lightweight
faux_device instead of a platform_device [Bjorn]; register the devfreq
device non-devm with matching teardown on our own error paths, fixing a
device/devfreq leak and use-after-free on unwind [Sashiko].
- Switch param_ids to #defines (fixed wire tokens) and keep hw_type as
the only enum; unit-suffix frequencies, add a memlat_set_param()
helper and rename message locals for clarity [Bjorn].
- Bound the vendor-protocol GET response copy against the caller
buffer and skip the payload copy for zero-length transfers
[Sashiko]; add an algorithm-string allowlist so the firmware never
sees an unrecognised string [Sudeep].
- Rewrite the driver Kconfig help and commit message around the
CPUCP/kernel role split, and expand the MEMLAT documentation with
the motivation for a vendor protocol and a call flow [Bjorn, Sudeep].
- Fold scmi-qcom-memlat-cfg.h into the driver .c, laid out as
definitions / per-SoC configuration / logic and driver boilerplate;
add kernel-doc on the per-monitor tuneables (be_stall_floor, ipm_ceil,
etc.) and reword the devfreq polling-interval comment to explain why
half the CPUCP sample period is correct here [Bjorn].
- Link to v7: https://lore.kernel.org/lkml/20260610-rfc_v7_scmi_memlat-v7-0-f3f68c608f25@oss.qualcomm.com/
Changes in v7:
- Minor bug fixes and documentation improvements based on review feedback.
- Significantly expand the QCOM Generic Vendor Protocol documentation
with a dedicated MEMLAT section covering all param_ids, payloads and
return values [Sudeep, Cristian].
- Move per-SoC event IDs and hardware type identifiers from the driver
into the platform configuration header.
- Poll devfreq at twice the CPUCP sampling rate so every firmware voting
cycle is reliably observed [Lukasz].
- Add a devicetree binding schema for the Qualcomm SCMI vendor
protocol@80 node.
- Link to v6: https://lore.kernel.org/r/20260507062237.78051-1-sibi.sankar@oss.qualcomm.com
Changes in v6:
- Combining vendor protocol and the client and moving it
back into RFC mode.
- Introduce target_freq attr flag and TRACK_REMOTE devfreq
governor flag.
- Add basic remote devfreq governor to give users data like
transtat [Dmitry]
- Drop the current design that relies on manual parsing of
device tree data and move those into SoC specific structs
- Add Glymur/Mahua/Hamoa/Purwa support in the same series.
- Link to v5: https://lore.kernel.org/lkml/20241115011515.1313447-1-quic_sibis@quicinc.com/
Changes in v5:
- Splitting the series into vendor protocol and memlat client.
- Also the move the memlat client implementation back to RFC
due to multiple opens.
- Use common xfer helper to avoid code duplication [Dmitry]
- Update enum documentation without duplicate enum info [Dmitry]
- Update the protol attributes doc with more information. [Cristian]
- Link to v4: https://lore.kernel.org/lkml/20241007061023.1978380-1-quic_sibis@quicinc.com/
Changes in v4:
- Restructure the bindings to mimic IMX [Christian]
- Add documentation for the qcom generic vendor protocol [Christian/Sudeep]
- Pick up Rb tag and fixup/re-order elements of the vendor ops [Christian]
- Follow naming convention and folder structure used by IMX
- Add missing enum in the vendor protocol and fix documentation [Konrad]
- Add missing enum in the scmi memlat driver and fix documentation [Konrad]
- Add checks for max memory and monitor [Shivnandan]
- Fix typo from START_TIMER -> STOP_TIMER [Shivnandan]
- Make populate_physical_mask func to void [Shivnandan]
- Remove unecessary zero set [Shivnandan]
- Use __free(device node) in init_cpufreq-memfreqmap [Christian/Konrad]
- Use sdev->dev.of_node directly [Christian]
- use return dev_err_probe in multiple places [Christian]
- Link to v3: https://lore.kernel.org/lkml/20240702191440.2161623-1-quic_sibis@quicinc.com/
Changes in v3:
- Drop container dvfs memlat container node. [Rob]
- Move scmi-memlat.yaml to protocol level given that a lot of vendors might end up
- using the same protocol number. [Rob]
- Replace qcom,cpulist with the standard "cpus" property. [Rob]
- Fix up compute-type/ipm-ceil required. [Rob]
- Make driver changes to the accommodate bindings changes. [Rob]
- Minor fixups in subjects/coverletter.
- Minor style fixes in dts.
- Link to v2: https://lore.kernel.org/lkml/20240612183031.219906-1-quic_sibis@quicinc.com/
Changes in v2:
- Add missing bindings for the protocol. [Konrad/Dmitry]
- Use alternate bindings. [Dmitry/Konrad]
- Rebase on top of Cristian's "SCMI multiple vendor protocol support" series. [Cristian]
- Add more documentation wherever possible. [Sudeep]
- Replace pr_err/info with it's dev equivalents.
- Mixed tabs and initialization cleanups in the memlat driver. [Konrad]
- Commit message update for the memlat driver. [Dmitry]
- Cleanups/Fixes suggested for the client driver. [Dmitry/Konrad/Cristian]
- Use opp-tables instead of memfreq-tbl. [Dmitry/Konrad]
- Detect physical cpu to deal with variants with reduced cpu count.
- Add support for DDR_QOS mem_type.
- Link to v1: https://lore.kernel.org/lkml/20240117173458.2312669-1-quic_sibis@quicinc.com/
Signed-off-by: Pragnesh Papaniya <pragnesh.papaniya@oss.qualcomm.com>
---
Jia Yang (1):
arm64: dts: qcom: kaanapali: Enable LLCC/DDR/DDR_QOS DVFS
Pragnesh Papaniya (2):
firmware: arm_scmi: Add SCMI QCOM Generic Extension Protocol documentation
dt-bindings: firmware: arm,scmi: Add Qualcomm Generic Extension Protocol
Sibi Sankar (7):
firmware: arm_scmi: vendors: Add QCOM SCMI Generic Extensions
PM / devfreq: Add new target_freq attribute flag for governors
PM / devfreq: Add new track_remote flag for governors
PM / devfreq: Add a governor for tracking remote device frequencies
PM / devfreq: Introduce the QCOM SCMI Memlat devfreq driver
arm64: dts: qcom: glymur: Enable LLCC/DDR/DDR_QOS DVFS
arm64: dts: qcom: hamoa: Enable LLCC/DDR/DDR_QOS DVFS
Documentation/ABI/testing/sysfs-class-devfreq | 8 +
.../devicetree/bindings/firmware/arm,scmi.yaml | 1 +
.../bindings/firmware/qcom,generic-scmi.yaml | 27 +
MAINTAINERS | 18 +
arch/arm64/boot/dts/qcom/glymur.dtsi | 41 +
arch/arm64/boot/dts/qcom/hamoa.dtsi | 4 +
arch/arm64/boot/dts/qcom/kaanapali.dtsi | 41 +
drivers/devfreq/Kconfig | 23 +
drivers/devfreq/Makefile | 2 +
drivers/devfreq/devfreq.c | 27 +
drivers/devfreq/governor_passive.c | 1 +
drivers/devfreq/governor_performance.c | 1 +
drivers/devfreq/governor_powersave.c | 1 +
drivers/devfreq/governor_remote.c | 73 ++
drivers/devfreq/governor_simpleondemand.c | 1 +
drivers/devfreq/governor_userspace.c | 1 +
drivers/devfreq/hisi_uncore_freq.c | 1 +
drivers/devfreq/scmi-qcom-memlat-devfreq.c | 1331 ++++++++++++++++++++
drivers/devfreq/tegra30-devfreq.c | 3 +-
drivers/firmware/arm_scmi/Kconfig | 1 +
drivers/firmware/arm_scmi/Makefile | 1 +
drivers/firmware/arm_scmi/vendors/qcom/Kconfig | 15 +
drivers/firmware/arm_scmi/vendors/qcom/Makefile | 2 +
.../arm_scmi/vendors/qcom/qcom-generic-ext.c | 183 +++
.../arm_scmi/vendors/qcom/qcom_generic.rst | 954 ++++++++++++++
include/linux/devfreq-governor.h | 8 +
include/linux/devfreq.h | 1 +
include/linux/scmi_qcom_protocol.h | 37 +
28 files changed, 2806 insertions(+), 1 deletion(-)
---
base-commit: 9eebf259d5352b87080d67758f483583d9e763d7
change-id: 20260724-rfc_v8_scmi_memlat-bc57a7472637
Best regards,
--
Pragnesh Papaniya <pragnesh.papaniya@oss.qualcomm.com>