Re: [PATCH RFC 01/10] firmware: arm_scmi: Add SCMI QCOM Generic Extension Protocol documentation

Sudeep Holla <[email protected]> Fri, 24 Jul 2026 10:13:17 +0100
Newsgroups org.kernel.vger.arm-scmi,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pm,org.kernel.vger.linux-tegra
Message-ID <20260724-crouching-starfish-of-apotheosis-d1cdf8@sudeepholla>
On Fri, Jul 24, 2026 at 12:48:06PM +0530, Pragnesh Papaniya wrote:
> Add System Control Management Interface (SCMI) Qualcomm Generic Extension
> Protocol documentation. It 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.
> 
> It currently only supports MEMLAT (memory latency governor) algorithm.
> The immutable pairing of the MEMLAT algorithm string with the supported
> param_ids associated with it are documented here.
> 
> Co-developed-by: Sibi Sankar <[email protected]>
> Signed-off-by: Sibi Sankar <[email protected]>
> Signed-off-by: Pragnesh Papaniya <[email protected]>
> ---
>  .../arm_scmi/vendors/qcom/qcom_generic.rst         | 954 +++++++++++++++++++++
>  1 file changed, 954 insertions(+)
> 
> diff --git a/drivers/firmware/arm_scmi/vendors/qcom/qcom_generic.rst b/drivers/firmware/arm_scmi/vendors/qcom/qcom_generic.rst
> new file mode 100644
> index 000000000000..42e327d53841
> --- /dev/null
> +++ b/drivers/firmware/arm_scmi/vendors/qcom/qcom_generic.rst
> @@ -0,0 +1,954 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +.. include:: <isonum.txt>
> +
> +==================================================================================
> +System Control and Management Interface (SCMI) Qualcomm Generic Extension Protocol
> +==================================================================================
> +
> +:Copyright: |copy| Qualcomm Technologies, Inc. and/or its subsidiaries.
> +
> +:Authors:
> +   - Sibi Sankar <[email protected]>
> +   - Pragnesh Papaniya <[email protected]>
> +
> +System Control and Management Interface Qualcomm Generic Extension Vendor Protocol
> +==================================================================================
> +
> +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 multiplexer 'N' random algorithn into one single custom SCMI protocol ID
(0x80) seems to go against the general SCMI design principle and this seems
like a deliberated attempt to circumvent the standard SCMI protocol template.
Standard SCMI expects distinct features to occupy their own vendor protocol
IDs and utilize standard protocol discovery.

I have asked details of algorithm to be listed here atleast few times now
and has been constantly ignored. So don't complain if I start ignoring these
patches.

> +message_id: 0x1
> +protocol_id: 0x80
> +
> ++------------------+-----------------------------------------------------------+
> +|Return values                                                                 |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|int32 status      |See ARM SCMI Specification for status code definitions.    |
> ++------------------+-----------------------------------------------------------+
> +|uint32 attributes |Bits[31:16] Reserved, must be set to 0.                    |
> +|                  |Bits[15:8] Number of agents in the system. Must match the  |
> +|                  |value reported by the standard BASE protocol's             |
> +|                  |PROTOCOL_ATTRIBUTES response.                              |


Please drop the above, duplication is always recipe for problems.

> +|                  |Bits[7:0] Number of algorithmic strings supported by the   |
> +|                  |system. Only "MEMLAT" is currently supported hence it      |
> +|                  |returns 1.                                                 |
> ++------------------+-----------------------------------------------------------+

OK, so this is the only algorithm.

> +
> +PROTOCOL_MESSAGE_ATTRIBUTES
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +message_id: 0x2
> +protocol_id: 0x80
> +
> ++------------------+-----------------------------------------------------------+
> +|Return values                                                                 |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|int32 status      |See ARM SCMI Specification for status code definitions.    |
> ++------------------+-----------------------------------------------------------+
> +|uint32 attributes |For all message IDs the parameter has a value of 0.        |
> ++------------------+-----------------------------------------------------------+
> +
> +QCOM_SCMI_SET_PARAM
> +~~~~~~~~~~~~~~~~~~~
> +
> +message_id: 0x10
> +protocol_id: 0x80
> +
> ++------------------+-----------------------------------------------------------+
> +|Parameters                                                                    |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 ext_id     |Reserved, must be zero.                                    |
> ++------------------+-----------------------------------------------------------+
> +|uint32 algo_low   |Lower 32-bit value of the algorithm string.                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 algo_high  |Upper 32-bit value of the algorithm string.                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 param_id   |Serves as the token message id for the algorithm string    |
> +|                  |and is used to set various parameters supported by it.     |


This is too open and can soon become ambiguous. More description on what
exactly this token message id is a must. This is not like normal kernel
function to keep it this ambiguous, it is a firmware interface which is
comparable to the user ABI.

> ++------------------+-----------------------------------------------------------+
> +|uint32 buf[]      |Serves as the payload for the specified param_id and       |
> +|                  |algorithm string pair. The payload size depends on the     |
> +|                  |(algorithm string, param_id) pair; see the per-algorithm   |
> +|                  |sections below.                                            |


Ditto.

> ++------------------+-----------------------------------------------------------+
> +|Return values                                                                 |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|int32 status      |SUCCESS: if the param_id and buf[] is parsed successfully  |
> +|                  |by the chosen algorithm string.                            |
> +|                  |NOT_SUPPORTED: if the algorithm string does not have any   |
> +|                  |matches.                                                   |
> +|                  |INVALID_PARAMETERS: if the param_id and the buf[] passed   |
> +|                  |is rejected by the algorithm string.                       |
> ++------------------+-----------------------------------------------------------+
> +
> +QCOM_SCMI_GET_PARAM
> +~~~~~~~~~~~~~~~~~~~
> +
> +message_id: 0x11
> +protocol_id: 0x80
> +
> ++------------------+-----------------------------------------------------------+
> +|Parameters                                                                    |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 ext_id     |Reserved, must be zero.                                    |
> ++------------------+-----------------------------------------------------------+
> +|uint32 algo_low   |Lower 32-bit value of the algorithm string.                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 algo_high  |Upper 32-bit value of the algorithm string.                |


At this point I start to think what is the point of exchanging the whole 8
byte string back and forth instead of simple ID.

> ++------------------+-----------------------------------------------------------+
> +|uint32 param_id   |Serves as the token message id for the algorithm string.   |
> ++------------------+-----------------------------------------------------------+
> +|uint32 buf[]      |Serves as the payload and store of value for the specified |
> +|                  |param_id and algorithm string pair. The payload size       |
> +|                  |depends on the (algorithm string, param_id) pair; see the  |
> +|                  |per-algorithm sections below. The response payload is      |
> +|                  |returned in the same buffer, overwriting the request       |
> +|                  |contents on success.                                       |


Ditto as above(too ambiguous, gives no clue on what that is)

> ++------------------+-----------------------------------------------------------+
> +|Return values                                                                 |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|int32 status      |SUCCESS: if the param_id and buf[] is parsed successfully  |
> +|                  |by the chosen algorithm string and the result is copied    |
> +|                  |into buf[].                                                |
> +|                  |NOT_SUPPORTED: if the algorithm string does not have any   |
> +|                  |matches.                                                   |
> +|                  |INVALID_PARAMETERS: if the param_id and the buf[] passed   |
> +|                  |is rejected by the algorithm string.                       |
> ++------------------+-----------------------------------------------------------+
> +|uint32 buf[]      |Holds the payload of the result of the query, returned in  |
> +|                  |the same buffer used to send the request. Size depends on  |
> +|                  |the (algorithm string, param_id) pair.                     |
> ++------------------+-----------------------------------------------------------+
> +
> +QCOM_SCMI_START_ACTIVITY
> +~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +message_id: 0x12
> +protocol_id: 0x80
> +
> +The activity to be started is defined by the algorithm string; see the
> +per-algorithm sections (e.g. MEMLAT_START_TIMER) for valid param_ids.
> +
> ++------------------+-----------------------------------------------------------+
> +|Parameters                                                                    |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 ext_id     |Reserved, must be zero.                                    |
> ++------------------+-----------------------------------------------------------+
> +|uint32 algo_low   |Lower 32-bit value of the algorithm string.                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 algo_high  |Upper 32-bit value of the algorithm string.                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 param_id   |Serves as the token message id for the algorithm string    |
> +|                  |and is generally used to start the activity performed by   |
> +|                  |the algorithm string.                                      |
> ++------------------+-----------------------------------------------------------+
> +|uint32 buf[]      |Serves as the payload for the specified param_id and       |
> +|                  |algorithm string pair. The payload size depends on the     |
> +|                  |(algorithm string, param_id) pair; see the per-algorithm   |
> +|                  |sections below.                                            |


Ditto

> ++------------------+-----------------------------------------------------------+
> +|Return values                                                                 |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|int32 status      |SUCCESS: if the activity performed by the algorithm string |
> +|                  |starts successfully, or if it was already running.         |
> +|                  |NOT_SUPPORTED: if the algorithm string does not have any   |
> +|                  |matches.                                                   |
> ++------------------+-----------------------------------------------------------+
> +
> +QCOM_SCMI_STOP_ACTIVITY
> +~~~~~~~~~~~~~~~~~~~~~~~
> +
> +message_id: 0x13
> +protocol_id: 0x80
> +
> +The activity to be stopped is defined by the algorithm string; see the
> +per-algorithm sections (e.g. MEMLAT_STOP_TIMER) for valid param_ids.
> +
> ++------------------+-----------------------------------------------------------+
> +|Parameters                                                                    |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 ext_id     |Reserved, must be zero.                                    |
> ++------------------+-----------------------------------------------------------+
> +|uint32 algo_low   |Lower 32-bit value of the algorithm string.                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 algo_high  |Upper 32-bit value of the algorithm string.                |
> ++------------------+-----------------------------------------------------------+
> +|uint32 param_id   |Serves as the token message id for the algorithm string    |
> +|                  |and is generally used to stop the activity performed by    |
> +|                  |the algorithm string.                                      |
> ++------------------+-----------------------------------------------------------+
> +|uint32 buf[]      |Serves as the payload for the specified param_id and       |
> +|                  |algorithm string pair. The payload size depends on the     |
> +|                  |(algorithm string, param_id) pair; see the per-algorithm   |
> +|                  |sections below.                                            |


Ditto

> ++------------------+-----------------------------------------------------------+
> +|Return values                                                                 |
> ++------------------+-----------------------------------------------------------+
> +|Name              |Description                                                |
> ++------------------+-----------------------------------------------------------+
> +|int32 status      |SUCCESS: if the activity performed by the algorithm string |
> +|                  |stops successfully, or if it was not running.              |
> +|                  |NOT_SUPPORTED: if the algorithm string does not have any   |
> +|                  |matches.                                                   |
> ++------------------+-----------------------------------------------------------+
> +
> +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:
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +.. code-block:: text
> +
> +  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:
> +~~~~~~~~~~~~~~~~
> +
> +.. code-block:: text
> +
> +  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
> +
> +MEMLAT: Supported memory buses
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +The hw_type field carried in most payloads identifies the memory group:
> +
> ++----------+--------------------------------------------------------------+
> +|hw_type   |Group                                                         |
> ++----------+--------------------------------------------------------------+
> +|0         |DDR                                                           |
> ++----------+--------------------------------------------------------------+
> +|1         |LLCC                                                          |
> ++----------+--------------------------------------------------------------+
> +|2         |DDR_QOS_COMPUTE                                               |
> ++----------+--------------------------------------------------------------+
> +|3         |DDR_QOS_MOBILE                                                |
> ++----------+--------------------------------------------------------------+
> +
> +All multi-byte fields below are little-endian. mon_idx selects a monitor
> +within the group (0-based, less than the firmware-supported maximum). All
> +SET commands return the SCMI status word; on success it carries SUCCESS, on
> +lookup failure INVALID_PARAMETERS, and on an unknown param_id NOT_SUPPORTED.
> +
> +Frequency units are not uniform across commands (kHz, MHz or a raw 0/1
> +DDR_QOS level, depending on the param_id); each command documents its own
> +units below.
> +
> +MEMLAT_SET_MEM_GROUP
> +~~~~~~~~~~~~~~~~~~~~
> +
> +param_id: 0x10 (16)


Ah so, these are param id for the above commands I mentioned as too
ambiguous ? If so, at this point I think it is better to make custom
vendor protocol ID 0x80 for MEMLAT and make all these part of it.
I think my comment of multiplexing is a bad idea seem to be confirmed here.
I will skip the rest as it makes no sense to review it any further.

-- 
Regards,
Sudeep