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