1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * DHD debugability: Status Information Logging 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 <linuxver.h>
27*4882a593Smuzhiyun #include <typedefs.h>
28*4882a593Smuzhiyun #include <osl.h>
29*4882a593Smuzhiyun #include <bcmutils.h>
30*4882a593Smuzhiyun #include <ethernet.h>
31*4882a593Smuzhiyun #include <bcmevent.h>
32*4882a593Smuzhiyun #include <dngl_stats.h>
33*4882a593Smuzhiyun #include <dhd.h>
34*4882a593Smuzhiyun #include <dhd_dbg.h>
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #ifdef DHD_STATUS_LOGGING
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define DHD_STATLOG_ERR_INTERNAL(fmt, ...) DHD_ERROR(("STATLOG-" fmt, ##__VA_ARGS__))
39*4882a593Smuzhiyun #define DHD_STATLOG_INFO_INTERNAL(fmt, ...) DHD_INFO(("STATLOG-" fmt, ##__VA_ARGS__))
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define DHD_STATLOG_PRINT(x) DHD_ERROR(x)
42*4882a593Smuzhiyun #define DHD_STATLOG_ERR(x) DHD_STATLOG_ERR_INTERNAL x
43*4882a593Smuzhiyun #define DHD_STATLOG_INFO(x) DHD_STATLOG_INFO_INTERNAL x
44*4882a593Smuzhiyun #define DHD_STATLOG_VALID(stat) (((stat) > (ST(INVALID))) && ((stat) < (ST(MAX))))
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun dhd_statlog_handle_t *
dhd_attach_statlog(dhd_pub_t * dhdp,uint32 num_items,uint32 bdlog_num_items,uint32 logbuf_len)47*4882a593Smuzhiyun dhd_attach_statlog(dhd_pub_t *dhdp, uint32 num_items, uint32 bdlog_num_items, uint32 logbuf_len)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun dhd_statlog_t *statlog = NULL;
50*4882a593Smuzhiyun void *buf = NULL;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun if (!dhdp) {
53*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: dhdp is NULL\n", __FUNCTION__));
54*4882a593Smuzhiyun return NULL;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun statlog = (dhd_statlog_t *)VMALLOCZ(dhdp->osh, sizeof(dhd_statlog_t));
58*4882a593Smuzhiyun if (!statlog) {
59*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to allocate memory for dhd_statlog_t\n",
60*4882a593Smuzhiyun __FUNCTION__));
61*4882a593Smuzhiyun return NULL;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* allocate log buffer */
65*4882a593Smuzhiyun statlog->logbuf = (uint8 *)VMALLOCZ(dhdp->osh, logbuf_len);
66*4882a593Smuzhiyun if (!statlog->logbuf) {
67*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to alloc log buffer\n", __FUNCTION__));
68*4882a593Smuzhiyun goto error;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun statlog->logbuf_len = logbuf_len;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /* alloc ring buffer */
73*4882a593Smuzhiyun statlog->bufsize = (uint32)(dhd_ring_get_hdr_size() +
74*4882a593Smuzhiyun DHD_STATLOG_RING_SIZE(num_items));
75*4882a593Smuzhiyun buf = VMALLOCZ(dhdp->osh, statlog->bufsize);
76*4882a593Smuzhiyun if (!buf) {
77*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to allocate memory for ring buffer\n",
78*4882a593Smuzhiyun __FUNCTION__));
79*4882a593Smuzhiyun goto error;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun statlog->ringbuf = dhd_ring_init(dhdp, buf, statlog->bufsize,
83*4882a593Smuzhiyun DHD_STATLOG_ITEM_SIZE, num_items, DHD_RING_TYPE_SINGLE_IDX);
84*4882a593Smuzhiyun if (!statlog->ringbuf) {
85*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to init ring buffer\n", __FUNCTION__));
86*4882a593Smuzhiyun VMFREE(dhdp->osh, buf, statlog->bufsize);
87*4882a593Smuzhiyun goto error;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* alloc ring buffer for bigdata logging */
91*4882a593Smuzhiyun statlog->bdlog_bufsize = (uint32)(dhd_ring_get_hdr_size() +
92*4882a593Smuzhiyun DHD_STATLOG_RING_SIZE(bdlog_num_items));
93*4882a593Smuzhiyun buf = VMALLOCZ(dhdp->osh, statlog->bdlog_bufsize);
94*4882a593Smuzhiyun if (!buf) {
95*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to allocate memory for bigdata logging buffer\n",
96*4882a593Smuzhiyun __FUNCTION__));
97*4882a593Smuzhiyun goto error;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun statlog->bdlog_ringbuf = dhd_ring_init(dhdp, buf, statlog->bdlog_bufsize,
101*4882a593Smuzhiyun DHD_STATLOG_ITEM_SIZE, bdlog_num_items, DHD_RING_TYPE_SINGLE_IDX);
102*4882a593Smuzhiyun if (!statlog->bdlog_ringbuf) {
103*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to init ring buffer for bigdata logging\n",
104*4882a593Smuzhiyun __FUNCTION__));
105*4882a593Smuzhiyun VMFREE(dhdp->osh, buf, statlog->bdlog_bufsize);
106*4882a593Smuzhiyun goto error;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun return (dhd_statlog_handle_t *)statlog;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun error:
112*4882a593Smuzhiyun if (statlog->logbuf) {
113*4882a593Smuzhiyun VMFREE(dhdp->osh, statlog->logbuf, logbuf_len);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun if (statlog->ringbuf) {
117*4882a593Smuzhiyun dhd_ring_deinit(dhdp, statlog->ringbuf);
118*4882a593Smuzhiyun VMFREE(dhdp->osh, statlog->ringbuf, statlog->bufsize);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (statlog->bdlog_ringbuf) {
122*4882a593Smuzhiyun dhd_ring_deinit(dhdp, statlog->bdlog_ringbuf);
123*4882a593Smuzhiyun VMFREE(dhdp->osh, statlog->bdlog_ringbuf, statlog->bdlog_bufsize);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun if (statlog) {
127*4882a593Smuzhiyun VMFREE(dhdp->osh, statlog, sizeof(dhd_statlog_t));
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun return NULL;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun void
dhd_detach_statlog(dhd_pub_t * dhdp)134*4882a593Smuzhiyun dhd_detach_statlog(dhd_pub_t *dhdp)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun dhd_statlog_t *statlog;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun if (!dhdp) {
139*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: dhdp is NULL\n", __FUNCTION__));
140*4882a593Smuzhiyun return;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (!dhdp->statlog) {
144*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: statlog is NULL\n", __FUNCTION__));
145*4882a593Smuzhiyun return;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun statlog = (dhd_statlog_t *)(dhdp->statlog);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun if (statlog->bdlog_ringbuf) {
151*4882a593Smuzhiyun dhd_ring_deinit(dhdp, statlog->bdlog_ringbuf);
152*4882a593Smuzhiyun VMFREE(dhdp->osh, statlog->bdlog_ringbuf, statlog->bdlog_bufsize);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun if (statlog->ringbuf) {
156*4882a593Smuzhiyun dhd_ring_deinit(dhdp, statlog->ringbuf);
157*4882a593Smuzhiyun VMFREE(dhdp->osh, statlog->ringbuf, statlog->bufsize);
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun if (statlog->logbuf) {
161*4882a593Smuzhiyun VMFREE(dhdp->osh, statlog->logbuf, statlog->logbuf_len);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun VMFREE(dhdp->osh, statlog, sizeof(dhd_statlog_t));
165*4882a593Smuzhiyun dhdp->statlog = NULL;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun static int
dhd_statlog_ring_log(dhd_pub_t * dhdp,uint16 stat,uint8 ifidx,uint8 dir,uint16 status,uint16 reason)169*4882a593Smuzhiyun dhd_statlog_ring_log(dhd_pub_t *dhdp, uint16 stat, uint8 ifidx, uint8 dir,
170*4882a593Smuzhiyun uint16 status, uint16 reason)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun dhd_statlog_t *statlog;
173*4882a593Smuzhiyun stat_elem_t *elem;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun if (!dhdp || !dhdp->statlog) {
176*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: dhdp or dhdp->statlog is NULL\n",
177*4882a593Smuzhiyun __FUNCTION__));
178*4882a593Smuzhiyun return BCME_ERROR;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun if (ifidx >= DHD_MAX_IFS) {
182*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: invalid ifidx %d\n", __FUNCTION__, ifidx));
183*4882a593Smuzhiyun return BCME_ERROR;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun if (!DHD_STATLOG_VALID(stat)) {
187*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: invalid stat %d\n", __FUNCTION__, stat));
188*4882a593Smuzhiyun return BCME_ERROR;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun statlog = (dhd_statlog_t *)(dhdp->statlog);
192*4882a593Smuzhiyun elem = (stat_elem_t *)dhd_ring_get_empty(statlog->ringbuf);
193*4882a593Smuzhiyun if (!elem) {
194*4882a593Smuzhiyun /* no available slot */
195*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: cannot allocate a new element\n",
196*4882a593Smuzhiyun __FUNCTION__));
197*4882a593Smuzhiyun return BCME_ERROR;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun elem->ts_tz = OSL_SYSTZTIME_US();
201*4882a593Smuzhiyun elem->ts = OSL_LOCALTIME_NS();
202*4882a593Smuzhiyun elem->stat = stat;
203*4882a593Smuzhiyun elem->ifidx = ifidx;
204*4882a593Smuzhiyun elem->dir = dir;
205*4882a593Smuzhiyun elem->reason = reason;
206*4882a593Smuzhiyun elem->status = status;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* Logging for the bigdata */
209*4882a593Smuzhiyun if (isset(statlog->bdmask, stat)) {
210*4882a593Smuzhiyun stat_elem_t *elem_bd;
211*4882a593Smuzhiyun elem_bd = (stat_elem_t *)dhd_ring_get_empty(statlog->bdlog_ringbuf);
212*4882a593Smuzhiyun if (!elem_bd) {
213*4882a593Smuzhiyun /* no available slot */
214*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: cannot allocate a new element for bigdata\n",
215*4882a593Smuzhiyun __FUNCTION__));
216*4882a593Smuzhiyun return BCME_ERROR;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun bcopy(elem, elem_bd, sizeof(stat_elem_t));
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun return BCME_OK;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun int
dhd_statlog_ring_log_data(dhd_pub_t * dhdp,uint16 stat,uint8 ifidx,uint8 dir,bool cond)225*4882a593Smuzhiyun dhd_statlog_ring_log_data(dhd_pub_t *dhdp, uint16 stat, uint8 ifidx,
226*4882a593Smuzhiyun uint8 dir, bool cond)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun return cond ? dhd_statlog_ring_log(dhdp, stat, ifidx,
229*4882a593Smuzhiyun dir ? STDIR(TX) : STDIR(RX), 0, 0) : BCME_OK;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun int
dhd_statlog_ring_log_data_reason(dhd_pub_t * dhdp,uint16 stat,uint8 ifidx,uint8 dir,uint16 reason)233*4882a593Smuzhiyun dhd_statlog_ring_log_data_reason(dhd_pub_t *dhdp, uint16 stat,
234*4882a593Smuzhiyun uint8 ifidx, uint8 dir, uint16 reason)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun return dhd_statlog_ring_log(dhdp, stat, ifidx,
237*4882a593Smuzhiyun dir ? STDIR(TX) : STDIR(RX), 0, reason);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun int
dhd_statlog_ring_log_ctrl(dhd_pub_t * dhdp,uint16 stat,uint8 ifidx,uint16 reason)241*4882a593Smuzhiyun dhd_statlog_ring_log_ctrl(dhd_pub_t *dhdp, uint16 stat, uint8 ifidx, uint16 reason)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun return dhd_statlog_ring_log(dhdp, stat, ifidx, ST(DIR_TX), 0, reason);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun int
dhd_statlog_process_event(dhd_pub_t * dhdp,int type,uint8 ifidx,uint16 status,uint16 reason,uint16 flags)247*4882a593Smuzhiyun dhd_statlog_process_event(dhd_pub_t *dhdp, int type, uint8 ifidx,
248*4882a593Smuzhiyun uint16 status, uint16 reason, uint16 flags)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun int stat = ST(INVALID);
251*4882a593Smuzhiyun uint8 dir = STDIR(RX);
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun if (!dhdp || !dhdp->statlog) {
254*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: dhdp or dhdp->statlog is NULL\n",
255*4882a593Smuzhiyun __FUNCTION__));
256*4882a593Smuzhiyun return BCME_ERROR;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun switch (type) {
260*4882a593Smuzhiyun case WLC_E_SET_SSID:
261*4882a593Smuzhiyun if (status == WLC_E_STATUS_SUCCESS) {
262*4882a593Smuzhiyun stat = ST(ASSOC_DONE);
263*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_TIMEOUT) {
264*4882a593Smuzhiyun stat = ST(ASSOC_TIMEOUT);
265*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_FAIL) {
266*4882a593Smuzhiyun stat = ST(ASSOC_FAIL);
267*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_NO_ACK) {
268*4882a593Smuzhiyun stat = ST(ASSOC_NO_ACK);
269*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_ABORT) {
270*4882a593Smuzhiyun stat = ST(ASSOC_ABORT);
271*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_UNSOLICITED) {
272*4882a593Smuzhiyun stat = ST(ASSOC_UNSOLICITED);
273*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_NO_NETWORKS) {
274*4882a593Smuzhiyun stat = ST(ASSOC_NO_NETWORKS);
275*4882a593Smuzhiyun } else {
276*4882a593Smuzhiyun stat = ST(ASSOC_OTHERS);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun break;
279*4882a593Smuzhiyun case WLC_E_AUTH:
280*4882a593Smuzhiyun if (status == WLC_E_STATUS_SUCCESS) {
281*4882a593Smuzhiyun stat = ST(AUTH_DONE);
282*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_TIMEOUT) {
283*4882a593Smuzhiyun stat = ST(AUTH_TIMEOUT);
284*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_FAIL) {
285*4882a593Smuzhiyun stat = ST(AUTH_FAIL);
286*4882a593Smuzhiyun } else if (status == WLC_E_STATUS_NO_ACK) {
287*4882a593Smuzhiyun stat = ST(AUTH_NO_ACK);
288*4882a593Smuzhiyun } else {
289*4882a593Smuzhiyun stat = ST(AUTH_OTHERS);
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun dir = STDIR(TX);
292*4882a593Smuzhiyun break;
293*4882a593Smuzhiyun case WLC_E_AUTH_IND:
294*4882a593Smuzhiyun stat = ST(AUTH_DONE);
295*4882a593Smuzhiyun break;
296*4882a593Smuzhiyun case WLC_E_DEAUTH:
297*4882a593Smuzhiyun stat = ST(DEAUTH);
298*4882a593Smuzhiyun dir = STDIR(TX);
299*4882a593Smuzhiyun break;
300*4882a593Smuzhiyun case WLC_E_DEAUTH_IND:
301*4882a593Smuzhiyun stat = ST(DEAUTH);
302*4882a593Smuzhiyun break;
303*4882a593Smuzhiyun case WLC_E_DISASSOC:
304*4882a593Smuzhiyun stat = ST(DISASSOC);
305*4882a593Smuzhiyun dir = STDIR(TX);
306*4882a593Smuzhiyun break;
307*4882a593Smuzhiyun case WLC_E_LINK:
308*4882a593Smuzhiyun if (!(flags & WLC_EVENT_MSG_LINK)) {
309*4882a593Smuzhiyun stat = ST(LINKDOWN);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun break;
312*4882a593Smuzhiyun case WLC_E_ROAM_PREP:
313*4882a593Smuzhiyun stat = ST(REASSOC_START);
314*4882a593Smuzhiyun break;
315*4882a593Smuzhiyun case WLC_E_ASSOC_REQ_IE:
316*4882a593Smuzhiyun stat = ST(ASSOC_REQ);
317*4882a593Smuzhiyun dir = STDIR(TX);
318*4882a593Smuzhiyun break;
319*4882a593Smuzhiyun case WLC_E_ASSOC_RESP_IE:
320*4882a593Smuzhiyun stat = ST(ASSOC_RESP);
321*4882a593Smuzhiyun break;
322*4882a593Smuzhiyun case WLC_E_BSSID:
323*4882a593Smuzhiyun if (status == WLC_E_STATUS_SUCCESS) {
324*4882a593Smuzhiyun stat = ST(REASSOC_DONE);
325*4882a593Smuzhiyun } else {
326*4882a593Smuzhiyun stat = ST(REASSOC_DONE_OTHERS);
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun break;
329*4882a593Smuzhiyun case WLC_E_REASSOC:
330*4882a593Smuzhiyun if (status == WLC_E_STATUS_SUCCESS) {
331*4882a593Smuzhiyun stat = ST(REASSOC_SUCCESS);
332*4882a593Smuzhiyun } else {
333*4882a593Smuzhiyun stat = ST(REASSOC_FAILURE);
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun dir = STDIR(TX);
336*4882a593Smuzhiyun break;
337*4882a593Smuzhiyun case WLC_E_ASSOC_IND:
338*4882a593Smuzhiyun stat = ST(ASSOC_REQ);
339*4882a593Smuzhiyun break;
340*4882a593Smuzhiyun default:
341*4882a593Smuzhiyun break;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* logging interested events */
345*4882a593Smuzhiyun if (DHD_STATLOG_VALID(stat)) {
346*4882a593Smuzhiyun dhd_statlog_ring_log(dhdp, stat, ifidx, dir, status, reason);
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun return BCME_OK;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun uint32
dhd_statlog_get_logbuf_len(dhd_pub_t * dhdp)353*4882a593Smuzhiyun dhd_statlog_get_logbuf_len(dhd_pub_t *dhdp)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun uint32 length = 0;
356*4882a593Smuzhiyun dhd_statlog_t *statlog;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun if (dhdp && dhdp->statlog) {
359*4882a593Smuzhiyun statlog = (dhd_statlog_t *)(dhdp->statlog);
360*4882a593Smuzhiyun length = statlog->logbuf_len;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun return length;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun void *
dhd_statlog_get_logbuf(dhd_pub_t * dhdp)367*4882a593Smuzhiyun dhd_statlog_get_logbuf(dhd_pub_t *dhdp)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun dhd_statlog_t *statlog;
370*4882a593Smuzhiyun void *ret_addr = NULL;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun if (dhdp && dhdp->statlog) {
373*4882a593Smuzhiyun statlog = (dhd_statlog_t *)(dhdp->statlog);
374*4882a593Smuzhiyun ret_addr = (void *)(statlog->logbuf);
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun return ret_addr;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun /*
381*4882a593Smuzhiyun * called function uses buflen as the DHD_STATLOG_STATSTR_BUF_LEN max.
382*4882a593Smuzhiyun * So when adding a case, make sure the string is less than
383*4882a593Smuzhiyun * the DHD_STATLOG_STATSTR_BUF_LEN bytes
384*4882a593Smuzhiyun */
385*4882a593Smuzhiyun static void
dhd_statlog_stat_name(char * buf,uint32 buflen,uint32 state,uint8 dir)386*4882a593Smuzhiyun dhd_statlog_stat_name(char *buf, uint32 buflen, uint32 state, uint8 dir)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun char *stat_str = NULL;
389*4882a593Smuzhiyun bool tx = (dir == STDIR(TX));
390*4882a593Smuzhiyun uint32 max_buf_len = MIN(buflen, DHD_STATLOG_STATSTR_BUF_LEN);
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun switch (state) {
393*4882a593Smuzhiyun case ST(INVALID):
394*4882a593Smuzhiyun stat_str = "INVALID_STATE";
395*4882a593Smuzhiyun break;
396*4882a593Smuzhiyun case ST(WLAN_POWER_ON):
397*4882a593Smuzhiyun stat_str = "WLAN_POWER_ON";
398*4882a593Smuzhiyun break;
399*4882a593Smuzhiyun case ST(WLAN_POWER_OFF):
400*4882a593Smuzhiyun stat_str = "WLAN_POWER_OFF";
401*4882a593Smuzhiyun break;
402*4882a593Smuzhiyun case ST(ASSOC_START):
403*4882a593Smuzhiyun stat_str = "ASSOC_START";
404*4882a593Smuzhiyun break;
405*4882a593Smuzhiyun case ST(AUTH_DONE):
406*4882a593Smuzhiyun stat_str = "AUTH_DONE";
407*4882a593Smuzhiyun break;
408*4882a593Smuzhiyun case ST(ASSOC_REQ):
409*4882a593Smuzhiyun stat_str = tx ? "ASSOC_REQ" : "RX_ASSOC_REQ";
410*4882a593Smuzhiyun break;
411*4882a593Smuzhiyun case ST(ASSOC_RESP):
412*4882a593Smuzhiyun stat_str = "ASSOC_RESP";
413*4882a593Smuzhiyun break;
414*4882a593Smuzhiyun case ST(ASSOC_DONE):
415*4882a593Smuzhiyun stat_str = "ASSOC_DONE";
416*4882a593Smuzhiyun break;
417*4882a593Smuzhiyun case ST(DISASSOC_START):
418*4882a593Smuzhiyun stat_str = "DISASSOC_START";
419*4882a593Smuzhiyun break;
420*4882a593Smuzhiyun case ST(DISASSOC_INT_START):
421*4882a593Smuzhiyun stat_str = "DISASSOC_INTERNAL_START";
422*4882a593Smuzhiyun break;
423*4882a593Smuzhiyun case ST(DISASSOC_DONE):
424*4882a593Smuzhiyun stat_str = "DISASSOC_DONE";
425*4882a593Smuzhiyun break;
426*4882a593Smuzhiyun case ST(DISASSOC):
427*4882a593Smuzhiyun stat_str = tx ? "DISASSOC_EVENT" : "DISASSOC_IND_EVENT";
428*4882a593Smuzhiyun break;
429*4882a593Smuzhiyun case ST(DEAUTH):
430*4882a593Smuzhiyun stat_str = tx ? "DEAUTH_EVENT" : "DEAUTH_IND_EVENT";
431*4882a593Smuzhiyun break;
432*4882a593Smuzhiyun case ST(LINKDOWN):
433*4882a593Smuzhiyun stat_str = "LINKDOWN_EVENT";
434*4882a593Smuzhiyun break;
435*4882a593Smuzhiyun case ST(REASSOC_START):
436*4882a593Smuzhiyun stat_str = "REASSOC_START";
437*4882a593Smuzhiyun break;
438*4882a593Smuzhiyun case ST(REASSOC_INFORM):
439*4882a593Smuzhiyun stat_str = "REASSOC_INFORM";
440*4882a593Smuzhiyun break;
441*4882a593Smuzhiyun case ST(REASSOC_DONE):
442*4882a593Smuzhiyun stat_str = "REASSOC_DONE_SUCCESS";
443*4882a593Smuzhiyun break;
444*4882a593Smuzhiyun case ST(EAPOL_M1):
445*4882a593Smuzhiyun stat_str = tx ? "TX_EAPOL_M1" : "RX_EAPOL_M1";
446*4882a593Smuzhiyun break;
447*4882a593Smuzhiyun case ST(EAPOL_M2):
448*4882a593Smuzhiyun stat_str = tx ? "TX_EAPOL_M2" : "RX_EAPOL_M2";
449*4882a593Smuzhiyun break;
450*4882a593Smuzhiyun case ST(EAPOL_M3):
451*4882a593Smuzhiyun stat_str = tx ? "TX_EAPOL_M3" : "RX_EAPOL_M3";
452*4882a593Smuzhiyun break;
453*4882a593Smuzhiyun case ST(EAPOL_M4):
454*4882a593Smuzhiyun stat_str = tx ? "TX_EAPOL_M4" : "RX_EAPOL_M4";
455*4882a593Smuzhiyun break;
456*4882a593Smuzhiyun case ST(EAPOL_GROUPKEY_M1):
457*4882a593Smuzhiyun stat_str = tx ? "TX_EAPOL_GROUPKEY_M1" : "RX_EAPOL_GROUPKEY_M1";
458*4882a593Smuzhiyun break;
459*4882a593Smuzhiyun case ST(EAPOL_GROUPKEY_M2):
460*4882a593Smuzhiyun stat_str = tx ? "TX_EAPOL_GROUPKEY_M2" : "RX_EAPOL_GROUPKEY_M2";
461*4882a593Smuzhiyun break;
462*4882a593Smuzhiyun case ST(EAP_REQ_IDENTITY):
463*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_IDENTITY" : "RX_EAP_REQ_IDENTITY";
464*4882a593Smuzhiyun break;
465*4882a593Smuzhiyun case ST(EAP_RESP_IDENTITY):
466*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_IDENTITY" : "RX_EAP_RESP_IDENTITY";
467*4882a593Smuzhiyun break;
468*4882a593Smuzhiyun case ST(EAP_REQ_TLS):
469*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_TLS" : "RX_EAP_REQ_TLS";
470*4882a593Smuzhiyun break;
471*4882a593Smuzhiyun case ST(EAP_RESP_TLS):
472*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_TLS" : "RX_EAP_RESP_TLS";
473*4882a593Smuzhiyun break;
474*4882a593Smuzhiyun case ST(EAP_REQ_LEAP):
475*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_LEAP" : "RX_EAP_REQ_LEAP";
476*4882a593Smuzhiyun break;
477*4882a593Smuzhiyun case ST(EAP_RESP_LEAP):
478*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_LEAP" : "RX_EAP_RESP_LEAP";
479*4882a593Smuzhiyun break;
480*4882a593Smuzhiyun case ST(EAP_REQ_TTLS):
481*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_TTLS" : "RX_EAP_REQ_TTLS";
482*4882a593Smuzhiyun break;
483*4882a593Smuzhiyun case ST(EAP_RESP_TTLS):
484*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_TTLS" : "RX_EAP_RESP_TTLS";
485*4882a593Smuzhiyun break;
486*4882a593Smuzhiyun case ST(EAP_REQ_AKA):
487*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_AKA" : "RX_EAP_REQ_AKA";
488*4882a593Smuzhiyun break;
489*4882a593Smuzhiyun case ST(EAP_RESP_AKA):
490*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_AKA" : "RX_EAP_RESP_AKA";
491*4882a593Smuzhiyun break;
492*4882a593Smuzhiyun case ST(EAP_REQ_PEAP):
493*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_PEAP" : "RX_EAP_REQ_PEAP";
494*4882a593Smuzhiyun break;
495*4882a593Smuzhiyun case ST(EAP_RESP_PEAP):
496*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_PEAP" : "RX_EAP_RESP_PEAP";
497*4882a593Smuzhiyun break;
498*4882a593Smuzhiyun case ST(EAP_REQ_FAST):
499*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_FAST" : "RX_EAP_REQ_FAST";
500*4882a593Smuzhiyun break;
501*4882a593Smuzhiyun case ST(EAP_RESP_FAST):
502*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_FAST" : "RX_EAP_RESP_FAST";
503*4882a593Smuzhiyun break;
504*4882a593Smuzhiyun case ST(EAP_REQ_PSK):
505*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_PSK" : "RX_EAP_REQ_PSK";
506*4882a593Smuzhiyun break;
507*4882a593Smuzhiyun case ST(EAP_RESP_PSK):
508*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_PSK" : "RX_EAP_RESP_PSK";
509*4882a593Smuzhiyun break;
510*4882a593Smuzhiyun case ST(EAP_REQ_AKAP):
511*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_REQ_AKAP" : "RX_EAP_REQ_AKAP";
512*4882a593Smuzhiyun break;
513*4882a593Smuzhiyun case ST(EAP_RESP_AKAP):
514*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_RESP_AKAP" : "RX_EAP_RESP_AKAP";
515*4882a593Smuzhiyun break;
516*4882a593Smuzhiyun case ST(EAP_SUCCESS):
517*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_SUCCESS" : "RX_EAP_SUCCESS";
518*4882a593Smuzhiyun break;
519*4882a593Smuzhiyun case ST(EAP_FAILURE):
520*4882a593Smuzhiyun stat_str = tx ? "TX_EAP_FAILURE" : "RX_EAP_FAILURE";
521*4882a593Smuzhiyun break;
522*4882a593Smuzhiyun case ST(EAPOL_START):
523*4882a593Smuzhiyun stat_str = tx ? "TX_EAPOL_START" : "RX_EAPOL_START";
524*4882a593Smuzhiyun break;
525*4882a593Smuzhiyun case ST(WSC_START):
526*4882a593Smuzhiyun stat_str = tx ? "TX_WSC_START" : "RX_WSC_START";
527*4882a593Smuzhiyun break;
528*4882a593Smuzhiyun case ST(WSC_DONE):
529*4882a593Smuzhiyun stat_str = tx ? "TX_WSC_DONE" : "RX_WSC_DONE";
530*4882a593Smuzhiyun break;
531*4882a593Smuzhiyun case ST(WPS_M1):
532*4882a593Smuzhiyun stat_str = tx ? "TX_WPS_M1" : "RX_WPS_M1";
533*4882a593Smuzhiyun break;
534*4882a593Smuzhiyun case ST(WPS_M2):
535*4882a593Smuzhiyun stat_str = tx ? "TX_WPS_M2" : "RX_WPS_M2";
536*4882a593Smuzhiyun break;
537*4882a593Smuzhiyun case ST(WPS_M3):
538*4882a593Smuzhiyun stat_str = tx ? "TX_WPS_M3" : "RX_WPS_M3";
539*4882a593Smuzhiyun break;
540*4882a593Smuzhiyun case ST(WPS_M4):
541*4882a593Smuzhiyun stat_str = tx ? "TX_WPS_M4" : "RX_WPS_M4";
542*4882a593Smuzhiyun break;
543*4882a593Smuzhiyun case ST(WPS_M5):
544*4882a593Smuzhiyun stat_str = tx ? "TX_WPS_M5" : "RX_WPS_M5";
545*4882a593Smuzhiyun break;
546*4882a593Smuzhiyun case ST(WPS_M6):
547*4882a593Smuzhiyun stat_str = tx ? "TX_WPS_M6" : "RX_WPS_M6";
548*4882a593Smuzhiyun break;
549*4882a593Smuzhiyun case ST(WPS_M7):
550*4882a593Smuzhiyun stat_str = tx ? "TX_WPS_M7" : "RX_WPS_M7";
551*4882a593Smuzhiyun break;
552*4882a593Smuzhiyun case ST(WPS_M8):
553*4882a593Smuzhiyun stat_str = tx ? "TX_WPS_M8" : "RX_WPS_M8";
554*4882a593Smuzhiyun break;
555*4882a593Smuzhiyun case ST(8021X_OTHER):
556*4882a593Smuzhiyun stat_str = tx ? "TX_OTHER_8021X" : "RX_OTHER_8021X";
557*4882a593Smuzhiyun break;
558*4882a593Smuzhiyun case ST(INSTALL_KEY):
559*4882a593Smuzhiyun stat_str = "INSTALL_KEY";
560*4882a593Smuzhiyun break;
561*4882a593Smuzhiyun case ST(DELETE_KEY):
562*4882a593Smuzhiyun stat_str = "DELETE_KEY";
563*4882a593Smuzhiyun break;
564*4882a593Smuzhiyun case ST(INSTALL_PMKSA):
565*4882a593Smuzhiyun stat_str = "INSTALL_PMKSA";
566*4882a593Smuzhiyun break;
567*4882a593Smuzhiyun case ST(INSTALL_OKC_PMK):
568*4882a593Smuzhiyun stat_str = "INSTALL_OKC_PMK";
569*4882a593Smuzhiyun break;
570*4882a593Smuzhiyun case ST(DHCP_DISCOVER):
571*4882a593Smuzhiyun stat_str = tx ? "TX_DHCP_DISCOVER" : "RX_DHCP_DISCOVER";
572*4882a593Smuzhiyun break;
573*4882a593Smuzhiyun case ST(DHCP_OFFER):
574*4882a593Smuzhiyun stat_str = tx ? "TX_DHCP_OFFER" : "RX_DHCP_OFFER";
575*4882a593Smuzhiyun break;
576*4882a593Smuzhiyun case ST(DHCP_REQUEST):
577*4882a593Smuzhiyun stat_str = tx ? "TX_DHCP_REQUEST" : "RX_DHCP_REQUEST";
578*4882a593Smuzhiyun break;
579*4882a593Smuzhiyun case ST(DHCP_DECLINE):
580*4882a593Smuzhiyun stat_str = tx ? "TX_DHCP_DECLINE" : "RX_DHCP_DECLINE";
581*4882a593Smuzhiyun break;
582*4882a593Smuzhiyun case ST(DHCP_ACK):
583*4882a593Smuzhiyun stat_str = tx ? "TX_DHCP_ACK" : "RX_DHCP_ACK";
584*4882a593Smuzhiyun break;
585*4882a593Smuzhiyun case ST(DHCP_NAK):
586*4882a593Smuzhiyun stat_str = tx ? "TX_DHCP_NAK" : "RX_DHCP_NAK";
587*4882a593Smuzhiyun break;
588*4882a593Smuzhiyun case ST(DHCP_RELEASE):
589*4882a593Smuzhiyun stat_str = tx ? "TX_DHCP_RELEASE" : "RX_DHCP_RELEASE";
590*4882a593Smuzhiyun break;
591*4882a593Smuzhiyun case ST(DHCP_INFORM):
592*4882a593Smuzhiyun stat_str = tx ? "TX_DHCP_INFORM" : "RX_DHCP_INFORM";
593*4882a593Smuzhiyun break;
594*4882a593Smuzhiyun case ST(ICMP_PING_REQ):
595*4882a593Smuzhiyun stat_str = tx ? "TX_ICMP_PING_REQ" : "RX_ICMP_PING_REQ";
596*4882a593Smuzhiyun break;
597*4882a593Smuzhiyun case ST(ICMP_PING_RESP):
598*4882a593Smuzhiyun stat_str = tx ? "TX_ICMP_PING_RESP" : "RX_ICMP_PING_RESP";
599*4882a593Smuzhiyun break;
600*4882a593Smuzhiyun case ST(ICMP_DEST_UNREACH):
601*4882a593Smuzhiyun stat_str = tx ? "TX_ICMP_DEST_UNREACH" : "RX_ICMP_DEST_UNREACH";
602*4882a593Smuzhiyun break;
603*4882a593Smuzhiyun case ST(ICMP_OTHER):
604*4882a593Smuzhiyun stat_str = tx ? "TX_ICMP_OTHER" : "RX_ICMP_OTHER";
605*4882a593Smuzhiyun break;
606*4882a593Smuzhiyun case ST(ARP_REQ):
607*4882a593Smuzhiyun stat_str = tx ? "TX_ARP_REQ" : "RX_ARP_REQ";
608*4882a593Smuzhiyun break;
609*4882a593Smuzhiyun case ST(ARP_RESP):
610*4882a593Smuzhiyun stat_str = tx ? "TX_ARP_RESP" : "RX_ARP_RESP";
611*4882a593Smuzhiyun break;
612*4882a593Smuzhiyun case ST(DNS_QUERY):
613*4882a593Smuzhiyun stat_str = tx ? "TX_DNS_QUERY" : "RX_DNS_QUERY";
614*4882a593Smuzhiyun break;
615*4882a593Smuzhiyun case ST(DNS_RESP):
616*4882a593Smuzhiyun stat_str = tx ? "TX_DNS_RESP" : "RX_DNS_RESP";
617*4882a593Smuzhiyun break;
618*4882a593Smuzhiyun case ST(REASSOC_SUCCESS):
619*4882a593Smuzhiyun stat_str = "REASSOC_SUCCESS";
620*4882a593Smuzhiyun break;
621*4882a593Smuzhiyun case ST(REASSOC_FAILURE):
622*4882a593Smuzhiyun stat_str = "REASSOC_FAILURE";
623*4882a593Smuzhiyun break;
624*4882a593Smuzhiyun case ST(AUTH_TIMEOUT):
625*4882a593Smuzhiyun stat_str = "AUTH_TIMEOUT";
626*4882a593Smuzhiyun break;
627*4882a593Smuzhiyun case ST(AUTH_FAIL):
628*4882a593Smuzhiyun stat_str = "AUTH_FAIL";
629*4882a593Smuzhiyun break;
630*4882a593Smuzhiyun case ST(AUTH_NO_ACK):
631*4882a593Smuzhiyun stat_str = "AUTH_NO_ACK";
632*4882a593Smuzhiyun break;
633*4882a593Smuzhiyun case ST(AUTH_OTHERS):
634*4882a593Smuzhiyun stat_str = "AUTH_FAIL_OTHER_STATUS";
635*4882a593Smuzhiyun break;
636*4882a593Smuzhiyun case ST(ASSOC_TIMEOUT):
637*4882a593Smuzhiyun stat_str = "ASSOC_TIMEOUT";
638*4882a593Smuzhiyun break;
639*4882a593Smuzhiyun case ST(ASSOC_FAIL):
640*4882a593Smuzhiyun stat_str = "ASSOC_FAIL";
641*4882a593Smuzhiyun break;
642*4882a593Smuzhiyun case ST(ASSOC_NO_ACK):
643*4882a593Smuzhiyun stat_str = "ASSOC_NO_ACK";
644*4882a593Smuzhiyun break;
645*4882a593Smuzhiyun case ST(ASSOC_ABORT):
646*4882a593Smuzhiyun stat_str = "ASSOC_ABORT";
647*4882a593Smuzhiyun break;
648*4882a593Smuzhiyun case ST(ASSOC_UNSOLICITED):
649*4882a593Smuzhiyun stat_str = "ASSOC_UNSOLICITED";
650*4882a593Smuzhiyun break;
651*4882a593Smuzhiyun case ST(ASSOC_NO_NETWORKS):
652*4882a593Smuzhiyun stat_str = "ASSOC_NO_NETWORKS";
653*4882a593Smuzhiyun break;
654*4882a593Smuzhiyun case ST(ASSOC_OTHERS):
655*4882a593Smuzhiyun stat_str = "ASSOC_FAIL_OTHER_STATUS";
656*4882a593Smuzhiyun break;
657*4882a593Smuzhiyun case ST(REASSOC_DONE_OTHERS):
658*4882a593Smuzhiyun stat_str = "REASSOC_DONE_OTHER_STATUS";
659*4882a593Smuzhiyun break;
660*4882a593Smuzhiyun default:
661*4882a593Smuzhiyun stat_str = "UNKNOWN_STATUS";
662*4882a593Smuzhiyun break;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun strncpy(buf, stat_str, max_buf_len);
666*4882a593Smuzhiyun buf[max_buf_len - 1] = '\0';
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun static void
dhd_statlog_get_timestamp(stat_elem_t * elem,uint64 * sec,uint64 * usec)670*4882a593Smuzhiyun dhd_statlog_get_timestamp(stat_elem_t *elem, uint64 *sec, uint64 *usec)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun uint64 ts_nsec, rem_nsec;
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun ts_nsec = elem->ts;
675*4882a593Smuzhiyun rem_nsec = DIV_AND_MOD_U64_BY_U32(ts_nsec, NSEC_PER_SEC);
676*4882a593Smuzhiyun *sec = ts_nsec;
677*4882a593Smuzhiyun *usec = (uint64)(rem_nsec / NSEC_PER_USEC);
678*4882a593Smuzhiyun }
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun static void
dhd_statlog_convert_time(stat_elem_t * elem,uint8 * buf,uint32 buflen)681*4882a593Smuzhiyun dhd_statlog_convert_time(stat_elem_t *elem, uint8 *buf, uint32 buflen)
682*4882a593Smuzhiyun {
683*4882a593Smuzhiyun #if defined(LINUX) || defined(linux)
684*4882a593Smuzhiyun struct rtc_time tm;
685*4882a593Smuzhiyun uint64 ts_sec, rem_usec;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun if (!buf) {
688*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: buf is NULL\n", __FUNCTION__));
689*4882a593Smuzhiyun return;
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun bzero(buf, buflen);
693*4882a593Smuzhiyun ts_sec = elem->ts_tz;
694*4882a593Smuzhiyun rem_usec = DIV_AND_MOD_U64_BY_U32(ts_sec, USEC_PER_SEC);
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun rtc_time_to_tm((unsigned long)ts_sec, &tm);
697*4882a593Smuzhiyun snprintf(buf, buflen, DHD_STATLOG_TZFMT_YYMMDDHHMMSSMS,
698*4882a593Smuzhiyun tm.tm_year - 100, tm.tm_mon + 1, tm.tm_mday,
699*4882a593Smuzhiyun tm.tm_hour, tm.tm_min, tm.tm_sec,
700*4882a593Smuzhiyun (uint32)(rem_usec / USEC_PER_MSEC));
701*4882a593Smuzhiyun #endif /* LINUX || linux */
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun #ifdef DHD_LOG_DUMP
705*4882a593Smuzhiyun static int
dhd_statlog_dump(dhd_statlog_t * statlog,char * buf,uint32 buflen)706*4882a593Smuzhiyun dhd_statlog_dump(dhd_statlog_t *statlog, char *buf, uint32 buflen)
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun stat_elem_t *elem;
709*4882a593Smuzhiyun struct bcmstrbuf b;
710*4882a593Smuzhiyun struct bcmstrbuf *strbuf = &b;
711*4882a593Smuzhiyun char stat_str[DHD_STATLOG_STATSTR_BUF_LEN];
712*4882a593Smuzhiyun char ts_str[DHD_STATLOG_TZFMT_BUF_LEN];
713*4882a593Smuzhiyun uint64 sec = 0, usec = 0;
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun if (!statlog) {
716*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: statlog is NULL\n", __FUNCTION__));
717*4882a593Smuzhiyun return BCME_ERROR;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun bcm_binit(strbuf, buf, buflen);
721*4882a593Smuzhiyun bzero(stat_str, sizeof(stat_str));
722*4882a593Smuzhiyun bzero(ts_str, sizeof(ts_str));
723*4882a593Smuzhiyun dhd_ring_whole_lock(statlog->ringbuf);
724*4882a593Smuzhiyun elem = (stat_elem_t *)dhd_ring_get_first(statlog->ringbuf);
725*4882a593Smuzhiyun while (elem) {
726*4882a593Smuzhiyun if (DHD_STATLOG_VALID(elem->stat)) {
727*4882a593Smuzhiyun dhd_statlog_stat_name(stat_str, sizeof(stat_str),
728*4882a593Smuzhiyun elem->stat, elem->dir);
729*4882a593Smuzhiyun dhd_statlog_get_timestamp(elem, &sec, &usec);
730*4882a593Smuzhiyun dhd_statlog_convert_time(elem, ts_str, sizeof(ts_str));
731*4882a593Smuzhiyun bcm_bprintf(strbuf, "[%s][%5lu.%06lu] status=%s, ifidx=%d, "
732*4882a593Smuzhiyun "reason=%d, status=%d\n", ts_str, (unsigned long)sec,
733*4882a593Smuzhiyun (unsigned long)usec, stat_str, elem->ifidx,
734*4882a593Smuzhiyun elem->reason, elem->status);
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun elem = (stat_elem_t *)dhd_ring_get_next(statlog->ringbuf, (void *)elem);
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun dhd_ring_whole_unlock(statlog->ringbuf);
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun return (!strbuf->size ? BCME_BUFTOOSHORT : strbuf->size);
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun int
dhd_statlog_write_logdump(dhd_pub_t * dhdp,const void * user_buf,void * fp,uint32 len,unsigned long * pos)744*4882a593Smuzhiyun dhd_statlog_write_logdump(dhd_pub_t *dhdp, const void *user_buf,
745*4882a593Smuzhiyun void *fp, uint32 len, unsigned long *pos)
746*4882a593Smuzhiyun {
747*4882a593Smuzhiyun dhd_statlog_t *statlog;
748*4882a593Smuzhiyun log_dump_section_hdr_t sec_hdr;
749*4882a593Smuzhiyun char *buf;
750*4882a593Smuzhiyun uint32 buflen;
751*4882a593Smuzhiyun int remain_len = 0;
752*4882a593Smuzhiyun int ret = BCME_OK;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun if (!dhdp || !dhdp->statlog) {
755*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: dhdp or dhdp->statlog is NULL\n",
756*4882a593Smuzhiyun __FUNCTION__));
757*4882a593Smuzhiyun return BCME_ERROR;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun statlog = (dhd_statlog_t *)(dhdp->statlog);
761*4882a593Smuzhiyun if (!statlog->logbuf) {
762*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: logbuf is NULL\n", __FUNCTION__));
763*4882a593Smuzhiyun return BCME_ERROR;
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun buf = statlog->logbuf;
767*4882a593Smuzhiyun buflen = statlog->logbuf_len;
768*4882a593Smuzhiyun bzero(buf, buflen);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun remain_len = dhd_statlog_dump(statlog, buf, buflen);
771*4882a593Smuzhiyun if (remain_len < 0) {
772*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to write stat info to buffer\n",
773*4882a593Smuzhiyun __FUNCTION__));
774*4882a593Smuzhiyun return BCME_ERROR;
775*4882a593Smuzhiyun }
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun DHD_STATLOG_INFO(("%s: Start to write statlog\n", __FUNCTION__));
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun /* write the section header first */
780*4882a593Smuzhiyun ret = dhd_export_debug_data(STATUS_LOG_HDR, fp, user_buf,
781*4882a593Smuzhiyun strlen(STATUS_LOG_HDR), pos);
782*4882a593Smuzhiyun if (ret < 0) {
783*4882a593Smuzhiyun goto exit;
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun dhd_init_sec_hdr(&sec_hdr);
787*4882a593Smuzhiyun sec_hdr.type = LOG_DUMP_SECTION_STATUS;
788*4882a593Smuzhiyun sec_hdr.length = buflen - remain_len;
789*4882a593Smuzhiyun ret = dhd_export_debug_data((char *)&sec_hdr, fp, user_buf,
790*4882a593Smuzhiyun sizeof(sec_hdr), pos);
791*4882a593Smuzhiyun if (ret < 0) {
792*4882a593Smuzhiyun goto exit;
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun /* write status log info */
796*4882a593Smuzhiyun ret = dhd_export_debug_data(buf, fp, user_buf, buflen - remain_len, pos);
797*4882a593Smuzhiyun if (ret < 0) {
798*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to write stat info, err=%d\n",
799*4882a593Smuzhiyun __FUNCTION__, ret));
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun DHD_STATLOG_INFO(("%s: Complete to write statlog file, err=%d\n",
803*4882a593Smuzhiyun __FUNCTION__, ret));
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun exit:
806*4882a593Smuzhiyun return ret;
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun #endif /* DHD_LOG_DUMP */
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun int
dhd_statlog_generate_bdmask(dhd_pub_t * dhdp,void * reqbuf)811*4882a593Smuzhiyun dhd_statlog_generate_bdmask(dhd_pub_t *dhdp, void *reqbuf)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun dhd_statlog_t *statlog;
814*4882a593Smuzhiyun stat_bdmask_req_t *query;
815*4882a593Smuzhiyun uint8 *req_buf;
816*4882a593Smuzhiyun uint32 req_buf_len;
817*4882a593Smuzhiyun int cnt;
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun if (!dhdp || !dhdp->statlog) {
820*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: dhdp or statlog is NULL\n", __FUNCTION__));
821*4882a593Smuzhiyun return BCME_ERROR;
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun if (!reqbuf) {
825*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: invalid query\n", __FUNCTION__));
826*4882a593Smuzhiyun return BCME_ERROR;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun statlog = dhdp->statlog;
830*4882a593Smuzhiyun query = (stat_bdmask_req_t *)reqbuf;
831*4882a593Smuzhiyun req_buf = query->req_buf;
832*4882a593Smuzhiyun req_buf_len = query->req_buf_len;
833*4882a593Smuzhiyun if (!req_buf) {
834*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: invalid query\n", __FUNCTION__));
835*4882a593Smuzhiyun return BCME_ERROR;
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun bzero(statlog->bdmask, DHD_STAT_BDMASK_SIZE);
839*4882a593Smuzhiyun for (cnt = 0; cnt < req_buf_len; cnt++) {
840*4882a593Smuzhiyun if (DHD_STATLOG_VALID(req_buf[cnt])) {
841*4882a593Smuzhiyun setbit(statlog->bdmask, req_buf[cnt]);
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun return BCME_OK;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun int
dhd_statlog_get_latest_info(dhd_pub_t * dhdp,void * reqbuf)849*4882a593Smuzhiyun dhd_statlog_get_latest_info(dhd_pub_t *dhdp, void *reqbuf)
850*4882a593Smuzhiyun {
851*4882a593Smuzhiyun dhd_statlog_t *statlog;
852*4882a593Smuzhiyun stat_query_t *query;
853*4882a593Smuzhiyun stat_elem_t *elem;
854*4882a593Smuzhiyun uint8 *req_buf, *resp_buf, *sp;
855*4882a593Smuzhiyun uint32 req_buf_len, resp_buf_len, req_num;
856*4882a593Smuzhiyun int i, remain_len, cpcnt = 0;
857*4882a593Smuzhiyun uint8 filter[DHD_STAT_BDMASK_SIZE];
858*4882a593Smuzhiyun bool query_bigdata = FALSE;
859*4882a593Smuzhiyun void *ringbuf;
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun if (!dhdp || !dhdp->statlog) {
862*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: dhdp or statlog is NULL\n",
863*4882a593Smuzhiyun __FUNCTION__));
864*4882a593Smuzhiyun return BCME_ERROR;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun query = (stat_query_t *)reqbuf;
868*4882a593Smuzhiyun if (!query) {
869*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: invalid query\n", __FUNCTION__));
870*4882a593Smuzhiyun return BCME_ERROR;
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun statlog = (dhd_statlog_t *)(dhdp->statlog);
874*4882a593Smuzhiyun req_buf = query->req_buf;
875*4882a593Smuzhiyun req_buf_len = query->req_buf_len;
876*4882a593Smuzhiyun resp_buf = query->resp_buf;
877*4882a593Smuzhiyun resp_buf_len = query->resp_buf_len;
878*4882a593Smuzhiyun req_num = MIN(query->req_num, MAX_STATLOG_REQ_ITEM);
879*4882a593Smuzhiyun if (!resp_buf) {
880*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: invalid query\n", __FUNCTION__));
881*4882a593Smuzhiyun return BCME_ERROR;
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun bzero(filter, sizeof(filter));
885*4882a593Smuzhiyun if (!req_buf || !req_buf_len) {
886*4882a593Smuzhiyun query_bigdata = TRUE;
887*4882a593Smuzhiyun ringbuf = statlog->bdlog_ringbuf;
888*4882a593Smuzhiyun } else {
889*4882a593Smuzhiyun ringbuf = statlog->ringbuf;
890*4882a593Smuzhiyun /* build a filter from req_buf */
891*4882a593Smuzhiyun for (i = 0; i < req_buf_len; i++) {
892*4882a593Smuzhiyun if (DHD_STATLOG_VALID(req_buf[i])) {
893*4882a593Smuzhiyun setbit(filter, req_buf[i]);
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun }
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun sp = resp_buf;
899*4882a593Smuzhiyun remain_len = resp_buf_len;
900*4882a593Smuzhiyun dhd_ring_whole_lock(ringbuf);
901*4882a593Smuzhiyun elem = (stat_elem_t *)dhd_ring_get_last(ringbuf);
902*4882a593Smuzhiyun while (elem) {
903*4882a593Smuzhiyun if (query_bigdata || isset(filter, elem->stat)) {
904*4882a593Smuzhiyun /* found the status from the list of interests */
905*4882a593Smuzhiyun if (remain_len < sizeof(stat_elem_t)) {
906*4882a593Smuzhiyun dhd_ring_whole_unlock(ringbuf);
907*4882a593Smuzhiyun return BCME_BUFTOOSHORT;
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun bcopy((char *)elem, sp, sizeof(stat_elem_t));
910*4882a593Smuzhiyun sp += sizeof(stat_elem_t);
911*4882a593Smuzhiyun remain_len -= sizeof(stat_elem_t);
912*4882a593Smuzhiyun cpcnt++;
913*4882a593Smuzhiyun }
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun if (cpcnt >= req_num) {
916*4882a593Smuzhiyun break;
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun /* Proceed to next item */
920*4882a593Smuzhiyun elem = (stat_elem_t *)dhd_ring_get_prev(ringbuf, (void *)elem);
921*4882a593Smuzhiyun }
922*4882a593Smuzhiyun dhd_ring_whole_unlock(ringbuf);
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun return cpcnt;
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun int
dhd_statlog_query(dhd_pub_t * dhdp,char * cmd,int total_len)928*4882a593Smuzhiyun dhd_statlog_query(dhd_pub_t *dhdp, char *cmd, int total_len)
929*4882a593Smuzhiyun {
930*4882a593Smuzhiyun stat_elem_t *elem = NULL;
931*4882a593Smuzhiyun stat_query_t query;
932*4882a593Smuzhiyun char *pos, *token;
933*4882a593Smuzhiyun uint8 *req_buf = NULL, *resp_buf = NULL;
934*4882a593Smuzhiyun uint32 req_buf_len = 0, resp_buf_len = 0;
935*4882a593Smuzhiyun ulong req_num, stat_num, stat;
936*4882a593Smuzhiyun char stat_str[DHD_STATLOG_STATSTR_BUF_LEN];
937*4882a593Smuzhiyun uint64 sec = 0, usec = 0;
938*4882a593Smuzhiyun int i, resp_num, err = BCME_OK;
939*4882a593Smuzhiyun char ts_str[DHD_STATLOG_TZFMT_BUF_LEN];
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun /*
942*4882a593Smuzhiyun * DRIVER QUERY_STAT_LOG <total req num> <stat list num> <stat list>
943*4882a593Smuzhiyun * Note: use the defult status list if the 'stat list num' is zero
944*4882a593Smuzhiyun */
945*4882a593Smuzhiyun pos = cmd;
946*4882a593Smuzhiyun /* drop command */
947*4882a593Smuzhiyun token = bcmstrtok(&pos, " ", NULL);
948*4882a593Smuzhiyun /* total number of request */
949*4882a593Smuzhiyun token = bcmstrtok(&pos, " ", NULL);
950*4882a593Smuzhiyun if (!token) {
951*4882a593Smuzhiyun err = BCME_BADARG;
952*4882a593Smuzhiyun goto exit;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun req_num = bcm_strtoul(token, NULL, 0);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun /* total number of status list */
958*4882a593Smuzhiyun token = bcmstrtok(&pos, " ", NULL);
959*4882a593Smuzhiyun if (!token) {
960*4882a593Smuzhiyun err = BCME_BADARG;
961*4882a593Smuzhiyun goto exit;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun stat_num = bcm_strtoul(token, NULL, 0);
965*4882a593Smuzhiyun if (stat_num) {
966*4882a593Smuzhiyun /* create a status list */
967*4882a593Smuzhiyun req_buf_len = (uint32)(stat_num * sizeof(uint8));
968*4882a593Smuzhiyun req_buf = (uint8 *)MALLOCZ(dhdp->osh, req_buf_len);
969*4882a593Smuzhiyun if (!req_buf) {
970*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to allocate request buf\n",
971*4882a593Smuzhiyun __FUNCTION__));
972*4882a593Smuzhiyun err = BCME_NOMEM;
973*4882a593Smuzhiyun goto exit;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun /* parse the status list and update to the request buffer */
977*4882a593Smuzhiyun for (i = 0; i < (uint32)stat_num; i++) {
978*4882a593Smuzhiyun token = bcmstrtok(&pos, " ", NULL);
979*4882a593Smuzhiyun if (!token) {
980*4882a593Smuzhiyun err = BCME_BADARG;
981*4882a593Smuzhiyun goto exit;
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun stat = bcm_strtoul(token, NULL, 0);
984*4882a593Smuzhiyun req_buf[i] = (uint8)stat;
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun /* creat a response list */
989*4882a593Smuzhiyun resp_buf_len = (uint32)DHD_STATLOG_RING_SIZE(req_num);
990*4882a593Smuzhiyun resp_buf = (uint8 *)MALLOCZ(dhdp->osh, resp_buf_len);
991*4882a593Smuzhiyun if (!resp_buf) {
992*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to allocate response buf\n",
993*4882a593Smuzhiyun __FUNCTION__));
994*4882a593Smuzhiyun err = BCME_NOMEM;
995*4882a593Smuzhiyun goto exit;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun /* create query format and query the status */
999*4882a593Smuzhiyun query.req_buf = req_buf;
1000*4882a593Smuzhiyun query.req_buf_len = req_buf_len;
1001*4882a593Smuzhiyun query.resp_buf = resp_buf;
1002*4882a593Smuzhiyun query.resp_buf_len = resp_buf_len;
1003*4882a593Smuzhiyun query.req_num = (uint32)req_num;
1004*4882a593Smuzhiyun resp_num = dhd_statlog_get_latest_info(dhdp, (void *)&query);
1005*4882a593Smuzhiyun if (resp_num < 0) {
1006*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: failed to query the status\n", __FUNCTION__));
1007*4882a593Smuzhiyun err = BCME_ERROR;
1008*4882a593Smuzhiyun goto exit;
1009*4882a593Smuzhiyun }
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun /* print out the results */
1012*4882a593Smuzhiyun DHD_STATLOG_PRINT(("=============== QUERY RESULT ===============\n"));
1013*4882a593Smuzhiyun if (resp_num > 0) {
1014*4882a593Smuzhiyun elem = (stat_elem_t *)resp_buf;
1015*4882a593Smuzhiyun for (i = 0; i < resp_num; i++) {
1016*4882a593Smuzhiyun if (DHD_STATLOG_VALID(elem->stat)) {
1017*4882a593Smuzhiyun dhd_statlog_stat_name(stat_str, sizeof(stat_str),
1018*4882a593Smuzhiyun elem->stat, elem->dir);
1019*4882a593Smuzhiyun dhd_statlog_get_timestamp(elem, &sec, &usec);
1020*4882a593Smuzhiyun dhd_statlog_convert_time(elem, ts_str, sizeof(ts_str));
1021*4882a593Smuzhiyun DHD_STATLOG_PRINT(("[RAWTS:%llu][%s][%5lu.%06lu] status=%s,"
1022*4882a593Smuzhiyun " ifidx=%d, reason=%d, status=%d\n", elem->ts_tz,
1023*4882a593Smuzhiyun ts_str, (unsigned long)sec, (unsigned long)usec,
1024*4882a593Smuzhiyun stat_str, elem->ifidx, elem->reason, elem->status));
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun elem++;
1027*4882a593Smuzhiyun }
1028*4882a593Smuzhiyun } else {
1029*4882a593Smuzhiyun DHD_STATLOG_PRINT(("No data found\n"));
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun exit:
1033*4882a593Smuzhiyun if (resp_buf) {
1034*4882a593Smuzhiyun MFREE(dhdp->osh, resp_buf, resp_buf_len);
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun if (req_buf) {
1038*4882a593Smuzhiyun MFREE(dhdp->osh, req_buf, req_buf_len);
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun
1041*4882a593Smuzhiyun return err;
1042*4882a593Smuzhiyun }
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun void
dhd_statlog_dump_scr(dhd_pub_t * dhdp)1045*4882a593Smuzhiyun dhd_statlog_dump_scr(dhd_pub_t *dhdp)
1046*4882a593Smuzhiyun {
1047*4882a593Smuzhiyun dhd_statlog_t *statlog;
1048*4882a593Smuzhiyun stat_elem_t *elem;
1049*4882a593Smuzhiyun char stat_str[DHD_STATLOG_STATSTR_BUF_LEN];
1050*4882a593Smuzhiyun char ts_str[DHD_STATLOG_TZFMT_BUF_LEN];
1051*4882a593Smuzhiyun uint64 sec = 0, usec = 0;
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun if (!dhdp || !dhdp->statlog) {
1054*4882a593Smuzhiyun DHD_STATLOG_ERR(("%s: dhdp or statlog is NULL\n", __FUNCTION__));
1055*4882a593Smuzhiyun return;
1056*4882a593Smuzhiyun }
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun statlog = (dhd_statlog_t *)(dhdp->statlog);
1059*4882a593Smuzhiyun bzero(stat_str, sizeof(stat_str));
1060*4882a593Smuzhiyun bzero(ts_str, sizeof(ts_str));
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun DHD_STATLOG_PRINT(("=============== START OF CURRENT STATUS INFO ===============\n"));
1063*4882a593Smuzhiyun dhd_ring_whole_lock(statlog->ringbuf);
1064*4882a593Smuzhiyun elem = (stat_elem_t *)dhd_ring_get_first(statlog->ringbuf);
1065*4882a593Smuzhiyun while (elem) {
1066*4882a593Smuzhiyun if (DHD_STATLOG_VALID(elem->stat)) {
1067*4882a593Smuzhiyun dhd_statlog_stat_name(stat_str, sizeof(stat_str),
1068*4882a593Smuzhiyun elem->stat, elem->dir);
1069*4882a593Smuzhiyun dhd_statlog_get_timestamp(elem, &sec, &usec);
1070*4882a593Smuzhiyun dhd_statlog_convert_time(elem, ts_str, sizeof(ts_str));
1071*4882a593Smuzhiyun DHD_STATLOG_PRINT(("[RAWTS:%llu][%s][%5lu.%06lu] status=%s,"
1072*4882a593Smuzhiyun " ifidx=%d, reason=%d, status=%d\n", elem->ts_tz, ts_str,
1073*4882a593Smuzhiyun (unsigned long)sec, (unsigned long)usec, stat_str,
1074*4882a593Smuzhiyun elem->ifidx, elem->reason, elem->status));
1075*4882a593Smuzhiyun }
1076*4882a593Smuzhiyun elem = (stat_elem_t *)dhd_ring_get_next(statlog->ringbuf, (void *)elem);
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun dhd_ring_whole_unlock(statlog->ringbuf);
1079*4882a593Smuzhiyun DHD_STATLOG_PRINT(("=============== END OF CURRENT STATUS INFO ===============\n"));
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun #endif /* DHD_STATUS_LOGGING */
1082