Merge "cnss2: Add support to use new ramdump APIs"

This commit is contained in:
qctecmdr 2020-08-28 14:21:53 -07:00 • committed by Gerrit - the friendly Code Review server
commit 6278f1358d
3 changed files with 153 additions and 50 deletions

View file

@ -1001,6 +1001,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);
ret = cnss_bus_dev_powerup(plat_priv);
@ -1739,6 +1740,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)
@ -1788,6 +1852,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)

View file

@ -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
@ -469,6 +472,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);

View file

@ -1887,21 +1887,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)
@ -2065,52 +2058,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);