diff options
| author | Jitendra Sharma <shajit@codeaurora.org> | 2018-01-08 13:12:33 +0530 |
|---|---|---|
| committer | Jitendra Sharma <shajit@codeaurora.org> | 2018-01-24 13:05:12 +0530 |
| commit | abe5dd403221da76188889b63eceeae1f491761d (patch) | |
| tree | 89ec20180a4c5a026d4ff92650fccc3c1fc8500f /drivers/soc/qcom/peripheral-loader.c | |
| parent | a5cabe9334b684f828dab1d28167d2b154536851 (diff) | |
soc: qcom: pil: Add PDR minidump support
This change add support to collect PD dump along
with minidump on subsystem ssr event.
Change-Id: Icb3c20ee2f37ecc8bdbc91d9ba1ee7f383fa075a
Signed-off-by: Jitendra Sharma <shajit@codeaurora.org>
Diffstat (limited to 'drivers/soc/qcom/peripheral-loader.c')
| -rw-r--r-- | drivers/soc/qcom/peripheral-loader.c | 118 |
1 files changed, 85 insertions, 33 deletions
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 6e153500f639..32a457730869 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -147,7 +147,8 @@ struct pil_priv { phys_addr_t region_end; void *region; struct pil_image_info __iomem *info; - struct md_ssr_ss_info __iomem *minidump; + struct md_ssr_ss_info __iomem *minidump_ss; + struct md_ssr_ss_info __iomem *minidump_pdr; int minidump_id; int id; int unvoted_flag; @@ -156,30 +157,54 @@ struct pil_priv { static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev) { - struct boot_minidump_smem_region __iomem *region_info; + struct boot_minidump_smem_region __iomem *region_info_ss; + struct boot_minidump_smem_region __iomem *region_info_pdr; struct ramdump_segment *ramdump_segs, *s; struct pil_priv *priv = desc->priv; - void __iomem *subsys_smem_base; - void __iomem *offset; - int ss_mdump_seg_cnt; + void __iomem *subsys_smem_base_pdr; + void __iomem *subsys_smem_base_ss; + void __iomem *offset_ss; + void __iomem *offset_pdr; + int ss_mdump_seg_cnt_ss = 0, ss_mdump_seg_cnt_pdr = 0, total_segs; int ret, i; if (!ramdump_dev) return -ENODEV; - memcpy(&offset, &priv->minidump, sizeof(priv->minidump)); - offset = offset + sizeof(priv->minidump->md_ss_smem_regions_baseptr); + memcpy(&offset_ss, &priv->minidump_ss, sizeof(priv->minidump_ss)); + offset_ss = offset_ss + + sizeof(priv->minidump_ss->md_ss_smem_regions_baseptr); /* There are 3 encryption keys which also need to be dumped */ - ss_mdump_seg_cnt = readb_relaxed(offset) + + ss_mdump_seg_cnt_ss = readb_relaxed(offset_ss) + NUM_OF_ENCRYPTED_KEY; - pr_debug("SMEM base to read minidump segments is 0x%x\n", - __raw_readl(priv->minidump)); - subsys_smem_base = ioremap(__raw_readl(priv->minidump), - ss_mdump_seg_cnt * sizeof(*region_info)); - region_info = - (struct boot_minidump_smem_region __iomem *)subsys_smem_base; - ramdump_segs = kcalloc(ss_mdump_seg_cnt, + pr_debug("SMEM base to read minidump ss segments is 0x%x\n", + __raw_readl(priv->minidump_ss)); + subsys_smem_base_ss = ioremap(__raw_readl(priv->minidump_ss), + ss_mdump_seg_cnt_ss * sizeof(*region_info_ss)); + region_info_ss = + (struct boot_minidump_smem_region __iomem *)subsys_smem_base_ss; + + if (priv->minidump_pdr && (__raw_readl(priv->minidump_pdr) != 0)) { + memcpy(&offset_pdr, &priv->minidump_pdr, + sizeof(priv->minidump_pdr)); + offset_pdr = offset_pdr + + sizeof(priv->minidump_pdr->md_ss_smem_regions_baseptr); + /* There are 3 encryption keys which also need to be dumped */ + ss_mdump_seg_cnt_pdr = readb_relaxed(offset_pdr) + + NUM_OF_ENCRYPTED_KEY; + + pr_debug("SMEM base to read minidump pdr segments is 0x%x\n", + __raw_readl(priv->minidump_pdr)); + subsys_smem_base_pdr = ioremap(__raw_readl(priv->minidump_pdr), + ss_mdump_seg_cnt_pdr * sizeof(*region_info_pdr)); + region_info_pdr = + (struct boot_minidump_smem_region __iomem *) + subsys_smem_base_pdr; + } + + total_segs = ss_mdump_seg_cnt_ss + ss_mdump_seg_cnt_pdr; + ramdump_segs = kcalloc(total_segs, sizeof(*ramdump_segs), GFP_KERNEL); if (!ramdump_segs) return -ENOMEM; @@ -189,25 +214,43 @@ static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev) (priv->region_end - priv->region_start)); s = ramdump_segs; - for (i = 0; i < ss_mdump_seg_cnt; i++) { - memcpy(&offset, ®ion_info, sizeof(region_info)); - memcpy(&s->name, ®ion_info, sizeof(region_info)); - offset = offset + sizeof(region_info->region_name); - s->address = __raw_readl(offset); - offset = offset + sizeof(region_info->region_base_address); - s->size = __raw_readl(offset); + for (i = 0; i < ss_mdump_seg_cnt_ss; i++) { + memcpy(&offset_ss, ®ion_info_ss, sizeof(region_info_ss)); + memcpy(&s->name, ®ion_info_ss, sizeof(region_info_ss)); + offset_ss = offset_ss + sizeof(region_info_ss->region_name); + s->address = __raw_readl(offset_ss); + offset_ss = offset_ss + + sizeof(region_info_ss->region_base_address); + s->size = __raw_readl(offset_ss); + pr_debug("Dumping segment %s with address %pK and size 0x%x\n", + s->name, (void *)s->address, + (unsigned int)s->size); + s++; + region_info_ss++; + } + + for (i = 0; i < ss_mdump_seg_cnt_pdr; i++) { + memcpy(&offset_pdr, ®ion_info_pdr, sizeof(region_info_pdr)); + memcpy(&s->name, ®ion_info_pdr, sizeof(region_info_pdr)); + offset_pdr = offset_pdr + sizeof(region_info_pdr->region_name); + s->address = __raw_readl(offset_pdr); + offset_pdr = offset_pdr + + sizeof(region_info_pdr->region_base_address); + s->size = __raw_readl(offset_pdr); pr_debug("Dumping segment %s with address %pK and size 0x%x\n", s->name, (void *)s->address, (unsigned int)s->size); s++; - region_info++; + region_info_pdr++; } - ret = do_minidump(ramdump_dev, ramdump_segs, ss_mdump_seg_cnt); + + ret = do_minidump(ramdump_dev, ramdump_segs, total_segs); kfree(ramdump_segs); if (ret) pil_err(desc, "%s: Ramdump collection failed for subsys %s rc:%d\n", __func__, desc->name, ret); - writeb_relaxed(1, &priv->minidump->md_ss_ssr_cause); + writeb_relaxed(1, &priv->minidump_ss->md_ss_ssr_cause); + writeb_relaxed(1, &priv->minidump_pdr->md_ss_ssr_cause); if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_subsys(desc, priv->region_start, @@ -232,13 +275,13 @@ int pil_do_ramdump(struct pil_desc *desc, struct ramdump_segment *ramdump_segs, *s; void __iomem *offset; - memcpy(&offset, &priv->minidump, sizeof(priv->minidump)); + memcpy(&offset, &priv->minidump_ss, sizeof(priv->minidump_ss)); /* * Collect minidump if smem base is initialized, * ssr cause is 0. No need to check encryption status */ - if (priv->minidump - && (__raw_readl(priv->minidump) != 0) + if (priv->minidump_ss + && (__raw_readl(priv->minidump_ss) != 0) && (readb_relaxed(offset + sizeof(u32) + 2 * sizeof(u8)) == 0)) { pr_debug("Dumping Minidump for %s\n", desc->name); return pil_do_minidump(desc, minidump_dev); @@ -1113,7 +1156,7 @@ int pil_desc_init(struct pil_desc *desc) { struct pil_priv *priv; void __iomem *addr; - int ret, ss_imem_offset_mdump; + int ret, ss_imem_offset_mdump_ss, ss_imem_offset_mdump_pdr; char buf[sizeof(priv->info->name)]; struct device_node *ofnode = desc->dev->of_node; @@ -1142,16 +1185,25 @@ int pil_desc_init(struct pil_desc *desc) &priv->minidump_id)) pr_debug("minidump-id not found for %s\n", desc->name); else { - ss_imem_offset_mdump = + ss_imem_offset_mdump_ss = sizeof(struct md_ssr_ss_info) * priv->minidump_id; + ss_imem_offset_mdump_pdr = + sizeof(struct md_ssr_ss_info) * (priv->minidump_id + 1); if (pil_minidump_base) { /* Add 0x4 to get start of struct md_ssr_ss_info base * from struct md_ssr_toc for any subsystem, * struct md_ssr_ss_info is actually the pointer * of ToC in smem for any subsystem. */ - addr = pil_minidump_base + ss_imem_offset_mdump + 0x4; - priv->minidump = (struct md_ssr_ss_info __iomem *)addr; + addr = pil_minidump_base + + ss_imem_offset_mdump_ss + 0x4; + priv->minidump_ss = + (struct md_ssr_ss_info __iomem *)addr; + + addr = pil_minidump_base + + ss_imem_offset_mdump_pdr + 0x4; + priv->minidump_pdr = + (struct md_ssr_ss_info __iomem *)addr; } } |
