From nobody Thu Apr 2 10:43:03 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CA5B438237E; Sun, 29 Mar 2026 16:34:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774802098; cv=none; b=ihauCM82MMgT6wg10uyxjATaECGw04gpfD5Z98B6Ju7uOEIJKp2rWqnEpCDhQGjajOvEvhWidRpqGFtQlMkIBWx1Fu5nnYXz5/aT8Sdx+6yXOdV14JoIpAaUENKUhEfzd8Ytaw+qY2O7SkhC9gZvIJLM/BQVVQtG2PVQKZN40/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774802098; c=relaxed/simple; bh=uvOsmGvjVulKQfBZ+trVQ93a26jGUSXZoDI/MgW1pRs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qgOSz5PQeURtvDr42DhCk9DAE9h6hK12cyL2qj9tj7NQhganft+5+6kdEMsaNcoQSFbjZyrW03/onkSkdmD+PV2NuzCSIevCIuf8JmIb37CqOfKe5ojhGK+PT+FnIx1JXU5WnhlfWXFN0HcgkTVUGf2GoKAs4AjWagi1zN68PHc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=hOTz4gul; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="hOTz4gul" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7D2572A31; Sun, 29 Mar 2026 09:34:50 -0700 (PDT) Received: from pluto.fritz.box (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 592F83F915; Sun, 29 Mar 2026 09:34:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1774802096; bh=uvOsmGvjVulKQfBZ+trVQ93a26jGUSXZoDI/MgW1pRs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hOTz4gulNj/dScoOXGZ09eMALYJGpfgkbH422H2T/JRkDklSOBiutHkJRjz78ngvx 0gCqTwM0wB5Hb6PfSk8fXhiISykPoYgd+P3yvdRtqj7hszHGBJWGCTFiuxSW4vn9Sl hD8debTrGwsNsuaHg5JtNLCHNXvSZW5YVjw59xAE= From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, arm-scmi@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-doc@vger.kernel.org Cc: sudeep.holla@kernel.org, james.quinlan@broadcom.com, f.fainelli@gmail.com, vincent.guittot@linaro.org, etienne.carriere@st.com, peng.fan@oss.nxp.com, michal.simek@amd.com, dan.carpenter@linaro.org, d-gole@ti.com, jonathan.cameron@huawei.com, elif.topuz@arm.com, lukasz.luba@arm.com, philip.radford@arm.com, brauner@kernel.org, souvik.chakravarty@arm.com, Cristian Marussi Subject: [PATCH v3 13/24] firmware: arm_scmi: Add Telemetry notification support Date: Sun, 29 Mar 2026 17:33:24 +0100 Message-ID: <20260329163337.637393-14-cristian.marussi@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260329163337.637393-1-cristian.marussi@arm.com> References: <20260329163337.637393-1-cristian.marussi@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for notifications to Telemetry protocol and register an internal notifier during protocol initialization: any DE value received inside a notification payload will be cached for future user consumption. Signed-off-by: Cristian Marussi --- v2 --> v3 - changed a few dev_err into traces - split from monolithic telemetry protocol patch - use memcpy_from_le32 --- drivers/firmware/arm_scmi/telemetry.c | 124 ++++++++++++++++++++++++-- include/linux/scmi_protocol.h | 9 ++ 2 files changed, 128 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/arm_scmi/telemetry.c b/drivers/firmware/arm_s= cmi/telemetry.c index ff0a5a8f6f57..c793ac616a2a 100644 --- a/drivers/firmware/arm_scmi/telemetry.c +++ b/drivers/firmware/arm_scmi/telemetry.c @@ -448,12 +448,16 @@ struct telemetry_info { struct list_head free_des; struct list_head fcs_des; struct scmi_telemetry_info info; + struct notifier_block telemetry_nb; atomic_t rinfo_initializing; struct completion rinfo_initdone; struct scmi_telemetry_res_info __private *rinfo; struct scmi_telemetry_res_info *(*res_get)(struct telemetry_info *ti); }; =20 +#define telemetry_nb_to_info(x) \ + container_of(x, struct telemetry_info, telemetry_nb) + static struct scmi_telemetry_res_info * __scmi_telemetry_resources_get(struct telemetry_info *ti); =20 @@ -2379,16 +2383,15 @@ scmi_telemetry_msg_payld_process(struct telemetry_i= nfo *ti, next +=3D LINE_LENGTH_WORDS(payld); =20 if (DATA_INVALID(payld)) { - dev_err(ti->ph->dev, "MSG - Received INVALID DATA line\n"); + trace_scmi_tlm_access(PAYLD_ID(payld), "MSG_INVALID", 0, 0); continue; } =20 de_id =3D le32_to_cpu(payld->id); de =3D xa_load(&ti->xa_des, de_id); if (!de || !de->enabled) { - dev_err(ti->ph->dev, - "MSG - Received INVALID DE - ID:%u enabled:%c\n", - de_id, de ? (de->enabled ? 'Y' : 'N') : 'X'); + trace_scmi_tlm_access(de_id, de ? "MSG_DE_DISABLED" : + "MSG_DE_UNKNOWN", 0, 0); continue; } =20 @@ -2513,6 +2516,98 @@ static const struct scmi_telemetry_proto_ops tlm_pro= to_ops =3D { .reset =3D scmi_telemetry_reset, }; =20 +static bool +scmi_telemetry_notify_supported(const struct scmi_protocol_handle *ph, + u8 evt_id, u32 src_id) +{ + struct telemetry_info *ti =3D ph->get_priv(ph); + + return ti->info.continuos_update_support; +} + +static int +scmi_telemetry_set_notify_enabled(const struct scmi_protocol_handle *ph, + u8 evt_id, u32 src_id, bool enable) +{ + return 0; +} + +static void * +scmi_telemetry_fill_custom_report(const struct scmi_protocol_handle *ph, + u8 evt_id, ktime_t timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + const struct scmi_telemetry_update_notify_payld *p =3D payld; + struct scmi_telemetry_update_report *r =3D report; + + /* At least sized as an empty notification */ + if (payld_sz < sizeof(*p)) + return NULL; + + r->timestamp =3D timestamp; + r->agent_id =3D le32_to_cpu(p->agent_id); + r->status =3D le32_to_cpu(p->status); + r->num_dwords =3D le32_to_cpu(p->num_dwords); + /* + * Allocated dwords and report are sized as max_msg_size, so as + * to allow for the maximum payload permitted by the configured + * transport. Overflow is not possible since out-of-size messages + * are dropped at the transport layer. + */ + if (r->num_dwords) + memcpy_from_le32(r->dwords, p->array, r->num_dwords); + + *src_id =3D 0; + + return r; +} + +static const struct scmi_event tlm_events[] =3D { + { + .id =3D SCMI_EVENT_TELEMETRY_UPDATE, + .max_payld_sz =3D 0, + .max_report_sz =3D 0, + }, +}; + +static const struct scmi_event_ops tlm_event_ops =3D { + .is_notify_supported =3D scmi_telemetry_notify_supported, + .set_notify_enabled =3D scmi_telemetry_set_notify_enabled, + .fill_custom_report =3D scmi_telemetry_fill_custom_report, +}; + +static const struct scmi_protocol_events tlm_protocol_events =3D { + .queue_sz =3D SCMI_PROTO_QUEUE_SZ, + .ops =3D &tlm_event_ops, + .evts =3D tlm_events, + .num_events =3D ARRAY_SIZE(tlm_events), + .num_sources =3D 1, +}; + +static int scmi_telemetry_notifier(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct scmi_telemetry_update_report *er =3D data; + struct telemetry_info *ti =3D telemetry_nb_to_info(nb); + + if (er->status) { + trace_scmi_tlm_access(0, "BAD_NOTIF_MSG", 0, 0); + return NOTIFY_DONE; + } + + trace_scmi_tlm_access(0, "TLM_UPDATE_MSG", 0, 0); + /* Lookup the embedded DEs in the notification payload ... */ + if (er->num_dwords) + scmi_telemetry_msg_payld_process(ti, er->num_dwords, er->dwords); + + /* ...scan the SHMTI/FCs for any other DE updates. */ + if (ti->streaming_mode) + scmi_telemetry_scan_update(ti); + + return NOTIFY_OK; +} + /** * scmi_telemetry_resources_alloc - Resources allocation * @ti: A reference to the telemetry info descriptor for this instance @@ -2757,7 +2852,25 @@ static int scmi_telemetry_protocol_init(const struct= scmi_protocol_handle *ph) =20 ti->info.base.version =3D ph->version; =20 - return ph->set_priv(ph, ti); + ret =3D ph->set_priv(ph, ti); + if (ret) + return ret; + + /* + * Register a notifier anyway straight upon protocol initialization + * since there could be some DEs that are ONLY reported by notifications + * even though the chosen collection method was SHMTI/FCs. + */ + if (ti->info.continuos_update_support) { + ti->telemetry_nb.notifier_call =3D &scmi_telemetry_notifier; + ret =3D ph->notifier_register(ph, SCMI_EVENT_TELEMETRY_UPDATE, + NULL, &ti->telemetry_nb); + if (ret) + dev_warn(ph->dev, + "Could NOT register Telemetry notifications\n"); + } + + return ret; } =20 static const struct scmi_protocol scmi_telemetry =3D { @@ -2765,6 +2878,7 @@ static const struct scmi_protocol scmi_telemetry =3D { .owner =3D THIS_MODULE, .instance_init =3D &scmi_telemetry_protocol_init, .ops =3D &tlm_proto_ops, + .events =3D &tlm_protocol_events, .supported_version =3D SCMI_PROTOCOL_SUPPORTED_VERSION, }; =20 diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index fc3b5493dc1a..9d8b12b2160e 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -1198,6 +1198,7 @@ enum scmi_notification_events { SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER =3D 0x0, SCMI_EVENT_POWERCAP_CAP_CHANGED =3D 0x0, SCMI_EVENT_POWERCAP_MEASUREMENTS_CHANGED =3D 0x1, + SCMI_EVENT_TELEMETRY_UPDATE =3D 0x0, }; =20 struct scmi_power_state_changed_report { @@ -1285,4 +1286,12 @@ struct scmi_powercap_meas_changed_report { unsigned int domain_id; unsigned int power; }; + +struct scmi_telemetry_update_report { + ktime_t timestamp; + unsigned int agent_id; + int status; + unsigned int num_dwords; + unsigned int dwords[]; +}; #endif /* _LINUX_SCMI_PROTOCOL_H */ --=20 2.53.0