mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 07:37:31 -04:00
cnss2: Add support to use new ramdump APIs
Use new APIs from ramdump module which uses device coredump functionality to save WLAN dumps to file system. Change-Id: Ic6dd09d255bda2923f4680b057eacf4658d0aaa6 Signed-off-by: Yue Ma <yuem@codeaurora.org>
This commit is contained in:
parent
c4e9e0ada3
commit
f4ea8b516a
3 changed files with 153 additions and 50 deletions
|
|
@ -977,6 +977,7 @@ static void cnss_recovery_work_handler(struct work_struct *work)
|
|||
panic("subsys-restart: Resetting the SoC wlan crashed\n");
|
||||
|
||||
cnss_bus_dev_shutdown(plat_priv);
|
||||
cnss_bus_dev_ramdump(plat_priv);
|
||||
msleep(RECOVERY_DELAY_MS);
|
||||
cnss_bus_dev_powerup(plat_priv);
|
||||
}
|
||||
|
|
@ -1696,6 +1697,69 @@ static void cnss_destroy_ramdump_device(struct cnss_plat_data *plat_priv,
|
|||
{
|
||||
destroy_ramdump_device(ramdump_dev);
|
||||
}
|
||||
|
||||
int cnss_do_ramdump(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct cnss_ramdump_info *ramdump_info = &plat_priv->ramdump_info;
|
||||
struct ramdump_segment segment;
|
||||
|
||||
memset(&segment, 0, sizeof(segment));
|
||||
segment.v_address = (void __iomem *)ramdump_info->ramdump_va;
|
||||
segment.size = ramdump_info->ramdump_size;
|
||||
|
||||
return do_ramdump(ramdump_info->ramdump_dev, &segment, 1);
|
||||
}
|
||||
|
||||
int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
|
||||
struct cnss_dump_data *dump_data = &info_v2->dump_data;
|
||||
struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
|
||||
struct ramdump_segment *ramdump_segs, *s;
|
||||
struct cnss_dump_meta_info meta_info = {0};
|
||||
int i, ret = 0;
|
||||
|
||||
ramdump_segs = kcalloc(dump_data->nentries + 1,
|
||||
sizeof(*ramdump_segs),
|
||||
GFP_KERNEL);
|
||||
if (!ramdump_segs)
|
||||
return -ENOMEM;
|
||||
|
||||
s = ramdump_segs + 1;
|
||||
for (i = 0; i < dump_data->nentries; i++) {
|
||||
if (dump_seg->type >= CNSS_FW_DUMP_TYPE_MAX) {
|
||||
cnss_pr_err("Unsupported dump type: %d",
|
||||
dump_seg->type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meta_info.entry[dump_seg->type].entry_start == 0) {
|
||||
meta_info.entry[dump_seg->type].type = dump_seg->type;
|
||||
meta_info.entry[dump_seg->type].entry_start = i + 1;
|
||||
}
|
||||
meta_info.entry[dump_seg->type].entry_num++;
|
||||
|
||||
s->address = dump_seg->address;
|
||||
s->v_address = (void __iomem *)dump_seg->v_address;
|
||||
s->size = dump_seg->size;
|
||||
s++;
|
||||
dump_seg++;
|
||||
}
|
||||
|
||||
meta_info.magic = CNSS_RAMDUMP_MAGIC;
|
||||
meta_info.version = CNSS_RAMDUMP_VERSION;
|
||||
meta_info.chipset = plat_priv->device_id;
|
||||
meta_info.total_entries = CNSS_FW_DUMP_TYPE_MAX;
|
||||
|
||||
ramdump_segs->v_address = (void __iomem *)(&meta_info);
|
||||
ramdump_segs->size = sizeof(meta_info);
|
||||
|
||||
ret = do_elf_ramdump(info_v2->ramdump_dev, ramdump_segs,
|
||||
dump_data->nentries + 1);
|
||||
kfree(ramdump_segs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static int cnss_panic_handler(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
|
|
@ -1745,6 +1809,86 @@ static void cnss_destroy_ramdump_device(struct cnss_plat_data *plat_priv,
|
|||
void *ramdump_dev)
|
||||
{
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUBSYSTEM_RAMDUMP)
|
||||
int cnss_do_ramdump(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct cnss_ramdump_info *ramdump_info = &plat_priv->ramdump_info;
|
||||
struct qcom_dump_segment segment;
|
||||
struct list_head head;
|
||||
|
||||
INIT_LIST_HEAD(&head);
|
||||
memset(&segment, 0, sizeof(segment));
|
||||
segment.va = ramdump_info->ramdump_va;
|
||||
segment.size = ramdump_info->ramdump_size;
|
||||
list_add(&segment.node, &head);
|
||||
|
||||
return do_dump(&head, ramdump_info->ramdump_dev);
|
||||
}
|
||||
|
||||
int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
|
||||
struct cnss_dump_data *dump_data = &info_v2->dump_data;
|
||||
struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
|
||||
struct qcom_dump_segment *seg;
|
||||
struct cnss_dump_meta_info meta_info = {0};
|
||||
struct list_head head;
|
||||
int i, ret = 0;
|
||||
|
||||
INIT_LIST_HEAD(&head);
|
||||
for (i = 0; i < dump_data->nentries; i++) {
|
||||
if (dump_seg->type >= CNSS_FW_DUMP_TYPE_MAX) {
|
||||
cnss_pr_err("Unsupported dump type: %d",
|
||||
dump_seg->type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meta_info.entry[dump_seg->type].entry_start == 0) {
|
||||
meta_info.entry[dump_seg->type].type = dump_seg->type;
|
||||
meta_info.entry[dump_seg->type].entry_start = i + 1;
|
||||
}
|
||||
meta_info.entry[dump_seg->type].entry_num++;
|
||||
|
||||
seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
|
||||
seg->da = dump_seg->address;
|
||||
seg->va = dump_seg->v_address;
|
||||
seg->size = dump_seg->size;
|
||||
list_add_tail(&seg->node, &head);
|
||||
dump_seg++;
|
||||
}
|
||||
|
||||
meta_info.magic = CNSS_RAMDUMP_MAGIC;
|
||||
meta_info.version = CNSS_RAMDUMP_VERSION;
|
||||
meta_info.chipset = plat_priv->device_id;
|
||||
meta_info.total_entries = CNSS_FW_DUMP_TYPE_MAX;
|
||||
|
||||
seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
|
||||
seg->va = &meta_info;
|
||||
seg->size = sizeof(meta_info);
|
||||
list_add(&seg->node, &head);
|
||||
|
||||
ret = do_elf_dump(&head, info_v2->ramdump_dev);
|
||||
|
||||
while (!list_empty(&head)) {
|
||||
seg = list_first_entry(&head, struct qcom_dump_segment, node);
|
||||
list_del(&seg->node);
|
||||
kfree(seg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int cnss_do_ramdump(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_SUBSYSTEM_RAMDUMP */
|
||||
#endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
|
||||
|
||||
static int cnss_init_dump_entry(struct cnss_plat_data *plat_priv)
|
||||
|
|
|
|||
|
|
@ -14,8 +14,11 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <net/cnss2.h>
|
||||
#include <soc/qcom/memory_dump.h>
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART) || \
|
||||
IS_ENABLED(CONFIG_SUBSYSTEM_RAMDUMP)
|
||||
#include <soc/qcom/ramdump.h>
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
#include <soc/qcom/subsystem_notif.h>
|
||||
#include <soc/qcom/subsystem_restart.h>
|
||||
#endif
|
||||
|
|
@ -460,6 +463,8 @@ int cnss_register_subsys(struct cnss_plat_data *plat_priv);
|
|||
void cnss_unregister_subsys(struct cnss_plat_data *plat_priv);
|
||||
int cnss_register_ramdump(struct cnss_plat_data *plat_priv);
|
||||
void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv);
|
||||
int cnss_do_ramdump(struct cnss_plat_data *plat_priv);
|
||||
int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv);
|
||||
void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv);
|
||||
int cnss_get_cpr_info(struct cnss_plat_data *plat_priv);
|
||||
int cnss_update_cpr_info(struct cnss_plat_data *plat_priv);
|
||||
|
|
|
|||
|
|
@ -1821,21 +1821,14 @@ static void cnss_qca6174_crash_shutdown(struct cnss_pci_data *pci_priv)
|
|||
|
||||
static int cnss_qca6174_ramdump(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|
||||
struct cnss_ramdump_info *ramdump_info;
|
||||
struct ramdump_segment segment;
|
||||
|
||||
ramdump_info = &plat_priv->ramdump_info;
|
||||
if (!ramdump_info->ramdump_size)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&segment, 0, sizeof(segment));
|
||||
segment.v_address = ramdump_info->ramdump_va;
|
||||
segment.size = ramdump_info->ramdump_size;
|
||||
ret = do_ramdump(ramdump_info->ramdump_dev, &segment, 1);
|
||||
|
||||
return ret;
|
||||
return cnss_do_ramdump(plat_priv);
|
||||
}
|
||||
|
||||
static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv)
|
||||
|
|
@ -1999,52 +1992,13 @@ static int cnss_qca6290_ramdump(struct cnss_pci_data *pci_priv)
|
|||
struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
|
||||
struct cnss_dump_data *dump_data = &info_v2->dump_data;
|
||||
struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
|
||||
struct ramdump_segment *ramdump_segs, *s;
|
||||
struct cnss_dump_meta_info meta_info = {0};
|
||||
int i, ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!info_v2->dump_data_valid || !dump_seg ||
|
||||
dump_data->nentries == 0)
|
||||
return 0;
|
||||
|
||||
ramdump_segs = kcalloc(dump_data->nentries + 1,
|
||||
sizeof(*ramdump_segs),
|
||||
GFP_KERNEL);
|
||||
if (!ramdump_segs)
|
||||
return -ENOMEM;
|
||||
|
||||
s = ramdump_segs + 1;
|
||||
for (i = 0; i < dump_data->nentries; i++) {
|
||||
if (dump_seg->type >= CNSS_FW_DUMP_TYPE_MAX) {
|
||||
cnss_pr_err("Unsupported dump type: %d",
|
||||
dump_seg->type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meta_info.entry[dump_seg->type].entry_start == 0) {
|
||||
meta_info.entry[dump_seg->type].type = dump_seg->type;
|
||||
meta_info.entry[dump_seg->type].entry_start = i + 1;
|
||||
}
|
||||
meta_info.entry[dump_seg->type].entry_num++;
|
||||
|
||||
s->address = dump_seg->address;
|
||||
s->v_address = dump_seg->v_address;
|
||||
s->size = dump_seg->size;
|
||||
s++;
|
||||
dump_seg++;
|
||||
}
|
||||
|
||||
meta_info.magic = CNSS_RAMDUMP_MAGIC;
|
||||
meta_info.version = CNSS_RAMDUMP_VERSION;
|
||||
meta_info.chipset = pci_priv->device_id;
|
||||
meta_info.total_entries = CNSS_FW_DUMP_TYPE_MAX;
|
||||
|
||||
ramdump_segs->v_address = &meta_info;
|
||||
ramdump_segs->size = sizeof(meta_info);
|
||||
|
||||
ret = do_elf_ramdump(info_v2->ramdump_dev, ramdump_segs,
|
||||
dump_data->nentries + 1);
|
||||
kfree(ramdump_segs);
|
||||
ret = cnss_do_elf_ramdump(plat_priv);
|
||||
|
||||
cnss_pci_clear_dump_info(pci_priv);
|
||||
cnss_pci_deinit_mhi(pci_priv);
|
||||
|
|
|
|||
Loading…
Reference in a new issue