Commit 876eb848 authored by Baochen Qiang's avatar Baochen Qiang Committed by Kalle Valo
Browse files

wifi: ath11k: implement SRAM dump debugfs interface



On-board SRAM contains valuable information for firmware debugging so
add a new file named "sram" to debugfs with which we can dump SRAM
content using following the following:

cp /sys/kernel/debug/ath11k/wcn6855\ hw2.0/sram /tmp/sram

Currently this feature is enabled for QCA6390 and WCN6855.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: default avatarBaochen Qiang <quic_bqiang@quicinc.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220802075533.1744-3-quic_bqiang@quicinc.com
parent 90aad48e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -691,6 +691,7 @@ static const struct ath11k_hif_ops ath11k_ahb_hif_ops_ipq8074 = {
	.stop = ath11k_ahb_stop,
	.read32 = ath11k_ahb_read32,
	.write32 = ath11k_ahb_write32,
	.read = NULL,
	.irq_enable = ath11k_ahb_ext_irq_enable,
	.irq_disable = ath11k_ahb_ext_irq_disable,
	.map_service_to_pipe = ath11k_ahb_map_service_to_pipe,
@@ -703,6 +704,7 @@ static const struct ath11k_hif_ops ath11k_ahb_hif_ops_wcn6750 = {
	.stop = ath11k_pcic_stop,
	.read32 = ath11k_pcic_read32,
	.write32 = ath11k_pcic_write32,
	.read = NULL,
	.irq_enable = ath11k_pcic_ext_irq_enable,
	.irq_disable = ath11k_pcic_ext_irq_disable,
	.get_msi_address =  ath11k_pcic_get_msi_address,
+23 −0
Original line number Diff line number Diff line
@@ -108,6 +108,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.fixed_fw_mem = false,
		.support_off_channel_tx = false,
		.supports_multi_bssid = false,

		.sram_dump = {},
	},
	{
		.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -181,6 +183,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.fixed_fw_mem = false,
		.support_off_channel_tx = false,
		.supports_multi_bssid = false,

		.sram_dump = {},
	},
	{
		.name = "qca6390 hw2.0",
@@ -253,6 +257,11 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.fixed_fw_mem = false,
		.support_off_channel_tx = true,
		.supports_multi_bssid = true,

		.sram_dump = {
			.start = 0x01400000,
			.end = 0x0171ffff,
		},
	},
	{
		.name = "qcn9074 hw1.0",
@@ -325,6 +334,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.fixed_fw_mem = false,
		.support_off_channel_tx = false,
		.supports_multi_bssid = false,

		.sram_dump = {},
	},
	{
		.name = "wcn6855 hw2.0",
@@ -397,6 +408,11 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.fixed_fw_mem = false,
		.support_off_channel_tx = true,
		.supports_multi_bssid = true,

		.sram_dump = {
			.start = 0x01400000,
			.end = 0x0177ffff,
		},
	},
	{
		.name = "wcn6855 hw2.1",
@@ -468,6 +484,11 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.fixed_fw_mem = false,
		.support_off_channel_tx = true,
		.supports_multi_bssid = true,

		.sram_dump = {
			.start = 0x01400000,
			.end = 0x0177ffff,
		},
	},
	{
		.name = "wcn6750 hw1.0",
@@ -539,6 +560,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.fixed_fw_mem = true,
		.support_off_channel_tx = true,
		.supports_multi_bssid = true,

		.sram_dump = {},
	},
};

+62 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include "dp_tx.h"
#include "debugfs_htt_stats.h"
#include "peer.h"
#include "hif.h"

static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
	"REO2SW1_RING",
@@ -982,6 +983,63 @@ static const struct file_operations fops_fw_dbglog = {
	.llseek = default_llseek,
};

static int ath11k_open_sram_dump(struct inode *inode, struct file *file)
{
	struct ath11k_base *ab = inode->i_private;
	u8 *buf;
	u32 start, end;
	int ret;

	start = ab->hw_params.sram_dump.start;
	end = ab->hw_params.sram_dump.end;

	buf = vmalloc(end - start + 1);
	if (!buf)
		return -ENOMEM;

	ret = ath11k_hif_read(ab, buf, start, end);
	if (ret) {
		ath11k_warn(ab, "failed to dump sram: %d\n", ret);
		vfree(buf);
		return ret;
	}

	file->private_data = buf;
	return 0;
}

static ssize_t ath11k_read_sram_dump(struct file *file,
				     char __user *user_buf,
				     size_t count, loff_t *ppos)
{
	struct ath11k_base *ab = file->f_inode->i_private;
	const char *buf = file->private_data;
	int len;
	u32 start, end;

	start = ab->hw_params.sram_dump.start;
	end = ab->hw_params.sram_dump.end;
	len = end - start + 1;

	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}

static int ath11k_release_sram_dump(struct inode *inode, struct file *file)
{
	vfree(file->private_data);
	file->private_data = NULL;

	return 0;
}

static const struct file_operations fops_sram_dump = {
	.open = ath11k_open_sram_dump,
	.read = ath11k_read_sram_dump,
	.release = ath11k_release_sram_dump,
	.owner = THIS_MODULE,
	.llseek = default_llseek,
};

int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
{
	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
@@ -997,6 +1055,10 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
	debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
			    &fops_soc_dp_stats);

	if (ab->hw_params.sram_dump.start != 0)
		debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
				    &fops_sram_dump);

	return 0;
}

+11 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
struct ath11k_hif_ops {
	u32 (*read32)(struct ath11k_base *sc, u32 address);
	void (*write32)(struct ath11k_base *sc, u32 address, u32 data);
	int (*read)(struct ath11k_base *ab, void *buf, u32 start, u32 end);
	void (*irq_enable)(struct ath11k_base *sc);
	void (*irq_disable)(struct ath11k_base *sc);
	int (*start)(struct ath11k_base *sc);
@@ -99,6 +100,15 @@ static inline void ath11k_hif_write32(struct ath11k_base *sc, u32 address, u32 d
	sc->hif.ops->write32(sc, address, data);
}

static inline int ath11k_hif_read(struct ath11k_base *ab, void *buf,
				  u32 start, u32 end)
{
	if (!ab->hif.ops->read)
		return -EOPNOTSUPP;

	return ab->hif.ops->read(ab, buf, start, end);
}

static inline int ath11k_hif_map_service_to_pipe(struct ath11k_base *sc, u16 service_id,
						 u8 *ul_pipe, u8 *dl_pipe)
{
@@ -134,4 +144,5 @@ static inline void ath11k_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id,
	else
		*msi_data_idx = ce_id;
}

#endif /* _HIF_H_ */
+6 −0
Original line number Diff line number Diff line
@@ -202,6 +202,11 @@ struct ath11k_hw_params {
	bool fixed_fw_mem;
	bool support_off_channel_tx;
	bool supports_multi_bssid;

	struct {
		u32 start;
		u32 end;
	} sram_dump;
};

struct ath11k_hw_ops {
@@ -399,4 +404,5 @@ static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type)
}

extern const struct cfg80211_sar_capa ath11k_hw_sar_capa_wcn6855;

#endif
Loading