1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * DHD debugability support
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2020, Broadcom.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Unless you and Broadcom execute a separate written software license
7*4882a593Smuzhiyun * agreement governing use of this software, this software is licensed to you
8*4882a593Smuzhiyun * under the terms of the GNU General Public License version 2 (the "GPL"),
9*4882a593Smuzhiyun * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10*4882a593Smuzhiyun * following added to such license:
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * As a special exception, the copyright holders of this software give you
13*4882a593Smuzhiyun * permission to link this software with independent modules, and to copy and
14*4882a593Smuzhiyun * distribute the resulting executable under terms of your choice, provided that
15*4882a593Smuzhiyun * you also meet, for each linked independent module, the terms and conditions of
16*4882a593Smuzhiyun * the license of that module. An independent module is a module which is not
17*4882a593Smuzhiyun * derived from this software. The special exception does not apply to any
18*4882a593Smuzhiyun * modifications of the software.
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun * <<Broadcom-WL-IPTag/Open:>>
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * $Id$
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include <typedefs.h>
27*4882a593Smuzhiyun #include <osl.h>
28*4882a593Smuzhiyun #include <bcmutils.h>
29*4882a593Smuzhiyun #include <bcmendian.h>
30*4882a593Smuzhiyun #include <dngl_stats.h>
31*4882a593Smuzhiyun #include <dhd.h>
32*4882a593Smuzhiyun #include <dhd_dbg.h>
33*4882a593Smuzhiyun #include <dhd_dbg_ring.h>
34*4882a593Smuzhiyun #include <dhd_debug.h>
35*4882a593Smuzhiyun #include <dhd_mschdbg.h>
36*4882a593Smuzhiyun #include <dhd_bus.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #include <event_log.h>
39*4882a593Smuzhiyun #include <event_trace.h>
40*4882a593Smuzhiyun #include <msgtrace.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #if defined(DHD_EVENT_LOG_FILTER)
43*4882a593Smuzhiyun #include <dhd_event_log_filter.h>
44*4882a593Smuzhiyun #endif /* DHD_EVENT_LOG_FILTER */
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #if defined(DHD_EFI) || defined(NDIS)
47*4882a593Smuzhiyun #if !defined(offsetof)
48*4882a593Smuzhiyun #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
49*4882a593Smuzhiyun #endif /* !defined(offsetof) */
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define container_of(ptr, type, member) \
52*4882a593Smuzhiyun (type *)((char *)(ptr) - offsetof(type, member))
53*4882a593Smuzhiyun #endif /* defined(DHD_EFI ) || defined(NDIS) */
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
56*4882a593Smuzhiyun uint8 control_logtrace = LOGTRACE_RAW_FMT;
57*4882a593Smuzhiyun #else
58*4882a593Smuzhiyun uint8 control_logtrace = CUSTOM_CONTROL_LOGTRACE;
59*4882a593Smuzhiyun #endif
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun struct map_table {
62*4882a593Smuzhiyun uint16 fw_id;
63*4882a593Smuzhiyun uint16 host_id;
64*4882a593Smuzhiyun char *desc;
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun struct map_table event_map[] = {
68*4882a593Smuzhiyun {WLC_E_AUTH, WIFI_EVENT_AUTH_COMPLETE, "AUTH_COMPLETE"},
69*4882a593Smuzhiyun {WLC_E_ASSOC, WIFI_EVENT_ASSOC_COMPLETE, "ASSOC_COMPLETE"},
70*4882a593Smuzhiyun {TRACE_FW_AUTH_STARTED, WIFI_EVENT_FW_AUTH_STARTED, "AUTH STARTED"},
71*4882a593Smuzhiyun {TRACE_FW_ASSOC_STARTED, WIFI_EVENT_FW_ASSOC_STARTED, "ASSOC STARTED"},
72*4882a593Smuzhiyun {TRACE_FW_RE_ASSOC_STARTED, WIFI_EVENT_FW_RE_ASSOC_STARTED, "REASSOC STARTED"},
73*4882a593Smuzhiyun {TRACE_G_SCAN_STARTED, WIFI_EVENT_G_SCAN_STARTED, "GSCAN STARTED"},
74*4882a593Smuzhiyun {WLC_E_PFN_SCAN_COMPLETE, WIFI_EVENT_G_SCAN_COMPLETE, "GSCAN COMPLETE"},
75*4882a593Smuzhiyun {WLC_E_DISASSOC, WIFI_EVENT_DISASSOCIATION_REQUESTED, "DIASSOC REQUESTED"},
76*4882a593Smuzhiyun {WLC_E_REASSOC, WIFI_EVENT_RE_ASSOCIATION_REQUESTED, "REASSOC REQUESTED"},
77*4882a593Smuzhiyun {TRACE_ROAM_SCAN_STARTED, WIFI_EVENT_ROAM_REQUESTED, "ROAM REQUESTED"},
78*4882a593Smuzhiyun {WLC_E_BEACON_FRAME_RX, WIFI_EVENT_BEACON_RECEIVED, "BEACON Received"},
79*4882a593Smuzhiyun {TRACE_ROAM_SCAN_STARTED, WIFI_EVENT_ROAM_SCAN_STARTED, "ROAM SCAN STARTED"},
80*4882a593Smuzhiyun {TRACE_ROAM_SCAN_COMPLETE, WIFI_EVENT_ROAM_SCAN_COMPLETE, "ROAM SCAN COMPLETED"},
81*4882a593Smuzhiyun {TRACE_ROAM_AUTH_STARTED, WIFI_EVENT_ROAM_AUTH_STARTED, "ROAM AUTH STARTED"},
82*4882a593Smuzhiyun {WLC_E_AUTH, WIFI_EVENT_ROAM_AUTH_COMPLETE, "ROAM AUTH COMPLETED"},
83*4882a593Smuzhiyun {TRACE_FW_RE_ASSOC_STARTED, WIFI_EVENT_ROAM_ASSOC_STARTED, "ROAM ASSOC STARTED"},
84*4882a593Smuzhiyun {WLC_E_ASSOC, WIFI_EVENT_ROAM_ASSOC_COMPLETE, "ROAM ASSOC COMPLETED"},
85*4882a593Smuzhiyun {TRACE_ROAM_SCAN_COMPLETE, WIFI_EVENT_ROAM_SCAN_COMPLETE, "ROAM SCAN COMPLETED"},
86*4882a593Smuzhiyun {TRACE_BT_COEX_BT_SCO_START, WIFI_EVENT_BT_COEX_BT_SCO_START, "BT SCO START"},
87*4882a593Smuzhiyun {TRACE_BT_COEX_BT_SCO_STOP, WIFI_EVENT_BT_COEX_BT_SCO_STOP, "BT SCO STOP"},
88*4882a593Smuzhiyun {TRACE_BT_COEX_BT_SCAN_START, WIFI_EVENT_BT_COEX_BT_SCAN_START, "BT COEX SCAN START"},
89*4882a593Smuzhiyun {TRACE_BT_COEX_BT_SCAN_STOP, WIFI_EVENT_BT_COEX_BT_SCAN_STOP, "BT COEX SCAN STOP"},
90*4882a593Smuzhiyun {TRACE_BT_COEX_BT_HID_START, WIFI_EVENT_BT_COEX_BT_HID_START, "BT HID START"},
91*4882a593Smuzhiyun {TRACE_BT_COEX_BT_HID_STOP, WIFI_EVENT_BT_COEX_BT_HID_STOP, "BT HID STOP"},
92*4882a593Smuzhiyun {WLC_E_EAPOL_MSG, WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED, "FW EAPOL PKT RECEIVED"},
93*4882a593Smuzhiyun {TRACE_FW_EAPOL_FRAME_TRANSMIT_START, WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START,
94*4882a593Smuzhiyun "FW EAPOL PKT TRANSMITED"},
95*4882a593Smuzhiyun {TRACE_FW_EAPOL_FRAME_TRANSMIT_STOP, WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP,
96*4882a593Smuzhiyun "FW EAPOL PKT TX STOPPED"},
97*4882a593Smuzhiyun {TRACE_BLOCK_ACK_NEGOTIATION_COMPLETE, WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE,
98*4882a593Smuzhiyun "BLOCK ACK NEGO COMPLETED"},
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun struct map_table event_tag_map[] = {
102*4882a593Smuzhiyun {TRACE_TAG_VENDOR_SPECIFIC, WIFI_TAG_VENDOR_SPECIFIC, "VENDOR SPECIFIC DATA"},
103*4882a593Smuzhiyun {TRACE_TAG_BSSID, WIFI_TAG_BSSID, "BSSID"},
104*4882a593Smuzhiyun {TRACE_TAG_ADDR, WIFI_TAG_ADDR, "ADDR_0"},
105*4882a593Smuzhiyun {TRACE_TAG_SSID, WIFI_TAG_SSID, "SSID"},
106*4882a593Smuzhiyun {TRACE_TAG_STATUS, WIFI_TAG_STATUS, "STATUS"},
107*4882a593Smuzhiyun {TRACE_TAG_CHANNEL_SPEC, WIFI_TAG_CHANNEL_SPEC, "CHANSPEC"},
108*4882a593Smuzhiyun {TRACE_TAG_WAKE_LOCK_EVENT, WIFI_TAG_WAKE_LOCK_EVENT, "WAKELOCK EVENT"},
109*4882a593Smuzhiyun {TRACE_TAG_ADDR1, WIFI_TAG_ADDR1, "ADDR_1"},
110*4882a593Smuzhiyun {TRACE_TAG_ADDR2, WIFI_TAG_ADDR2, "ADDR_2"},
111*4882a593Smuzhiyun {TRACE_TAG_ADDR3, WIFI_TAG_ADDR3, "ADDR_3"},
112*4882a593Smuzhiyun {TRACE_TAG_ADDR4, WIFI_TAG_ADDR4, "ADDR_4"},
113*4882a593Smuzhiyun {TRACE_TAG_TSF, WIFI_TAG_TSF, "TSF"},
114*4882a593Smuzhiyun {TRACE_TAG_IE, WIFI_TAG_IE, "802.11 IE"},
115*4882a593Smuzhiyun {TRACE_TAG_INTERFACE, WIFI_TAG_INTERFACE, "INTERFACE"},
116*4882a593Smuzhiyun {TRACE_TAG_REASON_CODE, WIFI_TAG_REASON_CODE, "REASON CODE"},
117*4882a593Smuzhiyun {TRACE_TAG_RATE_MBPS, WIFI_TAG_RATE_MBPS, "RATE"},
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* define log level per ring type */
121*4882a593Smuzhiyun struct log_level_table fw_verbose_level_map[] = {
122*4882a593Smuzhiyun {1, EVENT_LOG_TAG_PCI_ERROR, "PCI_ERROR"},
123*4882a593Smuzhiyun #ifndef DISABLE_PCI_LOGGING
124*4882a593Smuzhiyun {1, EVENT_LOG_TAG_PCI_WARN, "PCI_WARN"},
125*4882a593Smuzhiyun {2, EVENT_LOG_TAG_PCI_INFO, "PCI_INFO"},
126*4882a593Smuzhiyun {3, EVENT_LOG_TAG_PCI_DBG, "PCI_DEBUG"},
127*4882a593Smuzhiyun #endif
128*4882a593Smuzhiyun #ifndef DISABLE_BEACON_LOGGING
129*4882a593Smuzhiyun {3, EVENT_LOG_TAG_BEACON_LOG, "BEACON_LOG"},
130*4882a593Smuzhiyun #endif
131*4882a593Smuzhiyun {2, EVENT_LOG_TAG_WL_ASSOC_LOG, "ASSOC_LOG"},
132*4882a593Smuzhiyun {2, EVENT_LOG_TAG_WL_ROAM_LOG, "ROAM_LOG"},
133*4882a593Smuzhiyun {1, EVENT_LOG_TAG_TRACE_WL_INFO, "WL INFO"},
134*4882a593Smuzhiyun {1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, "BTCOEX INFO"},
135*4882a593Smuzhiyun #ifdef DHD_RANDMAC_LOGGING
136*4882a593Smuzhiyun {1, EVENT_LOG_TAG_RANDMAC_ERR, "RANDMAC_ERR"},
137*4882a593Smuzhiyun #endif /* DHD_RANDMAC_LOGGING */
138*4882a593Smuzhiyun #ifdef CUSTOMER_HW4_DEBUG
139*4882a593Smuzhiyun {3, EVENT_LOG_TAG_SCAN_WARN, "SCAN_WARN"},
140*4882a593Smuzhiyun #else
141*4882a593Smuzhiyun {1, EVENT_LOG_TAG_SCAN_WARN, "SCAN_WARN"},
142*4882a593Smuzhiyun #endif /* CUSTOMER_HW4_DEBUG */
143*4882a593Smuzhiyun {1, EVENT_LOG_TAG_SCAN_ERROR, "SCAN_ERROR"},
144*4882a593Smuzhiyun {2, EVENT_LOG_TAG_SCAN_TRACE_LOW, "SCAN_TRACE_LOW"},
145*4882a593Smuzhiyun {2, EVENT_LOG_TAG_SCAN_TRACE_HIGH, "SCAN_TRACE_HIGH"},
146*4882a593Smuzhiyun #ifdef DHD_WL_ERROR_LOGGING
147*4882a593Smuzhiyun {3, EVENT_LOG_TAG_WL_ERROR, "WL_ERROR"},
148*4882a593Smuzhiyun #endif
149*4882a593Smuzhiyun #ifdef DHD_IE_ERROR_LOGGING
150*4882a593Smuzhiyun {3, EVENT_LOG_TAG_IE_ERROR, "IE_ERROR"},
151*4882a593Smuzhiyun #endif
152*4882a593Smuzhiyun #ifdef DHD_ASSOC_ERROR_LOGGING
153*4882a593Smuzhiyun {3, EVENT_LOG_TAG_ASSOC_ERROR, "ASSOC_ERROR"},
154*4882a593Smuzhiyun #endif
155*4882a593Smuzhiyun #ifdef DHD_PMU_ERROR_LOGGING
156*4882a593Smuzhiyun {3, EVENT_LOG_TAG_PMU_ERROR, "PMU_ERROR"},
157*4882a593Smuzhiyun #endif
158*4882a593Smuzhiyun #ifdef DHD_8021X_ERROR_LOGGING
159*4882a593Smuzhiyun {3, EVENT_LOG_TAG_4WAYHANDSHAKE, "8021X_ERROR"},
160*4882a593Smuzhiyun #endif
161*4882a593Smuzhiyun #ifdef DHD_AMPDU_ERROR_LOGGING
162*4882a593Smuzhiyun {3, EVENT_LOG_TAG_AMSDU_ERROR, "AMPDU_ERROR"},
163*4882a593Smuzhiyun #endif
164*4882a593Smuzhiyun #ifdef DHD_SAE_ERROR_LOGGING
165*4882a593Smuzhiyun {3, EVENT_LOG_TAG_SAE_ERROR, "SAE_ERROR"},
166*4882a593Smuzhiyun #endif
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* reference tab table */
170*4882a593Smuzhiyun uint ref_tag_tbl[EVENT_LOG_TAG_MAX + 1] = {0};
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun typedef struct dhddbg_loglist_item {
173*4882a593Smuzhiyun dll_t list;
174*4882a593Smuzhiyun prcd_event_log_hdr_t prcd_log_hdr;
175*4882a593Smuzhiyun } loglist_item_t;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun typedef struct dhbdbg_pending_item {
178*4882a593Smuzhiyun dll_t list;
179*4882a593Smuzhiyun dhd_dbg_ring_status_t ring_status;
180*4882a593Smuzhiyun dhd_dbg_ring_entry_t *ring_entry;
181*4882a593Smuzhiyun } pending_item_t;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun /* trace log entry header user space processing */
184*4882a593Smuzhiyun struct tracelog_header {
185*4882a593Smuzhiyun int magic_num;
186*4882a593Smuzhiyun int buf_size;
187*4882a593Smuzhiyun int seq_num;
188*4882a593Smuzhiyun };
189*4882a593Smuzhiyun #define TRACE_LOG_MAGIC_NUMBER 0xEAE47C06
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun int
dhd_dbg_push_to_ring(dhd_pub_t * dhdp,int ring_id,dhd_dbg_ring_entry_t * hdr,void * data)192*4882a593Smuzhiyun dhd_dbg_push_to_ring(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, void *data)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun dhd_dbg_ring_t *ring;
195*4882a593Smuzhiyun int ret = 0;
196*4882a593Smuzhiyun uint32 pending_len = 0;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
199*4882a593Smuzhiyun return BCME_BADADDR;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun if (!VALID_RING(ring_id)) {
203*4882a593Smuzhiyun DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
204*4882a593Smuzhiyun return BCME_RANGE;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun ring = &dhdp->dbg->dbg_rings[ring_id];
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun ret = dhd_dbg_ring_push(ring, hdr, data);
210*4882a593Smuzhiyun if (ret != BCME_OK)
211*4882a593Smuzhiyun return ret;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun pending_len = dhd_dbg_ring_get_pending_len(ring);
214*4882a593Smuzhiyun dhd_dbg_ring_sched_pull(ring, pending_len, dhdp->dbg->pullreq,
215*4882a593Smuzhiyun dhdp->dbg->private, ring->id);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun return ret;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun dhd_dbg_ring_t *
dhd_dbg_get_ring_from_ring_id(dhd_pub_t * dhdp,int ring_id)221*4882a593Smuzhiyun dhd_dbg_get_ring_from_ring_id(dhd_pub_t *dhdp, int ring_id)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
224*4882a593Smuzhiyun return NULL;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (!VALID_RING(ring_id)) {
228*4882a593Smuzhiyun DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
229*4882a593Smuzhiyun return NULL;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun return &dhdp->dbg->dbg_rings[ring_id];
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun int
dhd_dbg_pull_single_from_ring(dhd_pub_t * dhdp,int ring_id,void * data,uint32 buf_len,bool strip_header)236*4882a593Smuzhiyun dhd_dbg_pull_single_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len,
237*4882a593Smuzhiyun bool strip_header)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun dhd_dbg_ring_t *ring;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
242*4882a593Smuzhiyun return 0;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (!VALID_RING(ring_id)) {
246*4882a593Smuzhiyun DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
247*4882a593Smuzhiyun return BCME_RANGE;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun ring = &dhdp->dbg->dbg_rings[ring_id];
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun return dhd_dbg_ring_pull_single(ring, data, buf_len, strip_header);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun int
dhd_dbg_pull_from_ring(dhd_pub_t * dhdp,int ring_id,void * data,uint32 buf_len)256*4882a593Smuzhiyun dhd_dbg_pull_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun dhd_dbg_ring_t *ring;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg)
261*4882a593Smuzhiyun return 0;
262*4882a593Smuzhiyun if (!VALID_RING(ring_id)) {
263*4882a593Smuzhiyun DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
264*4882a593Smuzhiyun return BCME_RANGE;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun ring = &dhdp->dbg->dbg_rings[ring_id];
267*4882a593Smuzhiyun return dhd_dbg_ring_pull(ring, data, buf_len, FALSE);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun static int
dhd_dbg_msgtrace_seqchk(uint32 * prev,uint32 cur)271*4882a593Smuzhiyun dhd_dbg_msgtrace_seqchk(uint32 *prev, uint32 cur)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun /* normal case including wrap around */
274*4882a593Smuzhiyun if ((cur == 0 && *prev == 0xFFFFFFFF) || ((cur - *prev) == 1)) {
275*4882a593Smuzhiyun goto done;
276*4882a593Smuzhiyun } else if (cur == *prev) {
277*4882a593Smuzhiyun DHD_EVENT(("%s duplicate trace\n", __FUNCTION__));
278*4882a593Smuzhiyun return -1;
279*4882a593Smuzhiyun } else if (cur > *prev) {
280*4882a593Smuzhiyun DHD_EVENT(("%s lost %d packets\n", __FUNCTION__, cur - *prev));
281*4882a593Smuzhiyun } else {
282*4882a593Smuzhiyun DHD_EVENT(("%s seq out of order, dhd %d, dongle %d\n",
283*4882a593Smuzhiyun __FUNCTION__, *prev, cur));
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun done:
286*4882a593Smuzhiyun *prev = cur;
287*4882a593Smuzhiyun return 0;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun static void
dhd_dbg_msgtrace_msg_parser(void * event_data)291*4882a593Smuzhiyun dhd_dbg_msgtrace_msg_parser(void *event_data)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun msgtrace_hdr_t *hdr;
294*4882a593Smuzhiyun char *data, *s;
295*4882a593Smuzhiyun static uint32 seqnum_prev = 0;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun if (!event_data) {
298*4882a593Smuzhiyun DHD_ERROR(("%s: event_data is NULL\n", __FUNCTION__));
299*4882a593Smuzhiyun return;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun hdr = (msgtrace_hdr_t *)event_data;
303*4882a593Smuzhiyun data = (char *)event_data + MSGTRACE_HDRLEN;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun /* There are 2 bytes available at the end of data */
306*4882a593Smuzhiyun data[ntoh16(hdr->len)] = '\0';
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun if (ntoh32(hdr->discarded_bytes) || ntoh32(hdr->discarded_printf)) {
309*4882a593Smuzhiyun DHD_DBGIF(("WLC_E_TRACE: [Discarded traces in dongle -->"
310*4882a593Smuzhiyun "discarded_bytes %d discarded_printf %d]\n",
311*4882a593Smuzhiyun ntoh32(hdr->discarded_bytes),
312*4882a593Smuzhiyun ntoh32(hdr->discarded_printf)));
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun if (dhd_dbg_msgtrace_seqchk(&seqnum_prev, ntoh32(hdr->seqnum)))
316*4882a593Smuzhiyun return;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun /* Display the trace buffer. Advance from
319*4882a593Smuzhiyun * \n to \n to avoid display big
320*4882a593Smuzhiyun * printf (issue with Linux printk )
321*4882a593Smuzhiyun */
322*4882a593Smuzhiyun while (*data != '\0' && (s = strstr(data, "\n")) != NULL) {
323*4882a593Smuzhiyun *s = '\0';
324*4882a593Smuzhiyun DHD_FWLOG(("[FWLOG] %s\n", data));
325*4882a593Smuzhiyun data = s+1;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun if (*data)
328*4882a593Smuzhiyun DHD_FWLOG(("[FWLOG] %s", data));
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun #ifdef SHOW_LOGTRACE
331*4882a593Smuzhiyun #define DATA_UNIT_FOR_LOG_CNT 4
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
334*4882a593Smuzhiyun #pragma GCC diagnostic pop
335*4882a593Smuzhiyun #endif
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun int
replace_percent_p_to_x(char * fmt)338*4882a593Smuzhiyun replace_percent_p_to_x(char *fmt)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun int p_to_x_done = FALSE;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun while (*fmt != '\0')
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun /* Skip characters will we see a % */
345*4882a593Smuzhiyun if (*fmt++ != '%')
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun continue;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /*
351*4882a593Smuzhiyun * Skip any flags, field width and precision:
352*4882a593Smuzhiyun *Flags: Followed by %
353*4882a593Smuzhiyun * #, 0, -, ' ', +
354*4882a593Smuzhiyun */
355*4882a593Smuzhiyun if (*fmt == '#')
356*4882a593Smuzhiyun fmt++;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun if (*fmt == '0' || *fmt == '-' || *fmt == '+')
359*4882a593Smuzhiyun fmt++;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun /*
362*4882a593Smuzhiyun * Field width:
363*4882a593Smuzhiyun * An optional decimal digit string (with non-zero first digit)
364*4882a593Smuzhiyun * specifying a minimum field width
365*4882a593Smuzhiyun */
366*4882a593Smuzhiyun while (*fmt && bcm_isdigit(*fmt))
367*4882a593Smuzhiyun fmt++;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun /*
370*4882a593Smuzhiyun * Precision:
371*4882a593Smuzhiyun * An optional precision, in the form of a period ('.') followed by an
372*4882a593Smuzhiyun * optional decimal digit string.
373*4882a593Smuzhiyun */
374*4882a593Smuzhiyun if (*fmt == '.')
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun fmt++;
377*4882a593Smuzhiyun while (*fmt && bcm_isdigit(*fmt)) fmt++;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun /* If %p is seen, change it to %x */
381*4882a593Smuzhiyun if (*fmt == 'p')
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun *fmt = 'x';
384*4882a593Smuzhiyun p_to_x_done = TRUE;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun if (*fmt)
387*4882a593Smuzhiyun fmt++;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun return p_to_x_done;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun /* To identify format of types %Ns where N >= 0 is a number */
394*4882a593Smuzhiyun bool
check_valid_string_format(char * curr_ptr)395*4882a593Smuzhiyun check_valid_string_format(char *curr_ptr)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun char *next_ptr;
398*4882a593Smuzhiyun if ((next_ptr = bcmstrstr(curr_ptr, "s")) != NULL) {
399*4882a593Smuzhiyun /* Default %s format */
400*4882a593Smuzhiyun if (curr_ptr == next_ptr) {
401*4882a593Smuzhiyun return TRUE;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun /* Verify each charater between '%' and 's' is a valid number */
405*4882a593Smuzhiyun while (curr_ptr < next_ptr) {
406*4882a593Smuzhiyun if (bcm_isdigit(*curr_ptr) == FALSE) {
407*4882a593Smuzhiyun return FALSE;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun curr_ptr++;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun return TRUE;
413*4882a593Smuzhiyun } else {
414*4882a593Smuzhiyun return FALSE;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun /* To identify format of non string format types */
419*4882a593Smuzhiyun bool
check_valid_non_string_format(char * curr_ptr)420*4882a593Smuzhiyun check_valid_non_string_format(char *curr_ptr)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun char *next_ptr;
423*4882a593Smuzhiyun char *next_fmt_stptr;
424*4882a593Smuzhiyun char valid_fmt_types[17] = {'d', 'i', 'x', 'X', 'c', 'p', 'u',
425*4882a593Smuzhiyun 'f', 'F', 'e', 'E', 'g', 'G', 'o',
426*4882a593Smuzhiyun 'a', 'A', 'n'};
427*4882a593Smuzhiyun int i;
428*4882a593Smuzhiyun bool valid = FALSE;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun /* Check for next % in the fmt str */
431*4882a593Smuzhiyun next_fmt_stptr = bcmstrstr(curr_ptr, "%");
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun for (next_ptr = curr_ptr; *next_ptr != '\0'; next_ptr++) {
434*4882a593Smuzhiyun for (i = 0; i < (int)((sizeof(valid_fmt_types))/sizeof(valid_fmt_types[0])); i++) {
435*4882a593Smuzhiyun if (*next_ptr == valid_fmt_types[i]) {
436*4882a593Smuzhiyun /* Check whether format type found corresponds to current %
437*4882a593Smuzhiyun * and not the next one, if exists.
438*4882a593Smuzhiyun */
439*4882a593Smuzhiyun if ((next_fmt_stptr == NULL) ||
440*4882a593Smuzhiyun (next_fmt_stptr && (next_ptr < next_fmt_stptr))) {
441*4882a593Smuzhiyun /* Not validating for length/width fields in
442*4882a593Smuzhiyun * format specifier.
443*4882a593Smuzhiyun */
444*4882a593Smuzhiyun valid = TRUE;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun goto done;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun done:
452*4882a593Smuzhiyun return valid;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun #define MAX_NO_OF_ARG 16
456*4882a593Smuzhiyun #define FMTSTR_SIZE 200
457*4882a593Smuzhiyun #define ROMSTR_SIZE 268
458*4882a593Smuzhiyun #define SIZE_LOC_STR 50
459*4882a593Smuzhiyun #define LOG_PRINT_CNT_MAX 16u
460*4882a593Smuzhiyun #define EL_MSEC_PER_SEC 1000
461*4882a593Smuzhiyun #ifdef DHD_LOG_PRINT_RATE_LIMIT
462*4882a593Smuzhiyun #define MAX_LOG_PRINT_COUNT 100u
463*4882a593Smuzhiyun #define LOG_PRINT_THRESH (1u * USEC_PER_SEC)
464*4882a593Smuzhiyun #endif
465*4882a593Smuzhiyun #define EL_PARSE_VER "V02"
466*4882a593Smuzhiyun static uint64 verboselog_ts_saved = 0;
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun bool
dhd_dbg_process_event_log_hdr(event_log_hdr_t * log_hdr,prcd_event_log_hdr_t * prcd_log_hdr)469*4882a593Smuzhiyun dhd_dbg_process_event_log_hdr(event_log_hdr_t *log_hdr, prcd_event_log_hdr_t *prcd_log_hdr)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun event_log_extended_hdr_t *ext_log_hdr;
472*4882a593Smuzhiyun uint16 event_log_fmt_num;
473*4882a593Smuzhiyun uint8 event_log_hdr_type;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun /* Identify the type of event tag, payload type etc.. */
476*4882a593Smuzhiyun event_log_hdr_type = log_hdr->fmt_num & DHD_EVENT_LOG_HDR_MASK;
477*4882a593Smuzhiyun event_log_fmt_num = (log_hdr->fmt_num >> DHD_EVENT_LOG_FMT_NUM_OFFSET) &
478*4882a593Smuzhiyun DHD_EVENT_LOG_FMT_NUM_MASK;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun switch (event_log_hdr_type) {
481*4882a593Smuzhiyun case DHD_OW_NB_EVENT_LOG_HDR:
482*4882a593Smuzhiyun prcd_log_hdr->ext_event_log_hdr = FALSE;
483*4882a593Smuzhiyun prcd_log_hdr->binary_payload = FALSE;
484*4882a593Smuzhiyun break;
485*4882a593Smuzhiyun case DHD_TW_NB_EVENT_LOG_HDR:
486*4882a593Smuzhiyun prcd_log_hdr->ext_event_log_hdr = TRUE;
487*4882a593Smuzhiyun prcd_log_hdr->binary_payload = FALSE;
488*4882a593Smuzhiyun break;
489*4882a593Smuzhiyun case DHD_BI_EVENT_LOG_HDR:
490*4882a593Smuzhiyun if (event_log_fmt_num == DHD_OW_BI_EVENT_FMT_NUM) {
491*4882a593Smuzhiyun prcd_log_hdr->ext_event_log_hdr = FALSE;
492*4882a593Smuzhiyun prcd_log_hdr->binary_payload = TRUE;
493*4882a593Smuzhiyun } else if (event_log_fmt_num == DHD_TW_BI_EVENT_FMT_NUM) {
494*4882a593Smuzhiyun prcd_log_hdr->ext_event_log_hdr = TRUE;
495*4882a593Smuzhiyun prcd_log_hdr->binary_payload = TRUE;
496*4882a593Smuzhiyun } else {
497*4882a593Smuzhiyun DHD_ERROR(("%s: invalid format number 0x%X\n",
498*4882a593Smuzhiyun __FUNCTION__, event_log_fmt_num));
499*4882a593Smuzhiyun return FALSE;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun break;
502*4882a593Smuzhiyun case DHD_INVALID_EVENT_LOG_HDR:
503*4882a593Smuzhiyun default:
504*4882a593Smuzhiyun DHD_ERROR(("%s: invalid event log header type 0x%X\n",
505*4882a593Smuzhiyun __FUNCTION__, event_log_hdr_type));
506*4882a593Smuzhiyun return FALSE;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun /* Parse extended and legacy event log headers and populate prcd_event_log_hdr_t */
510*4882a593Smuzhiyun if (prcd_log_hdr->ext_event_log_hdr) {
511*4882a593Smuzhiyun ext_log_hdr = (event_log_extended_hdr_t *)
512*4882a593Smuzhiyun ((uint8 *)log_hdr - sizeof(event_log_hdr_t));
513*4882a593Smuzhiyun prcd_log_hdr->tag = ((ext_log_hdr->extended_tag &
514*4882a593Smuzhiyun DHD_TW_VALID_TAG_BITS_MASK) << DHD_TW_EVENT_LOG_TAG_OFFSET) | log_hdr->tag;
515*4882a593Smuzhiyun } else {
516*4882a593Smuzhiyun prcd_log_hdr->tag = log_hdr->tag;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun prcd_log_hdr->count = log_hdr->count;
519*4882a593Smuzhiyun prcd_log_hdr->fmt_num_raw = log_hdr->fmt_num;
520*4882a593Smuzhiyun prcd_log_hdr->fmt_num = event_log_fmt_num;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun /* update arm cycle */
523*4882a593Smuzhiyun /*
524*4882a593Smuzhiyun * For loegacy event tag :-
525*4882a593Smuzhiyun * |payload........|Timestamp| Tag
526*4882a593Smuzhiyun *
527*4882a593Smuzhiyun * For extended event tag:-
528*4882a593Smuzhiyun * |payload........|Timestamp|extended Tag| Tag.
529*4882a593Smuzhiyun *
530*4882a593Smuzhiyun */
531*4882a593Smuzhiyun prcd_log_hdr->armcycle = prcd_log_hdr->ext_event_log_hdr ?
532*4882a593Smuzhiyun *(uint32 *)(log_hdr - EVENT_TAG_TIMESTAMP_EXT_OFFSET) :
533*4882a593Smuzhiyun *(uint32 *)(log_hdr - EVENT_TAG_TIMESTAMP_OFFSET);
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun /* update event log data pointer address */
536*4882a593Smuzhiyun prcd_log_hdr->log_ptr =
537*4882a593Smuzhiyun (uint32 *)log_hdr - log_hdr->count - prcd_log_hdr->ext_event_log_hdr;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun /* handle error cases above this */
540*4882a593Smuzhiyun return TRUE;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun static void
dhd_dbg_verboselog_handler(dhd_pub_t * dhdp,prcd_event_log_hdr_t * plog_hdr,void * raw_event_ptr,uint32 logset,uint16 block,uint32 * data)544*4882a593Smuzhiyun dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, prcd_event_log_hdr_t *plog_hdr,
545*4882a593Smuzhiyun void *raw_event_ptr, uint32 logset, uint16 block, uint32* data)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun event_log_hdr_t *ts_hdr;
548*4882a593Smuzhiyun uint32 *log_ptr = plog_hdr->log_ptr;
549*4882a593Smuzhiyun char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
550*4882a593Smuzhiyun uint32 rom_str_len = 0;
551*4882a593Smuzhiyun uint32 *ts_data;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun if (!raw_event_ptr) {
554*4882a593Smuzhiyun return;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (log_ptr < data) {
558*4882a593Smuzhiyun DHD_ERROR(("Invalid log pointer, logptr : %p data : %p \n", log_ptr, data));
559*4882a593Smuzhiyun return;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun if (log_ptr > data) {
563*4882a593Smuzhiyun /* Get time stamp if it's updated */
564*4882a593Smuzhiyun ts_hdr = (event_log_hdr_t *)((char *)log_ptr - sizeof(event_log_hdr_t));
565*4882a593Smuzhiyun if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
566*4882a593Smuzhiyun ts_data = (uint32 *)ts_hdr - ts_hdr->count;
567*4882a593Smuzhiyun if (ts_data >= data) {
568*4882a593Smuzhiyun verboselog_ts_saved = (uint64)ts_data[0];
569*4882a593Smuzhiyun DHD_MSGTRACE_LOG(("EVENT_LOG_TS[0x%08x]: SYS:%08x CPU:%08x\n",
570*4882a593Smuzhiyun ts_data[ts_hdr->count - 1], ts_data[0], ts_data[1]));
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun } else if (ts_hdr->tag == EVENT_LOG_TAG_ENHANCED_TS) {
573*4882a593Smuzhiyun ets_msg_v1_t *ets;
574*4882a593Smuzhiyun ets = (ets_msg_v1_t *)ts_hdr - ts_hdr->count;
575*4882a593Smuzhiyun if ((uint32*)ets >= data &&
576*4882a593Smuzhiyun ts_hdr->count >= (sizeof(ets_msg_v1_t) / sizeof(uint32)) &&
577*4882a593Smuzhiyun ets->version == ENHANCED_TS_MSG_VERSION_1) {
578*4882a593Smuzhiyun DHD_MSGTRACE_LOG(("EVENT_LOG_ENHANCED_TS_V1: "
579*4882a593Smuzhiyun "SYS:%08x CPU:%08x CPUFREQ:%u\n",
580*4882a593Smuzhiyun ets->timestamp, ets->cyclecount, ets->cpu_freq));
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun if (plog_hdr->tag == EVENT_LOG_TAG_ROM_PRINTF) {
586*4882a593Smuzhiyun rom_str_len = (plog_hdr->count - 1) * sizeof(uint32);
587*4882a593Smuzhiyun if (rom_str_len >= (ROMSTR_SIZE -1))
588*4882a593Smuzhiyun rom_str_len = ROMSTR_SIZE - 1;
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun /* copy all ascii data for ROM printf to local string */
591*4882a593Smuzhiyun memcpy(fmtstr_loc_buf, log_ptr, rom_str_len);
592*4882a593Smuzhiyun /* add end of line at last */
593*4882a593Smuzhiyun fmtstr_loc_buf[rom_str_len] = '\0';
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun DHD_MSGTRACE_LOG(("EVENT_LOG_ROM[0x%08x]: %s",
596*4882a593Smuzhiyun log_ptr[plog_hdr->count - 1], fmtstr_loc_buf));
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun /* Add newline if missing */
599*4882a593Smuzhiyun if (fmtstr_loc_buf[strlen(fmtstr_loc_buf) - 1] != '\n')
600*4882a593Smuzhiyun DHD_MSGTRACE_LOG(("\n"));
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun return;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun if (plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE ||
606*4882a593Smuzhiyun plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE_TLV) {
607*4882a593Smuzhiyun wl_mschdbg_verboselog_handler(dhdp, raw_event_ptr, plog_hdr, log_ptr);
608*4882a593Smuzhiyun return;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun /* print the message out in a logprint */
612*4882a593Smuzhiyun dhd_dbg_verboselog_printf(dhdp, plog_hdr, raw_event_ptr, log_ptr, logset, block);
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun void
dhd_dbg_verboselog_printf(dhd_pub_t * dhdp,prcd_event_log_hdr_t * plog_hdr,void * raw_event_ptr,uint32 * log_ptr,uint32 logset,uint16 block)616*4882a593Smuzhiyun dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, prcd_event_log_hdr_t *plog_hdr,
617*4882a593Smuzhiyun void *raw_event_ptr, uint32 *log_ptr, uint32 logset, uint16 block)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun dhd_event_log_t *raw_event = (dhd_event_log_t *)raw_event_ptr;
620*4882a593Smuzhiyun uint16 count;
621*4882a593Smuzhiyun int log_level, id;
622*4882a593Smuzhiyun char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
623*4882a593Smuzhiyun char (*str_buf)[SIZE_LOC_STR] = NULL;
624*4882a593Smuzhiyun char *str_tmpptr = NULL;
625*4882a593Smuzhiyun uint32 addr = 0;
626*4882a593Smuzhiyun typedef union {
627*4882a593Smuzhiyun uint32 val;
628*4882a593Smuzhiyun char * addr;
629*4882a593Smuzhiyun } u_arg;
630*4882a593Smuzhiyun u_arg arg[MAX_NO_OF_ARG] = {{0}};
631*4882a593Smuzhiyun char *c_ptr = NULL;
632*4882a593Smuzhiyun struct bcmstrbuf b;
633*4882a593Smuzhiyun #ifdef DHD_LOG_PRINT_RATE_LIMIT
634*4882a593Smuzhiyun static int log_print_count = 0;
635*4882a593Smuzhiyun static uint64 ts0 = 0;
636*4882a593Smuzhiyun uint64 ts1 = 0;
637*4882a593Smuzhiyun #endif /* DHD_LOG_PRINT_RATE_LIMIT */
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun BCM_REFERENCE(arg);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun #ifdef DHD_LOG_PRINT_RATE_LIMIT
642*4882a593Smuzhiyun if (!ts0)
643*4882a593Smuzhiyun ts0 = OSL_SYSUPTIME_US();
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun ts1 = OSL_SYSUPTIME_US();
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun if (((ts1 - ts0) <= LOG_PRINT_THRESH) && (log_print_count >= MAX_LOG_PRINT_COUNT)) {
648*4882a593Smuzhiyun log_print_threshold = 1;
649*4882a593Smuzhiyun ts0 = 0;
650*4882a593Smuzhiyun log_print_count = 0;
651*4882a593Smuzhiyun DHD_ERROR(("%s: Log print water mark is reached,"
652*4882a593Smuzhiyun " console logs are dumped only to debug_dump file\n", __FUNCTION__));
653*4882a593Smuzhiyun } else if ((ts1 - ts0) > LOG_PRINT_THRESH) {
654*4882a593Smuzhiyun log_print_threshold = 0;
655*4882a593Smuzhiyun ts0 = 0;
656*4882a593Smuzhiyun log_print_count = 0;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun #endif /* DHD_LOG_PRINT_RATE_LIMIT */
660*4882a593Smuzhiyun /* print the message out in a logprint */
661*4882a593Smuzhiyun if ((control_logtrace == LOGTRACE_RAW_FMT) || !(raw_event->fmts)) {
662*4882a593Smuzhiyun if (dhdp->dbg) {
663*4882a593Smuzhiyun log_level = dhdp->dbg->dbg_rings[FW_VERBOSE_RING_ID].log_level;
664*4882a593Smuzhiyun for (id = 0; id < ARRAYSIZE(fw_verbose_level_map); id++) {
665*4882a593Smuzhiyun if ((fw_verbose_level_map[id].tag == plog_hdr->tag) &&
666*4882a593Smuzhiyun (fw_verbose_level_map[id].log_level > log_level))
667*4882a593Smuzhiyun return;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun if (plog_hdr->binary_payload) {
671*4882a593Smuzhiyun DHD_ECNTR_LOG(("%d.%d EL:tag=%d len=%d fmt=0x%x",
672*4882a593Smuzhiyun (uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
673*4882a593Smuzhiyun (uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
674*4882a593Smuzhiyun plog_hdr->tag,
675*4882a593Smuzhiyun plog_hdr->count,
676*4882a593Smuzhiyun plog_hdr->fmt_num_raw));
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun for (count = 0; count < (plog_hdr->count - 1); count++) {
679*4882a593Smuzhiyun /* XXX: skip first line feed in case count 0 */
680*4882a593Smuzhiyun if (count && (count % LOG_PRINT_CNT_MAX == 0)) {
681*4882a593Smuzhiyun DHD_ECNTR_LOG(("\n\t%08x", log_ptr[count]));
682*4882a593Smuzhiyun } else {
683*4882a593Smuzhiyun DHD_ECNTR_LOG((" %08x", log_ptr[count]));
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun DHD_ECNTR_LOG(("\n"));
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun else {
689*4882a593Smuzhiyun bcm_binit(&b, fmtstr_loc_buf, FMTSTR_SIZE);
690*4882a593Smuzhiyun /* XXX: The 'hdr->count - 1' is dongle time */
691*4882a593Smuzhiyun #ifndef OEM_ANDROID
692*4882a593Smuzhiyun bcm_bprintf(&b, "%06d.%03d EL: %d 0x%x",
693*4882a593Smuzhiyun (uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
694*4882a593Smuzhiyun (uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
695*4882a593Smuzhiyun plog_hdr->tag,
696*4882a593Smuzhiyun plog_hdr->fmt_num_raw);
697*4882a593Smuzhiyun #else
698*4882a593Smuzhiyun bcm_bprintf(&b, "%06d.%03d EL:%s:%u:%u %d %d 0x%x",
699*4882a593Smuzhiyun (uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
700*4882a593Smuzhiyun (uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
701*4882a593Smuzhiyun EL_PARSE_VER, logset, block,
702*4882a593Smuzhiyun plog_hdr->tag,
703*4882a593Smuzhiyun plog_hdr->count,
704*4882a593Smuzhiyun plog_hdr->fmt_num_raw);
705*4882a593Smuzhiyun #endif /* !OEM_ANDROID */
706*4882a593Smuzhiyun for (count = 0; count < (plog_hdr->count - 1); count++) {
707*4882a593Smuzhiyun bcm_bprintf(&b, " %x", log_ptr[count]);
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun /* ensure preserve fw logs go to debug_dump only in case of customer4 */
711*4882a593Smuzhiyun if (logset < dhdp->event_log_max_sets &&
712*4882a593Smuzhiyun ((0x01u << logset) & dhdp->logset_prsrv_mask)) {
713*4882a593Smuzhiyun DHD_PRSRV_MEM(("%s\n", b.origbuf));
714*4882a593Smuzhiyun } else {
715*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
716*4882a593Smuzhiyun DHD_FW_VERBOSE(("%s\n", b.origbuf));
717*4882a593Smuzhiyun #else
718*4882a593Smuzhiyun DHD_FWLOG(("%s\n", b.origbuf));
719*4882a593Smuzhiyun #endif
720*4882a593Smuzhiyun #ifdef DHD_LOG_PRINT_RATE_LIMIT
721*4882a593Smuzhiyun log_print_count++;
722*4882a593Smuzhiyun #endif /* DHD_LOG_PRINT_RATE_LIMIT */
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun return;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun str_buf = MALLOCZ(dhdp->osh, (MAX_NO_OF_ARG * SIZE_LOC_STR));
729*4882a593Smuzhiyun if (!str_buf) {
730*4882a593Smuzhiyun DHD_ERROR(("%s: malloc failed str_buf\n", __FUNCTION__));
731*4882a593Smuzhiyun return;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun if ((plog_hdr->fmt_num) < raw_event->num_fmts) {
735*4882a593Smuzhiyun if (plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE) {
736*4882a593Smuzhiyun snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "%s",
737*4882a593Smuzhiyun raw_event->fmts[plog_hdr->fmt_num]);
738*4882a593Smuzhiyun plog_hdr->count++;
739*4882a593Smuzhiyun } else {
740*4882a593Smuzhiyun snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "CONSOLE_E:%u:%u %06d.%03d %s",
741*4882a593Smuzhiyun logset, block,
742*4882a593Smuzhiyun (uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
743*4882a593Smuzhiyun (uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
744*4882a593Smuzhiyun raw_event->fmts[plog_hdr->fmt_num]);
745*4882a593Smuzhiyun }
746*4882a593Smuzhiyun c_ptr = fmtstr_loc_buf;
747*4882a593Smuzhiyun } else {
748*4882a593Smuzhiyun /* for ecounters, don't print the error as it will flood */
749*4882a593Smuzhiyun if ((plog_hdr->fmt_num != DHD_OW_BI_EVENT_FMT_NUM) &&
750*4882a593Smuzhiyun (plog_hdr->fmt_num != DHD_TW_BI_EVENT_FMT_NUM)) {
751*4882a593Smuzhiyun DHD_ERROR(("%s: fmt number: 0x%x out of range\n",
752*4882a593Smuzhiyun __FUNCTION__, plog_hdr->fmt_num));
753*4882a593Smuzhiyun } else {
754*4882a593Smuzhiyun DHD_INFO(("%s: fmt number: 0x%x out of range\n",
755*4882a593Smuzhiyun __FUNCTION__, plog_hdr->fmt_num));
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun goto exit;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun if (plog_hdr->count > MAX_NO_OF_ARG) {
762*4882a593Smuzhiyun DHD_ERROR(("%s: plog_hdr->count(%d) out of range\n",
763*4882a593Smuzhiyun __FUNCTION__, plog_hdr->count));
764*4882a593Smuzhiyun goto exit;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun /* print the format string which will be needed for debugging incorrect formats */
768*4882a593Smuzhiyun DHD_INFO(("%s: fmtstr_loc_buf = %s\n", __FUNCTION__, fmtstr_loc_buf));
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun /* Replace all %p to %x to handle 32 bit %p */
771*4882a593Smuzhiyun replace_percent_p_to_x(fmtstr_loc_buf);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun for (count = 0; count < (plog_hdr->count - 1); count++) {
774*4882a593Smuzhiyun if (c_ptr != NULL)
775*4882a593Smuzhiyun if ((c_ptr = bcmstrstr(c_ptr, "%")) != NULL)
776*4882a593Smuzhiyun c_ptr++;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun if (c_ptr != NULL) {
779*4882a593Smuzhiyun if (check_valid_string_format(c_ptr)) {
780*4882a593Smuzhiyun if ((raw_event->raw_sstr) &&
781*4882a593Smuzhiyun ((log_ptr[count] > raw_event->rodata_start) &&
782*4882a593Smuzhiyun (log_ptr[count] < raw_event->rodata_end))) {
783*4882a593Smuzhiyun /* ram static string */
784*4882a593Smuzhiyun addr = log_ptr[count] - raw_event->rodata_start;
785*4882a593Smuzhiyun str_tmpptr = raw_event->raw_sstr + addr;
786*4882a593Smuzhiyun memcpy(str_buf[count], str_tmpptr,
787*4882a593Smuzhiyun SIZE_LOC_STR);
788*4882a593Smuzhiyun str_buf[count][SIZE_LOC_STR-1] = '\0';
789*4882a593Smuzhiyun arg[count].addr = str_buf[count];
790*4882a593Smuzhiyun } else if ((raw_event->rom_raw_sstr) &&
791*4882a593Smuzhiyun ((log_ptr[count] >
792*4882a593Smuzhiyun raw_event->rom_rodata_start) &&
793*4882a593Smuzhiyun (log_ptr[count] <
794*4882a593Smuzhiyun raw_event->rom_rodata_end))) {
795*4882a593Smuzhiyun /* rom static string */
796*4882a593Smuzhiyun addr = log_ptr[count] - raw_event->rom_rodata_start;
797*4882a593Smuzhiyun str_tmpptr = raw_event->rom_raw_sstr + addr;
798*4882a593Smuzhiyun memcpy(str_buf[count], str_tmpptr,
799*4882a593Smuzhiyun SIZE_LOC_STR);
800*4882a593Smuzhiyun str_buf[count][SIZE_LOC_STR-1] = '\0';
801*4882a593Smuzhiyun arg[count].addr = str_buf[count];
802*4882a593Smuzhiyun } else {
803*4882a593Smuzhiyun /*
804*4882a593Smuzhiyun * Dynamic string OR
805*4882a593Smuzhiyun * No data for static string.
806*4882a593Smuzhiyun * So store all string's address as string.
807*4882a593Smuzhiyun */
808*4882a593Smuzhiyun snprintf(str_buf[count], SIZE_LOC_STR,
809*4882a593Smuzhiyun "(s)0x%x", log_ptr[count]);
810*4882a593Smuzhiyun arg[count].addr = str_buf[count];
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun } else if (check_valid_non_string_format(c_ptr)) {
813*4882a593Smuzhiyun /* Other than string format */
814*4882a593Smuzhiyun arg[count].val = log_ptr[count];
815*4882a593Smuzhiyun } else {
816*4882a593Smuzhiyun /* There is nothing copied after % or improper format specifier
817*4882a593Smuzhiyun * after current %, because of not enough buffer size for complete
818*4882a593Smuzhiyun * copy of original fmt string.
819*4882a593Smuzhiyun * This is causing error mentioned below.
820*4882a593Smuzhiyun * Error: "Please remove unsupported %\x00 in format string"
821*4882a593Smuzhiyun * error(lib/vsprintf.c:1900 format_decode+0x3bc/0x470).
822*4882a593Smuzhiyun * Refer to JIRA: SWWLAN-200629 for detailed info.
823*4882a593Smuzhiyun *
824*4882a593Smuzhiyun * Terminate the string at current .
825*4882a593Smuzhiyun */
826*4882a593Smuzhiyun *(c_ptr - 1) = '\0';
827*4882a593Smuzhiyun break;
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun }
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun /* ensure preserve fw logs go to debug_dump only in case of customer4 */
833*4882a593Smuzhiyun if (logset < dhdp->event_log_max_sets &&
834*4882a593Smuzhiyun ((0x01u << logset) & dhdp->logset_prsrv_mask)) {
835*4882a593Smuzhiyun if (dhd_msg_level & DHD_EVENT_VAL) {
836*4882a593Smuzhiyun if (dhd_msg_level & DHD_PRSRV_MEM_VAL)
837*4882a593Smuzhiyun printk(fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
838*4882a593Smuzhiyun arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
839*4882a593Smuzhiyun arg[11], arg[12], arg[13], arg[14], arg[15]);
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun } else {
842*4882a593Smuzhiyun if (dhd_msg_level & DHD_FWLOG_VAL) {
843*4882a593Smuzhiyun printk(fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
844*4882a593Smuzhiyun arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
845*4882a593Smuzhiyun arg[11], arg[12], arg[13], arg[14], arg[15]);
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun #ifdef DHD_LOG_PRINT_RATE_LIMIT
848*4882a593Smuzhiyun log_print_count++;
849*4882a593Smuzhiyun #endif /* DHD_LOG_PRINT_RATE_LIMIT */
850*4882a593Smuzhiyun }
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun exit:
853*4882a593Smuzhiyun MFREE(dhdp->osh, str_buf, (MAX_NO_OF_ARG * SIZE_LOC_STR));
854*4882a593Smuzhiyun }
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun #if defined(EWP_BCM_TRACE) || defined(EWP_RTT_LOGGING) || \
857*4882a593Smuzhiyun defined(EWP_ECNTRS_LOGGING)
858*4882a593Smuzhiyun static int
dhd_dbg_send_evtlog_to_ring(prcd_event_log_hdr_t * plog_hdr,dhd_dbg_ring_entry_t * msg_hdr,dhd_dbg_ring_t * ring,uint16 max_payload_len,uint8 * logbuf)859*4882a593Smuzhiyun dhd_dbg_send_evtlog_to_ring(prcd_event_log_hdr_t *plog_hdr,
860*4882a593Smuzhiyun dhd_dbg_ring_entry_t *msg_hdr, dhd_dbg_ring_t *ring,
861*4882a593Smuzhiyun uint16 max_payload_len, uint8 *logbuf)
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun event_log_hdr_t *log_hdr;
864*4882a593Smuzhiyun struct tracelog_header *logentry_header;
865*4882a593Smuzhiyun uint16 len_chk = 0;
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun BCM_REFERENCE(log_hdr);
868*4882a593Smuzhiyun BCM_REFERENCE(logentry_header);
869*4882a593Smuzhiyun /*
870*4882a593Smuzhiyun * check msg hdr len before pushing.
871*4882a593Smuzhiyun * FW msg_hdr.len includes length of event log hdr,
872*4882a593Smuzhiyun * logentry header and payload.
873*4882a593Smuzhiyun */
874*4882a593Smuzhiyun len_chk = (sizeof(*logentry_header) + sizeof(*log_hdr) +
875*4882a593Smuzhiyun max_payload_len);
876*4882a593Smuzhiyun /* account extended event log header(extended_event_log_hdr) */
877*4882a593Smuzhiyun if (plog_hdr->ext_event_log_hdr) {
878*4882a593Smuzhiyun len_chk += sizeof(*log_hdr);
879*4882a593Smuzhiyun }
880*4882a593Smuzhiyun if (msg_hdr->len > len_chk) {
881*4882a593Smuzhiyun DHD_ERROR(("%s: EVENT_LOG_VALIDATION_FAILS: "
882*4882a593Smuzhiyun "msg_hdr->len=%u, max allowed for %s=%u\n",
883*4882a593Smuzhiyun __FUNCTION__, msg_hdr->len, ring->name, len_chk));
884*4882a593Smuzhiyun return BCME_ERROR;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun dhd_dbg_ring_push(ring, msg_hdr, logbuf);
887*4882a593Smuzhiyun return BCME_OK;
888*4882a593Smuzhiyun }
889*4882a593Smuzhiyun #endif /* EWP_BCM_TRACE || EWP_RTT_LOGGING || EWP_ECNTRS_LOGGING */
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun void
dhd_dbg_msgtrace_log_parser(dhd_pub_t * dhdp,void * event_data,void * raw_event_ptr,uint datalen,bool msgtrace_hdr_present,uint32 msgtrace_seqnum)892*4882a593Smuzhiyun dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data,
893*4882a593Smuzhiyun void *raw_event_ptr, uint datalen, bool msgtrace_hdr_present,
894*4882a593Smuzhiyun uint32 msgtrace_seqnum)
895*4882a593Smuzhiyun {
896*4882a593Smuzhiyun msgtrace_hdr_t *hdr;
897*4882a593Smuzhiyun char *data, *tmpdata;
898*4882a593Smuzhiyun const uint32 log_hdr_len = sizeof(event_log_hdr_t);
899*4882a593Smuzhiyun uint32 log_pyld_len;
900*4882a593Smuzhiyun static uint32 seqnum_prev = 0;
901*4882a593Smuzhiyun event_log_hdr_t *log_hdr;
902*4882a593Smuzhiyun bool msg_processed = FALSE;
903*4882a593Smuzhiyun prcd_event_log_hdr_t prcd_log_hdr;
904*4882a593Smuzhiyun prcd_event_log_hdr_t *plog_hdr;
905*4882a593Smuzhiyun dll_t list_head, *cur;
906*4882a593Smuzhiyun loglist_item_t *log_item;
907*4882a593Smuzhiyun dhd_dbg_ring_entry_t msg_hdr;
908*4882a593Smuzhiyun char *logbuf;
909*4882a593Smuzhiyun struct tracelog_header *logentry_header;
910*4882a593Smuzhiyun uint ring_data_len = 0;
911*4882a593Smuzhiyun bool ecntr_pushed = FALSE;
912*4882a593Smuzhiyun bool rtt_pushed = FALSE;
913*4882a593Smuzhiyun bool bcm_trace_pushed = FALSE;
914*4882a593Smuzhiyun bool dll_inited = FALSE;
915*4882a593Smuzhiyun uint32 logset = 0;
916*4882a593Smuzhiyun uint16 block = 0;
917*4882a593Smuzhiyun bool event_log_max_sets_queried;
918*4882a593Smuzhiyun uint32 event_log_max_sets;
919*4882a593Smuzhiyun uint min_expected_len = 0;
920*4882a593Smuzhiyun uint16 len_chk = 0;
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun BCM_REFERENCE(ecntr_pushed);
923*4882a593Smuzhiyun BCM_REFERENCE(rtt_pushed);
924*4882a593Smuzhiyun BCM_REFERENCE(bcm_trace_pushed);
925*4882a593Smuzhiyun BCM_REFERENCE(len_chk);
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun /* store event_logset_queried and event_log_max_sets in local variables
928*4882a593Smuzhiyun * to avoid race conditions as they were set from different contexts(preinit)
929*4882a593Smuzhiyun */
930*4882a593Smuzhiyun event_log_max_sets_queried = dhdp->event_log_max_sets_queried;
931*4882a593Smuzhiyun /* Make sure queried is read first with wmb and then max_sets,
932*4882a593Smuzhiyun * as it is done in reverse order during preinit ioctls.
933*4882a593Smuzhiyun */
934*4882a593Smuzhiyun OSL_SMP_WMB();
935*4882a593Smuzhiyun event_log_max_sets = dhdp->event_log_max_sets;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun if (msgtrace_hdr_present)
938*4882a593Smuzhiyun min_expected_len = (MSGTRACE_HDRLEN + EVENT_LOG_BLOCK_LEN);
939*4882a593Smuzhiyun else
940*4882a593Smuzhiyun min_expected_len = EVENT_LOG_BLOCK_LEN;
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun /* log trace event consists of:
943*4882a593Smuzhiyun * msgtrace header
944*4882a593Smuzhiyun * event log block header
945*4882a593Smuzhiyun * event log payload
946*4882a593Smuzhiyun */
947*4882a593Smuzhiyun if (!event_data || (datalen <= min_expected_len)) {
948*4882a593Smuzhiyun DHD_ERROR(("%s: Not processing due to invalid event_data : %p or length : %d\n",
949*4882a593Smuzhiyun __FUNCTION__, event_data, datalen));
950*4882a593Smuzhiyun if (event_data && msgtrace_hdr_present) {
951*4882a593Smuzhiyun prhex("event_data dump", event_data, datalen);
952*4882a593Smuzhiyun tmpdata = (char *)event_data + MSGTRACE_HDRLEN;
953*4882a593Smuzhiyun if (tmpdata) {
954*4882a593Smuzhiyun DHD_ERROR(("EVENT_LOG_HDR[0x%x]: Set: 0x%08x length = %d\n",
955*4882a593Smuzhiyun ltoh16(*((uint16 *)(tmpdata+2))),
956*4882a593Smuzhiyun ltoh32(*((uint32 *)(tmpdata + 4))),
957*4882a593Smuzhiyun ltoh16(*((uint16 *)(tmpdata)))));
958*4882a593Smuzhiyun }
959*4882a593Smuzhiyun } else if (!event_data) {
960*4882a593Smuzhiyun DHD_ERROR(("%s: event_data is NULL, cannot dump prhex\n", __FUNCTION__));
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun return;
964*4882a593Smuzhiyun }
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun if (msgtrace_hdr_present) {
967*4882a593Smuzhiyun hdr = (msgtrace_hdr_t *)event_data;
968*4882a593Smuzhiyun data = (char *)event_data + MSGTRACE_HDRLEN;
969*4882a593Smuzhiyun datalen -= MSGTRACE_HDRLEN;
970*4882a593Smuzhiyun msgtrace_seqnum = ntoh32(hdr->seqnum);
971*4882a593Smuzhiyun } else {
972*4882a593Smuzhiyun data = (char *)event_data;
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun if (dhd_dbg_msgtrace_seqchk(&seqnum_prev, msgtrace_seqnum))
976*4882a593Smuzhiyun return;
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun /* Save the whole message to event log ring */
979*4882a593Smuzhiyun memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
980*4882a593Smuzhiyun logbuf = VMALLOC(dhdp->osh, sizeof(*logentry_header) + datalen);
981*4882a593Smuzhiyun if (logbuf == NULL)
982*4882a593Smuzhiyun return;
983*4882a593Smuzhiyun logentry_header = (struct tracelog_header *)logbuf;
984*4882a593Smuzhiyun logentry_header->magic_num = TRACE_LOG_MAGIC_NUMBER;
985*4882a593Smuzhiyun logentry_header->buf_size = datalen;
986*4882a593Smuzhiyun logentry_header->seq_num = msgtrace_seqnum;
987*4882a593Smuzhiyun msg_hdr.type = DBG_RING_ENTRY_DATA_TYPE;
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun ring_data_len = datalen + sizeof(*logentry_header);
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun if ((sizeof(*logentry_header) + datalen) > PAYLOAD_MAX_LEN) {
992*4882a593Smuzhiyun DHD_ERROR(("%s:Payload len=%u exceeds max len\n", __FUNCTION__,
993*4882a593Smuzhiyun ((uint)sizeof(*logentry_header) + datalen)));
994*4882a593Smuzhiyun goto exit;
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun msg_hdr.len = sizeof(*logentry_header) + datalen;
998*4882a593Smuzhiyun memcpy(logbuf + sizeof(*logentry_header), data, datalen);
999*4882a593Smuzhiyun DHD_DBGIF(("%s: datalen %d %d\n", __FUNCTION__, msg_hdr.len, datalen));
1000*4882a593Smuzhiyun #ifndef DHD_DEBUGABILITY_LOG_DUMP_RING
1001*4882a593Smuzhiyun dhd_dbg_push_to_ring(dhdp, FW_VERBOSE_RING_ID, &msg_hdr, logbuf);
1002*4882a593Smuzhiyun #endif
1003*4882a593Smuzhiyun /* Print sequence number, originating set and length of received
1004*4882a593Smuzhiyun * event log buffer. Refer to event log buffer structure in
1005*4882a593Smuzhiyun * event_log.h
1006*4882a593Smuzhiyun */
1007*4882a593Smuzhiyun DHD_MSGTRACE_LOG(("EVENT_LOG_HDR[0x%x]: Set: 0x%08x length = %d\n",
1008*4882a593Smuzhiyun ltoh16(*((uint16 *)(data+2))), ltoh32(*((uint32 *)(data + 4))),
1009*4882a593Smuzhiyun ltoh16(*((uint16 *)(data)))));
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun logset = ltoh32(*((uint32 *)(data + 4)));
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun if (logset >= event_log_max_sets) {
1014*4882a593Smuzhiyun DHD_ERROR(("%s logset: %d max: %d out of range queried: %d\n",
1015*4882a593Smuzhiyun __FUNCTION__, logset, event_log_max_sets, event_log_max_sets_queried));
1016*4882a593Smuzhiyun #ifdef DHD_FW_COREDUMP
1017*4882a593Smuzhiyun if (event_log_max_sets_queried) {
1018*4882a593Smuzhiyun DHD_ERROR(("%s: collect socram for DUMP_TYPE_LOGSET_BEYOND_RANGE\n",
1019*4882a593Smuzhiyun __FUNCTION__));
1020*4882a593Smuzhiyun dhdp->memdump_type = DUMP_TYPE_LOGSET_BEYOND_RANGE;
1021*4882a593Smuzhiyun dhd_bus_mem_dump(dhdp);
1022*4882a593Smuzhiyun }
1023*4882a593Smuzhiyun #endif /* DHD_FW_COREDUMP */
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun block = ltoh16(*((uint16 *)(data + 2)));
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun data += EVENT_LOG_BLOCK_HDRLEN;
1029*4882a593Smuzhiyun datalen -= EVENT_LOG_BLOCK_HDRLEN;
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun /* start parsing from the tail of packet
1032*4882a593Smuzhiyun * Sameple format of a meessage
1033*4882a593Smuzhiyun * 001d3c54 00000064 00000064 001d3c54 001dba08 035d6ce1 0c540639
1034*4882a593Smuzhiyun * 001d3c54 00000064 00000064 035d6d89 0c580439
1035*4882a593Smuzhiyun * 0x0c580439 -- 39 is tag, 04 is count, 580c is format number
1036*4882a593Smuzhiyun * all these uint32 values comes in reverse order as group as EL data
1037*4882a593Smuzhiyun * while decoding we can only parse from last to first
1038*4882a593Smuzhiyun * |<- datalen ->|
1039*4882a593Smuzhiyun * |----(payload and maybe more logs)----|event_log_hdr_t|
1040*4882a593Smuzhiyun * data log_hdr
1041*4882a593Smuzhiyun */
1042*4882a593Smuzhiyun dll_init(&list_head);
1043*4882a593Smuzhiyun dll_inited = TRUE;
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun while (datalen > log_hdr_len) {
1046*4882a593Smuzhiyun log_hdr = (event_log_hdr_t *)(data + datalen - log_hdr_len);
1047*4882a593Smuzhiyun memset(&prcd_log_hdr, 0, sizeof(prcd_log_hdr));
1048*4882a593Smuzhiyun if (!dhd_dbg_process_event_log_hdr(log_hdr, &prcd_log_hdr)) {
1049*4882a593Smuzhiyun DHD_ERROR(("%s: Error while parsing event log header\n",
1050*4882a593Smuzhiyun __FUNCTION__));
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun /* skip zero padding at end of frame */
1054*4882a593Smuzhiyun if (prcd_log_hdr.tag == EVENT_LOG_TAG_NULL) {
1055*4882a593Smuzhiyun datalen -= log_hdr_len;
1056*4882a593Smuzhiyun continue;
1057*4882a593Smuzhiyun }
1058*4882a593Smuzhiyun /* Check argument count (for non-ecounter events only),
1059*4882a593Smuzhiyun * any event log should contain at least
1060*4882a593Smuzhiyun * one argument (4 bytes) for arm cycle count and up to 16
1061*4882a593Smuzhiyun * arguments except EVENT_LOG_TAG_STATS which could use the
1062*4882a593Smuzhiyun * whole payload of 256 words
1063*4882a593Smuzhiyun */
1064*4882a593Smuzhiyun if (prcd_log_hdr.count == 0) {
1065*4882a593Smuzhiyun break;
1066*4882a593Smuzhiyun }
1067*4882a593Smuzhiyun /* Both tag_stats and proxd are binary payloads so skip
1068*4882a593Smuzhiyun * argument count check for these.
1069*4882a593Smuzhiyun */
1070*4882a593Smuzhiyun if ((prcd_log_hdr.tag != EVENT_LOG_TAG_STATS) &&
1071*4882a593Smuzhiyun (prcd_log_hdr.tag != EVENT_LOG_TAG_PROXD_SAMPLE_COLLECT) &&
1072*4882a593Smuzhiyun (prcd_log_hdr.tag != EVENT_LOG_TAG_ROAM_ENHANCED_LOG) &&
1073*4882a593Smuzhiyun (prcd_log_hdr.tag != EVENT_LOG_TAG_BCM_TRACE) &&
1074*4882a593Smuzhiyun (prcd_log_hdr.count > MAX_NO_OF_ARG)) {
1075*4882a593Smuzhiyun break;
1076*4882a593Smuzhiyun }
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun log_pyld_len = (prcd_log_hdr.count + prcd_log_hdr.ext_event_log_hdr) *
1079*4882a593Smuzhiyun DATA_UNIT_FOR_LOG_CNT;
1080*4882a593Smuzhiyun /* log data should not cross the event data boundary */
1081*4882a593Smuzhiyun if ((uint32)((char *)log_hdr - data) < log_pyld_len) {
1082*4882a593Smuzhiyun break;
1083*4882a593Smuzhiyun }
1084*4882a593Smuzhiyun /* skip 4 bytes time stamp packet */
1085*4882a593Smuzhiyun if (prcd_log_hdr.tag == EVENT_LOG_TAG_TS ||
1086*4882a593Smuzhiyun prcd_log_hdr.tag == EVENT_LOG_TAG_ENHANCED_TS) {
1087*4882a593Smuzhiyun datalen -= (log_pyld_len + log_hdr_len);
1088*4882a593Smuzhiyun continue;
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun if (!(log_item = MALLOC(dhdp->osh, sizeof(*log_item)))) {
1091*4882a593Smuzhiyun DHD_ERROR(("%s allocating log list item failed\n",
1092*4882a593Smuzhiyun __FUNCTION__));
1093*4882a593Smuzhiyun break;
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun log_item->prcd_log_hdr.tag = prcd_log_hdr.tag;
1097*4882a593Smuzhiyun log_item->prcd_log_hdr.count = prcd_log_hdr.count;
1098*4882a593Smuzhiyun log_item->prcd_log_hdr.fmt_num = prcd_log_hdr.fmt_num;
1099*4882a593Smuzhiyun log_item->prcd_log_hdr.fmt_num_raw = prcd_log_hdr.fmt_num_raw;
1100*4882a593Smuzhiyun log_item->prcd_log_hdr.armcycle = prcd_log_hdr.armcycle;
1101*4882a593Smuzhiyun log_item->prcd_log_hdr.log_ptr = prcd_log_hdr.log_ptr;
1102*4882a593Smuzhiyun log_item->prcd_log_hdr.payload_len = prcd_log_hdr.payload_len;
1103*4882a593Smuzhiyun log_item->prcd_log_hdr.ext_event_log_hdr = prcd_log_hdr.ext_event_log_hdr;
1104*4882a593Smuzhiyun log_item->prcd_log_hdr.binary_payload = prcd_log_hdr.binary_payload;
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun dll_insert(&log_item->list, &list_head);
1107*4882a593Smuzhiyun datalen -= (log_pyld_len + log_hdr_len);
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun while (!dll_empty(&list_head)) {
1111*4882a593Smuzhiyun msg_processed = FALSE;
1112*4882a593Smuzhiyun cur = dll_head_p(&list_head);
1113*4882a593Smuzhiyun
1114*4882a593Smuzhiyun GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
1115*4882a593Smuzhiyun log_item = (loglist_item_t *)container_of(cur, loglist_item_t, list);
1116*4882a593Smuzhiyun GCC_DIAGNOSTIC_POP();
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun plog_hdr = &log_item->prcd_log_hdr;
1119*4882a593Smuzhiyun #if defined(EWP_ECNTRS_LOGGING) && defined(DHD_LOG_DUMP)
1120*4882a593Smuzhiyun /* Ecounter tag can be time_data or log_stats+binary paloaod */
1121*4882a593Smuzhiyun if ((plog_hdr->tag == EVENT_LOG_TAG_ECOUNTERS_TIME_DATA) ||
1122*4882a593Smuzhiyun ((plog_hdr->tag == EVENT_LOG_TAG_STATS) &&
1123*4882a593Smuzhiyun (plog_hdr->binary_payload))) {
1124*4882a593Smuzhiyun if (!ecntr_pushed && dhd_log_dump_ecntr_enabled()) {
1125*4882a593Smuzhiyun if (dhd_dbg_send_evtlog_to_ring(plog_hdr, &msg_hdr,
1126*4882a593Smuzhiyun dhdp->ecntr_dbg_ring,
1127*4882a593Smuzhiyun PAYLOAD_ECNTR_MAX_LEN, logbuf) != BCME_OK) {
1128*4882a593Smuzhiyun goto exit;
1129*4882a593Smuzhiyun }
1130*4882a593Smuzhiyun ecntr_pushed = TRUE;
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun #endif /* EWP_ECNTRS_LOGGING && DHD_LOG_DUMP */
1134*4882a593Smuzhiyun
1135*4882a593Smuzhiyun if (plog_hdr->tag == EVENT_LOG_TAG_ROAM_ENHANCED_LOG) {
1136*4882a593Smuzhiyun print_roam_enhanced_log(plog_hdr);
1137*4882a593Smuzhiyun msg_processed = TRUE;
1138*4882a593Smuzhiyun }
1139*4882a593Smuzhiyun #if defined(EWP_RTT_LOGGING) && defined(DHD_LOG_DUMP)
1140*4882a593Smuzhiyun if ((plog_hdr->tag == EVENT_LOG_TAG_PROXD_SAMPLE_COLLECT) &&
1141*4882a593Smuzhiyun plog_hdr->binary_payload) {
1142*4882a593Smuzhiyun if (!rtt_pushed && dhd_log_dump_rtt_enabled()) {
1143*4882a593Smuzhiyun if (dhd_dbg_send_evtlog_to_ring(plog_hdr, &msg_hdr,
1144*4882a593Smuzhiyun dhdp->rtt_dbg_ring,
1145*4882a593Smuzhiyun PAYLOAD_RTT_MAX_LEN, logbuf) != BCME_OK) {
1146*4882a593Smuzhiyun goto exit;
1147*4882a593Smuzhiyun }
1148*4882a593Smuzhiyun rtt_pushed = TRUE;
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun }
1151*4882a593Smuzhiyun #endif /* EWP_RTT_LOGGING && DHD_LOG_DUMP */
1152*4882a593Smuzhiyun
1153*4882a593Smuzhiyun #ifdef EWP_BCM_TRACE
1154*4882a593Smuzhiyun if ((logset == EVENT_LOG_SET_BCM_TRACE) && !bcm_trace_pushed &&
1155*4882a593Smuzhiyun plog_hdr->binary_payload) {
1156*4882a593Smuzhiyun if (dhd_dbg_send_evtlog_to_ring(plog_hdr, &msg_hdr,
1157*4882a593Smuzhiyun dhdp->bcm_trace_dbg_ring,
1158*4882a593Smuzhiyun PAYLOAD_BCM_TRACE_MAX_LEN, logbuf) != BCME_OK) {
1159*4882a593Smuzhiyun goto exit;
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun bcm_trace_pushed = TRUE;
1162*4882a593Smuzhiyun }
1163*4882a593Smuzhiyun #endif /* EWP_BCM_TRACE */
1164*4882a593Smuzhiyun
1165*4882a593Smuzhiyun #if defined (DHD_EVENT_LOG_FILTER)
1166*4882a593Smuzhiyun if (plog_hdr->tag == EVENT_LOG_TAG_STATS) {
1167*4882a593Smuzhiyun dhd_event_log_filter_event_handler(dhdp, plog_hdr, plog_hdr->log_ptr);
1168*4882a593Smuzhiyun }
1169*4882a593Smuzhiyun #endif /* DHD_EVENT_LOG_FILTER */
1170*4882a593Smuzhiyun if (!msg_processed) {
1171*4882a593Smuzhiyun dhd_dbg_verboselog_handler(dhdp, plog_hdr, raw_event_ptr,
1172*4882a593Smuzhiyun logset, block, (uint32 *)data);
1173*4882a593Smuzhiyun }
1174*4882a593Smuzhiyun dll_delete(cur);
1175*4882a593Smuzhiyun MFREE(dhdp->osh, log_item, sizeof(*log_item));
1176*4882a593Smuzhiyun
1177*4882a593Smuzhiyun }
1178*4882a593Smuzhiyun BCM_REFERENCE(log_hdr);
1179*4882a593Smuzhiyun exit:
1180*4882a593Smuzhiyun while (dll_inited && (!dll_empty(&list_head))) {
1181*4882a593Smuzhiyun cur = dll_head_p(&list_head);
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
1184*4882a593Smuzhiyun log_item = (loglist_item_t *)container_of(cur, loglist_item_t, list);
1185*4882a593Smuzhiyun GCC_DIAGNOSTIC_POP();
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun dll_delete(cur);
1188*4882a593Smuzhiyun MFREE(dhdp->osh, log_item, sizeof(*log_item));
1189*4882a593Smuzhiyun }
1190*4882a593Smuzhiyun
1191*4882a593Smuzhiyun VMFREE(dhdp->osh, logbuf, ring_data_len);
1192*4882a593Smuzhiyun }
1193*4882a593Smuzhiyun #else /* !SHOW_LOGTRACE */
dhd_dbg_verboselog_handler(dhd_pub_t * dhdp,prcd_event_log_hdr_t * plog_hdr,void * raw_event_ptr,uint32 logset,uint16 block,uint32 * data)1194*4882a593Smuzhiyun static INLINE void dhd_dbg_verboselog_handler(dhd_pub_t *dhdp,
1195*4882a593Smuzhiyun prcd_event_log_hdr_t *plog_hdr, void *raw_event_ptr, uint32 logset, uint16 block,
1196*4882a593Smuzhiyun uint32 *data) {};
dhd_dbg_msgtrace_log_parser(dhd_pub_t * dhdp,void * event_data,void * raw_event_ptr,uint datalen,bool msgtrace_hdr_present,uint32 msgtrace_seqnum)1197*4882a593Smuzhiyun INLINE void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp,
1198*4882a593Smuzhiyun void *event_data, void *raw_event_ptr, uint datalen,
1199*4882a593Smuzhiyun bool msgtrace_hdr_present, uint32 msgtrace_seqnum) {};
1200*4882a593Smuzhiyun #endif /* SHOW_LOGTRACE */
1201*4882a593Smuzhiyun void
dhd_dbg_trace_evnt_handler(dhd_pub_t * dhdp,void * event_data,void * raw_event_ptr,uint datalen)1202*4882a593Smuzhiyun dhd_dbg_trace_evnt_handler(dhd_pub_t *dhdp, void *event_data,
1203*4882a593Smuzhiyun void *raw_event_ptr, uint datalen)
1204*4882a593Smuzhiyun {
1205*4882a593Smuzhiyun msgtrace_hdr_t *hdr;
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun hdr = (msgtrace_hdr_t *)event_data;
1208*4882a593Smuzhiyun
1209*4882a593Smuzhiyun if (hdr->version != MSGTRACE_VERSION) {
1210*4882a593Smuzhiyun DHD_DBGIF(("%s unsupported MSGTRACE version, dhd %d, dongle %d\n",
1211*4882a593Smuzhiyun __FUNCTION__, MSGTRACE_VERSION, hdr->version));
1212*4882a593Smuzhiyun return;
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun if (hdr->trace_type == MSGTRACE_HDR_TYPE_MSG)
1216*4882a593Smuzhiyun dhd_dbg_msgtrace_msg_parser(event_data);
1217*4882a593Smuzhiyun else if (hdr->trace_type == MSGTRACE_HDR_TYPE_LOG)
1218*4882a593Smuzhiyun dhd_dbg_msgtrace_log_parser(dhdp, event_data, raw_event_ptr, datalen, TRUE, 0);
1219*4882a593Smuzhiyun }
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun #ifdef BTLOG
1222*4882a593Smuzhiyun void
dhd_dbg_bt_log_handler(dhd_pub_t * dhdp,void * data,uint datalen)1223*4882a593Smuzhiyun dhd_dbg_bt_log_handler(dhd_pub_t *dhdp, void *data, uint datalen)
1224*4882a593Smuzhiyun {
1225*4882a593Smuzhiyun dhd_dbg_ring_entry_t msg_hdr;
1226*4882a593Smuzhiyun int ret;
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun /* push to ring */
1229*4882a593Smuzhiyun memset(&msg_hdr, 0, sizeof(msg_hdr));
1230*4882a593Smuzhiyun msg_hdr.type = DBG_RING_ENTRY_DATA_TYPE;
1231*4882a593Smuzhiyun msg_hdr.len = datalen;
1232*4882a593Smuzhiyun ret = dhd_dbg_push_to_ring(dhdp, BT_LOG_RING_ID, &msg_hdr, data);
1233*4882a593Smuzhiyun if (ret != BCME_OK) {
1234*4882a593Smuzhiyun DHD_ERROR(("%s ring push failed %d\n", __FUNCTION__, ret));
1235*4882a593Smuzhiyun }
1236*4882a593Smuzhiyun }
1237*4882a593Smuzhiyun #endif /* BTLOG */
1238*4882a593Smuzhiyun
1239*4882a593Smuzhiyun /*
1240*4882a593Smuzhiyun * dhd_dbg_set_event_log_tag : modify the state of an event log tag
1241*4882a593Smuzhiyun */
1242*4882a593Smuzhiyun void
dhd_dbg_set_event_log_tag(dhd_pub_t * dhdp,uint16 tag,uint8 set)1243*4882a593Smuzhiyun dhd_dbg_set_event_log_tag(dhd_pub_t *dhdp, uint16 tag, uint8 set)
1244*4882a593Smuzhiyun {
1245*4882a593Smuzhiyun wl_el_tag_params_t pars;
1246*4882a593Smuzhiyun char *cmd = "event_log_tag_control";
1247*4882a593Smuzhiyun char iovbuf[WLC_IOCTL_SMLEN] = { 0 };
1248*4882a593Smuzhiyun int ret;
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun memset(&pars, 0, sizeof(pars));
1251*4882a593Smuzhiyun pars.tag = tag;
1252*4882a593Smuzhiyun pars.set = set;
1253*4882a593Smuzhiyun pars.flags = EVENT_LOG_TAG_FLAG_LOG;
1254*4882a593Smuzhiyun
1255*4882a593Smuzhiyun if (!bcm_mkiovar(cmd, (char *)&pars, sizeof(pars), iovbuf, sizeof(iovbuf))) {
1256*4882a593Smuzhiyun DHD_ERROR(("%s mkiovar failed\n", __FUNCTION__));
1257*4882a593Smuzhiyun return;
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun ret = dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
1261*4882a593Smuzhiyun if (ret) {
1262*4882a593Smuzhiyun // DHD_ERROR(("%s set log tag iovar failed %d\n", __FUNCTION__, ret));
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun }
1265*4882a593Smuzhiyun
1266*4882a593Smuzhiyun int
dhd_dbg_set_configuration(dhd_pub_t * dhdp,int ring_id,int log_level,int flags,uint32 threshold)1267*4882a593Smuzhiyun dhd_dbg_set_configuration(dhd_pub_t *dhdp, int ring_id, int log_level, int flags, uint32 threshold)
1268*4882a593Smuzhiyun {
1269*4882a593Smuzhiyun dhd_dbg_ring_t *ring;
1270*4882a593Smuzhiyun uint8 set = 1;
1271*4882a593Smuzhiyun int i, array_len = 0;
1272*4882a593Smuzhiyun struct log_level_table *log_level_tbl = NULL;
1273*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg)
1274*4882a593Smuzhiyun return BCME_BADADDR;
1275*4882a593Smuzhiyun
1276*4882a593Smuzhiyun if (!VALID_RING(ring_id)) {
1277*4882a593Smuzhiyun DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
1278*4882a593Smuzhiyun return BCME_RANGE;
1279*4882a593Smuzhiyun }
1280*4882a593Smuzhiyun
1281*4882a593Smuzhiyun ring = &dhdp->dbg->dbg_rings[ring_id];
1282*4882a593Smuzhiyun dhd_dbg_ring_config(ring, log_level, threshold);
1283*4882a593Smuzhiyun
1284*4882a593Smuzhiyun if (log_level > 0)
1285*4882a593Smuzhiyun set = TRUE;
1286*4882a593Smuzhiyun
1287*4882a593Smuzhiyun if (ring->id == FW_VERBOSE_RING_ID) {
1288*4882a593Smuzhiyun log_level_tbl = fw_verbose_level_map;
1289*4882a593Smuzhiyun array_len = ARRAYSIZE(fw_verbose_level_map);
1290*4882a593Smuzhiyun }
1291*4882a593Smuzhiyun
1292*4882a593Smuzhiyun for (i = 0; i < array_len; i++) {
1293*4882a593Smuzhiyun if (log_level == 0 || (log_level_tbl[i].log_level > log_level)) {
1294*4882a593Smuzhiyun /* clear the reference per ring */
1295*4882a593Smuzhiyun ref_tag_tbl[log_level_tbl[i].tag] &= ~(1 << ring_id);
1296*4882a593Smuzhiyun } else {
1297*4882a593Smuzhiyun /* set the reference per ring */
1298*4882a593Smuzhiyun ref_tag_tbl[log_level_tbl[i].tag] |= (1 << ring_id);
1299*4882a593Smuzhiyun }
1300*4882a593Smuzhiyun set = (ref_tag_tbl[log_level_tbl[i].tag])? 1 : 0;
1301*4882a593Smuzhiyun DHD_DBGIF(("%s TAG(%s) is %s for the ring(%s)\n", __FUNCTION__,
1302*4882a593Smuzhiyun log_level_tbl[i].desc, (set)? "SET" : "CLEAR", ring->name));
1303*4882a593Smuzhiyun dhd_dbg_set_event_log_tag(dhdp, log_level_tbl[i].tag, set);
1304*4882a593Smuzhiyun }
1305*4882a593Smuzhiyun return BCME_OK;
1306*4882a593Smuzhiyun }
1307*4882a593Smuzhiyun
1308*4882a593Smuzhiyun int
__dhd_dbg_get_ring_status(dhd_dbg_ring_t * ring,dhd_dbg_ring_status_t * get_ring_status)1309*4882a593Smuzhiyun __dhd_dbg_get_ring_status(dhd_dbg_ring_t *ring, dhd_dbg_ring_status_t *get_ring_status)
1310*4882a593Smuzhiyun {
1311*4882a593Smuzhiyun dhd_dbg_ring_status_t ring_status;
1312*4882a593Smuzhiyun int ret = BCME_OK;
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun if (ring == NULL) {
1315*4882a593Smuzhiyun return BCME_BADADDR;
1316*4882a593Smuzhiyun }
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun bzero(&ring_status, sizeof(dhd_dbg_ring_status_t));
1319*4882a593Smuzhiyun RING_STAT_TO_STATUS(ring, ring_status);
1320*4882a593Smuzhiyun *get_ring_status = ring_status;
1321*4882a593Smuzhiyun
1322*4882a593Smuzhiyun return ret;
1323*4882a593Smuzhiyun }
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun /*
1326*4882a593Smuzhiyun * dhd_dbg_get_ring_status : get the ring status from the coresponding ring buffer
1327*4882a593Smuzhiyun * Return: An error code or 0 on success.
1328*4882a593Smuzhiyun */
1329*4882a593Smuzhiyun
1330*4882a593Smuzhiyun int
dhd_dbg_get_ring_status(dhd_pub_t * dhdp,int ring_id,dhd_dbg_ring_status_t * dbg_ring_status)1331*4882a593Smuzhiyun dhd_dbg_get_ring_status(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_status_t *dbg_ring_status)
1332*4882a593Smuzhiyun {
1333*4882a593Smuzhiyun int ret = BCME_OK;
1334*4882a593Smuzhiyun int id = 0;
1335*4882a593Smuzhiyun dhd_dbg_t *dbg;
1336*4882a593Smuzhiyun dhd_dbg_ring_t *dbg_ring;
1337*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg)
1338*4882a593Smuzhiyun return BCME_BADADDR;
1339*4882a593Smuzhiyun dbg = dhdp->dbg;
1340*4882a593Smuzhiyun
1341*4882a593Smuzhiyun for (id = DEBUG_RING_ID_INVALID + 1; id < DEBUG_RING_ID_MAX; id++) {
1342*4882a593Smuzhiyun dbg_ring = &dbg->dbg_rings[id];
1343*4882a593Smuzhiyun if (VALID_RING(dbg_ring->id) && (dbg_ring->id == ring_id)) {
1344*4882a593Smuzhiyun __dhd_dbg_get_ring_status(dbg_ring, dbg_ring_status);
1345*4882a593Smuzhiyun break;
1346*4882a593Smuzhiyun }
1347*4882a593Smuzhiyun }
1348*4882a593Smuzhiyun if (!VALID_RING(id)) {
1349*4882a593Smuzhiyun DHD_ERROR(("%s : cannot find the ring_id : %d\n", __FUNCTION__, ring_id));
1350*4882a593Smuzhiyun ret = BCME_NOTFOUND;
1351*4882a593Smuzhiyun }
1352*4882a593Smuzhiyun return ret;
1353*4882a593Smuzhiyun }
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun #ifdef SHOW_LOGTRACE
1356*4882a593Smuzhiyun void
dhd_dbg_read_ring_into_trace_buf(dhd_dbg_ring_t * ring,trace_buf_info_t * trace_buf_info)1357*4882a593Smuzhiyun dhd_dbg_read_ring_into_trace_buf(dhd_dbg_ring_t *ring, trace_buf_info_t *trace_buf_info)
1358*4882a593Smuzhiyun {
1359*4882a593Smuzhiyun dhd_dbg_ring_status_t ring_status;
1360*4882a593Smuzhiyun uint32 rlen = 0;
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun rlen = dhd_dbg_ring_pull_single(ring, trace_buf_info->buf, TRACE_LOG_BUF_MAX_SIZE, TRUE);
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun trace_buf_info->size = rlen;
1365*4882a593Smuzhiyun trace_buf_info->availability = NEXT_BUF_NOT_AVAIL;
1366*4882a593Smuzhiyun if (rlen == 0) {
1367*4882a593Smuzhiyun trace_buf_info->availability = BUF_NOT_AVAILABLE;
1368*4882a593Smuzhiyun return;
1369*4882a593Smuzhiyun }
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun __dhd_dbg_get_ring_status(ring, &ring_status);
1372*4882a593Smuzhiyun
1373*4882a593Smuzhiyun if (ring_status.written_bytes != ring_status.read_bytes) {
1374*4882a593Smuzhiyun trace_buf_info->availability = NEXT_BUF_AVAIL;
1375*4882a593Smuzhiyun }
1376*4882a593Smuzhiyun }
1377*4882a593Smuzhiyun #endif /* SHOW_LOGTRACE */
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun /*
1380*4882a593Smuzhiyun * dhd_dbg_find_ring_id : return ring_id based on ring_name
1381*4882a593Smuzhiyun * Return: An invalid ring id for failure or valid ring id on success.
1382*4882a593Smuzhiyun */
1383*4882a593Smuzhiyun
1384*4882a593Smuzhiyun int
dhd_dbg_find_ring_id(dhd_pub_t * dhdp,char * ring_name)1385*4882a593Smuzhiyun dhd_dbg_find_ring_id(dhd_pub_t *dhdp, char *ring_name)
1386*4882a593Smuzhiyun {
1387*4882a593Smuzhiyun int id;
1388*4882a593Smuzhiyun dhd_dbg_t *dbg;
1389*4882a593Smuzhiyun dhd_dbg_ring_t *ring;
1390*4882a593Smuzhiyun
1391*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg)
1392*4882a593Smuzhiyun return BCME_BADADDR;
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun dbg = dhdp->dbg;
1395*4882a593Smuzhiyun for (id = DEBUG_RING_ID_INVALID + 1; id < DEBUG_RING_ID_MAX; id++) {
1396*4882a593Smuzhiyun ring = &dbg->dbg_rings[id];
1397*4882a593Smuzhiyun if (!strncmp((char *)ring->name, ring_name, sizeof(ring->name) - 1))
1398*4882a593Smuzhiyun break;
1399*4882a593Smuzhiyun }
1400*4882a593Smuzhiyun return id;
1401*4882a593Smuzhiyun }
1402*4882a593Smuzhiyun
1403*4882a593Smuzhiyun /*
1404*4882a593Smuzhiyun * dhd_dbg_get_priv : get the private data of dhd dbugability module
1405*4882a593Smuzhiyun * Return : An NULL on failure or valid data address
1406*4882a593Smuzhiyun */
1407*4882a593Smuzhiyun void *
dhd_dbg_get_priv(dhd_pub_t * dhdp)1408*4882a593Smuzhiyun dhd_dbg_get_priv(dhd_pub_t *dhdp)
1409*4882a593Smuzhiyun {
1410*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg)
1411*4882a593Smuzhiyun return NULL;
1412*4882a593Smuzhiyun return dhdp->dbg->private;
1413*4882a593Smuzhiyun }
1414*4882a593Smuzhiyun
1415*4882a593Smuzhiyun /*
1416*4882a593Smuzhiyun * dhd_dbg_start : start and stop All of Ring buffers
1417*4882a593Smuzhiyun * Return: An error code or 0 on success.
1418*4882a593Smuzhiyun */
1419*4882a593Smuzhiyun int
dhd_dbg_start(dhd_pub_t * dhdp,bool start)1420*4882a593Smuzhiyun dhd_dbg_start(dhd_pub_t *dhdp, bool start)
1421*4882a593Smuzhiyun {
1422*4882a593Smuzhiyun int ret = BCME_OK;
1423*4882a593Smuzhiyun int ring_id;
1424*4882a593Smuzhiyun dhd_dbg_t *dbg;
1425*4882a593Smuzhiyun dhd_dbg_ring_t *dbg_ring;
1426*4882a593Smuzhiyun if (!dhdp)
1427*4882a593Smuzhiyun return BCME_BADARG;
1428*4882a593Smuzhiyun dbg = dhdp->dbg;
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) {
1431*4882a593Smuzhiyun dbg_ring = &dbg->dbg_rings[ring_id];
1432*4882a593Smuzhiyun if (!start) {
1433*4882a593Smuzhiyun if (VALID_RING(dbg_ring->id)) {
1434*4882a593Smuzhiyun dhd_dbg_ring_start(dbg_ring);
1435*4882a593Smuzhiyun }
1436*4882a593Smuzhiyun }
1437*4882a593Smuzhiyun }
1438*4882a593Smuzhiyun return ret;
1439*4882a593Smuzhiyun }
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun /*
1442*4882a593Smuzhiyun * dhd_dbg_send_urgent_evt: send the health check evt to Upper layer
1443*4882a593Smuzhiyun *
1444*4882a593Smuzhiyun * Return: An error code or 0 on success.
1445*4882a593Smuzhiyun */
1446*4882a593Smuzhiyun
1447*4882a593Smuzhiyun int
dhd_dbg_send_urgent_evt(dhd_pub_t * dhdp,const void * data,const uint32 len)1448*4882a593Smuzhiyun dhd_dbg_send_urgent_evt(dhd_pub_t *dhdp, const void *data, const uint32 len)
1449*4882a593Smuzhiyun {
1450*4882a593Smuzhiyun dhd_dbg_t *dbg;
1451*4882a593Smuzhiyun int ret = BCME_OK;
1452*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg)
1453*4882a593Smuzhiyun return BCME_BADADDR;
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun dbg = dhdp->dbg;
1456*4882a593Smuzhiyun if (dbg->urgent_notifier) {
1457*4882a593Smuzhiyun dbg->urgent_notifier(dhdp, data, len);
1458*4882a593Smuzhiyun }
1459*4882a593Smuzhiyun return ret;
1460*4882a593Smuzhiyun }
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun #if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING)
1463*4882a593Smuzhiyun uint32
__dhd_dbg_pkt_hash(uintptr_t pkt,uint32 pktid)1464*4882a593Smuzhiyun __dhd_dbg_pkt_hash(uintptr_t pkt, uint32 pktid)
1465*4882a593Smuzhiyun {
1466*4882a593Smuzhiyun uint32 __pkt;
1467*4882a593Smuzhiyun uint32 __pktid;
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun __pkt = ((int)pkt) >= 0 ? (2 * pkt) : (-2 * pkt - 1);
1470*4882a593Smuzhiyun __pktid = ((int)pktid) >= 0 ? (2 * pktid) : (-2 * pktid - 1);
1471*4882a593Smuzhiyun
1472*4882a593Smuzhiyun return (__pkt >= __pktid ? (__pkt * __pkt + __pkt + __pktid) :
1473*4882a593Smuzhiyun (__pkt + __pktid * __pktid));
1474*4882a593Smuzhiyun }
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun #define __TIMESPEC_TO_US(ts) \
1477*4882a593Smuzhiyun (((uint32)(ts).tv_sec * USEC_PER_SEC) + ((ts).tv_nsec / NSEC_PER_USEC))
1478*4882a593Smuzhiyun
1479*4882a593Smuzhiyun uint32
__dhd_dbg_driver_ts_usec(void)1480*4882a593Smuzhiyun __dhd_dbg_driver_ts_usec(void)
1481*4882a593Smuzhiyun {
1482*4882a593Smuzhiyun struct osl_timespec ts;
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun osl_get_monotonic_boottime(&ts);
1485*4882a593Smuzhiyun return ((uint32)(__TIMESPEC_TO_US(ts)));
1486*4882a593Smuzhiyun }
1487*4882a593Smuzhiyun
1488*4882a593Smuzhiyun wifi_tx_packet_fate
__dhd_dbg_map_tx_status_to_pkt_fate(uint16 status)1489*4882a593Smuzhiyun __dhd_dbg_map_tx_status_to_pkt_fate(uint16 status)
1490*4882a593Smuzhiyun {
1491*4882a593Smuzhiyun wifi_tx_packet_fate pkt_fate;
1492*4882a593Smuzhiyun
1493*4882a593Smuzhiyun switch (status) {
1494*4882a593Smuzhiyun case WLFC_CTL_PKTFLAG_DISCARD:
1495*4882a593Smuzhiyun pkt_fate = TX_PKT_FATE_ACKED;
1496*4882a593Smuzhiyun break;
1497*4882a593Smuzhiyun case WLFC_CTL_PKTFLAG_D11SUPPRESS:
1498*4882a593Smuzhiyun /* intensional fall through */
1499*4882a593Smuzhiyun case WLFC_CTL_PKTFLAG_WLSUPPRESS:
1500*4882a593Smuzhiyun pkt_fate = TX_PKT_FATE_FW_QUEUED;
1501*4882a593Smuzhiyun break;
1502*4882a593Smuzhiyun case WLFC_CTL_PKTFLAG_TOSSED_BYWLC:
1503*4882a593Smuzhiyun pkt_fate = TX_PKT_FATE_FW_DROP_INVALID;
1504*4882a593Smuzhiyun break;
1505*4882a593Smuzhiyun case WLFC_CTL_PKTFLAG_DISCARD_NOACK:
1506*4882a593Smuzhiyun pkt_fate = TX_PKT_FATE_SENT;
1507*4882a593Smuzhiyun break;
1508*4882a593Smuzhiyun case WLFC_CTL_PKTFLAG_EXPIRED:
1509*4882a593Smuzhiyun pkt_fate = TX_PKT_FATE_FW_DROP_EXPTIME;
1510*4882a593Smuzhiyun break;
1511*4882a593Smuzhiyun #ifndef OEM_ANDROID
1512*4882a593Smuzhiyun case WLFC_CTL_PKTFLAG_MKTFREE:
1513*4882a593Smuzhiyun pkt_fate = TX_PKT_FATE_FW_PKT_FREE;
1514*4882a593Smuzhiyun break;
1515*4882a593Smuzhiyun #endif /* !OEM_ANDROID */
1516*4882a593Smuzhiyun default:
1517*4882a593Smuzhiyun pkt_fate = TX_PKT_FATE_FW_DROP_OTHER;
1518*4882a593Smuzhiyun break;
1519*4882a593Smuzhiyun }
1520*4882a593Smuzhiyun
1521*4882a593Smuzhiyun return pkt_fate;
1522*4882a593Smuzhiyun }
1523*4882a593Smuzhiyun #endif /* DBG_PKT_MON || DHD_PKT_LOGGING */
1524*4882a593Smuzhiyun
1525*4882a593Smuzhiyun #ifdef DBG_PKT_MON
1526*4882a593Smuzhiyun static int
__dhd_dbg_free_tx_pkts(dhd_pub_t * dhdp,dhd_dbg_tx_info_t * tx_pkts,uint16 pkt_count)1527*4882a593Smuzhiyun __dhd_dbg_free_tx_pkts(dhd_pub_t *dhdp, dhd_dbg_tx_info_t *tx_pkts,
1528*4882a593Smuzhiyun uint16 pkt_count)
1529*4882a593Smuzhiyun {
1530*4882a593Smuzhiyun uint16 count;
1531*4882a593Smuzhiyun
1532*4882a593Smuzhiyun count = 0;
1533*4882a593Smuzhiyun while ((count < pkt_count) && tx_pkts) {
1534*4882a593Smuzhiyun if (tx_pkts->info.pkt) {
1535*4882a593Smuzhiyun PKTFREE(dhdp->osh, tx_pkts->info.pkt, TRUE);
1536*4882a593Smuzhiyun }
1537*4882a593Smuzhiyun tx_pkts++;
1538*4882a593Smuzhiyun count++;
1539*4882a593Smuzhiyun }
1540*4882a593Smuzhiyun
1541*4882a593Smuzhiyun return BCME_OK;
1542*4882a593Smuzhiyun }
1543*4882a593Smuzhiyun
1544*4882a593Smuzhiyun static int
__dhd_dbg_free_rx_pkts(dhd_pub_t * dhdp,dhd_dbg_rx_info_t * rx_pkts,uint16 pkt_count)1545*4882a593Smuzhiyun __dhd_dbg_free_rx_pkts(dhd_pub_t *dhdp, dhd_dbg_rx_info_t *rx_pkts,
1546*4882a593Smuzhiyun uint16 pkt_count)
1547*4882a593Smuzhiyun {
1548*4882a593Smuzhiyun uint16 count;
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun count = 0;
1551*4882a593Smuzhiyun while ((count < pkt_count) && rx_pkts) {
1552*4882a593Smuzhiyun if (rx_pkts->info.pkt) {
1553*4882a593Smuzhiyun PKTFREE(dhdp->osh, rx_pkts->info.pkt, TRUE);
1554*4882a593Smuzhiyun }
1555*4882a593Smuzhiyun rx_pkts++;
1556*4882a593Smuzhiyun count++;
1557*4882a593Smuzhiyun }
1558*4882a593Smuzhiyun
1559*4882a593Smuzhiyun return BCME_OK;
1560*4882a593Smuzhiyun }
1561*4882a593Smuzhiyun
1562*4882a593Smuzhiyun void
__dhd_dbg_dump_pkt_info(dhd_pub_t * dhdp,dhd_dbg_pkt_info_t * info)1563*4882a593Smuzhiyun __dhd_dbg_dump_pkt_info(dhd_pub_t *dhdp, dhd_dbg_pkt_info_t *info)
1564*4882a593Smuzhiyun {
1565*4882a593Smuzhiyun if (DHD_PKT_MON_DUMP_ON()) {
1566*4882a593Smuzhiyun DHD_PKT_MON(("payload type = %d\n", info->payload_type));
1567*4882a593Smuzhiyun DHD_PKT_MON(("driver ts = %u\n", info->driver_ts));
1568*4882a593Smuzhiyun DHD_PKT_MON(("firmware ts = %u\n", info->firmware_ts));
1569*4882a593Smuzhiyun DHD_PKT_MON(("packet hash = %u\n", info->pkt_hash));
1570*4882a593Smuzhiyun DHD_PKT_MON(("packet length = %zu\n", info->pkt_len));
1571*4882a593Smuzhiyun DHD_PKT_MON(("packet address = %p\n", info->pkt));
1572*4882a593Smuzhiyun DHD_PKT_MON(("packet data = \n"));
1573*4882a593Smuzhiyun if (DHD_PKT_MON_ON()) {
1574*4882a593Smuzhiyun prhex(NULL, PKTDATA(dhdp->osh, info->pkt), info->pkt_len);
1575*4882a593Smuzhiyun }
1576*4882a593Smuzhiyun }
1577*4882a593Smuzhiyun }
1578*4882a593Smuzhiyun
1579*4882a593Smuzhiyun void
__dhd_dbg_dump_tx_pkt_info(dhd_pub_t * dhdp,dhd_dbg_tx_info_t * tx_pkt,uint16 count)1580*4882a593Smuzhiyun __dhd_dbg_dump_tx_pkt_info(dhd_pub_t *dhdp, dhd_dbg_tx_info_t *tx_pkt,
1581*4882a593Smuzhiyun uint16 count)
1582*4882a593Smuzhiyun {
1583*4882a593Smuzhiyun if (DHD_PKT_MON_DUMP_ON()) {
1584*4882a593Smuzhiyun DHD_PKT_MON(("\nTX (count: %d)\n", ++count));
1585*4882a593Smuzhiyun DHD_PKT_MON(("packet fate = %d\n", tx_pkt->fate));
1586*4882a593Smuzhiyun __dhd_dbg_dump_pkt_info(dhdp, &tx_pkt->info);
1587*4882a593Smuzhiyun }
1588*4882a593Smuzhiyun }
1589*4882a593Smuzhiyun
1590*4882a593Smuzhiyun void
__dhd_dbg_dump_rx_pkt_info(dhd_pub_t * dhdp,dhd_dbg_rx_info_t * rx_pkt,uint16 count)1591*4882a593Smuzhiyun __dhd_dbg_dump_rx_pkt_info(dhd_pub_t *dhdp, dhd_dbg_rx_info_t *rx_pkt,
1592*4882a593Smuzhiyun uint16 count)
1593*4882a593Smuzhiyun {
1594*4882a593Smuzhiyun if (DHD_PKT_MON_DUMP_ON()) {
1595*4882a593Smuzhiyun DHD_PKT_MON(("\nRX (count: %d)\n", ++count));
1596*4882a593Smuzhiyun DHD_PKT_MON(("packet fate = %d\n", rx_pkt->fate));
1597*4882a593Smuzhiyun __dhd_dbg_dump_pkt_info(dhdp, &rx_pkt->info);
1598*4882a593Smuzhiyun }
1599*4882a593Smuzhiyun }
1600*4882a593Smuzhiyun
1601*4882a593Smuzhiyun int
dhd_dbg_attach_pkt_monitor(dhd_pub_t * dhdp,dbg_mon_tx_pkts_t tx_pkt_mon,dbg_mon_tx_status_t tx_status_mon,dbg_mon_rx_pkts_t rx_pkt_mon)1602*4882a593Smuzhiyun dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp,
1603*4882a593Smuzhiyun dbg_mon_tx_pkts_t tx_pkt_mon,
1604*4882a593Smuzhiyun dbg_mon_tx_status_t tx_status_mon,
1605*4882a593Smuzhiyun dbg_mon_rx_pkts_t rx_pkt_mon)
1606*4882a593Smuzhiyun {
1607*4882a593Smuzhiyun
1608*4882a593Smuzhiyun dhd_dbg_tx_report_t *tx_report = NULL;
1609*4882a593Smuzhiyun dhd_dbg_rx_report_t *rx_report = NULL;
1610*4882a593Smuzhiyun dhd_dbg_tx_info_t *tx_pkts = NULL;
1611*4882a593Smuzhiyun dhd_dbg_rx_info_t *rx_pkts = NULL;
1612*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_pkt_state;
1613*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_status_state;
1614*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t rx_pkt_state;
1615*4882a593Smuzhiyun uint32 alloc_len;
1616*4882a593Smuzhiyun int ret = BCME_OK;
1617*4882a593Smuzhiyun unsigned long flags;
1618*4882a593Smuzhiyun
1619*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
1620*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1621*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
1622*4882a593Smuzhiyun return -EINVAL;
1623*4882a593Smuzhiyun }
1624*4882a593Smuzhiyun
1625*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1626*4882a593Smuzhiyun tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1627*4882a593Smuzhiyun tx_status_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1628*4882a593Smuzhiyun rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1629*4882a593Smuzhiyun
1630*4882a593Smuzhiyun if (PKT_MON_ATTACHED(tx_pkt_state) || PKT_MON_ATTACHED(tx_status_state) ||
1631*4882a593Smuzhiyun PKT_MON_ATTACHED(rx_pkt_state)) {
1632*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor is already attached, "
1633*4882a593Smuzhiyun "tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
1634*4882a593Smuzhiyun __FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
1635*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1636*4882a593Smuzhiyun /* return success as the intention was to initialize packet monitor */
1637*4882a593Smuzhiyun return BCME_OK;
1638*4882a593Smuzhiyun }
1639*4882a593Smuzhiyun
1640*4882a593Smuzhiyun /* allocate and initialize tx packet monitoring */
1641*4882a593Smuzhiyun alloc_len = sizeof(*tx_report);
1642*4882a593Smuzhiyun tx_report = (dhd_dbg_tx_report_t *)MALLOCZ(dhdp->osh, alloc_len);
1643*4882a593Smuzhiyun if (unlikely(!tx_report)) {
1644*4882a593Smuzhiyun DHD_ERROR(("%s(): could not allocate memory for - "
1645*4882a593Smuzhiyun "dhd_dbg_tx_report_t\n", __FUNCTION__));
1646*4882a593Smuzhiyun ret = -ENOMEM;
1647*4882a593Smuzhiyun goto fail;
1648*4882a593Smuzhiyun }
1649*4882a593Smuzhiyun
1650*4882a593Smuzhiyun alloc_len = (sizeof(*tx_pkts) * MAX_FATE_LOG_LEN);
1651*4882a593Smuzhiyun tx_pkts = (dhd_dbg_tx_info_t *)MALLOCZ(dhdp->osh, alloc_len);
1652*4882a593Smuzhiyun if (unlikely(!tx_pkts)) {
1653*4882a593Smuzhiyun DHD_ERROR(("%s(): could not allocate memory for - "
1654*4882a593Smuzhiyun "dhd_dbg_tx_info_t\n", __FUNCTION__));
1655*4882a593Smuzhiyun ret = -ENOMEM;
1656*4882a593Smuzhiyun goto fail;
1657*4882a593Smuzhiyun }
1658*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_report = tx_report;
1659*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_report->tx_pkts = tx_pkts;
1660*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_mon = tx_pkt_mon;
1661*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_mon = tx_status_mon;
1662*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_ATTACHED;
1663*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_ATTACHED;
1664*4882a593Smuzhiyun
1665*4882a593Smuzhiyun /* allocate and initialze rx packet monitoring */
1666*4882a593Smuzhiyun alloc_len = sizeof(*rx_report);
1667*4882a593Smuzhiyun rx_report = (dhd_dbg_rx_report_t *)MALLOCZ(dhdp->osh, alloc_len);
1668*4882a593Smuzhiyun if (unlikely(!rx_report)) {
1669*4882a593Smuzhiyun DHD_ERROR(("%s(): could not allocate memory for - "
1670*4882a593Smuzhiyun "dhd_dbg_rx_report_t\n", __FUNCTION__));
1671*4882a593Smuzhiyun ret = -ENOMEM;
1672*4882a593Smuzhiyun goto fail;
1673*4882a593Smuzhiyun }
1674*4882a593Smuzhiyun
1675*4882a593Smuzhiyun alloc_len = (sizeof(*rx_pkts) * MAX_FATE_LOG_LEN);
1676*4882a593Smuzhiyun rx_pkts = (dhd_dbg_rx_info_t *)MALLOCZ(dhdp->osh, alloc_len);
1677*4882a593Smuzhiyun if (unlikely(!rx_pkts)) {
1678*4882a593Smuzhiyun DHD_ERROR(("%s(): could not allocate memory for - "
1679*4882a593Smuzhiyun "dhd_dbg_rx_info_t\n", __FUNCTION__));
1680*4882a593Smuzhiyun ret = -ENOMEM;
1681*4882a593Smuzhiyun goto fail;
1682*4882a593Smuzhiyun }
1683*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_report = rx_report;
1684*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_report->rx_pkts = rx_pkts;
1685*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_mon = rx_pkt_mon;
1686*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_ATTACHED;
1687*4882a593Smuzhiyun
1688*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1689*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor attach succeeded\n", __FUNCTION__));
1690*4882a593Smuzhiyun return ret;
1691*4882a593Smuzhiyun
1692*4882a593Smuzhiyun fail:
1693*4882a593Smuzhiyun /* tx packet monitoring */
1694*4882a593Smuzhiyun if (tx_pkts) {
1695*4882a593Smuzhiyun alloc_len = (sizeof(*tx_pkts) * MAX_FATE_LOG_LEN);
1696*4882a593Smuzhiyun MFREE(dhdp->osh, tx_pkts, alloc_len);
1697*4882a593Smuzhiyun }
1698*4882a593Smuzhiyun if (tx_report) {
1699*4882a593Smuzhiyun alloc_len = sizeof(*tx_report);
1700*4882a593Smuzhiyun MFREE(dhdp->osh, tx_report, alloc_len);
1701*4882a593Smuzhiyun }
1702*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_report = NULL;
1703*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_report->tx_pkts = NULL;
1704*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_mon = NULL;
1705*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_mon = NULL;
1706*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_DETACHED;
1707*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_DETACHED;
1708*4882a593Smuzhiyun
1709*4882a593Smuzhiyun /* rx packet monitoring */
1710*4882a593Smuzhiyun if (rx_pkts) {
1711*4882a593Smuzhiyun alloc_len = (sizeof(*rx_pkts) * MAX_FATE_LOG_LEN);
1712*4882a593Smuzhiyun MFREE(dhdp->osh, rx_pkts, alloc_len);
1713*4882a593Smuzhiyun }
1714*4882a593Smuzhiyun if (rx_report) {
1715*4882a593Smuzhiyun alloc_len = sizeof(*rx_report);
1716*4882a593Smuzhiyun MFREE(dhdp->osh, rx_report, alloc_len);
1717*4882a593Smuzhiyun }
1718*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_report = NULL;
1719*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_report->rx_pkts = NULL;
1720*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_mon = NULL;
1721*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_DETACHED;
1722*4882a593Smuzhiyun
1723*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1724*4882a593Smuzhiyun DHD_ERROR(("%s(): packet monitor attach failed\n", __FUNCTION__));
1725*4882a593Smuzhiyun return ret;
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun
1728*4882a593Smuzhiyun int
dhd_dbg_start_pkt_monitor(dhd_pub_t * dhdp)1729*4882a593Smuzhiyun dhd_dbg_start_pkt_monitor(dhd_pub_t *dhdp)
1730*4882a593Smuzhiyun {
1731*4882a593Smuzhiyun dhd_dbg_tx_report_t *tx_report;
1732*4882a593Smuzhiyun dhd_dbg_rx_report_t *rx_report;
1733*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_pkt_state;
1734*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_status_state;
1735*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t rx_pkt_state;
1736*4882a593Smuzhiyun unsigned long flags;
1737*4882a593Smuzhiyun
1738*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
1739*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1740*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
1741*4882a593Smuzhiyun return -EINVAL;
1742*4882a593Smuzhiyun }
1743*4882a593Smuzhiyun
1744*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1745*4882a593Smuzhiyun tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1746*4882a593Smuzhiyun tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1747*4882a593Smuzhiyun rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1748*4882a593Smuzhiyun
1749*4882a593Smuzhiyun if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
1750*4882a593Smuzhiyun PKT_MON_DETACHED(rx_pkt_state)) {
1751*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
1752*4882a593Smuzhiyun "tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
1753*4882a593Smuzhiyun __FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
1754*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1755*4882a593Smuzhiyun return -EINVAL;
1756*4882a593Smuzhiyun }
1757*4882a593Smuzhiyun
1758*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STARTING;
1759*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STARTING;
1760*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STARTING;
1761*4882a593Smuzhiyun
1762*4882a593Smuzhiyun tx_report = dhdp->dbg->pkt_mon.tx_report;
1763*4882a593Smuzhiyun rx_report = dhdp->dbg->pkt_mon.rx_report;
1764*4882a593Smuzhiyun if (!tx_report || !rx_report) {
1765*4882a593Smuzhiyun DHD_PKT_MON(("%s(): tx_report=%p, rx_report=%p\n",
1766*4882a593Smuzhiyun __FUNCTION__, tx_report, rx_report));
1767*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1768*4882a593Smuzhiyun return -EINVAL;
1769*4882a593Smuzhiyun }
1770*4882a593Smuzhiyun
1771*4882a593Smuzhiyun tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1772*4882a593Smuzhiyun tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1773*4882a593Smuzhiyun rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1774*4882a593Smuzhiyun
1775*4882a593Smuzhiyun /* Safe to free packets as state pkt_state is STARTING */
1776*4882a593Smuzhiyun __dhd_dbg_free_tx_pkts(dhdp, tx_report->tx_pkts, tx_report->pkt_pos);
1777*4882a593Smuzhiyun
1778*4882a593Smuzhiyun __dhd_dbg_free_rx_pkts(dhdp, rx_report->rx_pkts, rx_report->pkt_pos);
1779*4882a593Smuzhiyun
1780*4882a593Smuzhiyun /* reset array postion */
1781*4882a593Smuzhiyun tx_report->pkt_pos = 0;
1782*4882a593Smuzhiyun tx_report->status_pos = 0;
1783*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STARTED;
1784*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STARTED;
1785*4882a593Smuzhiyun
1786*4882a593Smuzhiyun rx_report->pkt_pos = 0;
1787*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STARTED;
1788*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1789*4882a593Smuzhiyun
1790*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor started\n", __FUNCTION__));
1791*4882a593Smuzhiyun return BCME_OK;
1792*4882a593Smuzhiyun }
1793*4882a593Smuzhiyun
1794*4882a593Smuzhiyun int
dhd_dbg_monitor_tx_pkts(dhd_pub_t * dhdp,void * pkt,uint32 pktid)1795*4882a593Smuzhiyun dhd_dbg_monitor_tx_pkts(dhd_pub_t *dhdp, void *pkt, uint32 pktid)
1796*4882a593Smuzhiyun {
1797*4882a593Smuzhiyun dhd_dbg_tx_report_t *tx_report;
1798*4882a593Smuzhiyun dhd_dbg_tx_info_t *tx_pkts;
1799*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_pkt_state;
1800*4882a593Smuzhiyun uint32 pkt_hash, driver_ts;
1801*4882a593Smuzhiyun uint16 pkt_pos;
1802*4882a593Smuzhiyun unsigned long flags;
1803*4882a593Smuzhiyun
1804*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
1805*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1806*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
1807*4882a593Smuzhiyun return -EINVAL;
1808*4882a593Smuzhiyun }
1809*4882a593Smuzhiyun
1810*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1811*4882a593Smuzhiyun tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1812*4882a593Smuzhiyun if (PKT_MON_STARTED(tx_pkt_state)) {
1813*4882a593Smuzhiyun tx_report = dhdp->dbg->pkt_mon.tx_report;
1814*4882a593Smuzhiyun pkt_pos = tx_report->pkt_pos;
1815*4882a593Smuzhiyun
1816*4882a593Smuzhiyun if (!PKT_MON_PKT_FULL(pkt_pos)) {
1817*4882a593Smuzhiyun tx_pkts = tx_report->tx_pkts;
1818*4882a593Smuzhiyun pkt_hash = __dhd_dbg_pkt_hash((uintptr_t)pkt, pktid);
1819*4882a593Smuzhiyun driver_ts = __dhd_dbg_driver_ts_usec();
1820*4882a593Smuzhiyun
1821*4882a593Smuzhiyun tx_pkts[pkt_pos].info.pkt = PKTDUP(dhdp->osh, pkt);
1822*4882a593Smuzhiyun tx_pkts[pkt_pos].info.pkt_len = PKTLEN(dhdp->osh, pkt);
1823*4882a593Smuzhiyun tx_pkts[pkt_pos].info.pkt_hash = pkt_hash;
1824*4882a593Smuzhiyun tx_pkts[pkt_pos].info.driver_ts = driver_ts;
1825*4882a593Smuzhiyun tx_pkts[pkt_pos].info.firmware_ts = 0U;
1826*4882a593Smuzhiyun tx_pkts[pkt_pos].info.payload_type = FRAME_TYPE_ETHERNET_II;
1827*4882a593Smuzhiyun tx_pkts[pkt_pos].fate = TX_PKT_FATE_DRV_QUEUED;
1828*4882a593Smuzhiyun
1829*4882a593Smuzhiyun tx_report->pkt_pos++;
1830*4882a593Smuzhiyun } else {
1831*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STOPPED;
1832*4882a593Smuzhiyun DHD_PKT_MON(("%s(): tx pkt logging stopped, reached "
1833*4882a593Smuzhiyun "max limit\n", __FUNCTION__));
1834*4882a593Smuzhiyun }
1835*4882a593Smuzhiyun }
1836*4882a593Smuzhiyun
1837*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1838*4882a593Smuzhiyun return BCME_OK;
1839*4882a593Smuzhiyun }
1840*4882a593Smuzhiyun
1841*4882a593Smuzhiyun int
dhd_dbg_monitor_tx_status(dhd_pub_t * dhdp,void * pkt,uint32 pktid,uint16 status)1842*4882a593Smuzhiyun dhd_dbg_monitor_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid,
1843*4882a593Smuzhiyun uint16 status)
1844*4882a593Smuzhiyun {
1845*4882a593Smuzhiyun dhd_dbg_tx_report_t *tx_report;
1846*4882a593Smuzhiyun dhd_dbg_tx_info_t *tx_pkt;
1847*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_status_state;
1848*4882a593Smuzhiyun wifi_tx_packet_fate pkt_fate;
1849*4882a593Smuzhiyun uint32 pkt_hash, temp_hash;
1850*4882a593Smuzhiyun uint16 pkt_pos, status_pos;
1851*4882a593Smuzhiyun int16 count;
1852*4882a593Smuzhiyun bool found = FALSE;
1853*4882a593Smuzhiyun unsigned long flags;
1854*4882a593Smuzhiyun
1855*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
1856*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1857*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
1858*4882a593Smuzhiyun return -EINVAL;
1859*4882a593Smuzhiyun }
1860*4882a593Smuzhiyun
1861*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1862*4882a593Smuzhiyun tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1863*4882a593Smuzhiyun if (PKT_MON_STARTED(tx_status_state)) {
1864*4882a593Smuzhiyun tx_report = dhdp->dbg->pkt_mon.tx_report;
1865*4882a593Smuzhiyun pkt_pos = tx_report->pkt_pos;
1866*4882a593Smuzhiyun status_pos = tx_report->status_pos;
1867*4882a593Smuzhiyun
1868*4882a593Smuzhiyun if (!PKT_MON_STATUS_FULL(pkt_pos, status_pos)) {
1869*4882a593Smuzhiyun pkt_hash = __dhd_dbg_pkt_hash((uintptr_t)pkt, pktid);
1870*4882a593Smuzhiyun pkt_fate = __dhd_dbg_map_tx_status_to_pkt_fate(status);
1871*4882a593Smuzhiyun
1872*4882a593Smuzhiyun /* best bet (in-order tx completion) */
1873*4882a593Smuzhiyun count = status_pos;
1874*4882a593Smuzhiyun tx_pkt = (((dhd_dbg_tx_info_t *)tx_report->tx_pkts) + status_pos);
1875*4882a593Smuzhiyun while ((count < pkt_pos) && tx_pkt) {
1876*4882a593Smuzhiyun temp_hash = tx_pkt->info.pkt_hash;
1877*4882a593Smuzhiyun if (temp_hash == pkt_hash) {
1878*4882a593Smuzhiyun tx_pkt->fate = pkt_fate;
1879*4882a593Smuzhiyun tx_report->status_pos++;
1880*4882a593Smuzhiyun found = TRUE;
1881*4882a593Smuzhiyun break;
1882*4882a593Smuzhiyun }
1883*4882a593Smuzhiyun tx_pkt++;
1884*4882a593Smuzhiyun count++;
1885*4882a593Smuzhiyun }
1886*4882a593Smuzhiyun
1887*4882a593Smuzhiyun /* search until beginning (handles out-of-order completion) */
1888*4882a593Smuzhiyun if (!found) {
1889*4882a593Smuzhiyun count = status_pos - 1;
1890*4882a593Smuzhiyun tx_pkt = (((dhd_dbg_tx_info_t *)tx_report->tx_pkts) + count);
1891*4882a593Smuzhiyun while ((count >= 0) && tx_pkt) {
1892*4882a593Smuzhiyun temp_hash = tx_pkt->info.pkt_hash;
1893*4882a593Smuzhiyun if (temp_hash == pkt_hash) {
1894*4882a593Smuzhiyun tx_pkt->fate = pkt_fate;
1895*4882a593Smuzhiyun tx_report->status_pos++;
1896*4882a593Smuzhiyun found = TRUE;
1897*4882a593Smuzhiyun break;
1898*4882a593Smuzhiyun }
1899*4882a593Smuzhiyun tx_pkt--;
1900*4882a593Smuzhiyun count--;
1901*4882a593Smuzhiyun }
1902*4882a593Smuzhiyun
1903*4882a593Smuzhiyun if (!found) {
1904*4882a593Smuzhiyun /* still couldn't match tx_status */
1905*4882a593Smuzhiyun DHD_INFO(("%s(): couldn't match tx_status, pkt_pos=%u, "
1906*4882a593Smuzhiyun "status_pos=%u, pkt_fate=%u\n", __FUNCTION__,
1907*4882a593Smuzhiyun pkt_pos, status_pos, pkt_fate));
1908*4882a593Smuzhiyun }
1909*4882a593Smuzhiyun }
1910*4882a593Smuzhiyun } else {
1911*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STOPPED;
1912*4882a593Smuzhiyun DHD_PKT_MON(("%s(): tx_status logging stopped, reached "
1913*4882a593Smuzhiyun "max limit\n", __FUNCTION__));
1914*4882a593Smuzhiyun }
1915*4882a593Smuzhiyun }
1916*4882a593Smuzhiyun
1917*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1918*4882a593Smuzhiyun return BCME_OK;
1919*4882a593Smuzhiyun }
1920*4882a593Smuzhiyun
1921*4882a593Smuzhiyun int
dhd_dbg_monitor_rx_pkts(dhd_pub_t * dhdp,void * pkt)1922*4882a593Smuzhiyun dhd_dbg_monitor_rx_pkts(dhd_pub_t *dhdp, void *pkt)
1923*4882a593Smuzhiyun {
1924*4882a593Smuzhiyun dhd_dbg_rx_report_t *rx_report;
1925*4882a593Smuzhiyun dhd_dbg_rx_info_t *rx_pkts;
1926*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t rx_pkt_state;
1927*4882a593Smuzhiyun uint32 driver_ts;
1928*4882a593Smuzhiyun uint16 pkt_pos;
1929*4882a593Smuzhiyun unsigned long flags;
1930*4882a593Smuzhiyun
1931*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
1932*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1933*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
1934*4882a593Smuzhiyun return -EINVAL;
1935*4882a593Smuzhiyun }
1936*4882a593Smuzhiyun
1937*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1938*4882a593Smuzhiyun rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1939*4882a593Smuzhiyun if (PKT_MON_STARTED(rx_pkt_state)) {
1940*4882a593Smuzhiyun rx_report = dhdp->dbg->pkt_mon.rx_report;
1941*4882a593Smuzhiyun pkt_pos = rx_report->pkt_pos;
1942*4882a593Smuzhiyun
1943*4882a593Smuzhiyun if (!PKT_MON_PKT_FULL(pkt_pos)) {
1944*4882a593Smuzhiyun rx_pkts = rx_report->rx_pkts;
1945*4882a593Smuzhiyun driver_ts = __dhd_dbg_driver_ts_usec();
1946*4882a593Smuzhiyun
1947*4882a593Smuzhiyun rx_pkts[pkt_pos].info.pkt = PKTDUP(dhdp->osh, pkt);
1948*4882a593Smuzhiyun rx_pkts[pkt_pos].info.pkt_len = PKTLEN(dhdp->osh, pkt);
1949*4882a593Smuzhiyun rx_pkts[pkt_pos].info.pkt_hash = 0U;
1950*4882a593Smuzhiyun rx_pkts[pkt_pos].info.driver_ts = driver_ts;
1951*4882a593Smuzhiyun rx_pkts[pkt_pos].info.firmware_ts = 0U;
1952*4882a593Smuzhiyun rx_pkts[pkt_pos].info.payload_type = FRAME_TYPE_ETHERNET_II;
1953*4882a593Smuzhiyun rx_pkts[pkt_pos].fate = RX_PKT_FATE_SUCCESS;
1954*4882a593Smuzhiyun
1955*4882a593Smuzhiyun rx_report->pkt_pos++;
1956*4882a593Smuzhiyun } else {
1957*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STOPPED;
1958*4882a593Smuzhiyun DHD_PKT_MON(("%s(): rx pkt logging stopped, reached "
1959*4882a593Smuzhiyun "max limit\n", __FUNCTION__));
1960*4882a593Smuzhiyun }
1961*4882a593Smuzhiyun }
1962*4882a593Smuzhiyun
1963*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1964*4882a593Smuzhiyun return BCME_OK;
1965*4882a593Smuzhiyun }
1966*4882a593Smuzhiyun
1967*4882a593Smuzhiyun int
dhd_dbg_stop_pkt_monitor(dhd_pub_t * dhdp)1968*4882a593Smuzhiyun dhd_dbg_stop_pkt_monitor(dhd_pub_t *dhdp)
1969*4882a593Smuzhiyun {
1970*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_pkt_state;
1971*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_status_state;
1972*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t rx_pkt_state;
1973*4882a593Smuzhiyun unsigned long flags;
1974*4882a593Smuzhiyun
1975*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
1976*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1977*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
1978*4882a593Smuzhiyun return -EINVAL;
1979*4882a593Smuzhiyun }
1980*4882a593Smuzhiyun
1981*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1982*4882a593Smuzhiyun tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1983*4882a593Smuzhiyun tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1984*4882a593Smuzhiyun rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1985*4882a593Smuzhiyun
1986*4882a593Smuzhiyun if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
1987*4882a593Smuzhiyun PKT_MON_DETACHED(rx_pkt_state)) {
1988*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
1989*4882a593Smuzhiyun "tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
1990*4882a593Smuzhiyun __FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
1991*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1992*4882a593Smuzhiyun return -EINVAL;
1993*4882a593Smuzhiyun }
1994*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STOPPED;
1995*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STOPPED;
1996*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STOPPED;
1997*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1998*4882a593Smuzhiyun
1999*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor stopped\n", __FUNCTION__));
2000*4882a593Smuzhiyun return BCME_OK;
2001*4882a593Smuzhiyun }
2002*4882a593Smuzhiyun
2003*4882a593Smuzhiyun #define __COPY_TO_USER(to, from, n) \
2004*4882a593Smuzhiyun do { \
2005*4882a593Smuzhiyun int __ret; \
2006*4882a593Smuzhiyun __ret = copy_to_user((void __user *)(to), (void *)(from), \
2007*4882a593Smuzhiyun (unsigned long)(n)); \
2008*4882a593Smuzhiyun if (unlikely(__ret)) { \
2009*4882a593Smuzhiyun DHD_ERROR(("%s():%d: copy_to_user failed, ret=%d\n", \
2010*4882a593Smuzhiyun __FUNCTION__, __LINE__, __ret)); \
2011*4882a593Smuzhiyun return __ret; \
2012*4882a593Smuzhiyun } \
2013*4882a593Smuzhiyun } while (0);
2014*4882a593Smuzhiyun
2015*4882a593Smuzhiyun int
dhd_dbg_monitor_get_tx_pkts(dhd_pub_t * dhdp,void __user * user_buf,uint16 req_count,uint16 * resp_count)2016*4882a593Smuzhiyun dhd_dbg_monitor_get_tx_pkts(dhd_pub_t *dhdp, void __user *user_buf,
2017*4882a593Smuzhiyun uint16 req_count, uint16 *resp_count)
2018*4882a593Smuzhiyun {
2019*4882a593Smuzhiyun dhd_dbg_tx_report_t *tx_report;
2020*4882a593Smuzhiyun dhd_dbg_tx_info_t *tx_pkt;
2021*4882a593Smuzhiyun wifi_tx_report_t *ptr;
2022*4882a593Smuzhiyun compat_wifi_tx_report_t *cptr;
2023*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_pkt_state;
2024*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_status_state;
2025*4882a593Smuzhiyun uint16 pkt_count, count;
2026*4882a593Smuzhiyun unsigned long flags;
2027*4882a593Smuzhiyun
2028*4882a593Smuzhiyun BCM_REFERENCE(ptr);
2029*4882a593Smuzhiyun BCM_REFERENCE(cptr);
2030*4882a593Smuzhiyun
2031*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
2032*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
2033*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
2034*4882a593Smuzhiyun return -EINVAL;
2035*4882a593Smuzhiyun }
2036*4882a593Smuzhiyun
2037*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
2038*4882a593Smuzhiyun tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
2039*4882a593Smuzhiyun tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
2040*4882a593Smuzhiyun if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state)) {
2041*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
2042*4882a593Smuzhiyun "tx_pkt_state=%d, tx_status_state=%d\n", __FUNCTION__,
2043*4882a593Smuzhiyun tx_pkt_state, tx_status_state));
2044*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2045*4882a593Smuzhiyun return -EINVAL;
2046*4882a593Smuzhiyun }
2047*4882a593Smuzhiyun
2048*4882a593Smuzhiyun count = 0;
2049*4882a593Smuzhiyun tx_report = dhdp->dbg->pkt_mon.tx_report;
2050*4882a593Smuzhiyun tx_pkt = tx_report->tx_pkts;
2051*4882a593Smuzhiyun pkt_count = MIN(req_count, tx_report->status_pos);
2052*4882a593Smuzhiyun
2053*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
2054*4882a593Smuzhiyun #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
2055*4882a593Smuzhiyun if (in_compat_syscall())
2056*4882a593Smuzhiyun #else
2057*4882a593Smuzhiyun if (is_compat_task())
2058*4882a593Smuzhiyun #endif
2059*4882a593Smuzhiyun {
2060*4882a593Smuzhiyun cptr = (compat_wifi_tx_report_t *)user_buf;
2061*4882a593Smuzhiyun while ((count < pkt_count) && tx_pkt && cptr) {
2062*4882a593Smuzhiyun compat_wifi_tx_report_t *comp_ptr = compat_ptr((uintptr_t) cptr);
2063*4882a593Smuzhiyun compat_dhd_dbg_pkt_info_t compat_tx_pkt;
2064*4882a593Smuzhiyun __dhd_dbg_dump_tx_pkt_info(dhdp, tx_pkt, count);
2065*4882a593Smuzhiyun __COPY_TO_USER(&comp_ptr->fate, &tx_pkt->fate, sizeof(tx_pkt->fate));
2066*4882a593Smuzhiyun
2067*4882a593Smuzhiyun compat_tx_pkt.payload_type = tx_pkt->info.payload_type;
2068*4882a593Smuzhiyun compat_tx_pkt.pkt_len = tx_pkt->info.pkt_len;
2069*4882a593Smuzhiyun compat_tx_pkt.driver_ts = tx_pkt->info.driver_ts;
2070*4882a593Smuzhiyun compat_tx_pkt.firmware_ts = tx_pkt->info.firmware_ts;
2071*4882a593Smuzhiyun compat_tx_pkt.pkt_hash = tx_pkt->info.pkt_hash;
2072*4882a593Smuzhiyun __COPY_TO_USER(&comp_ptr->frame_inf.payload_type,
2073*4882a593Smuzhiyun &compat_tx_pkt.payload_type,
2074*4882a593Smuzhiyun OFFSETOF(compat_dhd_dbg_pkt_info_t, pkt_hash));
2075*4882a593Smuzhiyun __COPY_TO_USER(comp_ptr->frame_inf.frame_content.ethernet_ii,
2076*4882a593Smuzhiyun PKTDATA(dhdp->osh, tx_pkt->info.pkt), tx_pkt->info.pkt_len);
2077*4882a593Smuzhiyun
2078*4882a593Smuzhiyun cptr++;
2079*4882a593Smuzhiyun tx_pkt++;
2080*4882a593Smuzhiyun count++;
2081*4882a593Smuzhiyun }
2082*4882a593Smuzhiyun } else
2083*4882a593Smuzhiyun #endif /* CONFIG_COMPAT */
2084*4882a593Smuzhiyun {
2085*4882a593Smuzhiyun ptr = (wifi_tx_report_t *)user_buf;
2086*4882a593Smuzhiyun while ((count < pkt_count) && tx_pkt && ptr) {
2087*4882a593Smuzhiyun __dhd_dbg_dump_tx_pkt_info(dhdp, tx_pkt, count);
2088*4882a593Smuzhiyun __COPY_TO_USER(&ptr->fate, &tx_pkt->fate, sizeof(tx_pkt->fate));
2089*4882a593Smuzhiyun __COPY_TO_USER(&ptr->frame_inf.payload_type,
2090*4882a593Smuzhiyun &tx_pkt->info.payload_type,
2091*4882a593Smuzhiyun OFFSETOF(dhd_dbg_pkt_info_t, pkt_hash));
2092*4882a593Smuzhiyun __COPY_TO_USER(ptr->frame_inf.frame_content.ethernet_ii,
2093*4882a593Smuzhiyun PKTDATA(dhdp->osh, tx_pkt->info.pkt), tx_pkt->info.pkt_len);
2094*4882a593Smuzhiyun
2095*4882a593Smuzhiyun ptr++;
2096*4882a593Smuzhiyun tx_pkt++;
2097*4882a593Smuzhiyun count++;
2098*4882a593Smuzhiyun }
2099*4882a593Smuzhiyun }
2100*4882a593Smuzhiyun *resp_count = pkt_count;
2101*4882a593Smuzhiyun
2102*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2103*4882a593Smuzhiyun if (!pkt_count) {
2104*4882a593Smuzhiyun DHD_ERROR(("%s(): no tx_status in tx completion messages, "
2105*4882a593Smuzhiyun "make sure that 'd11status' is enabled in firmware, "
2106*4882a593Smuzhiyun "status_pos=%u\n", __FUNCTION__, pkt_count));
2107*4882a593Smuzhiyun }
2108*4882a593Smuzhiyun
2109*4882a593Smuzhiyun return BCME_OK;
2110*4882a593Smuzhiyun }
2111*4882a593Smuzhiyun
2112*4882a593Smuzhiyun int
dhd_dbg_monitor_get_rx_pkts(dhd_pub_t * dhdp,void __user * user_buf,uint16 req_count,uint16 * resp_count)2113*4882a593Smuzhiyun dhd_dbg_monitor_get_rx_pkts(dhd_pub_t *dhdp, void __user *user_buf,
2114*4882a593Smuzhiyun uint16 req_count, uint16 *resp_count)
2115*4882a593Smuzhiyun {
2116*4882a593Smuzhiyun dhd_dbg_rx_report_t *rx_report;
2117*4882a593Smuzhiyun dhd_dbg_rx_info_t *rx_pkt;
2118*4882a593Smuzhiyun wifi_rx_report_t *ptr;
2119*4882a593Smuzhiyun compat_wifi_rx_report_t *cptr;
2120*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t rx_pkt_state;
2121*4882a593Smuzhiyun uint16 pkt_count, count;
2122*4882a593Smuzhiyun unsigned long flags;
2123*4882a593Smuzhiyun
2124*4882a593Smuzhiyun BCM_REFERENCE(ptr);
2125*4882a593Smuzhiyun BCM_REFERENCE(cptr);
2126*4882a593Smuzhiyun
2127*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
2128*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
2129*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
2130*4882a593Smuzhiyun return -EINVAL;
2131*4882a593Smuzhiyun }
2132*4882a593Smuzhiyun
2133*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
2134*4882a593Smuzhiyun rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
2135*4882a593Smuzhiyun if (PKT_MON_DETACHED(rx_pkt_state)) {
2136*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet fetch is not allowed , "
2137*4882a593Smuzhiyun "rx_pkt_state=%d\n", __FUNCTION__, rx_pkt_state));
2138*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2139*4882a593Smuzhiyun return -EINVAL;
2140*4882a593Smuzhiyun }
2141*4882a593Smuzhiyun
2142*4882a593Smuzhiyun count = 0;
2143*4882a593Smuzhiyun rx_report = dhdp->dbg->pkt_mon.rx_report;
2144*4882a593Smuzhiyun rx_pkt = rx_report->rx_pkts;
2145*4882a593Smuzhiyun pkt_count = MIN(req_count, rx_report->pkt_pos);
2146*4882a593Smuzhiyun
2147*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
2148*4882a593Smuzhiyun #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
2149*4882a593Smuzhiyun if (in_compat_syscall())
2150*4882a593Smuzhiyun #else
2151*4882a593Smuzhiyun if (is_compat_task())
2152*4882a593Smuzhiyun #endif
2153*4882a593Smuzhiyun {
2154*4882a593Smuzhiyun cptr = (compat_wifi_rx_report_t *)user_buf;
2155*4882a593Smuzhiyun while ((count < pkt_count) && rx_pkt && cptr) {
2156*4882a593Smuzhiyun compat_wifi_rx_report_t *comp_ptr = compat_ptr((uintptr_t) cptr);
2157*4882a593Smuzhiyun compat_dhd_dbg_pkt_info_t compat_rx_pkt;
2158*4882a593Smuzhiyun __dhd_dbg_dump_rx_pkt_info(dhdp, rx_pkt, count);
2159*4882a593Smuzhiyun __COPY_TO_USER(&comp_ptr->fate, &rx_pkt->fate, sizeof(rx_pkt->fate));
2160*4882a593Smuzhiyun
2161*4882a593Smuzhiyun compat_rx_pkt.payload_type = rx_pkt->info.payload_type;
2162*4882a593Smuzhiyun compat_rx_pkt.pkt_len = rx_pkt->info.pkt_len;
2163*4882a593Smuzhiyun compat_rx_pkt.driver_ts = rx_pkt->info.driver_ts;
2164*4882a593Smuzhiyun compat_rx_pkt.firmware_ts = rx_pkt->info.firmware_ts;
2165*4882a593Smuzhiyun compat_rx_pkt.pkt_hash = rx_pkt->info.pkt_hash;
2166*4882a593Smuzhiyun __COPY_TO_USER(&comp_ptr->frame_inf.payload_type,
2167*4882a593Smuzhiyun &compat_rx_pkt.payload_type,
2168*4882a593Smuzhiyun OFFSETOF(compat_dhd_dbg_pkt_info_t, pkt_hash));
2169*4882a593Smuzhiyun __COPY_TO_USER(comp_ptr->frame_inf.frame_content.ethernet_ii,
2170*4882a593Smuzhiyun PKTDATA(dhdp->osh, rx_pkt->info.pkt), rx_pkt->info.pkt_len);
2171*4882a593Smuzhiyun
2172*4882a593Smuzhiyun cptr++;
2173*4882a593Smuzhiyun rx_pkt++;
2174*4882a593Smuzhiyun count++;
2175*4882a593Smuzhiyun }
2176*4882a593Smuzhiyun } else
2177*4882a593Smuzhiyun #endif /* CONFIG_COMPAT */
2178*4882a593Smuzhiyun {
2179*4882a593Smuzhiyun ptr = (wifi_rx_report_t *)user_buf;
2180*4882a593Smuzhiyun while ((count < pkt_count) && rx_pkt && ptr) {
2181*4882a593Smuzhiyun __dhd_dbg_dump_rx_pkt_info(dhdp, rx_pkt, count);
2182*4882a593Smuzhiyun
2183*4882a593Smuzhiyun __COPY_TO_USER(&ptr->fate, &rx_pkt->fate, sizeof(rx_pkt->fate));
2184*4882a593Smuzhiyun __COPY_TO_USER(&ptr->frame_inf.payload_type,
2185*4882a593Smuzhiyun &rx_pkt->info.payload_type,
2186*4882a593Smuzhiyun OFFSETOF(dhd_dbg_pkt_info_t, pkt_hash));
2187*4882a593Smuzhiyun __COPY_TO_USER(ptr->frame_inf.frame_content.ethernet_ii,
2188*4882a593Smuzhiyun PKTDATA(dhdp->osh, rx_pkt->info.pkt), rx_pkt->info.pkt_len);
2189*4882a593Smuzhiyun
2190*4882a593Smuzhiyun ptr++;
2191*4882a593Smuzhiyun rx_pkt++;
2192*4882a593Smuzhiyun count++;
2193*4882a593Smuzhiyun }
2194*4882a593Smuzhiyun }
2195*4882a593Smuzhiyun
2196*4882a593Smuzhiyun *resp_count = pkt_count;
2197*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2198*4882a593Smuzhiyun
2199*4882a593Smuzhiyun return BCME_OK;
2200*4882a593Smuzhiyun }
2201*4882a593Smuzhiyun
2202*4882a593Smuzhiyun int
dhd_dbg_detach_pkt_monitor(dhd_pub_t * dhdp)2203*4882a593Smuzhiyun dhd_dbg_detach_pkt_monitor(dhd_pub_t *dhdp)
2204*4882a593Smuzhiyun {
2205*4882a593Smuzhiyun dhd_dbg_tx_report_t *tx_report;
2206*4882a593Smuzhiyun dhd_dbg_rx_report_t *rx_report;
2207*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_pkt_state;
2208*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t tx_status_state;
2209*4882a593Smuzhiyun dhd_dbg_pkt_mon_state_t rx_pkt_state;
2210*4882a593Smuzhiyun unsigned long flags;
2211*4882a593Smuzhiyun
2212*4882a593Smuzhiyun if (!dhdp || !dhdp->dbg) {
2213*4882a593Smuzhiyun DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
2214*4882a593Smuzhiyun dhdp, (dhdp ? dhdp->dbg : NULL)));
2215*4882a593Smuzhiyun return -EINVAL;
2216*4882a593Smuzhiyun }
2217*4882a593Smuzhiyun
2218*4882a593Smuzhiyun DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
2219*4882a593Smuzhiyun tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
2220*4882a593Smuzhiyun tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
2221*4882a593Smuzhiyun rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
2222*4882a593Smuzhiyun
2223*4882a593Smuzhiyun if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
2224*4882a593Smuzhiyun PKT_MON_DETACHED(rx_pkt_state)) {
2225*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor is already detached, "
2226*4882a593Smuzhiyun "tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
2227*4882a593Smuzhiyun __FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
2228*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2229*4882a593Smuzhiyun return -EINVAL;
2230*4882a593Smuzhiyun }
2231*4882a593Smuzhiyun
2232*4882a593Smuzhiyun tx_report = dhdp->dbg->pkt_mon.tx_report;
2233*4882a593Smuzhiyun rx_report = dhdp->dbg->pkt_mon.rx_report;
2234*4882a593Smuzhiyun
2235*4882a593Smuzhiyun /* free and de-initalize tx packet monitoring */
2236*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_DETACHED;
2237*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_DETACHED;
2238*4882a593Smuzhiyun if (tx_report) {
2239*4882a593Smuzhiyun if (tx_report->tx_pkts) {
2240*4882a593Smuzhiyun __dhd_dbg_free_tx_pkts(dhdp, tx_report->tx_pkts,
2241*4882a593Smuzhiyun tx_report->pkt_pos);
2242*4882a593Smuzhiyun MFREE(dhdp->osh, tx_report->tx_pkts,
2243*4882a593Smuzhiyun (sizeof(*tx_report->tx_pkts) * MAX_FATE_LOG_LEN));
2244*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_report->tx_pkts = NULL;
2245*4882a593Smuzhiyun }
2246*4882a593Smuzhiyun MFREE(dhdp->osh, tx_report, sizeof(*tx_report));
2247*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_report = NULL;
2248*4882a593Smuzhiyun }
2249*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_pkt_mon = NULL;
2250*4882a593Smuzhiyun dhdp->dbg->pkt_mon.tx_status_mon = NULL;
2251*4882a593Smuzhiyun
2252*4882a593Smuzhiyun /* free and de-initalize rx packet monitoring */
2253*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_DETACHED;
2254*4882a593Smuzhiyun if (rx_report) {
2255*4882a593Smuzhiyun if (rx_report->rx_pkts) {
2256*4882a593Smuzhiyun __dhd_dbg_free_rx_pkts(dhdp, rx_report->rx_pkts,
2257*4882a593Smuzhiyun rx_report->pkt_pos);
2258*4882a593Smuzhiyun MFREE(dhdp->osh, rx_report->rx_pkts,
2259*4882a593Smuzhiyun (sizeof(*rx_report->rx_pkts) * MAX_FATE_LOG_LEN));
2260*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_report->rx_pkts = NULL;
2261*4882a593Smuzhiyun }
2262*4882a593Smuzhiyun MFREE(dhdp->osh, rx_report, sizeof(*rx_report));
2263*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_report = NULL;
2264*4882a593Smuzhiyun }
2265*4882a593Smuzhiyun dhdp->dbg->pkt_mon.rx_pkt_mon = NULL;
2266*4882a593Smuzhiyun
2267*4882a593Smuzhiyun DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2268*4882a593Smuzhiyun DHD_PKT_MON(("%s(): packet monitor detach succeeded\n", __FUNCTION__));
2269*4882a593Smuzhiyun return BCME_OK;
2270*4882a593Smuzhiyun }
2271*4882a593Smuzhiyun #endif /* DBG_PKT_MON */
2272*4882a593Smuzhiyun
2273*4882a593Smuzhiyun #if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING)
2274*4882a593Smuzhiyun /*
2275*4882a593Smuzhiyun * XXX: WAR: Because of the overloading by DMA marker field,
2276*4882a593Smuzhiyun * tx_status in TX completion message cannot be used. As a WAR,
2277*4882a593Smuzhiyun * send d11 tx_status through unused status field of PCIe
2278*4882a593Smuzhiyun * completion header.
2279*4882a593Smuzhiyun */
2280*4882a593Smuzhiyun bool
dhd_dbg_process_tx_status(dhd_pub_t * dhdp,void * pkt,uint32 pktid,uint16 status)2281*4882a593Smuzhiyun dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid,
2282*4882a593Smuzhiyun uint16 status)
2283*4882a593Smuzhiyun {
2284*4882a593Smuzhiyun bool pkt_fate = TRUE;
2285*4882a593Smuzhiyun if (dhdp->d11_tx_status) {
2286*4882a593Smuzhiyun pkt_fate = (status == WLFC_CTL_PKTFLAG_DISCARD) ? TRUE : FALSE;
2287*4882a593Smuzhiyun DHD_DBG_PKT_MON_TX_STATUS(dhdp, pkt, pktid, status);
2288*4882a593Smuzhiyun }
2289*4882a593Smuzhiyun return pkt_fate;
2290*4882a593Smuzhiyun }
2291*4882a593Smuzhiyun #else /* DBG_PKT_MON || DHD_PKT_LOGGING */
2292*4882a593Smuzhiyun bool
dhd_dbg_process_tx_status(dhd_pub_t * dhdp,void * pkt,uint32 pktid,uint16 status)2293*4882a593Smuzhiyun dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt,
2294*4882a593Smuzhiyun uint32 pktid, uint16 status)
2295*4882a593Smuzhiyun {
2296*4882a593Smuzhiyun return TRUE;
2297*4882a593Smuzhiyun }
2298*4882a593Smuzhiyun #endif /* DBG_PKT_MON || DHD_PKT_LOGGING */
2299*4882a593Smuzhiyun
2300*4882a593Smuzhiyun #define EL_LOG_STR_LEN 512
2301*4882a593Smuzhiyun
2302*4882a593Smuzhiyun #define PRINT_CHN_PER_LINE 8
2303*4882a593Smuzhiyun #define PRINT_CHAN_LINE(cnt) \
2304*4882a593Smuzhiyun {\
2305*4882a593Smuzhiyun cnt ++; \
2306*4882a593Smuzhiyun if (cnt >= PRINT_CHN_PER_LINE) { \
2307*4882a593Smuzhiyun DHD_ERROR(("%s\n", b.origbuf)); \
2308*4882a593Smuzhiyun bcm_binit(&b, pr_buf, EL_LOG_STR_LEN); \
2309*4882a593Smuzhiyun bcm_bprintf(&b, "%s: ", prefix); \
2310*4882a593Smuzhiyun cnt = 0; \
2311*4882a593Smuzhiyun } \
2312*4882a593Smuzhiyun }
2313*4882a593Smuzhiyun
print_roam_chan_list(char * prefix,uint chan_num,uint16 band_2g,uint16 uni2a,uint8 uni3,uint8 * uni2c)2314*4882a593Smuzhiyun void print_roam_chan_list(char *prefix, uint chan_num, uint16 band_2g,
2315*4882a593Smuzhiyun uint16 uni2a, uint8 uni3, uint8 *uni2c)
2316*4882a593Smuzhiyun {
2317*4882a593Smuzhiyun struct bcmstrbuf b;
2318*4882a593Smuzhiyun char pr_buf[EL_LOG_STR_LEN] = { 0 };
2319*4882a593Smuzhiyun int cnt = 0;
2320*4882a593Smuzhiyun int idx, idx2;
2321*4882a593Smuzhiyun
2322*4882a593Smuzhiyun bcm_binit(&b, pr_buf, EL_LOG_STR_LEN);
2323*4882a593Smuzhiyun bcm_bprintf(&b, "%s: count(%d)", prefix, chan_num);
2324*4882a593Smuzhiyun /* 2G channnels */
2325*4882a593Smuzhiyun for (idx = 0; idx < NBITS(uint16); idx++) {
2326*4882a593Smuzhiyun if (BCM_BIT(idx) & band_2g) {
2327*4882a593Smuzhiyun bcm_bprintf(&b, " %d", idx);
2328*4882a593Smuzhiyun PRINT_CHAN_LINE(cnt);
2329*4882a593Smuzhiyun
2330*4882a593Smuzhiyun }
2331*4882a593Smuzhiyun }
2332*4882a593Smuzhiyun
2333*4882a593Smuzhiyun /* 5G UNII BAND 1, UNII BAND 2A */
2334*4882a593Smuzhiyun for (idx = 0; idx < NBITS(uint16); idx++) {
2335*4882a593Smuzhiyun if (BCM_BIT(idx) & uni2a) {
2336*4882a593Smuzhiyun bcm_bprintf(&b, " %u", ROAM_CHN_UNI_2A + idx * ROAM_CHN_SPACE);
2337*4882a593Smuzhiyun PRINT_CHAN_LINE(cnt);
2338*4882a593Smuzhiyun }
2339*4882a593Smuzhiyun }
2340*4882a593Smuzhiyun
2341*4882a593Smuzhiyun /* 5G UNII BAND 2C */
2342*4882a593Smuzhiyun for (idx2 = 0; idx2 < 3; idx2++) {
2343*4882a593Smuzhiyun for (idx = 0; idx < NBITS(uint8); idx++) {
2344*4882a593Smuzhiyun if (BCM_BIT(idx) & uni2c[idx2]) {
2345*4882a593Smuzhiyun bcm_bprintf(&b, " %u", ROAM_CHN_UNI_2C +
2346*4882a593Smuzhiyun idx2 * ROAM_CHN_SPACE * NBITS(uint8) +
2347*4882a593Smuzhiyun idx * ROAM_CHN_SPACE);
2348*4882a593Smuzhiyun PRINT_CHAN_LINE(cnt);
2349*4882a593Smuzhiyun }
2350*4882a593Smuzhiyun }
2351*4882a593Smuzhiyun }
2352*4882a593Smuzhiyun
2353*4882a593Smuzhiyun /* 5G UNII BAND 3 */
2354*4882a593Smuzhiyun for (idx = 0; idx < NBITS(uint8); idx++) {
2355*4882a593Smuzhiyun if (BCM_BIT(idx) & uni3) {
2356*4882a593Smuzhiyun bcm_bprintf(&b, " %u", ROAM_CHN_UNI_3 + idx * ROAM_CHN_SPACE);
2357*4882a593Smuzhiyun PRINT_CHAN_LINE(cnt);
2358*4882a593Smuzhiyun }
2359*4882a593Smuzhiyun }
2360*4882a593Smuzhiyun
2361*4882a593Smuzhiyun if (cnt != 0) {
2362*4882a593Smuzhiyun DHD_ERROR(("%s\n", b.origbuf));
2363*4882a593Smuzhiyun }
2364*4882a593Smuzhiyun }
2365*4882a593Smuzhiyun
2366*4882a593Smuzhiyun void pr_roam_scan_start_v1(prcd_event_log_hdr_t *plog_hdr);
2367*4882a593Smuzhiyun void pr_roam_scan_cmpl_v1(prcd_event_log_hdr_t *plog_hdr);
2368*4882a593Smuzhiyun void pr_roam_cmpl_v1(prcd_event_log_hdr_t *plog_hdr);
2369*4882a593Smuzhiyun void pr_roam_nbr_req_v1(prcd_event_log_hdr_t *plog_hdr);
2370*4882a593Smuzhiyun void pr_roam_nbr_rep_v1(prcd_event_log_hdr_t *plog_hdr);
2371*4882a593Smuzhiyun void pr_roam_bcn_req_v1(prcd_event_log_hdr_t *plog_hdr);
2372*4882a593Smuzhiyun void pr_roam_bcn_rep_v1(prcd_event_log_hdr_t *plog_hdr);
2373*4882a593Smuzhiyun
2374*4882a593Smuzhiyun void pr_roam_scan_start_v2(prcd_event_log_hdr_t *plog_hdr);
2375*4882a593Smuzhiyun void pr_roam_scan_cmpl_v2(prcd_event_log_hdr_t *plog_hdr);
2376*4882a593Smuzhiyun void pr_roam_nbr_rep_v2(prcd_event_log_hdr_t *plog_hdr);
2377*4882a593Smuzhiyun void pr_roam_bcn_rep_v2(prcd_event_log_hdr_t *plog_hdr);
2378*4882a593Smuzhiyun void pr_roam_btm_rep_v2(prcd_event_log_hdr_t *plog_hdr);
2379*4882a593Smuzhiyun
2380*4882a593Smuzhiyun void pr_roam_bcn_req_v3(prcd_event_log_hdr_t *plog_hdr);
2381*4882a593Smuzhiyun void pr_roam_bcn_rep_v3(prcd_event_log_hdr_t *plog_hdr);
2382*4882a593Smuzhiyun void pr_roam_btm_rep_v3(prcd_event_log_hdr_t *plog_hdr);
2383*4882a593Smuzhiyun
2384*4882a593Smuzhiyun static const pr_roam_tbl_t roam_log_print_tbl[] =
2385*4882a593Smuzhiyun {
2386*4882a593Smuzhiyun {ROAM_LOG_VER_1, ROAM_LOG_SCANSTART, pr_roam_scan_start_v1},
2387*4882a593Smuzhiyun {ROAM_LOG_VER_1, ROAM_LOG_SCAN_CMPLT, pr_roam_scan_cmpl_v1},
2388*4882a593Smuzhiyun {ROAM_LOG_VER_1, ROAM_LOG_ROAM_CMPLT, pr_roam_cmpl_v1},
2389*4882a593Smuzhiyun {ROAM_LOG_VER_1, ROAM_LOG_NBR_REQ, pr_roam_nbr_req_v1},
2390*4882a593Smuzhiyun {ROAM_LOG_VER_1, ROAM_LOG_NBR_REP, pr_roam_nbr_rep_v1},
2391*4882a593Smuzhiyun {ROAM_LOG_VER_1, ROAM_LOG_BCN_REQ, pr_roam_bcn_req_v1},
2392*4882a593Smuzhiyun {ROAM_LOG_VER_1, ROAM_LOG_BCN_REP, pr_roam_bcn_rep_v1},
2393*4882a593Smuzhiyun
2394*4882a593Smuzhiyun {ROAM_LOG_VER_2, ROAM_LOG_SCANSTART, pr_roam_scan_start_v2},
2395*4882a593Smuzhiyun {ROAM_LOG_VER_2, ROAM_LOG_SCAN_CMPLT, pr_roam_scan_cmpl_v2},
2396*4882a593Smuzhiyun {ROAM_LOG_VER_2, ROAM_LOG_ROAM_CMPLT, pr_roam_cmpl_v1},
2397*4882a593Smuzhiyun {ROAM_LOG_VER_2, ROAM_LOG_NBR_REQ, pr_roam_nbr_req_v1},
2398*4882a593Smuzhiyun {ROAM_LOG_VER_2, ROAM_LOG_NBR_REP, pr_roam_nbr_rep_v2},
2399*4882a593Smuzhiyun {ROAM_LOG_VER_2, ROAM_LOG_BCN_REQ, pr_roam_bcn_req_v1},
2400*4882a593Smuzhiyun {ROAM_LOG_VER_2, ROAM_LOG_BCN_REP, pr_roam_bcn_rep_v2},
2401*4882a593Smuzhiyun {ROAM_LOG_VER_2, ROAM_LOG_BTM_REP, pr_roam_btm_rep_v2},
2402*4882a593Smuzhiyun
2403*4882a593Smuzhiyun {ROAM_LOG_VER_3, ROAM_LOG_SCANSTART, pr_roam_scan_start_v2},
2404*4882a593Smuzhiyun {ROAM_LOG_VER_3, ROAM_LOG_SCAN_CMPLT, pr_roam_scan_cmpl_v2},
2405*4882a593Smuzhiyun {ROAM_LOG_VER_3, ROAM_LOG_ROAM_CMPLT, pr_roam_cmpl_v1},
2406*4882a593Smuzhiyun {ROAM_LOG_VER_3, ROAM_LOG_NBR_REQ, pr_roam_nbr_req_v1},
2407*4882a593Smuzhiyun {ROAM_LOG_VER_3, ROAM_LOG_NBR_REP, pr_roam_nbr_rep_v2},
2408*4882a593Smuzhiyun {ROAM_LOG_VER_3, ROAM_LOG_BCN_REQ, pr_roam_bcn_req_v3},
2409*4882a593Smuzhiyun {ROAM_LOG_VER_3, ROAM_LOG_BCN_REP, pr_roam_bcn_rep_v3},
2410*4882a593Smuzhiyun {ROAM_LOG_VER_3, ROAM_LOG_BTM_REP, pr_roam_btm_rep_v3},
2411*4882a593Smuzhiyun
2412*4882a593Smuzhiyun {0, PRSV_PERIODIC_ID_MAX, NULL}
2413*4882a593Smuzhiyun
2414*4882a593Smuzhiyun };
2415*4882a593Smuzhiyun
pr_roam_scan_start_v1(prcd_event_log_hdr_t * plog_hdr)2416*4882a593Smuzhiyun void pr_roam_scan_start_v1(prcd_event_log_hdr_t *plog_hdr)
2417*4882a593Smuzhiyun {
2418*4882a593Smuzhiyun roam_log_trig_v1_t *log = (roam_log_trig_v1_t *)plog_hdr->log_ptr;
2419*4882a593Smuzhiyun
2420*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_SCANSTART time: %d,"
2421*4882a593Smuzhiyun " version:%d reason: %d rssi:%d cu:%d result:%d\n",
2422*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version, log->reason,
2423*4882a593Smuzhiyun log->rssi, log->current_cu, log->result));
2424*4882a593Smuzhiyun if (log->reason == WLC_E_REASON_DEAUTH ||
2425*4882a593Smuzhiyun log->reason == WLC_E_REASON_DISASSOC) {
2426*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_PRT_ROAM: RCVD reason:%d\n",
2427*4882a593Smuzhiyun log->prt_roam.rcvd_reason));
2428*4882a593Smuzhiyun } else if (log->reason == WLC_E_REASON_BSSTRANS_REQ) {
2429*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_BSS_REQ: mode:%d candidate:%d token:%d "
2430*4882a593Smuzhiyun "duration disassoc:%d valid:%d term:%d\n",
2431*4882a593Smuzhiyun log->bss_trans.req_mode, log->bss_trans.nbrlist_size,
2432*4882a593Smuzhiyun log->bss_trans.token, log->bss_trans.disassoc_dur,
2433*4882a593Smuzhiyun log->bss_trans.validity_dur, log->bss_trans.bss_term_dur));
2434*4882a593Smuzhiyun }
2435*4882a593Smuzhiyun }
2436*4882a593Smuzhiyun
pr_roam_scan_cmpl_v1(prcd_event_log_hdr_t * plog_hdr)2437*4882a593Smuzhiyun void pr_roam_scan_cmpl_v1(prcd_event_log_hdr_t *plog_hdr)
2438*4882a593Smuzhiyun {
2439*4882a593Smuzhiyun roam_log_scan_cmplt_v1_t *log = (roam_log_scan_cmplt_v1_t *)plog_hdr->log_ptr;
2440*4882a593Smuzhiyun char chanspec_buf[CHANSPEC_STR_LEN];
2441*4882a593Smuzhiyun int i;
2442*4882a593Smuzhiyun
2443*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_SCAN_CMPL: time:%d version:%d"
2444*4882a593Smuzhiyun "is_full:%d scan_count:%d score_delta:%d",
2445*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version, log->full_scan,
2446*4882a593Smuzhiyun log->scan_count, log->score_delta));
2447*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_CUR_AP: " MACDBG "rssi:%d score:%d channel:%s\n",
2448*4882a593Smuzhiyun MAC2STRDBG((uint8 *)&log->cur_info.addr),
2449*4882a593Smuzhiyun log->cur_info.rssi,
2450*4882a593Smuzhiyun log->cur_info.score,
2451*4882a593Smuzhiyun wf_chspec_ntoa_ex(log->cur_info.chanspec, chanspec_buf)));
2452*4882a593Smuzhiyun for (i = 0; i < log->scan_list_size; i++) {
2453*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_CANDIDATE %d: " MACDBG
2454*4882a593Smuzhiyun "rssi:%d score:%d channel:%s TPUT:%dkbps\n",
2455*4882a593Smuzhiyun i, MAC2STRDBG((uint8 *)&log->scan_list[i].addr),
2456*4882a593Smuzhiyun log->scan_list[i].rssi, log->scan_list[i].score,
2457*4882a593Smuzhiyun wf_chspec_ntoa_ex(log->scan_list[i].chanspec,
2458*4882a593Smuzhiyun chanspec_buf),
2459*4882a593Smuzhiyun log->scan_list[i].estm_tput != ROAM_LOG_INVALID_TPUT?
2460*4882a593Smuzhiyun log->scan_list[i].estm_tput:0));
2461*4882a593Smuzhiyun }
2462*4882a593Smuzhiyun }
2463*4882a593Smuzhiyun
pr_roam_cmpl_v1(prcd_event_log_hdr_t * plog_hdr)2464*4882a593Smuzhiyun void pr_roam_cmpl_v1(prcd_event_log_hdr_t *plog_hdr)
2465*4882a593Smuzhiyun {
2466*4882a593Smuzhiyun roam_log_cmplt_v1_t *log = (roam_log_cmplt_v1_t *)plog_hdr->log_ptr;
2467*4882a593Smuzhiyun char chanspec_buf[CHANSPEC_STR_LEN];
2468*4882a593Smuzhiyun
2469*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_ROAM_CMPL: time: %d, version:%d"
2470*4882a593Smuzhiyun "status: %d reason: %d channel:%s retry:%d " MACDBG "\n",
2471*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version, log->status, log->reason,
2472*4882a593Smuzhiyun wf_chspec_ntoa_ex(log->chanspec, chanspec_buf),
2473*4882a593Smuzhiyun log->retry, MAC2STRDBG((uint8 *)&log->addr)));
2474*4882a593Smuzhiyun }
2475*4882a593Smuzhiyun
pr_roam_nbr_req_v1(prcd_event_log_hdr_t * plog_hdr)2476*4882a593Smuzhiyun void pr_roam_nbr_req_v1(prcd_event_log_hdr_t *plog_hdr)
2477*4882a593Smuzhiyun {
2478*4882a593Smuzhiyun roam_log_nbrreq_v1_t *log = (roam_log_nbrreq_v1_t *)plog_hdr->log_ptr;
2479*4882a593Smuzhiyun
2480*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_NBR_REQ: time: %d, version:%d token:%d\n",
2481*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version, log->token));
2482*4882a593Smuzhiyun }
2483*4882a593Smuzhiyun
pr_roam_nbr_rep_v1(prcd_event_log_hdr_t * plog_hdr)2484*4882a593Smuzhiyun void pr_roam_nbr_rep_v1(prcd_event_log_hdr_t *plog_hdr)
2485*4882a593Smuzhiyun {
2486*4882a593Smuzhiyun roam_log_nbrrep_v1_t *log = (roam_log_nbrrep_v1_t *)plog_hdr->log_ptr;
2487*4882a593Smuzhiyun
2488*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_NBR_REP: time:%d, veresion:%d chan_num:%d\n",
2489*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version, log->channel_num));
2490*4882a593Smuzhiyun }
2491*4882a593Smuzhiyun
pr_roam_bcn_req_v1(prcd_event_log_hdr_t * plog_hdr)2492*4882a593Smuzhiyun void pr_roam_bcn_req_v1(prcd_event_log_hdr_t *plog_hdr)
2493*4882a593Smuzhiyun {
2494*4882a593Smuzhiyun roam_log_bcnrpt_req_v1_t *log = (roam_log_bcnrpt_req_v1_t *)plog_hdr->log_ptr;
2495*4882a593Smuzhiyun
2496*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BCN_REQ: time:%d, version:%d ret:%d"
2497*4882a593Smuzhiyun "class:%d num_chan:%d ",
2498*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version,
2499*4882a593Smuzhiyun log->result, log->reg, log->channel));
2500*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BCN_REQ: mode:%d is_wild:%d duration:%d"
2501*4882a593Smuzhiyun "ssid_len:%d\n", log->mode, log->bssid_wild,
2502*4882a593Smuzhiyun log->duration, log->ssid_len));
2503*4882a593Smuzhiyun }
2504*4882a593Smuzhiyun
pr_roam_bcn_rep_v1(prcd_event_log_hdr_t * plog_hdr)2505*4882a593Smuzhiyun void pr_roam_bcn_rep_v1(prcd_event_log_hdr_t *plog_hdr)
2506*4882a593Smuzhiyun {
2507*4882a593Smuzhiyun roam_log_bcnrpt_rep_v1_t *log = (roam_log_bcnrpt_rep_v1_t *)plog_hdr->log_ptr;
2508*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BCN_REP: time:%d, verseion:%d count:%d\n",
2509*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version,
2510*4882a593Smuzhiyun log->count));
2511*4882a593Smuzhiyun }
2512*4882a593Smuzhiyun
pr_roam_scan_start_v2(prcd_event_log_hdr_t * plog_hdr)2513*4882a593Smuzhiyun void pr_roam_scan_start_v2(prcd_event_log_hdr_t *plog_hdr)
2514*4882a593Smuzhiyun {
2515*4882a593Smuzhiyun roam_log_trig_v2_t *log = (roam_log_trig_v2_t *)plog_hdr->log_ptr;
2516*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_SCANSTART time: %d,"
2517*4882a593Smuzhiyun " version:%d reason: %d rssi:%d cu:%d result:%d full_scan:%d\n",
2518*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version, log->reason,
2519*4882a593Smuzhiyun log->rssi, log->current_cu, log->result,
2520*4882a593Smuzhiyun log->result?(-1):log->full_scan));
2521*4882a593Smuzhiyun if (log->reason == WLC_E_REASON_DEAUTH ||
2522*4882a593Smuzhiyun log->reason == WLC_E_REASON_DISASSOC) {
2523*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_PRT_ROAM: RCVD reason:%d\n",
2524*4882a593Smuzhiyun log->prt_roam.rcvd_reason));
2525*4882a593Smuzhiyun } else if (log->reason == WLC_E_REASON_BSSTRANS_REQ) {
2526*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_BSS_REQ: mode:%d candidate:%d token:%d "
2527*4882a593Smuzhiyun "duration disassoc:%d valid:%d term:%d\n",
2528*4882a593Smuzhiyun log->bss_trans.req_mode, log->bss_trans.nbrlist_size,
2529*4882a593Smuzhiyun log->bss_trans.token, log->bss_trans.disassoc_dur,
2530*4882a593Smuzhiyun log->bss_trans.validity_dur, log->bss_trans.bss_term_dur));
2531*4882a593Smuzhiyun } else if (log->reason == WLC_E_REASON_LOW_RSSI) {
2532*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_LOW_RSSI: threshold:%d\n",
2533*4882a593Smuzhiyun log->low_rssi.rssi_threshold));
2534*4882a593Smuzhiyun }
2535*4882a593Smuzhiyun }
2536*4882a593Smuzhiyun
pr_roam_scan_cmpl_v2(prcd_event_log_hdr_t * plog_hdr)2537*4882a593Smuzhiyun void pr_roam_scan_cmpl_v2(prcd_event_log_hdr_t *plog_hdr)
2538*4882a593Smuzhiyun {
2539*4882a593Smuzhiyun int i;
2540*4882a593Smuzhiyun roam_log_scan_cmplt_v2_t *log = (roam_log_scan_cmplt_v2_t *)plog_hdr->log_ptr;
2541*4882a593Smuzhiyun char chanspec_buf[CHANSPEC_STR_LEN];
2542*4882a593Smuzhiyun
2543*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_SCAN_CMPL: time:%d version:%d"
2544*4882a593Smuzhiyun "scan_count:%d score_delta:%d",
2545*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version,
2546*4882a593Smuzhiyun log->scan_count, log->score_delta));
2547*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_CUR_AP: " MACDBG "rssi:%d score:%d channel:%s\n",
2548*4882a593Smuzhiyun MAC2STRDBG((uint8 *)&log->cur_info.addr),
2549*4882a593Smuzhiyun log->cur_info.rssi,
2550*4882a593Smuzhiyun log->cur_info.score,
2551*4882a593Smuzhiyun wf_chspec_ntoa_ex(log->cur_info.chanspec, chanspec_buf)));
2552*4882a593Smuzhiyun for (i = 0; i < log->scan_list_size; i++) {
2553*4882a593Smuzhiyun DHD_ERROR_ROAM((" ROAM_LOG_CANDIDATE %d: " MACDBG
2554*4882a593Smuzhiyun "rssi:%d score:%d cu :%d channel:%s TPUT:%dkbps\n",
2555*4882a593Smuzhiyun i, MAC2STRDBG((uint8 *)&log->scan_list[i].addr),
2556*4882a593Smuzhiyun log->scan_list[i].rssi, log->scan_list[i].score,
2557*4882a593Smuzhiyun log->scan_list[i].cu * 100 / WL_MAX_CHANNEL_USAGE,
2558*4882a593Smuzhiyun wf_chspec_ntoa_ex(log->scan_list[i].chanspec,
2559*4882a593Smuzhiyun chanspec_buf),
2560*4882a593Smuzhiyun log->scan_list[i].estm_tput != ROAM_LOG_INVALID_TPUT?
2561*4882a593Smuzhiyun log->scan_list[i].estm_tput:0));
2562*4882a593Smuzhiyun }
2563*4882a593Smuzhiyun if (log->chan_num != 0) {
2564*4882a593Smuzhiyun print_roam_chan_list("ROAM_LOG_SCAN_CHANLIST", log->chan_num,
2565*4882a593Smuzhiyun log->band2g_chan_list, log->uni2a_chan_list,
2566*4882a593Smuzhiyun log->uni3_chan_list, log->uni2c_chan_list);
2567*4882a593Smuzhiyun }
2568*4882a593Smuzhiyun
2569*4882a593Smuzhiyun }
2570*4882a593Smuzhiyun
pr_roam_nbr_rep_v2(prcd_event_log_hdr_t * plog_hdr)2571*4882a593Smuzhiyun void pr_roam_nbr_rep_v2(prcd_event_log_hdr_t *plog_hdr)
2572*4882a593Smuzhiyun {
2573*4882a593Smuzhiyun roam_log_nbrrep_v2_t *log = (roam_log_nbrrep_v2_t *)plog_hdr->log_ptr;
2574*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_NBR_REP: time:%d, veresion:%d chan_num:%d\n",
2575*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version, log->channel_num));
2576*4882a593Smuzhiyun if (log->channel_num != 0) {
2577*4882a593Smuzhiyun print_roam_chan_list("ROAM_LOG_NBR_REP_CHANLIST", log->channel_num,
2578*4882a593Smuzhiyun log->band2g_chan_list, log->uni2a_chan_list,
2579*4882a593Smuzhiyun log->uni3_chan_list, log->uni2c_chan_list);
2580*4882a593Smuzhiyun }
2581*4882a593Smuzhiyun }
2582*4882a593Smuzhiyun
pr_roam_bcn_rep_v2(prcd_event_log_hdr_t * plog_hdr)2583*4882a593Smuzhiyun void pr_roam_bcn_rep_v2(prcd_event_log_hdr_t *plog_hdr)
2584*4882a593Smuzhiyun {
2585*4882a593Smuzhiyun roam_log_bcnrpt_rep_v2_t *log = (roam_log_bcnrpt_rep_v2_t *)plog_hdr->log_ptr;
2586*4882a593Smuzhiyun
2587*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BCN_REP: time:%d, verseion:%d count:%d mode:%d\n",
2588*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version,
2589*4882a593Smuzhiyun log->count, log->reason));
2590*4882a593Smuzhiyun }
2591*4882a593Smuzhiyun
pr_roam_btm_rep_v2(prcd_event_log_hdr_t * plog_hdr)2592*4882a593Smuzhiyun void pr_roam_btm_rep_v2(prcd_event_log_hdr_t *plog_hdr)
2593*4882a593Smuzhiyun {
2594*4882a593Smuzhiyun roam_log_btm_rep_v2_t *log = (roam_log_btm_rep_v2_t *)plog_hdr->log_ptr;
2595*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BTM_REP: time:%d version:%d req_mode:%d "
2596*4882a593Smuzhiyun "status:%d ret:%d\n",
2597*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version,
2598*4882a593Smuzhiyun log->req_mode, log->status, log->result));
2599*4882a593Smuzhiyun }
2600*4882a593Smuzhiyun
pr_roam_bcn_req_v3(prcd_event_log_hdr_t * plog_hdr)2601*4882a593Smuzhiyun void pr_roam_bcn_req_v3(prcd_event_log_hdr_t *plog_hdr)
2602*4882a593Smuzhiyun {
2603*4882a593Smuzhiyun roam_log_bcnrpt_req_v3_t *log = (roam_log_bcnrpt_req_v3_t *)plog_hdr->log_ptr;
2604*4882a593Smuzhiyun
2605*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BCN_REQ: time:%d, version:%d ret:%d"
2606*4882a593Smuzhiyun "class:%d %s ",
2607*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version,
2608*4882a593Smuzhiyun log->result, log->reg, log->channel?"":"all_chan"));
2609*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BCN_REQ: mode:%d is_wild:%d duration:%d"
2610*4882a593Smuzhiyun "ssid_len:%d\n", log->mode, log->bssid_wild,
2611*4882a593Smuzhiyun log->duration, log->ssid_len));
2612*4882a593Smuzhiyun if (log->channel_num != 0) {
2613*4882a593Smuzhiyun print_roam_chan_list("ROAM_LOG_BCNREQ_SCAN_CHANLIST", log->channel_num,
2614*4882a593Smuzhiyun log->band2g_chan_list, log->uni2a_chan_list,
2615*4882a593Smuzhiyun log->uni3_chan_list, log->uni2c_chan_list);
2616*4882a593Smuzhiyun }
2617*4882a593Smuzhiyun }
2618*4882a593Smuzhiyun
2619*4882a593Smuzhiyun static const char*
pr_roam_bcn_rep_reason(uint16 reason_detail)2620*4882a593Smuzhiyun pr_roam_bcn_rep_reason(uint16 reason_detail)
2621*4882a593Smuzhiyun {
2622*4882a593Smuzhiyun static const char* reason_tbl[] = {
2623*4882a593Smuzhiyun "BCNRPT_RSN_SUCCESS",
2624*4882a593Smuzhiyun "BCNRPT_RSN_BADARG",
2625*4882a593Smuzhiyun "BCNRPT_RSN_SCAN_ING",
2626*4882a593Smuzhiyun "BCNRPT_RSN_SCAN_FAIL",
2627*4882a593Smuzhiyun "UNKNOWN"
2628*4882a593Smuzhiyun };
2629*4882a593Smuzhiyun
2630*4882a593Smuzhiyun if (reason_detail >= ARRAYSIZE(reason_tbl)) {
2631*4882a593Smuzhiyun DHD_ERROR_ROAM(("UNKNOWN Reason:%u\n", reason_detail));
2632*4882a593Smuzhiyun ASSERT(0);
2633*4882a593Smuzhiyun reason_detail = ARRAYSIZE(reason_tbl) - 1;
2634*4882a593Smuzhiyun
2635*4882a593Smuzhiyun }
2636*4882a593Smuzhiyun return reason_tbl[reason_detail];
2637*4882a593Smuzhiyun }
2638*4882a593Smuzhiyun
pr_roam_bcn_rep_v3(prcd_event_log_hdr_t * plog_hdr)2639*4882a593Smuzhiyun void pr_roam_bcn_rep_v3(prcd_event_log_hdr_t *plog_hdr)
2640*4882a593Smuzhiyun {
2641*4882a593Smuzhiyun roam_log_bcnrpt_rep_v3_t *log = (roam_log_bcnrpt_rep_v3_t *)plog_hdr->log_ptr;
2642*4882a593Smuzhiyun
2643*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BCN_REP: time:%d, verseion:%d count:%d mode:%d\n",
2644*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version,
2645*4882a593Smuzhiyun log->count, log->reason));
2646*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BCN_REP: mode reason(%d):%s scan_stus:%u duration:%u\n",
2647*4882a593Smuzhiyun log->reason_detail, pr_roam_bcn_rep_reason(log->reason_detail),
2648*4882a593Smuzhiyun (log->reason_detail == BCNRPT_RSN_SCAN_FAIL)? log->scan_status:0,
2649*4882a593Smuzhiyun log->duration));
2650*4882a593Smuzhiyun }
2651*4882a593Smuzhiyun
pr_roam_btm_rep_v3(prcd_event_log_hdr_t * plog_hdr)2652*4882a593Smuzhiyun void pr_roam_btm_rep_v3(prcd_event_log_hdr_t *plog_hdr)
2653*4882a593Smuzhiyun {
2654*4882a593Smuzhiyun roam_log_btm_rep_v3_t *log = (roam_log_btm_rep_v3_t *)plog_hdr->log_ptr;
2655*4882a593Smuzhiyun DHD_ERROR_ROAM(("ROAM_LOG_BTM_REP: time:%d version:%d req_mode:%d "
2656*4882a593Smuzhiyun "status:%d ret:%d target:" MACDBG "\n",
2657*4882a593Smuzhiyun plog_hdr->armcycle, log->hdr.version,
2658*4882a593Smuzhiyun log->req_mode, log->status, log->result,
2659*4882a593Smuzhiyun MAC2STRDBG((uint8 *)&log->target_addr)));
2660*4882a593Smuzhiyun }
2661*4882a593Smuzhiyun
2662*4882a593Smuzhiyun void
print_roam_enhanced_log(prcd_event_log_hdr_t * plog_hdr)2663*4882a593Smuzhiyun print_roam_enhanced_log(prcd_event_log_hdr_t *plog_hdr)
2664*4882a593Smuzhiyun {
2665*4882a593Smuzhiyun prsv_periodic_log_hdr_t *hdr = (prsv_periodic_log_hdr_t *)plog_hdr->log_ptr;
2666*4882a593Smuzhiyun uint32 *ptr = (uint32 *)plog_hdr->log_ptr;
2667*4882a593Smuzhiyun int i;
2668*4882a593Smuzhiyun int loop_cnt = hdr->length / sizeof(uint32);
2669*4882a593Smuzhiyun struct bcmstrbuf b;
2670*4882a593Smuzhiyun char pr_buf[EL_LOG_STR_LEN] = { 0 };
2671*4882a593Smuzhiyun const pr_roam_tbl_t *cur_elem = &roam_log_print_tbl[0];
2672*4882a593Smuzhiyun
2673*4882a593Smuzhiyun while (cur_elem && cur_elem->pr_func) {
2674*4882a593Smuzhiyun if (hdr->version == cur_elem->version &&
2675*4882a593Smuzhiyun hdr->id == cur_elem->id) {
2676*4882a593Smuzhiyun cur_elem->pr_func(plog_hdr);
2677*4882a593Smuzhiyun return;
2678*4882a593Smuzhiyun }
2679*4882a593Smuzhiyun cur_elem++;
2680*4882a593Smuzhiyun }
2681*4882a593Smuzhiyun
2682*4882a593Smuzhiyun bcm_binit(&b, pr_buf, EL_LOG_STR_LEN);
2683*4882a593Smuzhiyun bcm_bprintf(&b, "ROAM_LOG_UNKNOWN ID:%d ver:%d armcycle:%d",
2684*4882a593Smuzhiyun hdr->id, hdr->version, plog_hdr->armcycle);
2685*4882a593Smuzhiyun for (i = 0; i < loop_cnt && b.size > 0; i++) {
2686*4882a593Smuzhiyun bcm_bprintf(&b, " %x", *ptr);
2687*4882a593Smuzhiyun ptr++;
2688*4882a593Smuzhiyun }
2689*4882a593Smuzhiyun DHD_ERROR_ROAM(("%s\n", b.origbuf));
2690*4882a593Smuzhiyun }
2691*4882a593Smuzhiyun
2692*4882a593Smuzhiyun /*
2693*4882a593Smuzhiyun * dhd_dbg_attach: initialziation of dhd dbugability module
2694*4882a593Smuzhiyun *
2695*4882a593Smuzhiyun * Return: An error code or 0 on success.
2696*4882a593Smuzhiyun */
2697*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
2698*4882a593Smuzhiyun struct dhd_dbg_ring_buf g_ring_buf;
2699*4882a593Smuzhiyun #endif /* DHD_DEBUGABILITY_LOG_DUMP_RING */
2700*4882a593Smuzhiyun int
dhd_dbg_attach(dhd_pub_t * dhdp,dbg_pullreq_t os_pullreq,dbg_urgent_noti_t os_urgent_notifier,void * os_priv)2701*4882a593Smuzhiyun dhd_dbg_attach(dhd_pub_t *dhdp, dbg_pullreq_t os_pullreq,
2702*4882a593Smuzhiyun dbg_urgent_noti_t os_urgent_notifier, void *os_priv)
2703*4882a593Smuzhiyun {
2704*4882a593Smuzhiyun dhd_dbg_t *dbg = NULL;
2705*4882a593Smuzhiyun dhd_dbg_ring_t *ring = NULL;
2706*4882a593Smuzhiyun int ret = BCME_ERROR, ring_id = 0;
2707*4882a593Smuzhiyun void *buf = NULL;
2708*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
2709*4882a593Smuzhiyun struct dhd_dbg_ring_buf *ring_buf;
2710*4882a593Smuzhiyun #endif /* DHD_DEBUGABILITY_LOG_DUMP_RING */
2711*4882a593Smuzhiyun
2712*4882a593Smuzhiyun dbg = MALLOCZ(dhdp->osh, sizeof(dhd_dbg_t));
2713*4882a593Smuzhiyun if (!dbg)
2714*4882a593Smuzhiyun return BCME_NOMEM;
2715*4882a593Smuzhiyun
2716*4882a593Smuzhiyun #ifdef CONFIG_DHD_USE_STATIC_BUF
2717*4882a593Smuzhiyun buf = DHD_OS_PREALLOC(dhdp, DHD_PREALLOC_FW_VERBOSE_RING, FW_VERBOSE_RING_SIZE);
2718*4882a593Smuzhiyun #else
2719*4882a593Smuzhiyun buf = MALLOCZ(dhdp->osh, FW_VERBOSE_RING_SIZE);
2720*4882a593Smuzhiyun #endif
2721*4882a593Smuzhiyun if (!buf)
2722*4882a593Smuzhiyun goto error;
2723*4882a593Smuzhiyun ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[FW_VERBOSE_RING_ID], FW_VERBOSE_RING_ID,
2724*4882a593Smuzhiyun (uint8 *)FW_VERBOSE_RING_NAME, FW_VERBOSE_RING_SIZE, buf, FALSE);
2725*4882a593Smuzhiyun if (ret)
2726*4882a593Smuzhiyun goto error;
2727*4882a593Smuzhiyun
2728*4882a593Smuzhiyun #ifdef CONFIG_DHD_USE_STATIC_BUF
2729*4882a593Smuzhiyun buf = DHD_OS_PREALLOC(dhdp, DHD_PREALLOC_DHD_EVENT_RING, DHD_EVENT_RING_SIZE);
2730*4882a593Smuzhiyun #else
2731*4882a593Smuzhiyun buf = MALLOCZ(dhdp->osh, DHD_EVENT_RING_SIZE);
2732*4882a593Smuzhiyun #endif
2733*4882a593Smuzhiyun if (!buf)
2734*4882a593Smuzhiyun goto error;
2735*4882a593Smuzhiyun ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[DHD_EVENT_RING_ID], DHD_EVENT_RING_ID,
2736*4882a593Smuzhiyun (uint8 *)DHD_EVENT_RING_NAME, DHD_EVENT_RING_SIZE, buf, FALSE);
2737*4882a593Smuzhiyun if (ret)
2738*4882a593Smuzhiyun goto error;
2739*4882a593Smuzhiyun
2740*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
2741*4882a593Smuzhiyun buf = MALLOCZ(dhdp->osh, DRIVER_LOG_RING_SIZE);
2742*4882a593Smuzhiyun if (!buf)
2743*4882a593Smuzhiyun goto error;
2744*4882a593Smuzhiyun ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[DRIVER_LOG_RING_ID], DRIVER_LOG_RING_ID,
2745*4882a593Smuzhiyun (uint8 *)DRIVER_LOG_RING_NAME, DRIVER_LOG_RING_SIZE, buf, FALSE);
2746*4882a593Smuzhiyun if (ret)
2747*4882a593Smuzhiyun goto error;
2748*4882a593Smuzhiyun
2749*4882a593Smuzhiyun buf = MALLOCZ(dhdp->osh, ROAM_STATS_RING_SIZE);
2750*4882a593Smuzhiyun if (!buf)
2751*4882a593Smuzhiyun goto error;
2752*4882a593Smuzhiyun ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[ROAM_STATS_RING_ID], ROAM_STATS_RING_ID,
2753*4882a593Smuzhiyun (uint8 *)ROAM_STATS_RING_NAME, ROAM_STATS_RING_SIZE, buf, FALSE);
2754*4882a593Smuzhiyun if (ret)
2755*4882a593Smuzhiyun goto error;
2756*4882a593Smuzhiyun #endif /* DHD_DEBUGABILITY_LOG_DUMP_RING */
2757*4882a593Smuzhiyun #ifdef BTLOG
2758*4882a593Smuzhiyun buf = MALLOCZ(dhdp->osh, BT_LOG_RING_SIZE);
2759*4882a593Smuzhiyun if (!buf)
2760*4882a593Smuzhiyun goto error;
2761*4882a593Smuzhiyun ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[BT_LOG_RING_ID], BT_LOG_RING_ID,
2762*4882a593Smuzhiyun BT_LOG_RING_NAME, BT_LOG_RING_SIZE, buf, FALSE);
2763*4882a593Smuzhiyun if (ret)
2764*4882a593Smuzhiyun goto error;
2765*4882a593Smuzhiyun #endif /* BTLOG */
2766*4882a593Smuzhiyun
2767*4882a593Smuzhiyun dbg->private = os_priv;
2768*4882a593Smuzhiyun dbg->pullreq = os_pullreq;
2769*4882a593Smuzhiyun dbg->urgent_notifier = os_urgent_notifier;
2770*4882a593Smuzhiyun dhdp->dbg = dbg;
2771*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
2772*4882a593Smuzhiyun ring_buf = &g_ring_buf;
2773*4882a593Smuzhiyun ring_buf->dhd_pub = dhdp;
2774*4882a593Smuzhiyun #endif /* DHD_DEBUGABILITY_LOG_DUMP_RING */
2775*4882a593Smuzhiyun return BCME_OK;
2776*4882a593Smuzhiyun
2777*4882a593Smuzhiyun error:
2778*4882a593Smuzhiyun for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) {
2779*4882a593Smuzhiyun if (VALID_RING(dbg->dbg_rings[ring_id].id)) {
2780*4882a593Smuzhiyun ring = &dbg->dbg_rings[ring_id];
2781*4882a593Smuzhiyun dhd_dbg_ring_deinit(dhdp, ring);
2782*4882a593Smuzhiyun if (ring->ring_buf) {
2783*4882a593Smuzhiyun #ifndef CONFIG_DHD_USE_STATIC_BUF
2784*4882a593Smuzhiyun MFREE(dhdp->osh, ring->ring_buf, ring->ring_size);
2785*4882a593Smuzhiyun #endif
2786*4882a593Smuzhiyun ring->ring_buf = NULL;
2787*4882a593Smuzhiyun }
2788*4882a593Smuzhiyun ring->ring_size = 0;
2789*4882a593Smuzhiyun }
2790*4882a593Smuzhiyun }
2791*4882a593Smuzhiyun MFREE(dhdp->osh, dbg, sizeof(dhd_dbg_t));
2792*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
2793*4882a593Smuzhiyun ring_buf = &g_ring_buf;
2794*4882a593Smuzhiyun ring_buf->dhd_pub = NULL;
2795*4882a593Smuzhiyun #endif /* DHD_DEBUGABILITY_LOG_DUMP_RING */
2796*4882a593Smuzhiyun
2797*4882a593Smuzhiyun return ret;
2798*4882a593Smuzhiyun }
2799*4882a593Smuzhiyun
2800*4882a593Smuzhiyun /*
2801*4882a593Smuzhiyun * dhd_dbg_detach: clean up dhd dbugability module
2802*4882a593Smuzhiyun */
2803*4882a593Smuzhiyun void
dhd_dbg_detach(dhd_pub_t * dhdp)2804*4882a593Smuzhiyun dhd_dbg_detach(dhd_pub_t *dhdp)
2805*4882a593Smuzhiyun {
2806*4882a593Smuzhiyun int ring_id;
2807*4882a593Smuzhiyun dhd_dbg_t *dbg;
2808*4882a593Smuzhiyun dhd_dbg_ring_t *ring = NULL;
2809*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
2810*4882a593Smuzhiyun struct dhd_dbg_ring_buf *ring_buf;
2811*4882a593Smuzhiyun #endif /* DHD_DEBUGABILITY_LOG_DUMP_RING */
2812*4882a593Smuzhiyun
2813*4882a593Smuzhiyun if (!dhdp->dbg)
2814*4882a593Smuzhiyun return;
2815*4882a593Smuzhiyun
2816*4882a593Smuzhiyun dbg = dhdp->dbg;
2817*4882a593Smuzhiyun for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) {
2818*4882a593Smuzhiyun if (VALID_RING(dbg->dbg_rings[ring_id].id)) {
2819*4882a593Smuzhiyun ring = &dbg->dbg_rings[ring_id];
2820*4882a593Smuzhiyun dhd_dbg_ring_deinit(dhdp, ring);
2821*4882a593Smuzhiyun if (ring->ring_buf) {
2822*4882a593Smuzhiyun #ifndef CONFIG_DHD_USE_STATIC_BUF
2823*4882a593Smuzhiyun MFREE(dhdp->osh, ring->ring_buf, ring->ring_size);
2824*4882a593Smuzhiyun #endif
2825*4882a593Smuzhiyun ring->ring_buf = NULL;
2826*4882a593Smuzhiyun }
2827*4882a593Smuzhiyun ring->ring_size = 0;
2828*4882a593Smuzhiyun }
2829*4882a593Smuzhiyun }
2830*4882a593Smuzhiyun MFREE(dhdp->osh, dhdp->dbg, sizeof(dhd_dbg_t));
2831*4882a593Smuzhiyun #ifdef DHD_DEBUGABILITY_LOG_DUMP_RING
2832*4882a593Smuzhiyun ring_buf = &g_ring_buf;
2833*4882a593Smuzhiyun ring_buf->dhd_pub = NULL;
2834*4882a593Smuzhiyun #endif /* DHD_DEBUGABILITY_LOG_DUMP_RING */
2835*4882a593Smuzhiyun }
2836*4882a593Smuzhiyun
2837*4882a593Smuzhiyun uint32
dhd_dbg_get_fwverbose(dhd_pub_t * dhdp)2838*4882a593Smuzhiyun dhd_dbg_get_fwverbose(dhd_pub_t *dhdp)
2839*4882a593Smuzhiyun {
2840*4882a593Smuzhiyun if (dhdp && dhdp->dbg) {
2841*4882a593Smuzhiyun return dhdp->dbg->dbg_rings[FW_VERBOSE_RING_ID].log_level;
2842*4882a593Smuzhiyun }
2843*4882a593Smuzhiyun return 0;
2844*4882a593Smuzhiyun }
2845*4882a593Smuzhiyun
2846*4882a593Smuzhiyun void
dhd_dbg_set_fwverbose(dhd_pub_t * dhdp,uint32 new_val)2847*4882a593Smuzhiyun dhd_dbg_set_fwverbose(dhd_pub_t *dhdp, uint32 new_val)
2848*4882a593Smuzhiyun {
2849*4882a593Smuzhiyun
2850*4882a593Smuzhiyun if (dhdp && dhdp->dbg) {
2851*4882a593Smuzhiyun dhdp->dbg->dbg_rings[FW_VERBOSE_RING_ID].log_level = new_val;
2852*4882a593Smuzhiyun }
2853*4882a593Smuzhiyun }
2854