From f4ea8b516ae2937af14f6f9c70e461dac3fdd4d9 Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Fri, 31 Jul 2020 18:10:32 -0700 Subject: [PATCH] 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 --- drivers/net/wireless/cnss2/main.c | 144 ++++++++++++++++++++++++++++++ drivers/net/wireless/cnss2/main.h | 7 +- drivers/net/wireless/cnss2/pci.c | 52 +---------- 3 files changed, 153 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 79aa1efa6001..08bd61423058 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -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) diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index 0401c69809e9..a580f91fe8f6 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -14,8 +14,11 @@ #include #include #include -#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART) +#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART) || \ + IS_ENABLED(CONFIG_SUBSYSTEM_RAMDUMP) #include +#endif +#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART) #include #include #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); diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 522bd617f1df..262656aebb74 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -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);