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