1 /* 2 * DHD debugability packet logging header file 3 * 4 * Copyright (C) 2020, Broadcom. 5 * 6 * Unless you and Broadcom execute a separate written software license 7 * agreement governing use of this software, this software is licensed to you 8 * under the terms of the GNU General Public License version 2 (the "GPL"), 9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10 * following added to such license: 11 * 12 * As a special exception, the copyright holders of this software give you 13 * permission to link this software with independent modules, and to copy and 14 * distribute the resulting executable under terms of your choice, provided that 15 * you also meet, for each linked independent module, the terms and conditions of 16 * the license of that module. An independent module is a module which is not 17 * derived from this software. The special exception does not apply to any 18 * modifications of the software. 19 * 20 * 21 * <<Broadcom-WL-IPTag/Open:>> 22 * 23 * $Id$ 24 */ 25 26 #ifndef __DHD_PKTLOG_H_ 27 #define __DHD_PKTLOG_H_ 28 29 #include <dhd_debug.h> 30 #include <dhd.h> 31 #include <asm/atomic.h> 32 #ifdef DHD_COMPACT_PKT_LOG 33 #include <linux/rbtree.h> 34 #endif /* DHD_COMPACT_PKT_LOG */ 35 36 #ifdef DHD_PKT_LOGGING 37 #define DHD_PKT_LOG(args) DHD_INFO(args) 38 #define DEFAULT_MULTIPLE_PKTLOG_BUF 1 39 #ifndef CUSTOM_MULTIPLE_PKTLOG_BUF 40 #define CUSTOM_MULTIPLE_PKTLOG_BUF DEFAULT_MULTIPLE_PKTLOG_BUF 41 #endif /* CUSTOM_MULTIPLE_PKTLOG_BUF */ 42 #define MIN_PKTLOG_LEN (32 * 10 * 2 * CUSTOM_MULTIPLE_PKTLOG_BUF) 43 #define MAX_PKTLOG_LEN (32 * 10 * 2 * 10) 44 #define MAX_DHD_PKTLOG_FILTER_LEN 14 45 #define MAX_MASK_PATTERN_FILTER_LEN 64 46 #define PKTLOG_TXPKT_CASE 0x0001 47 #define PKTLOG_TXSTATUS_CASE 0x0002 48 #define PKTLOG_RXPKT_CASE 0x0004 49 /* MAX_FILTER_PATTERN_LEN is buf len to print bitmask/pattern with string */ 50 #define MAX_FILTER_PATTERN_LEN \ 51 ((MAX_MASK_PATTERN_FILTER_LEN * HD_BYTE_SIZE) + HD_PREFIX_SIZE + 1) * 2 52 #define PKTLOG_DUMP_BUF_SIZE (64 * 1024) 53 54 typedef struct dhd_dbg_pktlog_info { 55 frame_type payload_type; 56 size_t pkt_len; 57 uint32 driver_ts_sec; 58 uint32 driver_ts_usec; 59 uint32 firmware_ts; 60 uint32 pkt_hash; 61 bool direction; 62 void *pkt; 63 } dhd_dbg_pktlog_info_t; 64 65 typedef struct dhd_pktlog_ring_info 66 { 67 dll_t p_info; /* list pointer */ 68 union { 69 wifi_tx_packet_fate tx_fate; 70 wifi_rx_packet_fate rx_fate; 71 uint32 fate; 72 }; 73 dhd_dbg_pktlog_info_t info; 74 } dhd_pktlog_ring_info_t; 75 76 typedef struct dhd_pktlog_ring 77 { 78 dll_t ring_info_head; /* ring_info list */ 79 dll_t ring_info_free; /* ring_info free list */ 80 osl_atomic_t start; 81 uint32 pktlog_minmize; 82 uint32 pktlog_len; /* size of pkts */ 83 uint32 pktcount; 84 spinlock_t *pktlog_ring_lock; 85 dhd_pub_t *dhdp; 86 dhd_pktlog_ring_info_t *ring_info_mem; /* ring_info mem pointer */ 87 } dhd_pktlog_ring_t; 88 89 typedef struct dhd_pktlog_filter_info 90 { 91 uint32 id; 92 uint32 offset; 93 uint32 size_bytes; /* Size of pattern. */ 94 uint32 enable; 95 uint8 mask[MAX_MASK_PATTERN_FILTER_LEN]; 96 uint8 pattern[MAX_MASK_PATTERN_FILTER_LEN]; 97 } dhd_pktlog_filter_info_t; 98 99 typedef struct dhd_pktlog_filter 100 { 101 dhd_pktlog_filter_info_t *info; 102 uint32 list_cnt; 103 uint32 enable; 104 } dhd_pktlog_filter_t; 105 106 typedef struct dhd_pktlog 107 { 108 struct dhd_pktlog_ring *pktlog_ring; 109 struct dhd_pktlog_filter *pktlog_filter; 110 osl_atomic_t pktlog_status; 111 dhd_pub_t *dhdp; 112 #ifdef DHD_COMPACT_PKT_LOG 113 struct rb_root cpkt_log_tt_rbt; 114 #endif /* DHD_COMPACT_PKT_LOG */ 115 } dhd_pktlog_t; 116 117 typedef struct dhd_pktlog_pcap_hdr 118 { 119 uint32 magic_number; 120 uint16 version_major; 121 uint16 version_minor; 122 uint16 thiszone; 123 uint32 sigfigs; 124 uint32 snaplen; 125 uint32 network; 126 } dhd_pktlog_pcap_hdr_t; 127 128 #define PKTLOG_PCAP_MAGIC_NUM 0xa1b2c3d4 129 #define PKTLOG_PCAP_MAJOR_VER 0x02 130 #define PKTLOG_PCAP_MINOR_VER 0x04 131 #define PKTLOG_PCAP_SNAP_LEN 0x40000 132 #define PKTLOG_PCAP_NETWORK_TYPE 147 133 134 extern int dhd_os_attach_pktlog(dhd_pub_t *dhdp); 135 extern int dhd_os_detach_pktlog(dhd_pub_t *dhdp); 136 extern dhd_pktlog_ring_t* dhd_pktlog_ring_init(dhd_pub_t *dhdp, int size); 137 extern int dhd_pktlog_ring_deinit(dhd_pub_t *dhdp, dhd_pktlog_ring_t *ring); 138 extern int dhd_pktlog_ring_set_nextpos(dhd_pktlog_ring_t *ringbuf); 139 extern int dhd_pktlog_ring_get_nextbuf(dhd_pktlog_ring_t *ringbuf, void **data); 140 extern int dhd_pktlog_ring_set_prevpos(dhd_pktlog_ring_t *ringbuf); 141 extern int dhd_pktlog_ring_get_prevbuf(dhd_pktlog_ring_t *ringbuf, void **data); 142 extern int dhd_pktlog_ring_get_writebuf(dhd_pktlog_ring_t *ringbuf, void **data); 143 extern int dhd_pktlog_ring_add_pkts(dhd_pub_t *dhdp, void *pkt, void *pktdata, uint32 pktid, 144 uint32 direction); 145 extern int dhd_pktlog_ring_tx_status(dhd_pub_t *dhdp, void *pkt, void *pktdata, uint32 pktid, 146 uint16 status); 147 extern dhd_pktlog_ring_t* dhd_pktlog_ring_change_size(dhd_pktlog_ring_t *ringbuf, int size); 148 extern void dhd_pktlog_filter_pull_forward(dhd_pktlog_filter_t *filter, 149 uint32 del_filter_id, uint32 list_cnt); 150 151 #define PKT_RX 0 152 #define PKT_TX 1 153 #define PKT_WAKERX 2 154 #define DHD_INVALID_PKTID (0U) 155 #define PKTLOG_TRANS_TX 0x01 156 #define PKTLOG_TRANS_RX 0x02 157 #define PKTLOG_TRANS_TXS 0x04 158 159 #define PKTLOG_SET_IN_TX(dhdp) \ 160 { \ 161 do { \ 162 OSL_ATOMIC_OR((dhdp)->osh, &(dhdp)->pktlog->pktlog_status, PKTLOG_TRANS_TX); \ 163 } while (0); \ 164 } 165 166 #define PKTLOG_SET_IN_RX(dhdp) \ 167 { \ 168 do { \ 169 OSL_ATOMIC_OR((dhdp)->osh, &(dhdp)->pktlog->pktlog_status, PKTLOG_TRANS_RX); \ 170 } while (0); \ 171 } 172 173 #define PKTLOG_SET_IN_TXS(dhdp) \ 174 { \ 175 do { \ 176 OSL_ATOMIC_OR((dhdp)->osh, &(dhdp)->pktlog->pktlog_status, PKTLOG_TRANS_TXS); \ 177 } while (0); \ 178 } 179 180 #define PKTLOG_CLEAR_IN_TX(dhdp) \ 181 { \ 182 do { \ 183 OSL_ATOMIC_AND((dhdp)->osh, &(dhdp)->pktlog->pktlog_status, ~PKTLOG_TRANS_TX); \ 184 } while (0); \ 185 } 186 187 #define PKTLOG_CLEAR_IN_RX(dhdp) \ 188 { \ 189 do { \ 190 OSL_ATOMIC_AND((dhdp)->osh, &(dhdp)->pktlog->pktlog_status, ~PKTLOG_TRANS_RX); \ 191 } while (0); \ 192 } 193 194 #define PKTLOG_CLEAR_IN_TXS(dhdp) \ 195 { \ 196 do { \ 197 OSL_ATOMIC_AND((dhdp)->osh, &(dhdp)->pktlog->pktlog_status, ~PKTLOG_TRANS_TXS); \ 198 } while (0); \ 199 } 200 201 #define DHD_PKTLOG_TX(dhdp, pkt, pktdata, pktid) \ 202 { \ 203 do { \ 204 if ((dhdp) && (dhdp)->pktlog && (pkt)) { \ 205 PKTLOG_SET_IN_TX(dhdp); \ 206 if ((dhdp)->pktlog->pktlog_ring && \ 207 OSL_ATOMIC_READ((dhdp)->osh, \ 208 (&(dhdp)->pktlog->pktlog_ring->start))) { \ 209 dhd_pktlog_ring_add_pkts(dhdp, pkt, pktdata, pktid, PKT_TX); \ 210 } \ 211 PKTLOG_CLEAR_IN_TX(dhdp); \ 212 } \ 213 } while (0); \ 214 } 215 216 #define DHD_PKTLOG_TXS(dhdp, pkt, pktdata, pktid, status) \ 217 { \ 218 do { \ 219 if ((dhdp) && (dhdp)->pktlog && (pkt)) { \ 220 PKTLOG_SET_IN_TXS(dhdp); \ 221 if ((dhdp)->pktlog->pktlog_ring && \ 222 OSL_ATOMIC_READ((dhdp)->osh, \ 223 (&(dhdp)->pktlog->pktlog_ring->start))) { \ 224 dhd_pktlog_ring_tx_status(dhdp, pkt, pktdata, pktid, status); \ 225 } \ 226 PKTLOG_CLEAR_IN_TXS(dhdp); \ 227 } \ 228 } while (0); \ 229 } 230 231 #define DHD_PKTLOG_RX(dhdp, pkt, pktdata) \ 232 { \ 233 do { \ 234 if ((dhdp) && (dhdp)->pktlog && (pkt)) { \ 235 PKTLOG_SET_IN_RX(dhdp); \ 236 if (ntoh16((pkt)->protocol) != ETHER_TYPE_BRCM) { \ 237 if ((dhdp)->pktlog->pktlog_ring && \ 238 OSL_ATOMIC_READ((dhdp)->osh, \ 239 (&(dhdp)->pktlog->pktlog_ring->start))) { \ 240 dhd_pktlog_ring_add_pkts(dhdp, pkt, pktdata, \ 241 DHD_INVALID_PKTID, PKT_RX); \ 242 } \ 243 } \ 244 PKTLOG_CLEAR_IN_RX(dhdp); \ 245 } \ 246 } while (0); \ 247 } 248 249 #define DHD_PKTLOG_WAKERX(dhdp, pkt, pktdata) \ 250 { \ 251 do { \ 252 if ((dhdp) && (dhdp)->pktlog && (pkt)) { \ 253 PKTLOG_SET_IN_RX(dhdp); \ 254 if (ntoh16((pkt)->protocol) != ETHER_TYPE_BRCM) { \ 255 if ((dhdp)->pktlog->pktlog_ring && \ 256 OSL_ATOMIC_READ((dhdp)->osh, \ 257 (&(dhdp)->pktlog->pktlog_ring->start))) { \ 258 dhd_pktlog_ring_add_pkts(dhdp, pkt, pktdata, \ 259 DHD_INVALID_PKTID, PKT_WAKERX); \ 260 } \ 261 } \ 262 PKTLOG_CLEAR_IN_RX(dhdp); \ 263 } \ 264 } while (0); \ 265 } 266 267 extern dhd_pktlog_filter_t* dhd_pktlog_filter_init(int size); 268 extern int dhd_pktlog_filter_deinit(dhd_pktlog_filter_t *filter); 269 extern int dhd_pktlog_filter_add(dhd_pktlog_filter_t *filter, char *arg); 270 extern int dhd_pktlog_filter_del(dhd_pktlog_filter_t *filter, char *arg); 271 extern int dhd_pktlog_filter_enable(dhd_pktlog_filter_t *filter, uint32 pktlog_case, uint32 enable); 272 extern int dhd_pktlog_filter_pattern_enable(dhd_pktlog_filter_t *filter, char *arg, uint32 enable); 273 extern int dhd_pktlog_filter_info(dhd_pktlog_filter_t *filter); 274 extern bool dhd_pktlog_filter_matched(dhd_pktlog_filter_t *filter, char *data, uint32 pktlog_case); 275 extern bool dhd_pktlog_filter_existed(dhd_pktlog_filter_t *filter, char *arg, uint32 *id); 276 277 #define DHD_PKTLOG_FILTER_ADD(pattern, filter_pattern, dhdp) \ 278 { \ 279 do { \ 280 if ((strlen(pattern) + 1) < sizeof(filter_pattern)) { \ 281 strncpy(filter_pattern, pattern, sizeof(filter_pattern)); \ 282 dhd_pktlog_filter_add(dhdp->pktlog->pktlog_filter, filter_pattern); \ 283 } \ 284 } while (0); \ 285 } 286 287 #define DHD_PKTLOG_DUMP_PATH DHD_COMMON_DUMP_PATH 288 extern int dhd_pktlog_debug_dump(dhd_pub_t *dhdp); 289 extern void dhd_pktlog_dump(void *handle, void *event_info, u8 event); 290 extern void dhd_schedule_pktlog_dump(dhd_pub_t *dhdp); 291 extern int dhd_pktlog_dump_write_memory(dhd_pub_t *dhdp, const void *user_buf, uint32 size); 292 extern int dhd_pktlog_dump_write_file(dhd_pub_t *dhdp); 293 294 #define DHD_PKTLOG_FATE_INFO_STR_LEN 256 295 #define DHD_PKTLOG_FATE_INFO_FORMAT "BRCM_Packet_Fate" 296 #define DHD_PKTLOG_DUMP_TYPE "pktlog_dump" 297 #define DHD_PKTLOG_DEBUG_DUMP_TYPE "pktlog_debug_dump" 298 299 extern void dhd_pktlog_get_filename(dhd_pub_t *dhdp, char *dump_path, int len); 300 extern uint32 dhd_pktlog_get_item_length(dhd_pktlog_ring_info_t *report_ptr); 301 extern uint32 dhd_pktlog_get_dump_length(dhd_pub_t *dhdp); 302 extern uint32 __dhd_dbg_pkt_hash(uintptr_t pkt, uint32 pktid); 303 304 #ifdef DHD_COMPACT_PKT_LOG 305 #define CPKT_LOG_BIT_SIZE 22 306 #define CPKT_LOG_MAX_NUM 80 307 extern int dhd_cpkt_log_proc(dhd_pub_t *dhdp, char *buf, int buf_len, 308 int bit_offset, int req_pkt_num); 309 #endif /* DHD_COMPACT_PKT_LOG */ 310 #endif /* DHD_PKT_LOGGING */ 311 #endif /* __DHD_PKTLOG_H_ */ 312