mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-24 21:02:35 +00:00
216 lines
7.4 KiB
Diff
216 lines
7.4 KiB
Diff
From b3213496ab8688c6ef6f92be1dce0d1ed32ca9e3 Mon Sep 17 00:00:00 2001
|
|
From: Ramya Gnanasekar <rgnanase@codeaurora.org>
|
|
Date: Thu, 9 Jul 2020 10:48:15 +0530
|
|
Subject: [PATCH] ath11k: add support to collect q6mem dump
|
|
|
|
q6mem dump is not collected when fw crashes due to system restart.
|
|
Implemented a knob in debugfs to enable/disable fw recovery from
|
|
qsdk to collect q6mem dump .
|
|
|
|
root@OpenWrt:~# echo 1 > /sys/kernel/debug/ath11k/ipq6018_2/set_fw_recovery
|
|
root@OpenWrt:~# cat /sys/kernel/debug/ath11k/ipq6018_2/set_fw_recovery
|
|
1
|
|
|
|
Signed-off-by: Ramya Gnanasekar <rgnanase@codeaurora.org>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/core.c | 3 ++-
|
|
drivers/net/wireless/ath/ath11k/core.h | 1 +
|
|
drivers/net/wireless/ath/ath11k/debug.c | 46 +++++++++++++++++++++++++++++++++
|
|
3 files changed, 49 insertions(+), 1 deletion(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
|
@@ -693,7 +693,8 @@ int ath11k_core_ssr_notifier_cb(struct n
|
|
/* TODO Add more driver stats */
|
|
|
|
/* Crash the system once all the stats are dumped */
|
|
- BUG_ON(1);
|
|
+ if(!qmi->ab->fw_recovery_support)
|
|
+ BUG_ON(1);
|
|
|
|
return 0;
|
|
}
|
|
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -831,6 +831,7 @@ struct ath11k_base {
|
|
u32 num_db_cap;
|
|
u32 sw_pdev_id_map[MAX_RADIOS];
|
|
u32 hw_pdev_id_map[MAX_RADIOS];
|
|
+ bool fw_recovery_support;
|
|
/* must be last */
|
|
u8 drv_priv[0] __aligned(sizeof(void *));
|
|
};
|
|
@@ -990,6 +991,7 @@ void ath11k_core_free_bdf(struct ath11k_
|
|
|
|
void ath11k_core_halt(struct ath11k *ar);
|
|
|
|
+void ath11k_core_dump_bp_stats(struct ath11k_base *ab);
|
|
void ath11k_coredump_qdss_dump(struct ath11k_base *ab,
|
|
struct ath11k_qmi_event_qdss_trace_save_data *event_data);
|
|
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
|
|
--- a/drivers/net/wireless/ath/ath11k/debug.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/debug.c
|
|
@@ -1207,6 +1207,48 @@ static const struct file_operations fops
|
|
.llseek = default_llseek,
|
|
};
|
|
|
|
+static ssize_t ath11k_debug_write_fw_recovery(struct file *file,
|
|
+ char __user *user_buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath11k_base *ab = file->private_data;
|
|
+ bool enable;
|
|
+ int ret;
|
|
+
|
|
+ if (kstrtobool_from_user(user_buf, count, &enable))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (enable == ab->fw_recovery_support) {
|
|
+ ret = count;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ ab->fw_recovery_support = enable;
|
|
+ ret = count;
|
|
+
|
|
+exit:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static ssize_t ath11k_debug_read_fw_recovery(struct file *file,
|
|
+ char __user *user_buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath11k_base *ab = file->private_data;
|
|
+ char buf[32];
|
|
+ size_t len;
|
|
+
|
|
+ len = scnprintf(buf, sizeof(buf), "%u\n", ab->fw_recovery_support);
|
|
+
|
|
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_fw_recovery = {
|
|
+ .read = ath11k_debug_read_fw_recovery,
|
|
+ .write = ath11k_debug_write_fw_recovery,
|
|
+ .open = simple_open,
|
|
+};
|
|
+
|
|
int ath11k_debug_pdev_create(struct ath11k_base *ab)
|
|
{
|
|
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
|
|
@@ -1221,6 +1263,10 @@ int ath11k_debug_pdev_create(struct ath1
|
|
debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
|
|
&fops_soc_dp_stats);
|
|
|
|
+ debugfs_create_file("set_fw_recovery", 0600, ab->debugfs_soc, ab,
|
|
+ &fops_fw_recovery);
|
|
+
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/pci.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/pci.c
|
|
@@ -982,6 +982,8 @@ static int ath11k_pci_probe(struct pci_d
|
|
ab_pci->pdev = pdev;
|
|
ab->hif.ops = &ath11k_pci_hif_ops;
|
|
pci_set_drvdata(pdev, ab);
|
|
+ ab->fw_recovery_support = false;
|
|
+
|
|
spin_lock_init(&ab_pci->window_lock);
|
|
|
|
switch (pci_dev->device) {
|
|
--- a/drivers/net/wireless/ath/ath11k/coredump.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/coredump.c
|
|
@@ -162,13 +162,16 @@ void ath11k_coredump_download_rddm(struc
|
|
fw_img = mhi_ctrl->fbc_image;
|
|
|
|
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
|
- if (ab->qmi.target_mem[i].type == HOST_DDR_REGION_TYPE)
|
|
+ if (ab->qmi.target_mem[i].type == HOST_DDR_REGION_TYPE ||
|
|
+ ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE ||
|
|
+ ab->qmi.target_mem[i].type == M3_DUMP_REGION_TYPE)
|
|
rem_seg_cnt++;
|
|
}
|
|
|
|
num_seg = fw_img->entries + rddm_img->entries + rem_seg_cnt;
|
|
if (ab->is_qdss_tracing)
|
|
num_seg += qdss_seg_cnt;
|
|
+
|
|
len = num_seg * sizeof(*segment);
|
|
|
|
seg_info = segment = (struct ath11k_dump_segment *)vzalloc(len);
|
|
@@ -195,31 +198,46 @@ void ath11k_coredump_download_rddm(struc
|
|
ath11k_info(ab, "seg vaddr is %px len is 0x%x type %d\n",
|
|
seg_info->vaddr, seg_info->len, seg_info->type);
|
|
seg_info->type = ATH11K_FW_CRASH_RDDM_DATA;
|
|
+ ath11k_info(ab, "seg vaddr is %px len is 0x%x type %d\n",
|
|
+ seg_info->vaddr, seg_info->len, seg_info->type);
|
|
seg_info++;
|
|
}
|
|
|
|
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
|
- if (ab->qmi.target_mem[i].type != HOST_DDR_REGION_TYPE)
|
|
- continue;
|
|
- seg_info->len = ab->qmi.target_mem[i].size;
|
|
- seg_info->addr = ab->qmi.target_mem[i].paddr;
|
|
- seg_info->vaddr = ab->qmi.target_mem[i].vaddr;
|
|
- ath11k_info(ab, "seg vaddr is %px len is 0x%x type %d\n",
|
|
- seg_info->vaddr, seg_info->len, seg_info->type);
|
|
- seg_info->type = ATH11K_FW_REMOTE_MEM_DATA;
|
|
- seg_info++;
|
|
+ if (ab->qmi.target_mem[i].type == HOST_DDR_REGION_TYPE ||
|
|
+ ab->qmi.target_mem[i].type == M3_DUMP_REGION_TYPE) {
|
|
+ seg_info->len = ab->qmi.target_mem[i].size;
|
|
+ seg_info->addr = ab->qmi.target_mem[i].paddr;
|
|
+ seg_info->vaddr = ab->qmi.target_mem[i].vaddr;
|
|
+ seg_info->type = ATH11K_FW_REMOTE_MEM_DATA;
|
|
+ ath11k_info(ab, "seg vaddr is %px len is 0x%x type %d\n",
|
|
+ seg_info->vaddr, seg_info->len, seg_info->type);
|
|
+ seg_info++;
|
|
+ }
|
|
}
|
|
|
|
if (ab->is_qdss_tracing) {
|
|
seg_info->len = ab->qmi.qdss_mem[0].size;
|
|
seg_info->addr = ab->qmi.qdss_mem[0].paddr;
|
|
seg_info->vaddr = ab->qmi.qdss_mem[0].vaddr;
|
|
- ath11k_dbg(ab, ATH11K_DBG_QMI, "seg vaddr is %px len is 0x%x type %d\n",
|
|
- seg_info->vaddr, seg_info->len, seg_info->type);
|
|
- seg_info->type = ATH11K_FW_QDSS_DATA;
|
|
+ seg_info->type = ATH11K_FW_REMOTE_MEM_DATA;
|
|
+ ath11k_info(ab, "seg vaddr is %px len is 0x%x type %d\n",
|
|
+ seg_info->vaddr, seg_info->len, seg_info->type);
|
|
seg_info++;
|
|
}
|
|
|
|
+ for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
|
+ if (ab->qmi.target_mem[i].type == CALDB_MEM_REGION_TYPE) {
|
|
+ seg_info->len = ab->qmi.target_mem[i].size;
|
|
+ seg_info->addr = ab->qmi.target_mem[i].paddr;
|
|
+ seg_info->vaddr = ab->qmi.target_mem[i].vaddr;
|
|
+ seg_info->type = ATH11K_FW_REMOTE_MEM_DATA;
|
|
+ ath11k_info(ab, "seg vaddr is %px len is 0x%x type %d\n",
|
|
+ seg_info->vaddr, seg_info->len, seg_info->type);
|
|
+ seg_info++;
|
|
+ }
|
|
+ }
|
|
+
|
|
/* Crash the system once all the stats are dumped */
|
|
if(!ab->fw_recovery_support) {
|
|
ath11k_core_dump_bp_stats(ab);
|
|
--- a/drivers/net/wireless/ath/ath11k/qmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
|
|
@@ -2413,6 +2413,10 @@ static int ath11k_qmi_assign_target_mem_
|
|
ab->qmi.target_mem[idx].paddr = ab->hw_params.m3_addr;
|
|
else
|
|
ab->qmi.target_mem[idx].paddr = (phys_addr_t)addr;
|
|
+
|
|
+ ab->qmi.target_mem[idx].vaddr =
|
|
+ ioremap(ab->qmi.target_mem[idx].paddr,
|
|
+ ab->qmi.target_mem[i].size);
|
|
idx++;
|
|
break;
|
|
default:
|