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