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