[PATCH v7 14/23] firmware: arm_scmi: Add Telemetry generation counter event
From: Cristian Marussi <cristian.marussi@arm.com>
Date: 2026-08-02 14:58:42
Also in:
arm-scmi, linux-doc, lkml
Subsystem:
system control & power/management interface (scpi/scmi) message protocol drivers, the rest · Maintainers:
Sudeep Holla, Linus Torvalds
Add a per-instance generation counter to track configuration changes which uses the common telemetry events framework. Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> --- v6 --> v7 - use new Generic event mechanism based on EventFD instead of WaitQ v5 --> v6 - add relese semantic to the atomic set of the generation counter - use new eventfd_ctx common event logic --- drivers/firmware/arm_scmi/telemetry.c | 48 +++++++++++++++++++++++++++ include/linux/scmi_protocol.h | 5 ++- 2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_scmi/telemetry.c b/drivers/firmware/arm_scmi/telemetry.c
index dfe18729c6f1..8cb81afd7781 100644
--- a/drivers/firmware/arm_scmi/telemetry.c
+++ b/drivers/firmware/arm_scmi/telemetry.c@@ -23,6 +23,7 @@ #include <linux/string.h> #include <linux/uuid.h> #include <linux/xarray.h> +#include <linux/wait.h> #include "protocols.h" #include "notify.h"
@@ -32,6 +33,7 @@ /* Updated only after ALL the mandatory features for that version are merged */ #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000 +#define SCMI_TLM_GENERATION_ONE (SCMI_TLM_GENERATION_INVALID + 1U) #define SCMI_TLM_TDCF_MAX_RETRIES 5 #define SCMI_TLM_DE_IMPL_NUM_DWORDS 4
@@ -700,6 +702,35 @@ scmi_telemetry_tde_cache_lookup(struct telemetry_de *tde, return 0; } +static inline void __scmi_telemetry_generation_set(struct telemetry_info *ti, + unsigned int new) +{ + int ret; + + atomic_set_release(&ti->info.generation, new); + + ret = scmi_telemetry_event_signal(ti, SCMI_TLM_EVT_GENERATION); + if (ret) + dev_warn_once(ti->ph->dev, + "Could NOT signal telemetry event %d\n", + SCMI_TLM_EVT_GENERATION); +} + +static inline void scmi_telemetry_generation_update(struct telemetry_info *ti) +{ + unsigned int next; + + /* Wrap around skipping invalid generation 0 */ + next = (atomic_read(&ti->info.generation) + 1) ?: SCMI_TLM_GENERATION_ONE; + + __scmi_telemetry_generation_set(ti, next); +} + +static inline void scmi_telemetry_generation_reset(struct telemetry_info *ti) +{ + __scmi_telemetry_generation_set(ti, SCMI_TLM_GENERATION_ONE); +} + struct scmi_tlm_de_priv { struct telemetry_info *ti; void *next;
@@ -2351,6 +2382,8 @@ static int __scmi_telemetry_state_set(const struct scmi_protocol_handle *ph, tstamp_enabled_state, *tstamp); + /* A local change can have an impact anyway */ + scmi_telemetry_generation_update(ti); return 0; }
@@ -2412,6 +2445,9 @@ static int __scmi_telemetry_state_set(const struct scmi_protocol_handle *ph, ph->xops->xfer_put(ph, t); + if (!ret) + scmi_telemetry_generation_update(ti); + return ret; }
@@ -2544,6 +2580,9 @@ static int scmi_telemetry_all_disable(const struct scmi_protocol_handle *ph, ph->xops->xfer_put(ph, t); + if (!ret) + scmi_telemetry_generation_update(ti); + return ret; }
@@ -2616,6 +2655,9 @@ scmi_telemetry_collection_configure(const struct scmi_protocol_handle *ph, ph->xops->xfer_put(ph, t); + if (!ret) + scmi_telemetry_generation_update(ti); + return ret; }
@@ -3080,6 +3122,10 @@ static int scmi_telemetry_reset(const struct scmi_protocol_handle *ph) struct telemetry_info *ti = ph->get_priv(ph); scmi_telemetry_local_resources_reset(ti); + + /* Reset generation now that server has been reset */ + scmi_telemetry_generation_reset(ti); + /* Fetch again the states from platform. */ ret = scmi_telemetry_initial_state_lookup(ti); if (ret)
@@ -3504,6 +3550,8 @@ static int scmi_telemetry_instance_init(struct telemetry_info *ti) for (int i = 0; i < SCMI_TLM_EVT_MAX; i++) INIT_LIST_HEAD(&ti->events[i]); mutex_init(&ti->events_mtx); + /* Generation counter init */ + atomic_set(&ti->info.generation, SCMI_TLM_GENERATION_ONE); atomic_set(&ti->des_enabled[ENA_STATE], 0); atomic_set(&ti->des_enabled[ENA_TSTAMP], 0); /* Setup resources lazy initialization */
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 3206b0710bcc..d48b1030ddb4 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h@@ -891,6 +891,7 @@ enum scmi_telemetry_collection { SCMI_TLM_SINGLE_READ, }; +#define SCMI_TLM_GENERATION_INVALID 0U #define SCMI_TLM_GRP_INVALID 0xFFFFFFFF struct scmi_telemetry_intervals {
@@ -986,6 +987,7 @@ struct scmi_telemetry_info { bool enabled; bool notif_enabled; enum scmi_telemetry_collection current_mode; + atomic_t generation; }; struct scmi_telemetry_de_sample {
@@ -996,6 +998,7 @@ struct scmi_telemetry_de_sample { }; enum scmi_telemetry_event { + SCMI_TLM_EVT_GENERATION, SCMI_TLM_EVT_MAX };
@@ -1022,11 +1025,11 @@ enum scmi_telemetry_event { * the ones belonging to a specific group when provided. * This causes an immediate update platform-side of all the * enabled DEs. - * @reset: reset configuration and telemetry data. * @event_subscribe: subscribe to the specified event @type using the provided * @eventfd_ctx. * @event_unsubscribe: unsubscribe to the specified event @type the previously * registered @eventfd_ctx. + * @reset: reset configuration and telemetry data. */ struct scmi_telemetry_proto_ops { const struct scmi_telemetry_info __must_check *(*info_get)
--
2.54.0