blob: bcb03ab88d8ffd3e523927d37a36d85664c3f17a [file] [log] [blame]
developer617abbd2024-04-23 14:50:01 +08001From a5d6a71a81b1bd7daadd810a601615a293beea80 Mon Sep 17 00:00:00 2001
2From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
3Date: Thu, 11 Jan 2024 08:55:13 +0800
4Subject: [PATCH 082/116] mtk: wifi: mt76: mt7992: add support to enable index
5 FW log for ConsysPlanet
6
7Add support to enable and record index FW log, which is the input for ConsysPlanet, via mt76-test command.
8
9Usage:
101. Foreground logging
11 1) Start: mt76-test phy0 idxlog
12 2) Stop: Ctrl + C
132. Background logging
14 1) Start: mt76-test phy0 idxlog &
15 2) Stop: killall mt76-test
163. Logging with FW Parser
17 1) Start Ethernet recording of FW Parser.
18 2) Start: mt76-test phy0 idxlog <PC's IP Address>
19 3) Stop: Ctrl + C
20 4) Stop FW Parser.
21
22Log Files
23- FW Log: FW text message
24 - Location: /tmp/log/clog_(timestamp)/WIFI_FW_(timestamp).clog
25- Driver Log: log message printed at driver layer
26 - Location: /tmp/log/clog_(timestamp)/WIFI_KERNEL_(timestamp).clog
27
28CR-Id: WCNCR00298425
29Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
30Change-Id: I5d72c844e920cdcbaed4c65f734de8f041e6f384
31---
32 mt7996/debugfs.c | 90 +++++++++++++++++--
33 mt7996/mac.c | 10 ++-
34 mt7996/mcu.c | 34 +++++++-
35 mt7996/mcu.h | 4 +-
36 mt7996/mt7996.h | 3 +
37 tools/fwlog.c | 218 ++++++++++++++++++++++++++++++++++------------
38 tools/main.c | 2 +
39 tools/mt76-test.h | 3 +
40 8 files changed, 295 insertions(+), 69 deletions(-)
41
42diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
43index e26de48c6..837758611 100644
44--- a/mt7996/debugfs.c
45+++ b/mt7996/debugfs.c
46@@ -430,8 +430,8 @@ create_buf_file_cb(const char *filename, struct dentry *parent, umode_t mode,
47 {
48 struct dentry *f;
49
50- f = debugfs_create_file("fwlog_data", mode, parent, buf,
51- &relay_file_operations);
52+ f = debugfs_create_file(filename[0] == 'f' ? "fwlog_data" : "idxlog_data",
53+ mode, parent, buf, &relay_file_operations);
54 if (IS_ERR(f))
55 return NULL;
56
57@@ -522,6 +522,53 @@ mt7996_fw_debug_bin_get(void *data, u64 *val)
58 DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_bin, mt7996_fw_debug_bin_get,
59 mt7996_fw_debug_bin_set, "%lld\n");
60
61+static int
62+mt7996_idxlog_enable_get(void *data, u64 *val)
63+{
64+ struct mt7996_dev *dev = data;
65+
66+ *val = dev->idxlog_enable;
67+
68+ return 0;
69+}
70+
71+static int
72+mt7996_idxlog_enable_set(void *data, u64 val)
73+{
74+ static struct rchan_callbacks relay_cb = {
75+ .create_buf_file = create_buf_file_cb,
76+ .remove_buf_file = remove_buf_file_cb,
77+ };
78+ struct mt7996_dev *dev = data;
79+
80+ if (dev->idxlog_enable == !!val)
81+ return 0;
82+
83+ if (!dev->relay_idxlog) {
84+ dev->relay_idxlog = relay_open("idxlog_data", dev->debugfs_dir,
85+ 1500, 512, &relay_cb, NULL);
86+ if (!dev->relay_idxlog)
87+ return -ENOMEM;
88+ }
89+
90+ dev->idxlog_enable = !!val;
91+
92+ if (val) {
93+ int ret = mt7996_mcu_fw_time_sync(&dev->mt76);
94+ if (ret)
95+ return ret;
96+
97+ /* Reset relay channel only when it is not being written to. */
98+ relay_reset(dev->relay_idxlog);
99+ }
100+
101+ return mt7996_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM,
102+ val ? MCU_FW_LOG_RELAY_IDX : 0);
103+}
104+
105+DEFINE_DEBUGFS_ATTRIBUTE(fops_idxlog_enable, mt7996_idxlog_enable_get,
106+ mt7996_idxlog_enable_set, "%llu\n");
107+
108 static int
109 mt7996_fw_util_wa_show(struct seq_file *file, void *data)
110 {
111@@ -1042,6 +1089,7 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
112 debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
113 debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
114 debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
115+ debugfs_create_file("idxlog_enable", 0600, dir, dev, &fops_idxlog_enable);
116 /* TODO: wm fw cpu utilization */
117 debugfs_create_file("fw_util_wa", 0400, dir, dev,
118 &mt7996_fw_util_wa_fops);
119@@ -1108,6 +1156,32 @@ mt7996_debugfs_write_fwlog(struct mt7996_dev *dev, const void *hdr, int hdrlen,
120 spin_unlock_irqrestore(&lock, flags);
121 }
122
123+static void
124+mt7996_debugfs_write_idxlog(struct mt7996_dev *dev, const void *data, int len)
125+{
126+ static DEFINE_SPINLOCK(lock);
127+ unsigned long flags;
128+ void *dest;
129+
130+ if (!dev->relay_idxlog)
131+ return;
132+
133+ spin_lock_irqsave(&lock, flags);
134+
135+ dest = relay_reserve(dev->relay_idxlog, len + 4);
136+ if (!dest)
137+ dev_err(dev->mt76.dev, "Failed to reserve slot in %s\n",
138+ dev->relay_idxlog->base_filename);
139+ else {
140+ *(u32 *)dest = len;
141+ dest += 4;
142+ memcpy(dest, data, len);
143+ relay_flush(dev->relay_idxlog);
144+ }
145+
146+ spin_unlock_irqrestore(&lock, flags);
147+}
148+
149 void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len)
150 {
151 struct {
152@@ -1132,11 +1206,15 @@ void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int
153
154 bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len)
155 {
156- if (get_unaligned_le32(data) != FW_BIN_LOG_MAGIC)
157- return false;
158+ bool is_fwlog = get_unaligned_le32(data) == FW_BIN_LOG_MAGIC;
159
160- if (dev->relay_fwlog)
161- mt7996_debugfs_write_fwlog(dev, NULL, 0, data, len);
162+ if (is_fwlog) {
163+ if (dev->relay_fwlog)
164+ mt7996_debugfs_write_fwlog(dev, NULL, 0, data, len);
165+ } else if (dev->relay_idxlog)
166+ mt7996_debugfs_write_idxlog(dev, data, len);
167+ else
168+ return false;
169
170 return true;
171 }
172diff --git a/mt7996/mac.c b/mt7996/mac.c
173index e3758ff13..8c444423b 100644
174--- a/mt7996/mac.c
175+++ b/mt7996/mac.c
176@@ -2279,11 +2279,9 @@ void mt7996_mac_work(struct work_struct *work)
177 mutex_lock(&mdev->mutex);
178
179 mt76_update_survey(mphy);
180- if (++mphy->mac_work_count == 5) {
181+ if (++mphy->mac_work_count % 5 == 0) {
182 int i;
183
184- mphy->mac_work_count = 0;
185-
186 mt7996_mac_update_stats(phy);
187
188 /* Update DEV-wise information only in
189@@ -2302,6 +2300,12 @@ void mt7996_mac_work(struct work_struct *work)
190 if (mt7996_mcu_wa_cmd(phy->dev, MCU_WA_PARAM_CMD(QUERY), MCU_WA_PARAM_BSS_ACQ_PKT_CNT,
191 BSS_ACQ_PKT_CNT_BSS_BITMAP_ALL | BSS_ACQ_PKT_CNT_READ_CLR, 0))
192 dev_err(mdev->dev, "Failed to query per-AC-queue packet counts.\n");
193+
194+ if (mphy->mac_work_count == 100) {
195+ if (phy->dev->idxlog_enable && mt7996_mcu_fw_time_sync(mdev))
196+ dev_err(mdev->dev, "Failed to synchronize time with FW.\n");
197+ mphy->mac_work_count = 0;
198+ }
199 } else if (mt7996_band_valid(phy->dev, i) &&
200 test_bit(MT76_STATE_RUNNING, &mdev->phys[i]->state))
201 break;
202diff --git a/mt7996/mcu.c b/mt7996/mcu.c
203index 6fb9f81f0..3a376c9ac 100644
204--- a/mt7996/mcu.c
205+++ b/mt7996/mcu.c
206@@ -400,6 +400,7 @@ static void
207 mt7996_mcu_rx_log_message(struct mt7996_dev *dev, struct sk_buff *skb)
208 {
209 #define UNI_EVENT_FW_LOG_FORMAT 0
210+#define UNI_EVENT_FW_LOG_MEMORY 1
211 struct mt7996_mcu_rxd *rxd = (struct mt7996_mcu_rxd *)skb->data;
212 const char *data = (char *)&rxd[1] + 4, *type;
213 struct tlv *tlv = (struct tlv *)data;
214@@ -411,7 +412,8 @@ mt7996_mcu_rx_log_message(struct mt7996_dev *dev, struct sk_buff *skb)
215 goto out;
216 }
217
218- if (le16_to_cpu(tlv->tag) != UNI_EVENT_FW_LOG_FORMAT)
219+ if (le16_to_cpu(tlv->tag) != UNI_EVENT_FW_LOG_FORMAT &&
220+ le16_to_cpu(tlv->tag) != UNI_EVENT_FW_LOG_MEMORY)
221 return;
222
223 data += sizeof(*tlv) + 4;
224@@ -3184,6 +3186,36 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level)
225 sizeof(data), false);
226 }
227
228+int mt7996_mcu_fw_time_sync(struct mt76_dev *dev)
229+{
230+ struct {
231+ u8 _rsv[4];
232+
233+ __le16 tag;
234+ __le16 len;
235+ __le32 sec;
236+ __le32 usec;
237+ } data = {
238+ .tag = cpu_to_le16(UNI_WSYS_CONFIG_FW_TIME_SYNC),
239+ .len = cpu_to_le16(sizeof(data) - 4),
240+ };
241+ struct timespec64 ts;
242+ struct tm tm;
243+
244+ ktime_get_real_ts64(&ts);
245+ data.sec = cpu_to_le32((u32)ts.tv_sec);
246+ data.usec = cpu_to_le32((u32)(ts.tv_nsec / 1000));
247+
248+ /* Dump synchronized time for ConsysPlanet to parse. */
249+ time64_to_tm(ts.tv_sec, 0, &tm);
250+ dev_info(dev->dev, "%ld-%02d-%02d %02d:%02d:%02d.%ld UTC\n",
251+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
252+ tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec / 1000);
253+
254+ return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(WSYS_CONFIG), &data,
255+ sizeof(data), true);
256+}
257+
258 static int mt7996_mcu_set_mwds(struct mt7996_dev *dev, bool enabled)
259 {
260 struct {
261diff --git a/mt7996/mcu.h b/mt7996/mcu.h
262index d24874a4b..814072e3a 100644
263--- a/mt7996/mcu.h
264+++ b/mt7996/mcu.h
265@@ -357,7 +357,8 @@ enum {
266 MCU_FW_LOG_WM,
267 MCU_FW_LOG_WA,
268 MCU_FW_LOG_TO_HOST,
269- MCU_FW_LOG_RELAY = 16
270+ MCU_FW_LOG_RELAY = 16,
271+ MCU_FW_LOG_RELAY_IDX = 40
272 };
273
274 enum {
275@@ -950,6 +951,7 @@ enum {
276 UNI_WSYS_CONFIG_FW_LOG_CTRL,
277 UNI_WSYS_CONFIG_FW_DBG_CTRL,
278 UNI_CMD_CERT_CFG = 6,
279+ UNI_WSYS_CONFIG_FW_TIME_SYNC, /* UNI_CMD_FW_TIME_SYNC in FW */
280 };
281
282 enum {
283diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
284index 69bcf78f5..d03d3d94c 100644
285--- a/mt7996/mt7996.h
286+++ b/mt7996/mt7996.h
287@@ -591,9 +591,11 @@ struct mt7996_dev {
288 u8 fw_debug_bin;
289 u16 fw_debug_seq;
290 bool fw_debug_muru_disable;
291+ bool idxlog_enable;
292
293 struct dentry *debugfs_dir;
294 struct rchan *relay_fwlog;
295+ struct rchan *relay_idxlog;
296
297 void *cal;
298 u32 cur_prek_offset;
299@@ -845,6 +847,7 @@ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
300 int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable);
301 int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
302 int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
303+int mt7996_mcu_fw_time_sync(struct mt76_dev *dev);
304 int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
305 void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
306 void mt7996_mcu_exit(struct mt7996_dev *dev);
307diff --git a/tools/fwlog.c b/tools/fwlog.c
308index 3c6a61d71..0e2de2dc2 100644
309--- a/tools/fwlog.c
310+++ b/tools/fwlog.c
311@@ -29,10 +29,9 @@ static const char *debugfs_path(const char *phyname, const char *file)
312 static int mt76_set_fwlog_en(const char *phyname, bool en, char *val)
313 {
314 FILE *f = fopen(debugfs_path(phyname, "fw_debug_bin"), "w");
315-
316 if (!f) {
317- fprintf(stderr, "Could not open fw_debug_bin file\n");
318- return 1;
319+ perror("fopen");
320+ return -1;
321 }
322
323 if (en && val)
324@@ -47,6 +46,21 @@ static int mt76_set_fwlog_en(const char *phyname, bool en, char *val)
325 return 0;
326 }
327
328+static int mt76_set_idxlog_enable(const char *phyname, bool enable)
329+{
330+ FILE *f = fopen(debugfs_path(phyname, "idxlog_enable"), "w");
331+ if (!f) {
332+ perror("fopen");
333+ return -1;
334+ }
335+
336+ fprintf(f, "%hhu", enable);
337+
338+ fclose(f);
339+
340+ return 0;
341+}
342+
343 int read_retry(int fd, void *buf, int len)
344 {
345 int out_len = 0;
346@@ -80,105 +94,193 @@ static void handle_signal(int sig)
347 done = true;
348 }
349
350-int mt76_fwlog(const char *phyname, int argc, char **argv)
351+static int mt76_log_socket(struct sockaddr_in *remote, char *ip)
352 {
353-#define BUF_SIZE 1504
354 struct sockaddr_in local = {
355 .sin_family = AF_INET,
356 .sin_addr.s_addr = INADDR_ANY,
357 };
358- struct sockaddr_in remote = {
359- .sin_family = AF_INET,
360- .sin_port = htons(55688),
361- };
362- char *buf = calloc(BUF_SIZE, sizeof(char));
363- int ret = 0;
364- /* int yes = 1; */
365- int s, fd;
366-
367- if (argc < 1) {
368- fprintf(stderr, "need destination address\n");
369- return 1;
370- }
371+ int s, ret;
372
373- if (!inet_aton(argv[0], &remote.sin_addr)) {
374- fprintf(stderr, "invalid destination address\n");
375- return 1;
376+ remote->sin_family = AF_INET;
377+ remote->sin_port = htons(55688);
378+ if (!inet_aton(ip, &remote->sin_addr)) {
379+ fprintf(stderr, "Invalid destination IP address: %s\n", ip);
380+ return -EINVAL;
381 }
382
383 s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
384 if (s < 0) {
385 perror("socket");
386- return 1;
387+ return s;
388 }
389
390- /* setsockopt(s, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes)); */
391- if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0) {
392+ ret = bind(s, (struct sockaddr *)&local, sizeof(local));
393+ if (ret) {
394 perror("bind");
395- return 1;
396+ close(s);
397+ return ret;
398 }
399
400- if (mt76_set_fwlog_en(phyname, true, argv[1]))
401- return 1;
402+ return s;
403+}
404+
405+static int mt76_log_relay(int in_fd, int out_fd, struct sockaddr_in *remote)
406+{
407+ char *buf = malloc(FWLOG_BUF_SIZE);
408+ int ret = 0;
409
410- fd = open(debugfs_path(phyname, "fwlog_data"), O_RDONLY);
411- if (fd < 0) {
412- fprintf(stderr, "Could not open fwlog_data file: %s\n", strerror(errno));
413- ret = 1;
414- goto out;
415+ if (!buf) {
416+ perror("malloc");
417+ return -ENOMEM;
418 }
419
420 signal(SIGTERM, handle_signal);
421 signal(SIGINT, handle_signal);
422 signal(SIGQUIT, handle_signal);
423
424- while (1) {
425+ while (!done) {
426 struct pollfd pfd = {
427- .fd = fd,
428- .events = POLLIN | POLLHUP | POLLERR,
429+ .fd = in_fd,
430+ .events = POLLIN,
431 };
432 uint32_t len;
433- int r;
434-
435- if (done)
436- break;
437+ int rc;
438
439 poll(&pfd, 1, -1);
440
441- r = read_retry(fd, &len, sizeof(len));
442- if (r < 0)
443+ rc = read_retry(in_fd, &len, sizeof(len));
444+ if (rc < 0) {
445+ if (!done) {
446+ fprintf(stderr, "Failed to read relay file.\n");
447+ ret = -1;
448+ }
449 break;
450-
451- if (!r)
452+ }
453+ if (!rc)
454 continue;
455
456- if (len > BUF_SIZE) {
457- fprintf(stderr, "Length error: %d > %d\n", len, BUF_SIZE);
458- ret = 1;
459+ if (len > FWLOG_BUF_SIZE) {
460+ fprintf(stderr, "Log size was too large: %u bytes\n", len);
461+ ret = -ENOMEM;
462 break;
463 }
464
465- if (done)
466+ rc = read_retry(in_fd, buf, len);
467+ if (rc < 0) {
468+ if (!done) {
469+ fprintf(stderr, "Failed to read relay file.\n");
470+ ret = -1;
471+ }
472 break;
473-
474- r = read_retry(fd, buf, len);
475- if (done)
476+ }
477+ if (rc != len) {
478+ fprintf(stderr, "Expected log size: %u bytes\n", len);
479+ fprintf(stderr, "Read log size: %u bytes\n", rc);
480+ ret = -EIO;
481 break;
482+ }
483
484- if (r != len) {
485- fprintf(stderr, "Short read: %d < %d\n", r, len);
486- ret = 1;
487+ if (remote)
488+ rc = sendto(out_fd, buf, len, 0, (struct sockaddr *)remote, sizeof(*remote));
489+ else
490+ rc = write(out_fd, buf, len);
491+ if (rc < 0) {
492+ perror("sendto/write");
493+ ret = -1;
494 break;
495 }
496+ }
497+
498+ free(buf);
499+
500+ return ret;
501+}
502+
503+int mt76_fwlog(const char *phyname, int argc, char **argv)
504+{
505+ struct sockaddr_in remote;
506+ int in_fd, out_fd, ret;
507+
508+ if (argc < 1) {
509+ fprintf(stderr, "need destination address\n");
510+ return -EINVAL;
511+ }
512+
513+ out_fd = mt76_log_socket(&remote, argv[0]);
514+ if (out_fd < 0)
515+ return out_fd;
516+
517+ ret = mt76_set_fwlog_en(phyname, true, argv[1]);
518+ if (ret)
519+ goto close;
520
521- /* send buf */
522- sendto(s, buf, len, 0, (struct sockaddr *)&remote, sizeof(remote));
523+ in_fd = open(debugfs_path(phyname, "fwlog_data"), O_RDONLY);
524+ if (in_fd < 0) {
525+ perror("open");
526+ goto disable;
527 }
528
529- close(fd);
530+ if (mt76_log_relay(in_fd, out_fd, &remote))
531+ fprintf(stderr, "Failed to relay FW log.\n");
532
533-out:
534- mt76_set_fwlog_en(phyname, false, NULL);
535+ close(in_fd);
536+disable:
537+ ret = mt76_set_fwlog_en(phyname, false, NULL);
538+close:
539+ close(out_fd);
540+
541+ return ret;
542+}
543+
544+int mt76_idxlog(const char *phyname, int argc, char **argv)
545+{
546+#define IDXLOG_FILE_PATH "/tmp/log/WIFI_FW.clog"
547+ struct sockaddr_in remote;
548+ int in_fd, out_fd, ret;
549+
550+ if (argc) {
551+ out_fd = mt76_log_socket(&remote, argv[0]);
552+ if (out_fd < 0)
553+ return out_fd;
554+ } else {
555+ out_fd = open(IDXLOG_FILE_PATH, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR);
556+ if (out_fd < 0) {
557+ perror("open");
558+ return -1;
559+ }
560+ }
561+
562+ ret = mt76_set_idxlog_enable(phyname, true);
563+ if (ret)
564+ goto close;
565+
566+ in_fd = open(debugfs_path(phyname, "idxlog_data"), O_RDONLY);
567+ if (in_fd < 0) {
568+ perror("open");
569+ goto disable;
570+ }
571+
572+ if (mt76_log_relay(in_fd, out_fd, argc ? &remote : NULL))
573+ fprintf(stderr, "Failed to relay index log.\n");
574+
575+ close(in_fd);
576+disable:
577+ ret = mt76_set_idxlog_enable(phyname, false);
578+close:
579+ close(out_fd);
580+
581+ if (argc)
582+ system("timestamp=$(date +\"%y%m%d_%H%M%S\");"
583+ "clog_dir=/tmp/log/clog_${timestamp};"
584+ "mkdir ${clog_dir};"
585+ "dmesg > ${clog_dir}/WIFI_KERNEL_${timestamp}.clog");
586+ else
587+ system("timestamp=$(date +\"%y%m%d_%H%M%S\");"
588+ "clog_dir=/tmp/log/clog_${timestamp};"
589+ "mkdir ${clog_dir};"
590+ "mv /tmp/log/WIFI_FW.clog ${clog_dir}/WIFI_FW_${timestamp}.clog;"
591+ "dmesg > ${clog_dir}/WIFI_KERNEL_${timestamp}.clog");
592
593 return ret;
594 }
595diff --git a/tools/main.c b/tools/main.c
596index 699a9eea6..e9e255679 100644
597--- a/tools/main.c
598+++ b/tools/main.c
599@@ -198,6 +198,8 @@ int main(int argc, char **argv)
600 ret = mt76_eeprom(phy, argc, argv);
601 else if (!strcmp(cmd, "fwlog"))
602 ret = mt76_fwlog(phyname, argc, argv);
603+ else if (!strcmp(cmd, "idxlog"))
604+ ret = mt76_idxlog(phyname, argc, argv);
605 else
606 usage();
607
608diff --git a/tools/mt76-test.h b/tools/mt76-test.h
609index d2fafa862..b9d508c5c 100644
610--- a/tools/mt76-test.h
611+++ b/tools/mt76-test.h
612@@ -22,6 +22,8 @@
613 #define EEPROM_FILE_PATH_FMT "/tmp/mt76-test-%s"
614 #define EEPROM_PART_SIZE 20480
615
616+#define FWLOG_BUF_SIZE 1504
617+
618 struct nl_msg;
619 struct nlattr;
620
621@@ -61,5 +63,6 @@ extern unsigned char *eeprom_data;
622 void usage(void);
623 int mt76_eeprom(int phy, int argc, char **argv);
624 int mt76_fwlog(const char *phyname, int argc, char **argv);
625+int mt76_idxlog(const char *phyname, int argc, char **argv);
626
627 #endif
628--
6292.39.2
630