All of lore.kernel.org
 help / color / mirror / Atom feed
From: viktor.barna@celeno.com
To: linux-wireless@vger.kernel.org
Cc: Kalle Valo <kvalo@codeaurora.org>,
	"David S . Miller" <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>,
	Aviad Brikman <aviad.brikman@celeno.com>,
	Eliav Farber <eliav.farber@gmail.com>,
	Oleksandr Savchenko <oleksandr.savchenko@celeno.com>,
	Shay Bar <shay.bar@celeno.com>,
	Viktor Barna <viktor.barna@celeno.com>
Subject: [RFC v1 086/256] cl8k: add fw/fw_dbg.c
Date: Thu, 17 Jun 2021 15:59:33 +0000	[thread overview]
Message-ID: <20210617160223.160998-87-viktor.barna@celeno.com> (raw)
In-Reply-To: <20210617160223.160998-1-viktor.barna@celeno.com>

From: Viktor Barna <viktor.barna@celeno.com>

(Part of the split. Please, take a look at the cover letter for more
details).

Signed-off-by: Viktor Barna <viktor.barna@celeno.com>
---
 drivers/net/wireless/celeno/cl8k/fw/fw_dbg.c | 2686 ++++++++++++++++++
 1 file changed, 2686 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/fw/fw_dbg.c

diff --git a/drivers/net/wireless/celeno/cl8k/fw/fw_dbg.c b/drivers/net/wireless/celeno/cl8k/fw/fw_dbg.c
new file mode 100644
index 000000000000..413f45b433c6
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/fw/fw_dbg.c
@@ -0,0 +1,2686 @@
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+#include <linux/utsname.h>
+
+#include "utils/utils.h"
+#include "fw/fw_dbg.h"
+#ifdef CONFIG_CL_PCIE
+#include "bus/pci/ipc.h"
+#endif
+#include "band.h"
+#include "chip.h"
+#include "coredump.h"
+#include "ela.h"
+#include "utils/file.h"
+#include "dbgfile.h"
+#include "rx/rx.h"
+#include "fw/msg_tx.h"
+
+/* Work struct wrapper for print statistics */
+struct cl_print_stats_work {
+       struct work_struct ws;
+       struct cl_hw *cl_hw;
+       u32 dbg_info_type;
+};
+
+#define FW_DBG_INVALID_SESSION U8_MAX
+
+#define PRINT_FW(cl_hw, fmt, ...) \
+       pr_debug("%cmac%u " fmt, (cl_hw)->fw_prefix, (cl_hw)->chip->idx, ##__VA_ARGS__)
+
+/*
+ * Display 2 digit decimal fraction.
+ * Example: x = 541, y = 19 = 28.47368
+ *   ==> 47
+ */
+#define DECIMAL_FRACTION_X2(x, y) (100 * ((x) - (y) * ((x) / (y))) / (y))
+
+static void cl_print_tx_stats(struct cl_hw *cl_hw, struct cl_txl_statistics *tx_stats)
+{
+       int i;
+       u8 per = 0;
+       u64 total_retry = 0;
+       u64 total_tx = 0;
+       u32 total_natt = 0;
+       u32 avg_backoff = 0;
+       u32 agg_size_total = 0;
+       u32 agg_size_x100 = 0;
+       u32 total_vns_off = 0;
+       u32 total_vns_on = 0;
+       bool is_agg_in_txop = false;
+       struct cl_txl_agg_statistics *agg = &tx_stats->agg;
+       struct cl_txl_htp_statistics *htp = &tx_stats->htp;
+       struct cl_txl_natt_statistics *natt = &tx_stats->natt;
+       struct cl_txl_vns_statistics *vns = &tx_stats->vns;
+       struct cl_txl_fec_statistics *fec = &tx_stats->fec;
+       struct cl_txl_backoff_params *backoff_params = &tx_stats->backoff_params;
+       struct cl_txl_rts_cts_statistics *rts_cts = &tx_stats->rts_cts;
+       struct cl_txl_underrun_statistics *underrun = &tx_stats->underrun;
+
+       const char *fw_tx_backoff_str[CL_MAX_FRM_TYPE] = {
+               [CE_BACKOFF_25]          = "<25",
+               [CE_BACKOFF_50]          = "50",
+               [CE_BACKOFF_100]         = "100",
+               [CE_BACKOFF_500]         = "500",
+               [CE_BACKOFF_1000]        = "1000",
+               [CE_BACKOFF_5000]        = "5000",
+               [CE_BACKOFF_10000]       = "10000",
+               [CE_BACKOFF_20000]       = "20000",
+               [CE_BACKOFF_20000_ABOVE] = ">20000",
+       };
+
+       /* Singles info */
+       PRINT_FW(cl_hw, "TX statistics - singles\n");
+       PRINT_FW(cl_hw, "------------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "| q |sent      |retry     |lft exp   |ret limit |ret lim ps|per %%|\n");
+       PRINT_FW(cl_hw, "|---+----------+----------+----------+----------+----------+-----|\n");
+
+       for (i = 0; i < IPC_TX_QUEUE_CNT; i++) {
+               total_retry = tx_stats->single[i].total_rtx_cnt +
+                       tx_stats->single[i].total_lifetime_expired_cnt +
+                       tx_stats->single[i].total_rtx_limit_reached;
+
+               total_tx = tx_stats->single[i].total_cnt + total_retry;
+
+               if (total_tx == 0)
+                       continue;
+
+               per = (u8)div64_u64(total_retry * 100, total_tx);
+
+               PRINT_FW(cl_hw, "|%3u|%10u|%10u|%10u|%10u|%10u|%5u|\n",
+                        i,
+                        tx_stats->single[i].total_cnt,
+                        tx_stats->single[i].total_rtx_cnt,
+                        tx_stats->single[i].total_lifetime_expired_cnt,
+                        tx_stats->single[i].total_rtx_limit_reached,
+                        tx_stats->single[i].total_rtx_limit_reached_ps,
+                        per);
+       }
+
+       PRINT_FW(cl_hw, "------------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* Aggregation info */
+       PRINT_FW(cl_hw, "TX statistics - aggregations - MAX [%u]\n", IPC_MAX_BA_SESSIONS);
+       PRINT_FW(cl_hw, "-----------------------------------------------------------------------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "|Q |Total    |Total    |Lifetime|Retry |BA       |BA not   |BA     |BA     |BA    |Below BA|Above BA|ACK    |PS BA not|Total|\n");
+       PRINT_FW(cl_hw, "|  |sent     |retry    |expired |Limit |received |received |Cleared|Invalid|un-exp|window  |window  |inst BA|received |Per %%|\n");
+       PRINT_FW(cl_hw, "|--+---------+---------+--------+------+---------+---------+-------+-------+------+--------+--------+-------+---------+-----|\n");
+
+       for (i = 0; i < IPC_MAX_BA_SESSIONS; i++) {
+               total_retry = tx_stats->ba[i].total_rtx_cnt +
+                       tx_stats->ba[i].total_lifetime_expired_cnt +
+                       tx_stats->ba[i].total_rtx_limit_reached;
+
+               total_tx = tx_stats->ba[i].total_cnt;
+
+               if (total_tx == 0)
+                       continue;
+
+               per = (u8)div64_u64(total_retry * 100, total_tx);
+
+               PRINT_FW(cl_hw, "|%2u|%9u|%9u|%8u|%6u|%9u|%9u|%7u|%7u|%6u|%8u|%8u|%7u|%9u|%5u|\n",
+                        i,
+                        tx_stats->ba[i].total_cnt,
+                        tx_stats->ba[i].total_rtx_cnt,
+                        tx_stats->ba[i].total_lifetime_expired_cnt,
+                        tx_stats->ba[i].total_rtx_limit_reached,
+                        tx_stats->ba[i].total_ba_received,
+                        tx_stats->ba[i].total_ba_not_received_cnt,
+                        tx_stats->ba[i].total_cleard_ba,
+                        tx_stats->ba[i].total_invalid_ba,
+                        tx_stats->ba[i].total_unexpected_ba,
+                        tx_stats->ba[i].total_packets_below_baw,
+                        tx_stats->ba[i].total_packets_above_baw,
+                        tx_stats->ba[i].total_ack_instead_ba,
+                        tx_stats->ba[i].total_ba_not_received_cnt_ps,
+                        per);
+       }
+       PRINT_FW(cl_hw, "-----------------------------------------------------------------------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* TID info */
+       PRINT_FW(cl_hw, "----------------\n");
+       PRINT_FW(cl_hw, "|TID|NumPackets|\n");
+       PRINT_FW(cl_hw, "|---+----------|\n");
+
+       for (i = 0; i < TID_MAX; i++) {
+               if (tx_stats->tid[i].total_tid_desc_cnt == 0)
+                       continue;
+
+               PRINT_FW(cl_hw, "|%3d|%10u|\n", i, tx_stats->tid[i].total_tid_desc_cnt);
+       }
+
+       PRINT_FW(cl_hw, "----------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* AC info */
+       PRINT_FW(cl_hw, "---------------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "|     AC     |    0     |    1     |    2     |    3     |    4     |\n");
+       PRINT_FW(cl_hw, "|------------+----------+----------+----------+----------+----------|\n");
+       PRINT_FW(cl_hw, "|Num switches|%10u|%10u|%10u|%10u|%10u|\n",
+                tx_stats->ac[0].total_q_switch_cnt,
+                tx_stats->ac[1].total_q_switch_cnt,
+                tx_stats->ac[2].total_q_switch_cnt,
+                tx_stats->ac[3].total_q_switch_cnt,
+                tx_stats->ac[4].total_q_switch_cnt);
+       PRINT_FW(cl_hw, "|Num txdesc  |%10u|%10u|%10u|%10u|%10u|\n",
+                tx_stats->ac[0].total_ac_desc_cnt,
+                tx_stats->ac[1].total_ac_desc_cnt,
+                tx_stats->ac[2].total_ac_desc_cnt,
+                tx_stats->ac[3].total_ac_desc_cnt,
+                tx_stats->ac[4].total_ac_desc_cnt);
+       PRINT_FW(cl_hw, "---------------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* Underrun info */
+       if (underrun->length_cnt || underrun->pattern_cnt) {
+               PRINT_FW(cl_hw, "======== Underrun recovery statistics =======\n");
+               PRINT_FW(cl_hw, "Length underrun %u\n",
+                        underrun->length_cnt);
+               PRINT_FW(cl_hw, "Pattern underrun %u\n",
+                        underrun->pattern_cnt);
+               PRINT_FW(cl_hw, "Total frames flushed in underrun %u\n",
+                        underrun->flushed_frames_cnt);
+               PRINT_FW(cl_hw, "\n");
+       }
+
+       /* BW drop fail info */
+       if (tx_stats->tx_obtain_bw_fail_cnt) {
+               PRINT_FW(cl_hw, "Failed to obtain BW count %u\n", tx_stats->tx_obtain_bw_fail_cnt);
+               PRINT_FW(cl_hw, "\n");
+       }
+
+       /* Backoff time info */
+       PRINT_FW(cl_hw, "Backoff Time [us]\n");
+       PRINT_FW(cl_hw, "------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "|Backoff |   AC 0   |   AC 1   |   AC 2   |   AC 3   |\n");
+
+       for (i = 0; i < CE_BACKOFF_MAX; i++) {
+               if (tx_stats->backoff_stats[AC_BK].backoff_hist[i] == 0 &&
+                   tx_stats->backoff_stats[AC_BE].backoff_hist[i] == 0 &&
+                   tx_stats->backoff_stats[AC_VI].backoff_hist[i] == 0 &&
+                   tx_stats->backoff_stats[AC_VO].backoff_hist[i] == 0)
+                       continue;
+
+               PRINT_FW(cl_hw, "|--------+----------+----------+----------+----------|\n");
+               PRINT_FW(cl_hw, "| %6s |%10u|%10u|%10u|%10u|\n",
+                        fw_tx_backoff_str[i],
+                        tx_stats->backoff_stats[AC_BK].backoff_hist[i],
+                        tx_stats->backoff_stats[AC_BE].backoff_hist[i],
+                        tx_stats->backoff_stats[AC_VI].backoff_hist[i],
+                        tx_stats->backoff_stats[AC_VO].backoff_hist[i]);
+       }
+
+       PRINT_FW(cl_hw, "------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* AMSDU Packet cnt */
+       PRINT_FW(cl_hw, "|--------------------|\n");
+       PRINT_FW(cl_hw, "|  AMSDU Packet cnt  |\n");
+       PRINT_FW(cl_hw, "|--------------------|\n");
+       for (i = 0; i < IPC_MAX_BA_SESSIONS; i++) {
+               if (agg->amsdu_stat[i].packet_cnt_2 == 0 &&
+                   agg->amsdu_stat[i].packet_cnt_3 == 0 &&
+                   agg->amsdu_stat[i].packet_cnt_4 == 0 &&
+                   agg->amsdu_stat[i].packet_cnt_5_or_more == 0)
+                       continue;
+
+               PRINT_FW(cl_hw, "# session=%u\n", i);
+               PRINT_FW(cl_hw, "packet_cnt  = 2: [%u]\n",
+                        agg->amsdu_stat[i].packet_cnt_2);
+               PRINT_FW(cl_hw, "packet_cnt  = 3: [%u]\n",
+                        agg->amsdu_stat[i].packet_cnt_3);
+               PRINT_FW(cl_hw, "packet_cnt  = 4: [%u]\n",
+                        agg->amsdu_stat[i].packet_cnt_4);
+               PRINT_FW(cl_hw, "packet_cnt >= 5: [%u]\n",
+                        agg->amsdu_stat[i].packet_cnt_5_or_more);
+               PRINT_FW(cl_hw, "\n");
+       }
+       PRINT_FW(cl_hw, "\n");
+
+       /* Agg statistics */
+       for (i = 1; i < CL_MAX_AGG_IN_TXOP; i++) {
+               if (agg->agg_in_txop_statistics[i]) {
+                       is_agg_in_txop = true;
+                       break;
+               }
+       }
+
+       if (is_agg_in_txop) {
+               /* Agg in TXOP */
+               PRINT_FW(cl_hw, "Agg in TXOP\n");
+               PRINT_FW(cl_hw, "|----------------|\n");
+               PRINT_FW(cl_hw, "| Agg |  Count   |\n");
+               PRINT_FW(cl_hw, "|-----+----------|\n");
+
+               for (i = 1; i < CL_MAX_AGG_IN_TXOP; i++) {
+                       if (!agg->agg_in_txop_statistics[i])
+                               continue;
+
+                       PRINT_FW(cl_hw, "|%5u|%10u|\n",
+                                i + 1, agg->agg_in_txop_statistics[i]);
+               }
+
+               PRINT_FW(cl_hw, "|----------------|\n");
+               PRINT_FW(cl_hw, "\n");
+
+               /* Agg close reason & Agg queue switch */
+               PRINT_FW(cl_hw, "Agg close reason:\n");
+               PRINT_FW(cl_hw, "  Not enough txdescs = %u\n",
+                        agg->agg_in_txop_close_reason[AGG_IN_TXOP_CLOSE_REASON_NO_TXDESC]);
+               PRINT_FW(cl_hw, "  TXOP expired       = %u\n",
+                        agg->agg_in_txop_close_reason[AGG_IN_TXOP_CLOSE_REASON_TXOP_EXPIRED]);
+               PRINT_FW(cl_hw, "  Delba in process   = %u\n",
+                        agg->agg_in_txop_close_reason[AGG_IN_TXOP_CLOSE_REASON_ACTIVE_DELBA]);
+               PRINT_FW(cl_hw, "Agg queue switch:\n");
+               PRINT_FW(cl_hw, "  Queue switch within TXOP               = %u\n",
+                        agg->agg_in_txop_queue_switch);
+               PRINT_FW(cl_hw, "  Queue switch abort due diff bw in TXOP = %u\n",
+                        agg->agg_in_txop_queue_switch_abort_bw);
+               PRINT_FW(cl_hw, "\n");
+       }
+
+       /* RTS-CTS statistics */
+       if (rts_cts->fw_rts_cnt ||
+           rts_cts->fw_cts_cnt ||
+           rts_cts->hw_rts_cnt ||
+           rts_cts->hw_cts_cnt) {
+               PRINT_FW(cl_hw, "RTS-CTS statistics\n");
+               PRINT_FW(cl_hw, "==================\n");
+               PRINT_FW(cl_hw, "FW RTS frame count = %u\n", rts_cts->fw_rts_cnt);
+               PRINT_FW(cl_hw, "FW CTS frame count = %u\n", rts_cts->fw_cts_cnt);
+               PRINT_FW(cl_hw, "HW RTS frame count = %u\n", rts_cts->hw_rts_cnt);
+               PRINT_FW(cl_hw, "HW CTS frame count = %u\n", rts_cts->hw_cts_cnt);
+               PRINT_FW(cl_hw, "\n");
+       }
+
+       /* Natt statistics */
+       PRINT_FW(cl_hw, "natt statistics\n");
+       PRINT_FW(cl_hw, "===============\n");
+       PRINT_FW(cl_hw, "agg size[0] = %u <singeltons>\n", agg->agg_size_statistics[0]);
+       PRINT_FW(cl_hw, "\n");
+
+       PRINT_FW(cl_hw, "-----------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "|agg | num sent |percent | pass per | drop per | PER per  |\n");
+       PRINT_FW(cl_hw, "|size| per size |per size| agg size | agg size | agg size |\n");
+       PRINT_FW(cl_hw, "|----+----------+--------+----------+----------+----------|\n");
+
+       for (i = 1; i < DBG_STATS_MAX_AGG_SIZE; i++)
+               agg_size_total += agg->agg_size_statistics[i];
+
+       for (i = 1; i < DBG_STATS_MAX_AGG_SIZE; i++) {
+               if (agg->agg_size_statistics[i] == 0)
+                       continue;
+
+               total_natt = agg->packet_failed_statistics[i] + agg->packet_passed_statistics[i];
+
+               if (total_natt == 0)
+                       continue;
+
+               agg_size_x100 = 100 * agg->agg_size_statistics[i];
+
+               PRINT_FW(cl_hw, "|%4u|%10u|%5u.%02u|%10u|%10u|%10u|\n",
+                        i,
+                        agg->agg_size_statistics[i],
+                        agg_size_x100 / agg_size_total,
+                        DECIMAL_FRACTION_X2(agg_size_x100, agg_size_total),
+                        agg->packet_passed_statistics[i],
+                        agg->packet_failed_statistics[i],
+                        ((agg->packet_failed_statistics[i] * 100) / total_natt));
+       }
+       PRINT_FW(cl_hw, "-----------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "Amount of all su aggregations: %u\n", agg_size_total);
+       PRINT_FW(cl_hw, "\n");
+
+       /* Natt statistics (HTP flows) */
+       PRINT_FW(cl_hw, "natt statistics HTP flows\n");
+       PRINT_FW(cl_hw, "=========================\n");
+       PRINT_FW(cl_hw, "-----------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "|agg |num sent| percent  | pass per | drop per | PER per  |\n");
+       PRINT_FW(cl_hw, "|size|per size| per size | agg size | agg size | agg size |\n");
+       PRINT_FW(cl_hw, "|----+--------+----------+----------+----------+----------|\n");
+
+       agg_size_total = 0;
+       for (i = 1; i < DBG_STATS_MAX_AGG_SIZE; i++)
+               agg_size_total += agg->htp_agg_size_statistics[i];
+
+       for (i = 1; i < DBG_STATS_MAX_AGG_SIZE; i++) {
+               if (agg->htp_agg_size_statistics[i] == 0)
+                       continue;
+
+               total_natt = agg->htp_packet_failed_statistics[i] +
+                       agg->htp_packet_passed_statistics[i];
+
+               if (total_natt == 0)
+                       continue;
+
+               agg_size_x100 = 100 * agg->htp_agg_size_statistics[i];
+
+               PRINT_FW(cl_hw, "|%4u|%10u|%5u.%02u|%10u|%10u|%10u|\n",
+                        i,
+                        agg->htp_agg_size_statistics[i],
+                        agg_size_x100 / agg_size_total,
+                        DECIMAL_FRACTION_X2(agg_size_x100, agg_size_total),
+                        agg->htp_packet_passed_statistics[i],
+                        agg->htp_packet_failed_statistics[i],
+                        (agg->htp_agg_size_statistics[i] * 100 / total_natt));
+       }
+       PRINT_FW(cl_hw, "-----------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* Chosen frame BW */
+       PRINT_FW(cl_hw, "Chosen frame BW\n");
+       for (i = 0; i < NATT_BW_MAX; i++)
+               PRINT_FW(cl_hw, "BW[%u] = %u\n", i, natt->chosen_frame_bw[i]);
+       PRINT_FW(cl_hw, "\n");
+
+       /* Natt operation mode */
+       PRINT_FW(cl_hw, "Natt operation mode\n");
+       for (i = 0; i < 8; i++)
+               if (natt->operation_mode[i] != 0)
+                       PRINT_FW(cl_hw, "[0x%x] = %u\n", i, natt->operation_mode[i]);
+       PRINT_FW(cl_hw, "\n");
+
+       /* Natt agg close reason */
+       PRINT_FW(cl_hw, "natt agg close reason\n");
+       PRINT_FW(cl_hw, "=====================\n");
+       PRINT_FW(cl_hw, "Max length exceed  %u\n", natt->agg_close_reason[NATT_REASON_MAX_LEN]);
+       PRINT_FW(cl_hw, "TXOP limit exceed  %u\n", natt->agg_close_reason[NATT_REASON_TXOP_LIMIT]);
+       PRINT_FW(cl_hw, "MPDU number exceed %u\n", natt->agg_close_reason[NATT_REASON_MPDU_NUM]);
+       PRINT_FW(cl_hw, "\n");
+
+       /* Recovery count */
+       if (tx_stats->recovery_count) {
+               PRINT_FW(cl_hw, "Recovery count\n");
+               PRINT_FW(cl_hw, "==============\n");
+               PRINT_FW(cl_hw, "Total: %u\n", tx_stats->recovery_count);
+               PRINT_FW(cl_hw, "\n");
+       }
+
+       /* Singelton backoff_params time */
+       PRINT_FW(cl_hw, "Singelton backoff_params time:\n");
+       for (i = 0; i < AC_MAX; i++) {
+               if (backoff_params->singelton_cnt[i]) {
+                       avg_backoff = backoff_params->singelton_total[i] /
+                               backoff_params->singelton_cnt[i];
+                       PRINT_FW(cl_hw, "ac%d avarage backoff_params %u\n", i, avg_backoff);
+               } else {
+                       PRINT_FW(cl_hw, "ac%d avarage backoff_params 0\n", i);
+               }
+       }
+       PRINT_FW(cl_hw, "\n");
+
+       /* Aggregation backoff_params time */
+       PRINT_FW(cl_hw, "Aggregation backoff_params time:\n");
+       for (i = 0; i < AC_VO; i++) {
+               if (backoff_params->agg_cnt[i]) {
+                       avg_backoff = backoff_params->agg_total[i] /
+                               backoff_params->agg_cnt[i];
+                       PRINT_FW(cl_hw, "ac%d avarage backoff_params %u\n", i, avg_backoff);
+               } else {
+                       PRINT_FW(cl_hw, "ac%d avarage backoff_params 0\n", i);
+               }
+       }
+       PRINT_FW(cl_hw, "\n");
+
+       /* Trigger Based traffic statistics */
+       PRINT_FW(cl_hw, "Trigger Based traffic statistics:\n");
+       for (i = 0; i < TID_MAX; i++)
+               if (htp->total_cnt[i])
+                       PRINT_FW(cl_hw, "TID%d total_cnt %u\n", i, htp->total_cnt[i]);
+       PRINT_FW(cl_hw, "\n");
+
+       if (htp->need_response || htp->tb_response_required) {
+               PRINT_FW(cl_hw, "need_response         = %u\n", htp->need_response);
+               PRINT_FW(cl_hw, "tb_response_required  = %u\n", htp->tb_response_required);
+               PRINT_FW(cl_hw, "ac_not_found          = %u\n", htp->ac_not_found);
+               PRINT_FW(cl_hw, "end_of_packet_int     = %u\n", htp->end_of_packet_int);
+               PRINT_FW(cl_hw, "tb_bw_decision        = %u\n", htp->tb_bw_decision);
+               PRINT_FW(cl_hw, "tb_ba_thd_removed     = %u\n", htp->tb_ba_thd_removed);
+               PRINT_FW(cl_hw, "tb_ac_unchain         = %u\n", htp->tb_ac_unchain);
+               PRINT_FW(cl_hw, "tb_htp_unchain        = %u\n", htp->tb_htp_unchain);
+               PRINT_FW(cl_hw, "tb_dummy_htp_tx       = %u\n", htp->tb_dummy_htp_tx);
+               PRINT_FW(cl_hw, "tb_dummy_no_tx        = %u\n", htp->tb_dummy_no_tx);
+               PRINT_FW(cl_hw, "msta_ba_received      = %u\n", htp->msta_ba_received);
+               PRINT_FW(cl_hw, "msta_ba_aid_not_found = %u\n", htp->msta_ba_aid_not_found);
+       }
+
+       total_vns_off = vns->off_cck + vns->off_ofdm + vns->off_ht_vht + vns->off_he;
+       total_vns_on = vns->on_cck + vns->on_ofdm + vns->on_ht_vht + vns->on_he;
+
+       if (total_vns_off || total_vns_on) {
+               PRINT_FW(cl_hw, "       -----------------------\n");
+               PRINT_FW(cl_hw, "       | VNS-OFF  |  VNS-ON  |\n");
+               PRINT_FW(cl_hw, "-------+----------+----------|\n");
+               PRINT_FW(cl_hw, "|CCK   |%10u|%10u|\n", vns->off_cck, vns->on_cck);
+               PRINT_FW(cl_hw, "|OFDM  |%10u|%10u|\n", vns->off_ofdm, vns->on_ofdm);
+               PRINT_FW(cl_hw, "|HT-VHT|%10u|%10u|\n", vns->off_ht_vht, vns->on_ht_vht);
+               PRINT_FW(cl_hw, "|HE    |%10u|%10u|\n", vns->off_he, vns->on_he);
+               PRINT_FW(cl_hw, "|------+----------+----------|\n");
+               PRINT_FW(cl_hw, "|TOTAL |%10u|%10u|\n", total_vns_off, total_vns_on);
+               PRINT_FW(cl_hw, "------------------------------\n");
+               PRINT_FW(cl_hw, "\n");
+       }
+
+       if (fec->ldpc || fec->bcc) {
+               PRINT_FW(cl_hw, "FEC Coding:\n");
+               PRINT_FW(cl_hw, "LDPC = %u\n", fec->ldpc);
+               PRINT_FW(cl_hw, "BCC  = %u\n", fec->bcc);
+               PRINT_FW(cl_hw, "\n");
+       }
+}
+
+static void cl_print_tx_mu_stats(struct cl_hw *cl_hw, struct cl_txl_statistics *tx_stats)
+{
+       int i;
+       struct cl_txl_agg_statistics *agg = &tx_stats->agg;
+
+       if (agg->mu_stats[CL_MU1_IDX].chain_cnt == 0) {
+               PRINT_FW(cl_hw, "~~~~~~~~~~~~~~~~~~  MU  statistics - EMPTY  ~~~~~~~~~~~~~~~~~~\n");
+               return;
+       }
+
+       PRINT_FW(cl_hw, "~~~~~~~~~~~~~~~~~~~~~~~~~  MU  statistics  ~~~~~~~~~~~~~~~~~~~~~~~~~\n");
+       PRINT_FW(cl_hw, "\n");
+
+#if (MU_MAX_STREAMS >= 4)
+       /* MU status statistics */
+       PRINT_FW(cl_hw, "--------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "|            | MU1 | MU2 | MU3 | MU4 | MU5 | MU6 | MU7 |\n");
+       PRINT_FW(cl_hw, "|------------+-----+-----+-----+-----+-----+-----+-----|\n");
+       PRINT_FW(cl_hw, "|Chain count |%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU1_IDX].chain_cnt,
+                agg->mu_stats[CL_MU2_IDX].chain_cnt,
+                agg->mu_stats[CL_MU3_IDX].chain_cnt,
+                agg->mu_stats[CL_MU4_IDX].chain_cnt,
+                agg->mu_stats[CL_MU5_IDX].chain_cnt,
+                agg->mu_stats[CL_MU6_IDX].chain_cnt,
+                agg->mu_stats[CL_MU7_IDX].chain_cnt);
+       PRINT_FW(cl_hw, "|Status count|%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU1_IDX].status_cnt,
+                agg->mu_stats[CL_MU2_IDX].status_cnt,
+                agg->mu_stats[CL_MU3_IDX].status_cnt,
+                agg->mu_stats[CL_MU4_IDX].status_cnt,
+                agg->mu_stats[CL_MU5_IDX].status_cnt,
+                agg->mu_stats[CL_MU6_IDX].status_cnt,
+                agg->mu_stats[CL_MU7_IDX].status_cnt);
+       PRINT_FW(cl_hw, "--------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* MU agg-size statistics */
+       PRINT_FW(cl_hw, "------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "| agg size | MU0 | MU1 | MU2 | MU3 | MU4 | MU5 | MU6 | MU7 |\n");
+       PRINT_FW(cl_hw, "|----------+-----+-----+-----+-----+-----+-----+-----+-----|\n");
+       for (i = 1; i < DBG_STATS_MAX_AGG_SIZE; i++) {
+               if (agg->mu_agg_size_statistics[CL_MU0_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU1_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU2_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU3_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU4_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU5_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU6_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU7_IDX][i]) {
+                       PRINT_FW(cl_hw, "|%10u|%5u|%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                                i,
+                                agg->mu_agg_size_statistics[CL_MU0_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU1_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU2_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU3_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU4_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU5_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU6_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU7_IDX][i]);
+               }
+       }
+       PRINT_FW(cl_hw, "------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* MU BA statistics */
+       PRINT_FW(cl_hw, "--------------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "| MU BA statistics | MU0 | MU1 | MU2 | MU3 | MU4 | MU5 | MU6 | MU7 |\n");
+       PRINT_FW(cl_hw, "|------------------+-----+-----+-----+-----+-----+-----+-----+-----|\n");
+       PRINT_FW(cl_hw, "|  BA Received     |%5u|%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].ba_received,
+                agg->mu_stats[CL_MU1_IDX].ba_received,
+                agg->mu_stats[CL_MU2_IDX].ba_received,
+                agg->mu_stats[CL_MU3_IDX].ba_received,
+                agg->mu_stats[CL_MU4_IDX].ba_received,
+                agg->mu_stats[CL_MU5_IDX].ba_received,
+                agg->mu_stats[CL_MU6_IDX].ba_received,
+                agg->mu_stats[CL_MU7_IDX].ba_received);
+       PRINT_FW(cl_hw, "|  --Unexpected BA |%5u|%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU1_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU2_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU3_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU4_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU5_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU6_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU7_IDX].unexpected_ba);
+       PRINT_FW(cl_hw, "|  --Cleared    BA |%5u|%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].clear_ba,
+                agg->mu_stats[CL_MU1_IDX].clear_ba,
+                agg->mu_stats[CL_MU2_IDX].clear_ba,
+                agg->mu_stats[CL_MU3_IDX].clear_ba,
+                agg->mu_stats[CL_MU4_IDX].clear_ba,
+                agg->mu_stats[CL_MU5_IDX].clear_ba,
+                agg->mu_stats[CL_MU6_IDX].clear_ba,
+                agg->mu_stats[CL_MU7_IDX].clear_ba);
+       PRINT_FW(cl_hw, "|  --Invalid    BA |%5u|%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].invalid_ba,
+                agg->mu_stats[CL_MU1_IDX].invalid_ba,
+                agg->mu_stats[CL_MU2_IDX].invalid_ba,
+                agg->mu_stats[CL_MU3_IDX].invalid_ba,
+                agg->mu_stats[CL_MU4_IDX].invalid_ba,
+                agg->mu_stats[CL_MU5_IDX].invalid_ba,
+                agg->mu_stats[CL_MU6_IDX].invalid_ba,
+                agg->mu_stats[CL_MU7_IDX].invalid_ba);
+       PRINT_FW(cl_hw, "|  --Correct    BA |%5u|%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].correct_ba,
+                agg->mu_stats[CL_MU1_IDX].correct_ba,
+                agg->mu_stats[CL_MU2_IDX].correct_ba,
+                agg->mu_stats[CL_MU3_IDX].correct_ba,
+                agg->mu_stats[CL_MU4_IDX].correct_ba,
+                agg->mu_stats[CL_MU5_IDX].correct_ba,
+                agg->mu_stats[CL_MU6_IDX].correct_ba,
+                agg->mu_stats[CL_MU7_IDX].correct_ba);
+       PRINT_FW(cl_hw, "|  BA not Received |%5u|%5u|%5u|%5u|%5u|%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].ba_no_received,
+                agg->mu_stats[CL_MU1_IDX].ba_no_received,
+                agg->mu_stats[CL_MU2_IDX].ba_no_received,
+                agg->mu_stats[CL_MU3_IDX].ba_no_received,
+                agg->mu_stats[CL_MU4_IDX].ba_no_received,
+                agg->mu_stats[CL_MU5_IDX].ba_no_received,
+                agg->mu_stats[CL_MU6_IDX].ba_no_received,
+                agg->mu_stats[CL_MU7_IDX].ba_no_received);
+       PRINT_FW(cl_hw, "--------------------------------------------------------------------\n");
+#elif (MU_MAX_STREAMS == 3)
+       /* MU status statistics */
+       PRINT_FW(cl_hw, "--------------------------\n");
+       PRINT_FW(cl_hw, "|            | MU1 | MU2 |\n");
+       PRINT_FW(cl_hw, "|------------+-----+-----|\n");
+       PRINT_FW(cl_hw, "|Chain count |%5u|%5u|\n",
+                agg->mu_stats[CL_MU1_IDX].chain_cnt,
+                agg->mu_stats[CL_MU2_IDX].chain_cnt);
+       PRINT_FW(cl_hw, "|Status count|%5u|%5u|\n",
+                agg->mu_stats[CL_MU1_IDX].status_cnt,
+                agg->mu_stats[CL_MU2_IDX].status_cnt);
+       PRINT_FW(cl_hw, "--------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* MU agg-size statistics */
+       PRINT_FW(cl_hw, "------------------------------\n");
+       PRINT_FW(cl_hw, "| agg size | MU0 | MU1 | MU2 |\n");
+       PRINT_FW(cl_hw, "|----------+-----+-----+-----|\n");
+       for (i = 1; i < DBG_STATS_MAX_AGG_SIZE; i++) {
+               if (agg->mu_agg_size_statistics[CL_MU0_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU1_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU2_IDX][i]) {
+                       PRINT_FW(cl_hw, "|%10u|%5u|%5u|%5u|\n",
+                                i,
+                                agg->mu_agg_size_statistics[CL_MU0_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU1_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU2_IDX][i]);
+               }
+       }
+       PRINT_FW(cl_hw, "------------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* MU BA statistics */
+       PRINT_FW(cl_hw, "--------------------------------------\n");
+       PRINT_FW(cl_hw, "| MU BA statistics | MU0 | MU1 | MU2 |\n");
+       PRINT_FW(cl_hw, "|------------------+-----+-----+-----|\n");
+       PRINT_FW(cl_hw, "|  BA Received     |%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].ba_received,
+                agg->mu_stats[CL_MU1_IDX].ba_received,
+                agg->mu_stats[CL_MU2_IDX].ba_received);
+       PRINT_FW(cl_hw, "|  --Unexpected BA |%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU1_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU2_IDX].unexpected_ba);
+       PRINT_FW(cl_hw, "|  --Cleared    BA |%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].clear_ba,
+                agg->mu_stats[CL_MU1_IDX].clear_ba,
+                agg->mu_stats[CL_MU2_IDX].clear_ba);
+       PRINT_FW(cl_hw, "|  --Invalid    BA |%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].invalid_ba,
+                agg->mu_stats[CL_MU1_IDX].invalid_ba,
+                agg->mu_stats[CL_MU2_IDX].invalid_ba);
+       PRINT_FW(cl_hw, "|  --Correct    BA |%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].correct_ba,
+                agg->mu_stats[CL_MU1_IDX].correct_ba,
+                agg->mu_stats[CL_MU2_IDX].correct_ba);
+       PRINT_FW(cl_hw, "|  BA not Received |%5u|%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].ba_no_received,
+                agg->mu_stats[CL_MU1_IDX].ba_no_received,
+                agg->mu_stats[CL_MU2_IDX].ba_no_received);
+       PRINT_FW(cl_hw, "--------------------------------------\n");
+#else
+       /* MU status statistics */
+       PRINT_FW(cl_hw, "--------------------\n");
+       PRINT_FW(cl_hw, "|            | MU1 |\n");
+       PRINT_FW(cl_hw, "|------------+-----|\n");
+       PRINT_FW(cl_hw, "|Chain count |%5u|\n",
+                agg->mu_stats[CL_MU1_IDX].chain_cnt);
+       PRINT_FW(cl_hw, "|Status count|%5u|\n",
+                agg->mu_stats[CL_MU1_IDX].status_cnt);
+       PRINT_FW(cl_hw, "--------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* MU agg-size statistics */
+       PRINT_FW(cl_hw, "------------------------\n");
+       PRINT_FW(cl_hw, "| agg size | MU0 | MU1 |\n");
+       PRINT_FW(cl_hw, "|----------+-----+-----|\n");
+       for (i = 1; i < DBG_STATS_MAX_AGG_SIZE; i++) {
+               if (agg->mu_agg_size_statistics[CL_MU0_IDX][i] ||
+                   agg->mu_agg_size_statistics[CL_MU1_IDX][i]) {
+                       PRINT_FW(cl_hw, "|%10u|%5u|%5u|\n",
+                                i,
+                                agg->mu_agg_size_statistics[CL_MU0_IDX][i],
+                                agg->mu_agg_size_statistics[CL_MU1_IDX][i]);
+               }
+       }
+       PRINT_FW(cl_hw, "------------------------\n");
+       PRINT_FW(cl_hw, "\n");
+
+       /* MU BA statistics */
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "| MU BA statistics | MU0 | MU1 |\n");
+       PRINT_FW(cl_hw, "|------------------+-----+-----|\n");
+       PRINT_FW(cl_hw, "|  BA Received     |%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].ba_received,
+                agg->mu_stats[CL_MU1_IDX].ba_received);
+       PRINT_FW(cl_hw, "|  --Unexpected BA |%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].unexpected_ba,
+                agg->mu_stats[CL_MU1_IDX].unexpected_ba);
+       PRINT_FW(cl_hw, "|  --Cleared    BA |%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].clear_ba,
+                agg->mu_stats[CL_MU1_IDX].clear_ba);
+       PRINT_FW(cl_hw, "|  --Invalid    BA |%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].invalid_ba,
+                agg->mu_stats[CL_MU1_IDX].invalid_ba);
+       PRINT_FW(cl_hw, "|  --Correct    BA |%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].correct_ba,
+                agg->mu_stats[CL_MU1_IDX].correct_ba);
+       PRINT_FW(cl_hw, "|  BA not Received |%5u|%5u|\n",
+                agg->mu_stats[CL_MU0_IDX].ba_no_received,
+                agg->mu_stats[CL_MU1_IDX].ba_no_received);
+       PRINT_FW(cl_hw, "--------------------------------\n");
+#endif
+}
+
+static void cl_print_bcn_stats(struct cl_hw *cl_hw, struct cl_bcn_statistics *bcn_stats)
+{
+       struct beacon_timing *bcn_timing_stats = &bcn_stats->beacon_timing;
+       struct beacon_counters *bcn_cnt_stats = &bcn_stats->beacon_counters;
+       struct bcn_backup_stats *bcn_backup_stats = &bcn_stats->bcn_backup_stats;
+       u32 avg_time_between_bcn = 0, avg_time_bcn_chain = 0;
+
+       if (bcn_cnt_stats->nof_time_intervals_between_beacons != 0)
+               avg_time_between_bcn = (bcn_timing_stats->total_bcn_time /
+                                       bcn_cnt_stats->nof_time_intervals_between_beacons);
+
+       if (bcn_cnt_stats->bcn_chain_total_cnt != 0)
+               avg_time_bcn_chain = ((bcn_timing_stats->bcn_chain_total_time) /
+                                     (bcn_cnt_stats->bcn_chain_total_cnt));
+
+       PRINT_FW(cl_hw, "----------------------------------------\n");
+       PRINT_FW(cl_hw, "Number of beacon flushed\n");
+       PRINT_FW(cl_hw, "+---------+-------------+--------------+\n");
+       PRINT_FW(cl_hw, "| pending | downloading | transmitting |\n");
+       PRINT_FW(cl_hw, "+---------+-------------+--------------+\n");
+       PRINT_FW(cl_hw, "|%-9u|%-13u|%-14u|\n",
+                bcn_cnt_stats->ce_txl_flushed_beacons[BCN_FLUSH_PENDING],
+                bcn_cnt_stats->ce_txl_flushed_beacons[BCN_FLUSH_DOWNLOADING],
+                bcn_cnt_stats->ce_txl_flushed_beacons[BCN_FLUSH_TRANSMITTING]);
+       PRINT_FW(cl_hw, "+---------+-------------+--------------+\n\n");
+
+       PRINT_FW(cl_hw, "----------------------------------------\n");
+       PRINT_FW(cl_hw, "Time between transmission of two beacons\n");
+       PRINT_FW(cl_hw, "+----------+----------+---------+----------------+\n");
+       PRINT_FW(cl_hw, "| min time | max time | bcn cnt | avg time[mSec] |\n");
+       PRINT_FW(cl_hw, "+----------+----------+---------+----------------+\n");
+       PRINT_FW(cl_hw, "|%-10u|%-10u|%-9u|%-16u|\n",
+                bcn_timing_stats->min_time_from_last_bcn,
+                bcn_timing_stats->max_time_from_last_bcn,
+                bcn_cnt_stats->total_cnt,
+                avg_time_between_bcn);
+       PRINT_FW(cl_hw, "+----------+----------+---------+----------------+\n\n");
+
+       PRINT_FW(cl_hw, "---------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, "Time of beacon until chain\n");
+       PRINT_FW(cl_hw, "+----------+----------+---------------+----------+\n");
+       PRINT_FW(cl_hw, "| min time | max time | bcn chain cnt | avg time |\n");
+       PRINT_FW(cl_hw, "+----------+----------+---------------+----------+\n");
+       PRINT_FW(cl_hw, "|%-10u|%-10u|%-15u|%-10u|\n",
+                bcn_timing_stats->bcn_chain_min_time,
+                bcn_timing_stats->bcn_chain_max_time,
+                bcn_cnt_stats->bcn_chain_total_cnt,
+                avg_time_bcn_chain);
+       PRINT_FW(cl_hw, "+----------+----------+---------------+----------+\n\n");
+
+       PRINT_FW(cl_hw, "---------------------------------------------------------------------\n");
+       PRINT_FW(cl_hw, " beacon pending-chain path max time = %u\n",
+                bcn_timing_stats->bcn_pending_2_chain_max_time);
+       PRINT_FW(cl_hw, " beacon pending-chain not in time count = %u\n",
+                bcn_cnt_stats->pending2chain_not_in_threshold_cnt);
+       PRINT_FW(cl_hw, " Max time until recievd beacon from driver = %u\n",
+                bcn_timing_stats->max_bcn_time_until_get_beacon_from_driver_in_tbtt);
+       PRINT_FW(cl_hw, " Total count of beacon flushed because didn't received in time = %u\n",
+                bcn_cnt_stats->bcn_time_from_driver_not_in_threshold_cnt);
+       PRINT_FW(cl_hw, " Max num of beacon not received from driver = %u\n",
+                bcn_cnt_stats->max_bcn_not_received_from_host);
+       PRINT_FW(cl_hw, "---------------------------------------------------------------------\n");
+
+       PRINT_FW(cl_hw, "+--------------------------------------+\n");
+       PRINT_FW(cl_hw, "|        Backup beacon stats           |\n");
+       PRINT_FW(cl_hw, "+------+------+---------+--------------+\n");
+       PRINT_FW(cl_hw, "| Used |  TX  | flushed | Max in a row |\n");
+       PRINT_FW(cl_hw, "+------+------+---------+--------------+\n");
+       PRINT_FW(cl_hw, "|%6u|%6u|%9u|%14u|\n",
+                bcn_backup_stats->bcn_backup_used_cnt,
+                bcn_backup_stats->bcn_backup_tx_cnt,
+                bcn_backup_stats->bcn_backup_flushed_cnt,
+                bcn_backup_stats->bcn_backup_max_used_in_arow_cnt);
+       PRINT_FW(cl_hw, "+------+------+---------+--------------+\n");
+}
+
+static void cl_print_rate_fallback_stats(struct cl_hw *cl_hw,
+                                        struct cl_rate_drop_statistics *stats)
+{
+       PRINT_FW(cl_hw, "\n");
+       PRINT_FW(cl_hw, "---------------------------\n");
+       PRINT_FW(cl_hw, "   Fallback statistics\n");
+       PRINT_FW(cl_hw, "---------------------------\n");
+       PRINT_FW(cl_hw, "ba_per_stats          = %u\n",
+                stats->drop_reason[AGG_TX_RATE_DROP_MAX_BA_PER_REACHED]);
+       PRINT_FW(cl_hw, "ba_not_received_stats = %u\n",
+                stats->drop_reason[AGG_TX_RATE_DROP_MAX_BA_NOT_RECEIVED_REACHED]);
+       PRINT_FW(cl_hw, "max_retry_reached     = %u\n",
+                stats->drop_reason[AGG_TX_RATE_DROP_MAX_RETRY_REACHED]);
+}
+
+static void cl_print_rx_stats_precent(struct cl_hw *cl_hw, const char *str, u32 x, u32 y)
+{
+       /*
+        * Example:
+        * x = 541, y = 19
+        * Result 28.4736
+        */
+       u32 integer = x / y;
+       u32 fraction = 10000 * (x - y * (x / y)) / y;
+
+       PRINT_FW(cl_hw, "%s = %u.%04u\n", str, integer, fraction);
+}
+
+static void cl_print_rx_stats(struct cl_hw *cl_hw, struct cl_rxl_statistics *rx_stats)
+{
+       int i, mu_idx, total_rx = 0;
+       enum format_mode fm;
+
+       PRINT_FW(cl_hw, "=========================================\n");
+       PRINT_FW(cl_hw, "        Global RX stats\n");
+       PRINT_FW(cl_hw, "=========================================\n");
+       PRINT_FW(cl_hw, "host rxelem not ready      = %u\n",
+                rx_stats->host_rxelem_not_ready_cnt);
+       PRINT_FW(cl_hw, "MSDU host rxelem not ready = %u\n",
+                rx_stats->msdu_host_rxelem_not_ready_cnt);
+       PRINT_FW(cl_hw, "MSDU dma pool not ready    = %u\n",
+                rx_stats->dma_rx_pool_not_ready_cnt);
+       PRINT_FW(cl_hw, "Percent of Rx CCA busy      = %u\n",
+                rx_stats->cca_busy_percent);
+       PRINT_FW(cl_hw, "Percent of Rx mine CCA busy = %u\n",
+                rx_stats->rx_mine_busy_percent);
+       PRINT_FW(cl_hw, "Percent of Tx mine busy     = %u\n",
+                rx_stats->tx_mine_busy_percent);
+       PRINT_FW(cl_hw, "\n");
+
+       PRINT_FW(cl_hw, "=== Rx Format ==\n");
+       for (fm = 0; fm < FORMATMOD_MAX; fm++)
+               if (rx_stats->stats_rx_format[fm])
+                       PRINT_FW(cl_hw, "Rx Format[%d] = %u\n", fm, rx_stats->stats_rx_format[fm]);
+
+       PRINT_FW(cl_hw, "=== Rx Decryption errors ==\n");
+       for (i = RHD_DECR_ICVFAIL_IDX; i < RHD_DECR_IDX_MAX; i++)
+               if (rx_stats->decrypt_err[i])
+                       PRINT_FW(cl_hw, "decrypt_err[%d] = %u\n", i, rx_stats->decrypt_err[i]);
+
+       /* RX prints */
+       for (mu_idx = 0; mu_idx < MU_UL_MAX; mu_idx++) {
+               PRINT_FW(cl_hw, "============================================\n");
+               PRINT_FW(cl_hw, "=====         RX MAC HW MU [%2d]       =====\n", mu_idx);
+               PRINT_FW(cl_hw, "============================================\n");
+               total_rx = rx_stats->total_rx_packets[mu_idx] +
+                       rx_stats->fcs_error_counter[mu_idx] +
+                       rx_stats->phy_error_counter[mu_idx] +
+                       rx_stats->ampdu_incorrect_received_counter[mu_idx] +
+                       rx_stats->delimiter_error_counter[mu_idx] +
+                       rx_stats->rx_fifo_overflow_err_cnt[mu_idx];
+
+               if (total_rx == 0)
+                       continue;
+
+               for (i = 0; i < MAX_HANDLED_FRM_TYPE; i++) {
+                       if (!rx_stats->emb_ll1_handled_frame_counter[mu_idx][i])
+                               continue;
+
+                       PRINT_FW(cl_hw, "emb_handled_packet[%d] - %u\n",
+                                i, rx_stats->emb_ll1_handled_frame_counter[mu_idx][i]);
+               }
+
+               PRINT_FW(cl_hw, "Total packets dropped (pckt_len > %u) %u\n",
+                        rx_stats->max_mpdu_data_len[mu_idx],
+                        rx_stats->rx_pckt_exceed_max_len_cnt[mu_idx]);
+               PRINT_FW(cl_hw, "Number of bad formated BA frames = %u\n",
+                        rx_stats->rx_pckt_bad_ba_statinfo_cnt[mu_idx]);
+               PRINT_FW(cl_hw, "Max occupancy list2 = %u\n",
+                        rx_stats->rhd_ll2_max_cnt[mu_idx]);
+               PRINT_FW(cl_hw, "Max occupancy list1 = %u\n",
+                        rx_stats->rhd_ll1_max_cnt[mu_idx]);
+               PRINT_FW(cl_hw, "\n");
+               PRINT_FW(cl_hw, "Total Qos MPDU received    = %u\n",
+                        rx_stats->total_rx_packets[mu_idx]);
+               PRINT_FW(cl_hw, "Total Aggregation received = %u\n",
+                        rx_stats->total_agg_packets[mu_idx]);
+               PRINT_FW(cl_hw, "Number of Rx Fifo Overflow = %u\n",
+                        rx_stats->rx_fifo_overflow_err_cnt[mu_idx]);
+               PRINT_FW(cl_hw, "Number of FCS ERROR        = %u\n",
+                        rx_stats->fcs_error_counter[mu_idx]);
+               PRINT_FW(cl_hw, "Number of PHY ERROR        = %u\n",
+                        rx_stats->phy_error_counter[mu_idx]);
+               PRINT_FW(cl_hw, "Number of AMPDUS           = %u\n",
+                        rx_stats->ampdu_received_counter[mu_idx]);
+               PRINT_FW(cl_hw, "Number of Incorrect AMPDUS = %u\n",
+                        rx_stats->ampdu_incorrect_received_counter[mu_idx]);
+               PRINT_FW(cl_hw, "Number of Delimiter errors = %u\n",
+                        rx_stats->delimiter_error_counter[mu_idx]);
+
+               if (rx_stats->total_rx_packets[mu_idx]) {
+                       u32 total_rx_packets = rx_stats->total_rx_packets[mu_idx] +
+                               rx_stats->rx_fifo_overflow_err_cnt[mu_idx] +
+                               rx_stats->fcs_error_counter[mu_idx] +
+                               rx_stats->phy_error_counter[mu_idx] +
+                               rx_stats->delimiter_error_counter[mu_idx];
+
+                       cl_print_rx_stats_precent(cl_hw,
+                                                 "Rx Fifo Overflow percent  ",
+                                                 100 * rx_stats->rx_fifo_overflow_err_cnt[mu_idx],
+                                                 total_rx_packets);
+                       cl_print_rx_stats_precent(cl_hw,
+                                                 "FCS Error percent         ",
+                                                 100 * rx_stats->fcs_error_counter[mu_idx],
+                                                 total_rx_packets);
+                       cl_print_rx_stats_precent(cl_hw,
+                                                 "Phy Error percent         ",
+                                                 100 * rx_stats->phy_error_counter[mu_idx],
+                                                 total_rx_packets);
+                       cl_print_rx_stats_precent(cl_hw,
+                                                 "Delimiter Error percent   ",
+                                                 100 * rx_stats->delimiter_error_counter[mu_idx],
+                                                 total_rx_packets);
+               }
+
+               PRINT_FW(cl_hw, "Current NAV value          = %u\n", rx_stats->nav_value[mu_idx]);
+
+               PRINT_FW(cl_hw, "\n");
+               PRINT_FW(cl_hw, "Rx LL split stats: 1st LL interrupts = %u\n",
+                        rx_stats->counter_timer_trigger_ll1[mu_idx]);
+               PRINT_FW(cl_hw, "Rx LL split stats: 2nd LL interrupts = %u\n",
+                        rx_stats->counter_timer_trigger_ll2[mu_idx]);
+               PRINT_FW(cl_hw, "Number of incorrect format mode received = %u\n",
+                        rx_stats->rx_incorrect_format_mode[mu_idx]);
+
+               for (i = 0; i < RX_CLASSIFICATION_MAX; i++) {
+                       if (!rx_stats->rx_class_counter[mu_idx][i])
+                               continue;
+
+                       PRINT_FW(cl_hw, "Rx classification rules stats: Rx rule%d= %u\n",
+                                i, rx_stats->rx_class_counter[mu_idx][i]);
+               }
+
+               if (rx_stats->rx_class_int_counter[mu_idx])
+                       PRINT_FW(cl_hw, "Rx classification interrupts rules = %u\n",
+                                rx_stats->rx_class_int_counter[mu_idx]);
+
+               PRINT_FW(cl_hw, "\n");
+               PRINT_FW(cl_hw, "Rx Implicit BF statistics:      = %u\n",
+                        rx_stats->rx_imp_bf_counter[mu_idx]);
+               PRINT_FW(cl_hw, "Rx Implicit BF interrupts stats = %u\n",
+                        rx_stats->rx_imp_bf_int_counter[mu_idx]);
+               PRINT_FW(cl_hw, "RXM STATISTICS\n");
+               PRINT_FW(cl_hw, "rxm_stats_overflow      = %u\n",
+                        rx_stats->rxm_stats_overflow[mu_idx]);
+               PRINT_FW(cl_hw, "rx_incorrect_format_mode= %u\n",
+                        rx_stats->rx_incorrect_format_mode[mu_idx]);
+               PRINT_FW(cl_hw, "correct_received_mpdu   = %u\n",
+                        rx_stats->correct_received_mpdu[mu_idx]);
+               PRINT_FW(cl_hw, "incorrect_received_mpdu = %u\n",
+                        rx_stats->incorrect_received_mpdu[mu_idx]);
+               PRINT_FW(cl_hw, "discarded_mpdu          = %u\n",
+                        rx_stats->discarded_mpdu[mu_idx]);
+               PRINT_FW(cl_hw, "incorrect_delimiter     = %u\n",
+                        rx_stats->incorrect_delimiter[mu_idx]);
+               PRINT_FW(cl_hw, "rts_bar_cnt             = %u\n",
+                        rx_stats->rts_bar_cnt[mu_idx]);
+               PRINT_FW(cl_hw, "rxm_mpdu_cnt            = %u\n",
+                        rx_stats->rxm_mpdu_cnt[mu_idx]);
+
+               if (rx_stats->rxm_mpdu_cnt[mu_idx]) {
+                       PRINT_FW(cl_hw, "rxm_rule0_match        = %u\n",
+                                rx_stats->rxm_rule0_match[mu_idx]);
+                       PRINT_FW(cl_hw, "rxm_rule1_match        = %u\n",
+                                rx_stats->rxm_rule1_match[mu_idx]);
+                       PRINT_FW(cl_hw, "rxm_rule2_match        = %u\n",
+                                rx_stats->rxm_rule2_match[mu_idx]);
+                       PRINT_FW(cl_hw, "rxm_rule3_match        = %u\n",
+                                rx_stats->rxm_rule3_match[mu_idx]);
+                       PRINT_FW(cl_hw, "rxm_rule4_match        = %u\n",
+                                rx_stats->rxm_rule4_match[mu_idx]);
+                       PRINT_FW(cl_hw, "rxm_rule5_match        = %u\n",
+                                rx_stats->rxm_rule5_match[mu_idx]);
+                       PRINT_FW(cl_hw, "rxm_rule6_match        = %u\n",
+                                rx_stats->rxm_rule6_match[mu_idx]);
+                       PRINT_FW(cl_hw, "rxm_default_rule_match = %u\n",
+                                rx_stats->rxm_default_rule_match[mu_idx]);
+                       PRINT_FW(cl_hw, "RXM amsdu stat not supported. use iwcl stats instead\n");
+               }
+
+               /* RX AMSDU prints */
+               PRINT_FW(cl_hw, "\n");
+               PRINT_FW(cl_hw, "RX AMSDU STATS\n");
+
+               PRINT_FW(cl_hw, "AMSDU RX cnt  = %u\n",
+                        rx_stats->stats_tot_rx_amsdu_cnt[mu_idx]);
+
+               for (i = 0; i < ARRAY_SIZE(rx_stats->stats_rx_amsdu_cnt[mu_idx]); i++)
+                       if (rx_stats->stats_rx_amsdu_cnt[mu_idx][i])
+                               PRINT_FW(cl_hw, "A-MSDU of %d = %u\n",
+                                        i + 1, rx_stats->stats_rx_amsdu_cnt[mu_idx][i]);
+
+               PRINT_FW(cl_hw, "A-MSDU RX errors:\n");
+               for (i = 0; i < AMSDU_DEAGGREGATION_ERR_MAX; i++)
+                       if (rx_stats->stats_rx_amsdu_err[mu_idx][i])
+                               PRINT_FW(cl_hw, " err_id[%d] = %u\n",
+                                        i, rx_stats->stats_rx_amsdu_err[mu_idx][i]);
+       }
+
+       PRINT_FW(cl_hw, "Frequency offset:\n");
+       for (i = 0; i < FREQ_OFFSET_TABLE_IDX_MAX; i++)
+               if (rx_stats->frequency_offset[i])
+                       PRINT_FW(cl_hw, "frequency_offset = %u\n", rx_stats->frequency_offset[i]);
+}
+
+static void cl_print_trigger_flow_stats(struct cl_hw *cl_hw,
+                                       struct cl_trigger_flow_statistics *tf_stats)
+{
+       u16 idx;
+       struct cl_rx_trigger_based_stats *tb_stats = &cl_hw->tb_stats;
+
+       if (!tb_stats->enable) {
+               PRINT_FW(cl_hw, "WARNING: Trigger based statistics are disabled!\n");
+               return;
+       }
+
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "     Trigger flow statistics\n");
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "Sent trigger frames\n");
+       PRINT_FW(cl_hw, "---------------|---AC0---|---AC1---|---AC2---|---AC3---|\n");
+       PRINT_FW(cl_hw, "BASIC TRIGGER: |%9u|%9u|%9u|%9u|\n",
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BASIC_TRIGGER_TYPE][AC_BK],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BASIC_TRIGGER_TYPE][AC_BE],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BASIC_TRIGGER_TYPE][AC_VI],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BASIC_TRIGGER_TYPE][AC_VO]);
+       PRINT_FW(cl_hw, "BSRP:          |%9u|%9u|%9u|%9u|\n",
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BSRP_TYPE][AC_BK],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BSRP_TYPE][AC_BE],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BSRP_TYPE][AC_VI],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BSRP_TYPE][AC_VO]);
+       PRINT_FW(cl_hw, "BFRP:          |%9u|%9u|%9u|%9u|\n",
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BFRP_TYPE][AC_BK],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BFRP_TYPE][AC_BE],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BFRP_TYPE][AC_VI],
+                tf_stats->single_trigger_sent[TRIGGER_FLOW_BFRP_TYPE][AC_VO]);
+       PRINT_FW(cl_hw, "HTP FAILURE:   |%9u|%9u|%9u|%9u|\n",
+                tf_stats->htp_rx_failure[AC_BK],
+                tf_stats->htp_rx_failure[AC_BE],
+                tf_stats->htp_rx_failure[AC_VI],
+                tf_stats->htp_rx_failure[AC_VO]);
+
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "TRIGGER BASED MPDUs PER MAC HW\n");
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       tf_stats->trigger_based_mpdu[0] = tb_stats->total;
+
+       for (idx = 1; idx < MU_UL_MAX; idx++)
+               tf_stats->trigger_based_mpdu[0] -= tf_stats->trigger_based_mpdu[idx];
+
+       for (idx = 0; idx < MU_UL_MAX; idx++)
+               PRINT_FW(cl_hw, "MAC HW %u - %10u\n", idx, tf_stats->trigger_based_mpdu[idx]);
+
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "TRIGGER BASED AGGREGATIONS SIZE\n");
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "|-SIZE-|---TB AGGS---|\n");
+
+       for (idx = 1; idx < DBG_STATS_MAX_AGG_SIZE; idx++) {
+               if (tb_stats->data[idx] == 0)
+                       continue;
+
+               PRINT_FW(cl_hw, "| %4u |%13u|\n", idx, tb_stats->data[idx]);
+       }
+
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "TRIGGER BASED QOS NULL AGGR SIZE\n");
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "|-SIZE-|---TB AGGS---|\n");
+
+       for (idx = 1; idx < TID_MAX + 1; idx++)
+               if (tb_stats->qos_null[idx] > 0)
+                       PRINT_FW(cl_hw, "| %4u |%13u|\n", idx, tb_stats->qos_null[idx]);
+
+       if (tb_stats->qos_null[TID_MAX + 1] > 0)
+               PRINT_FW(cl_hw, "|  >8  |%13u|\n", tb_stats->qos_null[TID_MAX + 1]);
+}
+
+static void cl_print_dyn_calib_stats(struct cl_hw *cl_hw,
+                                    struct cl_dyn_calib_statistics *dyn_cal_stats)
+{
+       u8 i, j;
+
+       PRINT_FW(cl_hw, "--------------------------------\n");
+       PRINT_FW(cl_hw, "Dynamic Calibration Information\n");
+       PRINT_FW(cl_hw, "--------------------------------\n\n");
+
+       PRINT_FW(cl_hw, "Default Dynamic Calibation Value = %u\n\n",
+                dyn_cal_stats->default_dyn_cal_val);
+
+       for (i = dyn_cal_stats->dyn_cal_debug_info_ix, j = 0;
+            j < DYN_CAL_DEBUG_NUM_ITER;
+            (i = ((i + 1) % 3)), j++) {
+               struct dyn_cal_debug_info_t *dyn_cal_debug_info =
+                       &dyn_cal_stats->dyn_cal_debug_info[i];
+
+               if (dyn_cal_stats->is_multi_client_mode)
+                       PRINT_FW(cl_hw,
+                                "calib_num = %u, min_val = %d, max_val = %d, min_config = %u, "
+                                "max_config = %u, curr_config = %u, new_config = %u\n",
+                                dyn_cal_debug_info->calib_num,
+                                (s32)dyn_cal_debug_info->dyn_cal_min_val,
+                                (s32)dyn_cal_debug_info->dyn_cal_max_val,
+                                dyn_cal_debug_info->min_config,
+                                dyn_cal_debug_info->max_config,
+                                dyn_cal_debug_info->curr_config,
+                                dyn_cal_debug_info->new_config);
+               else
+                       PRINT_FW(cl_hw,
+                                "calib_num = %u, iter_num = %u, config_val_prev = %u, "
+                                "measured_val = %u, new_config_val = %u\n",
+                                dyn_cal_debug_info->calib_num,
+                                dyn_cal_debug_info->iter_num,
+                                dyn_cal_debug_info->curr_config,
+                                dyn_cal_debug_info->measured_val,
+                                dyn_cal_debug_info->new_config);
+       }
+
+       if (dyn_cal_stats->mac_phy_sync_err_cnt)
+               PRINT_FW(cl_hw, "mac_phy_sync_err_cnt = %u\n\n",
+                        dyn_cal_stats->mac_phy_sync_err_cnt);
+
+       PRINT_FW(cl_hw, "\n-----------------------------------------\n\n");
+}
+
+static void cl_print_bf_stats(struct cl_hw *cl_hw, struct cl_bf_statistics *bf_stats)
+{
+       u32 idx;
+       bool should_print = false;
+       u16 *tx_bf_data_err;
+
+       for (idx = 0; idx < BF_DB_MAX; idx++)
+               if (bf_stats->print_active_free_list == bf_stats->stats_data[idx].is_active_list) {
+                       should_print = true;
+                       break;
+               }
+
+       if (!should_print)
+               return;
+
+       /* Info phase 1 */
+       PRINT_FW(cl_hw, "List of non active BFs:\n");
+       PRINT_FW(cl_hw, "============================\n");
+       PRINT_FW(cl_hw, "BF_CTRL statistics\n");
+       PRINT_FW(cl_hw, "+-----+----+----+-------+-------+----------------+-----------------+--------------+---------------+-----------------+---------------+--------------+------------+-------+\n");
+       PRINT_FW(cl_hw, "|INDEX|#NDP|#BFP|#SU BFR|#MU BFR|#BFR_BW_MISMATCH|#BFR_NSS_MISMATCH|#SOUNDING_CHBW|#TOKEN_MISMATCH|#NDP_NDPA_TX_DROP|#BFR_RX_ERR_ACK|#BFR SEGMENTED|#RESOURCE_NA|STA_IDX|\n");
+       PRINT_FW(cl_hw, "+-----+----+----+-------+-------+----------------+-----------------+--------------+---------------+-----------------+---------------+--------------+------------+-------+\n");
+
+       for (idx = 0; idx < BF_DB_MAX; idx++) {
+               if (bf_stats->print_active_free_list != bf_stats->stats_data[idx].is_active_list)
+                       continue;
+
+               PRINT_FW(cl_hw,
+                        "|%5u|%4u|%4u|%7u|%7u|%16u|%17u|%14u|%15u|%17u|%15u|%14u|%12u|%7u|\n",
+                        idx,
+                        bf_stats->stats_data[idx].dbg.ndp_cnt,
+                        bf_stats->stats_data[idx].dbg.bfp_cnt,
+                        bf_stats->stats_data[idx].dbg.su_bfr_cnt,
+                        bf_stats->stats_data[idx].dbg.mu_bfr_cnt,
+                        bf_stats->stats_data[idx].dbg.bf_invalid_cnt[BFR_RX_ERR_BW_MISMATCH],
+                        bf_stats->stats_data[idx].dbg.bf_invalid_cnt[BFR_RX_ERR_NSS_MISMATCH],
+                        bf_stats->stats_data[idx].dbg.bf_invalid_cnt[BFR_RX_ERR_SOUNDING_CHBW],
+                        bf_stats->stats_data[idx].dbg.bf_invalid_cnt[BFR_RX_ERR_TOKEN_MISMATCH],
+                        bf_stats->stats_data[idx].dbg.bf_invalid_cnt[BFR_RX_ERR_NDP_DROP],
+                        bf_stats->stats_data[idx].dbg.bf_invalid_cnt[BFR_RX_ERR_MISS_ACK],
+                        bf_stats->stats_data[idx].dbg.bf_invalid_cnt[BFR_SEGMENTED_DROP],
+                        bf_stats->stats_data[idx].dbg.bf_invalid_cnt[BFR_RX_ERR_RESOURCE_NA],
+                        bf_stats->stats_data[idx].sta_idx);
+       }
+
+       PRINT_FW(cl_hw, "+-----+----+----+-------+-------+----------------+-----------------+--------------+---------------+-----------------+---------------+--------------+------------+-------+\n");
+
+       /* Info phase 2 */
+       PRINT_FW(cl_hw, "statistic BF DATA FRAMESs:\n");
+       PRINT_FW(cl_hw, "============================\n");
+       PRINT_FW(cl_hw, "BF_CTRL statistics\n");
+       PRINT_FW(cl_hw, "+-----+-----------+------------+-------------+-----------------+----------------+-----------------+-----------+-----------+----------+------------------+-----------------+-------+\n");
+       PRINT_FW(cl_hw, "|INDEX|#ACTIVE_IDX|#PASSIVE_IDX|#ERR_BFR_MISS|#ERR_BFR_OUTDATED|#ERR_BW_MISMATCH|#ERR_NSS_MISMATCH|#BF_DATA_OK|#BUFF_IN_PS|#REL_IN_PS|#BUFF_RESOURCE_ERR|#REL_RESOURCE_ERR|STA_IDX|\n");
+       PRINT_FW(cl_hw, "+-----+-----------+------------+-------------+-----------------+----------------+-----------------+-----------+-----------+----------+------------------+-----------------+-------+\n");
+
+       for (idx = 0; idx < BF_DB_MAX; idx++) {
+               if (bf_stats->print_active_free_list != bf_stats->stats_data[idx].is_active_list)
+                       continue;
+
+               tx_bf_data_err = bf_stats->stats_data[idx].dbg.tx_bf_data_err;
+
+               PRINT_FW(cl_hw,
+                        "|%5u|%11u|%12u|%13u|%17u|%16u|%17u|%11u|%11u|%10u|%18u|%17u|%7u|\n",
+                        idx,
+                        bf_stats->stats_data[idx].active_dsp_idx,
+                        bf_stats->stats_data[idx].passive_dsp_idx,
+                        tx_bf_data_err[TX_BF_DATA_ERR_BFR_MISS],
+                        tx_bf_data_err[TX_BF_DATA_ERR_BFR_OUTDATED],
+                        tx_bf_data_err[TX_BF_DATA_ERR_MISMATCH_BW],
+                        tx_bf_data_err[TX_BF_DATA_ERR_MISMATCH_NSS],
+                        tx_bf_data_err[TX_BF_DATA_OK],
+                        tx_bf_data_err[TX_BF_DATA_BUFFERED_PS_STA],
+                        tx_bf_data_err[TX_BF_DATA_RELEASED_PS_STA],
+                        tx_bf_data_err[TX_BF_DATA_BUFFERED_RESOURCE_ERR],
+                        tx_bf_data_err[TX_BF_DATA_RELEASED_RESOURCE_ERR],
+                        bf_stats->stats_data[idx].sta_idx);
+       }
+
+       PRINT_FW(cl_hw, "+-----+-----------+------------+-------------+-----------------+----------------+-----------------+-----------+-----------+----------+------------------+-----------------+-------+\n");
+}
+
+static void cl_print_stats_handler(struct work_struct *ws)
+{
+       struct cl_print_stats_work *stats_work = container_of(ws, struct cl_print_stats_work, ws);
+       struct cl_hw *cl_hw = stats_work->cl_hw;
+       u32 dbg_info_type = stats_work->dbg_info_type;
+
+       if (dbg_info_type == DBG_INFO_TX_STATS) {
+               struct cl_txl_statistics *tx_stats =
+                       &(((struct dbg_info *)cl_hw->dbginfo.buf)->u.tx_stats);
+
+               cl_print_tx_stats(cl_hw, tx_stats);
+               cl_print_tx_mu_stats(cl_hw, tx_stats);
+       } else if (dbg_info_type == DBG_INFO_BCN_STATS) {
+               struct cl_bcn_statistics *bcn_stats =
+                       &(((struct dbg_info *)cl_hw->dbginfo.buf)->u.bcn_stats);
+
+               cl_print_bcn_stats(cl_hw, bcn_stats);
+       } else if (dbg_info_type == DBG_INFO_RX_STATS) {
+               struct cl_rxl_statistics *rx_stats =
+                       &(((struct dbg_info *)cl_hw->dbginfo.buf)->u.rx_stats);
+
+               cl_print_rx_stats(cl_hw, rx_stats);
+       } else if (dbg_info_type == DBG_INFO_DYN_CAL_STATS) {
+               struct cl_dyn_calib_statistics *dyn_cal_stats =
+                       &(((struct dbg_info *)cl_hw->dbginfo.buf)->u.dyn_calib_stats);
+
+               cl_print_dyn_calib_stats(cl_hw, dyn_cal_stats);
+       } else if (dbg_info_type == DBG_INFO_RATE_FALLBACK_STATS) {
+               struct cl_rate_drop_statistics *agg_rate_drop_stats =
+                       &(((struct dbg_info *)cl_hw->dbginfo.buf)->u.rate_drop_stats);
+
+               cl_print_rate_fallback_stats(cl_hw, agg_rate_drop_stats);
+       } else if (dbg_info_type == DBG_INFO_BF) {
+               struct cl_bf_statistics *bf_stats =
+                       &(((struct dbg_info *)cl_hw->dbginfo.buf)->u.bf_stats);
+
+               cl_print_bf_stats(cl_hw, bf_stats);
+       } else if (dbg_info_type == DBG_INFO_TRIGGER_FLOW) {
+               struct cl_trigger_flow_statistics *tf_stats =
+                       &(((struct dbg_info *)cl_hw->dbginfo.buf)->u.trigger_flow_stats);
+
+               cl_print_trigger_flow_stats(cl_hw, tf_stats);
+       }
+
+#ifdef CONFIG_CL_PCIE
+       cl_ipc_dbginfobuf_push(cl_hw->ipc_env, cl_hw->dbginfo.dma_addr);
+#endif
+       kfree(stats_work);
+}
+
+static void cl_schedule_print_stats(struct cl_hw *cl_hw, u32 dbg_info_type)
+{
+       struct cl_print_stats_work *stats_work =
+               kzalloc(sizeof(*stats_work), GFP_ATOMIC);
+
+       if (stats_work) {
+               INIT_WORK(&stats_work->ws, cl_print_stats_handler);
+               stats_work->cl_hw = cl_hw;
+               stats_work->dbg_info_type = dbg_info_type;
+
+               /* Schedule work, the work will be executed in the background */
+               queue_work(cl_hw->drv_workqueue, &stats_work->ws);
+       } else {
+               cl_dbg_err(cl_hw, "stats_work allocation failed\n");
+       }
+}
+
+void cl_fw_dbg_handler(struct cl_hw *cl_hw)
+{
+       struct dbg_info *dbg_info = NULL;
+
+       /* Function called upon DBG_INFO_IND message reception. */
+       dma_sync_single_for_device(cl_hw->chip->dev, cl_hw->dbginfo.dma_addr,
+                                  cl_hw->dbginfo.bufsz, DMA_FROM_DEVICE);
+       dbg_info = (struct dbg_info *)cl_hw->dbginfo.buf;
+
+       if (dbg_info->u.type == DBG_INFO_DUMP) {
+               cl_dbg_info(cl_hw, "type %u): dump received\n",
+                           cl_hw->dbginfo.buf->u.dump.general_data.error_type);
+               cl_coredump_trigger(cl_hw);
+       } else if (dbg_info->u.type < DBG_INFO_MAX) {
+               cl_schedule_print_stats(cl_hw, dbg_info->u.type);
+       } else {
+               cl_dbg_warn(cl_hw, "Debug info wrong type - %u\n", dbg_info->u.type);
+       }
+}
+
+static int cl_fw_dbg_cli_help(struct cl_hw *cl_hw)
+{
+       char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       int err = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       snprintf(buf, PAGE_SIZE,
+                "fw usage:\n"
+                "-a : Trigger assert error (echo ASSERT_ERR > errsim)\n"
+                "-b : Trigger assert recovery (echo 1 > test_mode)\n"
+                "-d : Set trigger-based debug statistics [0-dis/1-en]\n"
+                "-m : Trigger firmware dump (echo 1 > mactrace)\n"
+                "-s : Print statistics (echo param > stat_print)\n"
+                "-t : Test mode command (cmd + 0 to 5 parameters)\n");
+
+       err = cl_vendor_reply(cl_hw, buf, strlen(buf));
+       kfree(buf);
+
+       return err;
+}
+
+int cl_fw_dbg_cli(struct cl_hw *cl_hw, struct cli_params *cli_params)
+{
+       u32 expected_params = 0;
+       bool assert_err = false;
+       bool assert_rec = false;
+       bool dbg_tb_stats = false;
+       bool mactrace = false;
+       bool stat_print = false;
+       bool test_mode = false;
+
+       switch (cli_params->option) {
+       case 'a':
+               assert_err = true;
+               expected_params = 0;
+               break;
+       case 'b':
+               assert_rec = true;
+               expected_params = 0;
+               break;
+       case 'd':
+               dbg_tb_stats = true;
+               expected_params = 1;
+               break;
+       case 'm':
+               mactrace = true;
+               expected_params = 0;
+               break;
+       case 's':
+               stat_print = true;
+               expected_params = 1;
+               break;
+       case 't':
+               test_mode = true;
+               break;
+       case '?':
+               return cl_fw_dbg_cli_help(cl_hw);
+       default:
+               cl_dbg_err(cl_hw, "Illegal option (%c) - try '?' for help\n", cli_params->option);
+               goto out_err;
+       }
+
+       if ((expected_params != cli_params->num_params) && !test_mode) {
+               cl_dbg_err(cl_hw, "Wrong number of arguments (expected %u) (actual %u)\n",
+                          expected_params, cli_params->num_params);
+               goto out_err;
+       }
+
+       if (assert_err) {
+               cl_msg_tx_key_del(cl_hw, 0xFF);
+               return 0;
+       }
+
+       if (assert_rec) {
+               u32 params[TEST_MODE_PARAM_MAX + 1] = {1, 0, 0, 0, 0, 0};
+
+               cl_msg_tx_dbg_test_mode(cl_hw, params);
+               return 0;
+       }
+
+       if (dbg_tb_stats) {
+               cl_hw->tb_stats.enable = (bool)cli_params->params[0];
+               pr_debug("TB statistics %s\n", cl_hw->tb_stats.enable ? "enable" : "disable");
+               return 0;
+       }
+
+       if (mactrace) {
+               cl_msg_tx_dbg_trigger(cl_hw, "Force trigger");
+               return 0;
+       }
+
+       if (stat_print) {
+               u32 bitmap = (u32)cli_params->params[0];
+
+               cl_msg_tx_dbg_print_stats(cl_hw, bitmap, 0, 0, 0, 0);
+               return 0;
+       }
+
+       if (test_mode) {
+               u32 params[TEST_MODE_PARAM_MAX + 1] = {0};
+               u8 i;
+
+               if (cli_params->num_params == 0 ||
+                   cli_params->num_params > TEST_MODE_PARAM_MAX + 1) {
+                       cl_dbg_err(cl_hw, "Test mode expects cmd + 0 to 5 parameters\n");
+                       goto out_err;
+               }
+
+               for (i = 0; i < cli_params->num_params; i++)
+                       params[i] = (u32)cli_params->params[i];
+
+               cl_msg_tx_dbg_test_mode(cl_hw, params);
+               return 0;
+       }
+
+out_err:
+       return -EIO;
+}
+
+static void cl_dbg_dump_check_params(struct cl_hw *cl_hw,
+                                    u8 *buf, int bufsz, int *pos,
+                                    struct dbg_error_trace_info_drv *dump)
+{
+       int is_mismatch = false;
+       struct dbg_meta_data *dbg_metadata = &dump->common_info.dbg_metadata;
+
+       if (dbg_metadata->lmac_req_buf_size != sizeof(struct dbg_error_trace_info_drv) ||
+           dbg_metadata->physical_queue_cnt != CL_MAX_BA_PHYSICAL_QUEUE_CNT ||
+           dbg_metadata->agg_index_max != AGG_IDX_MAX ||
+           dbg_metadata->ce_ac_max != CE_AC_MAX ||
+           dbg_metadata->mu_user_max != MU_MAX_STREAMS ||
+           dbg_metadata->txl_exch_trace_depth != DBG_TXL_FRAME_EXCH_TRACE_DEPTH ||
+           dbg_metadata->mac_hw_regs_max != HAL_MACHW_REG_NUM ||
+           dbg_metadata->phy_hw_regs_max != PHY_HW_DBG_REGS_CNT)
+               is_mismatch = true;
+
+       if (is_mismatch) {
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "\nWarning!!!!\n");
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "DBG metadata mismatch bwtween FW & DRV!!!!\n");
+       }
+
+       if (dbg_metadata->lmac_req_buf_size != (u32)(sizeof(struct dbg_error_trace_info_drv)))
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "FW buf size       %u expected %u\n",
+                                 dbg_metadata->lmac_req_buf_size,
+                                 (u32)(sizeof(struct dbg_error_trace_info_drv)));
+
+       if (dbg_metadata->physical_queue_cnt != CL_MAX_BA_PHYSICAL_QUEUE_CNT)
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "physical queue cn %u expected %u\n",
+                                 dbg_metadata->physical_queue_cnt,
+                                 CL_MAX_BA_PHYSICAL_QUEUE_CNT);
+
+       if (dbg_metadata->agg_index_max != AGG_IDX_MAX)
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "agg idx max       %u expected %u\n",
+                                 dbg_metadata->agg_index_max, AGG_IDX_MAX);
+
+       if (dbg_metadata->ce_ac_max != CE_AC_MAX)
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "ac max            %u expected %u\n",
+                                 dbg_metadata->ce_ac_max, CE_AC_MAX);
+
+       if (dbg_metadata->mu_user_max != MU_MAX_STREAMS)
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "MU MAX            %u expected %u\n",
+                                 dbg_metadata->mu_user_max, MU_MAX_STREAMS);
+
+       if (dbg_metadata->txl_exch_trace_depth != DBG_TXL_FRAME_EXCH_TRACE_DEPTH)
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "txl trace depth   %u expected %u\n",
+                                 dbg_metadata->txl_exch_trace_depth,
+                                 DBG_TXL_FRAME_EXCH_TRACE_DEPTH);
+
+       if (dbg_metadata->mac_hw_regs_max != HAL_MACHW_REG_NUM)
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "MAC HW regs cnt   %u expected %u\n",
+                                 dbg_metadata->mac_hw_regs_max,
+                                 HAL_MACHW_REG_NUM);
+
+       if (dbg_metadata->phy_hw_regs_max != PHY_HW_DBG_REGS_CNT)
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "PHY HW regs       %u expected %u\n",
+                                 dbg_metadata->phy_hw_regs_max,
+                                 PHY_HW_DBG_REGS_CNT);
+}
+
+static void cl_dbg_policy_table_print(struct cl_hw *cl_hw,
+                                     u8 *buf, int bufsz, int *pos,
+                                     struct tx_policy_tbl *policy_table_ptr,
+                                     u32 policy_table_addr)
+{
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "================================================="
+                         "= Policy Table 0x%x ============================="
+                         "============================\n",
+                        policy_table_addr);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| upatterntx         = 0x%08x| phycntrlinfo1      = 0x%08x"
+                         "| phycntrlinfo2     = 0x%08x| maccntrlinfo1      = 0x%08x|\n",
+                         policy_table_ptr->upatterntx,
+                         policy_table_ptr->phycntrlinfo1,
+                         policy_table_ptr->phycntrlinfo2,
+                         policy_table_ptr->maccntrlinfo1);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| maccntrlinfo2      = 0x%08x| ratecntrlinfo[0]   = 0x%08x"
+                         "| ratecntrlinfo[1]  = 0x%08x| ratecntrlinfo[2]   = 0x%08x|\n",
+                         policy_table_ptr->maccntrlinfo2,
+                         policy_table_ptr->ratecntrlinfo[0],
+                         policy_table_ptr->ratecntrlinfo[1],
+                         policy_table_ptr->ratecntrlinfo[2]);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| ratecntrlinfo[3]   = 0x%08x| phycntrlinfo3      = 0x%08x"
+                         "| phycntrlinfo4     = 0x%08x| phycntrlinfo5      = 0x%08x|\n",
+                         policy_table_ptr->ratecntrlinfo[3],
+                         policy_table_ptr->phycntrlinfo3,
+                         policy_table_ptr->phycntrlinfo4,
+                         policy_table_ptr->phycntrlinfo5);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| stationinfo        = 0x%08x| ratecntrlinfohe[0] = 0x%08x"
+                         "| ratecntrlinfohe[1]= 0x%08x| ratecntrlinfohe[2] = 0x%08x|\n",
+                         policy_table_ptr->stationinfo,
+                         policy_table_ptr->ratecntrlinfohe[0],
+                         policy_table_ptr->ratecntrlinfohe[1],
+                         policy_table_ptr->ratecntrlinfohe[2]);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| ratecntrlinfohe[3] = 0x%08x| maccntrlinfo3      = 0x%08x"
+                         "| triggercommoninfo = 0x%08x| trigperuserinfo[0] = 0x%08x|\n",
+                         policy_table_ptr->ratecntrlinfohe[3],
+                         policy_table_ptr->maccntrlinfo3,
+                         policy_table_ptr->triggercommoninfo,
+                         policy_table_ptr->triggerperuserinfo[0]);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| trigperuserinfo[1] = 0x%08x| trigperuserinfo[2] = 0x%08x"
+                         "| trigperuserinfo[3]= 0x%08x| trigperuserinfo[4] = 0x%08x|\n",
+                         policy_table_ptr->triggerperuserinfo[1],
+                         policy_table_ptr->triggerperuserinfo[2],
+                         policy_table_ptr->triggerperuserinfo[3],
+                         policy_table_ptr->triggerperuserinfo[4]);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| trigperuserinfo[5] = 0x%08x| trigperuserinfo[6] = 0x%08x"
+                         "| trigperuserinfo[7]= 0x%08x|\n",
+                         policy_table_ptr->triggerperuserinfo[5],
+                         policy_table_ptr->triggerperuserinfo[6],
+                         policy_table_ptr->triggerperuserinfo[7]);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| triginforallocau0u3= 0x%08x| triginforallocau4u7= 0x%08x |\n",
+                         policy_table_ptr->triggerinforuallocationu0u3,
+                         policy_table_ptr->triggerinforuallocationu4u7);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "===================================================="
+                         "===================================================="
+                         "============================\n\n");
+}
+
+static void cl_dbg_thd_print(struct cl_hw *cl_hw,
+                            u8 *buf, int bufsz, int *pos,
+                            struct tx_hd *thd_ptr, u32 thd_addr)
+{
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "=============================================="
+                         "=       THD 0x%x      ========================"
+                         "=======================\n",
+                         thd_addr);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| upatterntx   = 0x%08x | nextfrmexseq_ptr = 0x%08x "
+                         "| nextmpdudesc_ptr = 0x%08x | first_pbd_ptr = 0x%08x|\n",
+                        thd_ptr->upatterntx,
+                        thd_ptr->nextfrmexseq_ptr,
+                        thd_ptr->nextmpdudesc_ptr,
+                        thd_ptr->first_pbd_ptr);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| datastartptr = 0x%08x | dataendptr       = 0x%08x "
+                         "| frmlen           = 0x%08x | spacinginfo   = 0x%08x|\n",
+                         thd_ptr->datastartptr,
+                         thd_ptr->dataendptr,
+                         thd_ptr->frmlen,
+                         thd_ptr->spacinginfo);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| phyctrlinfo1 = 0x%08x | policyentryaddr  = 0x%08x "
+                         "| macctrlinfo1     = 0x%08x | macctrlinfo2  = 0x%08x|\n",
+                         thd_ptr->phyctrlinfo1,
+                         thd_ptr->policyentryaddr,
+                         thd_ptr->macctrlinfo1,
+                         thd_ptr->macctrlinfo2);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| statinfo     = 0x%08x | phyctrlinfo2     = 0x%08x |\n",
+                         thd_ptr->statinfo,
+                         thd_ptr->phyctrlinfo2);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "=============================================="
+                         "=============================================="
+                         "=============================\n\n");
+}
+
+static void cl_dbg_pbd_print(struct cl_hw *cl_hw,
+                            u8 *buf, int bufsz, int *pos,
+                            struct tx_pbd *pbd_ptr, u32 pbd_addr)
+{
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                        "==============================================="
+                        "===      PBD 0x%x     ========================="
+                        "========================\n",
+                        pbd_addr);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| upatterntx = 0x%08x | next = 0x%08x| datastartptr = 0x%08x"
+                         "| dataendptr = 0x%08x| bufctrlinfo = 0x%08x|\n",
+                         pbd_ptr->upatterntx,
+                         pbd_ptr->next,
+                         pbd_ptr->datastartptr,
+                         pbd_ptr->dataendptr,
+                         pbd_ptr->bufctrlinfo);
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "=============================================="
+                         "=============================================="
+                         "================================\n\n");
+}
+
+static void cl_dbg_dump_txm_regs(struct cl_hw *cl_hw,
+                                u8 *buf, int bufsz, int *pos,
+                                struct dbg_error_trace_info_drv *dump)
+{
+       int stream_idx;
+       struct dbg_fw_info *fw_info = &dump->common_info.fw_info;
+
+       for (stream_idx = 0; stream_idx < ARRAY_SIZE(fw_info->txlist_info_agg); ++stream_idx) {
+               struct dbg_txm_regs *txm_regs;
+
+               if (!fw_info->txlist_info_agg[stream_idx].curr_session_idx)
+                       continue;
+
+               txm_regs = &dump->common_info.hw_info.txm_regs[stream_idx];
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "#### TXM stream %u Registers\n", stream_idx);
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "|--------------------------------------------------------------------|\n");
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "| HW state = %3u FW state = %3u SPX state = %3u free buff state = %3u|\n",
+                                 txm_regs->hw_state, txm_regs->fw_state,
+                                 txm_regs->spx_state, txm_regs->free_buf_state);
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "| MPDU cnt = %3u LLI cnt  = %3u LLI done mpdu num = %3u  reason = %3u|\n",
+                                 txm_regs->mpdu_cnt, txm_regs->lli_cnt,
+                                 txm_regs->lli_done_mpdu_num, txm_regs->lli_done_reason);
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "| active bytes   = 0x%08x prefetch bytes = 0x%08x            |\n",
+                                 txm_regs->active_bytes, txm_regs->prefetch_bytes);
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "| last THD: addr = 0x%x MPDU number = %3u underrun cnt = %3u   |\n",
+                                 txm_regs->last_thd_done_addr,
+                                 txm_regs->last_thd_done_mpdu_num, txm_regs->underrun_cnt);
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                "|--------------------------------------------------------------------|\n\n");
+       }
+}
+
+static void cl_dbg_dump_machw_regs(struct cl_hw *cl_hw,
+                                  u8 *buf, int bufsz, int *pos,
+                                  struct dbg_error_trace_info_drv *dump)
+{
+       u8 i = 0, mu_idx;
+       struct dbg_hw_reg_info *hw_info = &dump->common_info.hw_info;
+
+       const char *hal_machw_reg_str[HAL_MACHW_REG_NUM] = {
+               [HAL_MACHW_AGGR_STATUS]                    = "AGGR_STATUS",
+               [HAL_MACHW_DEBUG_HWSM_1]                   = "DBG_HWSM_1",
+               [HAL_MACHW_DEBUG_HWSM_2]                   = "DBG_HWSM_2",
+               [HAL_MACHW_DEBUG_HWSM_3]                   = "DBG_HWSM_3",
+               [HAL_MACHW_DMA_STATUS_1]                   = "DMA_STATUS_1",
+               [HAL_MACHW_DMA_STATUS_2]                   = "DMA_STATUS_2",
+               [HAL_MACHW_DMA_STATUS_3]                   = "DMA_STATUS_3",
+               [HAL_MACHW_DMA_STATUS_4]                   = "DMA_STATUS_4",
+               [HAL_MACHW_RX_HEADER_H_PTR]                = "RX_HEADER_HEAD_PTR",
+               [HAL_MACHW_RX_PAYLOAD_H_PTR]               = "RX_PAYLOAD_HEAD_PTR",
+               [HAL_MACHW_DEBUG_BCN_S_PTR]                = "DBG_BCN_STATUS_PTR",
+               [HAL_MACHW_DEBUG_AC0_S_PTR]                = "DBG_AC_0_STATUS_PTR",
+               [HAL_MACHW_DEBUG_AC1_S_PTR]                = "DBG_AC_1_STATUS_PTR",
+               [HAL_MACHW_DEBUG_AC2_S_PTR]                = "DBG_AC_2_STATUS_PTR",
+               [HAL_MACHW_DEBUG_AC3_S_PTR]                = "DBG_AC_3_STATUS_PTR",
+               [HAL_MACHW_DEBUG_HTP_S_PTR]                = "DBG_HTP_STATUS_PTR",
+               [HAL_MACHW_DEBUG_TX_C_PTR]                 = "DBG_TX_CURRENT_PTR",
+               [HAL_MACHW_DEBUG_RX_HDR_C_PTR]             = "DBG_RX_HDR_CURRENT_PTR",
+               [HAL_MACHW_DEBUG_RX_PAY_C_PTR]             = "DBG_RX_PAY_CURRENT_PTR",
+               [HAL_MACHW_MU0_TX_POWER_LEVEL_DELTA_1]     = "DBG_MU0_TX_PWR_LEVEL_DELTA_1",
+               [HAL_MACHW_MU0_TX_POWER_LEVEL_DELTA_2]     = "DBG_MU0_TX_PWR_LEVEL_DELTA_2",
+               [HAL_MACHW_POWER_BW_CALIB_FACTOR]          = "DBG_TX_POWER_BW_CALIB_FACTOR",
+               [HAL_MACHW_TX_POWER_ANTENNA_FACTOR_1_ADDR] = "DBG_tX_POWER_ANT_FACTOR_1",
+               [HAL_MACHW_TX_POWER_ANTENNA_FACTOR_2_ADDR] = "DBG_TX_POWER_ANT_FACTOR_2"
+       };
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos, "\n##### MAC HW regs ####\n");
+
+       for (i = 0; i < ARRAY_SIZE(hw_info->mac_hw_reg); ++i)
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "%30s = 0x%08x\n",
+                                 hal_machw_reg_str[i], hw_info->mac_hw_reg[i]);
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#########################\n\n");
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "############# MAC HW Secondary FSMs #############\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|---------------------------------------------------------|\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                        "|MU IDX|%12s|%12s|%12s|%11s|\n",
+                         hal_machw_reg_str[HAL_MACHW_AGGR_STATUS],
+                         hal_machw_reg_str[HAL_MACHW_DEBUG_HWSM_1],
+                         hal_machw_reg_str[HAL_MACHW_DEBUG_HWSM_2],
+                         hal_machw_reg_str[HAL_MACHW_DEBUG_HWSM_3]);
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|---------------------------------------------------------|\n");
+
+       for (i = 0; i < ARRAY_SIZE(hw_info->mac_hw_sec_fsm); ++i) {
+               mu_idx = CL_MU1_IDX + i;
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "| MU %u | 0x%08x | 0x%08x | 0x%08x | 0x%08x|\n",
+                                 mu_idx,
+                                 hw_info->mac_hw_sec_fsm[i][HAL_MACHW_AGGR_STATUS],
+                                 hw_info->mac_hw_sec_fsm[i][HAL_MACHW_DEBUG_HWSM_1],
+                                 hw_info->mac_hw_sec_fsm[i][HAL_MACHW_DEBUG_HWSM_2],
+                                 hw_info->mac_hw_sec_fsm[i][HAL_MACHW_DEBUG_HWSM_3]);
+       }
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|---------------------------------------------------------|\n\n");
+
+       /* Write THD data if valid */
+       for (i = HAL_MACHW_DEBUG_BCN_S_PTR; i <= HAL_MACHW_DEBUG_TX_C_PTR; ++i)
+               if (hw_info->mac_hw_reg[i]) {
+                       u8 thd_idx = i - HAL_MACHW_DEBUG_BCN_S_PTR;
+
+                       cl_dbg_thd_print(cl_hw, buf, bufsz, pos,
+                                        &dump->machw_thd_info.thd[thd_idx],
+                                        hw_info->mac_hw_reg[i]);
+               }
+
+       cl_dbg_dump_txm_regs(cl_hw, buf, bufsz, pos, dump);
+}
+
+static void cl_dbg_dump_phyhw_regs(struct cl_hw *cl_hw,
+                                  u8 *buf, int bufsz, int *pos,
+                                  struct dbg_error_trace_info_drv *dump)
+{
+       int i = 0;
+       const char *phy_hw_mpu_reg_str[PHY_HW_DBG_REGS_CNT] = {
+               [MPU_COMMON_FORMAT]       = "MPU_COMMON_FORMAT",
+               [MPU_COMMON_FIELD_CTRL]   = "MPU_COMMON_FIELD_CTRL",
+               [MPU_COMMON_LEGACY_INFO]  = "MPU_COMMON_LEGACY_INFO",
+               [MPU_COMMON_COMMON_CFG_1] = "MPU_COMMON_COMMON_CFG_1",
+               [MPU_COMMON_COMMON_CFG_2] = "MPU_COMMON_COMMON_CFG_2",
+               [MPU_COMMON_COMMON_CFG_3] = "MPU_COMMON_COMMON_CFG_3",
+               [MPU_COMMON_HE_CFG_1]     = "MPU_COMMON_HE_CFG_1",
+               [MPU_COMMON_HE_CFG_2]     = "MPU_COMMON_HE_CFG_2",
+               [MPU_COMMON_INT_STAT_RAW] = "MPU_COMMON_INT_STAT_RAW",
+               [RIU_CCAGENSTAT]          = "RIU_CCAGENSTAT",
+       };
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos, "##### PHY HW regs ####\n");
+
+       for (i = 0; i < ARRAY_SIZE(dump->common_info.hw_info.phy_mpu_hw_reg); ++i)
+               *pos += scnprintf(buf + *pos, bufsz - *pos, "%25s = 0x%08x\n",
+                                 phy_hw_mpu_reg_str[i],
+                                 dump->common_info.hw_info.phy_mpu_hw_reg[i]);
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos, "#########################\n\n");
+}
+
+static void cl_dbg_dump_ac_info(struct cl_hw *cl_hw,
+                               u8 *buf, int bufsz, int *pos,
+                               struct dbg_error_trace_info_drv *dump)
+{
+       int i = 0;
+       struct dbg_fw_info *fw_info = &dump->common_info.fw_info;
+       const char *fw_tx_state_str[CE_TXL_TX_PATH_MAX] = {
+               [CE_TXL_TX_PATH_IDLE]                  = "PATH_IDLE",
+               [CE_TXL_TX_PATH_START]                 = "PATH_START",
+               [CE_TXL_TX_PATH_POST_START_DOWNLOAD]   = "POST_START_DOWNLOAD",
+               [CE_TXL_TX_PATH_TX_DATA_DOWNLOADING]   = "TX_DATA_DOWNLOADING",
+               [CE_TXL_TX_PATH_MU_RECOVERY]           = "MU_RECOVERY",
+               [CE_TXL_TX_PATH_LAST_DOWNLOADING]      = "LAST_DOWNLOADING",
+               [CE_TXL_TX_PATH_NEXT_SESSION_PREPARED] = "NEXT_SESSION_PREP",
+               [CE_TXL_TX_PATH_MU_NEXT_JOB_READY]     = "MU_NEXT_JOB_READY",
+       };
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "\n#####  Per AC info  ####\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|--------------------------------------------------------|\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|AC|MU|session|phys queue|check_state|   TX path state   |\n");
+
+       for (i = 0; i < ARRAY_SIZE(fw_info->ac_info); ++i) {
+               u32 mu_idx = (i >= IPC_TX_QUEUE_CNT) ? (i - IPC_TX_QUEUE_CNT + 1) : 0;
+               u32 session_idx = (fw_info->ac_info[i].active_session != FW_DBG_INVALID_SESSION) ?
+                       fw_info->ac_info[i].active_session : 0;
+
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "|--+--+-------+----------+-----------+-------------------|\n");
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "|%2u|%2u|%7u|%10u|%11u|%19s|\n",
+                                 i,
+                                 mu_idx,
+                                 session_idx,
+                                 fw_info->ac_info[i].physical_queue_idx,
+                                 fw_info->ac_info[i].chk_state,
+                                 fw_tx_state_str[fw_info->ac_info[i].tx_path_state]);
+       }
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|--------------------------------------------------------|\n");
+}
+
+static void cl_dbg_dump_single_tx_list_info(struct cl_hw *cl_hw,
+                                           u8 *buf, int bufsz, int *pos,
+                                           struct dbg_error_trace_info_drv *dump)
+{
+       int i = 0;
+       struct dbg_fw_info *fw_info = &dump->common_info.fw_info;
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "\n##### Singles txdesc lists info ####\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|----|---------|-------------|--------------|\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "| AC | pending | downloading | transmitting |\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|----|---------|-------------|--------------|\n");
+
+       for (i = 0; i < ARRAY_SIZE(fw_info->txlist_info_singles); ++i) {
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "|%4u|%9u|%13u|%14u|\n",
+                                 i,
+                                 fw_info->txlist_info_singles[i].pending_cnt,
+                                 fw_info->txlist_info_singles[i].download_cnt,
+                                 fw_info->txlist_info_singles[i].transmit_cnt);
+
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "|----|---------|-------------|--------------|\n");
+       }
+}
+
+static void cl_dbg_dump_agg_tx_list_info(struct cl_hw *cl_hw,
+                                        u8 *buf, int bufsz, int *pos,
+                                        struct dbg_error_trace_info_drv *dump)
+{
+       int i = 0;
+       u32 mu_idx;
+       struct dbg_fw_info *fw_info = &dump->common_info.fw_info;
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "\n##### Agg txdesc lists info ####\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|----------------------------------------------------------------|\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|idx|mu|session|pending|download|transmit|wait4ba|next   |next   |\n");
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|   |  |       |       |        |        |       |session|pending|\n");
+
+       for (i = 0; i < ARRAY_SIZE(fw_info->txlist_info_agg); ++i) {
+               mu_idx = ((i >= AGG_MU1_IDX) && (i <= AGG_MU7_IDX)) ? (i - AGG_MU1_IDX + 1) : 0;
+
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "|---+--+-------+-------+--------+--------+--"
+                                 "-----+-------+-------|\n");
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "|%3u|%2u|%7u|%7u|%8u|%8u|%7u|%7u|%7u|\n",
+                                 i,
+                                 mu_idx,
+                                 fw_info->txlist_info_agg[i].curr_session_idx,
+                                 fw_info->txlist_info_agg[i].pending_cnt,
+                                 fw_info->txlist_info_agg[i].download_cnt,
+                                 fw_info->txlist_info_agg[i].transmit_cnt,
+                                 fw_info->txlist_info_agg[i].wait_for_ba_cnt,
+                                 fw_info->txlist_info_agg[i].next_session_idx,
+                                fw_info->txlist_info_agg[i].next_pending_cnt);
+       }
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "|----------------------------------------------------------------|\n");
+}
+
+static void cl_dbg_dump_thd_chains_info(struct cl_hw *cl_hw,
+                                       u8 *buf, int bufsz, int *pos,
+                                       struct dbg_error_trace_info_drv *dump, u8 ac)
+{
+       int i = 0;
+       u32 data_offset = 0;
+       struct dbg_thd_chains_info *chain_info = &dump->thd_chains_info[ac];
+       struct dbg_thd_chains_data *chain_data = &dump->thd_chains_data[ac];
+       struct tx_hd *hd;
+       struct tx_policy_tbl *policy_tbl;
+       struct tx_pbd *pbd;
+
+       while (chain_info->type_array[i] != DBG_CHAINS_INFO_EMPTY) {
+               switch (chain_info->type_array[i]) {
+               case DBG_CHAINS_INFO_THD:
+                       hd = (struct tx_hd *)&chain_data->data[data_offset];
+                       cl_dbg_thd_print(cl_hw, buf, bufsz, pos, hd,
+                                        chain_info->elem_address[i]);
+                       data_offset += sizeof(struct tx_hd);
+                       break;
+
+               case DBG_CHAINS_INFO_PT:
+                       policy_tbl = (struct tx_policy_tbl *)&chain_data->data[data_offset];
+                       cl_dbg_policy_table_print(cl_hw, buf, bufsz, pos,
+                                                 policy_tbl,
+                                                 chain_info->elem_address[i]);
+                       data_offset += sizeof(struct tx_policy_tbl);
+                       break;
+
+               case DBG_CHAINS_INFO_PBD:
+                       pbd = (struct tx_pbd *)&chain_data->data[data_offset];
+                       cl_dbg_pbd_print(cl_hw, buf, bufsz, pos, pbd,
+                                        chain_info->elem_address[i]);
+                       data_offset += sizeof(struct tx_pbd);
+                       break;
+
+               default:
+                       return;
+               }
+
+               i++;
+               if (i >= DBG_CHAINS_INFO_ELEM_CNT)
+                       break;
+       }
+}
+
+static void cl_dbg_dump_agg_thd_info(struct cl_hw *cl_hw,
+                                    u8 *buf, int bufsz, int *pos,
+                                    struct dbg_error_trace_info_drv *dump,
+                                    u8 ac, u8 mu_idx)
+{
+       u8 agg_idx = (ac < AGG_MU1_IDX) ? ac : (mu_idx + AGG_MU1_IDX - 1);
+       u32 addr = dump->common_info.agg_thds_addr[agg_idx].rts_cts_thd_addr;
+
+       if (addr) {
+               /* RTS CTS THD print */
+               *pos += scnprintf(buf + *pos, bufsz - *pos, "\n  RTS CTS THD 0x%x\n", addr);
+               cl_dbg_thd_print(cl_hw, buf, bufsz, pos,
+                                &dump->agg_thd_info[agg_idx].rts_cts_thd, addr);
+       }
+
+       addr = dump->common_info.agg_thds_addr[agg_idx].athd_addr;
+       if (addr) {
+               /* ATHD print */
+               *pos += scnprintf(buf + *pos, bufsz - *pos, "\n  ATHD 0x%x\n", addr);
+               cl_dbg_thd_print(cl_hw, buf, bufsz, pos,
+                                &dump->agg_thd_info[agg_idx].athd, addr);
+       }
+
+       addr = dump->common_info.agg_thds_addr[agg_idx].policy_table_addr;
+       if (addr) {
+               /* Policy Table print */
+               *pos += scnprintf(buf + *pos, bufsz - *pos, "  Policy Table 0x%x\n", addr);
+               cl_dbg_policy_table_print(cl_hw, buf, bufsz, pos,
+                                         &dump->agg_thd_info[agg_idx].policy_table,
+                                         addr);
+       }
+
+       addr = dump->common_info.agg_thds_addr[agg_idx].tf_thd_addr;
+       if (addr) {
+               /* TF-THD print */
+               *pos += scnprintf(buf + *pos, bufsz - *pos, "  TF-THD 0x%x\n", addr);
+               cl_dbg_thd_print(cl_hw, buf, bufsz, pos,
+                                &dump->agg_thd_info[agg_idx].tf_thd, addr);
+       }
+
+       cl_dbg_dump_thd_chains_info(cl_hw, buf, bufsz, pos, dump, ac);
+
+       addr = dump->common_info.agg_thds_addr[agg_idx].bar_thd_addr;
+       if (addr) {
+               /* BAR THD print */
+               *pos += scnprintf(buf + *pos, bufsz - *pos, "  BAR THD 0x%x\n", addr);
+               cl_dbg_thd_print(cl_hw, buf, bufsz, pos,
+                                &dump->agg_thd_info[agg_idx].bar_thd, addr);
+       }
+}
+
+static void cl_dbg_dump_thd_info(struct cl_hw *cl_hw,
+                                u8 *buf, int bufsz, int *pos,
+                                struct dbg_error_trace_info_drv *dump,
+                                u8 ac, u8 mu_idx)
+{
+       u32 session_idx = dump->common_info.fw_info.ac_info[ac].active_session;
+
+       if (session_idx != FW_DBG_INVALID_SESSION) {
+               bool is_agg = ((mu_idx > 0) || (session_idx >= IPC_TX_QUEUE_CNT)) ? true : false;
+
+               if (is_agg)
+                       cl_dbg_dump_agg_thd_info(cl_hw, buf, bufsz, pos, dump, ac, mu_idx);
+               else
+                       cl_dbg_dump_thd_chains_info(cl_hw, buf, bufsz, pos, dump, ac);
+       }
+}
+
+static void cl_dbg_dump_tx_trace_info(struct cl_hw *cl_hw,
+                                     u8 *buf, int bufsz, int *pos,
+                                     struct dbg_error_trace_info_drv *dump)
+{
+       int i = 0;
+       const char *fw_tx_frame_type_str[CL_MAX_FRM_TYPE] = {
+               [SING_FRM_TYPE]             = "MPDU",
+               [AGG_FRM_TYPE]              = "AMPDU",
+               [AGG_NEXT_IN_TXOP_FRM_TYPE] = "TXOP",
+               [INT_FRM_TYPE]              = "INTERNAL",
+               [BCN_FRM_TYPE]              = "BCN",
+               [MU_FRM_TYPE]               = "MU_AMPDU",
+               [FRM_TYPE_BASIC_TRIGGER]    = "BASIC_TF",
+               [FRM_TYPE_MU_BAR_TRIGGER]   = "MU_BAR",
+               [BCK_BCN_TYPE]              = "BCN_BCK",
+               [QOS_NULL]                  = "QOSNULL",
+               [AGG_TB]                    = "AGG_TB",
+               [RTS_TYPE]                  = "RTS_FW",
+               [CTS_TYPE]                  = "CTS_FW",
+               [TB_SINGLE_FRM_TYPE]        = "TB_SMPDU",
+               [TF_AMPDU_TYPE]             = "TF_AMPDU"
+       };
+
+       *pos += scnprintf(buf + *pos,
+                         bufsz - *pos,
+                         "\n#### TX Trace ####\n");
+
+       for (i = 0; i < ARRAY_SIZE(dump->common_info.fw_info.txl_ac_chain_trace); ++i) {
+               u8 trace_idx = 0, table_idx = 0;
+               u32 mu_idx;
+               struct dbg_txl_ac_chain_trace *trace_ptr =
+                       &dump->common_info.fw_info.txl_ac_chain_trace[i];
+               struct cl_dbg_txl_chain_info *data;
+
+               if (trace_ptr->next_chain_index == 0)
+                       table_idx = DBG_TXL_FRAME_EXCH_TRACE_DEPTH - 1;
+               else
+                       table_idx = trace_ptr->next_chain_index - 1;
+
+               data = &trace_ptr->data[table_idx];
+
+               if (data->count == 0)
+                       continue;
+
+               mu_idx = (i >= IPC_TX_QUEUE_CNT) ? (i - IPC_TX_QUEUE_CNT + 1) : 0;
+
+               *pos += scnprintf(buf + *pos, bufsz - *pos, "\n AC %u MU idx %u:\n", i, mu_idx);
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "|========|========|==========|==========|=========="
+                                 "|======|==========|==========|=====|======="
+                                 "|======|=========|=======|==========|\n"
+                                 "|#PPDU   | Type   |First THD | Last THD | Prev THD "
+                                 "|Req BW| PTalbe   |PTalbe_HE |queue|Length "
+                                 "|#MPDU |Chosen BW|TX time| txstatus |\n"
+                                 "|========|========|==========|==========|=========="
+                                 "|======|==========|==========|=====|======="
+                                 "|======|=========|=======|==========|\n");
+
+               for (trace_idx = 0; trace_idx < DBG_TXL_FRAME_EXCH_TRACE_DEPTH; ++trace_idx) {
+                       *pos += scnprintf(buf + *pos,
+                                         bufsz - *pos,
+                                         "|%8u|%8s|0x%08x|0x%08x|0x%08x|%6u|0x%08x"
+                                         "|0x%08x|%5u|%7u|%6u|%9u|%7u|0x%08x|\n",
+                                         data->count,
+                                         fw_tx_frame_type_str[data->frm_type],
+                                         data->first_thd_ptr,
+                                         data->last_thd_ptr,
+                                         data->prev_thd_ptr,
+                                         data->reqbw,
+                                         data->rate_ctrl_info,
+                                         data->rate_ctrl_info_he,
+                                         data->ce_txq_idx,
+                                         data->length,
+                                         data->mpdu_count,
+                                         data->chbw,
+                                         data->tx_time,
+                                         data->txstatus);
+
+                       if (!table_idx)
+                               table_idx = DBG_TXL_FRAME_EXCH_TRACE_DEPTH - 1;
+                       else
+                               table_idx--;
+
+                       data = &trace_ptr->data[table_idx];
+               }
+
+               *pos += scnprintf(buf + *pos,
+                                 bufsz - *pos,
+                                 "|========|========|==========|==========|==="
+                                 "=======|======|==========|==========|=====|="
+                                 "======|======|=========|=======|==========|\n");
+
+               cl_dbg_dump_thd_info(cl_hw, buf, bufsz, pos, dump, i, mu_idx);
+       }
+}
+
+static void cl_dbg_dump_error_info(struct cl_hw *cl_hw,
+                                  u8 *buf, int bufsz, int *pos,
+                                  struct dbg_error_trace_info_drv *trace)
+{
+       struct dbg_print_ind *ind = &trace->common_info.error_info;
+       const char *assert_string;
+       u16 file_id = le16_to_cpu(ind->file_id);
+       u16 line = le16_to_cpu(ind->line);
+       u16 has_param = le16_to_cpu(ind->has_param);
+       u32 param = has_param ? le32_to_cpu(ind->param) : 0;
+
+       if (file_id && line) {
+               *pos += scnprintf(buf + *pos,
+                                bufsz - *pos,
+                                "ASSERT_TCV%u @ FILE=%hu LINE=%hu param=0x%08X\n",
+                                cl_hw->idx, file_id, line, param);
+
+               /* Get assert string */
+               assert_string = cl_dbgfile_get_msg_txt(&cl_hw->dbg_data, file_id, line);
+               if (!assert_string)
+                       assert_string = "ASSERT STRING NOT FOUND";
+
+               *pos += scnprintf(buf + *pos,
+                                 bufsz - *pos,
+                                 "%s\n", assert_string);
+       } else {
+               struct dbg_info *dbg_info = (struct dbg_info *)cl_hw->dbginfo.buf;
+
+               *pos += snprintf(buf + *pos,
+                                bufsz - *pos,
+                                "%s\n", dbg_info->u.dump.general_data.error);
+       }
+}
+
+static void cl_dbg_dump_fw_trace_info(struct cl_hw *cl_hw,
+                                     u8 *buf, int bufsz, int *pos,
+                                     struct dbg_error_trace_info_drv *dump)
+{
+       int i = 0;
+
+       *pos += scnprintf(buf + *pos,
+                         bufsz - *pos,
+                         "\n###   FW trace dump   ###\n"
+                         "------------------------------------------------------"
+                         "-----------------------------------\n"
+                         "|idx|   String        | value 1  | value 2  | value 3 "
+                         "| value 4  | value 5  | value 6  |\n"
+                         "|---+-----------------+----------+----------+---------"
+                         "-+----------+----------+----------|\n");
+
+       for (i = 0; i < ARRAY_SIZE(dump->common_info.fw_info.fw_trace); ++i) {
+               u8 dbg_idx = (dump->common_info.fw_info.fw_trace_idx + i) % DBG_FW_TRACE_SIZE;
+               struct dbg_fw_trace *trace = &dump->common_info.fw_info.fw_trace[dbg_idx];
+               char *str = trace->string_ptr ? trace->string_char : "NULL";
+
+               *pos += scnprintf(buf + *pos,
+                                 bufsz - *pos,
+                                 "|%3u|%17s|0x%08x|0x%08x|0x%08x|0x%08x|0x%08x|0x%08x|\n",
+                                 i,
+                                 str,
+                                 trace->var_1,
+                                 trace->var_2,
+                                 trace->var_3,
+                                 trace->var_4,
+                                 trace->var_5,
+                                 trace->var_6);
+       }
+
+       *pos += scnprintf(buf + *pos,
+                         bufsz - *pos,
+                         "----------------------------------------------------"
+                         "-------------------------------------\n");
+}
+
+static int cl_dbg_dump_host_descr(struct cl_hw *cl_hw,
+                                 u8 *buf, int bufsz, int *pos)
+{
+       struct new_utsname *nu = init_utsname();
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#### KERNEL ####\n"
+                         "release: %s\n"
+                         "version: %s\n"
+                         "machine: %s\n",
+                         nu->release,
+                         nu->version,
+                         nu->machine);
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#### CPUs ####\n"
+                         "num online  : %d\n"
+                         "num possible: %d\n"
+                         "num present : %d\n"
+                         "num active  : %d\n",
+                         num_online_cpus(),
+                         num_possible_cpus(),
+                         num_present_cpus(),
+                         num_active_cpus());
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#### ENDIANNESS ####\n"
+                         "LE (byte) : %u\n"
+                         "LE (bits) : %u\n"
+                         "BE (byte) : %u\n"
+                         "BE (bits) : %u\n",
+                         cl_are_host_bytes_le(),
+                         cl_are_host_bits_le(),
+                         cl_are_host_bytes_be(),
+                         cl_are_host_bits_be());
+       return 0;
+}
+
+static int cl_dbg_dump_chip_descr(struct cl_hw *cl_hw,
+                                 u8 *buf, int bufsz, int *pos)
+{
+       struct cl_version_db *vd = &cl_hw->version_db;
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#### BASE ####\n"
+                         "chip : %u\n"
+                         "TCV  : %u\n"
+                         "bus  : %u\n",
+                         cl_hw->chip->idx,
+                         cl_hw->tcv_idx,
+                         cl_hw->chip->bus_type);
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#### VERSIONS ####\n"
+                         "drv     : %s\n"
+                         "FW      : %s\n"
+                         "DSP     : 0x%-.8X\n"
+                         "RFIC SW : %u\n"
+                         "RFIC HW : 0x%X\n",
+                         vd->drv,
+                         vd->fw,
+                         vd->dsp,
+                         vd->rfic_sw,
+                         vd->rfic_hw);
+       /* TODO: AGC info */
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#### STATE ####\n"
+                         "recoveries : %u\n"
+                         "DRV flags  : %lu\n"
+                         "TCV-0 en   : %u\n"
+                         "TCV-1 en   : %u\n",
+                         cl_hw->fw_recovery_cntr,
+                         cl_hw->drv_flags,
+                         cl_chip_is_tcv0_enabled(cl_hw->chip),
+                         cl_chip_is_tcv1_enabled(cl_hw->chip));
+       return 0;
+}
+
+static int cl_dbg_dump_ela_descr(struct cl_hw *cl_hw,
+                                u8 *buf, int bufsz, int *pos)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       struct cl_ela_db *ed = &chip->ela_db;
+       int ret = 0;
+
+       if (cl_ela_is_on(chip)) {
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "#### CONF SOURCE ####\n"
+                                 "ELA mode: %s #\n",
+                                 chip->conf->ce_ela_mode);
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "#### CONF LIFETIME ####\n"
+                                 "adaptations  : %u #\n"
+                                 "applications : %u #\n"
+                                 "error state  : %d #\n",
+                                 ed->stats.adaptations_cnt,
+                                 ed->stats.applications_cnt,
+                                 ed->error_state);
+       } else {
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "#### DISABLED ####\n");
+       }
+       return ret;
+}
+
+static int cl_dbg_dump_raw_lcu_conf(struct cl_hw *cl_hw,
+                                   u8 *buf, int bufsz, int *pos)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       struct cl_ela_db *ed = &chip->ela_db;
+       int ret = 0;
+
+       if (cl_ela_is_on(chip) && ed->raw_lcu_config)
+               *pos += scnprintf(buf + *pos, bufsz - *pos, "%s", ed->raw_lcu_config);
+       else
+               ret = -ENODATA;
+       return ret;
+}
+
+static int cl_dbg_dump_adapted_lcu_conf(struct cl_hw *cl_hw,
+                                       u8 *buf, int bufsz, int *pos)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       struct cl_ela_db *ed = &chip->ela_db;
+       struct cl_lcu_cmd *cmd = NULL, *cmd_tmp = NULL;
+       int ret = 0;
+
+       if (cl_ela_is_on(chip)) {
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "#### CONF SOURCE ####\n"
+                                 "# %s #\n",
+                                 cl_ela_lcu_config_name(chip));
+               *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                 "#### CONF COMMANDS ####\n");
+
+               list_for_each_entry_safe(cmd, cmd_tmp, &ed->cmd_head, cmd_list)
+                       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                                         "%s 0x%X 0x%X\n",
+                                         cl_ela_lcu_cmd_str(cmd->type),
+                                         cmd->offset,
+                                         cmd->value);
+       } else {
+               ret = -ENODATA;
+       }
+       return ret;
+}
+
+static int cl_dbg_dump_la_mem(struct cl_hw *cl_hw,
+                             u8 *buf, int bufsz, int *pos,
+                             int idx, struct dbg_info *dbg_info)
+{
+       size_t la_size = 0;
+
+       if (ARRAY_SIZE(dbg_info->u.dump.la_mem) < idx + 1)
+               return -EINVAL;
+
+       la_size = ARRAY_SIZE(dbg_info->u.dump.la_mem[idx]);
+       if (la_size > (bufsz - *pos))
+               return -ENOBUFS;
+
+       memcpy(buf + *pos, &dbg_info->u.dump.la_mem[idx], la_size);
+       *pos += la_size;
+
+       return 0;
+}
+
+static int cl_dbg_dump_la_conf(struct cl_hw *cl_hw,
+                              u8 *buf, int bufsz, int *pos,
+                              int idx, struct dbg_debug_info_tag *gdata)
+{
+       size_t la_size = 0;
+
+       if (ARRAY_SIZE(gdata->la_conf) < idx + 1)
+               return -EINVAL;
+
+       la_size = sizeof(gdata->la_conf[idx]);
+       if (la_size > (bufsz - *pos))
+               return -ENOBUFS;
+
+       memcpy(buf + *pos, &gdata->la_conf[idx], la_size);
+       *pos += la_size;
+
+       return 0;
+}
+
+static int cl_dbg_dump_mac_diags(struct cl_hw *cl_hw,
+                                u8 *buf, int bufsz, int *pos,
+                                struct dbg_debug_info_tag *gdata)
+{
+       size_t la_size = ARRAY_SIZE(gdata->diags_mac);
+
+       if (la_size > (bufsz - *pos))
+               return -ENOBUFS;
+
+       memcpy(buf + *pos, &gdata->diags_mac, la_size);
+       *pos += la_size;
+
+       return 0;
+}
+
+static int cl_dbg_dump_hw_diags(struct cl_hw *cl_hw,
+                               u8 *buf, int bufsz, int *pos,
+                               struct dbg_debug_info_tag *gdata)
+{
+       *pos += scnprintf(buf + *pos, bufsz - *pos, "%08X\n", gdata->hw_diag);
+
+       return 0;
+}
+
+static int cl_dbg_dump_sw_diags(struct cl_hw *cl_hw,
+                               u8 *buf, int bufsz, int *pos,
+                               struct dbg_debug_info_tag *gdata)
+{
+       size_t la_size = min_t(size_t, ARRAY_SIZE(gdata->sw_diag),
+                              gdata->sw_diag_len);
+
+       if (la_size > (bufsz - *pos))
+               return -ENOBUFS;
+
+       memcpy(buf + *pos, &gdata->sw_diag, la_size);
+       *pos += la_size;
+
+       return 0;
+}
+
+static int cl_dbg_dump_chan_info(struct cl_hw *cl_hw,
+                                u8 *buf, int bufsz, int *pos,
+                                struct dbg_debug_info_tag *gdata)
+{
+       u32 info1 = le32_to_cpu(gdata->chan_info.info1);
+       u32 info2 = le32_to_cpu(gdata->chan_info.info2);
+       u8 band = info1 & 0xFF;
+       u8 type = (info1 >> 8) & 0xFF;
+       u16 prim20 = (info1 >> 16) & 0xFFFF;
+       u16 center1 = info2 & 0xFFFF;
+
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#### FW ####\n"
+                         "band         : %u\n"
+                         "type         : %u\n"
+                         "prim20_freq  : %u.%u MHz\n"
+                         "center1_freq : %u.%u MHz\n",
+                         band,
+                         type,
+                         Q2_TO_FREQ(prim20), Q2_TO_FREQ_FRAC(prim20),
+                         Q2_TO_FREQ(center1), Q2_TO_FREQ_FRAC(center1));
+       *pos += scnprintf(buf + *pos, bufsz - *pos,
+                         "#### DRIVER ####\n"
+                         "channel      : %u\n"
+                         "bw           : %u\n"
+                         "primary_freq : %u MHz\n"
+                         "center_freq  : %u MHz\n",
+                         cl_hw->channel,
+                         cl_hw->bw,
+                         cl_hw->primary_freq,
+                         cl_hw->center_freq);
+       return 0;
+}
+
+/**
+ * pre_fill_hook - initialize record data in coredump container
+ *
+ * Each record presents some section of information. Since, at this stage we
+ * have no idea about estimated data length, we shift "pos" only for size
+ * of header information, actual number of written bytes should be calculated
+ * in the post_fill_hook.
+ *
+ * @record: (NLEV) Name-Length-Error-Values record.
+ * @d: Coredump to fill in.
+ * @name: Name to set for this specific record;
+ * @pos: Position of last filled in element in the coredump (equal prev_pos till
+ *  fill in).
+ * @prev_pos: Position of the previous filled in element in the coredump.
+ *
+ * Returns nothing.
+ */
+static void pre_fill_hook(struct cl_nlev **record, struct cl_coredump *cd,
+                         char *name, int *pos, int *prev_pos)
+{
+       size_t coredump_space = le32_to_cpu(cd->len) - sizeof(*cd);
+       size_t free_space = coredump_space - *pos;
+
+       /* Save prev postion for NLEV length calculation in "post" hook */
+       *prev_pos = *pos;
+
+       /* Check if there is enough space for NLE (w/o V) */
+       if (free_space < sizeof(**record))
+               return;
+
+       /* Set pointer of the record to proper buffer place */
+       *record = (struct cl_nlev *)(cd->data + *pos);
+
+       /* Fill type info string */
+       scnprintf(cd->data + *pos, free_space, "%s", name);
+
+       /* Adjust position as like as new NLEV was added */
+       *pos += sizeof(**record);
+}
+
+/**
+ * post_fill_hook - finalize record data in the coredump container
+ *
+ * @record: (NLEV) Name-Length-Error-Values record.
+ * @err_code: processing error indication, typical errno
+ * @pos: Position of last filled in element in the coredump.
+ * @prev_pos: Position of the previous filled in element in the coredump,
+ *  in conjunction with "pos" is used to calculated filled in data and set
+ *  it as "Length" in the NLEV header.
+ *
+ * Returns nothing.
+ */
+static void post_fill_hook(struct cl_nlev **record, int *err_code, int *pos,
+                          int *prev_pos)
+{
+       /* Finalize what we know about NLEV - size (without headers)
+        * and processing error codeA
+        */
+       (**record).l = cpu_to_le32(*pos - *prev_pos - sizeof(**record));
+       (**record).e = cpu_to_le32(*err_code);
+
+       /* Reset error code for further usage */
+       *err_code = 0;
+}
+
+struct cl_coredump *cl_fw_dbg_prepare_coredump(struct cl_hw *cl_hw)
+{
+       struct dbg_info *dbg_info = (struct dbg_info *)cl_hw->dbginfo.buf;
+       struct dbg_error_trace_info_drv *fdump = &dbg_info->u.dump.fw_dump;
+       struct dbg_debug_info_tag *gdata = &dbg_info->u.dump.general_data;
+       struct cl_coredump *cd;
+       unsigned char *buf;
+       /* TODO: Make this size dynamic */
+       size_t len = PAGE_SIZE * 100;
+       size_t data_len = len - sizeof(*cd);
+       int pos = 0;
+       int prev_pos = 0;
+       int e = 0;
+       struct cl_nlev *rec = NULL;
+
+       buf = vzalloc(len);
+       if (!buf)
+               goto out;
+
+       cd = (typeof(cd))buf;
+       cd->len = cpu_to_le32(len);
+       cd->self_version = cpu_to_le32((CL_COREDUMP_V1 << 28) +
+                                      sizeof(*cd) + sizeof(*rec));
+       /* TODO: Mask support */
+       cd->dump_mask = cpu_to_le32(0);
+       cd->trig_tv_sec = cpu_to_le64(cl_hw->dbginfo.trigger_tstamp.tv_sec);
+       cd->trig_tv_nsec = cpu_to_le64(cl_hw->dbginfo.trigger_tstamp.tv_nsec);
+       scnprintf(cd->magic, sizeof(cd->magic), "CE_CL8K_DUMP");
+
+       /* Main section with dynamic dump data filling */
+       mutex_lock(&cl_hw->dbginfo.mutex);
+
+       pre_fill_hook(&rec, cd, "chip_descr", &pos, &prev_pos);
+       e = cl_dbg_dump_chip_descr(cl_hw, cd->data, data_len, &pos);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       pre_fill_hook(&rec, cd, "host_descr", &pos, &prev_pos);
+       e = cl_dbg_dump_host_descr(cl_hw, cd->data, data_len, &pos);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       pre_fill_hook(&rec, cd, "error", &pos, &prev_pos);
+       cl_dbg_dump_error_info(cl_hw, cd->data, data_len, &pos, fdump);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* Embedded logic analyzer info */
+       pre_fill_hook(&rec, cd, "ela_descr", &pos, &prev_pos);
+       e = cl_dbg_dump_ela_descr(cl_hw, cd->data, data_len, &pos);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       pre_fill_hook(&rec, cd, "raw_lcu_conf", &pos, &prev_pos);
+       e = cl_dbg_dump_raw_lcu_conf(cl_hw, cd->data, data_len, &pos);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       pre_fill_hook(&rec, cd, "adapted_lcu_conf", &pos, &prev_pos);
+       e = cl_dbg_dump_adapted_lcu_conf(cl_hw, cd->data, data_len, &pos);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* Stringified FW state conents */
+       pre_fill_hook(&rec, cd, "fw_dump", &pos, &prev_pos);
+       cl_dbg_dump_check_params(cl_hw, cd->data, data_len, &pos, fdump);
+       cl_dbg_dump_machw_regs(cl_hw, cd->data, data_len, &pos, fdump);
+       cl_dbg_dump_phyhw_regs(cl_hw, cd->data, data_len, &pos, fdump);
+       cl_dbg_dump_ac_info(cl_hw, cd->data, data_len, &pos, fdump);
+       cl_dbg_dump_single_tx_list_info(cl_hw, cd->data, data_len, &pos, fdump);
+       cl_dbg_dump_agg_tx_list_info(cl_hw, cd->data, data_len, &pos, fdump);
+       cl_dbg_dump_tx_trace_info(cl_hw, cd->data, data_len, &pos, fdump);
+       cl_dbg_dump_fw_trace_info(cl_hw, cd->data, data_len, &pos, fdump);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       pre_fill_hook(&rec, cd, "hw_diags", &pos, &prev_pos);
+       e = cl_dbg_dump_hw_diags(cl_hw, cd->data, data_len, &pos, gdata);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* FW/DRV-view of channel and freqs */
+       pre_fill_hook(&rec, cd, "chan_info", &pos, &prev_pos);
+       e = cl_dbg_dump_chan_info(cl_hw, cd->data, data_len, &pos, gdata);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* Logic analyzer (0) memory - MAC */
+       pre_fill_hook(&rec, cd, "la_mac_trace", &pos, &prev_pos);
+       e = cl_dbg_dump_la_mem(cl_hw, cd->data, data_len, &pos, LA_MAC_IDX, dbg_info);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* Logic analyzer (0) conf - MAC */
+       pre_fill_hook(&rec, cd, "la_mac_conf", &pos, &prev_pos);
+       e = cl_dbg_dump_la_conf(cl_hw, cd->data, data_len, &pos, LA_MAC_IDX, gdata);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* Logic analyzer (1) memory - PHY */
+       pre_fill_hook(&rec, cd, "la_phy_trace", &pos, &prev_pos);
+       e = cl_dbg_dump_la_mem(cl_hw, cd->data, data_len, &pos, LA_PHY_IDX, dbg_info);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* Logic analyzer (1) conf - PHY */
+       pre_fill_hook(&rec, cd, "la_phy_conf", &pos, &prev_pos);
+       e = cl_dbg_dump_la_conf(cl_hw, cd->data, data_len, &pos, LA_PHY_IDX, gdata);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* Diagnotics port - MAC */
+       pre_fill_hook(&rec, cd, "mac_diags", &pos, &prev_pos);
+       e = cl_dbg_dump_mac_diags(cl_hw, cd->data, data_len, &pos, gdata);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       /* SW diagnostics port */
+       pre_fill_hook(&rec, cd, "sw_diags", &pos, &prev_pos);
+       e = cl_dbg_dump_sw_diags(cl_hw, cd->data, data_len, &pos, gdata);
+       post_fill_hook(&rec, &e, &pos, &prev_pos);
+
+       mutex_unlock(&cl_hw->dbginfo.mutex);
+
+       /* devcoredump will take care of memory free process */
+       return cd;
+out:
+       return NULL;
+}
+
+#define INVALID_AMPDU_CNT U8_MAX
+
+void cl_fw_dbg_trigger_based_init(struct cl_hw *cl_hw)
+{
+       memset(&cl_hw->tb_stats, 0, sizeof(cl_hw->tb_stats));
+       cl_hw->tb_stats.ampdu_cnt = INVALID_AMPDU_CNT;
+}
+
+void cl_fw_dbg_trigger_based_update(struct cl_hw *cl_hw, struct hw_rxhdr *rxhdr,
+                                   struct ieee80211_hdr *hdr)
+{
+       struct cl_rx_trigger_based_stats *tb_stats = &cl_hw->tb_stats;
+
+       if (!tb_stats->enable)
+               return;
+
+       if (tb_stats->ampdu_cnt == INVALID_AMPDU_CNT) {
+               tb_stats->ampdu_cnt = rxhdr->ampdu_cnt;
+               if (rxhdr->format_mod == FORMATMOD_HE_TRIG) {
+                       if (ieee80211_is_qos_nullfunc(hdr->frame_control))
+                               tb_stats->qos_null_per_agg += rxhdr->frm_successful_rx;
+                       else
+                               tb_stats->data_per_agg += rxhdr->frm_successful_rx;
+
+                       tb_stats->total += rxhdr->frm_successful_rx;
+               }
+       } else if (tb_stats->ampdu_cnt == rxhdr->ampdu_cnt) {
+               if (rxhdr->format_mod == FORMATMOD_HE_TRIG) {
+                       if (ieee80211_is_qos_nullfunc(hdr->frame_control))
+                               tb_stats->qos_null_per_agg += rxhdr->frm_successful_rx;
+                       else
+                               tb_stats->data_per_agg += rxhdr->frm_successful_rx;
+
+                       tb_stats->total += rxhdr->frm_successful_rx;
+               }
+       } else {
+               tb_stats->ampdu_cnt = rxhdr->ampdu_cnt;
+               if (unlikely(tb_stats->data_per_agg >= DBG_STATS_MAX_AGG_SIZE))
+                       cl_dbg_err(cl_hw, "rx trigger_based agg size %u > 256\n",
+                                  tb_stats->data_per_agg);
+               else
+                       tb_stats->data[tb_stats->data_per_agg]++;
+
+               if (unlikely(tb_stats->qos_null_per_agg > TID_MAX))
+                       tb_stats->qos_null[TID_MAX + 1]++;
+               else
+                       tb_stats->qos_null[tb_stats->qos_null_per_agg]++;
+
+               tb_stats->data_per_agg = 0;
+               tb_stats->qos_null_per_agg = 0;
+
+               if (rxhdr->format_mod == FORMATMOD_HE_TRIG) {
+                       if (ieee80211_is_qos_nullfunc(hdr->frame_control))
+                               tb_stats->qos_null_per_agg += rxhdr->frm_successful_rx;
+                       else
+                               tb_stats->data_per_agg += rxhdr->frm_successful_rx;
+
+                       tb_stats->total += rxhdr->frm_successful_rx;
+               }
+       }
+}
+
+void cl_fw_dbg_trigger_based_reset(struct cl_hw *cl_hw)
+{
+       u32 idx;
+       struct cl_rx_trigger_based_stats *tb_stats = &cl_hw->tb_stats;
+
+       tb_stats->total = 0;
+
+       for (idx = 0; idx < ARRAY_SIZE(tb_stats->data); idx++)
+               tb_stats->data[idx] = 0;
+
+       for (idx = 0; idx < ARRAY_SIZE(tb_stats->qos_null); idx++)
+               tb_stats->qos_null[idx] = 0;
+}
--
2.30.0

________________________________
The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any retransmission, dissemination, copying or other use of, or taking of any action in reliance upon this information is prohibited. If you received this in error, please contact the sender and delete the material from any computer. Nothing contained herein shall be deemed as a representation, warranty or a commitment by Celeno. No warranties are expressed or implied, including, but not limited to, any implied warranties of non-infringement, merchantability and fitness for a particular purpose.
________________________________


  parent reply	other threads:[~2021-06-17 16:06 UTC|newest]

Thread overview: 262+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-17 15:58 [RFC v1 000/256] wireless: cl8k driver for Celeno IEEE 802.11ax devices viktor.barna
2021-06-17 15:58 ` [RFC v1 001/256] celeno: add Kconfig viktor.barna
2021-06-17 15:58 ` [RFC v1 002/256] celeno: add Makefile viktor.barna
2021-06-17 15:58 ` [RFC v1 003/256] cl8k: add Kconfig viktor.barna
2021-06-17 15:58 ` [RFC v1 004/256] cl8k: add Makefile viktor.barna
2021-06-17 15:58 ` [RFC v1 005/256] cl8k: add afe.c viktor.barna
2021-06-17 15:58 ` [RFC v1 006/256] cl8k: add afe.h viktor.barna
2021-06-17 15:58 ` [RFC v1 007/256] cl8k: add agc_params.c viktor.barna
2021-06-17 15:58 ` [RFC v1 008/256] cl8k: add agc_params.h viktor.barna
2021-06-17 15:58 ` [RFC v1 009/256] cl8k: add ampdu.c viktor.barna
2021-06-17 15:58 ` [RFC v1 010/256] cl8k: add ampdu.h viktor.barna
2021-06-17 15:58 ` [RFC v1 011/256] cl8k: add ate.c viktor.barna
2021-06-17 15:58 ` [RFC v1 012/256] cl8k: add ate.h viktor.barna
2021-06-17 15:58 ` [RFC v1 013/256] cl8k: add band.c viktor.barna
2021-06-17 15:58 ` [RFC v1 014/256] cl8k: add band.h viktor.barna
2021-06-17 15:58 ` [RFC v1 015/256] cl8k: add bf.c viktor.barna
2021-06-17 15:58 ` [RFC v1 016/256] cl8k: add bf.h viktor.barna
2021-06-17 15:58 ` [RFC v1 017/256] cl8k: add bus/pci/ipc.c viktor.barna
2021-06-17 15:58 ` [RFC v1 018/256] cl8k: add bus/pci/ipc.h viktor.barna
2021-06-17 15:58 ` [RFC v1 019/256] cl8k: add bus/pci/irq.c viktor.barna
2021-06-17 15:58 ` [RFC v1 020/256] cl8k: add bus/pci/irq.h viktor.barna
2021-06-17 15:58 ` [RFC v1 021/256] cl8k: add bus/pci/msg_pci.c viktor.barna
2021-06-17 15:58 ` [RFC v1 022/256] cl8k: add bus/pci/msg_pci.h viktor.barna
2021-06-17 15:58 ` [RFC v1 023/256] cl8k: add bus/pci/pci.c viktor.barna
2021-06-17 15:58 ` [RFC v1 024/256] cl8k: add bus/pci/rx_pci.c viktor.barna
2021-06-17 15:58 ` [RFC v1 025/256] cl8k: add bus/pci/rx_pci.h viktor.barna
2021-06-17 15:58 ` [RFC v1 026/256] cl8k: add bus/pci/tx_pci.c viktor.barna
2021-06-17 15:58 ` [RFC v1 027/256] cl8k: add bus/pci/tx_pci.h viktor.barna
2021-06-17 15:58 ` [RFC v1 028/256] cl8k: add calib.c viktor.barna
2021-06-17 15:58 ` [RFC v1 029/256] cl8k: add calib.h viktor.barna
2021-06-17 15:58 ` [RFC v1 030/256] cl8k: add cap.c viktor.barna
2021-06-17 15:58 ` [RFC v1 031/256] cl8k: add cap.h viktor.barna
2021-06-17 15:58 ` [RFC v1 032/256] cl8k: add cca.c viktor.barna
2021-06-17 15:58 ` [RFC v1 033/256] cl8k: add cca.h viktor.barna
2021-06-17 15:58 ` [RFC v1 034/256] cl8k: add cecli.c viktor.barna
2021-06-17 15:58 ` [RFC v1 035/256] cl8k: add cecli.h viktor.barna
2021-06-17 15:58 ` [RFC v1 036/256] cl8k: add chandef.c viktor.barna
2021-06-17 15:58 ` [RFC v1 037/256] cl8k: add chandef.h viktor.barna
2021-06-17 15:58 ` [RFC v1 038/256] cl8k: add channel.c viktor.barna
2021-06-17 15:58 ` [RFC v1 039/256] cl8k: add channel.h viktor.barna
2021-06-17 15:58 ` [RFC v1 040/256] cl8k: add chan_info.c viktor.barna
2021-06-17 15:58 ` [RFC v1 041/256] cl8k: add chan_info.h viktor.barna
2021-06-17 15:58 ` [RFC v1 042/256] cl8k: add chip.c viktor.barna
2021-06-17 15:58 ` [RFC v1 043/256] cl8k: add chip.h viktor.barna
2021-06-17 15:58 ` [RFC v1 044/256] cl8k: add chip_config.c viktor.barna
2021-06-17 15:58 ` [RFC v1 045/256] cl8k: add chip_config.h viktor.barna
2021-06-17 15:58 ` [RFC v1 046/256] cl8k: add config.c viktor.barna
2021-06-17 15:58 ` [RFC v1 047/256] cl8k: add config.h viktor.barna
2021-06-17 15:58 ` [RFC v1 048/256] cl8k: add coredump.c viktor.barna
2021-06-17 15:58 ` [RFC v1 049/256] cl8k: add coredump.h viktor.barna
2021-06-17 15:58 ` [RFC v1 050/256] cl8k: add data_rates.c viktor.barna
2021-06-17 15:58 ` [RFC v1 051/256] cl8k: add data_rates.h viktor.barna
2021-06-17 15:58 ` [RFC v1 052/256] cl8k: add dbgfile.c viktor.barna
2021-06-17 15:59 ` [RFC v1 053/256] cl8k: add dbgfile.h viktor.barna
2021-06-17 15:59 ` [RFC v1 054/256] cl8k: add debug.h viktor.barna
2021-06-17 15:59 ` [RFC v1 055/256] cl8k: add debugfs.c viktor.barna
2021-06-17 15:59 ` [RFC v1 056/256] cl8k: add debugfs.h viktor.barna
2021-06-17 15:59 ` [RFC v1 057/256] cl8k: add debugfs_defs.h viktor.barna
2021-06-17 15:59 ` [RFC v1 058/256] cl8k: add def.h viktor.barna
2021-06-17 15:59 ` [RFC v1 059/256] cl8k: add dfs/dfs.c viktor.barna
2021-06-17 15:59 ` [RFC v1 060/256] cl8k: add dfs/dfs.h viktor.barna
2021-06-17 15:59 ` [RFC v1 061/256] cl8k: add dfs/dfs_db.h viktor.barna
2021-06-17 15:59 ` [RFC v1 062/256] cl8k: add dfs/radar.c viktor.barna
2021-06-17 15:59 ` [RFC v1 063/256] cl8k: add dfs/radar.h viktor.barna
2021-06-17 15:59 ` [RFC v1 064/256] cl8k: add drv_ops.h viktor.barna
2021-06-17 15:59 ` [RFC v1 065/256] cl8k: add dsp.c viktor.barna
2021-06-17 15:59 ` [RFC v1 066/256] cl8k: add dsp.h viktor.barna
2021-06-17 15:59 ` [RFC v1 067/256] cl8k: add e2p.c viktor.barna
2021-06-17 15:59 ` [RFC v1 068/256] cl8k: add e2p.h viktor.barna
2021-06-17 15:59 ` [RFC v1 069/256] cl8k: add edca.c viktor.barna
2021-06-17 15:59 ` [RFC v1 070/256] cl8k: add edca.h viktor.barna
2021-06-17 15:59 ` [RFC v1 071/256] cl8k: add ela.c viktor.barna
2021-06-17 15:59 ` [RFC v1 072/256] cl8k: add ela.h viktor.barna
2021-06-17 15:59 ` [RFC v1 073/256] cl8k: add enhanced_tim.c viktor.barna
2021-06-17 15:59 ` [RFC v1 074/256] cl8k: add enhanced_tim.h viktor.barna
2021-06-17 15:59 ` [RFC v1 075/256] cl8k: add env_det.c viktor.barna
2021-06-17 15:59 ` [RFC v1 076/256] cl8k: add env_det.h viktor.barna
2021-06-17 15:59 ` [RFC v1 077/256] cl8k: add ext/dyn_bcast_rate.c viktor.barna
2021-06-17 15:59 ` [RFC v1 078/256] cl8k: add ext/dyn_bcast_rate.h viktor.barna
2021-06-17 15:59 ` [RFC v1 079/256] cl8k: add ext/dyn_mcast_rate.c viktor.barna
2021-06-17 15:59 ` [RFC v1 080/256] cl8k: add ext/dyn_mcast_rate.h viktor.barna
2021-06-17 15:59 ` [RFC v1 081/256] cl8k: add ext/vlan_dscp.c viktor.barna
2021-06-17 15:59 ` [RFC v1 082/256] cl8k: add ext/vlan_dscp.h viktor.barna
2021-06-17 15:59 ` [RFC v1 083/256] cl8k: add fem.c viktor.barna
2021-06-17 15:59 ` [RFC v1 084/256] cl8k: add fem.h viktor.barna
2021-06-17 15:59 ` [RFC v1 085/256] cl8k: add fem_common.h viktor.barna
2021-06-17 15:59 ` viktor.barna [this message]
2021-06-17 15:59 ` [RFC v1 087/256] cl8k: add fw/fw_dbg.h viktor.barna
2021-06-17 15:59 ` [RFC v1 088/256] cl8k: add fw/fw_file.c viktor.barna
2021-06-17 15:59 ` [RFC v1 089/256] cl8k: add fw/fw_file.h viktor.barna
2021-06-17 15:59 ` [RFC v1 090/256] cl8k: add fw/fw_msg.c viktor.barna
2021-06-17 15:59 ` [RFC v1 091/256] cl8k: add fw/fw_msg.h viktor.barna
2021-06-17 15:59 ` [RFC v1 092/256] cl8k: add fw/msg_cfm.c viktor.barna
2021-06-17 15:59 ` [RFC v1 093/256] cl8k: add fw/msg_cfm.h viktor.barna
2021-06-17 15:59 ` [RFC v1 094/256] cl8k: add fw/msg_rx.c viktor.barna
2021-06-17 15:59 ` [RFC v1 095/256] cl8k: add fw/msg_rx.h viktor.barna
2021-06-17 15:59 ` [RFC v1 096/256] cl8k: add fw/msg_tx.c viktor.barna
2021-06-17 15:59 ` [RFC v1 097/256] cl8k: add fw/msg_tx.h viktor.barna
2021-06-17 15:59 ` [RFC v1 098/256] cl8k: add hw.c viktor.barna
2021-06-17 15:59 ` [RFC v1 099/256] cl8k: add hw.h viktor.barna
2021-06-17 15:59 ` [RFC v1 100/256] cl8k: add hw_assert.c viktor.barna
2021-06-17 15:59 ` [RFC v1 101/256] cl8k: add hw_assert.h viktor.barna
2021-06-17 15:59 ` [RFC v1 102/256] cl8k: add ipc_shared.h viktor.barna
2021-06-17 15:59 ` [RFC v1 103/256] cl8k: add key.c viktor.barna
2021-06-17 15:59 ` [RFC v1 104/256] cl8k: add key.h viktor.barna
2021-06-17 15:59 ` [RFC v1 105/256] cl8k: add mac80211.c viktor.barna
2021-06-17 15:59 ` [RFC v1 106/256] cl8k: add mac80211.h viktor.barna
2021-06-17 15:59 ` [RFC v1 107/256] cl8k: add mac_addr.c viktor.barna
2021-06-17 15:59 ` [RFC v1 108/256] cl8k: add mac_addr.h viktor.barna
2021-06-17 15:59 ` [RFC v1 109/256] cl8k: add main.c viktor.barna
2021-06-17 15:59 ` [RFC v1 110/256] cl8k: add main.h viktor.barna
2021-06-17 15:59 ` [RFC v1 111/256] cl8k: add maintenance.c viktor.barna
2021-06-17 15:59 ` [RFC v1 112/256] cl8k: add maintenance.h viktor.barna
2021-06-17 16:00 ` [RFC v1 113/256] cl8k: add mib.c viktor.barna
2021-06-17 16:00 ` [RFC v1 114/256] cl8k: add mib.h viktor.barna
2021-06-17 16:00 ` [RFC v1 115/256] cl8k: add motion_sense.c viktor.barna
2021-06-17 16:00 ` [RFC v1 116/256] cl8k: add motion_sense.h viktor.barna
2021-06-17 16:00 ` [RFC v1 117/256] cl8k: add netlink.c viktor.barna
2021-06-17 16:00 ` [RFC v1 118/256] cl8k: add netlink.h viktor.barna
2021-06-17 16:00 ` [RFC v1 119/256] cl8k: add noise.c viktor.barna
2021-06-17 16:00 ` [RFC v1 120/256] cl8k: add noise.h viktor.barna
2021-06-17 16:00 ` [RFC v1 121/256] cl8k: add omi.c viktor.barna
2021-06-17 16:00 ` [RFC v1 122/256] cl8k: add omi.h viktor.barna
2021-06-17 16:00 ` [RFC v1 123/256] cl8k: add ops.c viktor.barna
2021-06-17 16:00 ` [RFC v1 124/256] cl8k: add ops.h viktor.barna
2021-06-17 16:00 ` [RFC v1 125/256] cl8k: add phy/phy.c viktor.barna
2021-06-17 16:00 ` [RFC v1 126/256] cl8k: add phy/phy.h viktor.barna
2021-06-17 16:00 ` [RFC v1 127/256] cl8k: add phy/phy_athos_lut.c viktor.barna
2021-06-17 16:00 ` [RFC v1 128/256] cl8k: add phy/phy_athos_lut.h viktor.barna
2021-06-17 16:00 ` [RFC v1 129/256] cl8k: add phy/phy_common_lut.c viktor.barna
2021-06-17 16:00 ` [RFC v1 130/256] cl8k: add phy/phy_common_lut.h viktor.barna
2021-06-17 16:00 ` [RFC v1 131/256] cl8k: add phy/phy_olympus_lut.c viktor.barna
2021-06-17 16:00 ` [RFC v1 132/256] cl8k: add phy/phy_olympus_lut.h viktor.barna
2021-06-17 16:00 ` [RFC v1 133/256] cl8k: add power.c viktor.barna
2021-06-17 16:00 ` [RFC v1 134/256] cl8k: add power.h viktor.barna
2021-06-17 16:00 ` [RFC v1 135/256] cl8k: add power_cli.c viktor.barna
2021-06-17 16:00 ` [RFC v1 136/256] cl8k: add power_cli.h viktor.barna
2021-06-17 16:00 ` [RFC v1 137/256] cl8k: add power_table.c viktor.barna
2021-06-17 16:00 ` [RFC v1 138/256] cl8k: add power_table.h viktor.barna
2021-06-17 16:00 ` [RFC v1 139/256] cl8k: add prot_mode.c viktor.barna
2021-06-17 16:00 ` [RFC v1 140/256] cl8k: add prot_mode.h viktor.barna
2021-06-17 16:00 ` [RFC v1 141/256] cl8k: add radio.c viktor.barna
2021-06-17 16:00 ` [RFC v1 142/256] cl8k: add radio.h viktor.barna
2021-06-17 16:00 ` [RFC v1 143/256] cl8k: add rate_ctrl.c viktor.barna
2021-06-17 16:00 ` [RFC v1 144/256] cl8k: add rate_ctrl.h viktor.barna
2021-06-17 16:00 ` [RFC v1 145/256] cl8k: add recovery.c viktor.barna
2021-06-17 16:00 ` [RFC v1 146/256] cl8k: add recovery.h viktor.barna
2021-06-17 16:00 ` [RFC v1 147/256] cl8k: add reg/ceva.h viktor.barna
2021-06-17 16:00 ` [RFC v1 148/256] cl8k: add reg/reg_access.h viktor.barna
2021-06-17 16:00 ` [RFC v1 149/256] cl8k: add reg/reg_cli.c viktor.barna
2021-06-17 16:00 ` [RFC v1 150/256] cl8k: add reg/reg_cli.h viktor.barna
2021-06-17 16:00 ` [RFC v1 151/256] cl8k: add reg/reg_cmu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 152/256] cl8k: add reg/reg_fem.h viktor.barna
2021-06-17 16:00 ` [RFC v1 153/256] cl8k: add reg/reg_io_ctrl.h viktor.barna
2021-06-17 16:00 ` [RFC v1 154/256] cl8k: add reg/reg_ipc.h viktor.barna
2021-06-17 16:00 ` [RFC v1 155/256] cl8k: add reg/reg_lcu_common.h viktor.barna
2021-06-17 16:00 ` [RFC v1 156/256] cl8k: add reg/reg_lcu_phy.h viktor.barna
2021-06-17 16:00 ` [RFC v1 157/256] cl8k: add reg/reg_macdsp_api.h viktor.barna
2021-06-17 16:00 ` [RFC v1 158/256] cl8k: add reg/reg_macsys_gcu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 159/256] cl8k: add reg/reg_mac_hw.h viktor.barna
2021-06-17 16:00 ` [RFC v1 160/256] cl8k: add reg/reg_mac_hw_mu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 161/256] cl8k: add reg/reg_modem_gcu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 162/256] cl8k: add reg/reg_otp_pvt.h viktor.barna
2021-06-17 16:00 ` [RFC v1 163/256] cl8k: add reg/reg_ricu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 164/256] cl8k: add reg/reg_riu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 165/256] cl8k: add reg/reg_riu_rc.h viktor.barna
2021-06-17 16:00 ` [RFC v1 166/256] cl8k: add rf_boot.c viktor.barna
2021-06-17 16:00 ` [RFC v1 167/256] cl8k: add rf_boot.h viktor.barna
2021-06-17 16:00 ` [RFC v1 168/256] cl8k: add rsrc_mgmt.c viktor.barna
2021-06-17 16:00 ` [RFC v1 169/256] cl8k: add rsrc_mgmt.h viktor.barna
2021-06-17 16:00 ` [RFC v1 170/256] cl8k: add rssi.c viktor.barna
2021-06-17 16:00 ` [RFC v1 171/256] cl8k: add rssi.h viktor.barna
2021-06-17 16:00 ` [RFC v1 172/256] cl8k: add rx/rx.c viktor.barna
2021-06-17 16:01 ` [RFC v1 173/256] cl8k: add rx/rx.h viktor.barna
2021-06-17 16:01 ` [RFC v1 174/256] cl8k: add rx/rx_amsdu.c viktor.barna
2021-06-17 16:01 ` [RFC v1 175/256] cl8k: add rx/rx_amsdu.h viktor.barna
2021-06-17 16:01 ` [RFC v1 176/256] cl8k: add rx/rx_filter.c viktor.barna
2021-06-17 16:01 ` [RFC v1 177/256] cl8k: add rx/rx_filter.h viktor.barna
2021-06-17 16:01 ` [RFC v1 178/256] cl8k: add rx/rx_reorder.c viktor.barna
2021-06-17 16:01 ` [RFC v1 179/256] cl8k: add rx/rx_reorder.h viktor.barna
2021-06-17 16:01 ` [RFC v1 180/256] cl8k: add sounding.c viktor.barna
2021-06-17 16:01 ` [RFC v1 181/256] cl8k: add sounding.h viktor.barna
2021-06-17 16:01 ` [RFC v1 182/256] cl8k: add sta.c viktor.barna
2021-06-17 16:01 ` [RFC v1 183/256] cl8k: add sta.h viktor.barna
2021-06-17 16:01 ` [RFC v1 184/256] cl8k: add stats.c viktor.barna
2021-06-17 16:01 ` [RFC v1 185/256] cl8k: add stats.h viktor.barna
2021-06-17 16:01 ` [RFC v1 186/256] cl8k: add tcv_config.c viktor.barna
2021-06-17 16:01 ` [RFC v1 187/256] cl8k: add tcv_config.h viktor.barna
2021-06-17 16:01 ` [RFC v1 188/256] cl8k: add temperature.c viktor.barna
2021-06-17 16:01 ` [RFC v1 189/256] cl8k: add temperature.h viktor.barna
2021-06-17 16:01 ` [RFC v1 190/256] cl8k: add trace.c viktor.barna
2021-06-17 16:01 ` [RFC v1 191/256] cl8k: add trace.h viktor.barna
2021-06-17 16:01 ` [RFC v1 192/256] cl8k: add traffic.c viktor.barna
2021-06-17 16:01 ` [RFC v1 193/256] cl8k: add traffic.h viktor.barna
2021-06-17 16:01 ` [RFC v1 194/256] cl8k: add twt.c viktor.barna
2021-06-17 16:01 ` [RFC v1 195/256] cl8k: add twt.h viktor.barna
2021-06-17 16:01 ` [RFC v1 196/256] cl8k: add twt_cli.c viktor.barna
2021-06-17 16:01 ` [RFC v1 197/256] cl8k: add twt_cli.h viktor.barna
2021-06-17 16:01 ` [RFC v1 198/256] cl8k: add twt_frame.c viktor.barna
2021-06-17 16:01 ` [RFC v1 199/256] cl8k: add twt_frame.h viktor.barna
2021-06-17 16:01 ` [RFC v1 200/256] cl8k: add tx/agg_cfm.c viktor.barna
2021-06-17 16:01 ` [RFC v1 201/256] cl8k: add tx/agg_cfm.h viktor.barna
2021-06-17 16:01 ` [RFC v1 202/256] cl8k: add tx/agg_tx_report.c viktor.barna
2021-06-17 16:01 ` [RFC v1 203/256] cl8k: add tx/agg_tx_report.h viktor.barna
2021-06-17 16:01 ` [RFC v1 204/256] cl8k: add tx/baw.c viktor.barna
2021-06-17 16:01 ` [RFC v1 205/256] cl8k: add tx/baw.h viktor.barna
2021-06-17 16:01 ` [RFC v1 206/256] cl8k: add tx/bcmc_cfm.c viktor.barna
2021-06-17 16:01 ` [RFC v1 207/256] cl8k: add tx/bcmc_cfm.h viktor.barna
2021-06-17 16:01 ` [RFC v1 208/256] cl8k: add tx/single_cfm.c viktor.barna
2021-06-17 16:01 ` [RFC v1 209/256] cl8k: add tx/single_cfm.h viktor.barna
2021-06-17 16:01 ` [RFC v1 210/256] cl8k: add tx/sw_txhdr.c viktor.barna
2021-06-17 16:01 ` [RFC v1 211/256] cl8k: add tx/sw_txhdr.h viktor.barna
2021-06-17 16:01 ` [RFC v1 212/256] cl8k: add tx/tx.c viktor.barna
2021-06-17 16:01 ` [RFC v1 213/256] cl8k: add tx/tx.h viktor.barna
2021-06-17 16:01 ` [RFC v1 214/256] cl8k: add tx/tx_amsdu.c viktor.barna
2021-06-17 16:01 ` [RFC v1 215/256] cl8k: add tx/tx_amsdu.h viktor.barna
2021-06-17 16:01 ` [RFC v1 216/256] cl8k: add tx/tx_inject.c viktor.barna
2021-06-17 16:01 ` [RFC v1 217/256] cl8k: add tx/tx_inject.h viktor.barna
2021-06-17 16:01 ` [RFC v1 218/256] cl8k: add tx/tx_queue.c viktor.barna
2021-06-17 16:01 ` [RFC v1 219/256] cl8k: add tx/tx_queue.h viktor.barna
2021-06-17 16:01 ` [RFC v1 220/256] cl8k: add utils/file.c viktor.barna
2021-06-17 16:01 ` [RFC v1 221/256] cl8k: add utils/file.h viktor.barna
2021-06-17 16:01 ` [RFC v1 222/256] cl8k: add utils/ip.c viktor.barna
2021-06-17 16:01 ` [RFC v1 223/256] cl8k: add utils/ip.h viktor.barna
2021-06-17 16:01 ` [RFC v1 224/256] cl8k: add utils/math.h viktor.barna
2021-06-17 16:01 ` [RFC v1 225/256] cl8k: add utils/string.c viktor.barna
2021-06-17 16:01 ` [RFC v1 226/256] cl8k: add utils/string.h viktor.barna
2021-06-17 16:01 ` [RFC v1 227/256] cl8k: add utils/timer.c viktor.barna
2021-06-17 16:01 ` [RFC v1 228/256] cl8k: add utils/timer.h viktor.barna
2021-06-17 16:01 ` [RFC v1 229/256] cl8k: add utils/utils.c viktor.barna
2021-06-17 16:01 ` [RFC v1 230/256] cl8k: add utils/utils.h viktor.barna
2021-06-17 16:01 ` [RFC v1 231/256] cl8k: add vendor_cmd.c viktor.barna
2021-06-17 16:01 ` [RFC v1 232/256] cl8k: add vendor_cmd.h viktor.barna
2021-06-17 16:02 ` [RFC v1 233/256] cl8k: add version.c viktor.barna
2021-06-17 16:02 ` [RFC v1 234/256] cl8k: add version.h viktor.barna
2021-06-17 16:02 ` [RFC v1 235/256] cl8k: add vif.c viktor.barna
2021-06-17 16:02 ` [RFC v1 236/256] cl8k: add vif.h viktor.barna
2021-06-17 16:02 ` [RFC v1 237/256] cl8k: add vns.c viktor.barna
2021-06-17 16:02 ` [RFC v1 238/256] cl8k: add vns.h viktor.barna
2021-06-17 16:02 ` [RFC v1 239/256] cl8k: add wrs/wrs.c viktor.barna
2021-06-17 16:02 ` [RFC v1 240/256] cl8k: add wrs/wrs.h viktor.barna
2021-06-17 16:02 ` [RFC v1 241/256] cl8k: add wrs/wrs_ap.c viktor.barna
2021-06-17 16:02 ` [RFC v1 242/256] cl8k: add wrs/wrs_ap.h viktor.barna
2021-06-17 16:02 ` [RFC v1 243/256] cl8k: add wrs/wrs_api.c viktor.barna
2021-06-17 16:02 ` [RFC v1 244/256] cl8k: add wrs/wrs_api.h viktor.barna
2021-06-17 16:02 ` [RFC v1 245/256] cl8k: add wrs/wrs_cli.c viktor.barna
2021-06-17 16:02 ` [RFC v1 246/256] cl8k: add wrs/wrs_cli.h viktor.barna
2021-06-17 16:02 ` [RFC v1 247/256] cl8k: add wrs/wrs_db.h viktor.barna
2021-06-17 16:02 ` [RFC v1 248/256] cl8k: add wrs/wrs_rssi.c viktor.barna
2021-06-17 16:02 ` [RFC v1 249/256] cl8k: add wrs/wrs_rssi.h viktor.barna
2021-06-17 16:02 ` [RFC v1 250/256] cl8k: add wrs/wrs_sta.c viktor.barna
2021-06-17 16:02 ` [RFC v1 251/256] cl8k: add wrs/wrs_sta.h viktor.barna
2021-06-17 16:02 ` [RFC v1 252/256] cl8k: add wrs/wrs_stats.c viktor.barna
2021-06-17 16:02 ` [RFC v1 253/256] cl8k: add wrs/wrs_stats.h viktor.barna
2021-06-17 16:02 ` [RFC v1 254/256] cl8k: add wrs/wrs_tables.c viktor.barna
2021-06-17 16:02 ` [RFC v1 255/256] cl8k: add wrs/wrs_tables.h viktor.barna
2021-06-17 16:02 ` [RFC v1 256/256] wireless: add Celeno vendor viktor.barna
2021-06-17 17:23 ` [RFC v1 000/256] wireless: cl8k driver for Celeno IEEE 802.11ax devices Johannes Berg
2022-05-22 17:51   ` viktor.barna
2021-06-19  6:39 ` Kalle Valo
2022-05-13 21:11   ` viktor.barna
2022-05-14  4:25     ` Kalle Valo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210617160223.160998-87-viktor.barna@celeno.com \
    --to=viktor.barna@celeno.com \
    --cc=aviad.brikman@celeno.com \
    --cc=davem@davemloft.net \
    --cc=eliav.farber@gmail.com \
    --cc=kuba@kernel.org \
    --cc=kvalo@codeaurora.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=oleksandr.savchenko@celeno.com \
    --cc=shay.bar@celeno.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.