]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
ath10k: Enable MSA region dump support for WCN3990
authorGovind Singh <govinds@codeaurora.org>
Wed, 18 Sep 2019 13:27:49 +0000 (16:27 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Sat, 21 Sep 2019 06:48:16 +0000 (09:48 +0300)
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>
drivers/net/wireless/ath/ath10k/coredump.c
drivers/net/wireless/ath/ath10k/coredump.h
drivers/net/wireless/ath/ath10k/qmi.c
drivers/net/wireless/ath/ath10k/snoc.c
drivers/net/wireless/ath/ath10k/snoc.h

index b6d2932383cf654737a2492ca9fa920ba68a5fa3..de0926c61ee72181c8cf5cf07639509761321046 100644 (file)
@@ -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)
index 09de41922f97060f9615bf81f0344bb338bd7e62..8bf03e8c1d3abc1ef07594947a661b3f14aa1cb6 100644 (file)
@@ -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
index 59e15c946db89cc33f74a514c5423bd81e7986c7..fbc2e4ffc12b5e92742949e8e6d5aacca862ac72 100644 (file)
@@ -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");
 }
index c8c92906a178044ccd47654cf9f9bb6e8e97cb4f..cd22c8654aa9c55ab75faf923a4512c011157e92 100644 (file)
@@ -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,
index bc2b925b1d5a6ae76d00c86158ad48d4aeca23ef..c05df45a394574511a990bb385a3ab3f079d1be8 100644 (file)
@@ -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_ */