mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 14:33:24 -04:00
firmware: qcom: scm: add trace events for the SMC call interface
The SCM SMC call path is opaque at runtime. Stalls caused by firmware
congestion, QCOM_SCM_WAITQ_SLEEP/RESUME cycles, and EBUSY retry loops
are invisible without recompiling the kernel with temporary printk
statements or attaching a hardware debugger.
Add five TRACE_EVENTs covering the complete lifecycle of an SCM call:
scm_smc_request
Emit before each arm_smccc_smc_quirk() invocation. Records the
SMC function ID, decoded service and command identifiers, argument
count, and up to six register arguments in hex and decimal. Because
the caller loops on QCOM_SCM_INTERRUPTED, this event fires once per
physical SMC instruction including inte
scm_smc_done
Emit after the outer __scm_smc_do() returns, pairing each
request with its final outcome. Records the SMC function ID, the
kernel error code returned to the caller, and the four firmware
result registers a0-a3.
scm_waitq_sleep
Emit when the firmware returns QCOM_SCM_WAITQ_SLEEP. Records
the wait-queue context and the SMC call context handles required
to issue the matching WAITQ_RESUME.
scm_waitq_resume
Emit just before constructing and sending the WAITQ_RESUME
follow-up call. Records the SMC call context handle being resumed.
scm_waitq_get_wq_ctx
Emit after a successful WAITQ_GET_WQ_CTX fast-call. Records
the returned wait-queue context, flags, and more_pending indicator.
These events let ftrace and perf reconstruct the full sequence of
firmware interactions, measure per-call and end-to-end latency, and
attribute waitqueue stalls to specific service/command pairs without
modifying driver source.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Yuvaraj Ranganathan <yuvaraj.ranganathan@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260522-scm-tracepoints-v2-1-e27cdbe0c585@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
This commit is contained in:
committed by
Bjorn Andersson
parent
f6540105e0
commit
f6bb2daa45
143
drivers/firmware/qcom/qcom_scm_trace.h
Normal file
143
drivers/firmware/qcom/qcom_scm_trace.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM qcom_scm
|
||||
|
||||
#if !defined(_TRACE_SCM_SMC_INTERFACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
|
||||
#define _TRACE_SCM_SMC_INTERFACE_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
TRACE_EVENT(scm_smc_request,
|
||||
|
||||
TP_PROTO(unsigned long a0, const struct arm_smccc_args *smc),
|
||||
|
||||
TP_ARGS(a0, smc),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u64, smc_id)
|
||||
__field(u8, svc_id)
|
||||
__field(u8, cmd_id)
|
||||
__field(u8, args_cnt)
|
||||
__dynamic_array(unsigned long, args,
|
||||
min_t(u8, (smc->args[1] & 0xF), (u8)6))
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->smc_id = a0;
|
||||
__entry->svc_id = (smc->args[0] >> 8) & 0xFF;
|
||||
__entry->cmd_id = smc->args[0] & 0xFF;
|
||||
u8 n = min_t(u8, (smc->args[1] & 0xF), (u8)6);
|
||||
|
||||
__entry->args_cnt = n;
|
||||
|
||||
unsigned long *dst = __get_dynamic_array(args);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
dst[i] = smc->args[2 + i];
|
||||
),
|
||||
|
||||
TP_printk("smc_id:0x%08llx svc_id:0x%02x cmd_id:0x%02x args_cnt:%u args:%s",
|
||||
__entry->smc_id, __entry->svc_id, __entry->cmd_id, __entry->args_cnt,
|
||||
__print_dynamic_array(args, sizeof(unsigned long)))
|
||||
);
|
||||
|
||||
TRACE_EVENT(scm_waitq_sleep,
|
||||
|
||||
TP_PROTO(u32 wq_ctx, u32 smc_ctx),
|
||||
|
||||
TP_ARGS(wq_ctx, smc_ctx),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, wq_ctx)
|
||||
__field(u32, smc_call_ctx)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->wq_ctx = wq_ctx;
|
||||
__entry->smc_call_ctx = smc_ctx;
|
||||
),
|
||||
|
||||
TP_printk("wq_ctx:%u, smc_call_ctx:%u", __entry->wq_ctx, __entry->smc_call_ctx)
|
||||
);
|
||||
|
||||
TRACE_EVENT(scm_waitq_resume,
|
||||
|
||||
TP_PROTO(u32 smc_ctx),
|
||||
|
||||
TP_ARGS(smc_ctx),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, smc_call_ctx)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->smc_call_ctx = smc_ctx;
|
||||
),
|
||||
|
||||
TP_printk("smc_call_ctx:%u", __entry->smc_call_ctx)
|
||||
);
|
||||
|
||||
TRACE_EVENT(scm_waitq_get_wq_ctx,
|
||||
|
||||
TP_PROTO(u32 wq_ctx, u32 flags, u32 pending),
|
||||
|
||||
TP_ARGS(wq_ctx, flags, pending),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, wq_ctx)
|
||||
__field(u32, flags)
|
||||
__field(u32, more_pending)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->wq_ctx = wq_ctx;
|
||||
__entry->flags = flags;
|
||||
__entry->more_pending = pending;
|
||||
),
|
||||
|
||||
TP_printk("wq_ctx:%u, flags:%u, more_pending:%u",
|
||||
__entry->wq_ctx, __entry->flags, __entry->more_pending)
|
||||
);
|
||||
|
||||
TRACE_EVENT(scm_smc_done,
|
||||
|
||||
TP_PROTO(int ret, u64 smc_id, struct arm_smccc_res *smc_res),
|
||||
|
||||
TP_ARGS(ret, smc_id, smc_res),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, ret)
|
||||
__field(u64, smc_id)
|
||||
__field(unsigned long, res)
|
||||
__field(unsigned long, res0)
|
||||
__field(unsigned long, res1)
|
||||
__field(unsigned long, res2)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->ret = ret;
|
||||
__entry->smc_id = smc_id;
|
||||
__entry->res = smc_res->a0;
|
||||
__entry->res0 = smc_res->a1;
|
||||
__entry->res1 = smc_res->a2;
|
||||
__entry->res2 = smc_res->a3;
|
||||
),
|
||||
|
||||
TP_printk("smc_id:0x%08llx, ret:%d res_to_callee:0x%lx res0:0x%lx res1:0x%lx res2:0x%lx",
|
||||
__entry->smc_id, __entry->ret, __entry->res,
|
||||
__entry->res0, __entry->res1, __entry->res2)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_SCM_SMC_INTERFACE_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#define TRACE_INCLUDE_FILE qcom_scm_trace
|
||||
|
||||
#include <trace/define_trace.h>
|
||||
|
||||
Reference in New Issue
Block a user