hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_debug.c
....@@ -1,15 +1,18 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * DHD debugability support
43 *
5
- * Copyright (C) 1999-2019, Broadcom Corporation
6
- *
4
+ * <<Broadcom-WL-IPTag/Open:>>
5
+ *
6
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
7
+ *
8
+ * Copyright (C) 1999-2017, Broadcom Corporation
9
+ *
710 * Unless you and Broadcom execute a separate written software license
811 * agreement governing use of this software, this software is licensed to you
912 * under the terms of the GNU General Public License version 2 (the "GPL"),
1013 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1114 * following added to such license:
12
- *
15
+ *
1316 * As a special exception, the copyright holders of this software give you
1417 * permission to link this software with independent modules, and to copy and
1518 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,12 +20,12 @@
1720 * the license of that module. An independent module is a module which is not
1821 * derived from this software. The special exception does not apply to any
1922 * modifications of the software.
20
- *
23
+ *
2124 * Notwithstanding the above, under no circumstances may you combine this
2225 * software in any way with any other Broadcom software provided under a license
2326 * other than the GPL, without Broadcom's express prior written consent.
2427 *
25
- * $Id: dhd_debug.c 560028 2015-05-29 10:50:33Z $
28
+ * $Id: dhd_debug.c 701420 2017-05-24 23:20:58Z $
2629 */
2730
2831 #include <typedefs.h>
....@@ -31,28 +34,22 @@
3134 #include <bcmendian.h>
3235 #include <dngl_stats.h>
3336 #include <dhd.h>
37
+#include <dhd_linux.h>
3438 #include <dhd_dbg.h>
39
+#include <dhd_dbg_ring.h>
3540 #include <dhd_debug.h>
41
+#include <dhd_mschdbg.h>
42
+#include <dhd_bus.h>
3643
3744 #include <event_log.h>
3845 #include <event_trace.h>
3946 #include <msgtrace.h>
4047
41
-#define DBGRING_FLUSH_THRESHOLD(ring) (ring->ring_size / 3)
42
-#define RING_STAT_TO_STATUS(ring, status) \
43
- do { \
44
- strncpy(status.name, ring->name, \
45
- sizeof(status.name) - 1); \
46
- status.ring_id = ring->id; \
47
- status.ring_buffer_byte_size = ring->ring_size; \
48
- status.written_bytes = ring->stat.written_bytes; \
49
- status.written_records = ring->stat.written_records; \
50
- status.read_bytes = ring->stat.read_bytes; \
51
- status.verbose_level = ring->log_level; \
52
- } while (0)
48
+#if defined(DHD_EVENT_LOG_FILTER)
49
+#include <dhd_event_log_filter.h>
50
+#endif /* DHD_EVENT_LOG_FILTER */
5351
54
-#define READ_AVAIL_SPACE(w, r, d) ((w >= r) ? (w - r) : (d - r))
55
-
52
+#define DHD_PKT_INFO DHD_ERROR
5653 struct map_table {
5754 uint16 fw_id;
5855 uint16 host_id;
....@@ -123,80 +120,22 @@
123120 {2, EVENT_LOG_TAG_WL_ROAM_LOG, "ROAM_LOG"},
124121 {1, EVENT_LOG_TAG_TRACE_WL_INFO, "WL INFO"},
125122 {1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, "BTCOEX INFO"},
123
+#ifdef CUSTOMER_HW4_DEBUG
124
+ {3, EVENT_LOG_TAG_SCAN_WARN, "SCAN_WARN"},
125
+#else
126126 {1, EVENT_LOG_TAG_SCAN_WARN, "SCAN_WARN"},
127
+#endif /* CUSTOMER_HW4_DEBUG */
127128 {1, EVENT_LOG_TAG_SCAN_ERROR, "SCAN_ERROR"},
128129 {2, EVENT_LOG_TAG_SCAN_TRACE_LOW, "SCAN_TRACE_LOW"},
129130 {2, EVENT_LOG_TAG_SCAN_TRACE_HIGH, "SCAN_TRACE_HIGH"}
130131 };
131132
132
-struct log_level_table fw_event_level_map[] = {
133
- {1, EVENT_LOG_TAG_TRACE_WL_INFO, "WL_INFO"},
134
- {1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, "BTCOEX_INFO"},
135
- {2, EVENT_LOG_TAG_BEACON_LOG, "BEACON LOG"},
136
-};
137
-
138
-struct map_table nan_event_map[] = {
139
- {TRACE_NAN_CLUSTER_STARTED, NAN_EVENT_CLUSTER_STARTED, "NAN_CLUSTER_STARTED"},
140
- {TRACE_NAN_CLUSTER_JOINED, NAN_EVENT_CLUSTER_JOINED, "NAN_CLUSTER_JOINED"},
141
- {TRACE_NAN_CLUSTER_MERGED, NAN_EVENT_CLUSTER_MERGED, "NAN_CLUSTER_MERGED"},
142
- {TRACE_NAN_ROLE_CHANGED, NAN_EVENT_ROLE_CHANGED, "NAN_ROLE_CHANGED"},
143
- {TRACE_NAN_SCAN_COMPLETE, NAN_EVENT_SCAN_COMPLETE, "NAN_SCAN_COMPLETE"},
144
- {TRACE_NAN_STATUS_CHNG, NAN_EVENT_STATUS_CHNG, "NAN_STATUS_CHNG"},
145
-};
146
-
147
-struct log_level_table nan_event_level_map[] = {
148
- {1, EVENT_LOG_TAG_NAN_ERROR, "NAN_ERROR"},
149
- {2, EVENT_LOG_TAG_NAN_INFO, "NAN_INFO"},
150
- {3, EVENT_LOG_TAG_NAN_DBG, "NAN_DEBUG"},
151
-};
152
-
153
-struct map_table nan_evt_tag_map[] = {
154
- {TRACE_TAG_BSSID, WIFI_TAG_BSSID, "BSSID"},
155
- {TRACE_TAG_ADDR, WIFI_TAG_ADDR, "ADDR_0"},
156
-};
157
-
158133 /* reference tab table */
159134 uint ref_tag_tbl[EVENT_LOG_TAG_MAX + 1] = {0};
160135
161
-enum dbg_ring_state {
162
- RING_STOP = 0, /* ring is not initialized */
163
- RING_ACTIVE, /* ring is live and logging */
164
- RING_SUSPEND /* ring is initialized but not logging */
165
-};
166
-
167
-struct ring_statistics {
168
- /* number of bytes that was written to the buffer by driver */
169
- uint32 written_bytes;
170
- /* number of bytes that was read from the buffer by user land */
171
- uint32 read_bytes;
172
- /* number of records that was written to the buffer by driver */
173
- uint32 written_records;
174
-};
175
-
176
-typedef struct dhd_dbg_ring {
177
- int id; /* ring id */
178
- uint8 name[DBGRING_NAME_MAX]; /* name string */
179
- uint32 ring_size; /* numbers of item in ring */
180
- uint32 wp; /* write pointer */
181
- uint32 rp; /* read pointer */
182
- uint32 log_level; /* log_level */
183
- uint32 threshold; /* threshold bytes */
184
- void * ring_buf; /* pointer of actually ring buffer */
185
- void * lock; /* spin lock for ring access */
186
- struct ring_statistics stat; /* statistics */
187
- enum dbg_ring_state state; /* ring state enum */
188
-} dhd_dbg_ring_t;
189
-
190
-typedef struct dhd_dbg {
191
- dhd_dbg_ring_t dbg_rings[DEBUG_RING_ID_MAX];
192
- void *private; /* os private_data */
193
- dbg_pullreq_t pullreq;
194
- dbg_urgent_noti_t urgent_notifier;
195
-} dhd_dbg_t;
196
-
197136 typedef struct dhddbg_loglist_item {
198137 dll_t list;
199
- event_log_hdr_t *hdr;
138
+ prcd_event_log_hdr_t prcd_log_hdr;
200139 } loglist_item_t;
201140
202141 typedef struct dhbdbg_pending_item {
....@@ -205,147 +144,91 @@
205144 dhd_dbg_ring_entry_t *ring_entry;
206145 } pending_item_t;
207146
208
-/* get next entry; offset must point to valid entry */
209
-static uint32
210
-next_entry(dhd_dbg_ring_t *ring, int32 offset)
211
-{
212
- dhd_dbg_ring_entry_t *entry =
213
- (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + offset);
214
-
215
- /*
216
- * A length == 0 record is the end of buffer marker. Wrap around and
217
- * read the message at the start of the buffer as *this* one, and
218
- * return the one after that.
219
- */
220
- if (!entry->len) {
221
- entry = (dhd_dbg_ring_entry_t *)ring->ring_buf;
222
- return ENTRY_LENGTH(entry);
223
- }
224
- return offset + ENTRY_LENGTH(entry);
225
-}
226
-
227
-/* get record by offset; idx must point to valid entry */
228
-static dhd_dbg_ring_entry_t *
229
-get_entry(dhd_dbg_ring_t *ring, int32 offset)
230
-{
231
- dhd_dbg_ring_entry_t *entry =
232
- (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + offset);
233
-
234
- /*
235
- * A length == 0 record is the end of buffer marker. Wrap around and
236
- * read the message at the start of the buffer.
237
- */
238
- if (!entry->len)
239
- return (dhd_dbg_ring_entry_t *)ring->ring_buf;
240
- return entry;
241
-}
147
+/* trace log entry header user space processing */
148
+struct tracelog_header {
149
+ int magic_num;
150
+ int buf_size;
151
+ int seq_num;
152
+};
153
+#define TRACE_LOG_MAGIC_NUMBER 0xEAE47C06
242154
243155 int
244
-dhd_dbg_ring_pull(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len)
156
+dhd_dbg_push_to_ring(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, void *data)
245157 {
246
- uint32 avail_len, r_len = 0;
247
- unsigned long flags;
248158 dhd_dbg_ring_t *ring;
249
- dhd_dbg_ring_entry_t *hdr;
159
+ int ret = 0;
160
+ uint32 pending_len = 0;
250161
251
- if (!dhdp || !dhdp->dbg)
252
- return r_len;
253
- ring = &dhdp->dbg->dbg_rings[ring_id];
254
- if (ring->state != RING_ACTIVE)
255
- return r_len;
256
-
257
- flags = dhd_os_spin_lock(ring->lock);
258
-
259
- /* get a fresh pending length */
260
- avail_len = READ_AVAIL_SPACE(ring->wp, ring->rp, ring->ring_size);
261
- while (avail_len > 0 && buf_len > 0) {
262
- hdr = get_entry(ring, ring->rp);
263
- memcpy(data, hdr, ENTRY_LENGTH(hdr));
264
- r_len += ENTRY_LENGTH(hdr);
265
- /* update read pointer */
266
- ring->rp = next_entry(ring, ring->rp);
267
- data = (uint8 *)data + ENTRY_LENGTH(hdr);
268
- avail_len -= ENTRY_LENGTH(hdr);
269
- buf_len -= ENTRY_LENGTH(hdr);
270
- ring->stat.read_bytes += ENTRY_LENGTH(hdr);
271
- DHD_DBGIF(("%s read_bytes %d\n", __FUNCTION__,
272
- ring->stat.read_bytes));
273
- }
274
- dhd_os_spin_unlock(ring->lock, flags);
275
-
276
- return r_len;
277
-}
278
-
279
-int
280
-dhd_dbg_ring_push(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, void *data)
281
-{
282
- unsigned long flags;
283
- uint32 w_len;
284
- dhd_dbg_ring_t *ring;
285
- dhd_dbg_ring_entry_t *w_entry;
286
- if (!dhdp || !dhdp->dbg)
162
+ if (!dhdp || !dhdp->dbg) {
287163 return BCME_BADADDR;
164
+ }
165
+
166
+ if (!VALID_RING(ring_id)) {
167
+ DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
168
+ return BCME_RANGE;
169
+ }
288170
289171 ring = &dhdp->dbg->dbg_rings[ring_id];
290172
291
- if (ring->state != RING_ACTIVE)
292
- return BCME_OK;
173
+ ret = dhd_dbg_ring_push(ring, hdr, data);
174
+ if (ret != BCME_OK)
175
+ return ret;
293176
294
- flags = dhd_os_spin_lock(ring->lock);
177
+ pending_len = dhd_dbg_ring_get_pending_len(ring);
178
+ dhd_dbg_ring_sched_pull(ring, pending_len, dhdp->dbg->pullreq,
179
+ dhdp->dbg->private, ring->id);
295180
296
- w_len = ENTRY_LENGTH(hdr);
297
- /* prep the space */
298
- do {
299
- if (ring->rp == ring->wp)
300
- break;
301
- if (ring->rp < ring->wp) {
302
- if (ring->ring_size - ring->wp == w_len) {
303
- if (ring->rp == 0)
304
- ring->rp = next_entry(ring, ring->rp);
305
- break;
306
- } else if (ring->ring_size - ring->wp < w_len) {
307
- if (ring->rp == 0)
308
- ring->rp = next_entry(ring, ring->rp);
309
- /* 0 pad insufficient tail space */
310
- memset((uint8 *)ring->ring_buf + ring->wp, 0,
311
- DBG_RING_ENTRY_SIZE);
312
- ring->wp = 0;
313
- continue;
314
- } else {
315
- break;
316
- }
317
- }
318
- if (ring->rp > ring->wp) {
319
- if (ring->rp - ring->wp <= w_len) {
320
- ring->rp = next_entry(ring, ring->rp);
321
- continue;
322
- } else {
323
- break;
324
- }
325
- }
326
- } while (1);
181
+ return ret;
182
+}
327183
328
- w_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + ring->wp);
329
- /* header */
330
- memcpy(w_entry, hdr, DBG_RING_ENTRY_SIZE);
331
- w_entry->len = hdr->len;
332
- /* payload */
333
- memcpy((char *)w_entry + DBG_RING_ENTRY_SIZE, data, w_entry->len);
334
- /* update write pointer */
335
- ring->wp += w_len;
336
- /* update statistics */
337
- ring->stat.written_records++;
338
- ring->stat.written_bytes += w_len;
339
- dhd_os_spin_unlock(ring->lock, flags);
340
- DHD_DBGIF(("%s : written_records %d, written_bytes %d\n", __FUNCTION__,
341
- ring->stat.written_records, ring->stat.written_bytes));
184
+dhd_dbg_ring_t *
185
+dhd_dbg_get_ring_from_ring_id(dhd_pub_t *dhdp, int ring_id)
186
+{
187
+ if (!dhdp || !dhdp->dbg) {
188
+ return NULL;
189
+ }
342190
343
- /* if the current pending size is bigger than threshold */
344
- if (ring->threshold > 0 &&
345
- (READ_AVAIL_SPACE(ring->wp, ring->rp, ring->ring_size) >=
346
- ring->threshold))
347
- dhdp->dbg->pullreq(dhdp->dbg->private, ring->id);
348
- return BCME_OK;
191
+ if (!VALID_RING(ring_id)) {
192
+ DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
193
+ return NULL;
194
+ }
195
+
196
+ return &dhdp->dbg->dbg_rings[ring_id];
197
+}
198
+
199
+int
200
+dhd_dbg_pull_single_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len,
201
+ bool strip_header)
202
+{
203
+ dhd_dbg_ring_t *ring;
204
+
205
+ if (!dhdp || !dhdp->dbg) {
206
+ return 0;
207
+ }
208
+
209
+ if (!VALID_RING(ring_id)) {
210
+ DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
211
+ return BCME_RANGE;
212
+ }
213
+
214
+ ring = &dhdp->dbg->dbg_rings[ring_id];
215
+
216
+ return dhd_dbg_ring_pull_single(ring, data, buf_len, strip_header);
217
+}
218
+
219
+int
220
+dhd_dbg_pull_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len)
221
+{
222
+ dhd_dbg_ring_t *ring;
223
+
224
+ if (!dhdp || !dhdp->dbg)
225
+ return 0;
226
+ if (!VALID_RING(ring_id)) {
227
+ DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
228
+ return BCME_RANGE;
229
+ }
230
+ ring = &dhdp->dbg->dbg_rings[ring_id];
231
+ return dhd_dbg_ring_pull(ring, data, buf_len, FALSE);
349232 }
350233
351234 static int
....@@ -368,12 +251,18 @@
368251 return 0;
369252 }
370253
254
+#ifndef MACOSX_DHD
371255 static void
372256 dhd_dbg_msgtrace_msg_parser(void *event_data)
373257 {
374258 msgtrace_hdr_t *hdr;
375259 char *data, *s;
376260 static uint32 seqnum_prev = 0;
261
+
262
+ if (!event_data) {
263
+ DHD_ERROR(("%s: event_data is NULL\n", __FUNCTION__));
264
+ return;
265
+ }
377266
378267 hdr = (msgtrace_hdr_t *)event_data;
379268 data = (char *)event_data + MSGTRACE_HDRLEN;
....@@ -403,293 +292,255 @@
403292 if (*data)
404293 DHD_FWLOG(("[FWLOG] %s", data));
405294 }
406
-
295
+#endif /* MACOSX_DHD */
407296 #ifdef SHOW_LOGTRACE
408
-static const uint8 *
409
-event_get_tlv(uint16 id, const char* tlvs, uint tlvs_len)
410
-{
411
- const uint8 *pos = tlvs;
412
- const uint8 *end = pos + tlvs_len;
413
- tlv_log *tlv;
414
- int rest;
415
-
416
- while (pos + 1 < end) {
417
- if (pos + 4 + pos[1] > end)
418
- break;
419
- tlv = (tlv_log *) pos;
420
- if (tlv->tag == id)
421
- return pos;
422
- rest = tlv->len % 4; /* padding values */
423
- pos += 4 + tlv->len + rest;
424
- }
425
- return NULL;
426
-}
427
-
428297 #define DATA_UNIT_FOR_LOG_CNT 4
429
-static int
430
-dhd_dbg_nan_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data)
298
+
299
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
300
+#pragma GCC diagnostic pop
301
+#endif // endif
302
+
303
+int
304
+replace_percent_p_to_x(char *fmt)
431305 {
432
- int ret = BCME_OK;
433
- wl_event_log_id_t nan_hdr;
434
- log_nan_event_t *evt_payload;
435
- uint16 evt_payload_len = 0, tot_payload_len = 0;
436
- dhd_dbg_ring_entry_t msg_hdr;
437
- bool evt_match = FALSE;
438
- event_log_hdr_t *ts_hdr;
439
- uint32 *ts_data;
440
- char *tlvs, *dest_tlvs;
441
- tlv_log *tlv_data;
442
- int tlv_len = 0;
443
- int i = 0, evt_idx = 0;
444
- char eaddr_buf[ETHER_ADDR_STR_LEN];
306
+ int p_to_x_done = FALSE;
445307
446
- BCM_REFERENCE(eaddr_buf);
308
+ while (*fmt != '\0')
309
+ {
310
+ /* Skip characters will we see a % */
311
+ if (*fmt++ != '%')
312
+ {
313
+ continue;
314
+ }
447315
448
- nan_hdr.t = *data;
449
- DHD_DBGIF(("%s: version %u event %x\n", __FUNCTION__, nan_hdr.version,
450
- nan_hdr.event));
316
+ /*
317
+ * Skip any flags, field width and precision:
318
+ *Flags: Followed by %
319
+ * #, 0, -, ' ', +
320
+ */
321
+ if (*fmt == '#')
322
+ fmt++;
451323
452
- if (nan_hdr.version != DIAG_VERSION) {
453
- DHD_ERROR(("Event payload version %u mismatch with current version %u\n",
454
- nan_hdr.version, DIAG_VERSION));
455
- return BCME_VERSION;
456
- }
457
- memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
458
- ts_hdr = (event_log_hdr_t *)((uint8 *)data - sizeof(event_log_hdr_t));
459
- if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
460
- ts_data = (uint32 *)ts_hdr - ts_hdr->count;
461
- msg_hdr.timestamp = (uint64)ts_data[0];
462
- msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP;
463
- }
464
- msg_hdr.type = DBG_RING_ENTRY_NAN_EVENT_TYPE;
465
- for (i = 0; i < ARRAYSIZE(nan_event_map); i++) {
466
- if (nan_event_map[i].fw_id == nan_hdr.event) {
467
- evt_match = TRUE;
468
- evt_idx = i;
469
- break;
324
+ if (*fmt == '0' || *fmt == '-' || *fmt == '+')
325
+ fmt++;
326
+
327
+ /*
328
+ * Field width:
329
+ * An optional decimal digit string (with non-zero first digit)
330
+ * specifying a minimum field width
331
+ */
332
+ while (*fmt && bcm_isdigit(*fmt))
333
+ fmt++;
334
+
335
+ /*
336
+ * Precision:
337
+ * An optional precision, in the form of a period ('.') followed by an
338
+ * optional decimal digit string.
339
+ */
340
+ if (*fmt == '.')
341
+ {
342
+ fmt++;
343
+ while (*fmt && bcm_isdigit(*fmt)) fmt++;
470344 }
471
- }
472
- if (evt_match) {
473
- DHD_DBGIF(("%s : event (%s)\n", __FUNCTION__, nan_event_map[evt_idx].desc));
474
- /* payload length for nan event data */
475
- evt_payload_len = sizeof(log_nan_event_t) +
476
- (hdr->count - 2) * DATA_UNIT_FOR_LOG_CNT;
477
- if ((evt_payload = MALLOC(dhdp->osh, evt_payload_len)) == NULL) {
478
- DHD_ERROR(("Memory allocation failed for nan evt log (%u)\n",
479
- evt_payload_len));
480
- return BCME_NOMEM;
345
+
346
+ /* If %p is seen, change it to %x */
347
+ if (*fmt == 'p')
348
+ {
349
+ *fmt = 'x';
350
+ p_to_x_done = TRUE;
481351 }
482
- evt_payload->version = NAN_EVENT_VERSION;
483
- evt_payload->event = nan_event_map[evt_idx].host_id;
484
- dest_tlvs = (char *)evt_payload->tlvs;
485
- tot_payload_len = sizeof(log_nan_event_t);
486
- tlvs = (char *)(&data[1]);
487
- tlv_len = (hdr->count - 2) * DATA_UNIT_FOR_LOG_CNT;
488
- for (i = 0; i < ARRAYSIZE(nan_evt_tag_map); i++) {
489
- tlv_data = (tlv_log *)event_get_tlv(nan_evt_tag_map[i].fw_id,
490
- tlvs, tlv_len);
491
- if (tlv_data) {
492
- DHD_DBGIF(("NAN evt tlv.tag(%s), tlv.len : %d, tlv.data : ",
493
- nan_evt_tag_map[i].desc, tlv_data->len));
494
- memcpy(dest_tlvs, tlv_data, sizeof(tlv_log) + tlv_data->len);
495
- tot_payload_len += tlv_data->len + sizeof(tlv_log);
496
- switch (tlv_data->tag) {
497
- case TRACE_TAG_BSSID:
498
- case TRACE_TAG_ADDR:
499
- DHD_DBGIF(("%s\n",
500
- bcm_ether_ntoa(
501
- (const struct ether_addr *)tlv_data->value,
502
- eaddr_buf)));
503
- break;
504
- default:
505
- if (DHD_DBGIF_ON()) {
506
- prhex(NULL, &tlv_data->value[0],
507
- tlv_data->len);
508
- }
509
- break;
510
- }
511
- dest_tlvs += tlv_data->len + sizeof(tlv_log);
512
- }
513
- }
514
- msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_BINARY;
515
- msg_hdr.len = tot_payload_len;
516
- dhd_dbg_ring_push(dhdp, NAN_EVENT_RING_ID, &msg_hdr, evt_payload);
517
- MFREE(dhdp->osh, evt_payload, evt_payload_len);
352
+ if (*fmt)
353
+ fmt++;
518354 }
519
- return ret;
355
+
356
+ return p_to_x_done;
520357 }
521358
522
-static int
523
-dhd_dbg_custom_evnt_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data)
359
+/* To identify format of types %Ns where N >= 0 is a number */
360
+bool
361
+check_valid_string_format(char *curr_ptr)
524362 {
525
- int i = 0, match_idx = 0;
526
- int payload_len, tlv_len;
527
- uint16 tot_payload_len = 0;
528
- int ret = BCME_OK;
529
- int log_level;
530
- wl_event_log_id_t wl_log_id;
531
- dhd_dbg_ring_entry_t msg_hdr;
532
- log_conn_event_t *event_data;
533
- bool evt_match = FALSE;
534
- event_log_hdr_t *ts_hdr;
535
- uint32 *ts_data;
536
- char *tlvs, *dest_tlvs;
537
- tlv_log *tlv_data;
538
- static uint64 ts_saved = 0;
539
- char eabuf[ETHER_ADDR_STR_LEN];
540
- char chanbuf[CHANSPEC_STR_LEN];
541
-
542
- BCM_REFERENCE(eabuf);
543
- BCM_REFERENCE(chanbuf);
544
- /* get a event type and version */
545
- wl_log_id.t = *data;
546
- if (wl_log_id.version != DIAG_VERSION)
547
- return BCME_VERSION;
548
-
549
- ts_hdr = (event_log_hdr_t *)((uint8 *)data - sizeof(event_log_hdr_t));
550
- if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
551
- ts_data = (uint32 *)ts_hdr - ts_hdr->count;
552
- ts_saved = (uint64)ts_data[0];
553
- }
554
- memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
555
- msg_hdr.timestamp = ts_saved;
556
-
557
- DHD_DBGIF(("Android Event ver %d, payload %d words, ts %llu\n",
558
- (*data >> 16), hdr->count - 1, ts_saved));
559
-
560
- /* Perform endian convertion */
561
- for (i = 0; i < hdr->count; i++) {
562
- /* *(data + i) = ntoh32(*(data + i)); */
563
- DHD_DATA(("%08x ", *(data + i)));
564
- }
565
- DHD_DATA(("\n"));
566
- msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP;
567
- msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_BINARY;
568
- msg_hdr.type = DBG_RING_ENTRY_EVENT_TYPE;
569
-
570
- /* convert the data to log_conn_event_t format */
571
- for (i = 0; i < ARRAYSIZE(event_map); i++) {
572
- if (event_map[i].fw_id == wl_log_id.event) {
573
- evt_match = TRUE;
574
- match_idx = i;
575
- break;
363
+ char *next_ptr;
364
+ if ((next_ptr = bcmstrstr(curr_ptr, "s")) != NULL) {
365
+ /* Default %s format */
366
+ if (curr_ptr == next_ptr) {
367
+ return TRUE;
576368 }
577
- }
578
- if (evt_match) {
579
- log_level = dhdp->dbg->dbg_rings[FW_EVENT_RING_ID].log_level;
580
- /* filter the data based on log_level */
581
- for (i = 0; i < ARRAYSIZE(fw_event_level_map); i++) {
582
- if ((fw_event_level_map[i].tag == hdr->tag) &&
583
- (fw_event_level_map[i].log_level > log_level)) {
584
- return BCME_OK;
369
+
370
+ /* Verify each charater between '%' and 's' is a valid number */
371
+ while (curr_ptr < next_ptr) {
372
+ if (bcm_isdigit(*curr_ptr) == FALSE) {
373
+ return FALSE;
585374 }
375
+ curr_ptr++;
586376 }
587
- DHD_DBGIF(("%s : event (%s)\n", __FUNCTION__, event_map[match_idx].desc));
588
- /* get the payload length for event data (skip : log header + timestamp) */
589
- payload_len = sizeof(log_conn_event_t) + DATA_UNIT_FOR_LOG_CNT * (hdr->count - 2);
590
- event_data = MALLOC(dhdp->osh, payload_len);
591
- if (!event_data) {
592
- DHD_ERROR(("failed to allocate the log_conn_event_t with length(%d)\n",
593
- payload_len));
594
- return BCME_NOMEM;
595
- }
596
- event_data->event = event_map[match_idx].host_id;
597
- dest_tlvs = (char *)event_data->tlvs;
598
- tot_payload_len = sizeof(log_conn_event_t);
599
- tlvs = (char *)(&data[1]);
600
- tlv_len = (hdr->count - 2) * DATA_UNIT_FOR_LOG_CNT;
601
- for (i = 0; i < ARRAYSIZE(event_tag_map); i++) {
602
- tlv_data = (tlv_log *)event_get_tlv(event_tag_map[i].fw_id, tlvs, tlv_len);
603
- if (tlv_data) {
604
- DHD_DBGIF(("tlv.tag(%s), tlv.len : %d, tlv.data : ",
605
- event_tag_map[i].desc, tlv_data->len));
606
- memcpy(dest_tlvs, tlv_data, sizeof(tlv_log) + tlv_data->len);
607
- tot_payload_len += tlv_data->len + sizeof(tlv_log);
608
- switch (tlv_data->tag) {
609
- case TRACE_TAG_BSSID:
610
- case TRACE_TAG_ADDR:
611
- case TRACE_TAG_ADDR1:
612
- case TRACE_TAG_ADDR2:
613
- case TRACE_TAG_ADDR3:
614
- case TRACE_TAG_ADDR4:
615
- DHD_DBGIF(("%s\n",
616
- bcm_ether_ntoa((const struct ether_addr *)tlv_data->value,
617
- eabuf)));
618
- break;
619
- case TRACE_TAG_SSID:
620
- DHD_DBGIF(("%s\n", tlv_data->value));
621
- break;
622
- case TRACE_TAG_STATUS:
623
- DHD_DBGIF(("%d\n", ltoh32_ua(&tlv_data->value[0])));
624
- break;
625
- case TRACE_TAG_REASON_CODE:
626
- DHD_DBGIF(("%d\n", ltoh16_ua(&tlv_data->value[0])));
627
- break;
628
- case TRACE_TAG_RATE_MBPS:
629
- DHD_DBGIF(("%d Kbps\n",
630
- ltoh16_ua(&tlv_data->value[0]) * 500));
631
- break;
632
- case TRACE_TAG_CHANNEL_SPEC:
633
- DHD_DBGIF(("%s\n",
634
- wf_chspec_ntoa(
635
- ltoh16_ua(&tlv_data->value[0]), chanbuf)));
636
- break;
637
- default:
638
- if (DHD_DBGIF_ON()) {
639
- prhex(NULL, &tlv_data->value[0], tlv_data->len);
640
- }
377
+
378
+ return TRUE;
379
+ } else {
380
+ return FALSE;
381
+ }
382
+}
383
+
384
+/* To identify format of non string format types */
385
+bool
386
+check_valid_non_string_format(char *curr_ptr)
387
+{
388
+ char *next_ptr;
389
+ char *next_fmt_stptr;
390
+ char valid_fmt_types[17] = {'d', 'i', 'x', 'X', 'c', 'p', 'u',
391
+ 'f', 'F', 'e', 'E', 'g', 'G', 'o',
392
+ 'a', 'A', 'n'};
393
+ int i;
394
+ bool valid = FALSE;
395
+
396
+ /* Check for next % in the fmt str */
397
+ next_fmt_stptr = bcmstrstr(curr_ptr, "%");
398
+
399
+ for (next_ptr = curr_ptr; *next_ptr != '\0'; next_ptr++) {
400
+ for (i = 0; i < (int)((sizeof(valid_fmt_types))/sizeof(valid_fmt_types[0])); i++) {
401
+ if (*next_ptr == valid_fmt_types[i]) {
402
+ /* Check whether format type found corresponds to current %
403
+ * and not the next one, if exists.
404
+ */
405
+ if ((next_fmt_stptr == NULL) ||
406
+ (next_fmt_stptr && (next_ptr < next_fmt_stptr))) {
407
+ /* Not validating for length/width fields in
408
+ * format specifier.
409
+ */
410
+ valid = TRUE;
641411 }
642
- dest_tlvs += tlv_data->len + sizeof(tlv_log);
412
+ goto done;
643413 }
644414 }
645
- msg_hdr.len = tot_payload_len;
646
- dhd_dbg_ring_push(dhdp, FW_EVENT_RING_ID, &msg_hdr, event_data);
647
- MFREE(dhdp->osh, event_data, payload_len);
648415 }
649
- return ret;
416
+
417
+done:
418
+ return valid;
650419 }
651420
652421 #define MAX_NO_OF_ARG 16
653
-#define FMTSTR_SIZE 132
654
-#define ROMSTR_SIZE 200
422
+#define FMTSTR_SIZE 200
423
+#define ROMSTR_SIZE 268
655424 #define SIZE_LOC_STR 50
656
-static void
657
-dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr,
658
- void *raw_event_ptr)
659
-{
660
- dhd_event_log_t *raw_event = (dhd_event_log_t *)raw_event_ptr;
661
- event_log_hdr_t *ts_hdr;
662
- uint32 *log_ptr = (uint32 *)hdr - hdr->count;
663
- uint16 count;
664
- int log_level, id;
665
- char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
666
- uint32 rom_str_len = 0;
667
- char (*str_buf)[SIZE_LOC_STR] = NULL;
668
- char *str_tmpptr = NULL;
669
- uint32 addr = 0;
670
- typedef union {
671
- uint32 val;
672
- char * addr;
673
- } u_arg;
674
- u_arg arg[MAX_NO_OF_ARG] = {{0}};
675
- char *c_ptr = NULL;
676
- uint32 *ts_data;
677
- static uint64 ts_saved = 0;
678
- dhd_dbg_ring_entry_t msg_hdr;
679
- struct bcmstrbuf b;
680
- UNUSED_PARAMETER(arg);
425
+#define LOG_PRINT_CNT_MAX 16u
426
+#define EL_PARSE_VER "V02"
427
+#define EL_MSEC_PER_SEC 1000
428
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
429
+#define MAX_LOG_PRINT_COUNT 100u
430
+#define LOG_PRINT_THRESH (1u * USEC_PER_SEC)
431
+#endif // endif
681432
682
- /* Get time stamp if it's updated */
683
- ts_hdr = (void *)log_ptr - sizeof(event_log_hdr_t);
684
- if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
685
- ts_data = (uint32 *)ts_hdr - ts_hdr->count;
686
- ts_saved = (uint64)ts_data[0];
687
- DHD_MSGTRACE_LOG(("EVENT_LOG_TS[0x%08x]: SYS:%08x CPU:%08x\n",
688
- ts_data[ts_hdr->count - 1], ts_data[0], ts_data[1]));
433
+bool
434
+dhd_dbg_process_event_log_hdr(event_log_hdr_t *log_hdr, prcd_event_log_hdr_t *prcd_log_hdr)
435
+{
436
+ event_log_extended_hdr_t *ext_log_hdr;
437
+ uint16 event_log_fmt_num;
438
+ uint8 event_log_hdr_type;
439
+
440
+ /* Identify the type of event tag, payload type etc.. */
441
+ event_log_hdr_type = log_hdr->fmt_num & DHD_EVENT_LOG_HDR_MASK;
442
+ event_log_fmt_num = (log_hdr->fmt_num >> DHD_EVENT_LOG_FMT_NUM_OFFSET) &
443
+ DHD_EVENT_LOG_FMT_NUM_MASK;
444
+
445
+ switch (event_log_hdr_type) {
446
+ case DHD_OW_NB_EVENT_LOG_HDR:
447
+ prcd_log_hdr->ext_event_log_hdr = FALSE;
448
+ prcd_log_hdr->binary_payload = FALSE;
449
+ break;
450
+ case DHD_TW_NB_EVENT_LOG_HDR:
451
+ prcd_log_hdr->ext_event_log_hdr = TRUE;
452
+ prcd_log_hdr->binary_payload = FALSE;
453
+ break;
454
+ case DHD_BI_EVENT_LOG_HDR:
455
+ if (event_log_fmt_num == DHD_OW_BI_EVENT_FMT_NUM) {
456
+ prcd_log_hdr->ext_event_log_hdr = FALSE;
457
+ prcd_log_hdr->binary_payload = TRUE;
458
+ } else if (event_log_fmt_num == DHD_TW_BI_EVENT_FMT_NUM) {
459
+ prcd_log_hdr->ext_event_log_hdr = TRUE;
460
+ prcd_log_hdr->binary_payload = TRUE;
461
+ } else {
462
+ DHD_ERROR(("%s: invalid format number 0x%X\n",
463
+ __FUNCTION__, event_log_fmt_num));
464
+ return FALSE;
465
+ }
466
+ break;
467
+ case DHD_INVALID_EVENT_LOG_HDR:
468
+ default:
469
+ DHD_ERROR(("%s: invalid event log header type 0x%X\n",
470
+ __FUNCTION__, event_log_hdr_type));
471
+ return FALSE;
689472 }
690473
691
- if (hdr->tag == EVENT_LOG_TAG_ROM_PRINTF) {
692
- rom_str_len = (hdr->count - 1) * sizeof(uint32);
474
+ /* Parse extended and legacy event log headers and populate prcd_event_log_hdr_t */
475
+ if (prcd_log_hdr->ext_event_log_hdr) {
476
+ ext_log_hdr = (event_log_extended_hdr_t *)
477
+ ((uint8 *)log_hdr - sizeof(event_log_hdr_t));
478
+ prcd_log_hdr->tag = ((ext_log_hdr->extended_tag &
479
+ DHD_TW_VALID_TAG_BITS_MASK) << DHD_TW_EVENT_LOG_TAG_OFFSET) | log_hdr->tag;
480
+ } else {
481
+ prcd_log_hdr->tag = log_hdr->tag;
482
+ }
483
+ prcd_log_hdr->count = log_hdr->count;
484
+ prcd_log_hdr->fmt_num_raw = log_hdr->fmt_num;
485
+ prcd_log_hdr->fmt_num = event_log_fmt_num;
486
+
487
+ /* update arm cycle */
488
+ /*
489
+ * For loegacy event tag :-
490
+ * |payload........|Timestamp| Tag
491
+ *
492
+ * For extended event tag:-
493
+ * |payload........|Timestamp|extended Tag| Tag.
494
+ *
495
+ */
496
+ prcd_log_hdr->armcycle = prcd_log_hdr->ext_event_log_hdr ?
497
+ *(uint32 *)(log_hdr - EVENT_TAG_TIMESTAMP_EXT_OFFSET) :
498
+ *(uint32 *)(log_hdr - EVENT_TAG_TIMESTAMP_OFFSET);
499
+
500
+ /* update event log data pointer address */
501
+ prcd_log_hdr->log_ptr =
502
+ (uint32 *)log_hdr - log_hdr->count - prcd_log_hdr->ext_event_log_hdr;
503
+
504
+ /* handle error cases above this */
505
+ return TRUE;
506
+}
507
+
508
+static void
509
+dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, prcd_event_log_hdr_t *plog_hdr,
510
+ void *raw_event_ptr, uint32 logset, uint16 block, uint32* data)
511
+{
512
+ event_log_hdr_t *ts_hdr;
513
+ uint32 *log_ptr = plog_hdr->log_ptr;
514
+ char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
515
+ uint32 rom_str_len = 0;
516
+ uint32 *ts_data;
517
+
518
+ if (!raw_event_ptr) {
519
+ return;
520
+ }
521
+
522
+ if (log_ptr < data) {
523
+ DHD_ERROR(("Invalid log pointer, logptr : %p data : %p \n", log_ptr, data));
524
+ return;
525
+ }
526
+
527
+ BCM_REFERENCE(ts_hdr);
528
+ BCM_REFERENCE(ts_data);
529
+
530
+ if (log_ptr > data) {
531
+ /* Get time stamp if it's updated */
532
+ ts_hdr = (event_log_hdr_t *)((char *)log_ptr - sizeof(event_log_hdr_t));
533
+ if (ts_hdr->tag == EVENT_LOG_TAG_TS) {
534
+ ts_data = (uint32 *)ts_hdr - ts_hdr->count;
535
+ if (ts_data >= data) {
536
+ DHD_MSGTRACE_LOG(("EVENT_LOG_TS[0x%08x]: SYS:%08x CPU:%08x\n",
537
+ ts_data[ts_hdr->count - 1], ts_data[0], ts_data[1]));
538
+ }
539
+ }
540
+ }
541
+
542
+ if (plog_hdr->tag == EVENT_LOG_TAG_ROM_PRINTF) {
543
+ rom_str_len = (plog_hdr->count - 1) * sizeof(uint32);
693544 if (rom_str_len >= (ROMSTR_SIZE -1))
694545 rom_str_len = ROMSTR_SIZE - 1;
695546
....@@ -699,7 +550,7 @@
699550 fmtstr_loc_buf[rom_str_len] = '\0';
700551
701552 DHD_MSGTRACE_LOG(("EVENT_LOG_ROM[0x%08x]: %s",
702
- log_ptr[hdr->count - 1], fmtstr_loc_buf));
553
+ log_ptr[plog_hdr->count - 1], fmtstr_loc_buf));
703554
704555 /* Add newline if missing */
705556 if (fmtstr_loc_buf[strlen(fmtstr_loc_buf) - 1] != '\n')
....@@ -708,36 +559,121 @@
708559 return;
709560 }
710561
562
+ if (plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE ||
563
+ plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE_TLV) {
564
+ wl_mschdbg_verboselog_handler(dhdp, raw_event_ptr, plog_hdr, log_ptr);
565
+ return;
566
+ }
567
+
711568 /* print the message out in a logprint */
712
- if (!(((raw_event->raw_sstr) || (raw_event->rom_raw_sstr)) &&
713
- raw_event->fmts) || hdr->fmt_num == 0xffff) {
569
+ dhd_dbg_verboselog_printf(dhdp, plog_hdr, raw_event_ptr, log_ptr, logset, block);
570
+}
571
+
572
+void
573
+dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, prcd_event_log_hdr_t *plog_hdr,
574
+ void *raw_event_ptr, uint32 *log_ptr, uint32 logset, uint16 block)
575
+{
576
+ dhd_event_log_t *raw_event = (dhd_event_log_t *)raw_event_ptr;
577
+ uint16 count;
578
+ int log_level, id;
579
+ char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
580
+ char (*str_buf)[SIZE_LOC_STR] = NULL;
581
+ char *str_tmpptr = NULL;
582
+ uint32 addr = 0;
583
+ typedef union {
584
+ uint32 val;
585
+ char * addr;
586
+ } u_arg;
587
+ u_arg arg[MAX_NO_OF_ARG] = {{0}};
588
+ char *c_ptr = NULL;
589
+ struct bcmstrbuf b;
590
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
591
+ static int log_print_count = 0;
592
+ static uint64 ts0 = 0;
593
+ uint64 ts1 = 0;
594
+#endif /* DHD_LOG_PRINT_RATE_LIMIT */
595
+
596
+ BCM_REFERENCE(arg);
597
+
598
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
599
+ if (!ts0)
600
+ ts0 = OSL_SYSUPTIME_US();
601
+
602
+ ts1 = OSL_SYSUPTIME_US();
603
+
604
+ if (((ts1 - ts0) <= LOG_PRINT_THRESH) && (log_print_count >= MAX_LOG_PRINT_COUNT)) {
605
+ log_print_threshold = 1;
606
+ ts0 = 0;
607
+ log_print_count = 0;
608
+ DHD_ERROR(("%s: Log print water mark is reached,"
609
+ " console logs are dumped only to debug_dump file\n", __FUNCTION__));
610
+ } else if ((ts1 - ts0) > LOG_PRINT_THRESH) {
611
+ log_print_threshold = 0;
612
+ ts0 = 0;
613
+ log_print_count = 0;
614
+ }
615
+
616
+#endif /* DHD_LOG_PRINT_RATE_LIMIT */
617
+ /* print the message out in a logprint. Logprint expects raw format number */
618
+ if (!(raw_event->fmts)) {
714619 if (dhdp->dbg) {
715620 log_level = dhdp->dbg->dbg_rings[FW_VERBOSE_RING_ID].log_level;
716621 for (id = 0; id < ARRAYSIZE(fw_verbose_level_map); id++) {
717
- if ((fw_verbose_level_map[id].tag == hdr->tag) &&
622
+ if ((fw_verbose_level_map[id].tag == plog_hdr->tag) &&
718623 (fw_verbose_level_map[id].log_level > log_level))
719624 return;
720625 }
721626 }
722627
723
- bcm_binit(&b, fmtstr_loc_buf, FMTSTR_SIZE);
724
- bcm_bprintf(&b, "%d.%d EL: %x %x", (uint32)ts_saved / 1000,
725
- (uint32)ts_saved % 1000,
726
- hdr->tag & EVENT_LOG_TAG_FLAG_SET_MASK,
727
- hdr->fmt_num);
728
- for (count = 0; count < (hdr->count - 1); count++)
729
- bcm_bprintf(&b, " %x", log_ptr[count]);
730
- bcm_bprintf(&b, "\n");
731
- DHD_MSGTRACE_LOG(("%s\n", b.origbuf));
732
- if (!dhdp->dbg)
733
- return;
734
- memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
735
- msg_hdr.timestamp = ts_saved;
736
- msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP;
737
- msg_hdr.type = DBG_RING_ENTRY_DATA_TYPE;
738
- msg_hdr.len = b.origsize - b.size;
739
- dhd_dbg_ring_push(dhdp, FW_VERBOSE_RING_ID, &msg_hdr,
740
- b.origbuf);
628
+ if (plog_hdr->binary_payload) {
629
+ DHD_ECNTR_LOG(("%06d.%03d EL:tag=%d len=%d fmt=0x%x",
630
+ (uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
631
+ (uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
632
+ plog_hdr->tag,
633
+ plog_hdr->count,
634
+ plog_hdr->fmt_num_raw));
635
+
636
+ for (count = 0; count < (plog_hdr->count - 1); count++) {
637
+ if (count && (count % LOG_PRINT_CNT_MAX == 0)) {
638
+ DHD_ECNTR_LOG(("\n\t%08x", log_ptr[count]));
639
+ } else {
640
+ DHD_ECNTR_LOG((" %08x", log_ptr[count]));
641
+ }
642
+ }
643
+ DHD_ECNTR_LOG(("\n"));
644
+ }
645
+ else {
646
+ bcm_binit(&b, fmtstr_loc_buf, FMTSTR_SIZE);
647
+#ifndef OEM_ANDROID
648
+ bcm_bprintf(&b, "%06d.%03d EL: %d 0x%x",
649
+ (uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
650
+ (uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
651
+ plog_hdr->tag,
652
+ plog_hdr->fmt_num_raw);
653
+#else
654
+ bcm_bprintf(&b, "%06d.%03d EL:%s:%u:%u %d %d 0x%x",
655
+ (uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
656
+ (uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
657
+ EL_PARSE_VER, logset, block,
658
+ plog_hdr->tag,
659
+ plog_hdr->count,
660
+ plog_hdr->fmt_num_raw);
661
+#endif /* !OEM_ANDROID */
662
+ for (count = 0; count < (plog_hdr->count - 1); count++) {
663
+ bcm_bprintf(&b, " %x", log_ptr[count]);
664
+ }
665
+
666
+ /* ensure preserve fw logs go to debug_dump only in case of customer4 */
667
+ if (logset < dhdp->event_log_max_sets &&
668
+ ((0x01u << logset) & dhdp->logset_prsrv_mask)) {
669
+ DHD_PRSRV_MEM(("%s\n", b.origbuf));
670
+ } else {
671
+ DHD_FWLOG(("%s\n", b.origbuf));
672
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
673
+ log_print_count++;
674
+#endif /* DHD_LOG_PRINT_RATE_LIMIT */
675
+ }
676
+ }
741677 return;
742678 }
743679
....@@ -747,96 +683,248 @@
747683 return;
748684 }
749685
750
- if ((hdr->fmt_num >> 2) < raw_event->num_fmts) {
751
- snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "CONSOLE_E: [0x%x] %s",
752
- log_ptr[hdr->count-1],
753
- raw_event->fmts[hdr->fmt_num >> 2]);
686
+ if ((plog_hdr->fmt_num) < raw_event->num_fmts) {
687
+ if (plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE) {
688
+ snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "%s",
689
+ raw_event->fmts[plog_hdr->fmt_num]);
690
+ plog_hdr->count++;
691
+ } else {
692
+ snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "CONSOLE_E:%u:%u %06d.%03d %s",
693
+ logset, block,
694
+ (uint32)(log_ptr[plog_hdr->count - 1] / EL_MSEC_PER_SEC),
695
+ (uint32)(log_ptr[plog_hdr->count - 1] % EL_MSEC_PER_SEC),
696
+ raw_event->fmts[plog_hdr->fmt_num]);
697
+ }
754698 c_ptr = fmtstr_loc_buf;
755699 } else {
756
- DHD_ERROR(("%s: fmt number out of range \n", __FUNCTION__));
700
+ /* for ecounters, don't print the error as it will flood */
701
+ if ((plog_hdr->fmt_num != DHD_OW_BI_EVENT_FMT_NUM) &&
702
+ (plog_hdr->fmt_num != DHD_TW_BI_EVENT_FMT_NUM)) {
703
+ DHD_ERROR(("%s: fmt number: 0x%x out of range\n",
704
+ __FUNCTION__, plog_hdr->fmt_num));
705
+ } else {
706
+ DHD_INFO(("%s: fmt number: 0x%x out of range\n",
707
+ __FUNCTION__, plog_hdr->fmt_num));
708
+ }
709
+
757710 goto exit;
758711 }
759712
760
- for (count = 0; count < (hdr->count - 1); count++) {
713
+ if (plog_hdr->count > MAX_NO_OF_ARG) {
714
+ DHD_ERROR(("%s: plog_hdr->count(%d) out of range\n",
715
+ __FUNCTION__, plog_hdr->count));
716
+ goto exit;
717
+ }
718
+
719
+ /* print the format string which will be needed for debugging incorrect formats */
720
+ DHD_INFO(("%s: fmtstr_loc_buf = %s\n", __FUNCTION__, fmtstr_loc_buf));
721
+
722
+ /* Replace all %p to %x to handle 32 bit %p */
723
+ replace_percent_p_to_x(fmtstr_loc_buf);
724
+
725
+ for (count = 0; count < (plog_hdr->count - 1); count++) {
761726 if (c_ptr != NULL)
762
- if ((c_ptr = strstr(c_ptr, "%")) != NULL)
727
+ if ((c_ptr = bcmstrstr(c_ptr, "%")) != NULL)
763728 c_ptr++;
764729
765
- if ((c_ptr != NULL) && (*c_ptr == 's')) {
766
- if ((raw_event->raw_sstr) &&
767
- ((log_ptr[count] > raw_event->rodata_start) &&
768
- (log_ptr[count] < raw_event->rodata_end))) {
769
- /* ram static string */
770
- addr = log_ptr[count] - raw_event->rodata_start;
771
- str_tmpptr = raw_event->raw_sstr + addr;
772
- memcpy(str_buf[count], str_tmpptr,
773
- SIZE_LOC_STR);
774
- str_buf[count][SIZE_LOC_STR-1] = '\0';
775
- arg[count].addr = str_buf[count];
776
- } else if ((raw_event->rom_raw_sstr) &&
777
- ((log_ptr[count] >
778
- raw_event->rom_rodata_start) &&
779
- (log_ptr[count] <
780
- raw_event->rom_rodata_end))) {
781
- /* rom static string */
782
- addr = log_ptr[count] - raw_event->rom_rodata_start;
783
- str_tmpptr = raw_event->rom_raw_sstr + addr;
784
- memcpy(str_buf[count], str_tmpptr,
785
- SIZE_LOC_STR);
786
- str_buf[count][SIZE_LOC_STR-1] = '\0';
787
- arg[count].addr = str_buf[count];
730
+ if (c_ptr != NULL) {
731
+ if (check_valid_string_format(c_ptr)) {
732
+ if ((raw_event->raw_sstr) &&
733
+ ((log_ptr[count] > raw_event->rodata_start) &&
734
+ (log_ptr[count] < raw_event->rodata_end))) {
735
+ /* ram static string */
736
+ addr = log_ptr[count] - raw_event->rodata_start;
737
+ str_tmpptr = raw_event->raw_sstr + addr;
738
+ memcpy(str_buf[count], str_tmpptr,
739
+ SIZE_LOC_STR);
740
+ str_buf[count][SIZE_LOC_STR-1] = '\0';
741
+ arg[count].addr = str_buf[count];
742
+ } else if ((raw_event->rom_raw_sstr) &&
743
+ ((log_ptr[count] >
744
+ raw_event->rom_rodata_start) &&
745
+ (log_ptr[count] <
746
+ raw_event->rom_rodata_end))) {
747
+ /* rom static string */
748
+ addr = log_ptr[count] - raw_event->rom_rodata_start;
749
+ str_tmpptr = raw_event->rom_raw_sstr + addr;
750
+ memcpy(str_buf[count], str_tmpptr,
751
+ SIZE_LOC_STR);
752
+ str_buf[count][SIZE_LOC_STR-1] = '\0';
753
+ arg[count].addr = str_buf[count];
754
+ } else {
755
+ /*
756
+ * Dynamic string OR
757
+ * No data for static string.
758
+ * So store all string's address as string.
759
+ */
760
+ snprintf(str_buf[count], SIZE_LOC_STR,
761
+ "(s)0x%x", log_ptr[count]);
762
+ arg[count].addr = str_buf[count];
763
+ }
764
+ } else if (check_valid_non_string_format(c_ptr)) {
765
+ /* Other than string format */
766
+ arg[count].val = log_ptr[count];
788767 } else {
789
- /*
790
- * Dynamic string OR
791
- * No data for static string.
792
- * So store all string's address as string.
793
- */
794
- snprintf(str_buf[count], SIZE_LOC_STR,
795
- "(s)0x%x", log_ptr[count]);
796
- arg[count].addr = str_buf[count];
768
+ *(c_ptr - 1) = '\0';
769
+ break;
797770 }
798
- } else {
799
- /* Other than string */
800
- arg[count].val = log_ptr[count];
801771 }
802
- DHD_DBGIF(("Arg val = %d and address = %p\n", arg[count].val, arg[count].addr));
803772 }
804
- DHD_EVENT((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
805
- arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
806
- arg[11], arg[12], arg[13], arg[14], arg[15]));
773
+
774
+ /* ensure preserve fw logs go to debug_dump only in case of customer4 */
775
+ if (logset < dhdp->event_log_max_sets &&
776
+ ((0x01u << logset) & dhdp->logset_prsrv_mask)) {
777
+ DHD_PRSRV_MEM((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
778
+ arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
779
+ arg[11], arg[12], arg[13], arg[14], arg[15]));
780
+ } else {
781
+ DHD_FWLOG((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3],
782
+ arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10],
783
+ arg[11], arg[12], arg[13], arg[14], arg[15]));
784
+#ifdef DHD_LOG_PRINT_RATE_LIMIT
785
+ log_print_count++;
786
+#endif /* DHD_LOG_PRINT_RATE_LIMIT */
787
+ }
807788
808789 exit:
809790 MFREE(dhdp->osh, str_buf, (MAX_NO_OF_ARG * SIZE_LOC_STR));
810791 }
811792
812
-static void
793
+void
813794 dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data,
814
- void *raw_event_ptr, uint datalen)
795
+ void *raw_event_ptr, uint datalen, bool msgtrace_hdr_present,
796
+ uint32 msgtrace_seqnum)
815797 {
816798 msgtrace_hdr_t *hdr;
817
- char *data;
818
- int id;
819
- uint32 hdrlen = sizeof(event_log_hdr_t);
799
+ char *data, *tmpdata;
800
+ const uint32 log_hdr_len = sizeof(event_log_hdr_t);
801
+ uint32 log_pyld_len;
820802 static uint32 seqnum_prev = 0;
821803 event_log_hdr_t *log_hdr;
822804 bool msg_processed = FALSE;
823
- uint32 *log_ptr = NULL;
805
+ prcd_event_log_hdr_t prcd_log_hdr;
806
+ prcd_event_log_hdr_t *plog_hdr;
824807 dll_t list_head, *cur;
825808 loglist_item_t *log_item;
826
- uint32 nan_evt_ring_log_level = 0;
809
+ dhd_dbg_ring_entry_t msg_hdr;
810
+ char *logbuf;
811
+ struct tracelog_header *logentry_header;
812
+ uint ring_data_len = 0;
813
+ bool ecntr_pushed = FALSE;
814
+ bool rtt_pushed = FALSE;
815
+ bool dll_inited = FALSE;
816
+ uint32 logset = 0;
817
+ uint16 block = 0;
818
+ bool event_log_max_sets_queried;
819
+ uint32 event_log_max_sets;
820
+ uint min_expected_len = 0;
821
+ uint16 len_chk = 0;
827822
828
- hdr = (msgtrace_hdr_t *)event_data;
829
- data = (char *)event_data + MSGTRACE_HDRLEN;
830
- datalen -= MSGTRACE_HDRLEN;
823
+ BCM_REFERENCE(ecntr_pushed);
824
+ BCM_REFERENCE(rtt_pushed);
825
+ BCM_REFERENCE(len_chk);
831826
832
- if (dhd_dbg_msgtrace_seqchk(&seqnum_prev, ntoh32(hdr->seqnum)))
827
+ /* store event_logset_queried and event_log_max_sets in local variables
828
+ * to avoid race conditions as they were set from different contexts(preinit)
829
+ */
830
+ event_log_max_sets_queried = dhdp->event_log_max_sets_queried;
831
+ /* Make sure queried is read first with wmb and then max_sets,
832
+ * as it is done in reverse order during preinit ioctls.
833
+ */
834
+ OSL_SMP_WMB();
835
+ event_log_max_sets = dhdp->event_log_max_sets;
836
+
837
+ if (msgtrace_hdr_present)
838
+ min_expected_len = (MSGTRACE_HDRLEN + EVENT_LOG_BLOCK_LEN);
839
+ else
840
+ min_expected_len = EVENT_LOG_BLOCK_LEN;
841
+
842
+ /* log trace event consists of:
843
+ * msgtrace header
844
+ * event log block header
845
+ * event log payload
846
+ */
847
+ if (!event_data || (datalen <= min_expected_len)) {
848
+ DHD_ERROR(("%s: Not processing due to invalid event_data : %p or length : %d\n",
849
+ __FUNCTION__, event_data, datalen));
850
+ if (event_data && msgtrace_hdr_present) {
851
+ prhex("event_data dump", event_data, datalen);
852
+ tmpdata = (char *)event_data + MSGTRACE_HDRLEN;
853
+ if (tmpdata) {
854
+ DHD_ERROR(("EVENT_LOG_HDR[0x%x]: Set: 0x%08x length = %d\n",
855
+ ltoh16(*((uint16 *)(tmpdata+2))),
856
+ ltoh32(*((uint32 *)(tmpdata + 4))),
857
+ ltoh16(*((uint16 *)(tmpdata)))));
858
+ }
859
+ } else if (!event_data) {
860
+ DHD_ERROR(("%s: event_data is NULL, cannot dump prhex\n", __FUNCTION__));
861
+ }
862
+ return;
863
+ }
864
+
865
+ if (msgtrace_hdr_present) {
866
+ hdr = (msgtrace_hdr_t *)event_data;
867
+ data = (char *)event_data + MSGTRACE_HDRLEN;
868
+ datalen -= MSGTRACE_HDRLEN;
869
+ msgtrace_seqnum = ntoh32(hdr->seqnum);
870
+ } else {
871
+ data = (char *)event_data;
872
+ }
873
+
874
+ if (dhd_dbg_msgtrace_seqchk(&seqnum_prev, msgtrace_seqnum))
833875 return;
834876
835
- DHD_MSGTRACE_LOG(("EVENT_LOG_HDR[No.%d]: timestamp 0x%08x length = %d\n",
836
- ltoh16(*((uint16 *)data)), ltoh16(*((uint16 *)(data + 2))),
837
- ltoh32(*((uint32 *)(data+4)))));
838
- data += 8;
839
- datalen -= 8;
877
+ /* Save the whole message to event log ring */
878
+ memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t));
879
+ logbuf = VMALLOC(dhdp->osh, sizeof(*logentry_header) + datalen);
880
+ if (logbuf == NULL)
881
+ return;
882
+ logentry_header = (struct tracelog_header *)logbuf;
883
+ logentry_header->magic_num = TRACE_LOG_MAGIC_NUMBER;
884
+ logentry_header->buf_size = datalen;
885
+ logentry_header->seq_num = msgtrace_seqnum;
886
+ msg_hdr.type = DBG_RING_ENTRY_DATA_TYPE;
887
+
888
+ ring_data_len = datalen + sizeof(*logentry_header);
889
+
890
+ if ((sizeof(*logentry_header) + datalen) > PAYLOAD_MAX_LEN) {
891
+ DHD_ERROR(("%s:Payload len=%u exceeds max len\n", __FUNCTION__,
892
+ ((uint)sizeof(*logentry_header) + datalen)));
893
+ goto exit;
894
+ }
895
+
896
+ msg_hdr.len = sizeof(*logentry_header) + datalen;
897
+ memcpy(logbuf + sizeof(*logentry_header), data, datalen);
898
+ DHD_DBGIF(("%s: datalen %d %d\n", __FUNCTION__, msg_hdr.len, datalen));
899
+ dhd_dbg_push_to_ring(dhdp, FW_VERBOSE_RING_ID, &msg_hdr, logbuf);
900
+
901
+ /* Print sequence number, originating set and length of received
902
+ * event log buffer. Refer to event log buffer structure in
903
+ * event_log.h
904
+ */
905
+ DHD_MSGTRACE_LOG(("EVENT_LOG_HDR[0x%x]: Set: 0x%08x length = %d\n",
906
+ ltoh16(*((uint16 *)(data+2))), ltoh32(*((uint32 *)(data + 4))),
907
+ ltoh16(*((uint16 *)(data)))));
908
+
909
+ logset = ltoh32(*((uint32 *)(data + 4)));
910
+
911
+ if (logset >= event_log_max_sets) {
912
+ DHD_ERROR(("%s logset: %d max: %d out of range queried: %d\n",
913
+ __FUNCTION__, logset, event_log_max_sets, event_log_max_sets_queried));
914
+#ifdef DHD_FW_COREDUMP
915
+ if (event_log_max_sets_queried) {
916
+ DHD_ERROR(("%s: collect socram for DUMP_TYPE_LOGSET_BEYOND_RANGE\n",
917
+ __FUNCTION__));
918
+ dhdp->memdump_type = DUMP_TYPE_LOGSET_BEYOND_RANGE;
919
+ dhd_bus_mem_dump(dhdp);
920
+ }
921
+#endif /* DHD_FW_COREDUMP */
922
+ }
923
+
924
+ block = ltoh16(*((uint16 *)(data+2)));
925
+
926
+ data += EVENT_LOG_BLOCK_HDRLEN;
927
+ datalen -= EVENT_LOG_BLOCK_HDRLEN;
840928
841929 /* start parsing from the tail of packet
842930 * Sameple format of a meessage
....@@ -845,27 +933,53 @@
845933 * 0x0c580439 -- 39 is tag, 04 is count, 580c is format number
846934 * all these uint32 values comes in reverse order as group as EL data
847935 * while decoding we can only parse from last to first
936
+ * |<- datalen ->|
937
+ * |----(payload and maybe more logs)----|event_log_hdr_t|
938
+ * data log_hdr
848939 */
849940 dll_init(&list_head);
850
- while (datalen > 0) {
851
- log_hdr = (event_log_hdr_t *)(data + datalen - hdrlen);
852
- /* pratially overwritten entries */
853
- if ((uint32 *)log_hdr - (uint32 *)data < log_hdr->count)
854
- break;
855
- /* Check argument count (only when format is valid) */
856
- if ((log_hdr->count > MAX_NO_OF_ARG) &&
857
- (log_hdr->fmt_num != 0xffff))
858
- break;
859
- /* end of frame? */
860
- if (log_hdr->tag == EVENT_LOG_TAG_NULL) {
861
- log_hdr--;
862
- datalen -= hdrlen;
941
+ dll_inited = TRUE;
942
+
943
+ while (datalen > log_hdr_len) {
944
+ log_hdr = (event_log_hdr_t *)(data + datalen - log_hdr_len);
945
+ memset(&prcd_log_hdr, 0, sizeof(prcd_log_hdr));
946
+ if (!dhd_dbg_process_event_log_hdr(log_hdr, &prcd_log_hdr)) {
947
+ DHD_ERROR(("%s: Error while parsing event log header\n",
948
+ __FUNCTION__));
949
+ }
950
+
951
+ /* skip zero padding at end of frame */
952
+ if (prcd_log_hdr.tag == EVENT_LOG_TAG_NULL) {
953
+ datalen -= log_hdr_len;
863954 continue;
864955 }
956
+ /* Check argument count (for non-ecounter events only),
957
+ * any event log should contain at least
958
+ * one argument (4 bytes) for arm cycle count and up to 16
959
+ * arguments except EVENT_LOG_TAG_STATS which could use the
960
+ * whole payload of 256 words
961
+ */
962
+ if (prcd_log_hdr.count == 0) {
963
+ break;
964
+ }
965
+ /* Both tag_stats and proxd are binary payloads so skip
966
+ * argument count check for these.
967
+ */
968
+ if ((prcd_log_hdr.tag != EVENT_LOG_TAG_STATS) &&
969
+ (prcd_log_hdr.tag != EVENT_LOG_TAG_PROXD_SAMPLE_COLLECT) &&
970
+ (prcd_log_hdr.count > MAX_NO_OF_ARG)) {
971
+ break;
972
+ }
973
+
974
+ log_pyld_len = (prcd_log_hdr.count + prcd_log_hdr.ext_event_log_hdr) *
975
+ DATA_UNIT_FOR_LOG_CNT;
976
+ /* log data should not cross the event data boundary */
977
+ if ((uint32)((char *)log_hdr - data) < log_pyld_len) {
978
+ break;
979
+ }
865980 /* skip 4 bytes time stamp packet */
866
- if (log_hdr->tag == EVENT_LOG_TAG_TS) {
867
- datalen -= log_hdr->count * 4 + hdrlen;
868
- log_hdr -= log_hdr->count + hdrlen / 4;
981
+ if (prcd_log_hdr.tag == EVENT_LOG_TAG_TS) {
982
+ datalen -= (log_pyld_len + log_hdr_len);
869983 continue;
870984 }
871985 if (!(log_item = MALLOC(dhdp->osh, sizeof(*log_item)))) {
....@@ -873,79 +987,132 @@
873987 __FUNCTION__));
874988 break;
875989 }
876
- log_item->hdr = log_hdr;
990
+
991
+ log_item->prcd_log_hdr.tag = prcd_log_hdr.tag;
992
+ log_item->prcd_log_hdr.count = prcd_log_hdr.count;
993
+ log_item->prcd_log_hdr.fmt_num = prcd_log_hdr.fmt_num;
994
+ log_item->prcd_log_hdr.fmt_num_raw = prcd_log_hdr.fmt_num_raw;
995
+ log_item->prcd_log_hdr.armcycle = prcd_log_hdr.armcycle;
996
+ log_item->prcd_log_hdr.log_ptr = prcd_log_hdr.log_ptr;
997
+ log_item->prcd_log_hdr.payload_len = prcd_log_hdr.payload_len;
998
+ log_item->prcd_log_hdr.ext_event_log_hdr = prcd_log_hdr.ext_event_log_hdr;
999
+ log_item->prcd_log_hdr.binary_payload = prcd_log_hdr.binary_payload;
1000
+
8771001 dll_insert(&log_item->list, &list_head);
878
- datalen -= (log_hdr->count * 4 + hdrlen);
1002
+ datalen -= (log_pyld_len + log_hdr_len);
8791003 }
8801004
8811005 while (!dll_empty(&list_head)) {
8821006 msg_processed = FALSE;
8831007 cur = dll_head_p(&list_head);
1008
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1009
+#pragma GCC diagnostic push
1010
+#pragma GCC diagnostic ignored "-Wcast-qual"
1011
+#endif // endif
8841012 log_item = (loglist_item_t *)container_of(cur, loglist_item_t, list);
885
- log_hdr = log_item->hdr;
886
- log_ptr = (uint32 *)log_hdr - log_hdr->count;
1013
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1014
+#pragma GCC diagnostic pop
1015
+#endif // endif
1016
+
1017
+ plog_hdr = &log_item->prcd_log_hdr;
1018
+
1019
+#if defined(EWP_ECNTRS_LOGGING) && defined(DHD_LOG_DUMP)
1020
+ /* Ecounter tag can be time_data or log_stats+binary paloaod */
1021
+ if ((plog_hdr->tag == EVENT_LOG_TAG_ECOUNTERS_TIME_DATA) ||
1022
+ ((plog_hdr->tag == EVENT_LOG_TAG_STATS) &&
1023
+ (plog_hdr->binary_payload))) {
1024
+ if (!ecntr_pushed && dhd_log_dump_ecntr_enabled()) {
1025
+ /*
1026
+ * check msg hdr len before pushing.
1027
+ * FW msg_hdr.len includes length of event log hdr,
1028
+ * logentry header and payload.
1029
+ */
1030
+ len_chk = (sizeof(*logentry_header) + sizeof(*log_hdr) +
1031
+ PAYLOAD_ECNTR_MAX_LEN);
1032
+ /* account extended event log header(extended_event_log_hdr) */
1033
+ if (plog_hdr->ext_event_log_hdr) {
1034
+ len_chk += sizeof(*log_hdr);
1035
+ }
1036
+ if (msg_hdr.len > len_chk) {
1037
+ DHD_ERROR(("%s: EVENT_LOG_VALIDATION_FAILS: "
1038
+ "msg_hdr.len=%u, max allowed for ecntrs=%u\n",
1039
+ __FUNCTION__, msg_hdr.len, len_chk));
1040
+ goto exit;
1041
+ }
1042
+ dhd_dbg_ring_push(dhdp->ecntr_dbg_ring, &msg_hdr, logbuf);
1043
+ ecntr_pushed = TRUE;
1044
+ }
1045
+ }
1046
+#endif /* EWP_ECNTRS_LOGGING && DHD_LOG_DUMP */
1047
+
1048
+#if defined(EWP_RTT_LOGGING) && defined(DHD_LOG_DUMP)
1049
+ if ((plog_hdr->tag == EVENT_LOG_TAG_PROXD_SAMPLE_COLLECT) &&
1050
+ plog_hdr->binary_payload) {
1051
+ if (!rtt_pushed && dhd_log_dump_rtt_enabled()) {
1052
+ /*
1053
+ * check msg hdr len before pushing.
1054
+ * FW msg_hdr.len includes length of event log hdr,
1055
+ * logentry header and payload.
1056
+ */
1057
+ len_chk = (sizeof(*logentry_header) + sizeof(*log_hdr) +
1058
+ PAYLOAD_RTT_MAX_LEN);
1059
+ /* account extended event log header(extended_event_log_hdr) */
1060
+ if (plog_hdr->ext_event_log_hdr) {
1061
+ len_chk += sizeof(*log_hdr);
1062
+ }
1063
+ if (msg_hdr.len > len_chk) {
1064
+ DHD_ERROR(("%s: EVENT_LOG_VALIDATION_FAILS: "
1065
+ "msg_hdr.len=%u, max allowed for ecntrs=%u\n",
1066
+ __FUNCTION__, msg_hdr.len, len_chk));
1067
+ goto exit;
1068
+ }
1069
+ dhd_dbg_ring_push(dhdp->rtt_dbg_ring, &msg_hdr, logbuf);
1070
+ rtt_pushed = TRUE;
1071
+ }
1072
+ }
1073
+#endif /* EWP_RTT_LOGGING && DHD_LOG_DUMP */
1074
+
1075
+#if defined(DHD_EVENT_LOG_FILTER)
1076
+ if (plog_hdr->tag == EVENT_LOG_TAG_STATS) {
1077
+ dhd_event_log_filter_event_handler(dhdp, plog_hdr, plog_hdr->log_ptr);
1078
+ }
1079
+#endif /* DHD_EVENT_LOG_FILTER */
1080
+
1081
+ if (!msg_processed) {
1082
+ dhd_dbg_verboselog_handler(dhdp, plog_hdr, raw_event_ptr,
1083
+ logset, block, (uint32 *)data);
1084
+ }
8871085 dll_delete(cur);
8881086 MFREE(dhdp->osh, log_item, sizeof(*log_item));
8891087
890
- /* Before DHD debugability is implemented WLC_E_TRACE had been
891
- * used to carry verbose logging from firmware. We need to
892
- * be able to handle those messages even without a initialized
893
- * debug layer.
894
- */
895
- if (dhdp->dbg) {
896
- /* check the data for NAN event ring; keeping first as small table */
897
- /* process only user configured to log */
898
- nan_evt_ring_log_level = dhdp->dbg->dbg_rings[NAN_EVENT_RING_ID].log_level;
899
- if (dhdp->dbg->dbg_rings[NAN_EVENT_RING_ID].log_level) {
900
- for (id = 0; id < ARRAYSIZE(nan_event_level_map); id++) {
901
- if (nan_event_level_map[id].tag == log_hdr->tag) {
902
- /* dont process if tag log level is greater
903
- * than ring log level
904
- */
905
- if (nan_event_level_map[id].log_level >
906
- nan_evt_ring_log_level) {
907
- msg_processed = TRUE;
908
- break;
909
- }
910
- /* In case of BCME_VERSION error,
911
- * this is not NAN event type data
912
- */
913
- if (dhd_dbg_nan_event_handler(dhdp,
914
- log_hdr, log_ptr) != BCME_VERSION) {
915
- msg_processed = TRUE;
916
- }
917
- break;
918
- }
919
- }
920
- }
921
- if (!msg_processed) {
922
- /* check the data for event ring */
923
- for (id = 0; id < ARRAYSIZE(fw_event_level_map); id++) {
924
- if (fw_event_level_map[id].tag == log_hdr->tag) {
925
- /* In case of BCME_VERSION error,
926
- * this is not event type data
927
- */
928
- if (dhd_dbg_custom_evnt_handler(dhdp,
929
- log_hdr, log_ptr) != BCME_VERSION) {
930
- msg_processed = TRUE;
931
- }
932
- break;
933
- }
934
- }
935
- }
936
- }
937
- if (!msg_processed)
938
- dhd_dbg_verboselog_handler(dhdp, log_hdr, raw_event_ptr);
939
-
9401088 }
1089
+ BCM_REFERENCE(log_hdr);
1090
+
1091
+exit:
1092
+ while (dll_inited && (!dll_empty(&list_head))) {
1093
+ cur = dll_head_p(&list_head);
1094
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1095
+#pragma GCC diagnostic push
1096
+#pragma GCC diagnostic ignored "-Wcast-qual"
1097
+#endif // endif
1098
+ log_item = (loglist_item_t *)container_of(cur, loglist_item_t, list);
1099
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1100
+#pragma GCC diagnostic pop
1101
+#endif // endif
1102
+ dll_delete(cur);
1103
+ MFREE(dhdp->osh, log_item, sizeof(*log_item));
1104
+ }
1105
+ VMFREE(dhdp->osh, logbuf, ring_data_len);
9411106 }
9421107 #else /* !SHOW_LOGTRACE */
9431108 static INLINE void dhd_dbg_verboselog_handler(dhd_pub_t *dhdp,
944
- event_log_hdr_t *hdr, void *raw_event_ptr) {};
945
-static INLINE void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp,
946
- void *event_data, void *raw_event_ptr, uint datalen) {};
1109
+ prcd_event_log_hdr_t *plog_hdr, void *raw_event_ptr, uint32 logset, uint16 block,
1110
+ uint32 *data) {};
1111
+INLINE void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp,
1112
+ void *event_data, void *raw_event_ptr, uint datalen,
1113
+ bool msgtrace_hdr_present, uint32 msgtrace_seqnum) {};
9471114 #endif /* SHOW_LOGTRACE */
948
-
1115
+#ifndef MACOSX_DHD
9491116 void
9501117 dhd_dbg_trace_evnt_handler(dhd_pub_t *dhdp, void *event_data,
9511118 void *raw_event_ptr, uint datalen)
....@@ -963,63 +1130,11 @@
9631130 if (hdr->trace_type == MSGTRACE_HDR_TYPE_MSG)
9641131 dhd_dbg_msgtrace_msg_parser(event_data);
9651132 else if (hdr->trace_type == MSGTRACE_HDR_TYPE_LOG)
966
- dhd_dbg_msgtrace_log_parser(dhdp, event_data, raw_event_ptr, datalen);
1133
+ dhd_dbg_msgtrace_log_parser(dhdp, event_data, raw_event_ptr, datalen,
1134
+ TRUE, 0);
9671135 }
9681136
969
-static int
970
-dhd_dbg_ring_init(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring, uint16 id, uint8 *name,
971
- uint32 ring_sz)
972
-{
973
- void *buf;
974
- unsigned long flags;
975
-
976
- buf = MALLOCZ(dhdp->osh, ring_sz);
977
- if (!buf)
978
- return BCME_NOMEM;
979
-
980
- ring->lock = dhd_os_spin_lock_init(dhdp->osh);
981
-
982
- flags = dhd_os_spin_lock(ring->lock);
983
- ring->id = id;
984
- strncpy(ring->name, name, DBGRING_NAME_MAX);
985
- ring->name[DBGRING_NAME_MAX - 1] = 0;
986
- ring->ring_size = ring_sz;
987
- ring->wp = ring->rp = 0;
988
- ring->ring_buf = buf;
989
- ring->threshold = DBGRING_FLUSH_THRESHOLD(ring);
990
- ring->state = RING_SUSPEND;
991
- dhd_os_spin_unlock(ring->lock, flags);
992
-
993
- return BCME_OK;
994
-}
995
-
996
-static void
997
-dhd_dbg_ring_deinit(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring)
998
-{
999
- void *buf;
1000
- uint32 ring_sz;
1001
- unsigned long flags;
1002
-
1003
- if (!ring->ring_buf)
1004
- return;
1005
-
1006
- flags = dhd_os_spin_lock(ring->lock);
1007
- ring->id = 0;
1008
- ring->name[0] = 0;
1009
- ring_sz = ring->ring_size;
1010
- ring->ring_size = 0;
1011
- ring->wp = ring->rp = 0;
1012
- buf = ring->ring_buf;
1013
- ring->ring_buf = NULL;
1014
- memset(&ring->stat, 0, sizeof(ring->stat));
1015
- ring->threshold = 0;
1016
- ring->state = RING_STOP;
1017
- dhd_os_spin_unlock(ring->lock, flags);
1018
-
1019
- dhd_os_spin_lock_deinit(dhdp->osh, ring->lock);
1020
-
1021
- MFREE(dhdp->osh, buf, ring_sz);
1022
-}
1137
+#endif /* MACOSX_DHD */
10231138
10241139 /*
10251140 * dhd_dbg_set_event_log_tag : modify the state of an event log tag
....@@ -1053,38 +1168,26 @@
10531168 {
10541169 dhd_dbg_ring_t *ring;
10551170 uint8 set = 1;
1056
- unsigned long lock_flags;
10571171 int i, array_len = 0;
10581172 struct log_level_table *log_level_tbl = NULL;
1173
+
10591174 if (!dhdp || !dhdp->dbg)
10601175 return BCME_BADADDR;
10611176
1177
+ if (!VALID_RING(ring_id)) {
1178
+ DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id));
1179
+ return BCME_RANGE;
1180
+ }
1181
+
10621182 ring = &dhdp->dbg->dbg_rings[ring_id];
1183
+ dhd_dbg_ring_config(ring, log_level, threshold);
10631184
1064
- if (ring->state == RING_STOP)
1065
- return BCME_UNSUPPORTED;
1066
-
1067
- lock_flags = dhd_os_spin_lock(ring->lock);
1068
- if (log_level == 0)
1069
- ring->state = RING_SUSPEND;
1070
- else
1071
- ring->state = RING_ACTIVE;
1072
- ring->log_level = log_level;
1073
-
1074
- ring->threshold = (threshold > ring->threshold) ? ring->ring_size : threshold;
1075
- dhd_os_spin_unlock(ring->lock, lock_flags);
10761185 if (log_level > 0)
10771186 set = TRUE;
10781187
1079
- if (ring->id == FW_EVENT_RING_ID) {
1080
- log_level_tbl = fw_event_level_map;
1081
- array_len = ARRAYSIZE(fw_event_level_map);
1082
- } else if (ring->id == FW_VERBOSE_RING_ID) {
1188
+ if (ring->id == FW_VERBOSE_RING_ID) {
10831189 log_level_tbl = fw_verbose_level_map;
10841190 array_len = ARRAYSIZE(fw_verbose_level_map);
1085
- } else if (ring->id == NAN_EVENT_RING_ID) {
1086
- log_level_tbl = nan_event_level_map;
1087
- array_len = ARRAYSIZE(nan_event_level_map);
10881191 }
10891192
10901193 for (i = 0; i < array_len; i++) {
....@@ -1103,6 +1206,23 @@
11031206 return BCME_OK;
11041207 }
11051208
1209
+int
1210
+__dhd_dbg_get_ring_status(dhd_dbg_ring_t *ring, dhd_dbg_ring_status_t *get_ring_status)
1211
+{
1212
+ dhd_dbg_ring_status_t ring_status;
1213
+ int ret = BCME_OK;
1214
+
1215
+ if (ring == NULL) {
1216
+ return BCME_BADADDR;
1217
+ }
1218
+
1219
+ bzero(&ring_status, sizeof(dhd_dbg_ring_status_t));
1220
+ RING_STAT_TO_STATUS(ring, ring_status);
1221
+ *get_ring_status = ring_status;
1222
+
1223
+ return ret;
1224
+}
1225
+
11061226 /*
11071227 * dhd_dbg_get_ring_status : get the ring status from the coresponding ring buffer
11081228 * Return: An error code or 0 on success.
....@@ -1115,17 +1235,14 @@
11151235 int id = 0;
11161236 dhd_dbg_t *dbg;
11171237 dhd_dbg_ring_t *dbg_ring;
1118
- dhd_dbg_ring_status_t ring_status;
11191238 if (!dhdp || !dhdp->dbg)
11201239 return BCME_BADADDR;
11211240 dbg = dhdp->dbg;
11221241
1123
- memset(&ring_status, 0, sizeof(dhd_dbg_ring_status_t));
11241242 for (id = DEBUG_RING_ID_INVALID + 1; id < DEBUG_RING_ID_MAX; id++) {
11251243 dbg_ring = &dbg->dbg_rings[id];
11261244 if (VALID_RING(dbg_ring->id) && (dbg_ring->id == ring_id)) {
1127
- RING_STAT_TO_STATUS(dbg_ring, ring_status);
1128
- *dbg_ring_status = ring_status;
1245
+ __dhd_dbg_get_ring_status(dbg_ring, dbg_ring_status);
11291246 break;
11301247 }
11311248 }
....@@ -1135,6 +1252,30 @@
11351252 }
11361253 return ret;
11371254 }
1255
+
1256
+#ifdef SHOW_LOGTRACE
1257
+void
1258
+dhd_dbg_read_ring_into_trace_buf(dhd_dbg_ring_t *ring, trace_buf_info_t *trace_buf_info)
1259
+{
1260
+ dhd_dbg_ring_status_t ring_status;
1261
+ uint32 rlen = 0;
1262
+
1263
+ rlen = dhd_dbg_ring_pull_single(ring, trace_buf_info->buf, TRACE_LOG_BUF_MAX_SIZE, TRUE);
1264
+
1265
+ trace_buf_info->size = rlen;
1266
+ trace_buf_info->availability = NEXT_BUF_NOT_AVAIL;
1267
+ if (rlen == 0) {
1268
+ trace_buf_info->availability = BUF_NOT_AVAILABLE;
1269
+ return;
1270
+ }
1271
+
1272
+ __dhd_dbg_get_ring_status(ring, &ring_status);
1273
+
1274
+ if (ring_status.written_bytes != ring_status.read_bytes) {
1275
+ trace_buf_info->availability = NEXT_BUF_AVAIL;
1276
+ }
1277
+}
1278
+#endif /* SHOW_LOGTRACE */
11381279
11391280 /*
11401281 * dhd_dbg_find_ring_id : return ring_id based on ring_name
....@@ -1154,7 +1295,7 @@
11541295 dbg = dhdp->dbg;
11551296 for (id = DEBUG_RING_ID_INVALID + 1; id < DEBUG_RING_ID_MAX; id++) {
11561297 ring = &dbg->dbg_rings[id];
1157
- if (!strncmp(ring->name, ring_name, sizeof(ring->name) - 1))
1298
+ if (!strncmp((char *)ring->name, ring_name, sizeof(ring->name) - 1))
11581299 break;
11591300 }
11601301 return id;
....@@ -1183,7 +1324,7 @@
11831324 int ring_id;
11841325 dhd_dbg_t *dbg;
11851326 dhd_dbg_ring_t *dbg_ring;
1186
- if (!dhdp || !dhdp->dbg)
1327
+ if (!dhdp)
11871328 return BCME_BADARG;
11881329 dbg = dhdp->dbg;
11891330
....@@ -1191,13 +1332,7 @@
11911332 dbg_ring = &dbg->dbg_rings[ring_id];
11921333 if (!start) {
11931334 if (VALID_RING(dbg_ring->id)) {
1194
- /* Initialize the information for the ring */
1195
- dbg_ring->state = RING_SUSPEND;
1196
- dbg_ring->log_level = 0;
1197
- dbg_ring->rp = dbg_ring->wp = 0;
1198
- dbg_ring->threshold = 0;
1199
- memset(&dbg_ring->stat, 0, sizeof(struct ring_statistics));
1200
- memset(dbg_ring->ring_buf, 0, dbg_ring->ring_size);
1335
+ dhd_dbg_ring_start(dbg_ring);
12011336 }
12021337 }
12031338 }
....@@ -1224,6 +1359,784 @@
12241359 }
12251360 return ret;
12261361 }
1362
+
1363
+#if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING)
1364
+uint32
1365
+__dhd_dbg_pkt_hash(uintptr_t pkt, uint32 pktid)
1366
+{
1367
+ uint32 __pkt;
1368
+ uint32 __pktid;
1369
+
1370
+ __pkt = ((int)pkt) >= 0 ? (2 * pkt) : (-2 * pkt - 1);
1371
+ __pktid = ((int)pktid) >= 0 ? (2 * pktid) : (-2 * pktid - 1);
1372
+
1373
+ return (__pkt >= __pktid ? (__pkt * __pkt + __pkt + __pktid) :
1374
+ (__pkt + __pktid * __pktid));
1375
+}
1376
+
1377
+#define __TIMESPEC_TO_US(ts) \
1378
+ (((uint32)(ts).tv_sec * USEC_PER_SEC) + ((ts).tv_nsec / NSEC_PER_USEC))
1379
+
1380
+uint32
1381
+__dhd_dbg_driver_ts_usec(void)
1382
+{
1383
+ struct timespec64 ts;
1384
+
1385
+ ts = ktime_to_timespec64(ktime_get_boottime());
1386
+ return ((uint32)(__TIMESPEC_TO_US(ts)));
1387
+}
1388
+
1389
+wifi_tx_packet_fate
1390
+__dhd_dbg_map_tx_status_to_pkt_fate(uint16 status)
1391
+{
1392
+ wifi_tx_packet_fate pkt_fate;
1393
+
1394
+ switch (status) {
1395
+ case WLFC_CTL_PKTFLAG_DISCARD:
1396
+ pkt_fate = TX_PKT_FATE_ACKED;
1397
+ break;
1398
+ case WLFC_CTL_PKTFLAG_D11SUPPRESS:
1399
+ /* intensional fall through */
1400
+ case WLFC_CTL_PKTFLAG_WLSUPPRESS:
1401
+ pkt_fate = TX_PKT_FATE_FW_QUEUED;
1402
+ break;
1403
+ case WLFC_CTL_PKTFLAG_TOSSED_BYWLC:
1404
+ pkt_fate = TX_PKT_FATE_FW_DROP_INVALID;
1405
+ break;
1406
+ case WLFC_CTL_PKTFLAG_DISCARD_NOACK:
1407
+ pkt_fate = TX_PKT_FATE_SENT;
1408
+ break;
1409
+ case WLFC_CTL_PKTFLAG_EXPIRED:
1410
+ pkt_fate = TX_PKT_FATE_FW_DROP_EXPTIME;
1411
+ break;
1412
+ case WLFC_CTL_PKTFLAG_MKTFREE:
1413
+ pkt_fate = TX_PKT_FATE_FW_PKT_FREE;
1414
+ break;
1415
+ default:
1416
+ pkt_fate = TX_PKT_FATE_FW_DROP_OTHER;
1417
+ break;
1418
+ }
1419
+
1420
+ return pkt_fate;
1421
+}
1422
+#endif /* DBG_PKT_MON || DHD_PKT_LOGGING */
1423
+
1424
+#ifdef DBG_PKT_MON
1425
+static int
1426
+__dhd_dbg_free_tx_pkts(dhd_pub_t *dhdp, dhd_dbg_tx_info_t *tx_pkts,
1427
+ uint16 pkt_count)
1428
+{
1429
+ uint16 count;
1430
+
1431
+ DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
1432
+ count = 0;
1433
+ while ((count < pkt_count) && tx_pkts) {
1434
+ if (tx_pkts->info.pkt) {
1435
+ PKTFREE(dhdp->osh, tx_pkts->info.pkt, TRUE);
1436
+ }
1437
+ tx_pkts++;
1438
+ count++;
1439
+ }
1440
+
1441
+ return BCME_OK;
1442
+}
1443
+
1444
+static int
1445
+__dhd_dbg_free_rx_pkts(dhd_pub_t *dhdp, dhd_dbg_rx_info_t *rx_pkts,
1446
+ uint16 pkt_count)
1447
+{
1448
+ uint16 count;
1449
+
1450
+ DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
1451
+ count = 0;
1452
+ while ((count < pkt_count) && rx_pkts) {
1453
+ if (rx_pkts->info.pkt) {
1454
+ PKTFREE(dhdp->osh, rx_pkts->info.pkt, TRUE);
1455
+ }
1456
+ rx_pkts++;
1457
+ count++;
1458
+ }
1459
+
1460
+ return BCME_OK;
1461
+}
1462
+
1463
+void
1464
+__dhd_dbg_dump_pkt_info(dhd_pub_t *dhdp, dhd_dbg_pkt_info_t *info)
1465
+{
1466
+ if (DHD_PKT_MON_DUMP_ON()) {
1467
+ DHD_PKT_MON(("payload type = %d\n", info->payload_type));
1468
+ DHD_PKT_MON(("driver ts = %u\n", info->driver_ts));
1469
+ DHD_PKT_MON(("firmware ts = %u\n", info->firmware_ts));
1470
+ DHD_PKT_MON(("packet hash = %u\n", info->pkt_hash));
1471
+ DHD_PKT_MON(("packet length = %zu\n", info->pkt_len));
1472
+ DHD_PKT_MON(("packet address = %p\n", info->pkt));
1473
+ DHD_PKT_MON(("packet data = \n"));
1474
+ if (DHD_PKT_MON_ON()) {
1475
+ prhex(NULL, PKTDATA(dhdp->osh, info->pkt), info->pkt_len);
1476
+ }
1477
+ }
1478
+}
1479
+
1480
+void
1481
+__dhd_dbg_dump_tx_pkt_info(dhd_pub_t *dhdp, dhd_dbg_tx_info_t *tx_pkt,
1482
+ uint16 count)
1483
+{
1484
+ if (DHD_PKT_MON_DUMP_ON()) {
1485
+ DHD_PKT_MON(("\nTX (count: %d)\n", ++count));
1486
+ DHD_PKT_MON(("packet fate = %d\n", tx_pkt->fate));
1487
+ __dhd_dbg_dump_pkt_info(dhdp, &tx_pkt->info);
1488
+ }
1489
+}
1490
+
1491
+void
1492
+__dhd_dbg_dump_rx_pkt_info(dhd_pub_t *dhdp, dhd_dbg_rx_info_t *rx_pkt,
1493
+ uint16 count)
1494
+{
1495
+ if (DHD_PKT_MON_DUMP_ON()) {
1496
+ DHD_PKT_MON(("\nRX (count: %d)\n", ++count));
1497
+ DHD_PKT_MON(("packet fate = %d\n", rx_pkt->fate));
1498
+ __dhd_dbg_dump_pkt_info(dhdp, &rx_pkt->info);
1499
+ }
1500
+}
1501
+
1502
+int
1503
+dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp,
1504
+ dbg_mon_tx_pkts_t tx_pkt_mon,
1505
+ dbg_mon_tx_status_t tx_status_mon,
1506
+ dbg_mon_rx_pkts_t rx_pkt_mon)
1507
+{
1508
+
1509
+ dhd_dbg_tx_report_t *tx_report = NULL;
1510
+ dhd_dbg_rx_report_t *rx_report = NULL;
1511
+ dhd_dbg_tx_info_t *tx_pkts = NULL;
1512
+ dhd_dbg_rx_info_t *rx_pkts = NULL;
1513
+ dhd_dbg_pkt_mon_state_t tx_pkt_state;
1514
+ dhd_dbg_pkt_mon_state_t tx_status_state;
1515
+ dhd_dbg_pkt_mon_state_t rx_pkt_state;
1516
+ uint32 alloc_len;
1517
+ int ret = BCME_OK;
1518
+ unsigned long flags;
1519
+
1520
+ DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
1521
+ if (!dhdp || !dhdp->dbg) {
1522
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1523
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
1524
+ return -EINVAL;
1525
+ }
1526
+
1527
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1528
+ tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1529
+ tx_status_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1530
+ rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1531
+
1532
+ if (PKT_MON_ATTACHED(tx_pkt_state) || PKT_MON_ATTACHED(tx_status_state) ||
1533
+ PKT_MON_ATTACHED(rx_pkt_state)) {
1534
+ DHD_PKT_MON(("%s(): packet monitor is already attached, "
1535
+ "tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
1536
+ __FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
1537
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1538
+ /* return success as the intention was to initialize packet monitor */
1539
+ return BCME_OK;
1540
+ }
1541
+
1542
+ /* allocate and initialize tx packet monitoring */
1543
+ alloc_len = sizeof(*tx_report);
1544
+ tx_report = (dhd_dbg_tx_report_t *)MALLOCZ(dhdp->osh, alloc_len);
1545
+ if (unlikely(!tx_report)) {
1546
+ DHD_ERROR(("%s(): could not allocate memory for - "
1547
+ "dhd_dbg_tx_report_t\n", __FUNCTION__));
1548
+ ret = -ENOMEM;
1549
+ goto fail;
1550
+ }
1551
+
1552
+ alloc_len = (sizeof(*tx_pkts) * MAX_FATE_LOG_LEN);
1553
+ tx_pkts = (dhd_dbg_tx_info_t *)MALLOCZ(dhdp->osh, alloc_len);
1554
+ if (unlikely(!tx_pkts)) {
1555
+ DHD_ERROR(("%s(): could not allocate memory for - "
1556
+ "dhd_dbg_tx_info_t\n", __FUNCTION__));
1557
+ ret = -ENOMEM;
1558
+ goto fail;
1559
+ }
1560
+ dhdp->dbg->pkt_mon.tx_report = tx_report;
1561
+ dhdp->dbg->pkt_mon.tx_report->tx_pkts = tx_pkts;
1562
+ dhdp->dbg->pkt_mon.tx_pkt_mon = tx_pkt_mon;
1563
+ dhdp->dbg->pkt_mon.tx_status_mon = tx_status_mon;
1564
+ dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_ATTACHED;
1565
+ dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_ATTACHED;
1566
+
1567
+ /* allocate and initialze rx packet monitoring */
1568
+ alloc_len = sizeof(*rx_report);
1569
+ rx_report = (dhd_dbg_rx_report_t *)MALLOCZ(dhdp->osh, alloc_len);
1570
+ if (unlikely(!rx_report)) {
1571
+ DHD_ERROR(("%s(): could not allocate memory for - "
1572
+ "dhd_dbg_rx_report_t\n", __FUNCTION__));
1573
+ ret = -ENOMEM;
1574
+ goto fail;
1575
+ }
1576
+
1577
+ alloc_len = (sizeof(*rx_pkts) * MAX_FATE_LOG_LEN);
1578
+ rx_pkts = (dhd_dbg_rx_info_t *)MALLOCZ(dhdp->osh, alloc_len);
1579
+ if (unlikely(!rx_pkts)) {
1580
+ DHD_ERROR(("%s(): could not allocate memory for - "
1581
+ "dhd_dbg_rx_info_t\n", __FUNCTION__));
1582
+ ret = -ENOMEM;
1583
+ goto fail;
1584
+ }
1585
+ dhdp->dbg->pkt_mon.rx_report = rx_report;
1586
+ dhdp->dbg->pkt_mon.rx_report->rx_pkts = rx_pkts;
1587
+ dhdp->dbg->pkt_mon.rx_pkt_mon = rx_pkt_mon;
1588
+ dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_ATTACHED;
1589
+
1590
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1591
+ DHD_PKT_MON(("%s(): packet monitor attach succeeded\n", __FUNCTION__));
1592
+ return ret;
1593
+
1594
+fail:
1595
+ /* tx packet monitoring */
1596
+ if (tx_pkts) {
1597
+ alloc_len = (sizeof(*tx_pkts) * MAX_FATE_LOG_LEN);
1598
+ MFREE(dhdp->osh, tx_pkts, alloc_len);
1599
+ }
1600
+ if (tx_report) {
1601
+ alloc_len = sizeof(*tx_report);
1602
+ MFREE(dhdp->osh, tx_report, alloc_len);
1603
+ }
1604
+ dhdp->dbg->pkt_mon.tx_report = NULL;
1605
+ dhdp->dbg->pkt_mon.tx_report->tx_pkts = NULL;
1606
+ dhdp->dbg->pkt_mon.tx_pkt_mon = NULL;
1607
+ dhdp->dbg->pkt_mon.tx_status_mon = NULL;
1608
+ dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_DETACHED;
1609
+ dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_DETACHED;
1610
+
1611
+ /* rx packet monitoring */
1612
+ if (rx_pkts) {
1613
+ alloc_len = (sizeof(*rx_pkts) * MAX_FATE_LOG_LEN);
1614
+ MFREE(dhdp->osh, rx_pkts, alloc_len);
1615
+ }
1616
+ if (rx_report) {
1617
+ alloc_len = sizeof(*rx_report);
1618
+ MFREE(dhdp->osh, rx_report, alloc_len);
1619
+ }
1620
+ dhdp->dbg->pkt_mon.rx_report = NULL;
1621
+ dhdp->dbg->pkt_mon.rx_report->rx_pkts = NULL;
1622
+ dhdp->dbg->pkt_mon.rx_pkt_mon = NULL;
1623
+ dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_DETACHED;
1624
+
1625
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1626
+ DHD_ERROR(("%s(): packet monitor attach failed\n", __FUNCTION__));
1627
+ return ret;
1628
+}
1629
+
1630
+int
1631
+dhd_dbg_start_pkt_monitor(dhd_pub_t *dhdp)
1632
+{
1633
+ dhd_dbg_tx_report_t *tx_report;
1634
+ dhd_dbg_rx_report_t *rx_report;
1635
+ dhd_dbg_pkt_mon_state_t tx_pkt_state;
1636
+ dhd_dbg_pkt_mon_state_t tx_status_state;
1637
+ dhd_dbg_pkt_mon_state_t rx_pkt_state;
1638
+ unsigned long flags;
1639
+
1640
+ DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
1641
+ if (!dhdp || !dhdp->dbg) {
1642
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1643
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
1644
+ return -EINVAL;
1645
+ }
1646
+
1647
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1648
+ tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1649
+ tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1650
+ rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1651
+
1652
+ if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
1653
+ PKT_MON_DETACHED(rx_pkt_state)) {
1654
+ DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
1655
+ "tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
1656
+ __FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
1657
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1658
+ return -EINVAL;
1659
+ }
1660
+
1661
+ dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STARTING;
1662
+ dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STARTING;
1663
+ dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STARTING;
1664
+
1665
+ tx_report = dhdp->dbg->pkt_mon.tx_report;
1666
+ rx_report = dhdp->dbg->pkt_mon.rx_report;
1667
+ if (!tx_report || !rx_report) {
1668
+ DHD_PKT_MON(("%s(): tx_report=%p, rx_report=%p\n",
1669
+ __FUNCTION__, tx_report, rx_report));
1670
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1671
+ return -EINVAL;
1672
+ }
1673
+
1674
+ tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1675
+ tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1676
+ rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1677
+
1678
+ /* Safe to free packets as state pkt_state is STARTING */
1679
+ __dhd_dbg_free_tx_pkts(dhdp, tx_report->tx_pkts, tx_report->pkt_pos);
1680
+
1681
+ __dhd_dbg_free_rx_pkts(dhdp, rx_report->rx_pkts, rx_report->pkt_pos);
1682
+
1683
+ /* reset array postion */
1684
+ tx_report->pkt_pos = 0;
1685
+ tx_report->status_pos = 0;
1686
+ dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STARTED;
1687
+ dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STARTED;
1688
+
1689
+ rx_report->pkt_pos = 0;
1690
+ dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STARTED;
1691
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1692
+
1693
+ DHD_PKT_MON(("%s(): packet monitor started\n", __FUNCTION__));
1694
+ return BCME_OK;
1695
+}
1696
+
1697
+int
1698
+dhd_dbg_monitor_tx_pkts(dhd_pub_t *dhdp, void *pkt, uint32 pktid)
1699
+{
1700
+ dhd_dbg_tx_report_t *tx_report;
1701
+ dhd_dbg_tx_info_t *tx_pkts;
1702
+ dhd_dbg_pkt_mon_state_t tx_pkt_state;
1703
+ uint32 pkt_hash, driver_ts;
1704
+ uint16 pkt_pos;
1705
+ unsigned long flags;
1706
+
1707
+ if (!dhdp || !dhdp->dbg) {
1708
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1709
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
1710
+ return -EINVAL;
1711
+ }
1712
+
1713
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1714
+ tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1715
+ if (PKT_MON_STARTED(tx_pkt_state)) {
1716
+ tx_report = dhdp->dbg->pkt_mon.tx_report;
1717
+ pkt_pos = tx_report->pkt_pos;
1718
+
1719
+ if (!PKT_MON_PKT_FULL(pkt_pos)) {
1720
+ tx_pkts = tx_report->tx_pkts;
1721
+ pkt_hash = __dhd_dbg_pkt_hash((uintptr_t)pkt, pktid);
1722
+ driver_ts = __dhd_dbg_driver_ts_usec();
1723
+
1724
+ tx_pkts[pkt_pos].info.pkt = PKTDUP(dhdp->osh, pkt);
1725
+ tx_pkts[pkt_pos].info.pkt_len = PKTLEN(dhdp->osh, pkt);
1726
+ tx_pkts[pkt_pos].info.pkt_hash = pkt_hash;
1727
+ tx_pkts[pkt_pos].info.driver_ts = driver_ts;
1728
+ tx_pkts[pkt_pos].info.firmware_ts = 0U;
1729
+ tx_pkts[pkt_pos].info.payload_type = FRAME_TYPE_ETHERNET_II;
1730
+ tx_pkts[pkt_pos].fate = TX_PKT_FATE_DRV_QUEUED;
1731
+
1732
+ tx_report->pkt_pos++;
1733
+ } else {
1734
+ dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STOPPED;
1735
+ DHD_PKT_MON(("%s(): tx pkt logging stopped, reached "
1736
+ "max limit\n", __FUNCTION__));
1737
+ }
1738
+ }
1739
+
1740
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1741
+ return BCME_OK;
1742
+}
1743
+
1744
+int
1745
+dhd_dbg_monitor_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid,
1746
+ uint16 status)
1747
+{
1748
+ dhd_dbg_tx_report_t *tx_report;
1749
+ dhd_dbg_tx_info_t *tx_pkt;
1750
+ dhd_dbg_pkt_mon_state_t tx_status_state;
1751
+ wifi_tx_packet_fate pkt_fate;
1752
+ uint32 pkt_hash, temp_hash;
1753
+ uint16 pkt_pos, status_pos;
1754
+ int16 count;
1755
+ bool found = FALSE;
1756
+ unsigned long flags;
1757
+
1758
+ if (!dhdp || !dhdp->dbg) {
1759
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1760
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
1761
+ return -EINVAL;
1762
+ }
1763
+
1764
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1765
+ tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1766
+ if (PKT_MON_STARTED(tx_status_state)) {
1767
+ tx_report = dhdp->dbg->pkt_mon.tx_report;
1768
+ pkt_pos = tx_report->pkt_pos;
1769
+ status_pos = tx_report->status_pos;
1770
+
1771
+ if (!PKT_MON_STATUS_FULL(pkt_pos, status_pos)) {
1772
+ pkt_hash = __dhd_dbg_pkt_hash((uintptr_t)pkt, pktid);
1773
+ pkt_fate = __dhd_dbg_map_tx_status_to_pkt_fate(status);
1774
+
1775
+ /* best bet (in-order tx completion) */
1776
+ count = status_pos;
1777
+ tx_pkt = (((dhd_dbg_tx_info_t *)tx_report->tx_pkts) + status_pos);
1778
+ while ((count < pkt_pos) && tx_pkt) {
1779
+ temp_hash = tx_pkt->info.pkt_hash;
1780
+ if (temp_hash == pkt_hash) {
1781
+ tx_pkt->fate = pkt_fate;
1782
+ tx_report->status_pos++;
1783
+ found = TRUE;
1784
+ break;
1785
+ }
1786
+ tx_pkt++;
1787
+ count++;
1788
+ }
1789
+
1790
+ /* search until beginning (handles out-of-order completion) */
1791
+ if (!found) {
1792
+ count = status_pos - 1;
1793
+ tx_pkt = (((dhd_dbg_tx_info_t *)tx_report->tx_pkts) + count);
1794
+ while ((count >= 0) && tx_pkt) {
1795
+ temp_hash = tx_pkt->info.pkt_hash;
1796
+ if (temp_hash == pkt_hash) {
1797
+ tx_pkt->fate = pkt_fate;
1798
+ tx_report->status_pos++;
1799
+ found = TRUE;
1800
+ break;
1801
+ }
1802
+ tx_pkt--;
1803
+ count--;
1804
+ }
1805
+
1806
+ if (!found) {
1807
+ /* still couldn't match tx_status */
1808
+ DHD_ERROR(("%s(): couldn't match tx_status, pkt_pos=%u, "
1809
+ "status_pos=%u, pkt_fate=%u\n", __FUNCTION__,
1810
+ pkt_pos, status_pos, pkt_fate));
1811
+ }
1812
+ }
1813
+ } else {
1814
+ dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STOPPED;
1815
+ DHD_PKT_MON(("%s(): tx_status logging stopped, reached "
1816
+ "max limit\n", __FUNCTION__));
1817
+ }
1818
+ }
1819
+
1820
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1821
+ return BCME_OK;
1822
+}
1823
+
1824
+int
1825
+dhd_dbg_monitor_rx_pkts(dhd_pub_t *dhdp, void *pkt)
1826
+{
1827
+ dhd_dbg_rx_report_t *rx_report;
1828
+ dhd_dbg_rx_info_t *rx_pkts;
1829
+ dhd_dbg_pkt_mon_state_t rx_pkt_state;
1830
+ uint32 driver_ts;
1831
+ uint16 pkt_pos;
1832
+ unsigned long flags;
1833
+
1834
+ if (!dhdp || !dhdp->dbg) {
1835
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1836
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
1837
+ return -EINVAL;
1838
+ }
1839
+
1840
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1841
+ rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1842
+ if (PKT_MON_STARTED(rx_pkt_state)) {
1843
+ rx_report = dhdp->dbg->pkt_mon.rx_report;
1844
+ pkt_pos = rx_report->pkt_pos;
1845
+
1846
+ if (!PKT_MON_PKT_FULL(pkt_pos)) {
1847
+ rx_pkts = rx_report->rx_pkts;
1848
+ driver_ts = __dhd_dbg_driver_ts_usec();
1849
+
1850
+ rx_pkts[pkt_pos].info.pkt = PKTDUP(dhdp->osh, pkt);
1851
+ rx_pkts[pkt_pos].info.pkt_len = PKTLEN(dhdp->osh, pkt);
1852
+ rx_pkts[pkt_pos].info.pkt_hash = 0U;
1853
+ rx_pkts[pkt_pos].info.driver_ts = driver_ts;
1854
+ rx_pkts[pkt_pos].info.firmware_ts = 0U;
1855
+ rx_pkts[pkt_pos].info.payload_type = FRAME_TYPE_ETHERNET_II;
1856
+ rx_pkts[pkt_pos].fate = RX_PKT_FATE_SUCCESS;
1857
+
1858
+ rx_report->pkt_pos++;
1859
+ } else {
1860
+ dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STOPPED;
1861
+ DHD_PKT_MON(("%s(): rx pkt logging stopped, reached "
1862
+ "max limit\n", __FUNCTION__));
1863
+ }
1864
+ }
1865
+
1866
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1867
+ return BCME_OK;
1868
+}
1869
+
1870
+int
1871
+dhd_dbg_stop_pkt_monitor(dhd_pub_t *dhdp)
1872
+{
1873
+ dhd_dbg_pkt_mon_state_t tx_pkt_state;
1874
+ dhd_dbg_pkt_mon_state_t tx_status_state;
1875
+ dhd_dbg_pkt_mon_state_t rx_pkt_state;
1876
+ unsigned long flags;
1877
+
1878
+ DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
1879
+ if (!dhdp || !dhdp->dbg) {
1880
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1881
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
1882
+ return -EINVAL;
1883
+ }
1884
+
1885
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1886
+ tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1887
+ tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1888
+ rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
1889
+
1890
+ if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
1891
+ PKT_MON_DETACHED(rx_pkt_state)) {
1892
+ DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
1893
+ "tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
1894
+ __FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
1895
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1896
+ return -EINVAL;
1897
+ }
1898
+ dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_STOPPED;
1899
+ dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_STOPPED;
1900
+ dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_STOPPED;
1901
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1902
+
1903
+ DHD_PKT_MON(("%s(): packet monitor stopped\n", __FUNCTION__));
1904
+ return BCME_OK;
1905
+}
1906
+
1907
+#define __COPY_TO_USER(to, from, n) \
1908
+ do { \
1909
+ int __ret; \
1910
+ __ret = copy_to_user((void __user *)(to), (void *)(from), \
1911
+ (unsigned long)(n)); \
1912
+ if (unlikely(__ret)) { \
1913
+ DHD_ERROR(("%s():%d: copy_to_user failed, ret=%d\n", \
1914
+ __FUNCTION__, __LINE__, __ret)); \
1915
+ return __ret; \
1916
+ } \
1917
+ } while (0);
1918
+
1919
+int
1920
+dhd_dbg_monitor_get_tx_pkts(dhd_pub_t *dhdp, void __user *user_buf,
1921
+ uint16 req_count, uint16 *resp_count)
1922
+{
1923
+ dhd_dbg_tx_report_t *tx_report;
1924
+ dhd_dbg_tx_info_t *tx_pkt;
1925
+ wifi_tx_report_t *ptr;
1926
+ compat_wifi_tx_report_t *cptr;
1927
+ dhd_dbg_pkt_mon_state_t tx_pkt_state;
1928
+ dhd_dbg_pkt_mon_state_t tx_status_state;
1929
+ uint16 pkt_count, count;
1930
+ unsigned long flags;
1931
+
1932
+ DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
1933
+ BCM_REFERENCE(ptr);
1934
+ BCM_REFERENCE(cptr);
1935
+
1936
+ if (!dhdp || !dhdp->dbg) {
1937
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
1938
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
1939
+ return -EINVAL;
1940
+ }
1941
+
1942
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
1943
+ tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
1944
+ tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
1945
+ if (PKT_MON_NOT_OPERATIONAL(tx_pkt_state) ||
1946
+ PKT_MON_NOT_OPERATIONAL(tx_status_state)) {
1947
+ DHD_PKT_MON(("%s(): packet monitor is not yet enabled, "
1948
+ "tx_pkt_state=%d, tx_status_state=%d\n", __FUNCTION__,
1949
+ tx_pkt_state, tx_status_state));
1950
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1951
+ return -EINVAL;
1952
+ }
1953
+
1954
+ count = 0;
1955
+ tx_report = dhdp->dbg->pkt_mon.tx_report;
1956
+ tx_pkt = tx_report->tx_pkts;
1957
+ pkt_count = MIN(req_count, tx_report->status_pos);
1958
+
1959
+ {
1960
+ ptr = (wifi_tx_report_t *)user_buf;
1961
+ while ((count < pkt_count) && tx_pkt && ptr) {
1962
+ __dhd_dbg_dump_tx_pkt_info(dhdp, tx_pkt, count);
1963
+ __COPY_TO_USER(&ptr->fate, &tx_pkt->fate, sizeof(tx_pkt->fate));
1964
+ __COPY_TO_USER(&ptr->frame_inf.payload_type,
1965
+ &tx_pkt->info.payload_type,
1966
+ OFFSETOF(dhd_dbg_pkt_info_t, pkt_hash));
1967
+ __COPY_TO_USER(ptr->frame_inf.frame_content.ethernet_ii,
1968
+ PKTDATA(dhdp->osh, tx_pkt->info.pkt), tx_pkt->info.pkt_len);
1969
+
1970
+ ptr++;
1971
+ tx_pkt++;
1972
+ count++;
1973
+ }
1974
+ }
1975
+ *resp_count = pkt_count;
1976
+
1977
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
1978
+ if (!pkt_count) {
1979
+ DHD_ERROR(("%s(): no tx_status in tx completion messages, "
1980
+ "make sure that 'd11status' is enabled in firmware, "
1981
+ "status_pos=%u", __FUNCTION__, pkt_count));
1982
+ }
1983
+
1984
+ return BCME_OK;
1985
+}
1986
+
1987
+int
1988
+dhd_dbg_monitor_get_rx_pkts(dhd_pub_t *dhdp, void __user *user_buf,
1989
+ uint16 req_count, uint16 *resp_count)
1990
+{
1991
+ dhd_dbg_rx_report_t *rx_report;
1992
+ dhd_dbg_rx_info_t *rx_pkt;
1993
+ wifi_rx_report_t *ptr;
1994
+ compat_wifi_rx_report_t *cptr;
1995
+ dhd_dbg_pkt_mon_state_t rx_pkt_state;
1996
+ uint16 pkt_count, count;
1997
+ unsigned long flags;
1998
+
1999
+ DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
2000
+ BCM_REFERENCE(ptr);
2001
+ BCM_REFERENCE(cptr);
2002
+
2003
+ if (!dhdp || !dhdp->dbg) {
2004
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
2005
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
2006
+ return -EINVAL;
2007
+ }
2008
+
2009
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
2010
+ rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
2011
+ if (PKT_MON_NOT_OPERATIONAL(rx_pkt_state)) {
2012
+ DHD_PKT_MON(("%s(): packet fetch is not allowed , "
2013
+ "rx_pkt_state=%d\n", __FUNCTION__, rx_pkt_state));
2014
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2015
+ return -EINVAL;
2016
+ }
2017
+
2018
+ count = 0;
2019
+ rx_report = dhdp->dbg->pkt_mon.rx_report;
2020
+ rx_pkt = rx_report->rx_pkts;
2021
+ pkt_count = MIN(req_count, rx_report->pkt_pos);
2022
+
2023
+ {
2024
+ ptr = (wifi_rx_report_t *)user_buf;
2025
+ while ((count < pkt_count) && rx_pkt && ptr) {
2026
+ __dhd_dbg_dump_rx_pkt_info(dhdp, rx_pkt, count);
2027
+
2028
+ __COPY_TO_USER(&ptr->fate, &rx_pkt->fate, sizeof(rx_pkt->fate));
2029
+ __COPY_TO_USER(&ptr->frame_inf.payload_type,
2030
+ &rx_pkt->info.payload_type,
2031
+ OFFSETOF(dhd_dbg_pkt_info_t, pkt_hash));
2032
+ __COPY_TO_USER(ptr->frame_inf.frame_content.ethernet_ii,
2033
+ PKTDATA(dhdp->osh, rx_pkt->info.pkt), rx_pkt->info.pkt_len);
2034
+
2035
+ ptr++;
2036
+ rx_pkt++;
2037
+ count++;
2038
+ }
2039
+ }
2040
+
2041
+ *resp_count = pkt_count;
2042
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2043
+
2044
+ return BCME_OK;
2045
+}
2046
+
2047
+int
2048
+dhd_dbg_detach_pkt_monitor(dhd_pub_t *dhdp)
2049
+{
2050
+ dhd_dbg_tx_report_t *tx_report;
2051
+ dhd_dbg_rx_report_t *rx_report;
2052
+ dhd_dbg_pkt_mon_state_t tx_pkt_state;
2053
+ dhd_dbg_pkt_mon_state_t tx_status_state;
2054
+ dhd_dbg_pkt_mon_state_t rx_pkt_state;
2055
+ unsigned long flags;
2056
+
2057
+ DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__));
2058
+ if (!dhdp || !dhdp->dbg) {
2059
+ DHD_PKT_MON(("%s(): dhdp=%p, dhdp->dbg=%p\n", __FUNCTION__,
2060
+ dhdp, (dhdp ? dhdp->dbg : NULL)));
2061
+ return -EINVAL;
2062
+ }
2063
+
2064
+ DHD_PKT_MON_LOCK(dhdp->dbg->pkt_mon_lock, flags);
2065
+ tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state;
2066
+ tx_status_state = dhdp->dbg->pkt_mon.tx_status_state;
2067
+ rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state;
2068
+
2069
+ if (PKT_MON_DETACHED(tx_pkt_state) || PKT_MON_DETACHED(tx_status_state) ||
2070
+ PKT_MON_DETACHED(rx_pkt_state)) {
2071
+ DHD_PKT_MON(("%s(): packet monitor is already detached, "
2072
+ "tx_pkt_state=%d, tx_status_state=%d, rx_pkt_state=%d\n",
2073
+ __FUNCTION__, tx_pkt_state, tx_status_state, rx_pkt_state));
2074
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2075
+ return -EINVAL;
2076
+ }
2077
+
2078
+ tx_report = dhdp->dbg->pkt_mon.tx_report;
2079
+ rx_report = dhdp->dbg->pkt_mon.rx_report;
2080
+
2081
+ /* free and de-initalize tx packet monitoring */
2082
+ dhdp->dbg->pkt_mon.tx_pkt_state = PKT_MON_DETACHED;
2083
+ dhdp->dbg->pkt_mon.tx_status_state = PKT_MON_DETACHED;
2084
+ if (tx_report) {
2085
+ if (tx_report->tx_pkts) {
2086
+ __dhd_dbg_free_tx_pkts(dhdp, tx_report->tx_pkts,
2087
+ tx_report->pkt_pos);
2088
+ MFREE(dhdp->osh, tx_report->tx_pkts,
2089
+ (sizeof(*tx_report->tx_pkts) * MAX_FATE_LOG_LEN));
2090
+ dhdp->dbg->pkt_mon.tx_report->tx_pkts = NULL;
2091
+ }
2092
+ MFREE(dhdp->osh, tx_report, sizeof(*tx_report));
2093
+ dhdp->dbg->pkt_mon.tx_report = NULL;
2094
+ }
2095
+ dhdp->dbg->pkt_mon.tx_pkt_mon = NULL;
2096
+ dhdp->dbg->pkt_mon.tx_status_mon = NULL;
2097
+
2098
+ /* free and de-initalize rx packet monitoring */
2099
+ dhdp->dbg->pkt_mon.rx_pkt_state = PKT_MON_DETACHED;
2100
+ if (rx_report) {
2101
+ if (rx_report->rx_pkts) {
2102
+ __dhd_dbg_free_rx_pkts(dhdp, rx_report->rx_pkts,
2103
+ rx_report->pkt_pos);
2104
+ MFREE(dhdp->osh, rx_report->rx_pkts,
2105
+ (sizeof(*rx_report->rx_pkts) * MAX_FATE_LOG_LEN));
2106
+ dhdp->dbg->pkt_mon.rx_report->rx_pkts = NULL;
2107
+ }
2108
+ MFREE(dhdp->osh, rx_report, sizeof(*rx_report));
2109
+ dhdp->dbg->pkt_mon.rx_report = NULL;
2110
+ }
2111
+ dhdp->dbg->pkt_mon.rx_pkt_mon = NULL;
2112
+
2113
+ DHD_PKT_MON_UNLOCK(dhdp->dbg->pkt_mon_lock, flags);
2114
+ DHD_PKT_MON(("%s(): packet monitor detach succeeded\n", __FUNCTION__));
2115
+ return BCME_OK;
2116
+}
2117
+#endif /* DBG_PKT_MON */
2118
+
2119
+#if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING)
2120
+bool
2121
+dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid,
2122
+ uint16 status)
2123
+{
2124
+ bool pkt_fate = TRUE;
2125
+ if (dhdp->d11_tx_status) {
2126
+ pkt_fate = (status == WLFC_CTL_PKTFLAG_DISCARD) ? TRUE : FALSE;
2127
+ DHD_DBG_PKT_MON_TX_STATUS(dhdp, pkt, pktid, status);
2128
+ }
2129
+ return pkt_fate;
2130
+}
2131
+#else /* DBG_PKT_MON || DHD_PKT_LOGGING */
2132
+bool
2133
+dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt,
2134
+ uint32 pktid, uint16 status)
2135
+{
2136
+ return TRUE;
2137
+}
2138
+#endif /* DBG_PKT_MON || DHD_PKT_LOGGING */
2139
+
12272140 /*
12282141 * dhd_dbg_attach: initialziation of dhd dbugability module
12292142 *
....@@ -1233,30 +2146,28 @@
12332146 dhd_dbg_attach(dhd_pub_t *dhdp, dbg_pullreq_t os_pullreq,
12342147 dbg_urgent_noti_t os_urgent_notifier, void *os_priv)
12352148 {
1236
- dhd_dbg_t *dbg;
1237
- int ret, ring_id;
2149
+ dhd_dbg_t *dbg = NULL;
2150
+ dhd_dbg_ring_t *ring = NULL;
2151
+ int ret = BCME_ERROR, ring_id = 0;
2152
+ void *buf = NULL;
12382153
12392154 dbg = MALLOCZ(dhdp->osh, sizeof(dhd_dbg_t));
12402155 if (!dbg)
12412156 return BCME_NOMEM;
12422157
2158
+ buf = MALLOCZ(dhdp->osh, FW_VERBOSE_RING_SIZE);
2159
+ if (!buf)
2160
+ goto error;
12432161 ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[FW_VERBOSE_RING_ID], FW_VERBOSE_RING_ID,
1244
- FW_VERBOSE_RING_NAME, FW_VERBOSE_RING_SIZE);
2162
+ (uint8 *)FW_VERBOSE_RING_NAME, FW_VERBOSE_RING_SIZE, buf, FALSE);
12452163 if (ret)
12462164 goto error;
12472165
1248
- ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[FW_EVENT_RING_ID], FW_EVENT_RING_ID,
1249
- FW_EVENT_RING_NAME, FW_EVENT_RING_SIZE);
1250
- if (ret)
2166
+ buf = MALLOCZ(dhdp->osh, DHD_EVENT_RING_SIZE);
2167
+ if (!buf)
12512168 goto error;
1252
-
12532169 ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[DHD_EVENT_RING_ID], DHD_EVENT_RING_ID,
1254
- DHD_EVENT_RING_NAME, DHD_EVENT_RING_SIZE);
1255
- if (ret)
1256
- goto error;
1257
-
1258
- ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[NAN_EVENT_RING_ID], NAN_EVENT_RING_ID,
1259
- NAN_EVENT_RING_NAME, NAN_EVENT_RING_SIZE);
2170
+ (uint8 *)DHD_EVENT_RING_NAME, DHD_EVENT_RING_SIZE, buf, FALSE);
12602171 if (ret)
12612172 goto error;
12622173
....@@ -1270,7 +2181,13 @@
12702181 error:
12712182 for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) {
12722183 if (VALID_RING(dbg->dbg_rings[ring_id].id)) {
1273
- dhd_dbg_ring_deinit(dhdp, &dbg->dbg_rings[ring_id]);
2184
+ ring = &dbg->dbg_rings[ring_id];
2185
+ dhd_dbg_ring_deinit(dhdp, ring);
2186
+ if (ring->ring_buf) {
2187
+ MFREE(dhdp->osh, ring->ring_buf, ring->ring_size);
2188
+ ring->ring_buf = NULL;
2189
+ }
2190
+ ring->ring_size = 0;
12742191 }
12752192 }
12762193 MFREE(dhdp->osh, dhdp->dbg, sizeof(dhd_dbg_t));
....@@ -1285,13 +2202,21 @@
12852202 dhd_dbg_detach(dhd_pub_t *dhdp)
12862203 {
12872204 int ring_id;
2205
+ dhd_dbg_ring_t *ring = NULL;
12882206 dhd_dbg_t *dbg;
2207
+
12892208 if (!dhdp->dbg)
12902209 return;
12912210 dbg = dhdp->dbg;
12922211 for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) {
12932212 if (VALID_RING(dbg->dbg_rings[ring_id].id)) {
1294
- dhd_dbg_ring_deinit(dhdp, &dbg->dbg_rings[ring_id]);
2213
+ ring = &dbg->dbg_rings[ring_id];
2214
+ dhd_dbg_ring_deinit(dhdp, ring);
2215
+ if (ring->ring_buf) {
2216
+ MFREE(dhdp->osh, ring->ring_buf, ring->ring_size);
2217
+ ring->ring_buf = NULL;
2218
+ }
2219
+ ring->ring_size = 0;
12952220 }
12962221 }
12972222 MFREE(dhdp->osh, dhdp->dbg, sizeof(dhd_dbg_t));