Skip to content

Commit

Permalink
ath10k: Enable MSA region dump support for WCN3990
Browse files Browse the repository at this point in the history
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: Govind Singh <govinds@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  • Loading branch information
Govind Singh authored and Kalle Valo committed Sep 21, 2019
1 parent 75f545e commit 3f14b73
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 0 deletions.
21 changes: 21 additions & 0 deletions drivers/net/wireless/ath/ath10k/coredump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath10k/coredump.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/wireless/ath/ath10k/qmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
66 changes: 66 additions & 0 deletions drivers/net/wireless/ath/ath10k/snoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/regulator/consumer.h>

#include "ce.h"
#include "coredump.h"
#include "debug.h"
#include "hif.h"
#include "htc.h"
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath10k/snoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */

0 comments on commit 3f14b73

Please sign in to comment.