• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * DHD debugability header file
4  *
5  * <<Broadcom-WL-IPTag/Open:>>
6  *
7  * Copyright (C) 1999-2019, Broadcom.
8  *
9  *      Unless you and Broadcom execute a separate written software license
10  * agreement governing use of this software, this software is licensed to you
11  * under the terms of the GNU General Public License version 2 (the "GPL"),
12  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
13  * following added to such license:
14  *
15  *      As a special exception, the copyright holders of this software give you
16  * permission to link this software with independent modules, and to copy and
17  * distribute the resulting executable under terms of your choice, provided that
18  * you also meet, for each linked independent module, the terms and conditions of
19  * the license of that module.  An independent module is a module which is not
20  * derived from this software.  The special exception does not apply to any
21  * modifications of the software.
22  *
23  *      Notwithstanding the above, under no circumstances may you combine this
24  * software in any way with any other Broadcom software provided under a license
25  * other than the GPL, without Broadcom's express prior written consent.
26  *
27  * $Id: dhd_debug.h 783721 2018-10-08 13:05:26Z $
28  */
29 
30 #ifndef _dhd_debug_h_
31 #define _dhd_debug_h_
32 #include <event_log.h>
33 #include <bcmutils.h>
34 #include <dhd_dbg_ring.h>
35 
36 enum {
37 	DEBUG_RING_ID_INVALID	= 0,
38 	FW_VERBOSE_RING_ID,
39 	DHD_EVENT_RING_ID,
40 	/* add new id here */
41 	DEBUG_RING_ID_MAX
42 };
43 
44 enum {
45 	/* Feature set */
46 	DBG_MEMORY_DUMP_SUPPORTED = (1 << (0)), /* Memory dump of FW */
47 	DBG_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), /* PKT Status */
48 	DBG_CONNECT_EVENT_SUPPORTED = (1 << (2)), /* Connectivity Event */
49 	DBG_POWER_EVENT_SUPOORTED = (1 << (3)), /* POWER of Driver */
50 	DBG_WAKE_LOCK_SUPPORTED = (1 << (4)), /* WAKE LOCK of Driver */
51 	DBG_VERBOSE_LOG_SUPPORTED = (1 << (5)), /* verbose log of FW */
52 	DBG_HEALTH_CHECK_SUPPORTED = (1 << (6)), /* monitor the health of FW */
53 	DBG_DRIVER_DUMP_SUPPORTED = (1 << (7)), /* dumps driver state */
54 	DBG_PACKET_FATE_SUPPORTED = (1 << (8)), /* tracks connection packets' fate */
55 	DBG_NAN_EVENT_SUPPORTED = (1 << (9)), /* NAN Events */
56 };
57 
58 enum {
59 	/* set for binary entries */
60 	DBG_RING_ENTRY_FLAGS_HAS_BINARY = (1 << (0)),
61 	/* set if 64 bits timestamp is present */
62 	DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP = (1 << (1))
63 };
64 
65 /* firmware verbose ring, ring id 1 */
66 #define FW_VERBOSE_RING_NAME		"fw_verbose"
67 #define FW_VERBOSE_RING_SIZE		(256 * 1024)
68 /* firmware event ring, ring id 2 */
69 #define FW_EVENT_RING_NAME		"fw_event"
70 #define FW_EVENT_RING_SIZE		(64 * 1024)
71 /* DHD connection event ring, ring id 3 */
72 #define DHD_EVENT_RING_NAME		"dhd_event"
73 #define DHD_EVENT_RING_SIZE		(64 * 1024)
74 /* NAN event ring, ring id 4 */
75 #define NAN_EVENT_RING_NAME		"nan_event"
76 #define NAN_EVENT_RING_SIZE		(64 * 1024)
77 
78 #define TLV_LOG_SIZE(tlv) ((tlv) ? (sizeof(tlv_log) + (tlv)->len) : 0)
79 
80 #define TLV_LOG_NEXT(tlv) \
81 	((tlv) ? ((tlv_log *)((uint8 *)tlv + TLV_LOG_SIZE(tlv))) : 0)
82 
83 #define VALID_RING(id)	\
84 	((id > DEBUG_RING_ID_INVALID) && (id < DEBUG_RING_ID_MAX))
85 
86 #ifdef DEBUGABILITY
87 #define DBG_RING_ACTIVE(dhdp, ring_id) \
88 	((dhdp)->dbg->dbg_rings[(ring_id)].state == RING_ACTIVE)
89 #else
90 #define DBG_RING_ACTIVE(dhdp, ring_id) 0
91 #endif /* DEBUGABILITY */
92 
93 enum {
94 	/* driver receive association command from kernel */
95 	WIFI_EVENT_ASSOCIATION_REQUESTED	= 0,
96 	WIFI_EVENT_AUTH_COMPLETE,
97 	WIFI_EVENT_ASSOC_COMPLETE,
98 	/* received firmware event indicating auth frames are sent */
99 	WIFI_EVENT_FW_AUTH_STARTED,
100 	/* received firmware event indicating assoc frames are sent */
101 	WIFI_EVENT_FW_ASSOC_STARTED,
102 	/* received firmware event indicating reassoc frames are sent */
103 	WIFI_EVENT_FW_RE_ASSOC_STARTED,
104 	WIFI_EVENT_DRIVER_SCAN_REQUESTED,
105 	WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND,
106 	WIFI_EVENT_DRIVER_SCAN_COMPLETE,
107 	WIFI_EVENT_G_SCAN_STARTED,
108 	WIFI_EVENT_G_SCAN_COMPLETE,
109 	WIFI_EVENT_DISASSOCIATION_REQUESTED,
110 	WIFI_EVENT_RE_ASSOCIATION_REQUESTED,
111 	WIFI_EVENT_ROAM_REQUESTED,
112 	/* received beacon from AP (event enabled only in verbose mode) */
113 	WIFI_EVENT_BEACON_RECEIVED,
114 	/* firmware has triggered a roam scan (not g-scan) */
115 	WIFI_EVENT_ROAM_SCAN_STARTED,
116 	/* firmware has completed a roam scan (not g-scan) */
117 	WIFI_EVENT_ROAM_SCAN_COMPLETE,
118 	/* firmware has started searching for roam candidates (with reason =xx) */
119 	WIFI_EVENT_ROAM_SEARCH_STARTED,
120 	/* firmware has stopped searching for roam candidates (with reason =xx) */
121 	WIFI_EVENT_ROAM_SEARCH_STOPPED,
122 	WIFI_EVENT_UNUSED_0,
123 	/* received channel switch anouncement from AP */
124 	WIFI_EVENT_CHANNEL_SWITCH_ANOUNCEMENT,
125 	/* fw start transmit eapol frame, with EAPOL index 1-4 */
126 	WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START,
127 	/* fw gives up eapol frame, with rate, success/failure and number retries */
128 	WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP,
129 	/* kernel queue EAPOL for transmission in driver with EAPOL index 1-4 */
130 	WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED,
131 	/* with rate, regardless of the fact that EAPOL frame is accepted or
132 	 * rejected by firmware
133 	 */
134 	WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED,
135 	WIFI_EVENT_UNUSED_1,
136 	/* with rate, and eapol index, driver has received */
137 	/* EAPOL frame and will queue it up to wpa_supplicant */
138 	WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED,
139 	/* with success/failure, parameters */
140 	WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE,
141 	WIFI_EVENT_BT_COEX_BT_SCO_START,
142 	WIFI_EVENT_BT_COEX_BT_SCO_STOP,
143 	/* for paging/scan etc..., when BT starts transmiting twice per BT slot */
144 	WIFI_EVENT_BT_COEX_BT_SCAN_START,
145 	WIFI_EVENT_BT_COEX_BT_SCAN_STOP,
146 	WIFI_EVENT_BT_COEX_BT_HID_START,
147 	WIFI_EVENT_BT_COEX_BT_HID_STOP,
148 	/* firmware sends auth frame in roaming to next candidate */
149 	WIFI_EVENT_ROAM_AUTH_STARTED,
150 	/* firmware receive auth confirm from ap */
151 	WIFI_EVENT_ROAM_AUTH_COMPLETE,
152 	/* firmware sends assoc/reassoc frame in */
153 	WIFI_EVENT_ROAM_ASSOC_STARTED,
154 	/* firmware receive assoc/reassoc confirm from ap */
155 	WIFI_EVENT_ROAM_ASSOC_COMPLETE,
156 	/* firmware sends stop G_SCAN */
157 	WIFI_EVENT_G_SCAN_STOP,
158 	/* firmware indicates G_SCAN scan cycle started */
159 	WIFI_EVENT_G_SCAN_CYCLE_STARTED,
160 	/* firmware indicates G_SCAN scan cycle completed */
161 	WIFI_EVENT_G_SCAN_CYCLE_COMPLETED,
162 	/* firmware indicates G_SCAN scan start for a particular bucket */
163 	WIFI_EVENT_G_SCAN_BUCKET_STARTED,
164 	/* firmware indicates G_SCAN scan completed for particular bucket */
165 	WIFI_EVENT_G_SCAN_BUCKET_COMPLETED,
166 	/* Event received from firmware about G_SCAN scan results being available */
167 	WIFI_EVENT_G_SCAN_RESULTS_AVAILABLE,
168 	/* Event received from firmware with G_SCAN capabilities */
169 	WIFI_EVENT_G_SCAN_CAPABILITIES,
170 	/* Event received from firmware when eligible candidate is found */
171 	WIFI_EVENT_ROAM_CANDIDATE_FOUND,
172 	/* Event received from firmware when roam scan configuration gets enabled or disabled */
173 	WIFI_EVENT_ROAM_SCAN_CONFIG,
174 	/* firmware/driver timed out authentication */
175 	WIFI_EVENT_AUTH_TIMEOUT,
176 	/* firmware/driver timed out association */
177 	WIFI_EVENT_ASSOC_TIMEOUT,
178 	/* firmware/driver encountered allocation failure */
179 	WIFI_EVENT_MEM_ALLOC_FAILURE,
180 	/* driver added a PNO network in firmware */
181 	WIFI_EVENT_DRIVER_PNO_ADD,
182 	/* driver removed a PNO network in firmware */
183 	WIFI_EVENT_DRIVER_PNO_REMOVE,
184 	/* driver received PNO networks found indication from firmware */
185 	WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND,
186 	/* driver triggered a scan for PNO networks */
187 	WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED,
188 	/* driver received scan results of PNO networks */
189 	WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND,
190 	/* driver updated scan results from PNO candidates to cfg */
191 	WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE
192 };
193 
194 enum {
195 	WIFI_TAG_VENDOR_SPECIFIC = 0, /* take a byte stream as parameter */
196 	WIFI_TAG_BSSID, /* takes a 6 bytes MAC address as parameter */
197 	WIFI_TAG_ADDR, /* takes a 6 bytes MAC address as parameter */
198 	WIFI_TAG_SSID, /* takes a 32 bytes SSID address as parameter */
199 	WIFI_TAG_STATUS, /* takes an integer as parameter */
200 	WIFI_TAG_CHANNEL_SPEC, /* takes one or more wifi_channel_spec as parameter */
201 	WIFI_TAG_WAKE_LOCK_EVENT, /* takes a wake_lock_event struct as parameter */
202 	WIFI_TAG_ADDR1, /* takes a 6 bytes MAC address as parameter */
203 	WIFI_TAG_ADDR2, /* takes a 6 bytes MAC address as parameter */
204 	WIFI_TAG_ADDR3, /* takes a 6 bytes MAC address as parameter */
205 	WIFI_TAG_ADDR4, /* takes a 6 bytes MAC address as parameter */
206 	WIFI_TAG_TSF, /* take a 64 bits TSF value as parameter */
207 	WIFI_TAG_IE,
208 	/* take one or more specific 802.11 IEs parameter, IEs are in turn
209 	 * indicated in TLV format as per 802.11 spec
210 	 */
211 	WIFI_TAG_INTERFACE,	/* take interface name as parameter */
212 	WIFI_TAG_REASON_CODE,	/* take a reason code as per 802.11 as parameter */
213 	WIFI_TAG_RATE_MBPS,	/* take a wifi rate in 0.5 mbps */
214 	WIFI_TAG_REQUEST_ID,	/* take an integer as parameter */
215 	WIFI_TAG_BUCKET_ID,	/* take an integer as parameter */
216 	WIFI_TAG_GSCAN_PARAMS,	/* takes a wifi_scan_cmd_params struct as parameter */
217 	WIFI_TAG_GSCAN_CAPABILITIES, /* takes a wifi_gscan_capabilities struct as parameter */
218 	WIFI_TAG_SCAN_ID,	/* take an integer as parameter */
219 	WIFI_TAG_RSSI,		/* takes s16 as parameter */
220 	WIFI_TAG_CHANNEL,	/* takes u16 as parameter */
221 	WIFI_TAG_LINK_ID,	/* take an integer as parameter */
222 	WIFI_TAG_LINK_ROLE,	/* take an integer as parameter */
223 	WIFI_TAG_LINK_STATE,	/* take an integer as parameter */
224 	WIFI_TAG_LINK_TYPE,	/* take an integer as parameter */
225 	WIFI_TAG_TSCO,		/* take an integer as parameter */
226 	WIFI_TAG_RSCO,		/* take an integer as parameter */
227 	WIFI_TAG_EAPOL_MESSAGE_TYPE /* take an integer as parameter */
228 };
229 
230 /* NAN  events */
231 typedef enum {
232 	NAN_EVENT_INVALID = 0,
233 	NAN_EVENT_CLUSTER_STARTED = 1,
234 	NAN_EVENT_CLUSTER_JOINED = 2,
235 	NAN_EVENT_CLUSTER_MERGED = 3,
236 	NAN_EVENT_ROLE_CHANGED = 4,
237 	NAN_EVENT_SCAN_COMPLETE = 5,
238 	NAN_EVENT_STATUS_CHNG  = 6,
239 	/* ADD new events before this line */
240 	NAN_EVENT_MAX
241 } nan_event_id_t;
242 
243 typedef struct {
244     uint16 tag;
245     uint16 len; /* length of value */
246     uint8 value[0];
247 } tlv_log;
248 
249 typedef struct per_packet_status_entry {
250     uint8 flags;
251     uint8 tid; /* transmit or received tid */
252     uint16 MCS; /* modulation and bandwidth */
253 	/*
254 	* TX: RSSI of ACK for that packet
255 	* RX: RSSI of packet
256 	*/
257     uint8 rssi;
258     uint8 num_retries; /* number of attempted retries */
259     uint16 last_transmit_rate; /* last transmit rate in .5 mbps */
260 	 /* transmit/reeive sequence for that MPDU packet */
261     uint16 link_layer_transmit_sequence;
262 	/*
263 	* TX: firmware timestamp (us) when packet is queued within firmware buffer
264 	* for SDIO/HSIC or into PCIe buffer
265 	* RX : firmware receive timestamp
266 	*/
267     uint64 firmware_entry_timestamp;
268 	/*
269 	* firmware timestamp (us) when packet start contending for the
270 	* medium for the first time, at head of its AC queue,
271 	* or as part of an MPDU or A-MPDU. This timestamp is not updated
272 	* for each retry, only the first transmit attempt.
273 	*/
274     uint64 start_contention_timestamp;
275 	/*
276 	* fimrware timestamp (us) when packet is successfully transmitted
277 	* or aborted because it has exhausted its maximum number of retries
278 	*/
279 	uint64 transmit_success_timestamp;
280 	/*
281 	* packet data. The length of packet data is determined by the entry_size field of
282 	* the wifi_ring_buffer_entry structure. It is expected that first bytes of the
283 	* packet, or packet headers only (up to TCP or RTP/UDP headers) will be copied into the ring
284 	*/
285     uint8 *data;
286 } per_packet_status_entry_t;
287 
288 #define PACKED_STRUCT __attribute__ ((packed))
289 
290 typedef struct log_conn_event {
291     uint16 event;
292     tlv_log *tlvs;
293 	/*
294 	* separate parameter structure per event to be provided and optional data
295 	* the event_data is expected to include an official android part, with some
296 	* parameter as transmit rate, num retries, num scan result found etc...
297 	* as well, event_data can include a vendor proprietary part which is
298 	* understood by the developer only.
299 	*/
300 } PACKED_STRUCT log_conn_event_t;
301 
302 /*
303  * Ring buffer name for power events ring. note that power event are extremely frequents
304  * and thus should be stored in their own ring/file so as not to clobber connectivity events
305  */
306 
307 typedef struct wake_lock_event {
308     uint32 status; /* 0 taken, 1 released */
309     uint32 reason; /* reason why this wake lock is taken */
310     char *name; /* null terminated */
311 } wake_lock_event_t;
312 
313 typedef struct wifi_power_event {
314     uint16 event;
315     tlv_log *tlvs;
316 } wifi_power_event_t;
317 
318 #define NAN_EVENT_VERSION 1
319 typedef struct log_nan_event {
320     uint8 version;
321     uint8 pad;
322     uint16 event;
323     tlv_log *tlvs;
324 } log_nan_event_t;
325 
326 /* entry type */
327 enum {
328 	DBG_RING_ENTRY_EVENT_TYPE = 1,
329 	DBG_RING_ENTRY_PKT_TYPE,
330 	DBG_RING_ENTRY_WAKE_LOCK_EVENT_TYPE,
331 	DBG_RING_ENTRY_POWER_EVENT_TYPE,
332 	DBG_RING_ENTRY_DATA_TYPE,
333 	DBG_RING_ENTRY_NAN_EVENT_TYPE
334 };
335 
336 struct log_level_table {
337 	int log_level;
338 	uint16 tag;
339 	char *desc;
340 };
341 
342 /*
343  * Assuming that the Ring lock is mutex, bailing out if the
344  * callers are from atomic context. On a long term, one has to
345  * schedule a job to execute in sleepable context so that
346  * contents are pushed to the ring.
347  */
348 #define DBG_EVENT_LOG(dhdp, connect_state)					\
349 {										\
350 	do {									\
351 		uint16 state = connect_state;					\
352 		if (CAN_SLEEP() && DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID))			\
353 			dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,	\
354 				&state, sizeof(state));				\
355 	} while (0);								\
356 }
357 
358 #define MD5_PREFIX_LEN				4
359 #define MAX_FATE_LOG_LEN			32
360 #define MAX_FRAME_LEN_ETHERNET		1518
361 #define MAX_FRAME_LEN_80211_MGMT	2352 /* 802.11-2012 Fig. 8-34 */
362 
363 typedef enum {
364 	/* Sent over air and ACKed. */
365 	TX_PKT_FATE_ACKED,
366 
367 	/* Sent over air but not ACKed. (Normal for broadcast/multicast.) */
368 	TX_PKT_FATE_SENT,
369 
370 	/* Queued within firmware, but not yet sent over air. */
371 	TX_PKT_FATE_FW_QUEUED,
372 
373 	/*
374 	 * Dropped by firmware as invalid. E.g. bad source address,
375 	 * bad checksum, or invalid for current state.
376 	 */
377 	TX_PKT_FATE_FW_DROP_INVALID,
378 
379 	/* Dropped by firmware due to lifetime expiration. */
380 	TX_PKT_FATE_FW_DROP_EXPTIME,
381 
382 	/*
383 	 * Dropped by firmware for any other reason. Includes
384 	 * frames that were sent by driver to firmware, but
385 	 * unaccounted for by firmware.
386 	 */
387 	TX_PKT_FATE_FW_DROP_OTHER,
388 
389 	/* Queued within driver, not yet sent to firmware. */
390 	TX_PKT_FATE_DRV_QUEUED,
391 
392 	/*
393 	 * Dropped by driver as invalid. E.g. bad source address,
394 	 * or invalid for current state.
395 	 */
396 	TX_PKT_FATE_DRV_DROP_INVALID,
397 
398 	/* Dropped by driver due to lack of buffer space. */
399 	TX_PKT_FATE_DRV_DROP_NOBUFS,
400 
401 	/*  Dropped by driver for any other reason. */
402 	TX_PKT_FATE_DRV_DROP_OTHER,
403 
404 	/* Packet free by firmware. */
405 	TX_PKT_FATE_FW_PKT_FREE,
406 
407 	} wifi_tx_packet_fate;
408 
409 typedef enum {
410 	/* Valid and delivered to network stack (e.g., netif_rx()). */
411 	RX_PKT_FATE_SUCCESS,
412 
413 	/* Queued within firmware, but not yet sent to driver. */
414 	RX_PKT_FATE_FW_QUEUED,
415 
416 	/* Dropped by firmware due to host-programmable filters. */
417 	RX_PKT_FATE_FW_DROP_FILTER,
418 
419 	/*
420 	 * Dropped by firmware as invalid. E.g. bad checksum,
421 	 * decrypt failed, or invalid for current state.
422 	 */
423 	RX_PKT_FATE_FW_DROP_INVALID,
424 
425 	/* Dropped by firmware due to lack of buffer space. */
426 	RX_PKT_FATE_FW_DROP_NOBUFS,
427 
428 	/* Dropped by firmware for any other reason. */
429 	RX_PKT_FATE_FW_DROP_OTHER,
430 
431 	/* Queued within driver, not yet delivered to network stack. */
432 	RX_PKT_FATE_DRV_QUEUED,
433 
434 	/* Dropped by driver due to filter rules. */
435 	RX_PKT_FATE_DRV_DROP_FILTER,
436 
437 	/* Dropped by driver as invalid. E.g. not permitted in current state. */
438 	RX_PKT_FATE_DRV_DROP_INVALID,
439 
440 	/* Dropped by driver due to lack of buffer space. */
441 	RX_PKT_FATE_DRV_DROP_NOBUFS,
442 
443 	/* Dropped by driver for any other reason. */
444 	RX_PKT_FATE_DRV_DROP_OTHER,
445 
446 	} wifi_rx_packet_fate;
447 
448 typedef enum {
449 	FRAME_TYPE_UNKNOWN,
450 	FRAME_TYPE_ETHERNET_II,
451 	FRAME_TYPE_80211_MGMT,
452 	} frame_type;
453 
454 typedef struct wifi_frame_info {
455 	/*
456 	 * The type of MAC-layer frame that this frame_info holds.
457 	 * - For data frames, use FRAME_TYPE_ETHERNET_II.
458 	 * - For management frames, use FRAME_TYPE_80211_MGMT.
459 	 * - If the type of the frame is unknown, use FRAME_TYPE_UNKNOWN.
460 	 */
461 	frame_type payload_type;
462 
463 	/*
464 	 * The number of bytes included in |frame_content|. If the frame
465 	 * contents are missing (e.g. RX frame dropped in firmware),
466 	 * |frame_len| should be set to 0.
467 	 */
468 	size_t frame_len;
469 
470 	/*
471 	 * Host clock when this frame was received by the driver (either
472 	 *	outbound from the host network stack, or inbound from the
473 	 *	firmware).
474 	 *	- The timestamp should be taken from a clock which includes time
475 	 *	  the host spent suspended (e.g. ktime_get_boottime()).
476 	 *	- If no host timestamp is available (e.g. RX frame was dropped in
477 	 *	  firmware), this field should be set to 0.
478 	 */
479 	uint32 driver_timestamp_usec;
480 
481 	/*
482 	 * Firmware clock when this frame was received by the firmware
483 	 *	(either outbound from the host, or inbound from a remote
484 	 *	station).
485 	 *	- The timestamp should be taken from a clock which includes time
486 	 *	  firmware spent suspended (if applicable).
487 	 *	- If no firmware timestamp is available (e.g. TX frame was
488 	 *	  dropped by driver), this field should be set to 0.
489 	 *	- Consumers of |frame_info| should _not_ assume any
490 	 *	  synchronization between driver and firmware clocks.
491 	 */
492 	uint32 firmware_timestamp_usec;
493 
494 	/*
495 	 * Actual frame content.
496 	 * - Should be provided for TX frames originated by the host.
497 	 * - Should be provided for RX frames received by the driver.
498 	 * - Optionally provided for TX frames originated by firmware. (At
499 	 *   discretion of HAL implementation.)
500 	 * - Optionally provided for RX frames dropped in firmware. (At
501 	 *   discretion of HAL implementation.)
502 	 * - If frame content is not provided, |frame_len| should be set
503 	 *   to 0.
504 	 */
505 	union {
506 		char ethernet_ii[MAX_FRAME_LEN_ETHERNET];
507 		char ieee_80211_mgmt[MAX_FRAME_LEN_80211_MGMT];
508 	} frame_content;
509 } wifi_frame_info_t;
510 
511 typedef struct wifi_tx_report {
512 	/*
513 	 * Prefix of MD5 hash of |frame_inf.frame_content|. If frame
514 	 * content is not provided, prefix of MD5 hash over the same data
515 	 * that would be in frame_content, if frame content were provided.
516 	 */
517 	char md5_prefix[MD5_PREFIX_LEN];
518 	wifi_tx_packet_fate fate;
519 	wifi_frame_info_t frame_inf;
520 } wifi_tx_report_t;
521 
522 typedef struct wifi_rx_report {
523 	/*
524 	 * Prefix of MD5 hash of |frame_inf.frame_content|. If frame
525 	 * content is not provided, prefix of MD5 hash over the same data
526 	 * that would be in frame_content, if frame content were provided.
527 	 */
528 	char md5_prefix[MD5_PREFIX_LEN];
529 	wifi_rx_packet_fate fate;
530 	wifi_frame_info_t frame_inf;
531 } wifi_rx_report_t;
532 
533 typedef struct compat_wifi_frame_info {
534 	frame_type payload_type;
535 
536 	uint32 frame_len;
537 
538 	uint32 driver_timestamp_usec;
539 
540 	uint32 firmware_timestamp_usec;
541 
542 	union {
543 		char ethernet_ii[MAX_FRAME_LEN_ETHERNET];
544 		char ieee_80211_mgmt[MAX_FRAME_LEN_80211_MGMT];
545 	} frame_content;
546 } compat_wifi_frame_info_t;
547 
548 typedef struct compat_wifi_tx_report {
549 	char md5_prefix[MD5_PREFIX_LEN];
550 	wifi_tx_packet_fate fate;
551 	compat_wifi_frame_info_t frame_inf;
552 } compat_wifi_tx_report_t;
553 
554 typedef struct compat_wifi_rx_report {
555 	char md5_prefix[MD5_PREFIX_LEN];
556 	wifi_rx_packet_fate fate;
557 	compat_wifi_frame_info_t frame_inf;
558 } compat_wifi_rx_report_t;
559 
560 /*
561  * Packet logging - internal data
562  */
563 
564 typedef enum dhd_dbg_pkt_mon_state {
565 	PKT_MON_INVALID = 0,
566 	PKT_MON_ATTACHED,
567 	PKT_MON_STARTING,
568 	PKT_MON_STARTED,
569 	PKT_MON_STOPPING,
570 	PKT_MON_STOPPED,
571 	PKT_MON_DETACHED,
572 	} dhd_dbg_pkt_mon_state_t;
573 
574 typedef struct dhd_dbg_pkt_info {
575 	frame_type payload_type;
576 	size_t pkt_len;
577 	uint32 driver_ts;
578 	uint32 firmware_ts;
579 	uint32 pkt_hash;
580 	void *pkt;
581 } dhd_dbg_pkt_info_t;
582 
583 typedef struct compat_dhd_dbg_pkt_info {
584 	frame_type payload_type;
585 	uint32 pkt_len;
586 	uint32 driver_ts;
587 	uint32 firmware_ts;
588 	uint32 pkt_hash;
589 	void *pkt;
590 } compat_dhd_dbg_pkt_info_t;
591 
592 typedef struct dhd_dbg_tx_info
593 {
594 	wifi_tx_packet_fate fate;
595 	dhd_dbg_pkt_info_t info;
596 } dhd_dbg_tx_info_t;
597 
598 typedef struct dhd_dbg_rx_info
599 {
600 	wifi_rx_packet_fate fate;
601 	dhd_dbg_pkt_info_t info;
602 } dhd_dbg_rx_info_t;
603 
604 typedef struct dhd_dbg_tx_report
605 {
606 	dhd_dbg_tx_info_t *tx_pkts;
607 	uint16 pkt_pos;
608 	uint16 status_pos;
609 } dhd_dbg_tx_report_t;
610 
611 typedef struct dhd_dbg_rx_report
612 {
613 	dhd_dbg_rx_info_t *rx_pkts;
614 	uint16 pkt_pos;
615 } dhd_dbg_rx_report_t;
616 
617 typedef void (*dbg_pullreq_t)(void *os_priv, const int ring_id);
618 typedef void (*dbg_urgent_noti_t) (dhd_pub_t *dhdp, const void *data, const uint32 len);
619 typedef int (*dbg_mon_tx_pkts_t) (dhd_pub_t *dhdp, void *pkt, uint32 pktid);
620 typedef int (*dbg_mon_tx_status_t) (dhd_pub_t *dhdp, void *pkt,
621 	uint32 pktid, uint16 status);
622 typedef int (*dbg_mon_rx_pkts_t) (dhd_pub_t *dhdp, void *pkt);
623 
624 typedef struct dhd_dbg_pkt_mon
625 {
626 	dhd_dbg_tx_report_t *tx_report;
627 	dhd_dbg_rx_report_t *rx_report;
628 	dhd_dbg_pkt_mon_state_t tx_pkt_state;
629 	dhd_dbg_pkt_mon_state_t tx_status_state;
630 	dhd_dbg_pkt_mon_state_t rx_pkt_state;
631 
632 	/* call backs */
633 	dbg_mon_tx_pkts_t tx_pkt_mon;
634 	dbg_mon_tx_status_t tx_status_mon;
635 	dbg_mon_rx_pkts_t rx_pkt_mon;
636 } dhd_dbg_pkt_mon_t;
637 
638 typedef struct dhd_dbg {
639 	dhd_dbg_ring_t dbg_rings[DEBUG_RING_ID_MAX];
640 	void *private;          /* os private_data */
641 	dhd_dbg_pkt_mon_t pkt_mon;
642 	void *pkt_mon_lock; /* spin lock for packet monitoring */
643 	dbg_pullreq_t pullreq;
644 	dbg_urgent_noti_t urgent_notifier;
645 } dhd_dbg_t;
646 
647 #define PKT_MON_ATTACHED(state) \
648 		(((state) > PKT_MON_INVALID) && ((state) < PKT_MON_DETACHED))
649 #define PKT_MON_DETACHED(state) \
650 		(((state) == PKT_MON_INVALID) || ((state) == PKT_MON_DETACHED))
651 #define PKT_MON_STARTED(state) ((state) == PKT_MON_STARTED)
652 #define PKT_MON_STOPPED(state) ((state) == PKT_MON_STOPPED)
653 #define PKT_MON_NOT_OPERATIONAL(state) \
654 	(((state) != PKT_MON_STARTED) && ((state) != PKT_MON_STOPPED))
655 #define PKT_MON_SAFE_TO_FREE(state) \
656 	(((state) == PKT_MON_STARTING) || ((state) == PKT_MON_STOPPED))
657 #define PKT_MON_PKT_FULL(pkt_count) ((pkt_count) >= MAX_FATE_LOG_LEN)
658 #define PKT_MON_STATUS_FULL(pkt_count, status_count) \
659 		(((status_count) >= (pkt_count)) || ((status_count) >= MAX_FATE_LOG_LEN))
660 
661 #ifdef DBG_PKT_MON
662 #define DHD_DBG_PKT_MON_TX(dhdp, pkt, pktid) \
663 	do { \
664 		if ((dhdp) && (dhdp)->dbg && (dhdp)->dbg->pkt_mon.tx_pkt_mon && (pkt)) { \
665 			(dhdp)->dbg->pkt_mon.tx_pkt_mon((dhdp), (pkt), (pktid)); \
666 		} \
667 	} while (0);
668 #define DHD_DBG_PKT_MON_TX_STATUS(dhdp, pkt, pktid, status) \
669 	do { \
670 		if ((dhdp) && (dhdp)->dbg && (dhdp)->dbg->pkt_mon.tx_status_mon && (pkt)) { \
671 			(dhdp)->dbg->pkt_mon.tx_status_mon((dhdp), (pkt), (pktid), (status)); \
672 		} \
673 	} while (0);
674 #define DHD_DBG_PKT_MON_RX(dhdp, pkt) \
675 	do { \
676 		if ((dhdp) && (dhdp)->dbg && (dhdp)->dbg->pkt_mon.rx_pkt_mon && (pkt)) { \
677 			if (ntoh16((pkt)->protocol) != ETHER_TYPE_BRCM) { \
678 				(dhdp)->dbg->pkt_mon.rx_pkt_mon((dhdp), (pkt)); \
679 			} \
680 		} \
681 	} while (0);
682 
683 #define DHD_DBG_PKT_MON_START(dhdp) \
684 		dhd_os_dbg_start_pkt_monitor((dhdp));
685 #define DHD_DBG_PKT_MON_STOP(dhdp) \
686 		dhd_os_dbg_stop_pkt_monitor((dhdp));
687 #else
688 #define DHD_DBG_PKT_MON_TX(dhdp, pkt, pktid)
689 #define DHD_DBG_PKT_MON_TX_STATUS(dhdp, pkt, pktid, status)
690 #define DHD_DBG_PKT_MON_RX(dhdp, pkt)
691 #define DHD_DBG_PKT_MON_START(dhdp)
692 #define DHD_DBG_PKT_MON_STOP(dhdp)
693 #endif /* DBG_PKT_MON */
694 
695 #ifdef DUMP_IOCTL_IOV_LIST
696 typedef struct dhd_iov_li {
697 	dll_t list;
698 	uint32 cmd; /* command number */
699 	char buff[100]; /* command name */
700 } dhd_iov_li_t;
701 #endif /* DUMP_IOCTL_IOV_LIST */
702 
703 #define IOV_LIST_MAX_LEN 5
704 
705 #ifdef DHD_DEBUG
706 typedef struct {
707 	dll_t list;
708 	uint32 id; /* wasted chunk id */
709 	uint32 handle; /* wasted chunk handle */
710 	uint32 size; /* wasted chunk size */
711 } dhd_dbg_mwli_t;
712 #endif /* DHD_DEBUG */
713 
714 #define DHD_OW_BI_RAW_EVENT_LOG_FMT 0xFFFF
715 
716 /* LSB 2 bits of format number to identify the type of event log */
717 #define DHD_EVENT_LOG_HDR_MASK 0x3
718 
719 #define DHD_EVENT_LOG_FMT_NUM_OFFSET 2
720 #define DHD_EVENT_LOG_FMT_NUM_MASK 0x3FFF
721 /**
722  * OW:- one word
723  * TW:- two word
724  * NB:- non binary
725  * BI:- binary
726  */
727 #define	DHD_OW_NB_EVENT_LOG_HDR 0
728 #define DHD_TW_NB_EVENT_LOG_HDR 1
729 #define DHD_BI_EVENT_LOG_HDR 3
730 #define DHD_INVALID_EVENT_LOG_HDR 2
731 
732 #define DHD_TW_VALID_TAG_BITS_MASK 0xF
733 #define DHD_OW_BI_EVENT_FMT_NUM 0x3FFF
734 #define DHD_TW_BI_EVENT_FMT_NUM 0x3FFE
735 
736 #define DHD_TW_EVENT_LOG_TAG_OFFSET 8
737 
738 #define EVENT_TAG_TIMESTAMP_OFFSET 1
739 #define EVENT_TAG_TIMESTAMP_EXT_OFFSET 2
740 
741 typedef struct prcd_event_log_hdr {
742 	uint32 tag;		/* Event_log entry tag */
743 	uint32 count;		/* Count of 4-byte entries */
744 	uint32 fmt_num_raw;	/* Format number */
745 	uint32 fmt_num;		/* Format number >> 2 */
746 	uint32 armcycle;	/* global ARM CYCLE for TAG */
747 	uint32 *log_ptr;	/* start of payload */
748 	uint32	payload_len;
749 	/* Extended event log header info
750 	 * 0 - legacy, 1 - extended event log header present
751 	 */
752 	bool ext_event_log_hdr;
753 	bool binary_payload;	/* 0 - non binary payload, 1 - binary payload */
754 } prcd_event_log_hdr_t;		/* Processed event log header */
755 
756 /* dhd_dbg functions */
757 extern void dhd_dbg_trace_evnt_handler(dhd_pub_t *dhdp, void *event_data,
758 		void *raw_event_ptr, uint datalen);
759 void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data,
760 	void *raw_event_ptr, uint datalen, bool msgtrace_hdr_present,
761 	uint32 msgtrace_seqnum);
762 
763 extern int dhd_dbg_attach(dhd_pub_t *dhdp, dbg_pullreq_t os_pullreq,
764 	dbg_urgent_noti_t os_urgent_notifier, void *os_priv);
765 extern void dhd_dbg_detach(dhd_pub_t *dhdp);
766 extern int dhd_dbg_start(dhd_pub_t *dhdp, bool start);
767 extern int dhd_dbg_set_configuration(dhd_pub_t *dhdp, int ring_id,
768 		int log_level, int flags, uint32 threshold);
769 extern int dhd_dbg_find_ring_id(dhd_pub_t *dhdp, char *ring_name);
770 extern dhd_dbg_ring_t *dhd_dbg_get_ring_from_ring_id(dhd_pub_t *dhdp, int ring_id);
771 extern void *dhd_dbg_get_priv(dhd_pub_t *dhdp);
772 extern int dhd_dbg_send_urgent_evt(dhd_pub_t *dhdp, const void *data, const uint32 len);
773 extern void dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, prcd_event_log_hdr_t *plog_hdr,
774 	void *raw_event_ptr, uint32 *log_ptr, uint32 logset, uint16 block);
775 int dhd_dbg_pull_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len);
776 int dhd_dbg_pull_single_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len,
777 	bool strip_header);
778 int dhd_dbg_push_to_ring(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr,
779 		void *data);
780 int __dhd_dbg_get_ring_status(dhd_dbg_ring_t *ring, dhd_dbg_ring_status_t *ring_status);
781 int dhd_dbg_get_ring_status(dhd_pub_t *dhdp, int ring_id,
782 		dhd_dbg_ring_status_t *dbg_ring_status);
783 #ifdef SHOW_LOGTRACE
784 void dhd_dbg_read_ring_into_trace_buf(dhd_dbg_ring_t *ring, trace_buf_info_t *trace_buf_info);
785 #endif /* SHOW_LOGTRACE */
786 
787 #ifdef DBG_PKT_MON
788 extern int dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp,
789 		dbg_mon_tx_pkts_t tx_pkt_mon,
790 		dbg_mon_tx_status_t tx_status_mon,
791 		dbg_mon_rx_pkts_t rx_pkt_mon);
792 extern int dhd_dbg_start_pkt_monitor(dhd_pub_t *dhdp);
793 extern int dhd_dbg_monitor_tx_pkts(dhd_pub_t *dhdp, void *pkt, uint32 pktid);
794 extern int dhd_dbg_monitor_tx_status(dhd_pub_t *dhdp, void *pkt,
795 		uint32 pktid, uint16 status);
796 extern int dhd_dbg_monitor_rx_pkts(dhd_pub_t *dhdp, void *pkt);
797 extern int dhd_dbg_stop_pkt_monitor(dhd_pub_t *dhdp);
798 extern int dhd_dbg_monitor_get_tx_pkts(dhd_pub_t *dhdp, void __user *user_buf,
799 		uint16 req_count, uint16 *resp_count);
800 extern int dhd_dbg_monitor_get_rx_pkts(dhd_pub_t *dhdp, void __user *user_buf,
801 		uint16 req_count, uint16 *resp_count);
802 extern int dhd_dbg_detach_pkt_monitor(dhd_pub_t *dhdp);
803 #endif /* DBG_PKT_MON */
804 
805 extern bool dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt,
806 		uint32 pktid, uint16 status);
807 
808 /* os wrapper function */
809 extern int dhd_os_dbg_attach(dhd_pub_t *dhdp);
810 extern void dhd_os_dbg_detach(dhd_pub_t *dhdp);
811 extern int dhd_os_dbg_register_callback(int ring_id,
812 	void (*dbg_ring_sub_cb)(void *ctx, const int ring_id, const void *data,
813 		const uint32 len, const dhd_dbg_ring_status_t dbg_ring_status));
814 extern int dhd_os_dbg_register_urgent_notifier(dhd_pub_t *dhdp,
815 	void (*urgent_noti)(void *ctx, const void *data, const uint32 len, const uint32 fw_len));
816 
817 extern int dhd_os_start_logging(dhd_pub_t *dhdp, char *ring_name, int log_level,
818 		int flags, int time_intval, int threshold);
819 extern int dhd_os_reset_logging(dhd_pub_t *dhdp);
820 extern int dhd_os_suppress_logging(dhd_pub_t *dhdp, bool suppress);
821 
822 extern int dhd_os_get_ring_status(dhd_pub_t *dhdp, int ring_id,
823 		dhd_dbg_ring_status_t *dbg_ring_status);
824 extern int dhd_os_trigger_get_ring_data(dhd_pub_t *dhdp, char *ring_name);
825 extern int dhd_os_push_push_ring_data(dhd_pub_t *dhdp, int ring_id, void *data, int32 data_len);
826 extern int dhd_os_dbg_get_feature(dhd_pub_t *dhdp, int32 *features);
827 
828 #ifdef DBG_PKT_MON
829 extern int dhd_os_dbg_attach_pkt_monitor(dhd_pub_t *dhdp);
830 extern int dhd_os_dbg_start_pkt_monitor(dhd_pub_t *dhdp);
831 extern int dhd_os_dbg_monitor_tx_pkts(dhd_pub_t *dhdp, void *pkt,
832 	uint32 pktid);
833 extern int dhd_os_dbg_monitor_tx_status(dhd_pub_t *dhdp, void *pkt,
834 	uint32 pktid, uint16 status);
835 extern int dhd_os_dbg_monitor_rx_pkts(dhd_pub_t *dhdp, void *pkt);
836 extern int dhd_os_dbg_stop_pkt_monitor(dhd_pub_t *dhdp);
837 extern int dhd_os_dbg_monitor_get_tx_pkts(dhd_pub_t *dhdp,
838 	void __user *user_buf, uint16 req_count, uint16 *resp_count);
839 extern int dhd_os_dbg_monitor_get_rx_pkts(dhd_pub_t *dhdp,
840 	void __user *user_buf, uint16 req_count, uint16 *resp_count);
841 extern int dhd_os_dbg_detach_pkt_monitor(dhd_pub_t *dhdp);
842 #endif /* DBG_PKT_MON */
843 
844 #ifdef DUMP_IOCTL_IOV_LIST
845 extern void dhd_iov_li_append(dhd_pub_t *dhd, dll_t *list_head, dll_t *node);
846 extern void dhd_iov_li_print(dll_t *list_head);
847 extern void dhd_iov_li_delete(dhd_pub_t *dhd, dll_t *list_head);
848 #endif /* DUMP_IOCTL_IOV_LIST */
849 
850 #ifdef DHD_DEBUG
851 extern void dhd_mw_list_delete(dhd_pub_t *dhd, dll_t *list_head);
852 #endif /* DHD_DEBUG */
853 #endif /* _dhd_debug_h_ */
854