Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2 iwlwifi-next 13/15] wifi: iwlwifi: fw: separate out old-style dump code
From: Miri Korenblit @ 2026-05-17  7:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260517075959.2815365-1-miriam.rachel.korenblit@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

There are two dump paths: new "ini" style, and the old,
more driver-centric, way. Separate out the code for the
old way into a separate dbg-old.c file, to simplify.

Fix a typo ('trasport') along the way.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/Makefile   |    2 +-
 .../net/wireless/intel/iwlwifi/fw/dbg-old.c   | 1022 +++++++++++++++++
 drivers/net/wireless/intel/iwlwifi/fw/dbg.c   | 1012 +---------------
 drivers/net/wireless/intel/iwlwifi/fw/dbg.h   |    7 +-
 4 files changed, 1032 insertions(+), 1011 deletions(-)
 create mode 100644 drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c

diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile
index 941257b811b4..2a74efe09cf0 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -32,7 +32,7 @@ iwlwifi-objs		+= iwl-dbg-tlv.o
 iwlwifi-objs		+= iwl-trans.o
 
 iwlwifi-objs		+= fw/img.o fw/notif-wait.o fw/rs.o
-iwlwifi-objs		+= fw/dbg.o fw/pnvm.o fw/dump.o
+iwlwifi-objs		+= fw/dbg.o fw/dbg-old.o fw/pnvm.o fw/dump.o
 iwlwifi-objs		+= fw/regulatory.o
 iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o
 iwlwifi-$(CONFIG_IWLMLD) += fw/smem.o fw/init.o
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c
new file mode 100644
index 000000000000..19b1bfd0abee
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c
@@ -0,0 +1,1022 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2005-2014, 2018-2026 Intel Corporation
+ * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ */
+#include <linux/devcoredump.h>
+#include "iwl-drv.h"
+#include "runtime.h"
+#include "dbg.h"
+#include "debugfs.h"
+#include "iwl-io.h"
+#include "iwl-prph.h"
+#include "iwl-csr.h"
+#include "iwl-fh.h"
+
+/**
+ * struct iwl_fw_dump_ptrs - set of pointers needed for the fw-error-dump
+ *
+ * @fwrt_ptr: pointer to the buffer coming from fwrt
+ * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
+ *	transport's data.
+ * @fwrt_len: length of the valid data in fwrt_ptr
+ */
+struct iwl_fw_dump_ptrs {
+	struct iwl_trans_dump_data *trans_ptr;
+	void *fwrt_ptr;
+	u32 fwrt_len;
+};
+
+#define RADIO_REG_MAX_READ 0x2ad
+static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt,
+				struct iwl_fw_error_dump_data **dump_data)
+{
+	u8 *pos = (void *)(*dump_data)->data;
+	int i;
+
+	IWL_DEBUG_INFO(fwrt, "WRT radio registers dump\n");
+
+	if (!iwl_trans_grab_nic_access(fwrt->trans))
+		return;
+
+	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RADIO_REG);
+	(*dump_data)->len = cpu_to_le32(RADIO_REG_MAX_READ);
+
+	for (i = 0; i < RADIO_REG_MAX_READ; i++) {
+		u32 rd_cmd = RADIO_RSP_RD_CMD;
+
+		rd_cmd |= i << RADIO_RSP_ADDR_POS;
+		iwl_trans_write_prph(fwrt->trans, RSP_RADIO_CMD, rd_cmd);
+		*pos = (u8)iwl_trans_read_prph(fwrt->trans, RSP_RADIO_RDDAT);
+
+		pos++;
+	}
+
+	*dump_data = iwl_fw_error_next_data(*dump_data);
+
+	iwl_trans_release_nic_access(fwrt->trans);
+}
+
+static void iwl_fwrt_dump_rxf(struct iwl_fw_runtime *fwrt,
+			      struct iwl_fw_error_dump_data **dump_data,
+			      int size, u32 offset, int fifo_num)
+{
+	struct iwl_fw_error_dump_fifo *fifo_hdr;
+	u32 *fifo_data;
+	u32 fifo_len;
+	int i;
+
+	fifo_hdr = (void *)(*dump_data)->data;
+	fifo_data = (void *)fifo_hdr->data;
+	fifo_len = size;
+
+	/* No need to try to read the data if the length is 0 */
+	if (fifo_len == 0)
+		return;
+
+	/* Add a TLV for the RXF */
+	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
+	(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
+
+	fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
+	fifo_hdr->available_bytes =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						RXF_RD_D_SPACE + offset));
+	fifo_hdr->wr_ptr =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						RXF_RD_WR_PTR + offset));
+	fifo_hdr->rd_ptr =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						RXF_RD_RD_PTR + offset));
+	fifo_hdr->fence_ptr =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						RXF_RD_FENCE_PTR + offset));
+	fifo_hdr->fence_mode =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						RXF_SET_FENCE_MODE + offset));
+
+	/* Lock fence */
+	iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1);
+	/* Set fence pointer to the same place like WR pointer */
+	iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offset, 0x1);
+	/* Set fence offset */
+	iwl_trans_write_prph(fwrt->trans,
+			     RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0);
+
+	/* Read FIFO */
+	fifo_len /= sizeof(u32); /* Size in DWORDS */
+	for (i = 0; i < fifo_len; i++)
+		fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
+						 RXF_FIFO_RD_FENCE_INC +
+						 offset);
+	*dump_data = iwl_fw_error_next_data(*dump_data);
+}
+
+static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt,
+			      struct iwl_fw_error_dump_data **dump_data,
+			      int size, u32 offset, int fifo_num)
+{
+	struct iwl_fw_error_dump_fifo *fifo_hdr;
+	u32 *fifo_data;
+	u32 fifo_len;
+	int i;
+
+	fifo_hdr = (void *)(*dump_data)->data;
+	fifo_data = (void *)fifo_hdr->data;
+	fifo_len = size;
+
+	/* No need to try to read the data if the length is 0 */
+	if (fifo_len == 0)
+		return;
+
+	/* Add a TLV for the FIFO */
+	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXF);
+	(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
+
+	fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
+	fifo_hdr->available_bytes =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						TXF_FIFO_ITEM_CNT + offset));
+	fifo_hdr->wr_ptr =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						TXF_WR_PTR + offset));
+	fifo_hdr->rd_ptr =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						TXF_RD_PTR + offset));
+	fifo_hdr->fence_ptr =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						TXF_FENCE_PTR + offset));
+	fifo_hdr->fence_mode =
+		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+						TXF_LOCK_FENCE + offset));
+
+	/* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
+	iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offset,
+			     TXF_WR_PTR + offset);
+
+	/* Dummy-read to advance the read pointer to the head */
+	iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset);
+
+	/* Read FIFO */
+	for (i = 0; i < fifo_len / sizeof(u32); i++)
+		fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
+						  TXF_READ_MODIFY_DATA +
+						  offset);
+
+	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
+		fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
+					     fifo_data, fifo_len);
+
+	*dump_data = iwl_fw_error_next_data(*dump_data);
+}
+
+static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt,
+			    struct iwl_fw_error_dump_data **dump_data)
+{
+	struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
+
+	IWL_DEBUG_INFO(fwrt, "WRT RX FIFO dump\n");
+
+	if (!iwl_trans_grab_nic_access(fwrt->trans))
+		return;
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF)) {
+		/* Pull RXF1 */
+		iwl_fwrt_dump_rxf(fwrt, dump_data,
+				  cfg->lmac[0].rxfifo1_size, 0, 0);
+		/* Pull RXF2 */
+		iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
+				  RXF_DIFF_FROM_PREV +
+				  fwrt->trans->mac_cfg->umac_prph_offset, 1);
+		/* Pull LMAC2 RXF1 */
+		if (fwrt->smem_cfg.num_lmacs > 1)
+			iwl_fwrt_dump_rxf(fwrt, dump_data,
+					  cfg->lmac[1].rxfifo1_size,
+					  LMAC2_PRPH_OFFSET, 2);
+	}
+
+	iwl_trans_release_nic_access(fwrt->trans);
+}
+
+static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt,
+			    struct iwl_fw_error_dump_data **dump_data)
+{
+	struct iwl_fw_error_dump_fifo *fifo_hdr;
+	struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
+	u32 *fifo_data;
+	u32 fifo_len;
+	int i, j;
+
+	IWL_DEBUG_INFO(fwrt, "WRT TX FIFO dump\n");
+
+	if (!iwl_trans_grab_nic_access(fwrt->trans))
+		return;
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF)) {
+		/* Pull TXF data from LMAC1 */
+		for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
+			/* Mark the number of TXF we're pulling now */
+			iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
+			iwl_fwrt_dump_txf(fwrt, dump_data,
+					  cfg->lmac[0].txfifo_size[i], 0, i);
+		}
+
+		/* Pull TXF data from LMAC2 */
+		if (fwrt->smem_cfg.num_lmacs > 1) {
+			for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries;
+			     i++) {
+				/* Mark the number of TXF we're pulling now */
+				iwl_trans_write_prph(fwrt->trans,
+						     TXF_LARC_NUM +
+						     LMAC2_PRPH_OFFSET, i);
+				iwl_fwrt_dump_txf(fwrt, dump_data,
+						  cfg->lmac[1].txfifo_size[i],
+						  LMAC2_PRPH_OFFSET,
+						  i + cfg->num_txfifo_entries);
+			}
+		}
+	}
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
+	    fw_has_capa(&fwrt->fw->ucode_capa,
+			IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
+		/* Pull UMAC internal TXF data from all TXFs */
+		for (i = 0;
+		     i < ARRAY_SIZE(fwrt->smem_cfg.internal_txfifo_size);
+		     i++) {
+			fifo_hdr = (void *)(*dump_data)->data;
+			fifo_data = (void *)fifo_hdr->data;
+			fifo_len = fwrt->smem_cfg.internal_txfifo_size[i];
+
+			/* No need to try to read the data if the length is 0 */
+			if (fifo_len == 0)
+				continue;
+
+			/* Add a TLV for the internal FIFOs */
+			(*dump_data)->type =
+				cpu_to_le32(IWL_FW_ERROR_DUMP_INTERNAL_TXF);
+			(*dump_data)->len =
+				cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
+
+			fifo_hdr->fifo_num = cpu_to_le32(i);
+
+			/* Mark the number of TXF we're pulling now */
+			iwl_trans_write_prph(fwrt->trans, TXF_CPU2_NUM, i +
+				fwrt->smem_cfg.num_txfifo_entries);
+
+			fifo_hdr->available_bytes =
+				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+								TXF_CPU2_FIFO_ITEM_CNT));
+			fifo_hdr->wr_ptr =
+				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+								TXF_CPU2_WR_PTR));
+			fifo_hdr->rd_ptr =
+				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+								TXF_CPU2_RD_PTR));
+			fifo_hdr->fence_ptr =
+				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+								TXF_CPU2_FENCE_PTR));
+			fifo_hdr->fence_mode =
+				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
+								TXF_CPU2_LOCK_FENCE));
+
+			/* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */
+			iwl_trans_write_prph(fwrt->trans,
+					     TXF_CPU2_READ_MODIFY_ADDR,
+					     TXF_CPU2_WR_PTR);
+
+			/* Dummy-read to advance the read pointer to head */
+			iwl_trans_read_prph(fwrt->trans,
+					    TXF_CPU2_READ_MODIFY_DATA);
+
+			/* Read FIFO */
+			fifo_len /= sizeof(u32); /* Size in DWORDS */
+			for (j = 0; j < fifo_len; j++)
+				fifo_data[j] =
+					iwl_trans_read_prph(fwrt->trans,
+							    TXF_CPU2_READ_MODIFY_DATA);
+			*dump_data = iwl_fw_error_next_data(*dump_data);
+		}
+	}
+
+	iwl_trans_release_nic_access(fwrt->trans);
+}
+
+struct iwl_prph_range {
+	u32 start, end;
+};
+
+static const struct iwl_prph_range iwl_prph_dump_addr_comm[] = {
+	{ .start = 0x00a00000, .end = 0x00a00000 },
+	{ .start = 0x00a0000c, .end = 0x00a00024 },
+	{ .start = 0x00a0002c, .end = 0x00a0003c },
+	{ .start = 0x00a00410, .end = 0x00a00418 },
+	{ .start = 0x00a00420, .end = 0x00a00420 },
+	{ .start = 0x00a00428, .end = 0x00a00428 },
+	{ .start = 0x00a00430, .end = 0x00a0043c },
+	{ .start = 0x00a00444, .end = 0x00a00444 },
+	{ .start = 0x00a004c0, .end = 0x00a004cc },
+	{ .start = 0x00a004d8, .end = 0x00a004d8 },
+	{ .start = 0x00a004e0, .end = 0x00a004f0 },
+	{ .start = 0x00a00840, .end = 0x00a00840 },
+	{ .start = 0x00a00850, .end = 0x00a00858 },
+	{ .start = 0x00a01004, .end = 0x00a01008 },
+	{ .start = 0x00a01010, .end = 0x00a01010 },
+	{ .start = 0x00a01018, .end = 0x00a01018 },
+	{ .start = 0x00a01024, .end = 0x00a01024 },
+	{ .start = 0x00a0102c, .end = 0x00a01034 },
+	{ .start = 0x00a0103c, .end = 0x00a01040 },
+	{ .start = 0x00a01048, .end = 0x00a01094 },
+	{ .start = 0x00a01c00, .end = 0x00a01c20 },
+	{ .start = 0x00a01c58, .end = 0x00a01c58 },
+	{ .start = 0x00a01c7c, .end = 0x00a01c7c },
+	{ .start = 0x00a01c28, .end = 0x00a01c54 },
+	{ .start = 0x00a01c5c, .end = 0x00a01c5c },
+	{ .start = 0x00a01c60, .end = 0x00a01cdc },
+	{ .start = 0x00a01ce0, .end = 0x00a01d0c },
+	{ .start = 0x00a01d18, .end = 0x00a01d20 },
+	{ .start = 0x00a01d2c, .end = 0x00a01d30 },
+	{ .start = 0x00a01d40, .end = 0x00a01d5c },
+	{ .start = 0x00a01d80, .end = 0x00a01d80 },
+	{ .start = 0x00a01d98, .end = 0x00a01d9c },
+	{ .start = 0x00a01da8, .end = 0x00a01da8 },
+	{ .start = 0x00a01db8, .end = 0x00a01df4 },
+	{ .start = 0x00a01dc0, .end = 0x00a01dfc },
+	{ .start = 0x00a01e00, .end = 0x00a01e2c },
+	{ .start = 0x00a01e40, .end = 0x00a01e60 },
+	{ .start = 0x00a01e68, .end = 0x00a01e6c },
+	{ .start = 0x00a01e74, .end = 0x00a01e74 },
+	{ .start = 0x00a01e84, .end = 0x00a01e90 },
+	{ .start = 0x00a01e9c, .end = 0x00a01ec4 },
+	{ .start = 0x00a01ed0, .end = 0x00a01ee0 },
+	{ .start = 0x00a01f00, .end = 0x00a01f1c },
+	{ .start = 0x00a01f44, .end = 0x00a01ffc },
+	{ .start = 0x00a02000, .end = 0x00a02048 },
+	{ .start = 0x00a02068, .end = 0x00a020f0 },
+	{ .start = 0x00a02100, .end = 0x00a02118 },
+	{ .start = 0x00a02140, .end = 0x00a0214c },
+	{ .start = 0x00a02168, .end = 0x00a0218c },
+	{ .start = 0x00a021c0, .end = 0x00a021c0 },
+	{ .start = 0x00a02400, .end = 0x00a02410 },
+	{ .start = 0x00a02418, .end = 0x00a02420 },
+	{ .start = 0x00a02428, .end = 0x00a0242c },
+	{ .start = 0x00a02434, .end = 0x00a02434 },
+	{ .start = 0x00a02440, .end = 0x00a02460 },
+	{ .start = 0x00a02468, .end = 0x00a024b0 },
+	{ .start = 0x00a024c8, .end = 0x00a024cc },
+	{ .start = 0x00a02500, .end = 0x00a02504 },
+	{ .start = 0x00a0250c, .end = 0x00a02510 },
+	{ .start = 0x00a02540, .end = 0x00a02554 },
+	{ .start = 0x00a02580, .end = 0x00a025f4 },
+	{ .start = 0x00a02600, .end = 0x00a0260c },
+	{ .start = 0x00a02648, .end = 0x00a02650 },
+	{ .start = 0x00a02680, .end = 0x00a02680 },
+	{ .start = 0x00a026c0, .end = 0x00a026d0 },
+	{ .start = 0x00a02700, .end = 0x00a0270c },
+	{ .start = 0x00a02804, .end = 0x00a02804 },
+	{ .start = 0x00a02818, .end = 0x00a0281c },
+	{ .start = 0x00a02c00, .end = 0x00a02db4 },
+	{ .start = 0x00a02df4, .end = 0x00a02fb0 },
+	{ .start = 0x00a03000, .end = 0x00a03014 },
+	{ .start = 0x00a0301c, .end = 0x00a0302c },
+	{ .start = 0x00a03034, .end = 0x00a03038 },
+	{ .start = 0x00a03040, .end = 0x00a03048 },
+	{ .start = 0x00a03060, .end = 0x00a03068 },
+	{ .start = 0x00a03070, .end = 0x00a03074 },
+	{ .start = 0x00a0307c, .end = 0x00a0307c },
+	{ .start = 0x00a03080, .end = 0x00a03084 },
+	{ .start = 0x00a0308c, .end = 0x00a03090 },
+	{ .start = 0x00a03098, .end = 0x00a03098 },
+	{ .start = 0x00a030a0, .end = 0x00a030a0 },
+	{ .start = 0x00a030a8, .end = 0x00a030b4 },
+	{ .start = 0x00a030bc, .end = 0x00a030bc },
+	{ .start = 0x00a030c0, .end = 0x00a0312c },
+	{ .start = 0x00a03c00, .end = 0x00a03c5c },
+	{ .start = 0x00a04400, .end = 0x00a04454 },
+	{ .start = 0x00a04460, .end = 0x00a04474 },
+	{ .start = 0x00a044c0, .end = 0x00a044ec },
+	{ .start = 0x00a04500, .end = 0x00a04504 },
+	{ .start = 0x00a04510, .end = 0x00a04538 },
+	{ .start = 0x00a04540, .end = 0x00a04548 },
+	{ .start = 0x00a04560, .end = 0x00a0457c },
+	{ .start = 0x00a04590, .end = 0x00a04598 },
+	{ .start = 0x00a045c0, .end = 0x00a045f4 },
+};
+
+static const struct iwl_prph_range iwl_prph_dump_addr_9000[] = {
+	{ .start = 0x00a05c00, .end = 0x00a05c18 },
+	{ .start = 0x00a05400, .end = 0x00a056e8 },
+	{ .start = 0x00a08000, .end = 0x00a098bc },
+	{ .start = 0x00a02400, .end = 0x00a02758 },
+	{ .start = 0x00a04764, .end = 0x00a0476c },
+	{ .start = 0x00a04770, .end = 0x00a04774 },
+	{ .start = 0x00a04620, .end = 0x00a04624 },
+};
+
+static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = {
+	{ .start = 0x00a00000, .end = 0x00a00000 },
+	{ .start = 0x00a0000c, .end = 0x00a00024 },
+	{ .start = 0x00a0002c, .end = 0x00a00034 },
+	{ .start = 0x00a0003c, .end = 0x00a0003c },
+	{ .start = 0x00a00410, .end = 0x00a00418 },
+	{ .start = 0x00a00420, .end = 0x00a00420 },
+	{ .start = 0x00a00428, .end = 0x00a00428 },
+	{ .start = 0x00a00430, .end = 0x00a0043c },
+	{ .start = 0x00a00444, .end = 0x00a00444 },
+	{ .start = 0x00a00840, .end = 0x00a00840 },
+	{ .start = 0x00a00850, .end = 0x00a00858 },
+	{ .start = 0x00a01004, .end = 0x00a01008 },
+	{ .start = 0x00a01010, .end = 0x00a01010 },
+	{ .start = 0x00a01018, .end = 0x00a01018 },
+	{ .start = 0x00a01024, .end = 0x00a01024 },
+	{ .start = 0x00a0102c, .end = 0x00a01034 },
+	{ .start = 0x00a0103c, .end = 0x00a01040 },
+	{ .start = 0x00a01048, .end = 0x00a01050 },
+	{ .start = 0x00a01058, .end = 0x00a01058 },
+	{ .start = 0x00a01060, .end = 0x00a01070 },
+	{ .start = 0x00a0108c, .end = 0x00a0108c },
+	{ .start = 0x00a01c20, .end = 0x00a01c28 },
+	{ .start = 0x00a01d10, .end = 0x00a01d10 },
+	{ .start = 0x00a01e28, .end = 0x00a01e2c },
+	{ .start = 0x00a01e60, .end = 0x00a01e60 },
+	{ .start = 0x00a01e80, .end = 0x00a01e80 },
+	{ .start = 0x00a01ea0, .end = 0x00a01ea0 },
+	{ .start = 0x00a02000, .end = 0x00a0201c },
+	{ .start = 0x00a02024, .end = 0x00a02024 },
+	{ .start = 0x00a02040, .end = 0x00a02048 },
+	{ .start = 0x00a020c0, .end = 0x00a020e0 },
+	{ .start = 0x00a02400, .end = 0x00a02404 },
+	{ .start = 0x00a0240c, .end = 0x00a02414 },
+	{ .start = 0x00a0241c, .end = 0x00a0243c },
+	{ .start = 0x00a02448, .end = 0x00a024bc },
+	{ .start = 0x00a024c4, .end = 0x00a024cc },
+	{ .start = 0x00a02508, .end = 0x00a02508 },
+	{ .start = 0x00a02510, .end = 0x00a02514 },
+	{ .start = 0x00a0251c, .end = 0x00a0251c },
+	{ .start = 0x00a0252c, .end = 0x00a0255c },
+	{ .start = 0x00a02564, .end = 0x00a025a0 },
+	{ .start = 0x00a025a8, .end = 0x00a025b4 },
+	{ .start = 0x00a025c0, .end = 0x00a025c0 },
+	{ .start = 0x00a025e8, .end = 0x00a025f4 },
+	{ .start = 0x00a02c08, .end = 0x00a02c18 },
+	{ .start = 0x00a02c2c, .end = 0x00a02c38 },
+	{ .start = 0x00a02c68, .end = 0x00a02c78 },
+	{ .start = 0x00a03000, .end = 0x00a03000 },
+	{ .start = 0x00a03010, .end = 0x00a03014 },
+	{ .start = 0x00a0301c, .end = 0x00a0302c },
+	{ .start = 0x00a03034, .end = 0x00a03038 },
+	{ .start = 0x00a03040, .end = 0x00a03044 },
+	{ .start = 0x00a03060, .end = 0x00a03068 },
+	{ .start = 0x00a03070, .end = 0x00a03070 },
+	{ .start = 0x00a0307c, .end = 0x00a03084 },
+	{ .start = 0x00a0308c, .end = 0x00a03090 },
+	{ .start = 0x00a03098, .end = 0x00a03098 },
+	{ .start = 0x00a030a0, .end = 0x00a030a0 },
+	{ .start = 0x00a030a8, .end = 0x00a030b4 },
+	{ .start = 0x00a030bc, .end = 0x00a030c0 },
+	{ .start = 0x00a030c8, .end = 0x00a030f4 },
+	{ .start = 0x00a03100, .end = 0x00a0312c },
+	{ .start = 0x00a03c00, .end = 0x00a03c5c },
+	{ .start = 0x00a04400, .end = 0x00a04454 },
+	{ .start = 0x00a04460, .end = 0x00a04474 },
+	{ .start = 0x00a044c0, .end = 0x00a044ec },
+	{ .start = 0x00a04500, .end = 0x00a04504 },
+	{ .start = 0x00a04510, .end = 0x00a04538 },
+	{ .start = 0x00a04540, .end = 0x00a04548 },
+	{ .start = 0x00a04560, .end = 0x00a04560 },
+	{ .start = 0x00a04570, .end = 0x00a0457c },
+	{ .start = 0x00a04590, .end = 0x00a04590 },
+	{ .start = 0x00a04598, .end = 0x00a04598 },
+	{ .start = 0x00a045c0, .end = 0x00a045f4 },
+	{ .start = 0x00a05c18, .end = 0x00a05c1c },
+	{ .start = 0x00a0c000, .end = 0x00a0c018 },
+	{ .start = 0x00a0c020, .end = 0x00a0c028 },
+	{ .start = 0x00a0c038, .end = 0x00a0c094 },
+	{ .start = 0x00a0c0c0, .end = 0x00a0c104 },
+	{ .start = 0x00a0c10c, .end = 0x00a0c118 },
+	{ .start = 0x00a0c150, .end = 0x00a0c174 },
+	{ .start = 0x00a0c17c, .end = 0x00a0c188 },
+	{ .start = 0x00a0c190, .end = 0x00a0c198 },
+	{ .start = 0x00a0c1a0, .end = 0x00a0c1a8 },
+	{ .start = 0x00a0c1b0, .end = 0x00a0c1b8 },
+};
+
+static const struct iwl_prph_range iwl_prph_dump_addr_ax210[] = {
+	{ .start = 0x00d03c00, .end = 0x00d03c64 },
+	{ .start = 0x00d05c18, .end = 0x00d05c1c },
+	{ .start = 0x00d0c000, .end = 0x00d0c174 },
+};
+
+static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
+				u32 len_bytes, __le32 *data)
+{
+	u32 i;
+
+	for (i = 0; i < len_bytes; i += 4)
+		*data++ = cpu_to_le32(iwl_trans_read_prph(trans, start + i));
+}
+
+static void iwl_dump_prph(struct iwl_fw_runtime *fwrt,
+			  const struct iwl_prph_range *iwl_prph_dump_addr,
+			  u32 range_len, void *ptr)
+{
+	struct iwl_fw_error_dump_prph *prph;
+	struct iwl_trans *trans = fwrt->trans;
+	struct iwl_fw_error_dump_data **data =
+		(struct iwl_fw_error_dump_data **)ptr;
+	u32 i;
+
+	if (!data)
+		return;
+
+	IWL_DEBUG_INFO(trans, "WRT PRPH dump\n");
+
+	if (!iwl_trans_grab_nic_access(trans))
+		return;
+
+	for (i = 0; i < range_len; i++) {
+		/* The range includes both boundaries */
+		int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
+			 iwl_prph_dump_addr[i].start + 4;
+
+		(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
+		(*data)->len = cpu_to_le32(sizeof(*prph) +
+					num_bytes_in_chunk);
+		prph = (void *)(*data)->data;
+		prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
+
+		iwl_read_prph_block(trans, iwl_prph_dump_addr[i].start,
+				    /* our range is inclusive, hence + 4 */
+				    iwl_prph_dump_addr[i].end -
+				    iwl_prph_dump_addr[i].start + 4,
+				    (void *)prph->data);
+
+		*data = iwl_fw_error_next_data(*data);
+	}
+
+	iwl_trans_release_nic_access(trans);
+}
+
+static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt,
+				const struct iwl_prph_range *iwl_prph_dump_addr,
+				u32 range_len, void *ptr)
+{
+	u32 *prph_len = (u32 *)ptr;
+	int i, num_bytes_in_chunk;
+
+	if (!prph_len)
+		return;
+
+	for (i = 0; i < range_len; i++) {
+		/* The range includes both boundaries */
+		num_bytes_in_chunk =
+			iwl_prph_dump_addr[i].end -
+			iwl_prph_dump_addr[i].start + 4;
+
+		*prph_len += sizeof(struct iwl_fw_error_dump_data) +
+			sizeof(struct iwl_fw_error_dump_prph) +
+			num_bytes_in_chunk;
+	}
+}
+
+static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
+				void (*handler)(struct iwl_fw_runtime *,
+						const struct iwl_prph_range *,
+						u32, void *))
+{
+	u32 range_len;
+
+	if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+		range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210);
+		handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr);
+	} else if (fwrt->trans->mac_cfg->device_family >=
+		   IWL_DEVICE_FAMILY_22000) {
+		range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
+		handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
+	} else {
+		range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm);
+		handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr);
+
+		if (fwrt->trans->mac_cfg->mq_rx_supported) {
+			range_len = ARRAY_SIZE(iwl_prph_dump_addr_9000);
+			handler(fwrt, iwl_prph_dump_addr_9000, range_len, ptr);
+		}
+	}
+}
+
+static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
+			    struct iwl_fw_error_dump_data **dump_data,
+			    u32 len, u32 ofs, u32 type)
+{
+	struct iwl_fw_error_dump_mem *dump_mem;
+
+	if (!len)
+		return;
+
+	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
+	(*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem));
+	dump_mem = (void *)(*dump_data)->data;
+	dump_mem->type = cpu_to_le32(type);
+	dump_mem->offset = cpu_to_le32(ofs);
+	iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
+	*dump_data = iwl_fw_error_next_data(*dump_data);
+
+	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+		fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, ofs,
+					     dump_mem->data, len);
+
+	IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
+}
+
+#define ADD_LEN(len, item_len, const_len) \
+	do {size_t item = item_len; len += (!!item) * const_len + item; } \
+	while (0)
+
+static int iwl_fw_rxf_len(struct iwl_fw_runtime *fwrt,
+			  struct iwl_fwrt_shared_mem_cfg *mem_cfg)
+{
+	size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
+			 sizeof(struct iwl_fw_error_dump_fifo);
+	u32 fifo_len = 0;
+	int i;
+
+	if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF))
+		return 0;
+
+	/* Count RXF2 size */
+	ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len);
+
+	/* Count RXF1 sizes */
+	if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
+		mem_cfg->num_lmacs = MAX_NUM_LMAC;
+
+	for (i = 0; i < mem_cfg->num_lmacs; i++)
+		ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len);
+
+	return fifo_len;
+}
+
+static int iwl_fw_txf_len(struct iwl_fw_runtime *fwrt,
+			  struct iwl_fwrt_shared_mem_cfg *mem_cfg)
+{
+	size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
+			 sizeof(struct iwl_fw_error_dump_fifo);
+	u32 fifo_len = 0;
+	int i;
+
+	if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF))
+		goto dump_internal_txf;
+
+	/* Count TXF sizes */
+	if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
+		mem_cfg->num_lmacs = MAX_NUM_LMAC;
+
+	for (i = 0; i < mem_cfg->num_lmacs; i++) {
+		int j;
+
+		for (j = 0; j < mem_cfg->num_txfifo_entries; j++)
+			ADD_LEN(fifo_len, mem_cfg->lmac[i].txfifo_size[j],
+				hdr_len);
+	}
+
+dump_internal_txf:
+	if (!(iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
+	      fw_has_capa(&fwrt->fw->ucode_capa,
+			  IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)))
+		goto out;
+
+	for (i = 0; i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); i++)
+		ADD_LEN(fifo_len, mem_cfg->internal_txfifo_size[i], hdr_len);
+
+out:
+	return fifo_len;
+}
+
+static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
+			    struct iwl_fw_error_dump_data **data)
+{
+	int i;
+
+	IWL_DEBUG_INFO(fwrt, "WRT paging dump\n");
+	for (i = 1; i < fwrt->num_of_paging_blk + 1; i++) {
+		struct iwl_fw_error_dump_paging *paging;
+		struct page *pages =
+			fwrt->fw_paging_db[i].fw_paging_block;
+		dma_addr_t addr = fwrt->fw_paging_db[i].fw_paging_phys;
+
+		(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
+		(*data)->len = cpu_to_le32(sizeof(*paging) +
+					     PAGING_BLOCK_SIZE);
+		paging =  (void *)(*data)->data;
+		paging->index = cpu_to_le32(i);
+		dma_sync_single_for_cpu(fwrt->trans->dev, addr,
+					PAGING_BLOCK_SIZE,
+					DMA_BIDIRECTIONAL);
+		memcpy(paging->data, page_address(pages),
+		       PAGING_BLOCK_SIZE);
+		dma_sync_single_for_device(fwrt->trans->dev, addr,
+					   PAGING_BLOCK_SIZE,
+					   DMA_BIDIRECTIONAL);
+		(*data) = iwl_fw_error_next_data(*data);
+
+		if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+			fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
+						     fwrt->fw_paging_db[i].fw_offs,
+						     paging->data,
+						     PAGING_BLOCK_SIZE);
+	}
+}
+
+static struct iwl_fw_error_dump_file *
+iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
+		       struct iwl_fw_dump_ptrs *fw_error_dump,
+		       struct iwl_fwrt_dump_data *data)
+{
+	struct iwl_fw_error_dump_file *dump_file;
+	struct iwl_fw_error_dump_data *dump_data;
+	struct iwl_fw_error_dump_info *dump_info;
+	struct iwl_fw_error_dump_smem_cfg *dump_smem_cfg;
+	struct iwl_fw_error_dump_trigger_desc *dump_trig;
+	u32 sram_len, sram_ofs;
+	const struct iwl_fw_dbg_mem_seg_tlv *fw_mem = fwrt->fw->dbg.mem_tlv;
+	struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
+	u32 file_len, fifo_len = 0, prph_len = 0, radio_len = 0;
+	u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->mac_cfg->base->smem_len;
+	u32 sram2_len = fwrt->fw->dbg.n_mem_tlv ?
+				0 : fwrt->trans->cfg->dccm2_len;
+	int i;
+
+	/* SRAM - include stack CCM if driver knows the values for it */
+	if (!fwrt->trans->cfg->dccm_offset ||
+	    !fwrt->trans->cfg->dccm_len) {
+		const struct fw_img *img;
+
+		if (fwrt->cur_fw_img >= IWL_UCODE_TYPE_MAX)
+			return NULL;
+		img = &fwrt->fw->img[fwrt->cur_fw_img];
+		sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
+		sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
+	} else {
+		sram_ofs = fwrt->trans->cfg->dccm_offset;
+		sram_len = fwrt->trans->cfg->dccm_len;
+	}
+
+	/* reading RXF/TXF sizes */
+	if (iwl_trans_is_fw_error(fwrt->trans)) {
+		fifo_len = iwl_fw_rxf_len(fwrt, mem_cfg);
+		fifo_len += iwl_fw_txf_len(fwrt, mem_cfg);
+
+		/* Make room for PRPH registers */
+		if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PRPH))
+			iwl_fw_prph_handler(fwrt, &prph_len,
+					    iwl_fw_get_prph_len);
+
+		if (fwrt->trans->mac_cfg->device_family ==
+		    IWL_DEVICE_FAMILY_7000 &&
+		    iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RADIO_REG))
+			radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
+	}
+
+	file_len = sizeof(*dump_file) + fifo_len + prph_len + radio_len;
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_DEV_FW_INFO))
+		file_len += sizeof(*dump_data) + sizeof(*dump_info);
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM_CFG))
+		file_len += sizeof(*dump_data) + sizeof(*dump_smem_cfg);
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
+		size_t hdr_len = sizeof(*dump_data) +
+				 sizeof(struct iwl_fw_error_dump_mem);
+
+		/* Dump SRAM only if no mem_tlvs */
+		if (!fwrt->fw->dbg.n_mem_tlv)
+			ADD_LEN(file_len, sram_len, hdr_len);
+
+		/* Make room for all mem types that exist */
+		ADD_LEN(file_len, smem_len, hdr_len);
+		ADD_LEN(file_len, sram2_len, hdr_len);
+
+		for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++)
+			ADD_LEN(file_len, le32_to_cpu(fw_mem[i].len), hdr_len);
+	}
+
+	/* Make room for fw's virtual image pages, if it exists */
+	if (iwl_fw_dbg_is_paging_enabled(fwrt))
+		file_len += fwrt->num_of_paging_blk *
+			(sizeof(*dump_data) +
+			 sizeof(struct iwl_fw_error_dump_paging) +
+			 PAGING_BLOCK_SIZE);
+
+	if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
+		file_len += sizeof(*dump_data) +
+			fwrt->trans->mac_cfg->base->d3_debug_data_length * 2;
+	}
+
+	/* If we only want a monitor dump, reset the file length */
+	if (data->monitor_only) {
+		file_len = sizeof(*dump_file) + sizeof(*dump_data) * 2 +
+			   sizeof(*dump_info) + sizeof(*dump_smem_cfg);
+	}
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
+	    data->desc)
+		file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
+			data->desc->len;
+
+	dump_file = vzalloc(file_len);
+	if (!dump_file)
+		return NULL;
+
+	fw_error_dump->fwrt_ptr = dump_file;
+
+	dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
+	dump_data = (void *)dump_file->data;
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_DEV_FW_INFO)) {
+		dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
+		dump_data->len = cpu_to_le32(sizeof(*dump_info));
+		dump_info = (void *)dump_data->data;
+		dump_info->hw_type =
+			cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev));
+		dump_info->hw_step =
+			cpu_to_le32(fwrt->trans->info.hw_rev_step);
+		memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
+		       sizeof(dump_info->fw_human_readable));
+		strscpy_pad(dump_info->dev_human_readable,
+			    fwrt->trans->info.name,
+			    sizeof(dump_info->dev_human_readable));
+		strscpy_pad(dump_info->bus_human_readable, fwrt->dev->bus->name,
+			sizeof(dump_info->bus_human_readable));
+		dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs;
+		dump_info->lmac_err_id[0] =
+			cpu_to_le32(fwrt->dump.lmac_err_id[0]);
+		if (fwrt->smem_cfg.num_lmacs > 1)
+			dump_info->lmac_err_id[1] =
+				cpu_to_le32(fwrt->dump.lmac_err_id[1]);
+		dump_info->umac_err_id = cpu_to_le32(fwrt->dump.umac_err_id);
+
+		dump_data = iwl_fw_error_next_data(dump_data);
+	}
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM_CFG)) {
+		/* Dump shared memory configuration */
+		dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
+		dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
+		dump_smem_cfg = (void *)dump_data->data;
+		dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
+		dump_smem_cfg->num_txfifo_entries =
+			cpu_to_le32(mem_cfg->num_txfifo_entries);
+		for (i = 0; i < MAX_NUM_LMAC; i++) {
+			int j;
+			u32 *txf_size = mem_cfg->lmac[i].txfifo_size;
+
+			for (j = 0; j < TX_FIFO_MAX_NUM; j++)
+				dump_smem_cfg->lmac[i].txfifo_size[j] =
+					cpu_to_le32(txf_size[j]);
+			dump_smem_cfg->lmac[i].rxfifo1_size =
+				cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
+		}
+		dump_smem_cfg->rxfifo2_size =
+			cpu_to_le32(mem_cfg->rxfifo2_size);
+		dump_smem_cfg->internal_txfifo_addr =
+			cpu_to_le32(mem_cfg->internal_txfifo_addr);
+		for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
+			dump_smem_cfg->internal_txfifo_size[i] =
+				cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
+		}
+
+		dump_data = iwl_fw_error_next_data(dump_data);
+	}
+
+	/* We only dump the FIFOs if the FW is in error state */
+	if (fifo_len) {
+		iwl_fw_dump_rxf(fwrt, &dump_data);
+		iwl_fw_dump_txf(fwrt, &dump_data);
+	}
+
+	if (radio_len)
+		iwl_read_radio_regs(fwrt, &dump_data);
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
+	    data->desc) {
+		dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
+		dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
+					     data->desc->len);
+		dump_trig = (void *)dump_data->data;
+		memcpy(dump_trig, &data->desc->trig_desc,
+		       sizeof(*dump_trig) + data->desc->len);
+
+		dump_data = iwl_fw_error_next_data(dump_data);
+	}
+
+	/* In case we only want monitor dump, skip to dump transport data */
+	if (data->monitor_only)
+		goto out;
+
+	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
+		const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem =
+			fwrt->fw->dbg.mem_tlv;
+
+		if (!fwrt->fw->dbg.n_mem_tlv)
+			iwl_fw_dump_mem(fwrt, &dump_data, sram_len, sram_ofs,
+					IWL_FW_ERROR_DUMP_MEM_SRAM);
+
+		for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++) {
+			u32 len = le32_to_cpu(fw_dbg_mem[i].len);
+			u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
+
+			iwl_fw_dump_mem(fwrt, &dump_data, len, ofs,
+					le32_to_cpu(fw_dbg_mem[i].data_type));
+		}
+
+		iwl_fw_dump_mem(fwrt, &dump_data, smem_len,
+				fwrt->trans->mac_cfg->base->smem_offset,
+				IWL_FW_ERROR_DUMP_MEM_SMEM);
+
+		iwl_fw_dump_mem(fwrt, &dump_data, sram2_len,
+				fwrt->trans->cfg->dccm2_offset,
+				IWL_FW_ERROR_DUMP_MEM_SRAM);
+	}
+
+	if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
+		u32 addr = fwrt->trans->mac_cfg->base->d3_debug_data_base_addr;
+		size_t data_size = fwrt->trans->mac_cfg->base->d3_debug_data_length;
+
+		dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
+		dump_data->len = cpu_to_le32(data_size * 2);
+
+		memcpy(dump_data->data, fwrt->dump.d3_debug_data, data_size);
+
+		kfree(fwrt->dump.d3_debug_data);
+		fwrt->dump.d3_debug_data = NULL;
+
+		iwl_trans_read_mem_bytes(fwrt->trans, addr,
+					 dump_data->data + data_size,
+					 data_size);
+
+		if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+			fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, addr,
+						     dump_data->data + data_size,
+						     data_size);
+
+		dump_data = iwl_fw_error_next_data(dump_data);
+	}
+
+	/* Dump fw's virtual image */
+	if (iwl_fw_dbg_is_paging_enabled(fwrt))
+		iwl_dump_paging(fwrt, &dump_data);
+
+	if (prph_len)
+		iwl_fw_prph_handler(fwrt, &dump_data, iwl_dump_prph);
+
+out:
+	dump_file->file_len = cpu_to_le32(file_len);
+	return dump_file;
+}
+
+void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
+		       struct iwl_fwrt_dump_data *dump_data)
+{
+	struct iwl_fw_dump_ptrs fw_error_dump = {};
+	struct iwl_fw_error_dump_file *dump_file;
+	struct scatterlist *sg_dump_data;
+	u32 file_len;
+	u32 dump_mask = fwrt->fw->dbg.dump_mask;
+
+	dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump, dump_data);
+	if (!dump_file)
+		return;
+
+	if (dump_data->monitor_only)
+		dump_mask &= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR);
+
+	fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask,
+						      fwrt->sanitize_ops,
+						      fwrt->sanitize_ctx);
+	file_len = le32_to_cpu(dump_file->file_len);
+	fw_error_dump.fwrt_len = file_len;
+
+	if (fw_error_dump.trans_ptr) {
+		file_len += fw_error_dump.trans_ptr->len;
+		dump_file->file_len = cpu_to_le32(file_len);
+	}
+
+	sg_dump_data = iwl_fw_dbg_alloc_sgtable(file_len);
+	if (sg_dump_data) {
+		sg_pcopy_from_buffer(sg_dump_data,
+				     sg_nents(sg_dump_data),
+				     fw_error_dump.fwrt_ptr,
+				     fw_error_dump.fwrt_len, 0);
+		if (fw_error_dump.trans_ptr)
+			sg_pcopy_from_buffer(sg_dump_data,
+					     sg_nents(sg_dump_data),
+					     fw_error_dump.trans_ptr->data,
+					     fw_error_dump.trans_ptr->len,
+					     fw_error_dump.fwrt_len);
+		dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
+			       GFP_KERNEL);
+	}
+	vfree(fw_error_dump.fwrt_ptr);
+	vfree(fw_error_dump.trans_ptr);
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 18667de4915f..64ead8ecd52c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -13,556 +13,13 @@
 #include "iwl-prph.h"
 #include "iwl-csr.h"
 #include "iwl-fh.h"
-/**
- * struct iwl_fw_dump_ptrs - set of pointers needed for the fw-error-dump
- *
- * @fwrt_ptr: pointer to the buffer coming from fwrt
- * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
- *	transport's data.
- * @fwrt_len: length of the valid data in fwrt_ptr
- */
-struct iwl_fw_dump_ptrs {
-	struct iwl_trans_dump_data *trans_ptr;
-	void *fwrt_ptr;
-	u32 fwrt_len;
-};
-
-#define RADIO_REG_MAX_READ 0x2ad
-static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt,
-				struct iwl_fw_error_dump_data **dump_data)
-{
-	u8 *pos = (void *)(*dump_data)->data;
-	int i;
-
-	IWL_DEBUG_INFO(fwrt, "WRT radio registers dump\n");
-
-	if (!iwl_trans_grab_nic_access(fwrt->trans))
-		return;
-
-	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RADIO_REG);
-	(*dump_data)->len = cpu_to_le32(RADIO_REG_MAX_READ);
-
-	for (i = 0; i < RADIO_REG_MAX_READ; i++) {
-		u32 rd_cmd = RADIO_RSP_RD_CMD;
-
-		rd_cmd |= i << RADIO_RSP_ADDR_POS;
-		iwl_trans_write_prph(fwrt->trans, RSP_RADIO_CMD, rd_cmd);
-		*pos = (u8)iwl_trans_read_prph(fwrt->trans, RSP_RADIO_RDDAT);
-
-		pos++;
-	}
-
-	*dump_data = iwl_fw_error_next_data(*dump_data);
-
-	iwl_trans_release_nic_access(fwrt->trans);
-}
-
-static void iwl_fwrt_dump_rxf(struct iwl_fw_runtime *fwrt,
-			      struct iwl_fw_error_dump_data **dump_data,
-			      int size, u32 offset, int fifo_num)
-{
-	struct iwl_fw_error_dump_fifo *fifo_hdr;
-	u32 *fifo_data;
-	u32 fifo_len;
-	int i;
-
-	fifo_hdr = (void *)(*dump_data)->data;
-	fifo_data = (void *)fifo_hdr->data;
-	fifo_len = size;
-
-	/* No need to try to read the data if the length is 0 */
-	if (fifo_len == 0)
-		return;
-
-	/* Add a TLV for the RXF */
-	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
-	(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
-
-	fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
-	fifo_hdr->available_bytes =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						RXF_RD_D_SPACE + offset));
-	fifo_hdr->wr_ptr =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						RXF_RD_WR_PTR + offset));
-	fifo_hdr->rd_ptr =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						RXF_RD_RD_PTR + offset));
-	fifo_hdr->fence_ptr =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						RXF_RD_FENCE_PTR + offset));
-	fifo_hdr->fence_mode =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						RXF_SET_FENCE_MODE + offset));
-
-	/* Lock fence */
-	iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1);
-	/* Set fence pointer to the same place like WR pointer */
-	iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offset, 0x1);
-	/* Set fence offset */
-	iwl_trans_write_prph(fwrt->trans,
-			     RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0);
-
-	/* Read FIFO */
-	fifo_len /= sizeof(u32); /* Size in DWORDS */
-	for (i = 0; i < fifo_len; i++)
-		fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
-						 RXF_FIFO_RD_FENCE_INC +
-						 offset);
-	*dump_data = iwl_fw_error_next_data(*dump_data);
-}
-
-static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt,
-			      struct iwl_fw_error_dump_data **dump_data,
-			      int size, u32 offset, int fifo_num)
-{
-	struct iwl_fw_error_dump_fifo *fifo_hdr;
-	u32 *fifo_data;
-	u32 fifo_len;
-	int i;
-
-	fifo_hdr = (void *)(*dump_data)->data;
-	fifo_data = (void *)fifo_hdr->data;
-	fifo_len = size;
-
-	/* No need to try to read the data if the length is 0 */
-	if (fifo_len == 0)
-		return;
-
-	/* Add a TLV for the FIFO */
-	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXF);
-	(*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
-
-	fifo_hdr->fifo_num = cpu_to_le32(fifo_num);
-	fifo_hdr->available_bytes =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						TXF_FIFO_ITEM_CNT + offset));
-	fifo_hdr->wr_ptr =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						TXF_WR_PTR + offset));
-	fifo_hdr->rd_ptr =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						TXF_RD_PTR + offset));
-	fifo_hdr->fence_ptr =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						TXF_FENCE_PTR + offset));
-	fifo_hdr->fence_mode =
-		cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-						TXF_LOCK_FENCE + offset));
-
-	/* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */
-	iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offset,
-			     TXF_WR_PTR + offset);
-
-	/* Dummy-read to advance the read pointer to the head */
-	iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset);
-
-	/* Read FIFO */
-	for (i = 0; i < fifo_len / sizeof(u32); i++)
-		fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
-						  TXF_READ_MODIFY_DATA +
-						  offset);
-
-	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
-		fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
-					     fifo_data, fifo_len);
-
-	*dump_data = iwl_fw_error_next_data(*dump_data);
-}
-
-static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt,
-			    struct iwl_fw_error_dump_data **dump_data)
-{
-	struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
-
-	IWL_DEBUG_INFO(fwrt, "WRT RX FIFO dump\n");
-
-	if (!iwl_trans_grab_nic_access(fwrt->trans))
-		return;
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF)) {
-		/* Pull RXF1 */
-		iwl_fwrt_dump_rxf(fwrt, dump_data,
-				  cfg->lmac[0].rxfifo1_size, 0, 0);
-		/* Pull RXF2 */
-		iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
-				  RXF_DIFF_FROM_PREV +
-				  fwrt->trans->mac_cfg->umac_prph_offset, 1);
-		/* Pull LMAC2 RXF1 */
-		if (fwrt->smem_cfg.num_lmacs > 1)
-			iwl_fwrt_dump_rxf(fwrt, dump_data,
-					  cfg->lmac[1].rxfifo1_size,
-					  LMAC2_PRPH_OFFSET, 2);
-	}
-
-	iwl_trans_release_nic_access(fwrt->trans);
-}
-
-static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt,
-			    struct iwl_fw_error_dump_data **dump_data)
-{
-	struct iwl_fw_error_dump_fifo *fifo_hdr;
-	struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg;
-	u32 *fifo_data;
-	u32 fifo_len;
-	int i, j;
-
-	IWL_DEBUG_INFO(fwrt, "WRT TX FIFO dump\n");
-
-	if (!iwl_trans_grab_nic_access(fwrt->trans))
-		return;
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF)) {
-		/* Pull TXF data from LMAC1 */
-		for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
-			/* Mark the number of TXF we're pulling now */
-			iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
-			iwl_fwrt_dump_txf(fwrt, dump_data,
-					  cfg->lmac[0].txfifo_size[i], 0, i);
-		}
-
-		/* Pull TXF data from LMAC2 */
-		if (fwrt->smem_cfg.num_lmacs > 1) {
-			for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries;
-			     i++) {
-				/* Mark the number of TXF we're pulling now */
-				iwl_trans_write_prph(fwrt->trans,
-						     TXF_LARC_NUM +
-						     LMAC2_PRPH_OFFSET, i);
-				iwl_fwrt_dump_txf(fwrt, dump_data,
-						  cfg->lmac[1].txfifo_size[i],
-						  LMAC2_PRPH_OFFSET,
-						  i + cfg->num_txfifo_entries);
-			}
-		}
-	}
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
-	    fw_has_capa(&fwrt->fw->ucode_capa,
-			IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
-		/* Pull UMAC internal TXF data from all TXFs */
-		for (i = 0;
-		     i < ARRAY_SIZE(fwrt->smem_cfg.internal_txfifo_size);
-		     i++) {
-			fifo_hdr = (void *)(*dump_data)->data;
-			fifo_data = (void *)fifo_hdr->data;
-			fifo_len = fwrt->smem_cfg.internal_txfifo_size[i];
-
-			/* No need to try to read the data if the length is 0 */
-			if (fifo_len == 0)
-				continue;
-
-			/* Add a TLV for the internal FIFOs */
-			(*dump_data)->type =
-				cpu_to_le32(IWL_FW_ERROR_DUMP_INTERNAL_TXF);
-			(*dump_data)->len =
-				cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
-
-			fifo_hdr->fifo_num = cpu_to_le32(i);
-
-			/* Mark the number of TXF we're pulling now */
-			iwl_trans_write_prph(fwrt->trans, TXF_CPU2_NUM, i +
-				fwrt->smem_cfg.num_txfifo_entries);
-
-			fifo_hdr->available_bytes =
-				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-								TXF_CPU2_FIFO_ITEM_CNT));
-			fifo_hdr->wr_ptr =
-				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-								TXF_CPU2_WR_PTR));
-			fifo_hdr->rd_ptr =
-				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-								TXF_CPU2_RD_PTR));
-			fifo_hdr->fence_ptr =
-				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-								TXF_CPU2_FENCE_PTR));
-			fifo_hdr->fence_mode =
-				cpu_to_le32(iwl_trans_read_prph(fwrt->trans,
-								TXF_CPU2_LOCK_FENCE));
-
-			/* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */
-			iwl_trans_write_prph(fwrt->trans,
-					     TXF_CPU2_READ_MODIFY_ADDR,
-					     TXF_CPU2_WR_PTR);
-
-			/* Dummy-read to advance the read pointer to head */
-			iwl_trans_read_prph(fwrt->trans,
-					    TXF_CPU2_READ_MODIFY_DATA);
-
-			/* Read FIFO */
-			fifo_len /= sizeof(u32); /* Size in DWORDS */
-			for (j = 0; j < fifo_len; j++)
-				fifo_data[j] =
-					iwl_trans_read_prph(fwrt->trans,
-							    TXF_CPU2_READ_MODIFY_DATA);
-			*dump_data = iwl_fw_error_next_data(*dump_data);
-		}
-	}
-
-	iwl_trans_release_nic_access(fwrt->trans);
-}
-
-struct iwl_prph_range {
-	u32 start, end;
-};
-
-static const struct iwl_prph_range iwl_prph_dump_addr_comm[] = {
-	{ .start = 0x00a00000, .end = 0x00a00000 },
-	{ .start = 0x00a0000c, .end = 0x00a00024 },
-	{ .start = 0x00a0002c, .end = 0x00a0003c },
-	{ .start = 0x00a00410, .end = 0x00a00418 },
-	{ .start = 0x00a00420, .end = 0x00a00420 },
-	{ .start = 0x00a00428, .end = 0x00a00428 },
-	{ .start = 0x00a00430, .end = 0x00a0043c },
-	{ .start = 0x00a00444, .end = 0x00a00444 },
-	{ .start = 0x00a004c0, .end = 0x00a004cc },
-	{ .start = 0x00a004d8, .end = 0x00a004d8 },
-	{ .start = 0x00a004e0, .end = 0x00a004f0 },
-	{ .start = 0x00a00840, .end = 0x00a00840 },
-	{ .start = 0x00a00850, .end = 0x00a00858 },
-	{ .start = 0x00a01004, .end = 0x00a01008 },
-	{ .start = 0x00a01010, .end = 0x00a01010 },
-	{ .start = 0x00a01018, .end = 0x00a01018 },
-	{ .start = 0x00a01024, .end = 0x00a01024 },
-	{ .start = 0x00a0102c, .end = 0x00a01034 },
-	{ .start = 0x00a0103c, .end = 0x00a01040 },
-	{ .start = 0x00a01048, .end = 0x00a01094 },
-	{ .start = 0x00a01c00, .end = 0x00a01c20 },
-	{ .start = 0x00a01c58, .end = 0x00a01c58 },
-	{ .start = 0x00a01c7c, .end = 0x00a01c7c },
-	{ .start = 0x00a01c28, .end = 0x00a01c54 },
-	{ .start = 0x00a01c5c, .end = 0x00a01c5c },
-	{ .start = 0x00a01c60, .end = 0x00a01cdc },
-	{ .start = 0x00a01ce0, .end = 0x00a01d0c },
-	{ .start = 0x00a01d18, .end = 0x00a01d20 },
-	{ .start = 0x00a01d2c, .end = 0x00a01d30 },
-	{ .start = 0x00a01d40, .end = 0x00a01d5c },
-	{ .start = 0x00a01d80, .end = 0x00a01d80 },
-	{ .start = 0x00a01d98, .end = 0x00a01d9c },
-	{ .start = 0x00a01da8, .end = 0x00a01da8 },
-	{ .start = 0x00a01db8, .end = 0x00a01df4 },
-	{ .start = 0x00a01dc0, .end = 0x00a01dfc },
-	{ .start = 0x00a01e00, .end = 0x00a01e2c },
-	{ .start = 0x00a01e40, .end = 0x00a01e60 },
-	{ .start = 0x00a01e68, .end = 0x00a01e6c },
-	{ .start = 0x00a01e74, .end = 0x00a01e74 },
-	{ .start = 0x00a01e84, .end = 0x00a01e90 },
-	{ .start = 0x00a01e9c, .end = 0x00a01ec4 },
-	{ .start = 0x00a01ed0, .end = 0x00a01ee0 },
-	{ .start = 0x00a01f00, .end = 0x00a01f1c },
-	{ .start = 0x00a01f44, .end = 0x00a01ffc },
-	{ .start = 0x00a02000, .end = 0x00a02048 },
-	{ .start = 0x00a02068, .end = 0x00a020f0 },
-	{ .start = 0x00a02100, .end = 0x00a02118 },
-	{ .start = 0x00a02140, .end = 0x00a0214c },
-	{ .start = 0x00a02168, .end = 0x00a0218c },
-	{ .start = 0x00a021c0, .end = 0x00a021c0 },
-	{ .start = 0x00a02400, .end = 0x00a02410 },
-	{ .start = 0x00a02418, .end = 0x00a02420 },
-	{ .start = 0x00a02428, .end = 0x00a0242c },
-	{ .start = 0x00a02434, .end = 0x00a02434 },
-	{ .start = 0x00a02440, .end = 0x00a02460 },
-	{ .start = 0x00a02468, .end = 0x00a024b0 },
-	{ .start = 0x00a024c8, .end = 0x00a024cc },
-	{ .start = 0x00a02500, .end = 0x00a02504 },
-	{ .start = 0x00a0250c, .end = 0x00a02510 },
-	{ .start = 0x00a02540, .end = 0x00a02554 },
-	{ .start = 0x00a02580, .end = 0x00a025f4 },
-	{ .start = 0x00a02600, .end = 0x00a0260c },
-	{ .start = 0x00a02648, .end = 0x00a02650 },
-	{ .start = 0x00a02680, .end = 0x00a02680 },
-	{ .start = 0x00a026c0, .end = 0x00a026d0 },
-	{ .start = 0x00a02700, .end = 0x00a0270c },
-	{ .start = 0x00a02804, .end = 0x00a02804 },
-	{ .start = 0x00a02818, .end = 0x00a0281c },
-	{ .start = 0x00a02c00, .end = 0x00a02db4 },
-	{ .start = 0x00a02df4, .end = 0x00a02fb0 },
-	{ .start = 0x00a03000, .end = 0x00a03014 },
-	{ .start = 0x00a0301c, .end = 0x00a0302c },
-	{ .start = 0x00a03034, .end = 0x00a03038 },
-	{ .start = 0x00a03040, .end = 0x00a03048 },
-	{ .start = 0x00a03060, .end = 0x00a03068 },
-	{ .start = 0x00a03070, .end = 0x00a03074 },
-	{ .start = 0x00a0307c, .end = 0x00a0307c },
-	{ .start = 0x00a03080, .end = 0x00a03084 },
-	{ .start = 0x00a0308c, .end = 0x00a03090 },
-	{ .start = 0x00a03098, .end = 0x00a03098 },
-	{ .start = 0x00a030a0, .end = 0x00a030a0 },
-	{ .start = 0x00a030a8, .end = 0x00a030b4 },
-	{ .start = 0x00a030bc, .end = 0x00a030bc },
-	{ .start = 0x00a030c0, .end = 0x00a0312c },
-	{ .start = 0x00a03c00, .end = 0x00a03c5c },
-	{ .start = 0x00a04400, .end = 0x00a04454 },
-	{ .start = 0x00a04460, .end = 0x00a04474 },
-	{ .start = 0x00a044c0, .end = 0x00a044ec },
-	{ .start = 0x00a04500, .end = 0x00a04504 },
-	{ .start = 0x00a04510, .end = 0x00a04538 },
-	{ .start = 0x00a04540, .end = 0x00a04548 },
-	{ .start = 0x00a04560, .end = 0x00a0457c },
-	{ .start = 0x00a04590, .end = 0x00a04598 },
-	{ .start = 0x00a045c0, .end = 0x00a045f4 },
-};
-
-static const struct iwl_prph_range iwl_prph_dump_addr_9000[] = {
-	{ .start = 0x00a05c00, .end = 0x00a05c18 },
-	{ .start = 0x00a05400, .end = 0x00a056e8 },
-	{ .start = 0x00a08000, .end = 0x00a098bc },
-	{ .start = 0x00a02400, .end = 0x00a02758 },
-	{ .start = 0x00a04764, .end = 0x00a0476c },
-	{ .start = 0x00a04770, .end = 0x00a04774 },
-	{ .start = 0x00a04620, .end = 0x00a04624 },
-};
-
-static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = {
-	{ .start = 0x00a00000, .end = 0x00a00000 },
-	{ .start = 0x00a0000c, .end = 0x00a00024 },
-	{ .start = 0x00a0002c, .end = 0x00a00034 },
-	{ .start = 0x00a0003c, .end = 0x00a0003c },
-	{ .start = 0x00a00410, .end = 0x00a00418 },
-	{ .start = 0x00a00420, .end = 0x00a00420 },
-	{ .start = 0x00a00428, .end = 0x00a00428 },
-	{ .start = 0x00a00430, .end = 0x00a0043c },
-	{ .start = 0x00a00444, .end = 0x00a00444 },
-	{ .start = 0x00a00840, .end = 0x00a00840 },
-	{ .start = 0x00a00850, .end = 0x00a00858 },
-	{ .start = 0x00a01004, .end = 0x00a01008 },
-	{ .start = 0x00a01010, .end = 0x00a01010 },
-	{ .start = 0x00a01018, .end = 0x00a01018 },
-	{ .start = 0x00a01024, .end = 0x00a01024 },
-	{ .start = 0x00a0102c, .end = 0x00a01034 },
-	{ .start = 0x00a0103c, .end = 0x00a01040 },
-	{ .start = 0x00a01048, .end = 0x00a01050 },
-	{ .start = 0x00a01058, .end = 0x00a01058 },
-	{ .start = 0x00a01060, .end = 0x00a01070 },
-	{ .start = 0x00a0108c, .end = 0x00a0108c },
-	{ .start = 0x00a01c20, .end = 0x00a01c28 },
-	{ .start = 0x00a01d10, .end = 0x00a01d10 },
-	{ .start = 0x00a01e28, .end = 0x00a01e2c },
-	{ .start = 0x00a01e60, .end = 0x00a01e60 },
-	{ .start = 0x00a01e80, .end = 0x00a01e80 },
-	{ .start = 0x00a01ea0, .end = 0x00a01ea0 },
-	{ .start = 0x00a02000, .end = 0x00a0201c },
-	{ .start = 0x00a02024, .end = 0x00a02024 },
-	{ .start = 0x00a02040, .end = 0x00a02048 },
-	{ .start = 0x00a020c0, .end = 0x00a020e0 },
-	{ .start = 0x00a02400, .end = 0x00a02404 },
-	{ .start = 0x00a0240c, .end = 0x00a02414 },
-	{ .start = 0x00a0241c, .end = 0x00a0243c },
-	{ .start = 0x00a02448, .end = 0x00a024bc },
-	{ .start = 0x00a024c4, .end = 0x00a024cc },
-	{ .start = 0x00a02508, .end = 0x00a02508 },
-	{ .start = 0x00a02510, .end = 0x00a02514 },
-	{ .start = 0x00a0251c, .end = 0x00a0251c },
-	{ .start = 0x00a0252c, .end = 0x00a0255c },
-	{ .start = 0x00a02564, .end = 0x00a025a0 },
-	{ .start = 0x00a025a8, .end = 0x00a025b4 },
-	{ .start = 0x00a025c0, .end = 0x00a025c0 },
-	{ .start = 0x00a025e8, .end = 0x00a025f4 },
-	{ .start = 0x00a02c08, .end = 0x00a02c18 },
-	{ .start = 0x00a02c2c, .end = 0x00a02c38 },
-	{ .start = 0x00a02c68, .end = 0x00a02c78 },
-	{ .start = 0x00a03000, .end = 0x00a03000 },
-	{ .start = 0x00a03010, .end = 0x00a03014 },
-	{ .start = 0x00a0301c, .end = 0x00a0302c },
-	{ .start = 0x00a03034, .end = 0x00a03038 },
-	{ .start = 0x00a03040, .end = 0x00a03044 },
-	{ .start = 0x00a03060, .end = 0x00a03068 },
-	{ .start = 0x00a03070, .end = 0x00a03070 },
-	{ .start = 0x00a0307c, .end = 0x00a03084 },
-	{ .start = 0x00a0308c, .end = 0x00a03090 },
-	{ .start = 0x00a03098, .end = 0x00a03098 },
-	{ .start = 0x00a030a0, .end = 0x00a030a0 },
-	{ .start = 0x00a030a8, .end = 0x00a030b4 },
-	{ .start = 0x00a030bc, .end = 0x00a030c0 },
-	{ .start = 0x00a030c8, .end = 0x00a030f4 },
-	{ .start = 0x00a03100, .end = 0x00a0312c },
-	{ .start = 0x00a03c00, .end = 0x00a03c5c },
-	{ .start = 0x00a04400, .end = 0x00a04454 },
-	{ .start = 0x00a04460, .end = 0x00a04474 },
-	{ .start = 0x00a044c0, .end = 0x00a044ec },
-	{ .start = 0x00a04500, .end = 0x00a04504 },
-	{ .start = 0x00a04510, .end = 0x00a04538 },
-	{ .start = 0x00a04540, .end = 0x00a04548 },
-	{ .start = 0x00a04560, .end = 0x00a04560 },
-	{ .start = 0x00a04570, .end = 0x00a0457c },
-	{ .start = 0x00a04590, .end = 0x00a04590 },
-	{ .start = 0x00a04598, .end = 0x00a04598 },
-	{ .start = 0x00a045c0, .end = 0x00a045f4 },
-	{ .start = 0x00a05c18, .end = 0x00a05c1c },
-	{ .start = 0x00a0c000, .end = 0x00a0c018 },
-	{ .start = 0x00a0c020, .end = 0x00a0c028 },
-	{ .start = 0x00a0c038, .end = 0x00a0c094 },
-	{ .start = 0x00a0c0c0, .end = 0x00a0c104 },
-	{ .start = 0x00a0c10c, .end = 0x00a0c118 },
-	{ .start = 0x00a0c150, .end = 0x00a0c174 },
-	{ .start = 0x00a0c17c, .end = 0x00a0c188 },
-	{ .start = 0x00a0c190, .end = 0x00a0c198 },
-	{ .start = 0x00a0c1a0, .end = 0x00a0c1a8 },
-	{ .start = 0x00a0c1b0, .end = 0x00a0c1b8 },
-};
-
-static const struct iwl_prph_range iwl_prph_dump_addr_ax210[] = {
-	{ .start = 0x00d03c00, .end = 0x00d03c64 },
-	{ .start = 0x00d05c18, .end = 0x00d05c1c },
-	{ .start = 0x00d0c000, .end = 0x00d0c174 },
-};
-
-static void iwl_read_prph_block(struct iwl_trans *trans, u32 start,
-				u32 len_bytes, __le32 *data)
-{
-	u32 i;
-
-	for (i = 0; i < len_bytes; i += 4)
-		*data++ = cpu_to_le32(iwl_trans_read_prph(trans, start + i));
-}
-
-static void iwl_dump_prph(struct iwl_fw_runtime *fwrt,
-			  const struct iwl_prph_range *iwl_prph_dump_addr,
-			  u32 range_len, void *ptr)
-{
-	struct iwl_fw_error_dump_prph *prph;
-	struct iwl_trans *trans = fwrt->trans;
-	struct iwl_fw_error_dump_data **data =
-		(struct iwl_fw_error_dump_data **)ptr;
-	u32 i;
-
-	if (!data)
-		return;
-
-	IWL_DEBUG_INFO(trans, "WRT PRPH dump\n");
-
-	if (!iwl_trans_grab_nic_access(trans))
-		return;
-
-	for (i = 0; i < range_len; i++) {
-		/* The range includes both boundaries */
-		int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
-			 iwl_prph_dump_addr[i].start + 4;
-
-		(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
-		(*data)->len = cpu_to_le32(sizeof(*prph) +
-					num_bytes_in_chunk);
-		prph = (void *)(*data)->data;
-		prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
-
-		iwl_read_prph_block(trans, iwl_prph_dump_addr[i].start,
-				    /* our range is inclusive, hence + 4 */
-				    iwl_prph_dump_addr[i].end -
-				    iwl_prph_dump_addr[i].start + 4,
-				    (void *)prph->data);
-
-		*data = iwl_fw_error_next_data(*data);
-	}
-
-	iwl_trans_release_nic_access(trans);
-}
 
 /*
- * alloc_sgtable - allocates (chained) scatterlist in the given size,
+ * iwl_fw_dbg_alloc_sgtable - allocates (chained) scatterlist in the given size,
  *	fills it with pages and returns it
  * @size: the size (in bytes) of the table
  */
-static struct scatterlist *alloc_sgtable(ssize_t size)
+struct scatterlist *iwl_fw_dbg_alloc_sgtable(ssize_t size)
 {
 	struct scatterlist *result = NULL, *prev;
 	int nents, i, n_prev;
@@ -625,423 +82,6 @@ static struct scatterlist *alloc_sgtable(ssize_t size)
 	return result;
 }
 
-static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt,
-				const struct iwl_prph_range *iwl_prph_dump_addr,
-				u32 range_len, void *ptr)
-{
-	u32 *prph_len = (u32 *)ptr;
-	int i, num_bytes_in_chunk;
-
-	if (!prph_len)
-		return;
-
-	for (i = 0; i < range_len; i++) {
-		/* The range includes both boundaries */
-		num_bytes_in_chunk =
-			iwl_prph_dump_addr[i].end -
-			iwl_prph_dump_addr[i].start + 4;
-
-		*prph_len += sizeof(struct iwl_fw_error_dump_data) +
-			sizeof(struct iwl_fw_error_dump_prph) +
-			num_bytes_in_chunk;
-	}
-}
-
-static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
-				void (*handler)(struct iwl_fw_runtime *,
-						const struct iwl_prph_range *,
-						u32, void *))
-{
-	u32 range_len;
-
-	if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
-		range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210);
-		handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr);
-	} else if (fwrt->trans->mac_cfg->device_family >=
-		   IWL_DEVICE_FAMILY_22000) {
-		range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
-		handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
-	} else {
-		range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm);
-		handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr);
-
-		if (fwrt->trans->mac_cfg->mq_rx_supported) {
-			range_len = ARRAY_SIZE(iwl_prph_dump_addr_9000);
-			handler(fwrt, iwl_prph_dump_addr_9000, range_len, ptr);
-		}
-	}
-}
-
-static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
-			    struct iwl_fw_error_dump_data **dump_data,
-			    u32 len, u32 ofs, u32 type)
-{
-	struct iwl_fw_error_dump_mem *dump_mem;
-
-	if (!len)
-		return;
-
-	(*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
-	(*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem));
-	dump_mem = (void *)(*dump_data)->data;
-	dump_mem->type = cpu_to_le32(type);
-	dump_mem->offset = cpu_to_le32(ofs);
-	iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
-	*dump_data = iwl_fw_error_next_data(*dump_data);
-
-	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
-		fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, ofs,
-					     dump_mem->data, len);
-
-	IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
-}
-
-#define ADD_LEN(len, item_len, const_len) \
-	do {size_t item = item_len; len += (!!item) * const_len + item; } \
-	while (0)
-
-static int iwl_fw_rxf_len(struct iwl_fw_runtime *fwrt,
-			  struct iwl_fwrt_shared_mem_cfg *mem_cfg)
-{
-	size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
-			 sizeof(struct iwl_fw_error_dump_fifo);
-	u32 fifo_len = 0;
-	int i;
-
-	if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RXF))
-		return 0;
-
-	/* Count RXF2 size */
-	ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len);
-
-	/* Count RXF1 sizes */
-	if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
-		mem_cfg->num_lmacs = MAX_NUM_LMAC;
-
-	for (i = 0; i < mem_cfg->num_lmacs; i++)
-		ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len);
-
-	return fifo_len;
-}
-
-static int iwl_fw_txf_len(struct iwl_fw_runtime *fwrt,
-			  struct iwl_fwrt_shared_mem_cfg *mem_cfg)
-{
-	size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) +
-			 sizeof(struct iwl_fw_error_dump_fifo);
-	u32 fifo_len = 0;
-	int i;
-
-	if (!iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_TXF))
-		goto dump_internal_txf;
-
-	/* Count TXF sizes */
-	if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC))
-		mem_cfg->num_lmacs = MAX_NUM_LMAC;
-
-	for (i = 0; i < mem_cfg->num_lmacs; i++) {
-		int j;
-
-		for (j = 0; j < mem_cfg->num_txfifo_entries; j++)
-			ADD_LEN(fifo_len, mem_cfg->lmac[i].txfifo_size[j],
-				hdr_len);
-	}
-
-dump_internal_txf:
-	if (!(iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
-	      fw_has_capa(&fwrt->fw->ucode_capa,
-			  IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)))
-		goto out;
-
-	for (i = 0; i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); i++)
-		ADD_LEN(fifo_len, mem_cfg->internal_txfifo_size[i], hdr_len);
-
-out:
-	return fifo_len;
-}
-
-static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
-			    struct iwl_fw_error_dump_data **data)
-{
-	int i;
-
-	IWL_DEBUG_INFO(fwrt, "WRT paging dump\n");
-	for (i = 1; i < fwrt->num_of_paging_blk + 1; i++) {
-		struct iwl_fw_error_dump_paging *paging;
-		struct page *pages =
-			fwrt->fw_paging_db[i].fw_paging_block;
-		dma_addr_t addr = fwrt->fw_paging_db[i].fw_paging_phys;
-
-		(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
-		(*data)->len = cpu_to_le32(sizeof(*paging) +
-					     PAGING_BLOCK_SIZE);
-		paging =  (void *)(*data)->data;
-		paging->index = cpu_to_le32(i);
-		dma_sync_single_for_cpu(fwrt->trans->dev, addr,
-					PAGING_BLOCK_SIZE,
-					DMA_BIDIRECTIONAL);
-		memcpy(paging->data, page_address(pages),
-		       PAGING_BLOCK_SIZE);
-		dma_sync_single_for_device(fwrt->trans->dev, addr,
-					   PAGING_BLOCK_SIZE,
-					   DMA_BIDIRECTIONAL);
-		(*data) = iwl_fw_error_next_data(*data);
-
-		if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
-			fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
-						     fwrt->fw_paging_db[i].fw_offs,
-						     paging->data,
-						     PAGING_BLOCK_SIZE);
-	}
-}
-
-static struct iwl_fw_error_dump_file *
-iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
-		       struct iwl_fw_dump_ptrs *fw_error_dump,
-		       struct iwl_fwrt_dump_data *data)
-{
-	struct iwl_fw_error_dump_file *dump_file;
-	struct iwl_fw_error_dump_data *dump_data;
-	struct iwl_fw_error_dump_info *dump_info;
-	struct iwl_fw_error_dump_smem_cfg *dump_smem_cfg;
-	struct iwl_fw_error_dump_trigger_desc *dump_trig;
-	u32 sram_len, sram_ofs;
-	const struct iwl_fw_dbg_mem_seg_tlv *fw_mem = fwrt->fw->dbg.mem_tlv;
-	struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
-	u32 file_len, fifo_len = 0, prph_len = 0, radio_len = 0;
-	u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->mac_cfg->base->smem_len;
-	u32 sram2_len = fwrt->fw->dbg.n_mem_tlv ?
-				0 : fwrt->trans->cfg->dccm2_len;
-	int i;
-
-	/* SRAM - include stack CCM if driver knows the values for it */
-	if (!fwrt->trans->cfg->dccm_offset ||
-	    !fwrt->trans->cfg->dccm_len) {
-		const struct fw_img *img;
-
-		if (fwrt->cur_fw_img >= IWL_UCODE_TYPE_MAX)
-			return NULL;
-		img = &fwrt->fw->img[fwrt->cur_fw_img];
-		sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
-		sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
-	} else {
-		sram_ofs = fwrt->trans->cfg->dccm_offset;
-		sram_len = fwrt->trans->cfg->dccm_len;
-	}
-
-	/* reading RXF/TXF sizes */
-	if (iwl_trans_is_fw_error(fwrt->trans)) {
-		fifo_len = iwl_fw_rxf_len(fwrt, mem_cfg);
-		fifo_len += iwl_fw_txf_len(fwrt, mem_cfg);
-
-		/* Make room for PRPH registers */
-		if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PRPH))
-			iwl_fw_prph_handler(fwrt, &prph_len,
-					    iwl_fw_get_prph_len);
-
-		if (fwrt->trans->mac_cfg->device_family ==
-		    IWL_DEVICE_FAMILY_7000 &&
-		    iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RADIO_REG))
-			radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
-	}
-
-	file_len = sizeof(*dump_file) + fifo_len + prph_len + radio_len;
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_DEV_FW_INFO))
-		file_len += sizeof(*dump_data) + sizeof(*dump_info);
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM_CFG))
-		file_len += sizeof(*dump_data) + sizeof(*dump_smem_cfg);
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
-		size_t hdr_len = sizeof(*dump_data) +
-				 sizeof(struct iwl_fw_error_dump_mem);
-
-		/* Dump SRAM only if no mem_tlvs */
-		if (!fwrt->fw->dbg.n_mem_tlv)
-			ADD_LEN(file_len, sram_len, hdr_len);
-
-		/* Make room for all mem types that exist */
-		ADD_LEN(file_len, smem_len, hdr_len);
-		ADD_LEN(file_len, sram2_len, hdr_len);
-
-		for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++)
-			ADD_LEN(file_len, le32_to_cpu(fw_mem[i].len), hdr_len);
-	}
-
-	/* Make room for fw's virtual image pages, if it exists */
-	if (iwl_fw_dbg_is_paging_enabled(fwrt))
-		file_len += fwrt->num_of_paging_blk *
-			(sizeof(*dump_data) +
-			 sizeof(struct iwl_fw_error_dump_paging) +
-			 PAGING_BLOCK_SIZE);
-
-	if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
-		file_len += sizeof(*dump_data) +
-			fwrt->trans->mac_cfg->base->d3_debug_data_length * 2;
-	}
-
-	/* If we only want a monitor dump, reset the file length */
-	if (data->monitor_only) {
-		file_len = sizeof(*dump_file) + sizeof(*dump_data) * 2 +
-			   sizeof(*dump_info) + sizeof(*dump_smem_cfg);
-	}
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
-	    data->desc)
-		file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
-			data->desc->len;
-
-	dump_file = vzalloc(file_len);
-	if (!dump_file)
-		return NULL;
-
-	fw_error_dump->fwrt_ptr = dump_file;
-
-	dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
-	dump_data = (void *)dump_file->data;
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_DEV_FW_INFO)) {
-		dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
-		dump_data->len = cpu_to_le32(sizeof(*dump_info));
-		dump_info = (void *)dump_data->data;
-		dump_info->hw_type =
-			cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev));
-		dump_info->hw_step =
-			cpu_to_le32(fwrt->trans->info.hw_rev_step);
-		memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
-		       sizeof(dump_info->fw_human_readable));
-		strscpy_pad(dump_info->dev_human_readable,
-			    fwrt->trans->info.name,
-			    sizeof(dump_info->dev_human_readable));
-		strscpy_pad(dump_info->bus_human_readable, fwrt->dev->bus->name,
-			sizeof(dump_info->bus_human_readable));
-		dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs;
-		dump_info->lmac_err_id[0] =
-			cpu_to_le32(fwrt->dump.lmac_err_id[0]);
-		if (fwrt->smem_cfg.num_lmacs > 1)
-			dump_info->lmac_err_id[1] =
-				cpu_to_le32(fwrt->dump.lmac_err_id[1]);
-		dump_info->umac_err_id = cpu_to_le32(fwrt->dump.umac_err_id);
-
-		dump_data = iwl_fw_error_next_data(dump_data);
-	}
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM_CFG)) {
-		/* Dump shared memory configuration */
-		dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
-		dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
-		dump_smem_cfg = (void *)dump_data->data;
-		dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
-		dump_smem_cfg->num_txfifo_entries =
-			cpu_to_le32(mem_cfg->num_txfifo_entries);
-		for (i = 0; i < MAX_NUM_LMAC; i++) {
-			int j;
-			u32 *txf_size = mem_cfg->lmac[i].txfifo_size;
-
-			for (j = 0; j < TX_FIFO_MAX_NUM; j++)
-				dump_smem_cfg->lmac[i].txfifo_size[j] =
-					cpu_to_le32(txf_size[j]);
-			dump_smem_cfg->lmac[i].rxfifo1_size =
-				cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
-		}
-		dump_smem_cfg->rxfifo2_size =
-			cpu_to_le32(mem_cfg->rxfifo2_size);
-		dump_smem_cfg->internal_txfifo_addr =
-			cpu_to_le32(mem_cfg->internal_txfifo_addr);
-		for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
-			dump_smem_cfg->internal_txfifo_size[i] =
-				cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
-		}
-
-		dump_data = iwl_fw_error_next_data(dump_data);
-	}
-
-	/* We only dump the FIFOs if the FW is in error state */
-	if (fifo_len) {
-		iwl_fw_dump_rxf(fwrt, &dump_data);
-		iwl_fw_dump_txf(fwrt, &dump_data);
-	}
-
-	if (radio_len)
-		iwl_read_radio_regs(fwrt, &dump_data);
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
-	    data->desc) {
-		dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
-		dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
-					     data->desc->len);
-		dump_trig = (void *)dump_data->data;
-		memcpy(dump_trig, &data->desc->trig_desc,
-		       sizeof(*dump_trig) + data->desc->len);
-
-		dump_data = iwl_fw_error_next_data(dump_data);
-	}
-
-	/* In case we only want monitor dump, skip to dump trasport data */
-	if (data->monitor_only)
-		goto out;
-
-	if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
-		const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem =
-			fwrt->fw->dbg.mem_tlv;
-
-		if (!fwrt->fw->dbg.n_mem_tlv)
-			iwl_fw_dump_mem(fwrt, &dump_data, sram_len, sram_ofs,
-					IWL_FW_ERROR_DUMP_MEM_SRAM);
-
-		for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++) {
-			u32 len = le32_to_cpu(fw_dbg_mem[i].len);
-			u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
-
-			iwl_fw_dump_mem(fwrt, &dump_data, len, ofs,
-					le32_to_cpu(fw_dbg_mem[i].data_type));
-		}
-
-		iwl_fw_dump_mem(fwrt, &dump_data, smem_len,
-				fwrt->trans->mac_cfg->base->smem_offset,
-				IWL_FW_ERROR_DUMP_MEM_SMEM);
-
-		iwl_fw_dump_mem(fwrt, &dump_data, sram2_len,
-				fwrt->trans->cfg->dccm2_offset,
-				IWL_FW_ERROR_DUMP_MEM_SRAM);
-	}
-
-	if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
-		u32 addr = fwrt->trans->mac_cfg->base->d3_debug_data_base_addr;
-		size_t data_size = fwrt->trans->mac_cfg->base->d3_debug_data_length;
-
-		dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
-		dump_data->len = cpu_to_le32(data_size * 2);
-
-		memcpy(dump_data->data, fwrt->dump.d3_debug_data, data_size);
-
-		kfree(fwrt->dump.d3_debug_data);
-		fwrt->dump.d3_debug_data = NULL;
-
-		iwl_trans_read_mem_bytes(fwrt->trans, addr,
-					 dump_data->data + data_size,
-					 data_size);
-
-		if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
-			fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, addr,
-						     dump_data->data + data_size,
-						     data_size);
-
-		dump_data = iwl_fw_error_next_data(dump_data);
-	}
-
-	/* Dump fw's virtual image */
-	if (iwl_fw_dbg_is_paging_enabled(fwrt))
-		iwl_dump_paging(fwrt, &dump_data);
-
-	if (prph_len)
-		iwl_fw_prph_handler(fwrt, &dump_data, iwl_dump_prph);
-
-out:
-	dump_file->file_len = cpu_to_le32(file_len);
-	return dump_file;
-}
-
 /**
  * struct iwl_dump_ini_region_data - region data
  * @reg_tlv: region TLV
@@ -2826,52 +1866,6 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt,
 	fwrt->dump.umac_err_id = 0;
 }
 
-static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
-			      struct iwl_fwrt_dump_data *dump_data)
-{
-	struct iwl_fw_dump_ptrs fw_error_dump = {};
-	struct iwl_fw_error_dump_file *dump_file;
-	struct scatterlist *sg_dump_data;
-	u32 file_len;
-	u32 dump_mask = fwrt->fw->dbg.dump_mask;
-
-	dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump, dump_data);
-	if (!dump_file)
-		return;
-
-	if (dump_data->monitor_only)
-		dump_mask &= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR);
-
-	fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask,
-						      fwrt->sanitize_ops,
-						      fwrt->sanitize_ctx);
-	file_len = le32_to_cpu(dump_file->file_len);
-	fw_error_dump.fwrt_len = file_len;
-
-	if (fw_error_dump.trans_ptr) {
-		file_len += fw_error_dump.trans_ptr->len;
-		dump_file->file_len = cpu_to_le32(file_len);
-	}
-
-	sg_dump_data = alloc_sgtable(file_len);
-	if (sg_dump_data) {
-		sg_pcopy_from_buffer(sg_dump_data,
-				     sg_nents(sg_dump_data),
-				     fw_error_dump.fwrt_ptr,
-				     fw_error_dump.fwrt_len, 0);
-		if (fw_error_dump.trans_ptr)
-			sg_pcopy_from_buffer(sg_dump_data,
-					     sg_nents(sg_dump_data),
-					     fw_error_dump.trans_ptr->data,
-					     fw_error_dump.trans_ptr->len,
-					     fw_error_dump.fwrt_len);
-		dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len,
-			       GFP_KERNEL);
-	}
-	vfree(fw_error_dump.fwrt_ptr);
-	vfree(fw_error_dump.trans_ptr);
-}
-
 static void iwl_dump_ini_list_free(struct list_head *list)
 {
 	while (!list_empty(list)) {
@@ -2900,7 +1894,7 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
 	if (!file_len)
 		return;
 
-	sg_dump_data = alloc_sgtable(file_len);
+	sg_dump_data = iwl_fw_dbg_alloc_sgtable(file_len);
 	if (sg_dump_data) {
 		struct iwl_fw_ini_dump_entry *entry;
 		int sg_entries = sg_nents(sg_dump_data);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index 8034c9ecba69..fc962a320583 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2005-2014, 2018-2019, 2021-2025 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021-2026 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -38,6 +38,11 @@ struct iwl_fw_dbg_params {
 	u32 out_ctrl;
 };
 
+/* old-style dump entry point */
+void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
+		       struct iwl_fwrt_dump_data *dump_data);
+struct scatterlist *iwl_fw_dbg_alloc_sgtable(ssize_t size);
+
 extern const struct iwl_fw_dump_desc iwl_dump_desc_assert;
 
 int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
-- 
2.34.1


^ permalink raw reply related

* [PATCH v2 iwlwifi-next 14/15] wifi: iwlwifi: dbg: remove unused 'range_len' arg from dump
From: Miri Korenblit @ 2026-05-17  7:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260517075959.2815365-1-miriam.rachel.korenblit@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

None of the functions use this, and it's not really passed the
length of the specific range anyway, but rather the entire
remaining size. Remove the unused argument.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 45 ++++++++++-----------
 1 file changed, 22 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 64ead8ecd52c..069c3bad6f29 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -111,7 +111,7 @@ static int iwl_dump_ini_prph_mac_iter_common(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
 			   struct iwl_dump_ini_region_data *reg_data,
-			   void *range_ptr, u32 range_len, int idx)
+			   void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	u32 addr = le32_to_cpu(reg->addrs[idx]) +
@@ -124,7 +124,7 @@ iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_prph_mac_block_iter(struct iwl_fw_runtime *fwrt,
 				 struct iwl_dump_ini_region_data *reg_data,
-				 void *range_ptr, u32 range_len, int idx)
+				 void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
@@ -201,7 +201,7 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
 			   struct iwl_dump_ini_region_data *reg_data,
-			   void *range_ptr, u32 range_len, int idx)
+			   void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	u32 addr = le32_to_cpu(reg->addrs[idx]);
@@ -214,7 +214,7 @@ iwl_dump_ini_prph_phy_iter(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_prph_phy_block_iter(struct iwl_fw_runtime *fwrt,
 				 struct iwl_dump_ini_region_data *reg_data,
-				 void *range_ptr, u32 range_len, int idx)
+				 void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs;
@@ -227,7 +227,7 @@ iwl_dump_ini_prph_phy_block_iter(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
 				 struct iwl_dump_ini_region_data *reg_data,
-				 void *range_ptr, u32 range_len, int idx)
+				 void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -246,7 +246,7 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_config_iter(struct iwl_fw_runtime *fwrt,
 				    struct iwl_dump_ini_region_data *reg_data,
-				    void *range_ptr, u32 range_len, int idx)
+				    void *range_ptr, int idx)
 {
 	struct iwl_trans *trans = fwrt->trans;
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
@@ -274,7 +274,7 @@ static int iwl_dump_ini_config_iter(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
 				     struct iwl_dump_ini_region_data *reg_data,
-				     void *range_ptr, u32 range_len, int idx)
+				     void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -296,7 +296,7 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
 }
 
 static int _iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
-				     void *range_ptr, u32 range_len, int idx)
+				     void *range_ptr, int idx)
 {
 	struct page *page = fwrt->fw_paging_db[idx].fw_paging_block;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -316,7 +316,7 @@ static int _iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
 				    struct iwl_dump_ini_region_data *reg_data,
-				    void *range_ptr, u32 range_len, int idx)
+				    void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_error_dump_range *range;
 	u32 page_size;
@@ -325,7 +325,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
 	idx++;
 
 	if (!fwrt->trans->mac_cfg->gen2)
-		return _iwl_dump_ini_paging_iter(fwrt, range_ptr, range_len, idx);
+		return _iwl_dump_ini_paging_iter(fwrt, range_ptr, idx);
 
 	range = range_ptr;
 	page_size = fwrt->trans->init_dram.paging[idx].size;
@@ -341,7 +341,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
 			   struct iwl_dump_ini_region_data *reg_data,
-			   void *range_ptr, u32 range_len, int idx)
+			   void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -360,7 +360,7 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_mon_smem_iter(struct iwl_fw_runtime *fwrt,
 				      struct iwl_dump_ini_region_data *reg_data,
-				      void *range_ptr, u32 range_len, int idx)
+				      void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -428,7 +428,7 @@ static bool iwl_ini_txf_iter(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
 				 struct iwl_dump_ini_region_data *reg_data,
-				 void *range_ptr, u32 range_len, int idx)
+				 void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -497,7 +497,7 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt,
 				   struct iwl_dump_ini_region_data *reg_data,
-				   void *range_ptr, u32 range_len, int idx)
+				   void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -610,7 +610,7 @@ static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
 				 struct iwl_dump_ini_region_data *reg_data,
-				 void *range_ptr, u32 range_len, int idx)
+				 void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -676,7 +676,7 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_err_table_iter(struct iwl_fw_runtime *fwrt,
 			    struct iwl_dump_ini_region_data *reg_data,
-			    void *range_ptr, u32 range_len, int idx)
+			    void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_region_err_table *err_table = &reg->err_table;
@@ -695,7 +695,7 @@ iwl_dump_ini_err_table_iter(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_special_mem_iter(struct iwl_fw_runtime *fwrt,
 			      struct iwl_dump_ini_region_data *reg_data,
-			      void *range_ptr, u32 range_len, int idx)
+			      void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_region_special_device_memory *special_mem =
@@ -716,7 +716,7 @@ iwl_dump_ini_special_mem_iter(struct iwl_fw_runtime *fwrt,
 static int
 iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
 			    struct iwl_dump_ini_region_data *reg_data,
-			    void *range_ptr, u32 range_len, int idx)
+			    void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -746,7 +746,7 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_fw_pkt_iter(struct iwl_fw_runtime *fwrt,
 				    struct iwl_dump_ini_region_data *reg_data,
-				    void *range_ptr, u32 range_len, int idx)
+				    void *range_ptr, int idx)
 {
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
 	struct iwl_rx_packet *pkt = reg_data->dump_data->fw_pkt;
@@ -767,7 +767,7 @@ static int iwl_dump_ini_fw_pkt_iter(struct iwl_fw_runtime *fwrt,
 
 static int iwl_dump_ini_imr_iter(struct iwl_fw_runtime *fwrt,
 				 struct iwl_dump_ini_region_data *reg_data,
-				 void *range_ptr, u32 range_len, int idx)
+				 void *range_ptr, int idx)
 {
 	/* read the IMR memory and DMA it to SRAM */
 	struct iwl_fw_ini_error_dump_range *range = range_ptr;
@@ -1277,7 +1277,7 @@ struct iwl_dump_ini_mem_ops {
 			      void *data, u32 data_len);
 	int (*fill_range)(struct iwl_fw_runtime *fwrt,
 			  struct iwl_dump_ini_region_data *reg_data,
-			  void *range, u32 range_len, int idx);
+			  void *range, int idx);
 };
 
 struct iwl_fw_ini_dump_entry {
@@ -1413,8 +1413,7 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
 	free_size -= header_size;
 
 	for (i = 0; i < le32_to_cpu(header->num_of_ranges); i++) {
-		int range_size = ops->fill_range(fwrt, reg_data, range,
-						 free_size, i);
+		int range_size = ops->fill_range(fwrt, reg_data, range, i);
 
 		if (range_size < 0) {
 			IWL_ERR(fwrt,
-- 
2.34.1


^ permalink raw reply related

* [PATCH v2 iwlwifi-next 15/15] wifi: iwlwifi: transport: add memory read under NIC access
From: Miri Korenblit @ 2026-05-17  7:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260517075959.2815365-1-miriam.rachel.korenblit@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

Add functions to be able to do memory read under NIC access,
in order to use them later during firmware dump. These may
drop and re-acquire the spinlock, but will not acquire and
release the NIC access.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
 .../net/wireless/intel/iwlwifi/iwl-trans.c    |  6 +++
 .../net/wireless/intel/iwlwifi/iwl-trans.h    | 16 ++++++
 .../intel/iwlwifi/pcie/gen1_2/internal.h      |  2 +
 .../intel/iwlwifi/pcie/gen1_2/trans.c         | 54 +++++++++++++++++++
 4 files changed, 78 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index 5b44e15fe64d..0009488ca51b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -459,6 +459,12 @@ int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
 }
 IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
 
+int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+			       void *buf, u32 dwords)
+{
+	return iwl_trans_pcie_read_mem_no_grab(trans, addr, buf, dwords);
+}
+
 int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
 			const void *buf, int dwords)
 {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 1ed6bcb7882c..3ae840e546e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -919,6 +919,14 @@ void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
 int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
 		       void *buf, int dwords);
 
+/*
+ * Note the special calling convention - it's allowed to drop the
+ * internal transport lock and re-enable BHs temporarily, but will
+ * not release NIC access.
+ */
+int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+			       void *buf, u32 dwords);
+
 int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
 			    u32 *val);
 
@@ -934,6 +942,14 @@ void iwl_trans_debugfs_cleanup(struct iwl_trans *trans);
 				   (bufsize) / sizeof(u32));	\
 	})
 
+static inline int
+iwl_trans_read_mem_bytes_no_grab(struct iwl_trans *trans,
+				 u32 addr, void *buf, u32 bufsize)
+{
+	return iwl_trans_read_mem_no_grab(trans, addr, buf,
+					  bufsize / sizeof(u32));
+}
+
 int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
 			    u64 src_addr, u32 byte_cnt);
 
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
index 24f8714eae9f..abc0c831d1ca 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
@@ -1186,6 +1186,8 @@ u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg);
 void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val);
 int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
 			    void *buf, int dwords);
+int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+				    void *buf, u32 dwords);
 int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership);
 struct iwl_trans_dump_data *
 iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
index 50342604491d..1c4ee76d8387 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
@@ -2424,6 +2424,15 @@ bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
 	return false;
 }
 
+static void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+	spin_unlock_bh(&trans_pcie->reg_lock);
+	cond_resched();
+	spin_lock_bh(&trans_pcie->reg_lock);
+}
+
 void __releases(nic_access_nobh)
 iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
 {
@@ -2506,6 +2515,51 @@ int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
 	return 0;
 }
 
+int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+				    void *buf, u32 dwords)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+#define IWL_MAX_HW_ERRS 5
+	unsigned int num_consec_hw_errors = 0;
+	u32 offs = 0;
+	u32 *vals = buf;
+
+	lockdep_assert_held(&trans_pcie->reg_lock);
+
+	while (offs < dwords) {
+		/* limit the time we spin here under lock to 1/2s */
+		unsigned long end = jiffies + HZ / 2;
+		bool resched = false;
+
+		iwl_write32(trans, HBUS_TARG_MEM_RADDR,
+			    addr + 4 * offs);
+
+		while (offs < dwords) {
+			vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
+
+			if (iwl_trans_is_hw_error_value(vals[offs]))
+				num_consec_hw_errors++;
+			else
+				num_consec_hw_errors = 0;
+
+			if (num_consec_hw_errors >= IWL_MAX_HW_ERRS)
+				return -EIO;
+
+			offs++;
+
+			if (time_after(jiffies, end)) {
+				resched = true;
+				break;
+			}
+		}
+
+		if (resched)
+			iwl_trans_pcie_resched_with_nic_access(trans);
+	}
+
+	return 0;
+}
+
 int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs,
 				 u32 *val)
 {
-- 
2.34.1


^ permalink raw reply related

* Re: [DONOTAPPLY RFC PATCH v2 0/4] WiFi support for samsung,coreprimevelte
From: Karel Balej @ 2026-05-17  8:14 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Brian Norris, Francesco Dolcini, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Duje Mihanović, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Ulf Hansson, Frank Li, linux-wireless,
	devicetree, linux-kernel, linux-arm-kernel, linux-mmc,
	~postmarketos/upstreaming, phone-devel, Jeff Chen, Peng Fan,
	david
In-Reply-To: <DI5L100Q1RKO.1A68EJIPWYSRC@matfyz.cz>

Johannes,

Karel Balej, 2026-04-29T12:55:23+02:00:
> Brian, what are the options here now? Would it be possible to make an
> exception and accept the patches without the firmware being in
> linux-firmware? This is an old device with no mainstream audience so I
> expect everyone who will want to use it will be able to supply the
> firmware themselves and it would be great to not have to keep the
> patches in a fork, especially when trying to build on top of them
> further (such as to fix the driver-firmware incompatibilities discussed
> in one of the patches of this series).

would you please let us know whether there is any chance an exception
could be made for this chip regarding the firmware or whether there is
any other way to upstream the support?

Thank you and best regards,
Karel

^ permalink raw reply

* Re: [PATCH v2] wireless-regdb: Update regulatory info for Brunei Darussalam (BN) for 2022
From: Chen-Yu Tsai @ 2026-05-17  9:53 UTC (permalink / raw)
  To: hfzz7; +Cc: linux-wireless, wireless-regdb
In-Reply-To: <BFBA868E-9B63-48A6-9B73-E749857BD106.1@smtp-inbound1.duck.com>

On Fri, May 1, 2026 at 11:41 PM <hfzz7@duck.com> wrote:
>
> In 2022, Authority for Info-communications Technology Industry of Brunei
> Darussalam (AITI) updated The Brunei Darussalam Radio Spectrum Plan. [1]
>
> * 2400-2483.5 MHz
>         - 200 mW
>
> * 5150-5350 MHz
>         - 1000 mW
>         (For 5250-5.350 MHz, DFS and TPC are required)
>
> * 5470-5725 MHz
>         - 1000 mW
>         - DFS
>         - TPC
>
> * 5725-5850 MHz
>         - 4000 mW
>
> Also, add regulatory info for WiGig/60 GHz
> * 57000-66000 MHz
>         - 10 W / 10000 mW
>
> Note: According to the Telecommunications (Radio-communication) Regulations,
> 2013 of the Telecommunications Order, 2001 (S 38/2001), "non-localised use"
> refers to the operations of specified radio-communication equipment or network
> at a specific frequency or in any specified frequency within the whole of
> Brunei Darussalam. [2]
>
> [1] https://aiti.gov.bn/media/planjc1p/bd-radio-spectrum-plan-2019.pdf
> [2] https://www.agc.gov.bn/AGC%20Images/LAWS/Gazette_PDF/2013/EN/s086.pdf
>
> Signed-off-by: Hafiz Zafran <hfzz7@duck.com>

So the author (the email's From: header) only has your email. With
your permission, I will add use name from your Signed-off-by as
the commit's author.


ChenYu

> ---
> Changes since v1:
>         - fix grammar issues on the commit message
>         - adjust transmit power limit to 500 mW for frequencies that
>           require TPC
>         - add INDOOR-ONLY flag to WiGig, as per review
> ---
>  db.txt | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/db.txt b/db.txt
> index 3252521..2de3281 100644
> --- a/db.txt
> +++ b/db.txt
> @@ -326,11 +326,16 @@ country BM: DFS-FCC
>         (5490 - 5730 @ 160), (24), DFS
>         (5735 - 5835 @ 80), (30)
>
> -country BN: DFS-JP
> -       (2402 - 2482 @ 40), (20)
> -       (5170 - 5250 @ 80), (20), AUTO-BW
> -       (5250 - 5330 @ 80), (20), DFS, AUTO-BW
> -       (5735 - 5835 @ 80), (20)
> +# Source:
> +# https://aiti.gov.bn/media/planjc1p/bd-radio-spectrum-plan-2019.pdf
> +# Section 7.5, Page 244-251
> +country BN: DFS-FCC
> +       (2400 - 2483.5 @ 40), (200 mW)
> +       (5150 - 5250 @ 80), (1000 mW), AUTO-BW
> +       (5250 - 5350 @ 80), (500 mW), DFS, AUTO-BW
> +       (5470 - 5730 @ 160), (500 mW), DFS
> +       (5725 - 5850 @ 80), (4000 mW), AUTO-BW
> +       (57000 - 66000 @ 2160), (10000 mW), INDOOR-ONLY
>
>  country BO: DFS-JP
>         (2402 - 2482 @ 40), (20)
> --
> 2.54.0
>
>

^ permalink raw reply

* Re: [bug report] wifi: mt76: mt7925: iw set txpower fixed accepted but ignored
From: John Henry @ 2026-05-17 13:01 UTC (permalink / raw)
  To: Sean Wang
  Cc: Javier Tia, Bradley Pizzimenti, linux-wireless, linux-kernel, nbd,
	lorenzo, ryder.lee, shayne.chen, sean.wang,
	moderated list:ARM/Mediatek SoC support, Deren Wu, Nick Morrow
In-Reply-To: <CAN6xzWdsYY0eni7aHG2Q=i2zz-rVxFRJJhCJbUsn=Pn_oDY-bQ@mail.gmail.com>

Just a kind reminder of this issue, has anyone been able to reproduce
this monitor mode issue?
When scanning through channels, and the list of channels is > 4, there
is a large transmit tick/burst coming from the MT7921u and the MT7925.
This can easily be seen on an RF Spectrum Analyzer.
Confirmed on an Alfa AWUS036AXML consumer product and the Netgear
Nighthawk A9000.
This can be reproduced with simple scripts.

Reproduction with stock iw commands (no custom code):

IFACE=$(iw dev | awk '/Interface wl/ {print $2; exit}')
iw reg set US ; sleep 1
ip link set "$IFACE" down
iw dev "$IFACE" set type monitor
ip link set "$IFACE" up

# This triggers narrowband bursts at channel center on each retune:
while true; do
  for f in 2412 2417 2422 2427 2432; do
    iw dev "$IFACE" set freq "$f" HT20
  done
done

# This does NOT (only 4 frequencies):
while true; do
  for f in 2412 2422 2462 2484; do
    iw dev "$IFACE" set freq "$f" HT20
  done
done

Bursts are ~800 kHz wide at the base, -30 to -50 dBm OTA at close
range, brief (estimated few hundred microseconds), at channel
frequency. tx_stats counters remain zero throughout.
On Mon, May 11, 2026 at 1:58 PM John Henry <jshenry1963@gmail.com> wrote:
>
> Bradley/Sean,
>
> Thank you all very much for the information.
> I tested this on mt7921u based Alfa AWUS unit and also an mt7925 based
> Netgear Nighthawk unit.
> I can confirm that the RF tick issue is present on both models when in
> Monitor Mode. I'm assuming it is in the base mt76?
>
> I attempted sudo iw dev wlxxx set txpower fixed nn where nn is the
> minimum value, next few values up, and then a few near the max values,
> and see no change in the signal strength of the RF Ticks when scanning
> through 5 or more channels.
>
> Please keep this in mind when attempting to resolve the known txpower
> 3dBm issue if possible, or please generate a new bug report for that
> specifically so that I can track when it is patched, or in ??? version
> so that I can test here locally.
>
> Incidentally, I'd appreciate it if anyone could please attempt to
> repeat using the scripts I had shown in the previous posts and confirm
> it is indeed seen by others.
>
> Thank you very much for your time and assistance
>
> John Henry
>
>
>
>
> From: Bradley Pizzimenti <brad.pizzimenti@gmail.com>
> To: linux-wireless@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org, nbd@nbd.name, lorenzo@kernel.org,
> ryder.lee@mediatek.com, shayne.chen@mediatek.com,
> sean.wang@mediatek.com
> Subject: [bug report] wifi: mt76: mt7925: iw set txpower fixed
> accepted but ignored
> Date: Mon, 4 May 2026 15:04:35 -0700 [thread overview]
> Message-ID: <CACjnFagN9zeSkwEv3-CSPJDUENPcEcOLjKyQoLQ91Yjn=rq5ww@mail.gmail.com>
> (raw)
>
> Hi there maintainers,
>
> `iw dev <iface> set txpower fixed N` returns success on mt7925 for any
> N tested, but the reported txpower never changes from a stuck value of
> 3.00 dBm. The kernel accepts and ignores the call silently in both
> directions (above and below the displayed value), and well below the
> regulatory ceiling.
>
> I'm aware there's prior art on the cosmetic 3.00 dBm display issue
> (Razvan Grigore's v2 series, Feb 2025; Ming Yen Hsieh's txpower init
> refactor, Sept 2025). What seems potentially distinct here is that the
> user-issued `iw set txpower fixed N` itself is silently no-op'd,
> separate from the reported-value question. Reporting as breadcrumbs
> in case the second observation is a separate bug rather than the same
> one.
>
> Hardware
> --------
> MEDIATEK MT7925 [Filogic 360], 802.11be 2x2, PCI 14c3:7925
> ASIC revision 0x79250000
> Driver in use: mt7925e (in-tree)
>
> Firmware (from dmesg at probe)
> ------------------------------
> mt7925e 0000:01:00.0: HW/SW Version: 0x8a108a10,
>                      Build Time: 20260106153007a
> mt7925e 0000:01:00.0: WM Firmware Version: ____000000,
>                      Build Time: 20260106153120
> Files: mediatek/mt7925/WIFI_MT7925_PATCH_MCU_1_1_hdr.bin
>        mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin
>
> Kernel
> ------
> 6.18.18-1-MANJARO (close to vanilla 6.18 stable; not yet tested on
> wireless-next or nbd168/wireless HEAD -- happy to retest if needed,
> but flagging the data point in case it helps as-is).
>
> Tools: iw version 6.17
>
> Regulatory
> ----------
> $ iw reg get
> country US: DFS-FCC
>    ...
>    (5730 - 5850 @ 80), (N/A, 30), (N/A), AUTO-BW
>    ...
>
> Connection context: 5GHz channel 161 (5805 MHz), 80 MHz, VHT-MCS,
> NSS 1. So we are on a band with a 30 dBm regulatory cap.
>
> Observed
> --------
> $ iw dev wlp1s0 info | grep txpower
>         txpower 3.00 dBm
>
> $ sudo iw dev wlp1s0 set txpower fixed 100   # 1 dBm
> $ iw dev wlp1s0 info | grep txpower
>         txpower 3.00 dBm
>
> $ sudo iw dev wlp1s0 set txpower fixed 1500  # 15 dBm
> $ iw dev wlp1s0 info | grep txpower
>         txpower 3.00 dBm
>
> $ sudo iw dev wlp1s0 set txpower auto
> $ iw dev wlp1s0 info | grep txpower
>         txpower 3.00 dBm
>
> All four `set` invocations return exit code 0. The reported value
> never moves.
>
> Expected
> --------
> Either:
>   - The reported txpower follows the requested value (or, where
>     capped, the actual applied value with extack indicating the
>     cap reason), or
>   - The set call returns an error rather than silently ignoring the
>     request.
>
> Caveats
> -------
> - Not yet tested on wireless-next or nbd168/wireless HEAD. If a
>   reproduction on a current dev tree would be useful, I can do that.
> - I have not verified whether the actual radiated TX power changes
>   in response to `set txpower fixed`; I am reporting only the
>   user-visible behavior.
>
> Thanks,
> Bradley
>
> On Wed, May 6, 2026 at 8:12 PM Sean Wang <sean.wang@kernel.org> wrote:
> >
> > Hi,
> >
> > The TX power reporting issue has already been investigated by Lucid
> > from the Linux WiFi USB community, and there is a proposed solution.
> > I think we can continue checking whether there are any remaining
> > issues on top of that work. Please refer to the patches here:
> > https://lists.infradead.org/pipermail/linux-mediatek/2026-April/105726.html
> > Thanks everyone for reporting and raising these concerns.
> >
> > On Wed, May 6, 2026 at 3:09 PM Javier Tia <floss@jetm.me> wrote:
> > >
> > > On Sun May  4 22:04:48 2026 Bradley Pizzimenti wrote:
> > > > `iw dev <iface> set txpower fixed N` returns success on mt7925 for
> > > > any N tested, but the reported txpower never changes from a stuck
> > > > value of 3.00 dBm.
> > >
> > > Hi Bradley,
> > >
> > > The 3 dBm display bug is a known issue we have seen when using mt7927
> > > and a tested fix has been working well so far. The root cause is that
> > > mt7925_mcu_set_rate_txpower() programs the per-band SKU tables into
> > > firmware but never assigns phy->txpower_cur. mt76_get_txpower() then
> > > computes:
> > >
> > >   DIV_ROUND_UP(0 + 6, 2) = 3
> > >
> > > regardless of the actual power level. The RF output is unaffected;
> > > it is a display-only bug.
> > >
> > > The fix reads the effective TX power back from the rate power limits
> > > after programming the SKU tables and writes it to phy->txpower_cur,
> > > following the same pattern used by mt7996:
> > >
> > >   https://github.com/jetm/mediatek-mt7927-dkms/blob/master/mt7927-wifi-14-fix-reported-txpower-always-showing-3-db.patch
> > >
> > > This is part of a series we are targeting for wireless-next; not
> > > yet upstream.
> > >
> > > > What seems potentially distinct here is that the user-issued
> > > > `iw set txpower fixed N` itself is silently no-op'd, separate
> > > > from the reported-value question.
> > >
> > > Agreed those are two separate issues. Our patch addresses the
> > > display-only side: after applying it, iw will report the value the
> > > firmware is actually using based on the SKU tables, rather than
> > > always 3 dBm. Whether `set txpower fixed N` propagates to firmware
> > > to change actual output power is orthogonal and not addressed here.
> > >
> > > If you can test the patch on your MT7925 and confirm the displayed
> > > value reflects the correct power after association, a Tested-by
> > > would be appreciated.
> > >
> > > Best,
> > > Javier
> > >
> >

^ permalink raw reply

* Re: [PATCH rtw-next] wifi: rtw88: Add more validation for the RX descriptor
From: Oleksandr Havrylov @ 2026-05-17 16:17 UTC (permalink / raw)
  To: Bitterblue Smith
  Cc: linux-wireless@vger.kernel.org, Ping-Ke Shih, Martin Blumenstingl,
	Fiona Klute, andrej.skvortzov, anarsoul, Zhen XIN
In-Reply-To: <a237ba9e-9f05-451f-9dfc-9aa8b11b7bc4@gmail.com>

Hi Bitterblue,

Thank you for the patch.

I have manually applied and tested this patch on top of kernel
7.0.7-1-default (x86_64) running on openSUSE Slowroll.

The test was conducted on the following hardware:
Machine: HP Notebook (SKU: P3S95EA#ACB)
Adapter: Realtek Semiconductor Co., Ltd. RTL8821CE 802.11ac PCIe
Wireless Network Adapter [10ec:c821]

I verified the driver stability through a series of rigorous tests:
1. Heavy Concurrent Load: Downloading a 1.5GB Linux ISO image while
running a continuous flood ping.
2. Wi-Fi/BT Coexistence: The load test was performed while maintaining
an active Bluetooth audio stream (AVRCP profile) to check for
coexistence issues.
3. Interface Toggling: Repeatedly turning the Wi-Fi radio off and on
to simulate the network stack behavior.
4. Power Management (S3 Sleep & S4 Hibernation): Forced the system
into Suspend-to-RAM and Suspend-to-Disk (via rtcwake) and verified
that the driver successfully resumed, reinitialized the firmware, and
automatically re-associated with the AP without any lockups or
descriptor errors upon waking up.

The driver handled all tests flawlessly without any connection drops
or hangs. The new RX descriptor validation checks work exactly as
intended—they successfully caught and discarded malformed frames,
completely preventing the kernel crashes and warnings that were
previously triggered by corrupted descriptors. No regressions were
observed in network throughput, coexistence, or power management
flows.

Tested-by: Oleksandr Havrylov <goainwo@gmail.com>

^ permalink raw reply

* [PATCH ath-next] wifi: ath9k: remove TX99 power array zero init
From: Rosen Penev @ 2026-05-17 22:21 UTC (permalink / raw)
  To: linux-wireless; +Cc: Toke Høiland-Jørgensen, open list

This array is fully initialized in the loop itself. No need to zero
initialize and then overwrite.

Remove static from the array. This was a holdover from when the array
was a static global variable. It no longer confers any benefit.

Also add a min() call to avoid the manual if/ternary operation.

Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 6274d1624261..5d0433f2ae37 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1811,10 +1811,10 @@ static void ar9003_hw_tx99_stop(struct ath_hw *ah)
 
 static void ar9003_hw_tx99_set_txpower(struct ath_hw *ah, u8 txpower)
 {
-	static u8 p_pwr_array[ar9300RateSize] = { 0 };
+	u8 p_pwr_array[ar9300RateSize];
 	unsigned int i;
 
-	txpower = txpower <= MAX_RATE_POWER ? txpower : MAX_RATE_POWER;
+	txpower = min(txpower, MAX_RATE_POWER);
 	for (i = 0; i < ar9300RateSize; i++)
 		p_pwr_array[i] = txpower;
 
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH] wifi: mt76: disable rx napi before queue cleanup
From: Ruslan Isaev @ 2026-05-17 22:46 UTC (permalink / raw)
  To: linux-wireless
  Cc: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang
In-Reply-To: <agEbiurBZzZv_Yt0@wico-dev.wnam.ru>

Gentle ping for review

May 11, 2026 02:58:02 Ruslan Isaev <legale.legale@gmail.com>:

> mt76_dma_cleanup() already disables tx napi before deleting it, but
> it still removes rx napi instances while they can remain enabled on the
> normal device remove path. On mt7915 this triggers a warning.
> 
> Disable each rx napi instance before netif_napi_del() and page pool
> destruction. This fixes repeated warnings on rmmod mt7915e on
> mt7915e/mt7981b.
> 
> Signed-off-by: Ruslan Isaev <legale.legale@gmail.com>
> ---
> drivers/net/wireless/mediatek/mt76/dma.c | 1 +
> 1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
> index f8c2fe5f2..12183142f 100644
> --- a/drivers/net/wireless/mediatek/mt76/dma.c
> +++ b/drivers/net/wireless/mediatek/mt76/dma.c
> @@ -1189,6 +1189,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
>     mt76_for_each_q_rx(dev, i) {
>         struct mt76_queue *q = &dev->q_rx[i];
> 
> +       napi_disable(&dev->napi[i]);
>         netif_napi_del(&dev->napi[i]);
>         mt76_dma_rx_cleanup(dev, q);
> 
> -- 
> 2.39.5

^ permalink raw reply

* [PATCH wireless-next] wifi: rt2x00: Allocate LED names dynamically
From: Rosen Penev @ 2026-05-17 23:17 UTC (permalink / raw)
  To: linux-wireless; +Cc: Stanislaw Gruszka, open list

The rt2x00 LED registration path builds LED class names from the
driver and wiphy names. A fixed stack buffer can truncate those names
before they are passed to the LED core.

Allocate each LED name with kasprintf(), check allocation failures, and
release the stored name when the LED is unregistered.

Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 .../net/wireless/ralink/rt2x00/rt2x00leds.c   | 30 ++++++++++++++-----
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
index f5361d582d4e..8818e0b2447b 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
@@ -100,6 +100,8 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
 
 	retval = led_classdev_register(device, &led->led_dev);
 	if (retval) {
+		kfree(name);
+		led->led_dev.name = NULL;
 		rt2x00_err(rt2x00dev, "Failed to register led handler\n");
 		return retval;
 	}
@@ -111,15 +113,19 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
 
 void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
 {
-	char name[36];
+	char *name;
 	int retval;
 	unsigned long on_period;
 	unsigned long off_period;
 	const char *phy_name = wiphy_name(rt2x00dev->hw->wiphy);
 
 	if (rt2x00dev->led_radio.flags & LED_INITIALIZED) {
-		snprintf(name, sizeof(name), "%s-%s::radio",
-			 rt2x00dev->ops->name, phy_name);
+		name = kasprintf(GFP_KERNEL, "%s-%s::radio",
+				 rt2x00dev->ops->name, phy_name);
+		if (!name) {
+			retval = -ENOMEM;
+			goto exit_fail;
+		}
 
 		retval = rt2x00leds_register_led(rt2x00dev,
 						 &rt2x00dev->led_radio,
@@ -129,8 +135,12 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
 	}
 
 	if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) {
-		snprintf(name, sizeof(name), "%s-%s::assoc",
-			 rt2x00dev->ops->name, phy_name);
+		name = kasprintf(GFP_KERNEL, "%s-%s::assoc",
+				 rt2x00dev->ops->name, phy_name);
+		if (!name) {
+			retval = -ENOMEM;
+			goto exit_fail;
+		}
 
 		retval = rt2x00leds_register_led(rt2x00dev,
 						 &rt2x00dev->led_assoc,
@@ -140,8 +150,12 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
 	}
 
 	if (rt2x00dev->led_qual.flags & LED_INITIALIZED) {
-		snprintf(name, sizeof(name), "%s-%s::quality",
-			 rt2x00dev->ops->name, phy_name);
+		name = kasprintf(GFP_KERNEL, "%s-%s::quality",
+				 rt2x00dev->ops->name, phy_name);
+		if (!name) {
+			retval = -ENOMEM;
+			goto exit_fail;
+		}
 
 		retval = rt2x00leds_register_led(rt2x00dev,
 						 &rt2x00dev->led_qual,
@@ -182,6 +196,8 @@ static void rt2x00leds_unregister_led(struct rt2x00_led *led)
 		led->led_dev.brightness_set(&led->led_dev, LED_OFF);
 
 	led->flags &= ~LED_REGISTERED;
+	kfree(led->led_dev.name);
+	led->led_dev.name = NULL;
 }
 
 void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH wireless-next] wifi: rt2x00: Allocate LED names dynamically
From: Rosen Penev @ 2026-05-17 23:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Stanislaw Gruszka, open list
In-Reply-To: <20260517231759.56638-1-rosenp@gmail.com>

On Sun, May 17, 2026 at 4:18 PM Rosen Penev <rosenp@gmail.com> wrote:
>
> The rt2x00 LED registration path builds LED class names from the
> driver and wiphy names. A fixed stack buffer can truncate those names
> before they are passed to the LED core.
>
> Allocate each LED name with kasprintf(), check allocation failures, and
> release the stored name when the LED is unregistered.
>
> Assisted-by: Codex:GPT-5.5
I got a crash from this driver:

[11292.387895] ieee80211 phy2: rt2x00_set_rt: Info - RT chipset 3070,
rev 0201 detected
[11293.065970] ieee80211 phy2: rt2x00_set_rf: Info - RF chipset 0005 detected
[11293.072037] ieee80211 phy2: Selected rate control algorithm 'minstrel_ht'
[11293.105170] ieee80211 phy2: rt2x00lib_request_firmware: Info -
Loading firmware file 'rt2870.bin'
[11293.105237] ieee80211 phy2: rt2x00lib_request_firmware: Info -
Firmware detected - version: 0.36
[11296.194097] usb 1-11: USB disconnect, device number 6
[11296.196552] ieee80211 phy2: rt2x00usb_vendor_request: Error -
Vendor Request 0x06 failed for offset 0x101c with error -19
[11301.161824] BUG: unable to handle page fault for address: ffffffffffffff08
[11301.161830] #PF: supervisor read access in kernel mode
[11301.161833] #PF: error_code(0x0000) - not-present page
[11301.161835] PGD ea3a27067 P4D ea3a27067 PUD ea3a29067 PMD 0
[11301.161842] Oops: Oops: 0000 [#1] SMP NOPTI
[11301.161847] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted
7.0.8-arch1-1 #1 PREEMPT(full)
c2ec282795e9f47cb8bc86f69b5629c84ae881f4
[11301.161851] Hardware name: To Be Filled By O.E.M. X370 Professional
Gaming/X370 Professional Gaming, BIOS P7.30 10/27/2022
[11301.161854] RIP: 0010:led_blink_set_nosleep+0x1a/0xa0
[11301.161860] Code: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
f3 0f 1e fa 0f 1f 44 00 00 53 48 89 fb 48 83 ec 10 48 89 74 24 08 48
89 14 24 <48> 83 7f 38 00 74 07 48 83 7f 28 00 75 35 48 8d bb 88 00 00
00 e8
[11301.161863] RSP: 0018:ffffc9fc80003d88 EFLAGS: 00010286
[11301.161867] RAX: 0000000000000000 RBX: fffffffffffffed0 RCX: ffffffffc232c4f8
[11301.161869] RDX: 0000000000000000 RSI: 0000000000000001 RDI: fffffffffffffed0
[11301.161871] RBP: ffff89714752de40 R08: ffff8975fef1f2c0 R09: 0000000100a7df80
[11301.161873] R10: 0000000000000201 R11: 0000000000000000 R12: 0000000000000001
[11301.161875] R13: 0000000000000000 R14: ffffc9fc80003e10 R15: ffff8975fef1f2c0
[11301.161877] FS:  0000000000000000(0000) GS:ffff897645967000(0000)
knlGS:0000000000000000
[11301.161880] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[11301.161882] CR2: ffffffffffffff08 CR3: 00000001191d1000 CR4: 0000000000f50ef0
[11301.161884] PKRU: 55555554
[11301.161887] Call Trace:
[11301.161889]  <IRQ>
[11301.161893]  led_trigger_blink+0x55/0x90
[11301.161898]  ? __pfx_tpt_trig_timer+0x10/0x10 [mac80211
43d2d2695e6be7042340c3321c2c597aa1cd7f70]
[11301.161944]  ? __pfx_tpt_trig_timer+0x10/0x10 [mac80211
43d2d2695e6be7042340c3321c2c597aa1cd7f70]
[11301.161980]  call_timer_fn+0x2a/0x140
[11301.161986]  __run_timers+0x269/0x330
[11301.161993]  timer_expire_remote+0x47/0x60
[11301.161997]  tmigr_handle_remote+0x498/0x570
[11301.162005]  handle_softirqs+0xe8/0x2c0
[11301.162011]  __irq_exit_rcu+0xc9/0xf0
[11301.162015]  sysvec_apic_timer_interrupt+0x71/0x90
[11301.162020]  </IRQ>
[11301.162022]  <TASK>
[11301.162024]  asm_sysvec_apic_timer_interrupt+0x1a/0x20
[11301.162028] RIP: 0010:cpuidle_enter_state+0xbb/0x440
[11301.162032] Code: 00 00 e8 c8 ec ec fe e8 93 ee ff ff 48 89 c5 0f
1f 44 00 00 31 ff e8 04 41 eb fe 45 84 ff 0f 85 74 01 00 00 fb 0f 1f
44 00 00 <45> 85 f6 0f 88 cb 01 00 00 44 89 f1 48 2b 2c 24 48 6b d1 68
48 89
[11301.162034] RSP: 0018:ffffffffb8403e10 EFLAGS: 00000246
[11301.162037] RAX: ffff897645967000 RBX: 0000000000000002 RCX: 0000000000000000
[11301.162039] RDX: 00000a4741bc4107 RSI: fffffffb5c704741 RDI: 0000000000000000
[11301.162041] RBP: 00000a4741bc4107 R08: ffff897645967000 R09: ffffffffb8619920
[11301.162043] R10: ffff8975fea217c0 R11: 0000000000000001 R12: ffff896702508800
[11301.162045] R13: ffffffffb8619920 R14: 0000000000000002 R15: 0000000000000000
[11301.162052]  cpuidle_enter+0x31/0x50
[11301.162057]  do_idle+0x14b/0x2a0
[11301.162063]  cpu_startup_entry+0x29/0x30
[11301.162067]  rest_init+0xcc/0xd0
[11301.162071]  start_kernel+0xa5b/0xa70
[11301.162077]  x86_64_start_reservations+0x24/0x30
[11301.162082]  x86_64_start_kernel+0xda/0xe0
[11301.162086]  common_startup_64+0x13e/0x141
[11301.162094]  </TASK>
[11301.162096] Modules linked in: rt2800usb rt2x00usb rt2800lib
rt2x00lib rfcomm snd_seq_dummy snd_hrtimer snd_seq snd_seq_device ccm
algif_aead des3_ede_x86_64 des_generic libdes cmac algif_skcipher md4
bnep algif_hash af_alg vfat fat amd_atl intel_rapl_msr
intel_rapl_common snd_hda_codec_alc882 snd_hda_codec_realtek_lib
snd_hda_codec_generic snd_hda_codec_atihdmi snd_hda_codec_hdmi
snd_hda_intel uvcvideo iwlmvm videobuf2_vmalloc kvm_amd snd_hda_codec
uvc snd_hda_core videobuf2_memops snd_intel_dspcfg videobuf2_v4l2
mac80211 btusb kvm snd_intel_sdw_acpi videobuf2_common btmtk snd_hwdep
btrtl videodev ee1004 libarc4 snd_pcm btbcm irqbypass igb atlantic
btintel snd_timer sp5100_tco mc mousedev iwlwifi wmi_bmof rapl macsec
dca snd mxm_wmi i2c_piix4 ptp pcspkr bluetooth soundcore k10temp
pps_core i2c_smbus gpio_amdpt gpio_generic mac_hid cfg80211 rfkill
crypto_user uinput pkcs8_key_parser i2c_dev ntsync nfnetlink zram
842_decompress 842_compress lz4hc_compress lz4_compress dm_crypt
encrypted_keys trusted asn1_encoder tee
[11301.162195]  dm_mod hid_logitech_hidpp amdgpu amdxcp i2c_algo_bit
drm_ttm_helper ttm drm_exec drm_panel_backlight_quirks gpu_sched
drm_suballoc_helper video drm_buddy sr_mod nvme drm_display_helper
hid_logitech_dj cdrom nvme_core ghash_clmulni_intel cec aesni_intel
nvme_keyring ccp nvme_auth hkdf wmi thunderbolt
[11301.162227] CR2: ffffffffffffff08
[11301.162230] ---[ end trace 0000000000000000 ]---
[11301.162232] RIP: 0010:led_blink_set_nosleep+0x1a/0xa0
[11301.162236] Code: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
f3 0f 1e fa 0f 1f 44 00 00 53 48 89 fb 48 83 ec 10 48 89 74 24 08 48
89 14 24 <48> 83 7f 38 00 74 07 48 83 7f 28 00 75 35 48 8d bb 88 00 00
00 e8
[11301.162238] RSP: 0018:ffffc9fc80003d88 EFLAGS: 00010286
[11301.162241] RAX: 0000000000000000 RBX: fffffffffffffed0 RCX: ffffffffc232c4f8
[11301.162243] RDX: 0000000000000000 RSI: 0000000000000001 RDI: fffffffffffffed0
[11301.162245] RBP: ffff89714752de40 R08: ffff8975fef1f2c0 R09: 0000000100a7df80
[11301.162247] R10: 0000000000000201 R11: 0000000000000000 R12: 0000000000000001
[11301.162249] R13: 0000000000000000 R14: ffffc9fc80003e10 R15: ffff8975fef1f2c0
[11301.162251] FS:  0000000000000000(0000) GS:ffff897645967000(0000)
knlGS:0000000000000000
[11301.162253] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[11301.162255] CR2: ffffffffffffff08 CR3: 00000001191d1000 CR4: 0000000000f50ef0
[11301.162258] PKRU: 55555554
[11301.162260] Kernel panic - not syncing: Fatal exception in interrupt
[11301.162414] Kernel Offset: 0x34c00000 from 0xffffffff81000000
(relocation range: 0xffffffff80000000-0xffffffffbfffffff)

This AI kept trying to patch net/mac80211/led.c . I really don't think
the problem is there. It found this one in the driver itself. Although
it's probably not it either.


> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
>  .../net/wireless/ralink/rt2x00/rt2x00leds.c   | 30 ++++++++++++++-----
>  1 file changed, 23 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
> index f5361d582d4e..8818e0b2447b 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
> @@ -100,6 +100,8 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
>
>         retval = led_classdev_register(device, &led->led_dev);
>         if (retval) {
> +               kfree(name);
> +               led->led_dev.name = NULL;
>                 rt2x00_err(rt2x00dev, "Failed to register led handler\n");
>                 return retval;
>         }
> @@ -111,15 +113,19 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
>
>  void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
>  {
> -       char name[36];
> +       char *name;
>         int retval;
>         unsigned long on_period;
>         unsigned long off_period;
>         const char *phy_name = wiphy_name(rt2x00dev->hw->wiphy);
>
>         if (rt2x00dev->led_radio.flags & LED_INITIALIZED) {
> -               snprintf(name, sizeof(name), "%s-%s::radio",
> -                        rt2x00dev->ops->name, phy_name);
> +               name = kasprintf(GFP_KERNEL, "%s-%s::radio",
> +                                rt2x00dev->ops->name, phy_name);
> +               if (!name) {
> +                       retval = -ENOMEM;
> +                       goto exit_fail;
> +               }
>
>                 retval = rt2x00leds_register_led(rt2x00dev,
>                                                  &rt2x00dev->led_radio,
> @@ -129,8 +135,12 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
>         }
>
>         if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) {
> -               snprintf(name, sizeof(name), "%s-%s::assoc",
> -                        rt2x00dev->ops->name, phy_name);
> +               name = kasprintf(GFP_KERNEL, "%s-%s::assoc",
> +                                rt2x00dev->ops->name, phy_name);
> +               if (!name) {
> +                       retval = -ENOMEM;
> +                       goto exit_fail;
> +               }
>
>                 retval = rt2x00leds_register_led(rt2x00dev,
>                                                  &rt2x00dev->led_assoc,
> @@ -140,8 +150,12 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
>         }
>
>         if (rt2x00dev->led_qual.flags & LED_INITIALIZED) {
> -               snprintf(name, sizeof(name), "%s-%s::quality",
> -                        rt2x00dev->ops->name, phy_name);
> +               name = kasprintf(GFP_KERNEL, "%s-%s::quality",
> +                                rt2x00dev->ops->name, phy_name);
> +               if (!name) {
> +                       retval = -ENOMEM;
> +                       goto exit_fail;
> +               }
>
>                 retval = rt2x00leds_register_led(rt2x00dev,
>                                                  &rt2x00dev->led_qual,
> @@ -182,6 +196,8 @@ static void rt2x00leds_unregister_led(struct rt2x00_led *led)
>                 led->led_dev.brightness_set(&led->led_dev, LED_OFF);
>
>         led->flags &= ~LED_REGISTERED;
> +       kfree(led->led_dev.name);
> +       led->led_dev.name = NULL;
>  }
>
>  void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
> --
> 2.54.0
>

^ permalink raw reply

* [PATCH 0/6] b43: complete N-PHY rev 8 + radio 2057 rev 8 support
From: Alessio Ferri @ 2026-05-18  1:49 UTC (permalink / raw)
  To: linux-wireless; +Cc: b43-dev, kvalo, linux-kernel

This series completes b43 support for the Broadcom N-PHY revision 8
paired with radio 2057 revision 8. b43 already supports the surrounding
PHY family - N-PHY rev 8 with radio 2057 rev 5 and rev 7 are handled,
and rev 16 with radio 2057 rev 9 is handled - but the rev 8 + rev 8
combination falls through four dispatcher gaps:

  - radio_2057.c, r2057_upload_inittabs(), case 8 lists radio_rev 5
    and 7 only;
  - radio_2057.c, r2057_get_chantabent_rev7(), case 8 lists radio_rev
    5 only;
  - tables_nphy.c, b43_nphy_get_ipa_gain_table(), case 8 lists
    radio_rev 5 only;
  - radio_2057.c carries r2057_rev8_init[] as a 54-entry stub commented
    out with "TODO: Which devices should use it?".

Two further pieces of plumbing are needed to reach those dispatchers
in the first place: d11 core revision 0x16 is missing from the b43
bcma id table, and the corerev 22 / radio 2057 combination needs the
24-bit indirect radio access path that brcmsmac uses for the same
silicon generation (see brcmsmac/phy/phy_cmn.c read_radio_reg() /
write_radio_reg()).

The series:

  1/6  b43: add d11 core revision 0x16 to id table
  2/6  b43: route d11 corerev 22 to 24-bit indirect radio access
  3/6  b43: support radio 2057 rev 8
  4/6  b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
  5/6  b43: add channel info table for N-PHY r8 + radio 2057 r8
  6/6  b43: add RF power offset for N-PHY r8 + radio 2057 r8

Patches are ordered so that each one fixes the next visible failure
in bring-up: 1/6 makes b43 bind to the core, 2/6 lets phy versioning
read coherent radio identifiers, 3/6 unblocks the boot-time radio
calibration that otherwise stalls the PSM at microcode startup, and
4/6-6/6 fill the remaining 2.4 GHz dispatcher entries so
b43_nphy_set_channel completes to the default channel and core_init
proceeds past PHY init.

Tested on a D-Link DSL-3580L (Broadcom BCM6362 SoC, single-die 2.4 GHz
N-PHY rev 8 + radio 2057 rev 8 in 2.4 GHz IPA mode). The chip is in
service worldwide in xDSL CPE devices.

b43 is currently Orphan in MAINTAINERS. These patches do not add a
new chip family or PHY infrastructure; they fill four explicit
dispatcher gaps for a combination of an already-supported PHY and
an already-supported radio.

Alessio Ferri (6):
  b43: add d11 core revision 0x16 to id table
  b43: route d11 corerev 22 to 24-bit indirect radio access
  b43: support radio 2057 rev 8
  b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
  b43: add channel info table for N-PHY r8 + radio 2057 r8
  b43: add RF power offset for N-PHY r8 + radio 2057 r8

 drivers/net/wireless/broadcom/b43/main.c      |  10 +-
 .../net/wireless/broadcom/b43/radio_2057.c    | 230 ++++++++++++++++--
 .../net/wireless/broadcom/b43/tables_nphy.c   |  58 +++++
 3 files changed, 280 insertions(+), 18 deletions(-)

-- 
2.43.0


^ permalink raw reply

* [PATCH 1/6] b43: add d11 core revision 0x16 to id table
From: Alessio Ferri @ 2026-05-18  1:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: b43-dev, kvalo, linux-kernel
In-Reply-To: <8c0a07d2-9ec9-43d6-bdf7-f625bbb4a38a@mythread.it>

Add d11 core revision 0x16 (= 22) to the b43 bcma device id table.

The b43 bcma id table covers d11 revisions 0x11, 0x15, 0x17, 0x18,
0x1C, 0x1D, 0x1E, 0x28 and 0x2A. Revision 0x16 belongs to the same
N-PHY family as revisions 0x17 and 0x18 (radio 2057) and needs no
new PHY or radio code beyond the radio_rev 8 dispatcher entries
added later in this series - only the device id entry is missing.
Without it bcma scan enumerates the 802.11 core but no driver binds.

The revision is used by the Broadcom BCM6362 single-die integrated
2.4 GHz wireless block found in xDSL SoCs.

Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
---
 drivers/net/wireless/broadcom/b43/main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index b0e6aeb0b..673a56c30 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -117,6 +117,7 @@ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if over
 static const struct bcma_device_id b43_bcma_tbl[] = {
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x15, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x16, BCMA_ANY_CLASS),
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1C, BCMA_ANY_CLASS),
-- 
2.43.0


Il 18/05/2026 03:49, Alessio Ferri ha scritto:
> This series completes b43 support for the Broadcom N-PHY revision 8
> paired with radio 2057 revision 8. b43 already supports the surrounding
> PHY family - N-PHY rev 8 with radio 2057 rev 5 and rev 7 are handled,
> and rev 16 with radio 2057 rev 9 is handled - but the rev 8 + rev 8
> combination falls through four dispatcher gaps:
> 
>   - radio_2057.c, r2057_upload_inittabs(), case 8 lists radio_rev 5
>     and 7 only;
>   - radio_2057.c, r2057_get_chantabent_rev7(), case 8 lists radio_rev
>     5 only;
>   - tables_nphy.c, b43_nphy_get_ipa_gain_table(), case 8 lists
>     radio_rev 5 only;
>   - radio_2057.c carries r2057_rev8_init[] as a 54-entry stub commented
>     out with "TODO: Which devices should use it?".
> 
> Two further pieces of plumbing are needed to reach those dispatchers
> in the first place: d11 core revision 0x16 is missing from the b43
> bcma id table, and the corerev 22 / radio 2057 combination needs the
> 24-bit indirect radio access path that brcmsmac uses for the same
> silicon generation (see brcmsmac/phy/phy_cmn.c read_radio_reg() /
> write_radio_reg()).
> 
> The series:
> 
>   1/6  b43: add d11 core revision 0x16 to id table
>   2/6  b43: route d11 corerev 22 to 24-bit indirect radio access
>   3/6  b43: support radio 2057 rev 8
>   4/6  b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
>   5/6  b43: add channel info table for N-PHY r8 + radio 2057 r8
>   6/6  b43: add RF power offset for N-PHY r8 + radio 2057 r8
> 
> Patches are ordered so that each one fixes the next visible failure
> in bring-up: 1/6 makes b43 bind to the core, 2/6 lets phy versioning
> read coherent radio identifiers, 3/6 unblocks the boot-time radio
> calibration that otherwise stalls the PSM at microcode startup, and
> 4/6-6/6 fill the remaining 2.4 GHz dispatcher entries so
> b43_nphy_set_channel completes to the default channel and core_init
> proceeds past PHY init.
> 
> Tested on a D-Link DSL-3580L (Broadcom BCM6362 SoC, single-die 2.4 GHz
> N-PHY rev 8 + radio 2057 rev 8 in 2.4 GHz IPA mode). The chip is in
> service worldwide in xDSL CPE devices.
> 
> b43 is currently Orphan in MAINTAINERS. These patches do not add a
> new chip family or PHY infrastructure; they fill four explicit
> dispatcher gaps for a combination of an already-supported PHY and
> an already-supported radio.
> 
> Alessio Ferri (6):
>   b43: add d11 core revision 0x16 to id table
>   b43: route d11 corerev 22 to 24-bit indirect radio access
>   b43: support radio 2057 rev 8
>   b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
>   b43: add channel info table for N-PHY r8 + radio 2057 r8
>   b43: add RF power offset for N-PHY r8 + radio 2057 r8
> 
>  drivers/net/wireless/broadcom/b43/main.c      |  10 +-
>  .../net/wireless/broadcom/b43/radio_2057.c    | 230 ++++++++++++++++--
>  .../net/wireless/broadcom/b43/tables_nphy.c   |  58 +++++
>  3 files changed, 280 insertions(+), 18 deletions(-)
> 


^ permalink raw reply related

* [PATCH 4/6] b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
From: Alessio Ferri @ 2026-05-18  1:53 UTC (permalink / raw)
  To: linux-wireless; +Cc: b43-dev, kvalo, linux-kernel
In-Reply-To: <8c0a07d2-9ec9-43d6-bdf7-f625bbb4a38a@mythread.it>

Add the 2.4 GHz IPA TX gain table for N-PHY rev 8 paired with radio
2057 rev 8 and wire it to the existing dispatcher.

b43_nphy_get_ipa_gain_table() in tables_nphy.c currently handles
case 8 only for radio_rev == 5; radio_rev == 8 falls through and
the function logs:

    b43-phyX ERROR: No 2GHz IPA gain table available for this device
    b43-phyX ERROR: PHY init: Channel switch to default failed

leaving b43_phy_init() to return an error and core_init to abort
before the MAC is enabled.

The new b43_ntab_tx_gain_ipa_2057_rev8_2g[] is 128 u32 entries,
matching the layout of the existing b43_ntab_tx_gain_ipa_2057_
rev5_2g and b43_ntab_tx_gain_ipa_2057_rev9_2g siblings in this
file. Each entry packs five gain fields decoded by
wlc_phy_get_tx_gain_nphy in the proprietary driver, the same
encoding b43 uses for the other 2057 IPA tables.

The high byte of every entry differs from the rev 5 sibling (0x40
vs 0x30): different PAD-gain code prefix for the rev 8 front-end.
The low 24 bits coincide with rev 5 across the whole table - the
gain step amplitudes are the same, only the PAD-gain selector
prefix changes.

Values extracted from an MMIO dump of the proprietary Broadcom wl
driver running on BCM6362 silicon (wl driver 6.30.102.7).
Encoding cross-validated by re-deriving the in-tree rev 5 table
from the same source using the same extraction method - the
result matches b43_ntab_tx_gain_ipa_2057_rev5_2g byte-for-byte.

Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
---
 .../net/wireless/broadcom/b43/tables_nphy.c   | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/net/wireless/broadcom/b43/tables_nphy.c b/drivers/net/wireless/broadcom/b43/tables_nphy.c
index 41a25d909..84e8d718d 100644
--- a/drivers/net/wireless/broadcom/b43/tables_nphy.c
+++ b/drivers/net/wireless/broadcom/b43/tables_nphy.c
@@ -2715,6 +2715,43 @@ static const u32 b43_ntab_tx_gain_ipa_2057_rev5_2g[] = {
 	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
 };
 
+/* Extracted from MMIO dump of 6.30.102.7 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev8_2g[] = {
+	0x40ff0031, 0x40e70031, 0x40e7002e, 0x40cf002e,
+	0x40bf002e, 0x40af002e, 0x409f002f, 0x407f0033,
+	0x407f0031, 0x407f002e, 0x4077002e, 0x406f002e,
+	0x4067002e, 0x405f002f, 0x40570030, 0x4057002d,
+	0x404f002e, 0x40470031, 0x4047002e, 0x4047002c,
+	0x40470029, 0x403f002c, 0x403f0029, 0x4037002d,
+	0x4037002a, 0x40370028, 0x402f002c, 0x402f002a,
+	0x402f0028, 0x402f0026, 0x4027002c, 0x40270029,
+	0x40270027, 0x40270025, 0x40270023, 0x401f002c,
+	0x401f002a, 0x401f0028, 0x401f0025, 0x401f0024,
+	0x401f0022, 0x401f001f, 0x4017002d, 0x4017002b,
+	0x40170028, 0x40170026, 0x40170024, 0x40170022,
+	0x40170020, 0x4017001e, 0x4017001d, 0x4017001b,
+	0x4017001a, 0x40170018, 0x40170017, 0x40170015,
+	0x400f002c, 0x400f0029, 0x400f0027, 0x400f0024,
+	0x400f0022, 0x400f0021, 0x400f001f, 0x400f001d,
+	0x400f001b, 0x400f001a, 0x400f0018, 0x400f0017,
+	0x400f0016, 0x400f0015, 0x400f0115, 0x400f0215,
+	0x400f0315, 0x400f0415, 0x400f0515, 0x400f0615,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+	0x400f0715, 0x400f0715, 0x400f0715, 0x400f0715,
+};
+
+
 /* Extracted from MMIO dump of 6.30.223.141 */
 static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = {
 	0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029,
@@ -3651,6 +3688,8 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
 		case 8:
 			if (phy->radio_rev == 5)
 				return b43_ntab_tx_gain_ipa_2057_rev5_2g;
+			if (phy->radio_rev == 8)
+				return b43_ntab_tx_gain_ipa_2057_rev8_2g;
 			break;
 		case 6:
 			if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162)
-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/6] b43: route d11 corerev 22 to 24-bit indirect radio access
From: Alessio Ferri @ 2026-05-18  1:51 UTC (permalink / raw)
  To: linux-wireless; +Cc: b43-dev, kvalo, linux-kernel
In-Reply-To: <8c0a07d2-9ec9-43d6-bdf7-f625bbb4a38a@mythread.it>

D11 core revision 22 is an outlier in the corerev-to-radio-access
mapping. b43_phy_versioning() reads radio identifiers via two
different paths:

  - core_rev >= 24: 24-bit indirect access (B43_MMIO_RADIO24_CONTROL
    + B43_MMIO_RADIO24_DATA);
  - otherwise: legacy 4-wire access (B43_MMIO_RADIO_CONTROL +
    B43_MMIO_RADIO_DATA_LOW/HIGH).

Corerev 22 backports the older 802.11 core but pairs it with a radio
in the 2057 family, which requires the 24-bit indirect path. With
the current dispatch, corerev 22 falls into the legacy 4-wire branch,
reads garbage for radio_id, and bails out with -EOPNOTSUPP at the
"FOUND UNSUPPORTED RADIO" branch below.

brcmsmac handles the same silicon family with the equivalent
dispatch in drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/
phy_cmn.c read_radio_reg() and write_radio_reg():

    if ((D11REV_GE(pi->sh->corerev, 24)) ||
        (D11REV_IS(pi->sh->corerev, 22)
         && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
            /* radioregaddr / radioregdata (indirect) */
    } else {
            /* phy4waddr / phy4wdatalo (legacy)      */
    }

The "phy_type != PHY_TYPE_SSN" carve-out in brcmsmac is for the SSN
PHY variant of corerev 22, which uses the legacy path. b43 does not
support SSN/SSLPN PHYs - they are rejected earlier in
b43_phy_versioning() at the "unsupported PHY type" switch - so by
the time control reaches the radio versioning dispatch there is no
SSN device to mis-route. A positive (core_rev == 22) clause is
therefore sufficient and equivalent.

Encountered on the Broadcom BCM6362 single-die integrated 2.4 GHz
wireless block (radio 2057 rev 8, paired with d11 corerev 22 on
this silicon).

Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
---
 drivers/net/wireless/broadcom/b43/main.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 673a56c30..7f96df5eb 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -4555,7 +4555,11 @@ static int b43_phy_versioning(struct b43_wldev *dev)
 		radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);
 
 		radio_ver = 0; /* Is there version somewhere? */
-	} else if (core_rev >= 24) {
+	} else if (core_rev >= 24 || core_rev == 22) {
+		/*
+		 * D11 corerev 22 pairs an older 802.11 core with a 2057
+		 * radio that requires the 24-bit indirect access path.
+		 */
 		u16 radio24[3];
 
 		for (tmp = 0; tmp < 3; tmp++) {
-- 
2.43.0



Il 18/05/2026 03:49, Alessio Ferri ha scritto:
> This series completes b43 support for the Broadcom N-PHY revision 8
> paired with radio 2057 revision 8. b43 already supports the surrounding
> PHY family - N-PHY rev 8 with radio 2057 rev 5 and rev 7 are handled,
> and rev 16 with radio 2057 rev 9 is handled - but the rev 8 + rev 8
> combination falls through four dispatcher gaps:
> 
>   - radio_2057.c, r2057_upload_inittabs(), case 8 lists radio_rev 5
>     and 7 only;
>   - radio_2057.c, r2057_get_chantabent_rev7(), case 8 lists radio_rev
>     5 only;
>   - tables_nphy.c, b43_nphy_get_ipa_gain_table(), case 8 lists
>     radio_rev 5 only;
>   - radio_2057.c carries r2057_rev8_init[] as a 54-entry stub commented
>     out with "TODO: Which devices should use it?".
> 
> Two further pieces of plumbing are needed to reach those dispatchers
> in the first place: d11 core revision 0x16 is missing from the b43
> bcma id table, and the corerev 22 / radio 2057 combination needs the
> 24-bit indirect radio access path that brcmsmac uses for the same
> silicon generation (see brcmsmac/phy/phy_cmn.c read_radio_reg() /
> write_radio_reg()).
> 
> The series:
> 
>   1/6  b43: add d11 core revision 0x16 to id table
>   2/6  b43: route d11 corerev 22 to 24-bit indirect radio access
>   3/6  b43: support radio 2057 rev 8
>   4/6  b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
>   5/6  b43: add channel info table for N-PHY r8 + radio 2057 r8
>   6/6  b43: add RF power offset for N-PHY r8 + radio 2057 r8
> 
> Patches are ordered so that each one fixes the next visible failure
> in bring-up: 1/6 makes b43 bind to the core, 2/6 lets phy versioning
> read coherent radio identifiers, 3/6 unblocks the boot-time radio
> calibration that otherwise stalls the PSM at microcode startup, and
> 4/6-6/6 fill the remaining 2.4 GHz dispatcher entries so
> b43_nphy_set_channel completes to the default channel and core_init
> proceeds past PHY init.
> 
> Tested on a D-Link DSL-3580L (Broadcom BCM6362 SoC, single-die 2.4 GHz
> N-PHY rev 8 + radio 2057 rev 8 in 2.4 GHz IPA mode). The chip is in
> service worldwide in xDSL CPE devices.
> 
> b43 is currently Orphan in MAINTAINERS. These patches do not add a
> new chip family or PHY infrastructure; they fill four explicit
> dispatcher gaps for a combination of an already-supported PHY and
> an already-supported radio.
> 
> Alessio Ferri (6):
>   b43: add d11 core revision 0x16 to id table
>   b43: route d11 corerev 22 to 24-bit indirect radio access
>   b43: support radio 2057 rev 8
>   b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
>   b43: add channel info table for N-PHY r8 + radio 2057 r8
>   b43: add RF power offset for N-PHY r8 + radio 2057 r8
> 
>  drivers/net/wireless/broadcom/b43/main.c      |  10 +-
>  .../net/wireless/broadcom/b43/radio_2057.c    | 230 ++++++++++++++++--
>  .../net/wireless/broadcom/b43/tables_nphy.c   |  58 +++++
>  3 files changed, 280 insertions(+), 18 deletions(-)
> 


^ permalink raw reply related

* [PATCH 5/6] b43: add channel info table for N-PHY r8 + radio 2057 r8
From: Alessio Ferri @ 2026-05-18  1:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: b43-dev, kvalo, linux-kernel
In-Reply-To: <8c0a07d2-9ec9-43d6-bdf7-f625bbb4a38a@mythread.it>

Add the 2.4 GHz channel info table for N-PHY rev 8 paired with
radio 2057 rev 8 and wire it to the existing dispatcher in
r2057_get_chantabent_rev7().

The dispatcher's case 8 currently handles radio_rev == 5 only.
For radio_rev == 8 both output pointers stay NULL,
b43_nphy_set_channel() returns an error and channel switch to
the default channel fails.

The new b43_nphy_chantab_phy_rev8_radio_rev8[] is 14 entries
covering the standard 2.4 GHz channel set (2412..2472 in 5 MHz
steps, plus 2484 for channel 14). Each entry uses the
b43_nphy_chantabent_rev7_2g struct layout already defined in this
file: 18 RADIOREGS7_2G fields followed by 6 PHYREGS (SFO config).

Values extracted from an MMIO dump of the proprietary Broadcom wl
driver running on BCM6362 silicon (wl driver 6.30.102.7). Field
ordering and encoding cross-validated by re-deriving the in-tree
b43_nphy_chantab_phy_rev8_radio_rev5 table from the same source
through the same extraction - the result matches the existing
in-tree table byte-for-byte.

Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
---
 .../net/wireless/broadcom/b43/radio_2057.c    | 106 ++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/drivers/net/wireless/broadcom/b43/radio_2057.c b/drivers/net/wireless/broadcom/b43/radio_2057.c
index 9f693d92b..e761f899b 100644
--- a/drivers/net/wireless/broadcom/b43/radio_2057.c
+++ b/drivers/net/wireless/broadcom/b43/radio_2057.c
@@ -445,6 +445,109 @@ static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev17_radio
 	},
 };
 
+/* Extracted from MMIO dump of 6.30.102.7 */
+static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev8_radio_rev8[] = {
+	{
+		.freq			= 2412,
+		RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+			      0x09, 0x0f, 0x09, 0x07, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+	},
+	{
+		.freq			= 2417,
+		RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+			      0x09, 0x0f, 0x09, 0x07, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+	},
+	{
+		.freq			= 2422,
+		RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+			      0x09, 0x0f, 0x09, 0x06, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+	},
+	{
+		.freq			= 2427,
+		RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+			      0x09, 0x0f, 0x09, 0x06, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+	},
+	{
+		.freq			= 2432,
+		RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+			      0x09, 0x0f, 0x09, 0x06, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+	},
+	{
+		.freq			= 2437,
+		RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+			      0x09, 0x0f, 0x09, 0x06, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+	},
+	{
+		.freq			= 2442,
+		RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+			      0x09, 0x0f, 0x08, 0x05, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+	},
+	{
+		.freq			= 2447,
+		RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+			      0x09, 0x0f, 0x08, 0x05, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+	},
+	{
+		.freq			= 2452,
+		RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+			      0x09, 0x0f, 0x08, 0x05, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+	},
+	{
+		.freq			= 2457,
+		RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+			      0x09, 0x0f, 0x08, 0x05, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+	},
+	{
+		.freq			= 2462,
+		RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+			      0x09, 0x0f, 0x08, 0x05, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+	},
+	{
+		.freq			= 2467,
+		RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
+			      0x09, 0x0f, 0x07, 0x04, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+	},
+	{
+		.freq			= 2472,
+		RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
+			      0x09, 0x0f, 0x07, 0x04, 0x61, 0x73, 0xf0, 0x61,
+			      0x73, 0xf0),
+		PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+	},
+	{
+		.freq			= 2484,
+		RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4,
+			      0x09, 0x0f, 0x07, 0x04, 0x61, 0x73, 0xe0, 0x61,
+			      0x73, 0xe0),
+		PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+	}
+};
+
+
 /* Extracted from MMIO dump of 6.30.223.141 */
 static const struct b43_nphy_chantabent_rev7 b43_nphy_chantab_phy_rev16_radio_rev9[] = {
 	{
@@ -678,6 +781,9 @@ void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
 		if (phy->radio_rev == 5) {
 			e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev5;
 			len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev5);
+		} else if (phy->radio_rev == 8) {
+			e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev8;
+			len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev8);
 		}
 		break;
 	case 16:
-- 
2.43.0


^ permalink raw reply related

* [PATCH 3/6] b43: support radio 2057 rev 8
From: Alessio Ferri @ 2026-05-18  1:51 UTC (permalink / raw)
  To: linux-wireless; +Cc: b43-dev, kvalo, linux-kernel
In-Reply-To: <8c0a07d2-9ec9-43d6-bdf7-f625bbb4a38a@mythread.it>

Add support for radio 2057 revision 8, paired with N-PHY rev 8 on
the Broadcom BCM6362 single-die integrated 2.4 GHz wireless block.

Three correlated changes are needed for the same chip:

  - main.c: the radio_rev allow-list under B43_PHYTYPE_N currently
    accepts radio 2057 revisions 9 and 14 only; extend to include
    rev 8.

  - radio_2057.c: the existing r2057_rev8_init[] is a 54-entry stub
    declared inside a /* TODO: Which devices should use it? */
    comment block and never referenced from r2057_upload_inittabs().
    Replace it with the full 412-entry register set actually
    programmed by the proprietary Broadcom wl driver on this radio.
    The origin of the original 54-entry stub cannot be traced - 8
    of its entries do not appear at all in the rev 8 register set
    and 7 more carry different values, so the stub is in any case
    not the rev 8 table. Loading it instead of the real table
    leaves the radio partially initialised and stalls the PSM at
    boot-time radio calibration, producing a "Microcode not
    responding" timeout one second into b43_upload_microcode().

  - radio_2057.c: r2057_upload_inittabs() case 8 handles radio_rev
    5 and 7 only; add the radio_rev == 8 branch pointing at the
    new table.

The init table is extracted from an MMIO dump of the radio
register set programmed during proprietary driver initialisation
on BCM6362 silicon (Broadcom wl driver 6.30.102.7). Layout
convention matches the existing r2057_rev5_init[] /
r2057_rev7_init[] / r2057_rev9_init[] arrays in this file:
{ u16 reg, u16 val } per entry.

Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
---
 drivers/net/wireless/broadcom/b43/main.c      |   3 +-
 .../net/wireless/broadcom/b43/radio_2057.c    | 124 +++++++++++++++---
 2 files changed, 110 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 7f96df5eb..0e4102f3c 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -4609,7 +4609,8 @@ static int b43_phy_versioning(struct b43_wldev *dev)
 		    radio_id != 0x2057)
 			unsupported = 1;
 		if (radio_id == 0x2057 &&
-		    !(radio_rev == 9 || radio_rev == 14))
+		    !(radio_rev == 8 || radio_rev == 9 ||
+		      radio_rev == 14))
 			unsupported = 1;
 		break;
 	case B43_PHYTYPE_LP:
diff --git a/drivers/net/wireless/broadcom/b43/radio_2057.c b/drivers/net/wireless/broadcom/b43/radio_2057.c
index bd7dafb56..9f693d92b 100644
--- a/drivers/net/wireless/broadcom/b43/radio_2057.c
+++ b/drivers/net/wireless/broadcom/b43/radio_2057.c
@@ -73,24 +73,112 @@ static u16 r2057_rev7_init[][2] = {
 	{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
 };
 
-/* TODO: Which devices should use it?
+/* Extracted from MMIO dump of 6.30.102.7 */
 static u16 r2057_rev8_init[][2] = {
-	{ 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
-	{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
-	{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f },
-	{ 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 }, { 0x7C, 0x0f },
-	{ 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
-	{ 0xA1, 0x20 }, { 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
-	{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0xF3, 0x58 },
-	{ 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x0f }, { 0x102, 0xee },
-	{ 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x126, 0x20 },
-	{ 0x14E, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
-	{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
-	{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
-	{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
-	{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
+	{ 0x0000, 0x0008 }, { 0x0001, 0x0057 }, { 0x0002, 0x0020 }, { 0x0003, 0x001f },
+	{ 0x0004, 0x0004 }, { 0x0005, 0x0002 }, { 0x0006, 0x0001 }, { 0x0007, 0x0001 },
+	{ 0x0008, 0x0001 }, { 0x0009, 0x0069 }, { 0x000a, 0x0066 }, { 0x000b, 0x0006 },
+	{ 0x000c, 0x0018 }, { 0x000d, 0x0003 }, { 0x000e, 0x0020 }, { 0x000f, 0x0020 },
+	{ 0x0010, 0x0000 }, { 0x0011, 0x007c }, { 0x0012, 0x0042 }, { 0x0013, 0x00bd },
+	{ 0x0014, 0x0007 }, { 0x0015, 0x0087 }, { 0x0016, 0x0008 }, { 0x0017, 0x0017 },
+	{ 0x0018, 0x0007 }, { 0x0019, 0x0000 }, { 0x001a, 0x0002 }, { 0x001b, 0x0013 },
+	{ 0x001c, 0x003e }, { 0x001d, 0x003e }, { 0x001e, 0x0096 }, { 0x001f, 0x0004 },
+	{ 0x0020, 0x0000 }, { 0x0021, 0x0000 }, { 0x0022, 0x0017 }, { 0x0023, 0x0006 },
+	{ 0x0024, 0x0001 }, { 0x0025, 0x0006 }, { 0x0026, 0x0004 }, { 0x0027, 0x000d },
+	{ 0x0028, 0x000d }, { 0x0029, 0x0030 }, { 0x002a, 0x0032 }, { 0x002b, 0x0008 },
+	{ 0x002c, 0x001c }, { 0x002d, 0x0002 }, { 0x002e, 0x0004 }, { 0x002f, 0x007f },
+	{ 0x0030, 0x0027 }, { 0x0031, 0x0000 }, { 0x0032, 0x0000 }, { 0x0033, 0x0000 },
+	{ 0x0034, 0x0000 }, { 0x0035, 0x0020 }, { 0x0036, 0x0018 }, { 0x0037, 0x0007 },
+	{ 0x0038, 0x0066 }, { 0x0039, 0x0066 }, { 0x003a, 0x0066 }, { 0x003b, 0x0066 },
+	{ 0x003c, 0x00ff }, { 0x003d, 0x00ff }, { 0x003e, 0x00ff }, { 0x003f, 0x00ff },
+	{ 0x0040, 0x0016 }, { 0x0041, 0x0007 }, { 0x0042, 0x0029 }, { 0x0043, 0x0007 },
+	{ 0x0044, 0x0006 }, { 0x0045, 0x0003 }, { 0x0046, 0x0001 }, { 0x0047, 0x0007 },
+	{ 0x0048, 0x0088 }, { 0x0049, 0x0005 }, { 0x004a, 0x0077 }, { 0x004b, 0x0066 },
+	{ 0x004c, 0x0066 }, { 0x004d, 0x0000 }, { 0x004e, 0x0004 }, { 0x004f, 0x000c },
+	{ 0x0050, 0x0000 }, { 0x0051, 0x0070 }, { 0x0056, 0x0007 }, { 0x0057, 0x0000 },
+	{ 0x0058, 0x0000 }, { 0x0059, 0x0088 }, { 0x005a, 0x0000 }, { 0x005b, 0x001f },
+	{ 0x005c, 0x0020 }, { 0x005d, 0x0001 }, { 0x005e, 0x0030 }, { 0x005f, 0x0070 },
+	{ 0x0060, 0x0000 }, { 0x0061, 0x0000 }, { 0x0062, 0x0033 }, { 0x0063, 0x000f },
+	{ 0x0064, 0x0013 }, { 0x0065, 0x0000 }, { 0x0066, 0x00ee }, { 0x0069, 0x0000 },
+	{ 0x006a, 0x007e }, { 0x006b, 0x003f }, { 0x006c, 0x007f }, { 0x006d, 0x0078 },
+	{ 0x006e, 0x0058 }, { 0x006f, 0x0088 }, { 0x0070, 0x0008 }, { 0x0071, 0x000f },
+	{ 0x0072, 0x00bc }, { 0x0073, 0x0008 }, { 0x0074, 0x0060 }, { 0x0075, 0x001a },
+	{ 0x0076, 0x0070 }, { 0x0077, 0x0000 }, { 0x0078, 0x0000 }, { 0x0079, 0x0000 },
+	{ 0x007a, 0x0033 }, { 0x007b, 0x001a }, { 0x007c, 0x0014 }, { 0x007d, 0x00ee },
+	{ 0x0080, 0x003c }, { 0x0081, 0x0001 }, { 0x0082, 0x000a }, { 0x0083, 0x009d },
+	{ 0x0084, 0x000a }, { 0x0085, 0x0000 }, { 0x0086, 0x0040 }, { 0x0087, 0x0040 },
+	{ 0x0088, 0x0088 }, { 0x0089, 0x0010 }, { 0x008a, 0x00f0 }, { 0x008b, 0x0010 },
+	{ 0x008c, 0x00f0 }, { 0x008d, 0x0000 }, { 0x008e, 0x0000 }, { 0x008f, 0x0010 },
+	{ 0x0090, 0x0055 }, { 0x0091, 0x003f }, { 0x0092, 0x0036 }, { 0x0093, 0x0000 },
+	{ 0x0094, 0x0000 }, { 0x0095, 0x0000 }, { 0x0096, 0x0087 }, { 0x0097, 0x0011 },
+	{ 0x0098, 0x0000 }, { 0x0099, 0x0033 }, { 0x009a, 0x0088 }, { 0x009b, 0x0000 },
+	{ 0x009c, 0x0087 }, { 0x009d, 0x0011 }, { 0x009e, 0x0000 }, { 0x009f, 0x0033 },
+	{ 0x00a0, 0x0088 }, { 0x00a1, 0x0020 }, { 0x00a2, 0x003f }, { 0x00a3, 0x0044 },
+	{ 0x00a4, 0x008c }, { 0x00a5, 0x006c }, { 0x00a6, 0x0022 }, { 0x00a7, 0x00be },
+	{ 0x00a8, 0x0055 }, { 0x00aa, 0x000c }, { 0x00ab, 0x00aa }, { 0x00ac, 0x0002 },
+	{ 0x00ad, 0x0000 }, { 0x00ae, 0x0010 }, { 0x00af, 0x0001 }, { 0x00b0, 0x0000 },
+	{ 0x00b1, 0x0000 }, { 0x00b2, 0x0080 }, { 0x00b3, 0x0060 }, { 0x00b4, 0x0044 },
+	{ 0x00b5, 0x0055 }, { 0x00b6, 0x0001 }, { 0x00b7, 0x0055 }, { 0x00b8, 0x0001 },
+	{ 0x00b9, 0x0005 }, { 0x00ba, 0x0055 }, { 0x00bb, 0x0055 }, { 0x00c1, 0x0000 },
+	{ 0x00c2, 0x0000 }, { 0x00c3, 0x0000 }, { 0x00c4, 0x0000 }, { 0x00c5, 0x0000 },
+	{ 0x00c6, 0x0000 }, { 0x00c7, 0x0000 }, { 0x00c8, 0x0000 }, { 0x00c9, 0x0001 },
+	{ 0x00ca, 0x0000 }, { 0x00cb, 0x0000 }, { 0x00cc, 0x0000 }, { 0x00cd, 0x0000 },
+	{ 0x00ce, 0x005e }, { 0x00cf, 0x000c }, { 0x00d0, 0x000c }, { 0x00d1, 0x000c },
+	{ 0x00d2, 0x0000 }, { 0x00d3, 0x002b }, { 0x00d4, 0x000c }, { 0x00d5, 0x0000 },
+	{ 0x00d6, 0x0070 }, { 0x00db, 0x0007 }, { 0x00dc, 0x0000 }, { 0x00dd, 0x0000 },
+	{ 0x00de, 0x0088 }, { 0x00df, 0x0000 }, { 0x00e0, 0x001f }, { 0x00e1, 0x0020 },
+	{ 0x00e2, 0x0001 }, { 0x00e3, 0x0030 }, { 0x00e4, 0x0070 }, { 0x00e5, 0x0000 },
+	{ 0x00e6, 0x0000 }, { 0x00e7, 0x0033 }, { 0x00e8, 0x000f }, { 0x00e9, 0x0013 },
+	{ 0x00ea, 0x0000 }, { 0x00eb, 0x00ee }, { 0x00ee, 0x0000 }, { 0x00ef, 0x007e },
+	{ 0x00f0, 0x003f }, { 0x00f1, 0x007f }, { 0x00f2, 0x0078 }, { 0x00f3, 0x0058 },
+	{ 0x00f4, 0x0088 }, { 0x00f5, 0x0008 }, { 0x00f6, 0x000f }, { 0x00f7, 0x00bc },
+	{ 0x00f8, 0x0008 }, { 0x00f9, 0x0060 }, { 0x00fa, 0x001a }, { 0x00fb, 0x0070 },
+	{ 0x00fc, 0x0000 }, { 0x00fd, 0x0000 }, { 0x00fe, 0x0000 }, { 0x00ff, 0x0033 },
+	{ 0x0100, 0x001a }, { 0x0101, 0x0014 }, { 0x0102, 0x00ee }, { 0x0105, 0x003c },
+	{ 0x0106, 0x0001 }, { 0x0107, 0x000a }, { 0x0108, 0x009d }, { 0x0109, 0x000a },
+	{ 0x010a, 0x0000 }, { 0x010b, 0x0040 }, { 0x010c, 0x0040 }, { 0x010d, 0x0088 },
+	{ 0x010e, 0x0010 }, { 0x010f, 0x00f0 }, { 0x0110, 0x0010 }, { 0x0111, 0x00f0 },
+	{ 0x0112, 0x0000 }, { 0x0113, 0x0000 }, { 0x0114, 0x0010 }, { 0x0115, 0x0055 },
+	{ 0x0116, 0x003f }, { 0x0117, 0x0036 }, { 0x0118, 0x0000 }, { 0x0119, 0x0000 },
+	{ 0x011a, 0x0000 }, { 0x011b, 0x0087 }, { 0x011c, 0x0011 }, { 0x011d, 0x0000 },
+	{ 0x011e, 0x0033 }, { 0x011f, 0x0088 }, { 0x0120, 0x0000 }, { 0x0121, 0x0087 },
+	{ 0x0122, 0x0011 }, { 0x0123, 0x0000 }, { 0x0124, 0x0033 }, { 0x0125, 0x0088 },
+	{ 0x0126, 0x0020 }, { 0x0127, 0x003f }, { 0x0128, 0x0044 }, { 0x0129, 0x008c },
+	{ 0x012a, 0x006c }, { 0x012b, 0x0022 }, { 0x012c, 0x00be }, { 0x012d, 0x0055 },
+	{ 0x012f, 0x000c }, { 0x0130, 0x00aa }, { 0x0131, 0x0002 }, { 0x0132, 0x0000 },
+	{ 0x0133, 0x0010 }, { 0x0134, 0x0001 }, { 0x0135, 0x0000 }, { 0x0136, 0x0000 },
+	{ 0x0137, 0x0080 }, { 0x0138, 0x0060 }, { 0x0139, 0x0044 }, { 0x013a, 0x0055 },
+	{ 0x013b, 0x0001 }, { 0x013c, 0x0055 }, { 0x013d, 0x0001 }, { 0x013e, 0x0005 },
+	{ 0x013f, 0x0055 }, { 0x0140, 0x0055 }, { 0x0146, 0x0000 }, { 0x0147, 0x0000 },
+	{ 0x0148, 0x0000 }, { 0x0149, 0x0000 }, { 0x014a, 0x0000 }, { 0x014b, 0x0000 },
+	{ 0x014c, 0x0000 }, { 0x014d, 0x0000 }, { 0x014e, 0x0001 }, { 0x014f, 0x0000 },
+	{ 0x0150, 0x0000 }, { 0x0151, 0x0000 }, { 0x0154, 0x000c }, { 0x0155, 0x000c },
+	{ 0x0156, 0x000c }, { 0x0157, 0x0000 }, { 0x0158, 0x002b }, { 0x0159, 0x0084 },
+	{ 0x015a, 0x0015 }, { 0x015b, 0x000f }, { 0x015c, 0x0000 }, { 0x015d, 0x0000 },
+	{ 0x015e, 0x0000 }, { 0x015f, 0x0000 }, { 0x0160, 0x0000 }, { 0x0161, 0x0000 },
+	{ 0x0162, 0x0000 }, { 0x0163, 0x0000 }, { 0x0164, 0x0000 }, { 0x0165, 0x0000 },
+	{ 0x0166, 0x0000 }, { 0x0167, 0x0000 }, { 0x0168, 0x0000 }, { 0x0169, 0x0000 },
+	{ 0x016a, 0x0000 }, { 0x016b, 0x0000 }, { 0x016c, 0x0000 }, { 0x016d, 0x0000 },
+	{ 0x0170, 0x0000 }, { 0x0171, 0x0077 }, { 0x0172, 0x0077 }, { 0x0173, 0x0077 },
+	{ 0x0174, 0x0077 }, { 0x0175, 0x0000 }, { 0x0176, 0x0003 }, { 0x0177, 0x0037 },
+	{ 0x0178, 0x0003 }, { 0x0179, 0x0000 }, { 0x017a, 0x0021 }, { 0x017b, 0x0002 },
+	{ 0x017c, 0x0000 }, { 0x017d, 0x00aa }, { 0x017e, 0x0000 }, { 0x017f, 0x00aa },
+	{ 0x0180, 0x0000 }, { 0x0190, 0x0000 }, { 0x0191, 0x0077 }, { 0x0192, 0x0077 },
+	{ 0x0193, 0x0077 }, { 0x0194, 0x0077 }, { 0x0195, 0x0000 }, { 0x0196, 0x0003 },
+	{ 0x0197, 0x0037 }, { 0x0198, 0x0003 }, { 0x0199, 0x0000 }, { 0x019a, 0x0021 },
+	{ 0x019b, 0x0002 }, { 0x019c, 0x0000 }, { 0x019d, 0x00aa }, { 0x019e, 0x0000 },
+	{ 0x019f, 0x00aa }, { 0x01a0, 0x0000 }, { 0x01a1, 0x0002 }, { 0x01a2, 0x000f },
+	{ 0x01a3, 0x000f }, { 0x01a4, 0x0000 }, { 0x01a5, 0x0000 }, { 0x01a6, 0x0000 },
+	{ 0x01a7, 0x0002 }, { 0x01a8, 0x000f }, { 0x01a9, 0x000f }, { 0x01aa, 0x0000 },
+	{ 0x01ab, 0x0000 }, { 0x01ac, 0x0000 }, { 0x01ad, 0x0084 }, { 0x01ae, 0x0060 },
+	{ 0x01af, 0x0047 }, { 0x01b0, 0x0047 }, { 0x01b1, 0x0000 }, { 0x01b2, 0x0000 },
+	{ 0x01b3, 0x0000 }, { 0x01b4, 0x0000 }, { 0x01b5, 0x0000 }, { 0x01b6, 0x0000 },
+	{ 0x01b7, 0x0005 }, { 0x01b8, 0x0000 }, { 0x01b9, 0x0000 }, { 0x01ba, 0x0000 },
+	{ 0x01bb, 0x0000 }, { 0x01bc, 0x0000 }, { 0x01bd, 0x0000 }, { 0x01be, 0x0000 },
+	{ 0x01bf, 0x0000 }, { 0x01c0, 0x0000 }, { 0x01c1, 0x0000 }, { 0x01c2, 0x00a0 },
+	{ 0x01c3, 0x0000 }, { 0x01c4, 0x0000 }, { 0x01c5, 0x0000 }, { 0x01c6, 0x0000 },
+	{ 0x01c7, 0x0000 }, { 0x01c8, 0x0000 }, { 0x01c9, 0x0000 }, { 0x01ca, 0x0000 },
 };
-*/
 
 /* Extracted from MMIO dump of 6.30.223.141 */
 static u16 r2057_rev9_init[][2] = {
@@ -539,6 +627,10 @@ void r2057_upload_inittabs(struct b43_wldev *dev)
 		} else if (phy->radio_rev == 7) {
 			table = r2057_rev7_init[0];
 			size = ARRAY_SIZE(r2057_rev7_init);
+		} else if (phy->radio_rev == 8) {
+			/* BCM6362 single-die 2.4 GHz. */
+			table = r2057_rev8_init[0];
+			size = ARRAY_SIZE(r2057_rev8_init);
 		}
 		break;
 	case 9:
-- 
2.43.0



Il 18/05/2026 03:49, Alessio Ferri ha scritto:
> This series completes b43 support for the Broadcom N-PHY revision 8
> paired with radio 2057 revision 8. b43 already supports the surrounding
> PHY family - N-PHY rev 8 with radio 2057 rev 5 and rev 7 are handled,
> and rev 16 with radio 2057 rev 9 is handled - but the rev 8 + rev 8
> combination falls through four dispatcher gaps:
> 
>   - radio_2057.c, r2057_upload_inittabs(), case 8 lists radio_rev 5
>     and 7 only;
>   - radio_2057.c, r2057_get_chantabent_rev7(), case 8 lists radio_rev
>     5 only;
>   - tables_nphy.c, b43_nphy_get_ipa_gain_table(), case 8 lists
>     radio_rev 5 only;
>   - radio_2057.c carries r2057_rev8_init[] as a 54-entry stub commented
>     out with "TODO: Which devices should use it?".
> 
> Two further pieces of plumbing are needed to reach those dispatchers
> in the first place: d11 core revision 0x16 is missing from the b43
> bcma id table, and the corerev 22 / radio 2057 combination needs the
> 24-bit indirect radio access path that brcmsmac uses for the same
> silicon generation (see brcmsmac/phy/phy_cmn.c read_radio_reg() /
> write_radio_reg()).
> 
> The series:
> 
>   1/6  b43: add d11 core revision 0x16 to id table
>   2/6  b43: route d11 corerev 22 to 24-bit indirect radio access
>   3/6  b43: support radio 2057 rev 8
>   4/6  b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
>   5/6  b43: add channel info table for N-PHY r8 + radio 2057 r8
>   6/6  b43: add RF power offset for N-PHY r8 + radio 2057 r8
> 
> Patches are ordered so that each one fixes the next visible failure
> in bring-up: 1/6 makes b43 bind to the core, 2/6 lets phy versioning
> read coherent radio identifiers, 3/6 unblocks the boot-time radio
> calibration that otherwise stalls the PSM at microcode startup, and
> 4/6-6/6 fill the remaining 2.4 GHz dispatcher entries so
> b43_nphy_set_channel completes to the default channel and core_init
> proceeds past PHY init.
> 
> Tested on a D-Link DSL-3580L (Broadcom BCM6362 SoC, single-die 2.4 GHz
> N-PHY rev 8 + radio 2057 rev 8 in 2.4 GHz IPA mode). The chip is in
> service worldwide in xDSL CPE devices.
> 
> b43 is currently Orphan in MAINTAINERS. These patches do not add a
> new chip family or PHY infrastructure; they fill four explicit
> dispatcher gaps for a combination of an already-supported PHY and
> an already-supported radio.
> 
> Alessio Ferri (6):
>   b43: add d11 core revision 0x16 to id table
>   b43: route d11 corerev 22 to 24-bit indirect radio access
>   b43: support radio 2057 rev 8
>   b43: add IPA TX gain table for N-PHY r8 + radio 2057 r8
>   b43: add channel info table for N-PHY r8 + radio 2057 r8
>   b43: add RF power offset for N-PHY r8 + radio 2057 r8
> 
>  drivers/net/wireless/broadcom/b43/main.c      |  10 +-
>  .../net/wireless/broadcom/b43/radio_2057.c    | 230 ++++++++++++++++--
>  .../net/wireless/broadcom/b43/tables_nphy.c   |  58 +++++
>  3 files changed, 280 insertions(+), 18 deletions(-)
> 


^ permalink raw reply related

* [PATCH 6/6] b43: add RF power offset for N-PHY r8 + radio 2057 r8
From: Alessio Ferri @ 2026-05-18  1:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: b43-dev, kvalo, linux-kernel
In-Reply-To: <8c0a07d2-9ec9-43d6-bdf7-f625bbb4a38a@mythread.it>

Add the 2.4 GHz RF power offset table for N-PHY rev 8 paired with
radio 2057 rev 8 and wire it to the existing dispatcher.

b43_ntab_get_rf_pwr_offset_table() currently dispatches on phy->rev
== 17 (radio_rev 14) and phy->rev == 16 (radio_rev 9) for 2.4 GHz.
phy->rev == 8 falls through and the function logs:

    b43-phyX ERROR: No 2GHz RF power table available for this device

Add a phy->rev == 8 / radio_rev == 8 case returning the new table.

The values are sourced from the proprietary Broadcom wl driver's
nphy_papd_padgain_dlt_2g_2057rev5 array. Reusing the rev 5 values
is structurally appropriate: the IPA TX gain table added by the
preceding patch in this series shares the low 24 bits of every
entry with rev 5 - same gain step amplitudes, only the PAD-gain
selector byte differs. b43's pad_gain extraction in
b43_nphy_tx_pwr_ctl_init() reads bits 19..23 of the gain entry,
which sit in the shared low-24-bit range; the same gain index
therefore maps to the same physical PAD gain code on both
revisions and warrants the same per-index dB offset.

Note that b43_nphy_tx_gain_table_upload() currently has a "TODO:
Enable this once we have gains configured" early-return for
phy->rev >= 7. With that early-return in place, this table is
fetched (silencing the b43err that would otherwise abort PHY
init) but its values are not yet written to MMIO. Resolving the
TODO is a separate investigation outside the scope of this
series; the values supplied here are documented now so that, once
the upload path is enabled, the correct rev 8 offsets are
already in tree.

Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
---
 .../net/wireless/broadcom/b43/tables_nphy.c   | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/net/wireless/broadcom/b43/tables_nphy.c b/drivers/net/wireless/broadcom/b43/tables_nphy.c
index 84e8d718d..ecd660b9c 100644
--- a/drivers/net/wireless/broadcom/b43/tables_nphy.c
+++ b/drivers/net/wireless/broadcom/b43/tables_nphy.c
@@ -2923,6 +2923,21 @@ static const s16 b43_ntab_rf_pwr_offset_2057_rev9_5g[] = {
 	0,
 };
 
+/* Sourced from the rev 5 sibling: the rev 8 IPA TX gain table
+ * shares the low 24 bits of every entry with rev 5 (only the
+ * PAD-gain selector byte differs), so the same gain index maps to
+ * the same physical PAD gain code on both revisions.
+ */
+static const s16 b43_ntab_rf_pwr_offset_2057_rev8_2g[] = {
+	-109, -109, -82, -68, -58,
+	-50,  -44, -39, -35, -31,
+	-28,  -26, -23, -21, -19,
+	-17,  -16, -14, -13, -11,
+	-10,   -9,  -8,  -7,  -5,
+	 -5,   -4,  -3,  -2,  -1,
+	 -1,    0,
+};
+
 /* Extracted from MMIO dump of 6.30.223.248
  * Entries: 0, 26, 28, 29, 30, 31 were guessed
  */
@@ -3782,6 +3797,10 @@ const s16 *b43_ntab_get_rf_pwr_offset_table(struct b43_wldev *dev)
 			if (phy->radio_rev == 9)
 				return b43_ntab_rf_pwr_offset_2057_rev9_2g;
 			break;
+		case 8:
+			if (phy->radio_rev == 8)
+				return b43_ntab_rf_pwr_offset_2057_rev8_2g;
+			break;
 		}
 
 		b43err(dev->wl,
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 0/1] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: Devin Wittmayer @ 2026-05-18  6:38 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Felix Fietkau, Lorenzo Bianconi, linux-kernel,
	stable, Oscar Alfonso Diaz, fjhhz1997
In-Reply-To: <20260308164510.5927-1-fjhhz1997@gmail.com>

This is v2 of fjh1997's patch, carried over at his request after his
reply on morrownr/USB-WiFi#682. Compared to v1: the substantive
change is the list_is_singular() guard agreed on in the v1 review
thread, so the fallback only fires when the chanctx_list is
unambiguous. The surrounding else block is also collapsed into a
single else-if matching the shape d594cc6f2c58 used for the emulate
case, and the v1 local ctx variable plus inline comment are dropped
(the rationale lives here in the commit message instead).

On the hang reports against the previous attempts at this fix (Oscar
against v1 in his March 19 2026 lore reply, and Johannes's Dec 2025
v2 at 20251216111909.25076-2-johannes@sipsolutions.net, held back for
similar reasons), I reran the airgeddon evil-twin flow (hostapd AP +
monitor VIF on the same phy + aireplay-ng deauth from the monitor) on
three setups:

GMKtec NucBox K8 Plus (MT7922 PCIe, in-kernel mt7921e, kernel 7.0.5):
  Stock and patched: no hang on 2.4 GHz or 5 GHz. dmesg clean.

Pi 5 (Alfa AWUS036AXML USB, OOT mt76 carrying morrownr/mt76 commit
903b05918523 "mt7921: assert sniffer enable on chanctx change",
kernel 6.12.47):
  Patched: no hang on 2.4 GHz or 5 GHz. dmesg clean.

Kali Linux 2026.1 VM, kernel 6.19.14+kali-amd64 (matching Oscar's
reported environment: Kali, MT7921U via USB passthrough of the Alfa
AWUS036AXML to a KVM guest; airgeddon 11.61 installed; v2 mac80211
built in-VM, installed, and loaded as the OOT-tainted module):
  Patched: no hang on 2.4 GHz or 5 GHz. dmesg clean (0 errors,
  0-1 warnings). Slab delta under 2 MB per 30 s run.

Patched did not hang on any of the three setups; K8 Plus stock also
cleared the same flow on both bands (Pi 5 and the Kali VM were
tested patched only). The prior reports look environment-specific to
Oscar's rig rather than kernel-side. If Oscar sees a recurrence on
this v2 I will iterate with him on the thread.

Discussion: https://github.com/morrownr/USB-WiFi/issues/682

傅继晗 (1):
  wifi: mac80211: fix monitor mode frame capture for real chanctx drivers

 net/mac80211/tx.c | 4 ++++
 1 file changed, 4 insertions(+)

--
2.43.0

^ permalink raw reply

* [PATCH v2 1/1] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: Devin Wittmayer @ 2026-05-18  6:40 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Felix Fietkau, Lorenzo Bianconi, linux-kernel,
	stable, Oscar Alfonso Diaz, fjhhz1997, Devin Wittmayer
In-Reply-To: <20260518063853.96384-1-lucid_duck@justthetip.ca>

From: 傅继晗 <fjhhz1997@gmail.com>

Commit d594cc6f2c58 ("wifi: mac80211: restore non-chanctx injection
behaviour") restored the monitor injection fallback for drivers using
chanctx emulation but explicitly deferred the harder case of drivers
that transitioned to real chanctx ops. mt76 falls in that category
and still drops every injected frame when monitor coexists with
another interface.

When the monitor has no chanctx of its own and exactly one chanctx is
in flight, fall back to that one. Otherwise refuse: picking
arbitrarily across multiple chanctxs would inject onto an unrelated
channel.

Reran the airgeddon evil-twin flow (hostapd AP + coexisting monitor
VIF on the same phy + aireplay-ng deauth from the monitor) against
this patch on mt7921e PCIe and mt7921u USB, across both 2.4 GHz and
5 GHz, and again on a Kali Linux VM with MT7921U USB-passthrough as
the closest match to the original reporter's setup. None of those
reproduced the hang reported against the earlier attempt at the same
fix (<20251216111909.25076-2-johannes@sipsolutions.net>) or against
v1 on lore in March 2026.

Cc: stable@vger.kernel.org # 6.9+
Reported-by: Oscar Alfonso Diaz <oscar.alfonso.diaz@gmail.com>
Tested-by: Devin Wittmayer <lucid_duck@justthetip.ca>
Fixes: 0a44dfc07074 ("wifi: mac80211: simplify non-chanctx drivers")
Link: https://github.com/morrownr/USB-WiFi/issues/682
Signed-off-by: 傅继晗 <fjhhz1997@gmail.com>
Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
---
 net/mac80211/tx.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2402,6 +2402,10 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
 		chandef = &chanctx_conf->def;
 	else if (local->emulate_chanctx)
 		chandef = &local->hw.conf.chandef;
+	else if (list_is_singular(&local->chanctx_list))
+		chandef = &list_first_entry(&local->chanctx_list,
+					    struct ieee80211_chanctx,
+					    list)->conf.def;
 	else
 		goto fail_rcu;
 
-- 
2.54.0


^ permalink raw reply

* Re: [PATCH v2 1/1] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: Johannes Berg @ 2026-05-18  6:42 UTC (permalink / raw)
  To: Devin Wittmayer, linux-wireless
  Cc: Felix Fietkau, Lorenzo Bianconi, linux-kernel, stable,
	Oscar Alfonso Diaz, fjhhz1997
In-Reply-To: <20260518064025.96792-1-lucid_duck@justthetip.ca>

On Sun, 2026-05-17 at 23:40 -0700, Devin Wittmayer wrote:
> From: 傅继晗 <fjhhz1997@gmail.com>
> 
> Commit d594cc6f2c58 ("wifi: mac80211: restore non-chanctx injection
> behaviour") restored the monitor injection fallback for drivers using
> chanctx emulation but explicitly deferred the harder case of drivers
> that transitioned to real chanctx ops. mt76 falls in that category
> and still drops every injected frame when monitor coexists with
> another interface.
> 
> When the monitor has no chanctx of its own and exactly one chanctx is
> in flight, fall back to that one. Otherwise refuse: picking
> arbitrarily across multiple chanctxs would inject onto an unrelated
> channel.
> 
> Reran the airgeddon evil-twin flow (hostapd AP + coexisting monitor
> VIF on the same phy + aireplay-ng deauth from the monitor) against
> this patch on mt7921e PCIe and mt7921u USB, across both 2.4 GHz and
> 5 GHz, and again on a Kali Linux VM with MT7921U USB-passthrough as
> the closest match to the original reporter's setup. None of those
> reproduced the hang reported against the earlier attempt at the same
> fix (<20251216111909.25076-2-johannes@sipsolutions.net>) or against
> v1 on lore in March 2026.
> 
> Cc: stable@vger.kernel.org # 6.9+
> Reported-by: Oscar Alfonso Diaz <oscar.alfonso.diaz@gmail.com>
> Tested-by: Devin Wittmayer <lucid_duck@justthetip.ca>
> Fixes: 0a44dfc07074 ("wifi: mac80211: simplify non-chanctx drivers")
> Link: https://github.com/morrownr/USB-WiFi/issues/682
> Signed-off-by: 傅继晗 <fjhhz1997@gmail.com>
> Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
> ---
>  net/mac80211/tx.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -2402,6 +2402,10 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
>  		chandef = &chanctx_conf->def;
>  	else if (local->emulate_chanctx)
>  		chandef = &local->hw.conf.chandef;
> +	else if (list_is_singular(&local->chanctx_list))
> +		chandef = &list_first_entry(&local->chanctx_list,
> +					    struct ieee80211_chanctx,
> +					    list)->conf.def;


Quoting include/linux/rculist.h:

 * Where are list_empty_rcu() and list_first_entry_rcu()?
 *
 * They do not exist because they would lead to subtle race conditions:
 *
 * if (!list_empty_rcu(mylist)) {
 *      struct foo *bar = list_first_entry_rcu(mylist, struct foo, list_member);
 *      do_something(bar);
 * }
 *
 * The list might be non-empty when list_empty_rcu() checks it, but it
 * might have become empty by the time that list_first_entry_rcu() rereads
 * the ->next pointer, which would result in a SEGV.
 *
 * When not using RCU, it is OK for list_first_entry() to re-read that
 * pointer because both functions should be protected by some lock that
 * blocks writers.
 *
 * When using RCU, list_empty() uses READ_ONCE() to fetch the
 * RCU-protected ->next pointer and then compares it to the address of the
 * list head.  However, it neither dereferences this pointer nor provides
 * this pointer to its caller.  Thus, READ_ONCE() suffices (that is,
 * rcu_dereference() is not needed), which means that list_empty() can be
 * used anywhere you would want to use list_empty_rcu().  Just don't
 * expect anything useful to happen if you do a subsequent lockless
 * call to list_first_entry_rcu()!!!
 *
 * See list_first_or_null_rcu for an alternative.

johannes

^ permalink raw reply

* RE: [PATCH v3] wifi: rtw88: usb: fix memory leaks on USB write failures
From: Ping-Ke Shih @ 2026-05-18  7:10 UTC (permalink / raw)
  To: luka.gejak@linux.dev, Kalle Valo
  Cc: Sascha Hauer, linux-wireless@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org
In-Reply-To: <20260513181008.13470-1-luka.gejak@linux.dev>

> @@ -456,7 +457,13 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
>         tx_desc = (struct rtw_tx_desc *)skb_head->data;
>         qsel = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_QSEL);
> 
> -       rtw_usb_write_port(rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb);
> +       ret = rtw_usb_write_port(rtwdev, qsel, skb_head,
> +                                rtw_usb_write_port_tx_complete, txcb);

ERROR: code indent should use tabs where possible
#54: FILE: drivers/net/wireless/realtek/rtw88/usb.c:461:
+^I^I^I         rtw_usb_write_port_tx_complete, txcb);$

CHECK: Alignment should match open parenthesis
#54: FILE: drivers/net/wireless/realtek/rtw88/usb.c:461:
+	ret = rtw_usb_write_port(rtwdev, qsel, skb_head,
+			         rtw_usb_write_port_tx_complete, txcb);

Please correct them and resend v4. (You can take my acked-by in v3)

> +       if (ret) {
> +               ieee80211_purge_tx_queue(rtwdev->hw, &txcb->tx_ack_queue);
> +               kfree(txcb);
> +               return false;
> +       }
> 
>         return true;
>  }




^ permalink raw reply

* Re: [PATCH v2] wireless-regdb: Update regulatory rules for Sri Lanka (LK)
From: Ping-Ke Shih @ 2026-05-18  7:22 UTC (permalink / raw)
  To: Mohamed Aashif; +Cc: linux-wireless, wireless-regdb
In-Reply-To: <20260516100024.103241-1-maashif011@gmail.com>

Mohamed Aashif <maashif011@gmail.com> wrote:
>
> Update Sri Lanka regulatory domain based on the RTTE Type Approval
> Rules 2020 from the Telecommunications Regulatory Commission of
> Sri Lanka (TRC).
>
> Source: https://www.trc.gov.lk/content/files/licensing/RTTE_GAZETTE-English.pdf
>
> Key changes:
> - Change DFS region from FCC to ETSI (document references ETSI
>   standards EN 300 328 and EN 301 893 as the applicable radio
>   interface standards)
> - 2.4 GHz: expand to 2400-2483.5 MHz at 23 dBm
> - 5150-5250 MHz: 23 dBm with DFS

This range doesn't need DFS.
Otherwise, looks good to me.

> - 5250-5350 MHz: 20 dBm with DFS (no TPC, 3 dB reduction per EN 301 893)
> - 5470-5725 MHz: 27 dBm with DFS (no TPC, per EN 301 893)
> - 5725-5875 MHz: 24 dBm with DFS (per ETSI EN 302 502)
>
> Note: The TRC gazette conflicts internally by allowing 30 dBm for
> 5725-5875 MHz while citing EN 301 893 (which doesn't cover this band).
> Lacking TRC clarification, we conservatively default to the ETSI
> EN 302 502 limits (24 dBm).
>
> Signed-off-by: Mohamed Aashif <maashif011@gmail.com>

^ permalink raw reply

* [PATCH v6 00/16] firmware: qcom: Add OP-TEE PAS service support
From: Sumit Garg @ 2026-05-18  7:28 UTC (permalink / raw)
  To: andersson
  Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
	netdev, linux-wireless, ath12k, linux-remoteproc, konradybcio,
	robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo, lumag,
	abhinav.kumar, jesszhan0024, marijn.suijten, airlied, simona,
	vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
	andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
	mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
	jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
	amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
	linux-kernel, Sumit Garg

From: Sumit Garg <sumit.garg@oss.qualcomm.com>

Qcom platforms has the legacy of using non-standard SCM calls
splintered over the various kernel drivers. These SCM calls aren't
compliant with the standard SMC calling conventions which is a
prerequisite to enable migration to the FF-A specifications from Arm.

OP-TEE as an alternative trusted OS to Qualcomm TEE (QTEE) can't
support these non-standard SCM calls. And even for newer architectures
using S-EL2 with Hafnium support, QTEE won't be able to support SCM
calls either with FF-A requirements coming in. And with both OP-TEE
and QTEE drivers well integrated in the TEE subsystem, it makes further
sense to reuse the TEE bus client drivers infrastructure.

The added benefit of TEE bus infrastructure is that there is support
for discoverable/enumerable services. With that client drivers don't
have to manually invoke a special SCM call to know the service status.

So enable the generic Peripheral Authentication Service (PAS) provided
by the firmware. It acts as the common layer with different TZ
backends plugged in whether it's an SCM implementation or a proper
TEE bus based PAS service implementation.

The TEE PAS service ABI is designed to be extensible with additional API
as PTA_QCOM_PAS_CAPABILITIES. This allows to accommodate any future
extensions of the PAS service needed while still maintaining backwards
compatibility.

Currently OP-TEE support is being added to provide the backend PAS
service implementation which can be found as part of this PR [1].
This implementation has been tested on Kodiak/RB3Gen2 board with lemans
EVK board being the next target. In addition to that WIN/IPQ targets
planning to use OP-TEE will use this service too. Surely the backwards
compatibility is maintained and tested for SCM backend.

Note that kernel PAS service support while running in EL2 is at parity
among OP-TEE vs QTEE. Especially the media (venus/iris) support depends
on proper IOMMU support being worked out on the PAS client end.

Patch summary:
- Patch #1: adds Kodiak EL2 overlay since boot stack with TF-A/OP-TEE
  only allow UEFI and Linux to boot in EL2.
- Patch #2: adds generic PAS service.
- Patch #3: migrates SCM backend to generic PAS service.
- Patch #4: adds TEE/OP-TEE backend for generic PAS service.
- Patch #5-#14: migrates all client drivers to generic PAS service.
- Patch #15: drops legacy PAS SCM exported APIs.

The patch-set is based on v7.1-rc4 tag and can be found in git tree here
[2].

Merge strategy:

It is expected due to APIs dependency, the entire patch-set to go via
the Qcom tree. All other subsystem maintainers, it will be great if I
can get acks for the corresponding subsystem patches.

[1] https://github.com/OP-TEE/optee_os/pull/7721 (already merged)
[2] https://git.kernel.org/pub/scm/linux/kernel/git/sumit.garg/linux.git/log/?h=qcom-pas-v6

---
Changes in v6:
- Rebased to v7.1-rc4 tag.
- Patch #14: fixed ret error print.
- Add Kconfig descriptions for PAS symbols such that they are visible
  in menuconfig to update.

Changes in v5:
- Incorporated misc. comments from Mukesh.
- Split up patch #11 into 2 to add an independent commit for passing
  proper PAS ID to set_remote_state API.
- Picked up tags.

Changes in v4:
- Incorporate misc. comments on patch #4.
- Picked up an ack for patch #10.
- Clarify in cover letter about state of media support.

Changes in v3:
- Incorporated some style and misc. comments for patch #2, #3 and #4.
- Add QCOM_PAS Kconfig dependency for various subsystems.
- Switch from pseudo TA to proper TA invoke commands.

Changes in v2:
- Fixed kernel doc warnings.
- Polish commit message and comments for patch #2.
- Pass proper PAS ID in set_remote_state API for media firmware drivers.
- Added Maintainer entry and dropped MODULE_AUTHOR.

Mukesh Ojha (1):
  arm64: dts: qcom: kodiak: Add EL2 overlay

Sumit Garg (15):
  firmware: qcom: Add a generic PAS service
  firmware: qcom_scm: Migrate to generic PAS service
  firmware: qcom: Add a PAS TEE service
  remoteproc: qcom_q6v5_pas: Switch over to generic PAS TZ APIs
  remoteproc: qcom_q6v5_mss: Switch to generic PAS TZ APIs
  soc: qcom: mdtloader: Switch to generic PAS TZ APIs
  remoteproc: qcom_wcnss: Switch to generic PAS TZ APIs
  remoteproc: qcom: Select QCOM_PAS generic service
  drm/msm: Switch to generic PAS TZ APIs
  media: qcom: Switch to generic PAS TZ APIs
  media: qcom: Pass proper PAS ID to set_remote_state API
  net: ipa: Switch to generic PAS TZ APIs
  wifi: ath12k: Switch to generic PAS TZ APIs
  firmware: qcom_scm: Remove SCM PAS wrappers
  MAINTAINERS: Add maintainer entry for Qualcomm PAS TZ service

 MAINTAINERS                                   |   9 +
 arch/arm64/boot/dts/qcom/Makefile             |   2 +
 arch/arm64/boot/dts/qcom/kodiak-el2.dtso      |  35 ++
 drivers/firmware/qcom/Kconfig                 |  21 +-
 drivers/firmware/qcom/Makefile                |   2 +
 drivers/firmware/qcom/qcom_pas.c              | 291 +++++++++++
 drivers/firmware/qcom/qcom_pas.h              |  50 ++
 drivers/firmware/qcom/qcom_pas_tee.c          | 476 ++++++++++++++++++
 drivers/firmware/qcom/qcom_scm.c              | 302 ++++-------
 drivers/gpu/drm/msm/Kconfig                   |   1 +
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c         |   4 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c       |  11 +-
 drivers/media/platform/qcom/iris/Kconfig      |  25 +-
 .../media/platform/qcom/iris/iris_firmware.c  |   9 +-
 drivers/media/platform/qcom/venus/Kconfig     |   1 +
 drivers/media/platform/qcom/venus/firmware.c  |  11 +-
 drivers/net/ipa/Kconfig                       |   2 +-
 drivers/net/ipa/ipa_main.c                    |  13 +-
 drivers/net/wireless/ath/ath12k/Kconfig       |   2 +-
 drivers/net/wireless/ath/ath12k/ahb.c         |  10 +-
 drivers/remoteproc/Kconfig                    |   4 +-
 drivers/remoteproc/qcom_q6v5_mss.c            |   5 +-
 drivers/remoteproc/qcom_q6v5_pas.c            |  51 +-
 drivers/remoteproc/qcom_wcnss.c               |  12 +-
 drivers/soc/qcom/mdt_loader.c                 |  12 +-
 include/linux/firmware/qcom/qcom_pas.h        |  43 ++
 include/linux/firmware/qcom/qcom_scm.h        |  29 --
 include/linux/soc/qcom/mdt_loader.h           |   6 +-
 28 files changed, 1119 insertions(+), 320 deletions(-)
 create mode 100644 arch/arm64/boot/dts/qcom/kodiak-el2.dtso
 create mode 100644 drivers/firmware/qcom/qcom_pas.c
 create mode 100644 drivers/firmware/qcom/qcom_pas.h
 create mode 100644 drivers/firmware/qcom/qcom_pas_tee.c
 create mode 100644 include/linux/firmware/qcom/qcom_pas.h

-- 
2.51.0


^ permalink raw reply

* [PATCH v6 01/16] arm64: dts: qcom: kodiak: Add EL2 overlay
From: Sumit Garg @ 2026-05-18  7:28 UTC (permalink / raw)
  To: andersson
  Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
	netdev, linux-wireless, ath12k, linux-remoteproc, konradybcio,
	robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo, lumag,
	abhinav.kumar, jesszhan0024, marijn.suijten, airlied, simona,
	vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
	andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
	mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
	jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
	amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
	linux-kernel, Sumit Garg
In-Reply-To: <20260518072856.22790-1-sumit.garg@kernel.org>

From: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>

All the existing variants Kodiak boards are using Gunyah hypervisor
which means that, so far, Linux-based OS could only boot in EL1 on those
devices.  However, it is possible for us to boot Linux at EL2 on these
devices [1].

When running under Gunyah, the remote processor firmware IOMMU
streams are controlled by Gunyah. However, without Gunyah, the IOMMU is
managed by the consumer of this DeviceTree. Therefore, describe the
firmware streams for each remote processor.

Add a EL2-specific DT overlay and apply it to Kodiak IOT variant
devices to create -el2.dtb for each of them alongside "normal" dtb.

[1]
https://docs.qualcomm.com/bundle/publicresource/topics/80-70020-4/boot-developer-touchpoints.html#uefi

Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
[SG: watchdog fixup]
Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/Makefile        |  2 ++
 arch/arm64/boot/dts/qcom/kodiak-el2.dtso | 35 ++++++++++++++++++++++++
 2 files changed, 37 insertions(+)
 create mode 100644 arch/arm64/boot/dts/qcom/kodiak-el2.dtso

diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 4ba8e7306419..28123cdc9de2 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -170,6 +170,8 @@ qcs615-ride-el2-dtbs := qcs615-ride.dtb talos-el2.dtbo
 dtb-$(CONFIG_ARCH_QCOM)	+= qcs615-ride-el2.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= qcs6490-radxa-dragon-q6a.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= qcs6490-rb3gen2.dtb
+qcs6490-rb3gen2-el2-dtbs := qcs6490-rb3gen2.dtb kodiak-el2.dtbo
+dtb-$(CONFIG_ARCH_QCOM)	+= qcs6490-rb3gen2-el2.dtb
 
 qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo
 qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo
diff --git a/arch/arm64/boot/dts/qcom/kodiak-el2.dtso b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso
new file mode 100644
index 000000000000..0b3a69a0d765
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * Kodiak specific modifications required to boot in EL2.
+ */
+
+
+/dts-v1/;
+/plugin/;
+
+&gpu_zap_shader {
+	status = "disabled";
+};
+
+&remoteproc_adsp {
+	iommus = <&apps_smmu 0x1800 0x0>;
+};
+
+&remoteproc_cdsp {
+	iommus = <&apps_smmu 0x11a0 0x0400>;
+};
+
+&remoteproc_wpss {
+	iommus = <&apps_smmu 0x1c03 0x1>,
+		 <&apps_smmu 0x1c83 0x1>;
+};
+
+&venus {
+	status = "disabled";
+};
+
+&watchdog {
+	status = "okay";
+};
-- 
2.51.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox