Loading drivers/soc/qcom/peripheral-loader.c +85 −33 Original line number Diff line number Diff line /* 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 Loading Loading @@ -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; Loading @@ -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_ss = readb_relaxed(offset_ss) + NUM_OF_ENCRYPTED_KEY; 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 = readb_relaxed(offset) + ss_mdump_seg_cnt_pdr = readb_relaxed(offset_pdr) + 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 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; Loading @@ -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++; region_info_ss++; } ret = do_minidump(ramdump_dev, ramdump_segs, ss_mdump_seg_cnt); 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_pdr++; } 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, Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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; } } Loading Loading
drivers/soc/qcom/peripheral-loader.c +85 −33 Original line number Diff line number Diff line /* 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 Loading Loading @@ -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; Loading @@ -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_ss = readb_relaxed(offset_ss) + NUM_OF_ENCRYPTED_KEY; 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 = readb_relaxed(offset) + ss_mdump_seg_cnt_pdr = readb_relaxed(offset_pdr) + 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 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; Loading @@ -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++; region_info_ss++; } ret = do_minidump(ramdump_dev, ramdump_segs, ss_mdump_seg_cnt); 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_pdr++; } 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, Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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; } } Loading