1a0c45b0bSGil Fine /* SPDX-License-Identifier: GPL-2.0 */ 2a0c45b0bSGil Fine /* 3a0c45b0bSGil Fine * Thunderbolt tracing support 4a0c45b0bSGil Fine * 5a0c45b0bSGil Fine * Copyright (C) 2024, Intel Corporation 6a0c45b0bSGil Fine * Author: Mika Westerberg <mika.westerberg@linux.intel.com> 7a0c45b0bSGil Fine * Gil Fine <gil.fine@intel.com> 8a0c45b0bSGil Fine */ 9a0c45b0bSGil Fine 10a0c45b0bSGil Fine #undef TRACE_SYSTEM 11a0c45b0bSGil Fine #define TRACE_SYSTEM thunderbolt 12a0c45b0bSGil Fine 13a0c45b0bSGil Fine #if !defined(TB_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) 14a0c45b0bSGil Fine #define TB_TRACE_H_ 15a0c45b0bSGil Fine 16a0c45b0bSGil Fine #include <linux/trace_seq.h> 17a0c45b0bSGil Fine #include <linux/tracepoint.h> 18a0c45b0bSGil Fine 19a0c45b0bSGil Fine #include "tb_msgs.h" 20a0c45b0bSGil Fine 21a0c45b0bSGil Fine #define tb_cfg_type_name(type) { type, #type } 22a0c45b0bSGil Fine #define show_type_name(val) \ 23a0c45b0bSGil Fine __print_symbolic(val, \ 24a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_READ), \ 25a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_WRITE), \ 26a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_ERROR), \ 27a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_NOTIFY_ACK), \ 28a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_EVENT), \ 29a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_XDOMAIN_REQ), \ 30a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_XDOMAIN_RESP), \ 31a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_OVERRIDE), \ 32a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_RESET), \ 33a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_ICM_EVENT), \ 34a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_ICM_CMD), \ 35a0c45b0bSGil Fine tb_cfg_type_name(TB_CFG_PKG_ICM_RESP)) 36a0c45b0bSGil Fine 37a0c45b0bSGil Fine #ifndef TB_TRACE_HELPERS 38a0c45b0bSGil Fine #define TB_TRACE_HELPERS 39a0c45b0bSGil Fine static inline const char *show_data_read_write(struct trace_seq *p, 40a0c45b0bSGil Fine const u32 *data) 41a0c45b0bSGil Fine { 42a0c45b0bSGil Fine const struct cfg_read_pkg *msg = (const struct cfg_read_pkg *)data; 43a0c45b0bSGil Fine const char *ret = trace_seq_buffer_ptr(p); 44a0c45b0bSGil Fine 45a0c45b0bSGil Fine trace_seq_printf(p, "offset=%#x, len=%u, port=%d, config=%#x, seq=%d, ", 46a0c45b0bSGil Fine msg->addr.offset, msg->addr.length, msg->addr.port, 47a0c45b0bSGil Fine msg->addr.space, msg->addr.seq); 48a0c45b0bSGil Fine 49a0c45b0bSGil Fine return ret; 50a0c45b0bSGil Fine } 51a0c45b0bSGil Fine 52a0c45b0bSGil Fine static inline const char *show_data_error(struct trace_seq *p, const u32 *data) 53a0c45b0bSGil Fine { 54a0c45b0bSGil Fine const struct cfg_error_pkg *msg = (const struct cfg_error_pkg *)data; 55a0c45b0bSGil Fine const char *ret = trace_seq_buffer_ptr(p); 56a0c45b0bSGil Fine 57a0c45b0bSGil Fine trace_seq_printf(p, "error=%#x, port=%d, plug=%#x, ", msg->error, 58a0c45b0bSGil Fine msg->port, msg->pg); 59a0c45b0bSGil Fine 60a0c45b0bSGil Fine return ret; 61a0c45b0bSGil Fine } 62a0c45b0bSGil Fine 63a0c45b0bSGil Fine static inline const char *show_data_event(struct trace_seq *p, const u32 *data) 64a0c45b0bSGil Fine { 65a0c45b0bSGil Fine const struct cfg_event_pkg *msg = (const struct cfg_event_pkg *)data; 66a0c45b0bSGil Fine const char *ret = trace_seq_buffer_ptr(p); 67a0c45b0bSGil Fine 68a0c45b0bSGil Fine trace_seq_printf(p, "port=%d, unplug=%#x, ", msg->port, msg->unplug); 69a0c45b0bSGil Fine 70a0c45b0bSGil Fine return ret; 71a0c45b0bSGil Fine } 72a0c45b0bSGil Fine 73a0c45b0bSGil Fine static inline const char *show_route(struct trace_seq *p, const u32 *data) 74a0c45b0bSGil Fine { 75a0c45b0bSGil Fine const struct tb_cfg_header *header = (const struct tb_cfg_header *)data; 76a0c45b0bSGil Fine const char *ret = trace_seq_buffer_ptr(p); 77a0c45b0bSGil Fine 78a0c45b0bSGil Fine trace_seq_printf(p, "route=%llx, ", tb_cfg_get_route(header)); 79a0c45b0bSGil Fine 80a0c45b0bSGil Fine return ret; 81a0c45b0bSGil Fine } 82a0c45b0bSGil Fine 83a0c45b0bSGil Fine static inline const char *show_data(struct trace_seq *p, u8 type, 84a0c45b0bSGil Fine const u32 *data, u32 length) 85a0c45b0bSGil Fine { 86a0c45b0bSGil Fine const char *ret = trace_seq_buffer_ptr(p); 87a0c45b0bSGil Fine const char *prefix = ""; 88a0c45b0bSGil Fine int i; 89a0c45b0bSGil Fine 90a0c45b0bSGil Fine switch (type) { 91a0c45b0bSGil Fine case TB_CFG_PKG_READ: 92a0c45b0bSGil Fine case TB_CFG_PKG_WRITE: 93*a3dc6d82SMika Westerberg show_route(p, data); 94a0c45b0bSGil Fine show_data_read_write(p, data); 95a0c45b0bSGil Fine break; 96a0c45b0bSGil Fine 97a0c45b0bSGil Fine case TB_CFG_PKG_ERROR: 98*a3dc6d82SMika Westerberg show_route(p, data); 99a0c45b0bSGil Fine show_data_error(p, data); 100a0c45b0bSGil Fine break; 101a0c45b0bSGil Fine 102a0c45b0bSGil Fine case TB_CFG_PKG_EVENT: 103*a3dc6d82SMika Westerberg show_route(p, data); 104a0c45b0bSGil Fine show_data_event(p, data); 105a0c45b0bSGil Fine break; 106a0c45b0bSGil Fine 107*a3dc6d82SMika Westerberg case TB_CFG_PKG_ICM_EVENT: 108*a3dc6d82SMika Westerberg case TB_CFG_PKG_ICM_CMD: 109*a3dc6d82SMika Westerberg case TB_CFG_PKG_ICM_RESP: 110*a3dc6d82SMika Westerberg /* ICM messages always target the host router */ 111*a3dc6d82SMika Westerberg trace_seq_puts(p, "route=0, "); 112*a3dc6d82SMika Westerberg break; 113*a3dc6d82SMika Westerberg 114a0c45b0bSGil Fine default: 115*a3dc6d82SMika Westerberg show_route(p, data); 116a0c45b0bSGil Fine break; 117a0c45b0bSGil Fine } 118a0c45b0bSGil Fine 119a0c45b0bSGil Fine trace_seq_printf(p, "data=["); 120a0c45b0bSGil Fine for (i = 0; i < length; i++) { 121a0c45b0bSGil Fine trace_seq_printf(p, "%s0x%08x", prefix, data[i]); 122a0c45b0bSGil Fine prefix = ", "; 123a0c45b0bSGil Fine } 124a0c45b0bSGil Fine trace_seq_printf(p, "]"); 125a0c45b0bSGil Fine trace_seq_putc(p, 0); 126a0c45b0bSGil Fine 127a0c45b0bSGil Fine return ret; 128a0c45b0bSGil Fine } 129a0c45b0bSGil Fine #endif 130a0c45b0bSGil Fine 131a0c45b0bSGil Fine DECLARE_EVENT_CLASS(tb_raw, 132a0c45b0bSGil Fine TP_PROTO(int index, u8 type, const void *data, size_t size), 133a0c45b0bSGil Fine TP_ARGS(index, type, data, size), 134a0c45b0bSGil Fine TP_STRUCT__entry( 135a0c45b0bSGil Fine __field(int, index) 136a0c45b0bSGil Fine __field(u8, type) 137a0c45b0bSGil Fine __field(size_t, size) 138a0c45b0bSGil Fine __dynamic_array(u32, data, size / 4) 139a0c45b0bSGil Fine ), 140a0c45b0bSGil Fine TP_fast_assign( 141a0c45b0bSGil Fine __entry->index = index; 142a0c45b0bSGil Fine __entry->type = type; 143a0c45b0bSGil Fine __entry->size = size / 4; 144a0c45b0bSGil Fine memcpy(__get_dynamic_array(data), data, size); 145a0c45b0bSGil Fine ), 146a0c45b0bSGil Fine TP_printk("type=%s, size=%zd, domain=%d, %s", 147a0c45b0bSGil Fine show_type_name(__entry->type), __entry->size, __entry->index, 148a0c45b0bSGil Fine show_data(p, __entry->type, __get_dynamic_array(data), 149a0c45b0bSGil Fine __entry->size) 150a0c45b0bSGil Fine ) 151a0c45b0bSGil Fine ); 152a0c45b0bSGil Fine 153a0c45b0bSGil Fine DEFINE_EVENT(tb_raw, tb_tx, 154a0c45b0bSGil Fine TP_PROTO(int index, u8 type, const void *data, size_t size), 155a0c45b0bSGil Fine TP_ARGS(index, type, data, size) 156a0c45b0bSGil Fine ); 157a0c45b0bSGil Fine 158a0c45b0bSGil Fine DEFINE_EVENT(tb_raw, tb_event, 159a0c45b0bSGil Fine TP_PROTO(int index, u8 type, const void *data, size_t size), 160a0c45b0bSGil Fine TP_ARGS(index, type, data, size) 161a0c45b0bSGil Fine ); 162a0c45b0bSGil Fine 163a0c45b0bSGil Fine TRACE_EVENT(tb_rx, 164a0c45b0bSGil Fine TP_PROTO(int index, u8 type, const void *data, size_t size, bool dropped), 165a0c45b0bSGil Fine TP_ARGS(index, type, data, size, dropped), 166a0c45b0bSGil Fine TP_STRUCT__entry( 167a0c45b0bSGil Fine __field(int, index) 168a0c45b0bSGil Fine __field(u8, type) 169a0c45b0bSGil Fine __field(size_t, size) 170a0c45b0bSGil Fine __dynamic_array(u32, data, size / 4) 171a0c45b0bSGil Fine __field(bool, dropped) 172a0c45b0bSGil Fine ), 173a0c45b0bSGil Fine TP_fast_assign( 174a0c45b0bSGil Fine __entry->index = index; 175a0c45b0bSGil Fine __entry->type = type; 176a0c45b0bSGil Fine __entry->size = size / 4; 177a0c45b0bSGil Fine memcpy(__get_dynamic_array(data), data, size); 178a0c45b0bSGil Fine __entry->dropped = dropped; 179a0c45b0bSGil Fine ), 180a0c45b0bSGil Fine TP_printk("type=%s, dropped=%u, size=%zd, domain=%d, %s", 181a0c45b0bSGil Fine show_type_name(__entry->type), __entry->dropped, 182a0c45b0bSGil Fine __entry->size, __entry->index, 183a0c45b0bSGil Fine show_data(p, __entry->type, __get_dynamic_array(data), 184a0c45b0bSGil Fine __entry->size) 185a0c45b0bSGil Fine ) 186a0c45b0bSGil Fine ); 187a0c45b0bSGil Fine 188a0c45b0bSGil Fine #endif /* TB_TRACE_H_ */ 189a0c45b0bSGil Fine 190a0c45b0bSGil Fine #undef TRACE_INCLUDE_PATH 191a0c45b0bSGil Fine #define TRACE_INCLUDE_PATH . 192a0c45b0bSGil Fine 193a0c45b0bSGil Fine #undef TRACE_INCLUDE_FILE 194a0c45b0bSGil Fine #define TRACE_INCLUDE_FILE trace 195a0c45b0bSGil Fine 196a0c45b0bSGil Fine /* This part must be outside protection */ 197a0c45b0bSGil Fine #include <trace/define_trace.h> 198