Add support for devcoredump in the driver. This helps in capturing
the snapshot of DDR memory that firmware uses in the event of a
firmware assert which aids in firmware debug.
First patch in the series adds the coredump infrastructure to the
driver but no hardware support is included. Second one in the series
adds the support to capture MSA memory during firmware assert on
WCN6750.
Manikanta Pubbisetty (2):
wifi: ath11k: Add coredump support
wifi: ath11k: Add coredump support of MSA region for WCN6750
drivers/net/wireless/ath/ath11k/Kconfig | 1 +
drivers/net/wireless/ath/ath11k/Makefile | 1 +
drivers/net/wireless/ath/ath11k/ahb.c | 127 +++++++++++-
drivers/net/wireless/ath/ath11k/ahb.h | 8 +-
drivers/net/wireless/ath/ath11k/core.c | 18 +-
drivers/net/wireless/ath/ath11k/core.h | 19 +-
drivers/net/wireless/ath/ath11k/coredump.c | 225 +++++++++++++++++++++
drivers/net/wireless/ath/ath11k/coredump.h | 147 ++++++++++++++
8 files changed, 541 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/wireless/ath/ath11k/coredump.c
create mode 100644 drivers/net/wireless/ath/ath11k/coredump.h
base-commit: 610b78b97bad8f3e77c27a15e9a03cbbb4109697
--
2.17.1
In the context of WCN6750, MSA is a 12MB reserved memory region
entirely used by WCN6750 firmware for it's operation. This memory
carries useful information required to debug firmware/hardware
issues. Therefore add coredump support to dump MSA region during
firmware assert for WCN6750.
Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1
Signed-off-by: Manikanta Pubbisetty <[email protected]>
---
drivers/net/wireless/ath/ath11k/ahb.c | 127 ++++++++++++++++++++-
drivers/net/wireless/ath/ath11k/ahb.h | 8 +-
drivers/net/wireless/ath/ath11k/coredump.c | 18 ++-
3 files changed, 149 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 5cbba9a8b6ba..e404466ab049 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -18,6 +18,8 @@
#include "pcic.h"
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/smem_state.h>
+#include <linux/remoteproc/qcom_rproc.h>
+#include "coredump.h"
static const struct of_device_id ath11k_ahb_of_match[] = {
/* TODO: Should we change the compatible string to something similar
@@ -935,6 +937,114 @@ static int ath11k_ahb_setup_resources(struct ath11k_base *ab)
return 0;
}
+static void ath11k_ahb_coredump_msa(struct ath11k_base *ab)
+{
+ struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
+ const struct ath11k_hw_mem_layout *mem_layout;
+ struct ath11k_fw_crash_data *crash_data;
+ const struct ath11k_mem_region *current_region;
+ struct ath11k_ramdump_hdr *hdr;
+ size_t buf_len;
+ u8 *buf;
+
+ mutex_lock(&ab->dump_mutex);
+
+ crash_data = ath11k_coredump_new(ab);
+ if (!crash_data)
+ goto out_unlock;
+
+ if (!crash_data->ramdump_buf)
+ goto out_unlock;
+
+ mem_layout = ath11k_coredump_get_mem_layout(ab);
+ if (!mem_layout)
+ goto out_unlock;
+
+ 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_le64((u64)ab_ahb->fw.msa_vaddr);
+
+ if (current_region->len < ab_ahb->fw.msa_size) {
+ memcpy(buf, ab_ahb->fw.msa_vaddr, current_region->len);
+ hdr->length = cpu_to_le32(current_region->len);
+
+ ath11k_warn(ab, "msa dump length is less than msa size %x, %x\n",
+ current_region->len, ab_ahb->fw.msa_size);
+ } else {
+ memcpy(buf, ab_ahb->fw.msa_vaddr, ab_ahb->fw.msa_size);
+ hdr->length = cpu_to_le32(ab_ahb->fw.msa_size);
+ }
+
+out_unlock:
+ mutex_unlock(&ab->dump_mutex);
+}
+
+static int ath11k_ahb_ssr_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct ath11k_ahb *ab_ahb = container_of(nb, struct ath11k_ahb, nb);
+ struct ath11k_base *ab = ab_ahb->ab;
+ struct qcom_ssr_notify_data *notify_data = data;
+
+ switch (action) {
+ case QCOM_SSR_BEFORE_POWERUP:
+ break;
+ case QCOM_SSR_AFTER_POWERUP:
+ break;
+ case QCOM_SSR_BEFORE_SHUTDOWN:
+ if (notify_data->crashed)
+ ath11k_ahb_coredump_msa(ab);
+ break;
+ case QCOM_SSR_AFTER_SHUTDOWN:
+ break;
+ default:
+ ath11k_err(ab, "received unrecognized event %lu\n", action);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static int ath11k_ahb_register_ssr_notifier(struct ath11k_base *ab)
+{
+ struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
+ void *notifier;
+ int ret;
+
+ ab_ahb->nb.notifier_call = ath11k_ahb_ssr_notifier;
+
+ notifier = qcom_register_ssr_notifier("wpss", &ab_ahb->nb);
+ if (IS_ERR(notifier)) {
+ ret = PTR_ERR(notifier);
+ ath11k_err(ab, "failed to initialize SSR notifier: %d\n", ret);
+ return ret;
+ }
+
+ ab_ahb->notifier = notifier;
+
+ return 0;
+}
+
+static void ath11k_ahb_unregister_ssr_notifier(struct ath11k_base *ab)
+{
+ struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
+ int ret;
+
+ ret = qcom_unregister_ssr_notifier(ab_ahb->notifier, &ab_ahb->nb);
+ if (ret)
+ ath11k_err(ab, "error %d unregistering notifier\n", ret);
+}
+
static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab)
{
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
@@ -956,6 +1066,14 @@ static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab)
ab_ahb->fw.msa_paddr = r.start;
ab_ahb->fw.msa_size = resource_size(&r);
+ ab_ahb->fw.msa_vaddr = devm_memremap(dev, ab_ahb->fw.msa_paddr,
+ ab_ahb->fw.msa_size,
+ MEMREMAP_WB);
+ if (IS_ERR(ab_ahb->fw.msa_vaddr)) {
+ dev_err(dev, "failed to map memory region: %pa\n",
+ &r.start);
+ return PTR_ERR(ab_ahb->fw.msa_vaddr);
+ }
node = of_parse_phandle(dev->of_node, "memory-region", 1);
if (!node)
@@ -971,7 +1089,7 @@ static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab)
ab_ahb->fw.ce_paddr = r.start;
ab_ahb->fw.ce_size = resource_size(&r);
- return 0;
+ return ath11k_ahb_register_ssr_notifier(ab);
}
static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab)
@@ -1087,6 +1205,8 @@ static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
if (ab_ahb->fw.use_tz)
return 0;
+ ath11k_ahb_unregister_ssr_notifier(ab);
+
iommu = ab_ahb->fw.iommu_domain;
unmapped_size = iommu_unmap(iommu, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);
@@ -1110,6 +1230,7 @@ static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
static int ath11k_ahb_probe(struct platform_device *pdev)
{
struct ath11k_base *ab;
+ struct ath11k_ahb *ab_ahb;
const struct of_device_id *of_id;
const struct ath11k_hif_ops *hif_ops;
const struct ath11k_pci_ops *pci_ops;
@@ -1156,6 +1277,8 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
ab->pdev = pdev;
ab->hw_rev = hw_rev;
platform_set_drvdata(pdev, ab);
+ ab_ahb = ath11k_ahb_priv(ab);
+ ab_ahb->ab = ab;
ret = ath11k_pcic_register_pci_ops(ab, pci_ops);
if (ret) {
diff --git a/drivers/net/wireless/ath/ath11k/ahb.h b/drivers/net/wireless/ath/ath11k/ahb.h
index 415ddfd26654..812d5aa8e87c 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.h
+++ b/drivers/net/wireless/ath/ath11k/ahb.h
@@ -1,11 +1,12 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_AHB_H
#define ATH11K_AHB_H
+#include <linux/notifier.h>
#include "core.h"
#define ATH11K_AHB_RECOVERY_TIMEOUT (3 * HZ)
@@ -23,11 +24,13 @@ struct ath11k_base;
struct ath11k_ahb {
struct rproc *tgt_rproc;
+ struct ath11k_base *ab;
struct {
struct device *dev;
struct iommu_domain *iommu_domain;
dma_addr_t msa_paddr;
u32 msa_size;
+ void *msa_vaddr;
dma_addr_t ce_paddr;
u32 ce_size;
bool use_tz;
@@ -37,6 +40,9 @@ struct ath11k_ahb {
unsigned int smem_bit;
struct qcom_smem_state *smem_state;
} smp2p_info;
+
+ struct notifier_block nb;
+ void *notifier;
};
static inline struct ath11k_ahb *ath11k_ahb_priv(struct ath11k_base *ab)
diff --git a/drivers/net/wireless/ath/ath11k/coredump.c b/drivers/net/wireless/ath/ath11k/coredump.c
index 1e5a58ec673e..1253b07806f4 100644
--- a/drivers/net/wireless/ath/ath11k/coredump.c
+++ b/drivers/net/wireless/ath/ath11k/coredump.c
@@ -12,8 +12,24 @@
#include "coredump.h"
#include "debug.h"
+static const struct ath11k_mem_region wcn6750_hw10_mem_regions[] = {
+ {
+ /* MSA region start is not fixed, hence it is assigned at runtime */
+ .type = ATH11K_MEM_REGION_TYPE_MSA,
+ .len = 0xC00000,
+ .name = "MSA",
+ },
+};
+
static const struct ath11k_hw_mem_layout hw_mem_layouts[] = {
- /* HW memory layouts shall be defined here */
+ {
+ .hw_rev = ATH11K_HW_WCN6750_HW10,
+ .bus = ATH11K_BUS_AHB,
+ .region_table = {
+ .regions = wcn6750_hw10_mem_regions,
+ .size = ARRAY_SIZE(wcn6750_hw10_mem_regions),
+ },
+ }
};
const struct ath11k_hw_mem_layout *
--
2.17.1
In the event of firmware asserts, it is very useful to capture the
snapshot of the memory that firmware uses. This aids in debugging
firmware asserts. The snapshot of the DDR memory that firmware uses
can be dumped to user space by using kernel's devcoredump framework.
The design of coredump is taken from ath10k. The ABI looks more or
less similar to ath10k although some fields are removed/modified
to suite the design of ath11k.
coredump is disabled by default and can be controlled by a module
parameter called coredump_mask. Currently only RAMDUMPs are
supported and the interface can be easily extended in future.
RAMDUMPs can be enabled by using the following command:
modprobe ath11k coredump_mask=0x1
This patch adds the framework required to enable coredump in ath11k
but no hardware support is included. The next patch will add support
for WCN6750.
Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1
Signed-off-by: Manikanta Pubbisetty <[email protected]>
---
drivers/net/wireless/ath/ath11k/Kconfig | 1 +
drivers/net/wireless/ath/ath11k/Makefile | 1 +
drivers/net/wireless/ath/ath11k/core.c | 18 +-
drivers/net/wireless/ath/ath11k/core.h | 19 +-
drivers/net/wireless/ath/ath11k/coredump.c | 209 +++++++++++++++++++++
drivers/net/wireless/ath/ath11k/coredump.h | 147 +++++++++++++++
6 files changed, 393 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/wireless/ath/ath11k/coredump.c
create mode 100644 drivers/net/wireless/ath/ath11k/coredump.h
diff --git a/drivers/net/wireless/ath/ath11k/Kconfig b/drivers/net/wireless/ath/ath11k/Kconfig
index ad5cc6cac05b..96074f5edfd0 100644
--- a/drivers/net/wireless/ath/ath11k/Kconfig
+++ b/drivers/net/wireless/ath/ath11k/Kconfig
@@ -5,6 +5,7 @@ config ATH11K
depends on CRYPTO_MICHAEL_MIC
select ATH_COMMON
select QCOM_QMI_HELPERS
+ select WANT_DEV_COREDUMP
help
This module adds support for Qualcomm Technologies 802.11ax family of
chipsets.
diff --git a/drivers/net/wireless/ath/ath11k/Makefile b/drivers/net/wireless/ath/ath11k/Makefile
index cc47e0114595..44f8039453d5 100644
--- a/drivers/net/wireless/ath/ath11k/Makefile
+++ b/drivers/net/wireless/ath/ath11k/Makefile
@@ -25,6 +25,7 @@ ath11k-$(CONFIG_ATH11K_TRACING) += trace.o
ath11k-$(CONFIG_THERMAL) += thermal.o
ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o
ath11k-$(CONFIG_PM) += wow.o
+ath11k-$(CONFIG_DEV_COREDUMP) += coredump.o
obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o
ath11k_ahb-y += ahb.o
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index b1b90bd34d67..d666da5c746c 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -16,6 +16,7 @@
#include "debug.h"
#include "hif.h"
#include "wow.h"
+#include "coredump.h"
unsigned int ath11k_debug_mask;
EXPORT_SYMBOL(ath11k_debug_mask);
@@ -32,6 +33,10 @@ module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
MODULE_PARM_DESC(frame_mode,
"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
+unsigned long ath11k_coredump_mask;
+module_param_named(coredump_mask, ath11k_coredump_mask, ulong, 0444);
+MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
+
static const struct ath11k_hw_params ath11k_hw_params[] = {
{
.hw_rev = ATH11K_HW_IPQ8074,
@@ -1825,6 +1830,11 @@ static void ath11k_core_restart(struct work_struct *work)
struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);
int ret;
+ ret = ath11k_coredump_submit(ab);
+ if (ret)
+ ath11k_warn(ab, "failed to send firmware crash dump via devcoredump: %d",
+ ret);
+
ret = ath11k_core_reconfigure_on_crash(ab);
if (ret) {
ath11k_err(ab, "failed to reconfigure driver on crash recovery\n");
@@ -1956,6 +1966,10 @@ int ath11k_core_init(struct ath11k_base *ab)
return ret;
}
+ ret = ath11k_coredump_create(ab);
+ if (ret)
+ ath11k_warn(ab, "failed to create coredump memory: %d", ret);
+
return 0;
}
EXPORT_SYMBOL(ath11k_core_init);
@@ -1971,6 +1985,7 @@ void ath11k_core_deinit(struct ath11k_base *ab)
ath11k_hif_power_down(ab);
ath11k_mac_destroy(ab);
+ ath11k_coredump_destroy(ab);
ath11k_core_soc_destroy(ab);
}
EXPORT_SYMBOL(ath11k_core_deinit);
@@ -2005,6 +2020,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
mutex_init(&ab->core_lock);
mutex_init(&ab->tbl_mtx_lock);
+ mutex_init(&ab->dump_mutex);
spin_lock_init(&ab->base_lock);
mutex_init(&ab->vdev_id_11d_lock);
init_completion(&ab->reset_complete);
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 0830276e5028..82334bc0f514 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_CORE_H
@@ -52,6 +52,7 @@
#define ATH11K_SMBIOS_BDF_EXT_MAGIC "BDF_"
extern unsigned int ath11k_frame_mode;
+extern unsigned long ath11k_coredump_mask;
#define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ)
@@ -589,6 +590,14 @@ struct ath11k_per_peer_tx_stats {
#define ATH11K_FLUSH_TIMEOUT (5 * HZ)
#define ATH11K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ)
+/* used for crash-dump storage, protected by dump_lock */
+struct ath11k_fw_crash_data {
+ guid_t guid;
+ struct timespec64 timestamp;
+ u8 *ramdump_buf;
+ size_t ramdump_buf_len;
+};
+
struct ath11k {
struct ath11k_base *ab;
struct ath11k_pdev *pdev;
@@ -978,6 +987,14 @@ struct ath11k_base {
const struct ath11k_pci_ops *ops;
} pci;
+#ifdef CONFIG_DEV_COREDUMP
+ struct {
+ struct ath11k_fw_crash_data *fw_crash_data;
+ } coredump;
+#endif
+ /* protects coredump data */
+ struct mutex dump_mutex;
+
/* must be last */
u8 drv_priv[] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath11k/coredump.c b/drivers/net/wireless/ath/ath11k/coredump.c
new file mode 100644
index 000000000000..1e5a58ec673e
--- /dev/null
+++ b/drivers/net/wireless/ath/ath11k/coredump.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/*
+ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/devcoredump.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/utsname.h>
+
+#include "coredump.h"
+#include "debug.h"
+
+static const struct ath11k_hw_mem_layout hw_mem_layouts[] = {
+ /* HW memory layouts shall be defined here */
+};
+
+const struct ath11k_hw_mem_layout *
+ath11k_coredump_get_mem_layout(struct ath11k_base *ab)
+{
+ int i;
+
+ if (!test_bit(ATH11K_FW_CRASH_DUMP_RAM_DATA, &ath11k_coredump_mask))
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(hw_mem_layouts); i++) {
+ if (ab->hw_rev == hw_mem_layouts[i].hw_rev &&
+ hw_mem_layouts[i].bus == ab->hif.bus)
+ return &hw_mem_layouts[i];
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(ath11k_coredump_get_mem_layout);
+
+static u32 ath11k_coredump_get_ramdump_size(struct ath11k_base *ab)
+{
+ const struct ath11k_hw_mem_layout *hw;
+ const struct ath11k_mem_region *mem_region;
+ size_t size = 0;
+ int i;
+
+ hw = ath11k_coredump_get_mem_layout(ab);
+
+ if (!hw)
+ return 0;
+
+ mem_region = &hw->region_table.regions[0];
+
+ for (i = 0; i < hw->region_table.size; i++) {
+ size += mem_region->len;
+ mem_region++;
+ }
+
+ /* reserve space for the headers */
+ size += hw->region_table.size * sizeof(struct ath11k_ramdump_hdr);
+
+ /* make sure it is aligned 16 bytes for debug message print out */
+ size = ALIGN(size, 16);
+
+ return size;
+}
+
+struct ath11k_fw_crash_data *ath11k_coredump_new(struct ath11k_base *ab)
+{
+ struct ath11k_fw_crash_data *crash_data = ab->coredump.fw_crash_data;
+
+ lockdep_assert_held(&ab->dump_mutex);
+
+ if (ath11k_coredump_mask == 0 || !crash_data)
+ /* coredump disabled */
+ return NULL;
+
+ guid_gen(&crash_data->guid);
+ ktime_get_real_ts64(&crash_data->timestamp);
+
+ return crash_data;
+}
+EXPORT_SYMBOL(ath11k_coredump_new);
+
+static struct ath11k_dump_file_data *ath11k_coredump_build(struct ath11k_base *ab)
+{
+ struct ath11k_fw_crash_data *crash_data = ab->coredump.fw_crash_data;
+ struct ath11k_dump_file_data *dump_data;
+ struct ath11k_tlv_dump_data *dump_tlv;
+ size_t hdr_len = sizeof(*dump_data);
+ size_t len, sofar = 0;
+ unsigned char *buf;
+
+ len = hdr_len;
+
+ if (test_bit(ATH11K_FW_CRASH_DUMP_RAM_DATA, &ath11k_coredump_mask) &&
+ crash_data->ramdump_buf)
+ len += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
+
+ sofar += hdr_len;
+
+ buf = vzalloc(len);
+ if (!buf)
+ return NULL;
+
+ mutex_lock(&ab->dump_mutex);
+
+ dump_data = (struct ath11k_dump_file_data *)(buf);
+
+ strscpy(dump_data->df_magic, "ATH11K-FW-DUMP",
+ sizeof(dump_data->df_magic));
+ dump_data->len = cpu_to_le32(len);
+
+ guid_copy(&dump_data->guid, &crash_data->guid);
+
+ dump_data->version = cpu_to_le32(ATH11K_FW_CRASH_DUMP_VERSION);
+ dump_data->hw_rev = cpu_to_le32(ab->hw_params.hw_rev);
+ dump_data->bus_type = cpu_to_le32(ab->hif.bus);
+
+ strscpy(dump_data->fw_ver, ab->qmi.target.fw_build_id,
+ sizeof(ab->qmi.target.fw_build_id));
+
+ dump_data->kernel_ver_code = 0;
+ strscpy(dump_data->kernel_ver, init_utsname()->release,
+ sizeof(dump_data->kernel_ver));
+
+ dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
+ dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
+
+ if (test_bit(ATH11K_FW_CRASH_DUMP_RAM_DATA, &ath11k_coredump_mask) &&
+ crash_data->ramdump_buf) {
+ dump_tlv = (struct ath11k_tlv_dump_data *)(buf + sofar);
+ dump_tlv->type = cpu_to_le32(ATH11K_FW_CRASH_DUMP_RAM_DATA);
+ dump_tlv->tlv_len = cpu_to_le32(crash_data->ramdump_buf_len);
+ if (crash_data->ramdump_buf_len) {
+ memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
+ crash_data->ramdump_buf_len);
+ sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
+ }
+ }
+
+ mutex_unlock(&ab->dump_mutex);
+
+ return dump_data;
+}
+
+int ath11k_coredump_submit(struct ath11k_base *ab)
+{
+ struct ath11k_dump_file_data *dump;
+
+ if (ath11k_coredump_mask == 0 || !ab->coredump.fw_crash_data)
+ /* coredump disabled */
+ return 0;
+
+ dump = ath11k_coredump_build(ab);
+ if (!dump) {
+ ath11k_warn(ab, "no crash dump data found for devcoredump");
+ return -ENODATA;
+ }
+
+ dev_coredumpv(ab->dev, dump, le32_to_cpu(dump->len), GFP_KERNEL);
+
+ return 0;
+}
+
+int ath11k_coredump_create(struct ath11k_base *ab)
+{
+ struct ath11k_fw_crash_data *crash_data;
+
+ if (ath11k_coredump_mask == 0)
+ /* coredump disabled */
+ return 0;
+
+ ab->coredump.fw_crash_data = vzalloc(sizeof(*ab->coredump.fw_crash_data));
+ if (!ab->coredump.fw_crash_data)
+ return -ENOMEM;
+
+ crash_data = ab->coredump.fw_crash_data;
+
+ if (test_bit(ATH11K_FW_CRASH_DUMP_RAM_DATA, &ath11k_coredump_mask)) {
+ crash_data->ramdump_buf_len = ath11k_coredump_get_ramdump_size(ab);
+
+ if (!crash_data->ramdump_buf_len)
+ return 0;
+
+ crash_data->ramdump_buf = vzalloc(crash_data->ramdump_buf_len);
+ if (!crash_data->ramdump_buf) {
+ ath11k_warn(ab, "failed to allocate ramdump buffer\n");
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+void ath11k_coredump_destroy(struct ath11k_base *ab)
+{
+ struct ath11k_fw_crash_data *crash_data = ab->coredump.fw_crash_data;
+
+ if (ath11k_coredump_mask == 0)
+ /* coredump disabled */
+ return;
+
+ if (crash_data->ramdump_buf) {
+ vfree(crash_data->ramdump_buf);
+ crash_data->ramdump_buf = NULL;
+ crash_data->ramdump_buf_len = 0;
+ }
+
+ vfree(crash_data);
+ ab->coredump.fw_crash_data = NULL;
+}
diff --git a/drivers/net/wireless/ath/ath11k/coredump.h b/drivers/net/wireless/ath/ath11k/coredump.h
new file mode 100644
index 000000000000..47fe4b66cd25
--- /dev/null
+++ b/drivers/net/wireless/ath/ath11k/coredump.h
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear
+ *
+ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _COREDUMP_H_
+#define _COREDUMP_H_
+
+#include "core.h"
+
+#define ATH11K_FW_CRASH_DUMP_VERSION 1
+
+enum ath11k_fw_crash_dump_type {
+ /* contains multiple struct ath11k_ramdump_hdr */
+ ATH11K_FW_CRASH_DUMP_RAM_DATA = 0,
+ ATH11K_FW_CRASH_DUMP_MAX,
+};
+
+struct ath11k_tlv_dump_data {
+ /* see ath11k_fw_crash_dump_type above */
+ __le32 type;
+
+ /* in bytes */
+ __le32 tlv_len;
+
+ /* pad to 32-bit boundaries as needed */
+ u8 tlv_data[];
+} __packed;
+
+struct ath11k_dump_file_data {
+ /* "ATH11K-FW-DUMP" */
+ char df_magic[16];
+
+ __le32 len;
+
+ /* file dump version */
+ __le32 version;
+
+ /* some info we can get from ath11k_base struct that might help */
+
+ guid_t guid;
+
+ __le32 hw_rev;
+
+ __le32 bus_type;
+
+ /* firmware version string */
+ char fw_ver[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1];
+
+ /* Kernel related information */
+
+ /* time-of-day stamp */
+ __le64 tv_sec;
+
+ /* time-of-day stamp, nano-seconds */
+ __le64 tv_nsec;
+
+ /* LINUX_VERSION_CODE */
+ __le32 kernel_ver_code;
+
+ /* VERMAGIC_STRING */
+ char kernel_ver[64];
+
+ /* room for growth w/out changing binary format */
+ u8 unused[128];
+
+ /* struct ath11k_tlv_dump_data + more */
+ u8 data[];
+} __packed;
+
+struct ath11k_ramdump_hdr {
+ /* enum ath11k_mem_region_type */
+ __le32 region_type;
+
+ __le64 start;
+
+ /* length of payload data, not including this header */
+ __le32 length;
+
+ u8 data[];
+};
+
+/* part of user space ABI */
+enum ath11k_mem_region_type {
+ ATH11K_MEM_REGION_TYPE_MSA = 1,
+};
+
+struct ath11k_mem_region {
+ enum ath11k_mem_region_type type;
+ u32 start;
+ u32 len;
+
+ const char *name;
+};
+
+/* Contains the memory layout of a hardware version identified with the
+ * hw_rev, split into regions.
+ */
+struct ath11k_hw_mem_layout {
+ u32 hw_rev;
+ enum ath11k_bus bus;
+
+ struct {
+ const struct ath11k_mem_region *regions;
+ int size;
+ } region_table;
+};
+
+#ifdef CONFIG_DEV_COREDUMP
+
+int ath11k_coredump_submit(struct ath11k_base *ab);
+struct ath11k_fw_crash_data *ath11k_coredump_new(struct ath11k_base *ab);
+int ath11k_coredump_create(struct ath11k_base *ab);
+void ath11k_coredump_destroy(struct ath11k_base *ab);
+const struct ath11k_hw_mem_layout *
+ath11k_coredump_get_mem_layout(struct ath11k_base *ab);
+
+#else /* CONFIG_DEV_COREDUMP */
+
+static inline int ath11k_coredump_submit(struct ath11k_base *ab)
+{
+ return 0;
+}
+
+static inline struct ath11k_fw_crash_data *ath11k_coredump_new(struct ath11k_base *ab)
+{
+ return NULL;
+}
+
+static inline int ath11k_coredump_create(struct ath11k_base *ab)
+{
+ return 0;
+}
+
+static inline void ath11k_coredump_destroy(struct ath11k_base *ab)
+{
+}
+
+static inline const struct ath11k_hw_mem_layout *
+ath11k_coredump_get_mem_layout(struct ath11k_base *ab)
+{
+ return NULL;
+}
+#endif /* CONFIG_DEV_COREDUMP */
+
+#endif /* _COREDUMP_H_ */
--
2.17.1
Hi Manikanta,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 610b78b97bad8f3e77c27a15e9a03cbbb4109697]
url: https://github.com/intel-lab-lkp/linux/commits/Manikanta-Pubbisetty/wifi-ath11k-Add-coredump-support/20230518-182743
base: 610b78b97bad8f3e77c27a15e9a03cbbb4109697
patch link: https://lore.kernel.org/r/20230518101546.27998-3-quic_mpubbise%40quicinc.com
patch subject: [PATCH 2/2] wifi: ath11k: Add coredump support of MSA region for WCN6750
config: m68k-allyesconfig
compiler: m68k-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/bc44b3e938250b717bcfa936b5378d2e77f504a5
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Manikanta-Pubbisetty/wifi-ath11k-Add-coredump-support/20230518-182743
git checkout bc44b3e938250b717bcfa936b5378d2e77f504a5
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/net/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All warnings (new ones prefixed by >>):
In file included from include/linux/swab.h:5,
from include/uapi/linux/byteorder/big_endian.h:14,
from include/linux/byteorder/big_endian.h:5,
from arch/m68k/include/uapi/asm/byteorder.h:5,
from include/asm-generic/bitops/le.h:6,
from arch/m68k/include/asm/bitops.h:545,
from include/linux/bitops.h:68,
from include/linux/thread_info.h:27,
from include/asm-generic/preempt.h:5,
from ./arch/m68k/include/generated/asm/preempt.h:1,
from include/linux/preempt.h:78,
from arch/m68k/include/asm/irqflags.h:6,
from include/linux/irqflags.h:16,
from arch/m68k/include/asm/atomic.h:6,
from include/linux/atomic.h:7,
from include/linux/mm_types_task.h:13,
from include/linux/mm_types.h:5,
from include/linux/buildid.h:5,
from include/linux/module.h:14,
from drivers/net/wireless/ath/ath11k/ahb.c:7:
drivers/net/wireless/ath/ath11k/ahb.c: In function 'ath11k_ahb_coredump_msa':
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:131:38: note: in definition of macro '__swab64'
131 | (__u64)(__builtin_constant_p(x) ? \
| ^
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:25:19: note: in definition of macro '___constant_swab64'
25 | (((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
| ^
include/uapi/linux/byteorder/big_endian.h:32:43: note: in expansion of macro '__swab64'
32 | #define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
| ^~~~~~~~
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:26:19: note: in definition of macro '___constant_swab64'
26 | (((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
| ^
include/uapi/linux/byteorder/big_endian.h:32:43: note: in expansion of macro '__swab64'
32 | #define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
| ^~~~~~~~
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:27:19: note: in definition of macro '___constant_swab64'
27 | (((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
| ^
include/uapi/linux/byteorder/big_endian.h:32:43: note: in expansion of macro '__swab64'
32 | #define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
| ^~~~~~~~
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:28:19: note: in definition of macro '___constant_swab64'
28 | (((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \
| ^
include/uapi/linux/byteorder/big_endian.h:32:43: note: in expansion of macro '__swab64'
32 | #define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
| ^~~~~~~~
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:29:19: note: in definition of macro '___constant_swab64'
29 | (((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \
| ^
include/uapi/linux/byteorder/big_endian.h:32:43: note: in expansion of macro '__swab64'
32 | #define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
| ^~~~~~~~
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:30:19: note: in definition of macro '___constant_swab64'
30 | (((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
| ^
include/uapi/linux/byteorder/big_endian.h:32:43: note: in expansion of macro '__swab64'
32 | #define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
| ^~~~~~~~
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:31:19: note: in definition of macro '___constant_swab64'
31 | (((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
| ^
include/uapi/linux/byteorder/big_endian.h:32:43: note: in expansion of macro '__swab64'
32 | #define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
| ^~~~~~~~
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:32:19: note: in definition of macro '___constant_swab64'
32 | (((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56)))
| ^
include/uapi/linux/byteorder/big_endian.h:32:43: note: in expansion of macro '__swab64'
32 | #define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
| ^~~~~~~~
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
>> drivers/net/wireless/ath/ath11k/ahb.c:975:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^
include/uapi/linux/swab.h:133:19: note: in definition of macro '__swab64'
133 | __fswab64(x))
| ^
include/linux/byteorder/generic.h:86:21: note: in expansion of macro '__cpu_to_le64'
86 | #define cpu_to_le64 __cpu_to_le64
| ^~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/ahb.c:975:22: note: in expansion of macro 'cpu_to_le64'
975 | hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
| ^~~~~~~~~~~
vim +975 drivers/net/wireless/ath/ath11k/ahb.c
939
940 static void ath11k_ahb_coredump_msa(struct ath11k_base *ab)
941 {
942 struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
943 const struct ath11k_hw_mem_layout *mem_layout;
944 struct ath11k_fw_crash_data *crash_data;
945 const struct ath11k_mem_region *current_region;
946 struct ath11k_ramdump_hdr *hdr;
947 size_t buf_len;
948 u8 *buf;
949
950 mutex_lock(&ab->dump_mutex);
951
952 crash_data = ath11k_coredump_new(ab);
953 if (!crash_data)
954 goto out_unlock;
955
956 if (!crash_data->ramdump_buf)
957 goto out_unlock;
958
959 mem_layout = ath11k_coredump_get_mem_layout(ab);
960 if (!mem_layout)
961 goto out_unlock;
962
963 current_region = &mem_layout->region_table.regions[0];
964
965 buf = crash_data->ramdump_buf;
966 buf_len = crash_data->ramdump_buf_len;
967 memset(buf, 0, buf_len);
968
969 /* Reserve space for the header. */
970 hdr = (void *)buf;
971 buf += sizeof(*hdr);
972 buf_len -= sizeof(*hdr);
973
974 hdr->region_type = cpu_to_le32(current_region->type);
> 975 hdr->start = cpu_to_le64((u64)ab_ahb->fw.msa_vaddr);
976
977 if (current_region->len < ab_ahb->fw.msa_size) {
978 memcpy(buf, ab_ahb->fw.msa_vaddr, current_region->len);
979 hdr->length = cpu_to_le32(current_region->len);
980
981 ath11k_warn(ab, "msa dump length is less than msa size %x, %x\n",
982 current_region->len, ab_ahb->fw.msa_size);
983 } else {
984 memcpy(buf, ab_ahb->fw.msa_vaddr, ab_ahb->fw.msa_size);
985 hdr->length = cpu_to_le32(ab_ahb->fw.msa_size);
986 }
987
988 out_unlock:
989 mutex_unlock(&ab->dump_mutex);
990 }
991
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki