Commit 3f14b73c authored by Govind Singh's avatar Govind Singh Committed by Kalle Valo
Browse files

ath10k: Enable MSA region dump support for WCN3990



MSA memory region caries the hw descriptors information.
Dump MSA region in core dump as this is very helpful in debugging
hw issues.

Testing: Tested on WCN3990 HW
Tested FW: WLAN.HL.3.1-00959-QCAHLSWMTPLZ-1

Signed-off-by: default avatarGovind Singh <govinds@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 75f545e8
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -951,6 +951,19 @@ static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
	},
};

static const struct ath10k_mem_region wcn399x_hw10_mem_regions[] = {
	{
		/* MSA region start is not fixed, hence it is assigned at runtime */
		.type = ATH10K_MEM_REGION_TYPE_MSA,
		.len = 0x100000,
		.name = "DRAM",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
};

static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
	{
		.hw_id = QCA6174_HW_1_0_VERSION,
@@ -1048,6 +1061,14 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
			.size = ARRAY_SIZE(qca4019_hw10_mem_regions),
		},
	},
	{
		.hw_id = WCN3990_HW_1_0_DEV_VERSION,
		.hw_rev = ATH10K_HW_WCN3990,
		.region_table = {
			.regions = wcn399x_hw10_mem_regions,
			.size = ARRAY_SIZE(wcn399x_hw10_mem_regions),
		},
	},
};

static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
+1 −0
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ enum ath10k_mem_region_type {
	ATH10K_MEM_REGION_TYPE_IRAM2	= 5,
	ATH10K_MEM_REGION_TYPE_IOSRAM	= 6,
	ATH10K_MEM_REGION_TYPE_IOREG	= 7,
	ATH10K_MEM_REGION_TYPE_MSA	= 8,
};

/* Define a section of the region which should be copied. As not all parts
+4 −0
Original line number Diff line number Diff line
@@ -829,9 +829,13 @@ ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
{
	struct ath10k *ar = qmi->ar;
	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);

	ath10k_qmi_remove_msa_permission(qmi);
	ath10k_core_free_board_files(ar);
	if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags))
		ath10k_snoc_fw_crashed_dump(ar);

	ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);
	ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service disconnected\n");
}
+66 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/regulator/consumer.h>

#include "ce.h"
#include "coredump.h"
#include "debug.h"
#include "hif.h"
#include "htc.h"
@@ -1389,6 +1390,71 @@ static int ath10k_hw_power_off(struct ath10k *ar)
	return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
}

static void ath10k_msa_dump_memory(struct ath10k *ar,
				   struct ath10k_fw_crash_data *crash_data)
{
	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
	const struct ath10k_hw_mem_layout *mem_layout;
	const struct ath10k_mem_region *current_region;
	struct ath10k_dump_ram_data_hdr *hdr;
	size_t buf_len;
	u8 *buf;

	if (!crash_data && !crash_data->ramdump_buf)
		return;

	mem_layout = ath10k_coredump_get_mem_layout(ar);
	if (!mem_layout)
		return;

	current_region = &mem_layout->region_table.regions[0];

	buf = crash_data->ramdump_buf;
	buf_len = crash_data->ramdump_buf_len;
	memset(buf, 0, buf_len);

	/* Reserve space for the header. */
	hdr = (void *)buf;
	buf += sizeof(*hdr);
	buf_len -= sizeof(*hdr);

	hdr->region_type = cpu_to_le32(current_region->type);
	hdr->start = cpu_to_le32((unsigned long)ar_snoc->qmi->msa_va);
	hdr->length = cpu_to_le32(ar_snoc->qmi->msa_mem_size);

	if (current_region->len < ar_snoc->qmi->msa_mem_size) {
		memcpy(buf, ar_snoc->qmi->msa_va, current_region->len);
		ath10k_warn(ar, "msa dump length is less than msa size %x, %x\n",
			    current_region->len, ar_snoc->qmi->msa_mem_size);
	} else {
		memcpy(buf, ar_snoc->qmi->msa_va, ar_snoc->qmi->msa_mem_size);
	}
}

void ath10k_snoc_fw_crashed_dump(struct ath10k *ar)
{
	struct ath10k_fw_crash_data *crash_data;
	char guid[UUID_STRING_LEN + 1];

	mutex_lock(&ar->dump_mutex);

	spin_lock_bh(&ar->data_lock);
	ar->stats.fw_crash_counter++;
	spin_unlock_bh(&ar->data_lock);

	crash_data = ath10k_coredump_new(ar);

	if (crash_data)
		scnprintf(guid, sizeof(guid), "%pUl", &crash_data->guid);
	else
		scnprintf(guid, sizeof(guid), "n/a");

	ath10k_err(ar, "firmware crashed! (guid %s)\n", guid);
	ath10k_print_driver_info(ar);
	ath10k_msa_dump_memory(ar, crash_data);
	mutex_unlock(&ar->dump_mutex);
}

static const struct of_device_id ath10k_snoc_dt_match[] = {
	{ .compatible = "qcom,wcn3990-wifi",
	 .data = &drv_priv,
+1 −0
Original line number Diff line number Diff line
@@ -79,5 +79,6 @@ static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
}

int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type);
void ath10k_snoc_fw_crashed_dump(struct ath10k *ar);

#endif /* _SNOC_H_ */