pi-linux/bsp/drivers/rpmsg/rpmsg_perf.c

137 lines
3.8 KiB
C

// SPDX-License-Identifier: GPL-2.0
#include <linux/aw_rpmsg.h>
#include <linux/amp_timestamp.h>
void *g_rpmsg_amp_ts_dev;
EXPORT_SYMBOL(g_rpmsg_amp_ts_dev);
uint64_t rpmsg_perf_get_timestamp(void)
{
int ret = 0;
uint64_t ts = 0;
if (!g_rpmsg_amp_ts_dev)
return 0;
ret = amp_ts_get_timestamp(g_rpmsg_amp_ts_dev, &ts);
if (ret) {
pr_err("amp_ts_get_timestamp failed, ret: %d", ret);
}
return ts;
}
EXPORT_SYMBOL(rpmsg_perf_get_timestamp);
int rpmsg_get_raw_perf_data(struct rpmsg_endpoint *ept, uint8_t *buf, uint32_t len)
{
uint32_t target_len;
struct aw_rpmsg_endpoint *aw_ept;
if (!ept || !buf || !len) {
pr_err("invalid arguments\n");
return -EINVAL;
}
target_len = (RPMSG_TRACE_TIMESTAMP_NUM) * sizeof(uint64_t);
if (len != target_len) {
pr_err("perf data buf length(%u) is not equal to %u", len, target_len);
return -EINVAL;
}
aw_ept = EPT_TO_AW_EPT(ept);
memcpy(buf, aw_ept->trace, len);
return 0;
}
EXPORT_SYMBOL(rpmsg_get_raw_perf_data);
int rpmsg_get_perf_data(struct rpmsg_endpoint *ept, rpmsg_perf_data_t *perf_data)
{
int ret, i, j;
uint64_t buf[RPMSG_TRACE_TIMESTAMP_NUM];
if (((sizeof(perf_data->time_span) / sizeof(uint32_t)) != (RPMSG_TRACE_TIMESTAMP_NUM - 1))
|| (sizeof(perf_data->time_span) != sizeof(perf_data->timestamp))) {
pr_err("rpbuf perf data definition is not correct!\n");
return -EINVAL;
}
ret = rpmsg_get_raw_perf_data(ept, (uint8_t *)buf, sizeof(buf));
if (ret)
return ret;
perf_data->raw_timestamp = buf[RPMSG_TRACE_START];
memset(perf_data->timestamp, 0, sizeof(perf_data->timestamp));
for (i = RPMSG_TRACE_START + 1, j = 0; i <= RPMSG_TRACE_END; i++, j++) {
perf_data->timestamp[j] = buf[i] - buf[RPMSG_TRACE_START];
}
memset(perf_data->time_span, 0, sizeof(perf_data->time_span));
for (i = RPMSG_TRACE_START + 1, j = 0; i <= RPMSG_TRACE_END; i++, j++) {
if (i == RPMSG_TRACE_R_PREPARE) {
perf_data->time_span[j] = buf[i] - buf[RPMSG_TRACE_S_NOTIFY];
} else {
perf_data->time_span[j] = buf[i] - buf[i - 1];
}
}
return 0;
}
EXPORT_SYMBOL(rpmsg_get_perf_data);
void rpmsg_dump_perf_data(const rpmsg_perf_data_t *perf_data)
{
uint64_t quotient;
uint32_t ts, time_span, remainder;
quotient = div_u64_rem(perf_data->raw_timestamp, 1000, &remainder);
pr_info("Timestamp:\n");
pr_info("Sender >>\n");
pr_info("Start : 0 us [%llu.%llu ms]\n", quotient, (uint64_t)remainder);
ts = perf_data->timestamp[RPMSG_PERF_POINT_SENDER_FILL];
pr_info("Fill buffer : %u us\n", ts);
ts = perf_data->timestamp[RPMSG_PERF_POINT_SENDER_NOTIFY];
pr_info("Notify : %u us\n", ts);
ts = perf_data->timestamp[RPMSG_PERF_POINT_SENDER_END];
pr_info("End : %u us\n", ts);
pr_info("Receiver<<\n");
ts = perf_data->timestamp[RPMSG_PERF_POINT_RECEIVER_PREPARE];
pr_info("Prepare : %u us\n", ts);
ts = perf_data->timestamp[RPMSG_PERF_POINT_RECEIVER_EXEC_CB];
pr_info("Exec CB : %u us\n", ts);
ts = perf_data->timestamp[RPMSG_PERF_POINT_RECEIVER_END];
pr_info("End : %u us\n", ts);
pr_info("Time span:\n");
pr_info("Sender >>\n");
time_span = perf_data->time_span[RPMSG_PERF_STAGE_SENDER_PREPARE];
pr_info("Prepare : %u us\n", time_span);
time_span = perf_data->time_span[RPMSG_PERF_STAGE_SENDER_FILL];
pr_info("Fill buffer : %u us\n", time_span);
time_span = perf_data->time_span[RPMSG_PERF_STAGE_SENDER_NOTIFY];
pr_info("Notify : %u us\n", time_span);
pr_info("Receiver<<\n");
time_span = perf_data->time_span[RPMSG_PERF_STAGE_RECEIVER_RECV];
pr_info("Recv : %u us\n", time_span);
time_span = perf_data->time_span[RPMSG_PERF_STAGE_RECEIVER_PREPARE];
pr_info("Prepare : %u us\n", time_span);
time_span = perf_data->time_span[RPMSG_PERF_STAGE_RECEIVER_EXEC_CB];
pr_info("Exec CB : %u us\n", time_span);
}
EXPORT_SYMBOL(rpmsg_dump_perf_data);