xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pktlog.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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